Annotation of lucent/sys/src/9/pc/devuart.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.