|
|
1.1 ! root 1: #include "u.h" ! 2: #include "../port/lib.h" ! 3: #include "mem.h" ! 4: #include "dat.h" ! 5: #include "fns.h" ! 6: #include "io.h" ! 7: #include "../port/error.h" ! 8: ! 9: #include "devtab.h" ! 10: #define nelem(x) (sizeof(x)/sizeof(x[0])) ! 11: /* ! 12: * Driver for an NS16450 serial port ! 13: */ ! 14: enum ! 15: { ! 16: /* ! 17: * register numbers ! 18: */ ! 19: Data= 0, /* xmit/rcv buffer */ ! 20: Iena= 1, /* interrupt enable */ ! 21: Ircv= (1<<0), /* for char rcv'd */ ! 22: Ixmt= (1<<1), /* for xmit buffer empty */ ! 23: Irstat=(1<<2), /* for change in rcv'er status */ ! 24: Imstat=(1<<3), /* for change in modem status */ ! 25: Istat= 2, /* interrupt flag (read) */ ! 26: Fenabd=(3<<6), /* on if fifo's enabled */ ! 27: Fifoctl=2, /* fifo control (write) */ ! 28: Fenab= (1<<0), /* enable xmit/rcv fifos */ ! 29: Ftrig= (1<<6), /* trigger after 4 input characters */ ! 30: Fclear=(3<<1), /* clear xmit & rcv fifos */ ! 31: Format= 3, /* byte format */ ! 32: Bits8= (3<<0), /* 8 bits/byte */ ! 33: Stop2= (1<<2), /* 2 stop bits */ ! 34: Pena= (1<<3), /* generate parity */ ! 35: Peven= (1<<4), /* even parity */ ! 36: Pforce=(1<<5), /* force parity */ ! 37: Break= (1<<6), /* generate a break */ ! 38: Dra= (1<<7), /* address the divisor */ ! 39: Mctl= 4, /* modem control */ ! 40: Dtr= (1<<0), /* data terminal ready */ ! 41: Rts= (1<<1), /* request to send */ ! 42: Ri= (1<<2), /* ring */ ! 43: Inton= (1<<3), /* turn on interrupts */ ! 44: Loop= (1<<4), /* loop back */ ! 45: Lstat= 5, /* line status */ ! 46: Inready=(1<<0), /* receive buffer full */ ! 47: Oerror=(1<<1), /* receiver overrun */ ! 48: Perror=(1<<2), /* receiver parity error */ ! 49: Ferror=(1<<3), /* rcv framing error */ ! 50: Outready=(1<<5), /* output buffer full */ ! 51: Mstat= 6, /* modem status */ ! 52: Ctsc= (1<<0), /* clear to send changed */ ! 53: Dsrc= (1<<1), /* data set ready changed */ ! 54: Rire= (1<<2), /* rising edge of ring indicator */ ! 55: Dcdc= (1<<3), /* data carrier detect changed */ ! 56: Cts= (1<<4), /* complement of clear to send line */ ! 57: Dsr= (1<<5), /* complement of data set ready line */ ! 58: Ring= (1<<6), /* complement of ring indicator line */ ! 59: Dcd= (1<<7), /* complement of data carrier detect line */ ! 60: Scratch=7, /* scratchpad */ ! 61: Dlsb= 0, /* divisor lsb */ ! 62: Dmsb= 1, /* divisor msb */ ! 63: ! 64: Serial= 0, ! 65: Modem= 1, ! 66: }; ! 67: ! 68: typedef struct Uart Uart; ! 69: struct Uart ! 70: { ! 71: QLock; ! 72: int port; ! 73: uchar sticky[8]; /* sticky write register values */ ! 74: int printing; /* true if printing */ ! 75: int enabled; ! 76: int cts; ! 77: ! 78: /* fifo control */ ! 79: int fifoon; ! 80: int nofifo; ! 81: int istat; ! 82: ! 83: /* console interface */ ! 84: int special; /* can't use the stream interface */ ! 85: IOQ *iq; /* input character queue */ ! 86: IOQ *oq; /* output character queue */ ! 87: ! 88: /* stream interface */ ! 89: Queue *wq; /* write queue */ ! 90: Rendez r; /* kproc waiting for input */ ! 91: int kstarted; /* kproc started */ ! 92: ! 93: /* error statistics */ ! 94: ulong frame; ! 95: ulong overrun; ! 96: }; ! 97: ! 98: typedef struct Scard ! 99: { ! 100: ISAConf; /* card configuration */ ! 101: int first; /* number of first port */ ! 102: } Scard; ! 103: ! 104: ! 105: Uart uart[34]; ! 106: int Nuart; /* total no of uarts in the machine */ ! 107: int Nscard; /* number of serial cards */ ! 108: Scard scard[5]; /* configs for the serial card */ ! 109: ! 110: #define UartFREQ 1843200 ! 111: ! 112: #define uartwrreg(u,r,v) outb((u)->port + r, (u)->sticky[r] | (v)) ! 113: #define uartrdreg(u,r) inb((u)->port + r) ! 114: ! 115: void uartintr(Ureg*, void*); ! 116: void mp008intr(Ureg*, void*); ! 117: ! 118: /* ! 119: * set the baud rate by calculating and setting the baudrate ! 120: * generator constant. This will work with fairly non-standard ! 121: * baud rates. ! 122: */ ! 123: void ! 124: uartsetbaud(Uart *up, int rate) ! 125: { ! 126: ulong brconst; ! 127: ! 128: brconst = (UartFREQ+8*rate-1)/(16*rate); ! 129: ! 130: uartwrreg(up, Format, Dra); ! 131: outb(up->port+Dmsb, (brconst>>8) & 0xff); ! 132: outb(up->port+Dlsb, brconst & 0xff); ! 133: uartwrreg(up, Format, 0); ! 134: } ! 135: ! 136: /* ! 137: * toggle DTR ! 138: */ ! 139: void ! 140: uartdtr(Uart *up, int n) ! 141: { ! 142: if(n) ! 143: up->sticky[Mctl] |= Dtr; ! 144: else ! 145: up->sticky[Mctl] &= ~Dtr; ! 146: uartwrreg(up, Mctl, 0); ! 147: } ! 148: ! 149: /* ! 150: * toggle RTS ! 151: */ ! 152: void ! 153: uartrts(Uart *up, int n) ! 154: { ! 155: if(n) ! 156: up->sticky[Mctl] |= Rts; ! 157: else ! 158: up->sticky[Mctl] &= ~Rts; ! 159: uartwrreg(up, Mctl, 0); ! 160: } ! 161: ! 162: /* ! 163: * send break ! 164: */ ! 165: void ! 166: uartbreak(Uart *up, int ms) ! 167: { ! 168: if(ms == 0) ! 169: ms = 200; ! 170: uartwrreg(up, Format, Break); ! 171: tsleep(&u->p->sleep, return0, 0, ms); ! 172: uartwrreg(up, Format, 0); ! 173: } ! 174: ! 175: /* ! 176: * set bits/char ! 177: */ ! 178: void ! 179: uartbits(Uart *up, int bits) ! 180: { ! 181: if(bits < 5 || bits > 8) ! 182: error(Ebadarg); ! 183: up->sticky[Format] &= ~3; ! 184: up->sticky[Format] |= bits-5; ! 185: uartwrreg(up, Format, 0); ! 186: } ! 187: ! 188: /* ! 189: * set parity ! 190: */ ! 191: void ! 192: uartparity(Uart *up, int c) ! 193: { ! 194: switch(c&0xff){ ! 195: case 'e': ! 196: up->sticky[Format] |= Pena|Peven; ! 197: break; ! 198: case 'o': ! 199: up->sticky[Format] &= ~Peven; ! 200: up->sticky[Format] |= Pena; ! 201: break; ! 202: default: ! 203: up->sticky[Format] &= ~(Pena|Peven); ! 204: break; ! 205: } ! 206: uartwrreg(up, Format, 0); ! 207: } ! 208: ! 209: /* ! 210: * set stop bits ! 211: */ ! 212: void ! 213: uartstop(Uart *up, int n) ! 214: { ! 215: switch(n){ ! 216: case 1: ! 217: up->sticky[Format] &= ~Stop2; ! 218: break; ! 219: case 2: ! 220: default: ! 221: up->sticky[Format] |= Stop2; ! 222: break; ! 223: } ! 224: uartwrreg(up, Format, 0); ! 225: } ! 226: ! 227: ! 228: void ! 229: uartfifoon(Uart *p) ! 230: { ! 231: ulong i, x; ! 232: ! 233: if(p->nofifo) ! 234: return; ! 235: ! 236: x = splhi(); ! 237: ! 238: /* empty buffer */ ! 239: for(i = 0; i < 16; i++) ! 240: uartrdreg(p, Data); ! 241: uartintr(0, p); ! 242: ! 243: /* turn on fifo */ ! 244: p->fifoon = 1; ! 245: uartwrreg(p, Fifoctl, Fenab|Ftrig); ! 246: ! 247: uartintr(0, p); ! 248: if((p->istat & Fenabd) == 0){ ! 249: /* didn't work, must be an earlier chip type */ ! 250: p->nofifo = 1; ! 251: } ! 252: ! 253: splx(x); ! 254: } ! 255: ! 256: /* ! 257: * modem flow control on/off (rts/cts) ! 258: */ ! 259: void ! 260: uartmflow(Uart *up, int n) ! 261: { ! 262: if(n){ ! 263: up->sticky[Iena] |= Imstat; ! 264: uartwrreg(up, Iena, 0); ! 265: up->cts = uartrdreg(up, Mstat) & Cts; ! 266: ! 267: /* turn on fifo's */ ! 268: uartfifoon(up); ! 269: } else { ! 270: up->sticky[Iena] &= ~Imstat; ! 271: uartwrreg(up, Iena, 0); ! 272: up->cts = 1; ! 273: ! 274: /* turn off fifo's */ ! 275: if(up->fifoon){ ! 276: up->fifoon = 0; ! 277: uartwrreg(up, Fifoctl, 0); ! 278: } ! 279: } ! 280: } ! 281: ! 282: ! 283: /* ! 284: * default is 9600 baud, 1 stop bit, 8 bit chars, no interrupts, ! 285: * transmit and receive enabled, interrupts disabled. ! 286: */ ! 287: void ! 288: uartsetup(void) ! 289: { ! 290: Uart *up; ! 291: Scard *sc; ! 292: int i, j, baddr; ! 293: static int already; ! 294: ! 295: if(already) ! 296: return; ! 297: already = 1; ! 298: ! 299: /* ! 300: * set port addresses ! 301: */ ! 302: uart[0].port = 0x3F8; ! 303: uart[1].port = 0x2F8; ! 304: setvec(Uart0vec, uartintr, &uart[0]); ! 305: setvec(Uart1vec, uartintr, &uart[1]); ! 306: Nuart = 2; ! 307: for(i = 0; isaconfig("serial", i, &scard[i]) && i < nelem(scard); i++) { ! 308: sc = &scard[i]; ! 309: if(strcmp(sc->type, "mp008") == 0 || strcmp(sc->type, "MP008") == 0){ ! 310: /* ! 311: * port gives base port address for uarts ! 312: * irq is interrupt ! 313: * mem is the polling port ! 314: * size is the number of serial ports on the same polling port ! 315: */ ! 316: sc->first = Nuart; ! 317: if(sc->size == 0) ! 318: sc->size = 8; ! 319: setvec(Int0vec + sc->irq, mp008intr, &scard[i]); ! 320: baddr = sc->port; ! 321: for(j=0, up = &uart[Nuart]; j < sc->size; baddr += 8, j++, up++){ ! 322: up->port = baddr; ! 323: Nuart++; ! 324: } ! 325: } else { ! 326: /* ! 327: * port gives base port address for uarts ! 328: * irq is interrupt ! 329: * size is the number of serial ports on the same polling port ! 330: */ ! 331: if(sc->size == 0) ! 332: sc->size = 1; ! 333: baddr = sc->port; ! 334: for(j=0, up = &uart[Nuart]; j < sc->size; baddr += 8, j++, up++){ ! 335: setvec(Int0vec + sc->irq, uartintr, &uart[Nuart]); ! 336: up->port = baddr; ! 337: Nuart++; ! 338: } ! 339: } ! 340: } ! 341: Nscard = i; ! 342: for(up = uart; up < &uart[Nuart]; up++){ ! 343: memset(up->sticky, 0, sizeof(up->sticky)); ! 344: /* ! 345: * set rate to 9600 baud. ! 346: * 8 bits/character. ! 347: * 1 stop bit. ! 348: * interrupts enabled. ! 349: */ ! 350: uartsetbaud(up, 9600); ! 351: up->sticky[Format] = Bits8; ! 352: uartwrreg(up, Format, 0); ! 353: up->sticky[Mctl] |= Inton; ! 354: uartwrreg(up, Mctl, 0x0); ! 355: } ! 356: } ! 357: ! 358: /* ! 359: * Queue n characters for output; if queue is full, we lose characters. ! 360: * Get the output going if it isn't already. ! 361: */ ! 362: void ! 363: uartputs(IOQ *cq, char *s, int n) ! 364: { ! 365: Uart *up = cq->ptr; ! 366: int ch, x, multiprocessor; ! 367: int tries; ! 368: ! 369: multiprocessor = active.machs > 1; ! 370: x = splhi(); ! 371: if(multiprocessor) ! 372: lock(cq); ! 373: puts(cq, s, n); ! 374: if(up->printing == 0){ ! 375: ch = getc(cq); ! 376: if(ch >= 0){ ! 377: up->printing = 1; ! 378: for(tries = 0; tries<10000 && !(uartrdreg(up, Lstat)&Outready); ! 379: tries++) ! 380: ; ! 381: outb(up->port + Data, ch); ! 382: } ! 383: } ! 384: if(multiprocessor) ! 385: unlock(cq); ! 386: splx(x); ! 387: } ! 388: ! 389: /* ! 390: * a uart interrupt (a damn lot of work for one character) ! 391: */ ! 392: void ! 393: uartintr(Ureg *ur, void *a) ! 394: { ! 395: int ch; ! 396: IOQ *cq; ! 397: int s, l, multiprocessor; ! 398: Uart *up = a; ! 399: ! 400: USED(ur, a); ! 401: ! 402: multiprocessor = active.machs > 1; ! 403: for(;;){ ! 404: s = uartrdreg(up, Istat); ! 405: switch(s & 0x3F){ ! 406: case 6: /* receiver line status */ ! 407: l = uartrdreg(up, Lstat); ! 408: if(l & Ferror) ! 409: up->frame++; ! 410: if(l & Oerror) ! 411: up->overrun++; ! 412: break; ! 413: ! 414: case 4: /* received data available */ ! 415: case 12: ! 416: ch = uartrdreg(up, Data) & 0xff; ! 417: cq = up->iq; ! 418: if(cq == 0) ! 419: break; ! 420: if(cq->putc) ! 421: (*cq->putc)(cq, ch); ! 422: else ! 423: putc(cq, ch); ! 424: break; ! 425: ! 426: case 2: /* transmitter empty */ ! 427: cq = up->oq; ! 428: if(cq == 0) ! 429: break; ! 430: if(multiprocessor) ! 431: lock(cq); ! 432: if(up->cts == 0) ! 433: up->printing = 0; ! 434: else { ! 435: ch = getc(cq); ! 436: if(ch < 0){ ! 437: up->printing = 0; ! 438: wakeup(&cq->r); ! 439: }else ! 440: outb(up->port + Data, ch); ! 441: } ! 442: if(multiprocessor) ! 443: unlock(cq); ! 444: break; ! 445: ! 446: case 0: /* modem status */ ! 447: ch = uartrdreg(up, Mstat); ! 448: if(ch & Ctsc){ ! 449: up->cts = ch & Cts; ! 450: cq = up->oq; ! 451: if(cq == 0) ! 452: break; ! 453: if(multiprocessor) ! 454: lock(cq); ! 455: if(up->cts && up->printing == 0){ ! 456: ch = getc(cq); ! 457: if(ch >= 0){ ! 458: up->printing = 1; ! 459: outb(up->port + Data, ch); ! 460: } else ! 461: wakeup(&cq->r); ! 462: } ! 463: if(multiprocessor) ! 464: unlock(cq); ! 465: } ! 466: break; ! 467: ! 468: default: ! 469: if(s&1) ! 470: return; ! 471: print("weird modem interrupt #%2.2ux\n", s); ! 472: break; ! 473: } ! 474: } ! 475: } ! 476: ! 477: void ! 478: mp008intr(Ureg *ur, void *a) ! 479: { ! 480: uchar i, n; ! 481: Scard *sc = a; ! 482: ! 483: USED(ur); ! 484: ! 485: n = ~inb(sc->mem); ! 486: for(i = 0; n; i++){ ! 487: if(n & 1) ! 488: uartintr(ur, &uart[sc->first + i]); ! 489: n >>= 1; ! 490: } ! 491: } ! 492: ! 493: void ! 494: uartclock(void) ! 495: { ! 496: Uart *up; ! 497: IOQ *cq; ! 498: ! 499: for(up = uart; up < &uart[Nuart]; up++){ ! 500: cq = up->iq; ! 501: if(up->wq && cangetc(cq)) ! 502: wakeup(&cq->r); ! 503: } ! 504: } ! 505: ! 506: ! 507: /* ! 508: * turn on a port's interrupts. set DTR and RTS ! 509: */ ! 510: void ! 511: uartenable(Uart *up) ! 512: { ! 513: /* ! 514: * turn on power to the port ! 515: */ ! 516: if(up == &uart[Modem]){ ! 517: if(modem(1) < 0) ! 518: print("can't turn on modem speaker\n"); ! 519: } else { ! 520: if(serial(1) < 0) ! 521: print("can't turn on serial port power\n"); ! 522: } ! 523: ! 524: /* ! 525: * set up i/o routines ! 526: */ ! 527: if(up->oq){ ! 528: up->oq->puts = uartputs; ! 529: up->oq->ptr = up; ! 530: } ! 531: if(up->iq){ ! 532: up->iq->ptr = up; ! 533: } ! 534: up->enabled = 1; ! 535: ! 536: /* ! 537: * turn on interrupts ! 538: */ ! 539: up->sticky[Iena] = Ircv | Ixmt | Irstat; ! 540: uartwrreg(up, Iena, 0); ! 541: ! 542: /* ! 543: * turn on DTR and RTS ! 544: */ ! 545: uartdtr(up, 1); ! 546: uartrts(up, 1); ! 547: ! 548: /* ! 549: * assume we can send ! 550: */ ! 551: up->cts = 1; ! 552: } ! 553: ! 554: /* ! 555: * turn off the uart ! 556: */ ! 557: void ! 558: uartdisable(Uart *up) ! 559: { ! 560: ! 561: /* ! 562: * turn off interrupts ! 563: */ ! 564: up->sticky[Iena] = 0; ! 565: uartwrreg(up, Iena, 0); ! 566: ! 567: /* ! 568: * revert to default settings ! 569: */ ! 570: up->sticky[Format] = Bits8; ! 571: uartwrreg(up, Format, 0); ! 572: ! 573: /* ! 574: * turn off DTR and RTS ! 575: */ ! 576: uartdtr(up, 0); ! 577: uartrts(up, 0); ! 578: up->enabled = 0; ! 579: ! 580: /* ! 581: * turn off power ! 582: */ ! 583: if(up == &uart[Modem]){ ! 584: if(modem(0) < 0) ! 585: print("can't turn off modem speaker\n"); ! 586: } else { ! 587: if(serial(0) < 0) ! 588: print("can't turn off serial power\n"); ! 589: } ! 590: } ! 591: ! 592: /* ! 593: * set up an uart port as something other than a stream ! 594: */ ! 595: void ! 596: uartspecial(int port, IOQ *oq, IOQ *iq, int baud) ! 597: { ! 598: Uart *up = &uart[port]; ! 599: ! 600: uartsetup(); ! 601: up->special = 1; ! 602: up->oq = oq; ! 603: up->iq = iq; ! 604: uartenable(up); ! 605: if(baud) ! 606: uartsetbaud(up, baud); ! 607: ! 608: if(iq){ ! 609: /* ! 610: * Stupid HACK to undo a stupid hack ! 611: */ ! 612: if(iq == &kbdq) ! 613: kbdq.putc = kbdcr2nl; ! 614: } ! 615: } ! 616: ! 617: static int uartputc(IOQ *, int); ! 618: static void uartstopen(Queue*, Stream*); ! 619: static void uartstclose(Queue*); ! 620: static void uartoput(Queue*, Block*); ! 621: static void uartkproc(void *); ! 622: Qinfo uartinfo = ! 623: { ! 624: nullput, ! 625: uartoput, ! 626: uartstopen, ! 627: uartstclose, ! 628: "uart" ! 629: }; ! 630: ! 631: static void ! 632: uartstopen(Queue *q, Stream *s) ! 633: { ! 634: Uart *up; ! 635: char name[NAMELEN]; ! 636: ! 637: up = &uart[s->id]; ! 638: up->iq->putc = 0; ! 639: uartenable(up); ! 640: ! 641: qlock(up); ! 642: up->wq = WR(q); ! 643: WR(q)->ptr = up; ! 644: RD(q)->ptr = up; ! 645: qunlock(up); ! 646: ! 647: if(up->kstarted == 0){ ! 648: up->kstarted = 1; ! 649: sprint(name, "uart%d", s->id); ! 650: kproc(name, uartkproc, up); ! 651: } ! 652: } ! 653: ! 654: static void ! 655: uartstclose(Queue *q) ! 656: { ! 657: Uart *up = q->ptr; ! 658: ! 659: if(up->special) ! 660: return; ! 661: ! 662: uartdisable(up); ! 663: ! 664: qlock(up); ! 665: kprint("uartstclose: q=0x%ux, id=%d\n", q, up-uart); ! 666: up->wq = 0; ! 667: up->iq->putc = 0; ! 668: WR(q)->ptr = 0; ! 669: RD(q)->ptr = 0; ! 670: qunlock(up); ! 671: } ! 672: ! 673: static int ! 674: xmtempty(void *arg) ! 675: { ! 676: IOQ *q=arg; ! 677: ! 678: return !cangetc(q); ! 679: } ! 680: ! 681: static void ! 682: uartoput(Queue *q, Block *bp) ! 683: { ! 684: Uart *up = q->ptr; ! 685: IOQ *cq; ! 686: int n, m; ! 687: ! 688: if(up == 0){ ! 689: freeb(bp); ! 690: return; ! 691: } ! 692: cq = up->oq; ! 693: if(waserror()){ ! 694: freeb(bp); ! 695: nexterror(); ! 696: } ! 697: if(bp->type == M_CTL){ ! 698: if(cangetc(cq)) /* let output drain */ ! 699: sleep(&cq->r, xmtempty, cq); ! 700: n = strtoul((char *)(bp->rptr+1), 0, 0); ! 701: switch(*bp->rptr){ ! 702: case 'B': ! 703: case 'b': ! 704: if(n <= 0) ! 705: error(Ebadctl); ! 706: uartsetbaud(up, n); ! 707: break; ! 708: case 'D': ! 709: case 'd': ! 710: uartdtr(up, n); ! 711: break; ! 712: case 'K': ! 713: case 'k': ! 714: uartbreak(up, n); ! 715: break; ! 716: case 'L': ! 717: case 'l': ! 718: uartbits(up, n); ! 719: break; ! 720: case 'm': ! 721: case 'M': ! 722: uartmflow(up, n); ! 723: break; ! 724: case 'P': ! 725: case 'p': ! 726: uartparity(up, *(bp->rptr+1)); ! 727: break; ! 728: case 'R': ! 729: case 'r': ! 730: uartrts(up, n); ! 731: break; ! 732: case 'S': ! 733: case 's': ! 734: uartstop(up, n); ! 735: break; ! 736: } ! 737: }else while((m = BLEN(bp)) > 0){ ! 738: while ((n = canputc(cq)) == 0){ ! 739: sleep(&cq->r, canputc, cq); ! 740: } ! 741: if(n > m) ! 742: n = m; ! 743: (*cq->puts)(cq, bp->rptr, n); ! 744: bp->rptr += n; ! 745: } ! 746: freeb(bp); ! 747: poperror(); ! 748: } ! 749: ! 750: /* ! 751: * process to send bytes upstream for a port ! 752: */ ! 753: static void ! 754: uartkproc(void *a) ! 755: { ! 756: Uart *up = a; ! 757: IOQ *cq = up->iq; ! 758: Block *bp; ! 759: int n; ! 760: ulong frame, overrun; ! 761: static ulong ints; ! 762: ! 763: frame = 0; ! 764: overrun = 0; ! 765: ! 766: if(waserror()) ! 767: print("uartkproc got an error\n"); ! 768: ! 769: for(;;){ ! 770: sleep(&cq->r, cangetc, cq); ! 771: if((ints++ & 0x1f) == 0) ! 772: lights((ints>>5)&1); ! 773: qlock(up); ! 774: if(up->wq == 0){ ! 775: cq->out = cq->in; ! 776: }else{ ! 777: n = cangetc(cq); ! 778: bp = allocb(n); ! 779: bp->flags |= S_DELIM; ! 780: bp->wptr += gets(cq, bp->wptr, n); ! 781: PUTNEXT(RD(up->wq), bp); ! 782: } ! 783: qunlock(up); ! 784: if(up->frame != frame){ ! 785: kprint("uart%d: %d framing\n", up-uart, up->frame); ! 786: frame = up->frame; ! 787: } ! 788: if(up->overrun != overrun){ ! 789: kprint("uart%d: %d overruns\n", up-uart, up->overrun); ! 790: overrun = up->overrun; ! 791: } ! 792: } ! 793: } ! 794: ! 795: enum{ ! 796: Qdir= 0, ! 797: }; ! 798: ! 799: Dirtab uartdir[2*nelem(uart)]; ! 800: ! 801: /* ! 802: * allocate the queues if no one else has ! 803: */ ! 804: void ! 805: uartreset(void) ! 806: { ! 807: Uart *up; ! 808: ! 809: uartsetup(); ! 810: for(up = uart; up < &uart[Nuart]; up++){ ! 811: if(up->special) ! 812: continue; ! 813: up->iq = xalloc(sizeof(IOQ)); ! 814: initq(up->iq); ! 815: up->oq = xalloc(sizeof(IOQ)); ! 816: initq(up->oq); ! 817: } ! 818: } ! 819: ! 820: void ! 821: uartinit(void) ! 822: { ! 823: int i; ! 824: ! 825: for(i=0; i < 2*Nuart; ++i) { ! 826: if(i & 1) { ! 827: sprint(uartdir[i].name, "eia%dctl", i/2); ! 828: uartdir[i].qid.path = STREAMQID(i/2, Sctlqid); ! 829: } else { ! 830: sprint(uartdir[i].name, "eia%d", i/2); ! 831: uartdir[i].qid.path = STREAMQID(i/2, Sdataqid); ! 832: } ! 833: uartdir[i].length = 0; ! 834: uartdir[i].perm = 0660; ! 835: } ! 836: } ! 837: ! 838: Chan* ! 839: uartattach(char *upec) ! 840: { ! 841: return devattach('t', upec); ! 842: } ! 843: ! 844: Chan* ! 845: uartclone(Chan *c, Chan *nc) ! 846: { ! 847: return devclone(c, nc); ! 848: } ! 849: ! 850: int ! 851: uartwalk(Chan *c, char *name) ! 852: { ! 853: return devwalk(c, name, uartdir, Nuart * 2, devgen); ! 854: } ! 855: ! 856: void ! 857: uartstat(Chan *c, char *dp) ! 858: { ! 859: int i; ! 860: ! 861: for(i=0; i < 2*Nuart; i += 2) ! 862: if(c->qid.path == uartdir[i].qid.path) { ! 863: streamstat(c, dp, uartdir[i].name, uartdir[i].perm); ! 864: return; ! 865: } ! 866: devstat(c, dp, uartdir, Nuart * 2, devgen); ! 867: } ! 868: ! 869: Chan* ! 870: uartopen(Chan *c, int omode) ! 871: { ! 872: Uart *up; ! 873: int i; ! 874: ! 875: up = 0; ! 876: for(i=0; i < 2*Nuart; ++i) ! 877: if(c->qid.path == uartdir[i].qid.path) { ! 878: up = &uart[i/2]; ! 879: break; ! 880: } ! 881: ! 882: if(up && up->special) ! 883: error(Einuse); ! 884: if((c->qid.path & CHDIR) == 0) ! 885: streamopen(c, &uartinfo); ! 886: return devopen(c, omode, uartdir, Nuart * 2, devgen); ! 887: } ! 888: ! 889: void ! 890: uartcreate(Chan *c, char *name, int omode, ulong perm) ! 891: { ! 892: USED(c, name, omode, perm); ! 893: error(Eperm); ! 894: } ! 895: ! 896: void ! 897: uartclose(Chan *c) ! 898: { ! 899: if(c->stream) ! 900: streamclose(c); ! 901: } ! 902: ! 903: long ! 904: uartstatus(Uart *up, void *buf, long n, ulong offset) ! 905: { ! 906: uchar mstat; ! 907: uchar tstat; ! 908: char str[128]; ! 909: ! 910: str[0] = 0; ! 911: tstat = up->sticky[Mctl]; ! 912: mstat = uartrdreg(up, Mstat); ! 913: if(mstat & Cts) ! 914: strcat(str, " cts"); ! 915: if(mstat & Dsr) ! 916: strcat(str, " dsr"); ! 917: if(mstat & Ring) ! 918: strcat(str, " ring"); ! 919: if(mstat & Dcd) ! 920: strcat(str, " dcd"); ! 921: if(tstat & Dtr) ! 922: strcat(str, " dtr"); ! 923: if(tstat & Rts) ! 924: strcat(str, " rts"); ! 925: return readstr(offset, buf, n, str); ! 926: } ! 927: ! 928: long ! 929: uartread(Chan *c, void *buf, long n, ulong offset) ! 930: { ! 931: int i; ! 932: long qpath; ! 933: ! 934: USED(offset); ! 935: qpath = c->qid.path & ~CHDIR; ! 936: if(qpath == Qdir) ! 937: return devdirread(c, buf, n, uartdir, Nuart * 2, devgen); ! 938: for(i=1; i < 2*Nuart; i += 2) ! 939: if(qpath == uartdir[i].qid.path) ! 940: return uartstatus(&uart[i/2], buf, n, offset); ! 941: return streamread(c, buf, n); ! 942: } ! 943: ! 944: long ! 945: uartwrite(Chan *c, void *va, long n, ulong offset) ! 946: { ! 947: USED(offset); ! 948: return streamwrite(c, va, n, 0); ! 949: } ! 950: ! 951: void ! 952: uartremove(Chan *c) ! 953: { ! 954: USED(c); ! 955: error(Eperm); ! 956: } ! 957: ! 958: void ! 959: uartwstat(Chan *c, char *dp) ! 960: { ! 961: USED(c, dp); ! 962: error(Eperm); ! 963: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.