Annotation of lucent/sys/src/9/port/devscc.c, revision 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.