Annotation of lucent/sys/src/9/port/devscc.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: 
                     11: /*
                     12:  *  Driver for the Z8530.
                     13:  */
                     14: enum
                     15: {
                     16:        /* wr 0 */
                     17:        ResExtPend=     2<<3,
                     18:        ResTxPend=      5<<3,
                     19:        ResErr=         6<<3,
                     20: 
                     21:        /* wr 1 */
                     22:        ExtIntEna=      1<<0,
                     23:        TxIntEna=       1<<1,
                     24:        RxIntDis=       0<<3,
                     25:        RxIntFirstEna=  1<<3,
                     26:        RxIntAllEna=    2<<3,
                     27: 
                     28:        /* wr 3 */
                     29:        RxEna=          1,
                     30:        Rx5bits=        0<<6,
                     31:        Rx7bits=        1<<6,
                     32:        Rx6bits=        2<<6,
                     33:        Rx8bits=        3<<6,
                     34:        Rxbitmask=      3<<6,
                     35: 
                     36:        /* wr 4 */
                     37:        ParEven=        3<<0,
                     38:        ParOdd=         1<<0,
                     39:        ParOff=         0<<0,
                     40:        ParMask=        3<<0,
                     41:        SyncMode=       0<<2,
                     42:        Rx1stop=        1<<2,
                     43:        Rx1hstop=       2<<2,
                     44:        Rx2stop=        3<<2,
                     45:        X16=            1<<6,
                     46: 
                     47:        /* wr 5 */
                     48:        TxRTS=          1<<1,
                     49:        TxEna=          1<<3,
                     50:        TxBreak=        1<<4,
                     51:        TxDTR=          1<<7,
                     52:        Tx5bits=        0<<5,
                     53:        Tx7bits=        1<<5,
                     54:        Tx6bits=        2<<5,
                     55:        Tx8bits=        3<<5,
                     56:        Txbitmask=      3<<5,
                     57: 
                     58:        /* wr 9 */
                     59:        IntEna=         1<<3,
                     60:        ResetB=         1<<6,
                     61:        ResetA=         2<<6,
                     62:        HardReset=      3<<6,
                     63: 
                     64:        /* wr 11 */
                     65:        TRxCOutBR=      2,
                     66:        TxClockTRxC=    1<<3,
                     67:        TxClockBR=      2<<3,
                     68:        RxClockTRxC=    1<<5,
                     69:        RxClockBR=      2<<5,
                     70:        TRxCOI=         1<<2,
                     71: 
                     72:        /* wr 14 */
                     73:        BREna=          1,
                     74:        BRSource=       2,
                     75: 
                     76:        /* rr 0 */
                     77:        RxReady=        1,
                     78:        TxReady=        1<<2,
                     79:        RxDCD=          1<<3,
                     80:        RxCTS=          1<<5,
                     81:        RxBreak=        1<<7,
                     82: 
                     83:        /* rr 3 */
                     84:        ExtPendB=       1,      
                     85:        TxPendB=        1<<1,
                     86:        RxPendB=        1<<2,
                     87:        ExtPendA=       1<<3,   
                     88:        TxPendA=        1<<4,
                     89:        RxPendA=        1<<5,
                     90: };
                     91: 
                     92: typedef struct SCC     SCC;
                     93: struct SCC
                     94: {
                     95:        QLock;
                     96:        ushort  sticky[16];     /* sticky write register values */
                     97:        uchar*  ptr;            /* command/pointer register in Z8530 */
                     98:        uchar*  data;           /* data register in Z8530 */
                     99:        int     printing;       /* true if printing */
                    100:        ulong   freq;           /* clock frequency */
                    101:        uchar   mask;           /* bits/char */
                    102: 
                    103:        /* console interface */
                    104:        int     special;        /* can't use the stream interface */
                    105:        IOQ*    iq;             /* input character queue */
                    106:        IOQ*    oq;             /* output character queue */
                    107: 
                    108:        /* stream interface */
                    109:        Queue*  wq;             /* write queue */
                    110:        Rendez  r;              /* kproc waiting for input */
                    111:        int     kstarted;       /* kproc started */
                    112: 
                    113:        /* idiot flow control */
                    114:        int     xonoff;         /* true if we obey this tradition */
                    115:        int     blocked;        /* abstinence */
                    116: };
                    117: 
                    118: int    invrtsdtr;      /* set to 1 on indigo's */
                    119: int    nscc;
                    120: SCC    *scc[8];        /* up to 4 8530's */
                    121: #define CTLS   023
                    122: #define CTLQ   021
                    123: 
                    124: #ifdef Zduart
                    125: #define        SCCTYPE 'z'
                    126: #define        onepointseven()
                    127: #else
                    128: #define        SCCTYPE 't'
                    129: void
                    130: onepointseven(void)
                    131: {
                    132:        int i;
                    133:        for(i = 0; i < 20; i++)
                    134:                ;
                    135: }
                    136: #endif
                    137: 
                    138: /*
                    139:  *  Access registers using the pointer in register 0.
                    140:  *  This is a bit stupid when accessing register 0.
                    141:  */
                    142: void
                    143: sccwrreg(SCC *sp, int addr, int value)
                    144: {
                    145:        onepointseven();
                    146:        *sp->ptr = addr;
                    147:        wbflush();
                    148:        onepointseven();
                    149:        *sp->ptr = sp->sticky[addr] | value;
                    150:        wbflush();
                    151: }
                    152: ushort
                    153: sccrdreg(SCC *sp, int addr)
                    154: {
                    155:        onepointseven();
                    156:        *sp->ptr = addr;
                    157:        wbflush();
                    158:        onepointseven();
                    159:        return *sp->ptr;
                    160: }
                    161: 
                    162: /*
                    163:  *  set the baud rate by calculating and setting the baudrate
                    164:  *  generator constant.  This will work with fairly non-standard
                    165:  *  baud rates.
                    166:  */
                    167: void
                    168: sccsetbaud(SCC *sp, int rate)
                    169: {
                    170:        int brconst;
                    171: 
                    172:        if(rate == 0)
                    173:                error(Ebadctl);
                    174: 
                    175:        brconst = (sp->freq+16*rate-1)/(2*16*rate) - 2;
                    176: 
                    177:        sccwrreg(sp, 12, brconst & 0xff);
                    178:        sccwrreg(sp, 13, (brconst>>8) & 0xff);
                    179: }
                    180: 
                    181: void
                    182: sccparity(SCC *sp, char type)
                    183: {
                    184:        int val;
                    185: 
                    186:        switch(type){
                    187:        case 'e':
                    188:                val = ParEven;
                    189:                break;
                    190:        case 'o':
                    191:                val = ParOdd;
                    192:                break;
                    193:        default:
                    194:                val = ParOff;
                    195:                break;
                    196:        }
                    197:        sp->sticky[4] = (sp->sticky[4] & ~ParMask) | val;
                    198:        sccwrreg(sp, 4, 0);
                    199: }
                    200: 
                    201: /*
                    202:  *  set bits/character, default 8
                    203:  */
                    204: void
                    205: sccbits(SCC *sp, int n)
                    206: {
                    207:        int rbits, tbits;
                    208: 
                    209:        switch(n){
                    210:        case 5:
                    211:                sp->mask = 0x1f;
                    212:                rbits = Rx5bits;
                    213:                tbits = Tx5bits;
                    214:                break;
                    215:        case 6:
                    216:                sp->mask = 0x3f;
                    217:                rbits = Rx6bits;
                    218:                tbits = Tx6bits;
                    219:                break;
                    220:        case 7:
                    221:                sp->mask = 0x7f;
                    222:                rbits = Rx7bits;
                    223:                tbits = Tx7bits;
                    224:                break;
                    225:        case 8:
                    226:        default:
                    227:                sp->mask = 0xff;
                    228:                rbits = Rx8bits;
                    229:                tbits = Tx8bits;
                    230:                break;
                    231:        }
                    232:        sp->sticky[3] = (sp->sticky[3]&~Rxbitmask) | rbits;
                    233:        sccwrreg(sp, 3, 0);
                    234:        sp->sticky[5] = (sp->sticky[5]&~Txbitmask) | tbits;
                    235:        sccwrreg(sp, 5, 0);
                    236: }
                    237: 
                    238: /*
                    239:  *  set/clear external clock mode; the indigo uses the CTS pin,
                    240:  *  so we disable external interrupts.
                    241:  */
                    242: void
                    243: sccextclk(SCC *sp, int n)
                    244: {
                    245:        if(n){
                    246:                sp->sticky[1] &= ~ExtIntEna;
                    247:                sp->sticky[11] = TxClockTRxC | RxClockTRxC;
                    248:        }else{
                    249:                sp->sticky[1] |= ExtIntEna;
                    250:                sp->sticky[11] = TxClockBR | RxClockBR | TRxCOutBR;
                    251:        }
                    252:        sccwrreg(sp, 1, 0);
                    253:        sccwrreg(sp, 11, 0);
                    254: }
                    255: 
                    256: /*
                    257:  *  toggle DTR
                    258:  */
                    259: void
                    260: sccdtr(SCC *sp, int n)
                    261: {
                    262:        if((n!=0)^invrtsdtr)
                    263:                sp->sticky[5] |= TxDTR;
                    264:        else
                    265:                sp->sticky[5] &=~TxDTR;
                    266:        sccwrreg(sp, 5, 0);
                    267: }
                    268: 
                    269: /*
                    270:  *  toggle RTS
                    271:  */
                    272: void
                    273: sccrts(SCC *sp, int n)
                    274: {
                    275:        if((n!=0)^invrtsdtr)
                    276:                sp->sticky[5] |= TxRTS;
                    277:        else
                    278:                sp->sticky[5] &=~TxRTS;
                    279:        sccwrreg(sp, 5, 0);
                    280: }
                    281: 
                    282: /*
                    283:  *  send break
                    284:  */
                    285: void
                    286: sccbreak(SCC *sp, int ms)
                    287: {
                    288:        if(ms == 0)
                    289:                ms = 100;
                    290:        sp->sticky[1] &=~TxIntEna;
                    291:        sccwrreg(sp, 1, 0);
                    292:        sccwrreg(sp, 5, TxBreak|TxEna);
                    293:        tsleep(&u->p->sleep, return0, 0, ms);
                    294:        sccwrreg(sp, 5, 0);
                    295:        if(sp->oq){
                    296:                sp->sticky[1] |= TxIntEna;
                    297:                sccwrreg(sp, 1, 0);
                    298:        }
                    299: }
                    300: 
                    301: /*
                    302:  *  set number of stop bits
                    303:  */
                    304: void
                    305: sccnstop(SCC *sp, char code)
                    306: {
                    307:        sp->sticky[4] &=~Rx2stop;
                    308:        switch(code){
                    309:        default:
                    310:                sp->sticky[4] |= Rx1stop;
                    311:                break;
                    312:        case 'h':
                    313:                sp->sticky[4] |= Rx1hstop;
                    314:                break;
                    315:        case '2':
                    316:                sp->sticky[4] |= Rx2stop;
                    317:                break;
                    318:        }
                    319:        sccwrreg(sp, 4, 0);
                    320: }
                    321: 
                    322: /*
                    323:  *  default is 9600 baud, 1 stop bit, 8 bit chars, no interrupts,
                    324:  *  transmit and receive enabled, interrupts disabled.
                    325:  */
                    326: static void
                    327: sccsetup0(SCC *sp, int brsource)
                    328: {
                    329:        memset(sp->sticky, 0, sizeof(sp->sticky));
                    330: 
                    331:        /*
                    332:         *  turn on baud rate generator and set rate to 9600 baud.
                    333:         *  use 1 stop bit.
                    334:         */
                    335:        sp->sticky[14] = brsource ? BRSource : 0;
                    336:        sccwrreg(sp, 14, 0);
                    337:        sccsetbaud(sp, 9600);
                    338:        sp->sticky[4] = Rx1stop | X16;
                    339:        sccwrreg(sp, 4, 0);
                    340:        sp->sticky[11] = TxClockBR | RxClockBR | TRxCOutBR /*| TRxCOI*/;
                    341:        sccwrreg(sp, 11, 0);
                    342:        sp->sticky[14] = BREna;
                    343:        if(brsource)
                    344:                sp->sticky[14] |= BRSource;
                    345:        sccwrreg(sp, 14, 0);
                    346: 
                    347:        /*
                    348:         *  enable I/O, 8 bits/character
                    349:         */
                    350:        sp->sticky[3] = RxEna | Rx8bits;
                    351:        sccwrreg(sp, 3, 0);
                    352:        sp->sticky[5] = TxEna | Tx8bits;
                    353:        sccwrreg(sp, 5, 0);
                    354:        sp->mask = 0xff;
                    355: }
                    356: 
                    357: void
                    358: sccsetup(void *addr, ulong freq, int brsource)
                    359: {
                    360:        SCCdev *dev;
                    361:        SCC *sp;
                    362: 
                    363:        dev = addr;
                    364: 
                    365:        /*
                    366:         *  allocate a structure, set port addresses, and setup the line
                    367:         */
                    368:        sp = xalloc(sizeof(SCC));
                    369:        scc[nscc] = sp;
                    370:        sp->ptr = &dev->ptra;
                    371:        sp->data = &dev->dataa;
                    372:        sp->freq = freq;
                    373:        sccsetup0(sp, brsource);
                    374:        sp = xalloc(sizeof(SCC));
                    375:        scc[nscc+1] = sp;
                    376:        sp->ptr = &dev->ptrb;
                    377:        sp->data = &dev->datab;
                    378:        sp->freq = freq;
                    379:        sccsetup0(sp, brsource);
                    380:        nscc += 2;
                    381: }
                    382: 
                    383: void
                    384: sccputc(int port, char ch)
                    385: {
                    386:        SCC *sp;
                    387: 
                    388:        sp = scc[port];
                    389:        for(;;) {
                    390:                onepointseven();
                    391:                if(*sp->ptr & TxReady)
                    392:                        break;
                    393:        }
                    394:        onepointseven();
                    395:        *sp->data = ch;
                    396: }
                    397: 
                    398: int
                    399: iprint(char *fmt, ...)
                    400: {
                    401:        int n, i;
                    402:        char buf[512];
                    403: 
                    404:        n = doprint(buf, buf+sizeof(buf), fmt, (&fmt+1)) - buf;
                    405:        for(i = 0; i < n; i++)
                    406:                sccputc(1, buf[i]);
                    407:        return n;
                    408: }
                    409: 
                    410: /*
                    411:  *  Queue n characters for output; if queue is full, we lose characters.
                    412:  *  Get the output going if it isn't already.
                    413:  */
                    414: void
                    415: sccputs(IOQ *cq, char *s, int n)
                    416: {
                    417:        SCC *sp = cq->ptr;
                    418:        int ch, x;
                    419: 
                    420:        x = splhi();
                    421:        lock(cq);
                    422:        puts(cq, s, n);
                    423:        if(sp->printing == 0 && sp->blocked==0){
                    424:                ch = getc(cq);
                    425:                /*kprint("<start %2.2ux>", ch);*/
                    426:                if(ch >= 0){
                    427:                        sp->printing = 1;
                    428:                        while((*sp->ptr&TxReady)==0)
                    429:                                ;
                    430:                        *sp->data = ch;
                    431:                }
                    432:        }
                    433:        unlock(cq);
                    434:        splx(x);
                    435: }
                    436: 
                    437: /*
                    438:  *  an scc interrupt (a damn lot of work for one character)
                    439:  */
                    440: void
                    441: sccintr0(SCC *sp, uchar x)
                    442: {
                    443:        int ch;
                    444:        IOQ *cq;
                    445: 
                    446:        if(x & ExtPendB){
                    447:                sccwrreg(sp, 0, ResExtPend);
                    448:        }
                    449:        if(x & RxPendB){
                    450:                cq = sp->iq;
                    451:                while(*sp->ptr&RxReady){
                    452:                        onepointseven();
                    453:                        ch = *sp->data & sp->mask;
                    454:                        if (ch == CTLS && sp->xonoff)
                    455:                                sp->blocked = 1;
                    456:                        else if (ch == CTLQ && sp->xonoff) {
                    457:                                sp->blocked = 0;
                    458:                                sccputs(sp->oq, "", 0);
                    459:                        }
                    460:                        if(cq->putc)
                    461:                                (*cq->putc)(cq, ch);
                    462:                        else
                    463:                                putc(cq, ch);
                    464:                }
                    465:        }
                    466:        if(x & TxPendB){
                    467:                if (sp->blocked) {
                    468:                        sccwrreg(sp, 0, ResTxPend);
                    469:                        sp->printing = 0;
                    470:                        return;
                    471:                }
                    472:                cq = sp->oq;
                    473:                lock(cq);
                    474:                ch = getc(cq);
                    475:                onepointseven();
                    476:                if(ch < 0){
                    477:                        sccwrreg(sp, 0, ResTxPend);
                    478:                        sp->printing = 0;
                    479:                        wakeup(&cq->r);
                    480:                }else
                    481:                        *sp->data = ch;
                    482:                unlock(cq);
                    483:        }
                    484: }
                    485: 
                    486: int
                    487: sccintr(void)
                    488: {
                    489:        uchar x;
                    490:        int i, j;
                    491: 
                    492:        for(i = j = 0; i < nscc; i += 2){
                    493:                x = sccrdreg(scc[i], 3);
                    494:                if(x & (ExtPendB|RxPendB|TxPendB))
                    495:                        ++j, sccintr0(scc[i+1], x);
                    496:                x = x >> 3;
                    497:                if(x & (ExtPendB|RxPendB|TxPendB))
                    498:                        ++j, sccintr0(scc[i], x);
                    499:        }
                    500:        return j;
                    501: }
                    502: 
                    503: void
                    504: sccclock(void)
                    505: {
                    506:        SCC *sp;
                    507:        IOQ *cq;
                    508:        int i;
                    509: 
                    510:        for(i = 0; i < nscc; i++){
                    511:                sp = scc[i];
                    512:                cq = sp->iq;
                    513:                if(sp->wq && cangetc(cq))
                    514:                        wakeup(&cq->r);
                    515:        }
                    516: }
                    517: 
                    518: /*
                    519:  *  turn on a port's interrupts.  set DTR and RTS
                    520:  */
                    521: void
                    522: sccenable(SCC *sp)
                    523: {
                    524:        /*
                    525:         *  set up i/o routines
                    526:         */
                    527:        if(sp->oq){
                    528:                sp->oq->puts = sccputs;
                    529:                sp->oq->ptr = sp;
                    530:                sp->sticky[1] |= TxIntEna | ExtIntEna;
                    531:        }
                    532:        if(sp->iq){
                    533:                sp->iq->ptr = sp;
                    534:                sp->sticky[1] |= RxIntAllEna | ExtIntEna;
                    535:        }
                    536: 
                    537:        /*
                    538:         *  turn on interrupts
                    539:         */
                    540:        sccwrreg(sp, 1, 0);
                    541:        sp->sticky[9] |= IntEna;
                    542:        sccwrreg(sp, 9, 0);
                    543: 
                    544:        /*
                    545:         *  turn on DTR and RTS
                    546:         */
                    547:        sccdtr(sp, 1);
                    548:        sccrts(sp, 1);
                    549: }
                    550: 
                    551: /*
                    552:  *  set up an scc port as something other than a stream
                    553:  */
                    554: void
                    555: sccspecial(int port, IOQ *oq, IOQ *iq, int baud)
                    556: {
                    557:        SCC *sp = scc[port];
                    558: 
                    559:        /* let output drain */
                    560:        if(sp->oq){
                    561:                while(cangetc(sp->oq))
                    562:                        sleep(&sp->oq->r, cangetc, sp->oq);
                    563:                tsleep(&sp->oq->r, cangetc, sp->oq, 50);
                    564:        }
                    565: 
                    566:        sp->special = 1;
                    567:        sp->oq = oq;
                    568:        sp->iq = iq;
                    569:        sccenable(sp);
                    570:        if(baud)
                    571:                sccsetbaud(sp, baud);
                    572: 
                    573:        if(iq){
                    574:                /*
                    575:                 *  Stupid HACK to undo a stupid hack
                    576:                 */ 
                    577:                if(iq == &kbdq)
                    578:                        kbdq.putc = kbdcr2nl;
                    579:        }
                    580: }
                    581: 
                    582: void
                    583: sccrawput(int port, int c)
                    584: {
                    585:        SCC *sp = scc[port];
                    586: 
                    587:        if(c == '\n') {
                    588:                sccrawput(port, '\r');
                    589:                delay(100);
                    590:        }
                    591: 
                    592:        while((*sp->ptr&TxReady)==0)
                    593:                ;
                    594:        *sp->data = c;
                    595: }
                    596: 
                    597: static void    sccstopen(Queue*, Stream*);
                    598: static void    sccstclose(Queue*);
                    599: static void    sccoput(Queue*, Block*);
                    600: static void    scckproc(void *);
                    601: Qinfo sccinfo =
                    602: {
                    603:        nullput,
                    604:        sccoput,
                    605:        sccstopen,
                    606:        sccstclose,
                    607:        "scc"
                    608: };
                    609: 
                    610: static void
                    611: sccstopen(Queue *q, Stream *s)
                    612: {
                    613:        SCC *sp;
                    614:        char name[NAMELEN];
                    615: 
                    616:        kprint("sccstopen: q=0x%ux, inuse=%d, type=%d, dev=%d, id=%d\n",
                    617:                q, s->inuse, s->type, s->dev, s->id);
                    618:        sp = scc[s->id];
                    619:        qlock(sp);
                    620:        sp->wq = WR(q);
                    621:        WR(q)->ptr = sp;
                    622:        RD(q)->ptr = sp;
                    623:        qunlock(sp);
                    624: 
                    625:        if(sp->kstarted == 0){
                    626:                sp->kstarted = 1;
                    627:                sprint(name, "scc%d", s->id);
                    628:                kproc(name, scckproc, sp);
                    629:        }
                    630: }
                    631: 
                    632: static void
                    633: sccstclose(Queue *q)
                    634: {
                    635:        SCC *sp = q->ptr;
                    636: 
                    637:        if(sp->special)
                    638:                return;
                    639: 
                    640:        qlock(sp);
                    641:        sp->wq = 0;
                    642:        sp->iq->putc = 0;
                    643:        WR(q)->ptr = 0;
                    644:        RD(q)->ptr = 0;
                    645:        qunlock(sp);
                    646: }
                    647: 
                    648: static void
                    649: sccoput(Queue *q, Block *bp)
                    650: {
                    651:        SCC *sp = q->ptr;
                    652:        IOQ *cq;
                    653:        int n, m;
                    654: 
                    655:        if(sp == 0){
                    656:                freeb(bp);
                    657:                return;
                    658:        }
                    659:        cq = sp->oq;
                    660:        if(waserror()){
                    661:                freeb(bp);
                    662:                nexterror();
                    663:        }
                    664:        if(bp->type == M_CTL){
                    665:                if(*bp->rptr == '!')    /* do it now! */
                    666:                        ++bp->rptr;
                    667:                else while(cangetc(cq)) /* else let output drain */
                    668:                        sleep(&cq->r, cangetc, cq);
                    669:                n = strtoul((char *)(bp->rptr+1), 0, 0);
                    670:                switch(*bp->rptr){
                    671:                case 'B':
                    672:                case 'b':
                    673:                        if(BLEN(bp)>4 && strncmp((char*)(bp->rptr+1), "reak", 4) == 0)
                    674:                                sccbreak(sp, 0);
                    675:                        else
                    676:                                sccsetbaud(sp, n);
                    677:                        break;
                    678:                case 'C':
                    679:                case 'c':
                    680:                        sccextclk(sp, n);
                    681:                        break;
                    682:                case 'D':
                    683:                case 'd':
                    684:                        sccdtr(sp, n);
                    685:                        break;
                    686:                case 'L':
                    687:                case 'l':
                    688:                        sccbits(sp, n);
                    689:                        break;
                    690: 
                    691:                case 'P':
                    692:                case 'p':
                    693:                        sccparity(sp, *(bp->rptr+1));
                    694:                        break;
                    695:                case 'K':
                    696:                case 'k':
                    697:                        sccbreak(sp, n);
                    698:                        break;
                    699:                case 'R':
                    700:                case 'r':
                    701:                        sccrts(sp, n);
                    702:                        break;
                    703:                case 'S':
                    704:                case 's':
                    705:                        sccnstop(sp, *(bp->rptr+1));
                    706:                        break;
                    707:                case 'W':
                    708:                case 'w':
                    709:                        /* obsolete */
                    710:                        break;
                    711:                case 'X':
                    712:                case 'x':
                    713:                        sp->xonoff = n;
                    714:                        break;
                    715:                }
                    716:        }else while((m = BLEN(bp)) > 0){
                    717:                while ((n = canputc(cq)) == 0){
                    718:                        kprint(" sccoput: sleeping\n");
                    719:                        sleep(&cq->r, canputc, cq);
                    720:                }
                    721:                if(n > m)
                    722:                        n = m;
                    723:                (*cq->puts)(cq, bp->rptr, n);
                    724:                bp->rptr += n;
                    725:        }
                    726:        freeb(bp);
                    727:        poperror();
                    728: }
                    729: 
                    730: /*
                    731:  *  process to send bytes upstream for a port
                    732:  */
                    733: static void
                    734: scckproc(void *a)
                    735: {
                    736:        SCC *sp = a;
                    737:        IOQ *cq = sp->iq;
                    738:        Block *bp;
                    739:        int n;
                    740: 
                    741: loop:
                    742:        while ((n = cangetc(cq)) == 0)
                    743:                sleep(&cq->r, cangetc, cq);
                    744:        /*kprint(" scckproc: %d\n", n);*/
                    745:        qlock(sp);
                    746:        if(sp->wq == 0){
                    747:                cq->out = cq->in;
                    748:        }else{
                    749:                bp = allocb(n);
                    750:                bp->flags |= S_DELIM;
                    751:                bp->wptr += gets(cq, bp->wptr, n);
                    752:                PUTNEXT(RD(sp->wq), bp);
                    753:        }
                    754:        qunlock(sp);
                    755:        goto loop;
                    756: }
                    757: 
                    758: Dirtab *sccdir;
                    759: 
                    760: /*
                    761:  *  create 2 directory entries for each 'sccsetup' ports.
                    762:  *  allocate the queues if no one else has.
                    763:  */
                    764: void
                    765: sccreset(void)
                    766: {
                    767:        SCC *sp;
                    768:        int i;
                    769:        Dirtab *dp;
                    770: 
                    771:        sccdir = xalloc(2 * nscc * sizeof(Dirtab));
                    772:        dp = sccdir;
                    773:        for(i = 0; i < nscc; i++){
                    774:                /* 2 directory entries per port */
                    775:                sprint(dp->name, "eia%d", i);
                    776:                dp->qid.path = STREAMQID(i, Sdataqid);
                    777:                dp->perm = 0666;
                    778:                dp++;
                    779:                sprint(dp->name, "eia%dctl", i);
                    780:                dp->qid.path = STREAMQID(i, Sctlqid);
                    781:                dp->perm = 0666;
                    782:                dp++;
                    783: 
                    784:                /* set up queues if a stream port */
                    785:                sp = scc[i];
                    786:                if(sp->special)
                    787:                        continue;
                    788:                sp->iq = xalloc(sizeof(IOQ));
                    789:                initq(sp->iq);
                    790:                sp->oq = xalloc(sizeof(IOQ));
                    791:                initq(sp->oq);
                    792:                sccenable(sp);
                    793:        }
                    794: }
                    795: 
                    796: void
                    797: sccinit(void)
                    798: {
                    799: }
                    800: 
                    801: Chan*
                    802: sccattach(char *spec)
                    803: {
                    804:        return devattach(SCCTYPE, spec);
                    805: }
                    806: 
                    807: Chan*
                    808: sccclone(Chan *c, Chan *nc)
                    809: {
                    810:        return devclone(c, nc);
                    811: }
                    812: 
                    813: int
                    814: sccwalk(Chan *c, char *name)
                    815: {
                    816:        return devwalk(c, name, sccdir, 2*nscc, devgen);
                    817: }
                    818: 
                    819: void
                    820: sccstat(Chan *c, char *dp)
                    821: {
                    822:        int i;
                    823: 
                    824:        i = STREAMID(c->qid.path);
                    825:        switch(STREAMTYPE(c->qid.path)){
                    826:        case Sdataqid:
                    827:                streamstat(c, dp, sccdir[2*i].name, sccdir[2*i].perm);
                    828:                break;
                    829:        default:
                    830:                devstat(c, dp, sccdir, 2*nscc, devgen);
                    831:                break;
                    832:        }
                    833: }
                    834: 
                    835: Chan*
                    836: sccopen(Chan *c, int omode)
                    837: {
                    838:        SCC *sp;
                    839: 
                    840:        if(c->qid.path != CHDIR){
                    841:                sp = scc[STREAMID(c->qid.path)];
                    842:                if(sp->special)
                    843:                        error(Einuse);
                    844:                streamopen(c, &sccinfo);
                    845:        }
                    846:        return devopen(c, omode, sccdir, 2*nscc, devgen);
                    847: }
                    848: 
                    849: void
                    850: scccreate(Chan *c, char *name, int omode, ulong perm)
                    851: {
                    852:        USED(c, name, omode, perm);
                    853:        error(Eperm);
                    854: }
                    855: 
                    856: void
                    857: sccclose(Chan *c)
                    858: {
                    859:        if(c->stream)
                    860:                streamclose(c);
                    861: }
                    862: 
                    863: long
                    864: sccread(Chan *c, void *buf, long n, ulong offset)
                    865: {
                    866:        char b[8];
                    867: 
                    868:        if(c->qid.path == CHDIR)
                    869:                return devdirread(c, buf, n, sccdir, 2*nscc, devgen);
                    870: 
                    871:        switch(STREAMTYPE(c->qid.path)){
                    872:        case Sdataqid:
                    873:                return streamread(c, buf, n);
                    874:        case Sctlqid:
                    875:                sprint(b, "%d", STREAMID(c->qid.path));
                    876:                return readstr(offset, buf, n, b);
                    877:        }
                    878:        error(Egreg);
                    879:        return 0;       /* not reached */
                    880: }
                    881: 
                    882: long
                    883: sccwrite(Chan *c, void *va, long n, ulong offset)
                    884: {
                    885:        USED(offset);
                    886:        return streamwrite(c, va, n, 0);
                    887: }
                    888: 
                    889: void
                    890: sccremove(Chan *c)
                    891: {
                    892:        USED(c);
                    893:        error(Eperm);
                    894: }
                    895: 
                    896: void
                    897: sccwstat(Chan *c, char *dp)
                    898: {
                    899:        USED(c, dp);
                    900:        error(Eperm);
                    901: }

unix.superglobalmegacorp.com

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