Annotation of lucent/sys/src/9/gnot/devincon.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       "../port/error.h"
                      7: #include       "devtab.h"
                      8: 
                      9: #include       "io.h"
                     10: #include       "ureg.h"
                     11: 
                     12: typedef struct Incon   Incon;
                     13: typedef struct Device  Device;
                     14: 
                     15: #define NOW (MACHP(0)->ticks*MS2HZ)
                     16: 
                     17: #define MICROSECOND USED(NOW)
                     18: 
                     19: #define DPRINT if(0)
                     20: 
                     21: enum {
                     22:        Minstation=     2,      /* lowest station # to poll */
                     23:        Maxstation=     15,     /* highest station # to poll */
                     24:        Nincon=         1,      /* number of incons */
                     25:        Nin=            32,     /* Blocks in the input ring */
                     26:        Bsize=          128,    /* size of an input ring block */
                     27:        Mfifo=          0xff,   /* a mask, must be 2^n-1, must be > Nin */
                     28: 
                     29:        Qstats=         1,      /* qid of the statistics file */
                     30: };
                     31: 
                     32: /*
                     33:  *  incon datakit board
                     34:  */
                     35: struct Device {
                     36:        uchar   cdata;
                     37: #define        cpolln  cdata
                     38:        uchar   u0;
                     39:        uchar   cstatus;
                     40:        uchar   u1;
                     41:        uchar   creset;
                     42:        uchar   u2;
                     43:        uchar   csend;
                     44:        uchar   u3;
                     45:        ushort  data_cntl;      /* data is high byte, cntl is low byte */
                     46:        uchar   status;
                     47: #define cmd    status
                     48:        uchar   u5;
                     49:        uchar   reset;
                     50:        uchar   u6;
                     51:        uchar   send;
                     52:        uchar   u7;
                     53: };
                     54: #define        INCON   ((Device *)0x40700000)
                     55: 
                     56: struct Incon {
                     57:        QLock;
                     58: 
                     59:        QLock   xmit;           /* transmit lock */
                     60:        QLock   reslock;        /* reset lock */
                     61:        Device  *dev;
                     62:        int     station;        /* station number */
                     63:        int     state;          /* chip state */
                     64:        Rendez  r;              /* output process */
                     65:        Rendez  kr;             /* input kernel process */
                     66:        ushort  chan;           /* current input channel */
                     67:        Queue   *rq;            /* read queue */
                     68:        int     kstarted;       /* true if kernel process started */
                     69: 
                     70:        /*  input blocks */
                     71: 
                     72:        Block   *inb[Nin];
                     73:        ushort  wi;             
                     74:        ushort  ri;
                     75: 
                     76:        /* statistics */
                     77: 
                     78:        ulong   overflow;       /* overflow errors */
                     79:        ulong   pack0;          /* channel 0 */
                     80:        ulong   crc;            /* crc errors */
                     81:        ulong   in;             /* bytes in */
                     82:        ulong   out;            /* bytes out */
                     83:        ulong   wait;           /* wait time in milliseconds */
                     84: };
                     85: 
                     86: Incon incon[Nincon];
                     87: 
                     88: /*
                     89:  *  chip state
                     90:  */
                     91: enum {
                     92:        Selecting,
                     93:        Selected,
                     94:        Notliving,
                     95: };
                     96: 
                     97: /*
                     98:  *  internal chip registers
                     99:  */
                    100: #define        sel_polln       0
                    101: #define        sel_station     1
                    102: #define        sel_poll0       2
                    103: #define sel_rcv_cnt    3
                    104: #define sel_rcv_tim    4
                    105: #define sel_tx_cnt     5
                    106: 
                    107: /*
                    108:  *  CSR bits
                    109:  */
                    110: #define INCON_RUN      0x80
                    111: #define INCON_STOP     0x00
                    112: #define ENABLE_IRQ     0x40
                    113: #define ENABLE_TX_IRQ  0x20
                    114: #define INCON_ALIVE    0x80
                    115: #define TX_FULL                0x10
                    116: #define TX_EMPTY       0x08
                    117: #define RCV_EMPTY      0x04
                    118: #define OVERFLOW       0x02
                    119: #define CRC_ERROR      0x01
                    120: 
                    121: /*
                    122:  *  polling constants
                    123:  */
                    124: #define HT_GNOT        0x30
                    125: #define ST_UNIX 0x04
                    126: #define NCHAN 16
                    127: 
                    128: static void inconkproc(void*);
                    129: 
                    130: /*
                    131:  *  incon stream module definition
                    132:  */
                    133: static void inconoput(Queue*, Block*);
                    134: static void inconstopen(Queue*, Stream*);
                    135: static void inconstclose(Queue*);
                    136: Qinfo inconinfo =
                    137: {
                    138:        nullput,
                    139:        inconoput,
                    140:        inconstopen,
                    141:        inconstclose,
                    142:        "incon"
                    143: };
                    144: 
                    145: int incondebug;
                    146: 
                    147: Dirtab incondir[]={
                    148:        "stats",                {Qstats},       0,              0444,
                    149: };
                    150: 
                    151: /*
                    152:  *  set the incon parameters
                    153:  */
                    154: void
                    155: inconset(Incon *ip, int cnt, int del)
                    156: {
                    157:        Device *dev;
                    158: 
                    159:        if (cnt<1 || cnt>14 || del<1 || del>15)
                    160:                error(Ebadarg);
                    161: 
                    162:        dev = ip->dev;
                    163:        dev->cmd = sel_rcv_cnt | INCON_RUN;
                    164:        MICROSECOND;
                    165:        *(uchar *)&dev->data_cntl = cnt;
                    166:        MICROSECOND;
                    167:        dev->cmd = sel_rcv_tim | INCON_RUN;
                    168:        MICROSECOND;
                    169:        *(uchar *)&dev->data_cntl = del;
                    170:        MICROSECOND;
                    171:        dev->cmd = INCON_RUN | ENABLE_IRQ;
                    172: }
                    173: 
                    174: /*
                    175:  *  parse a set request
                    176:  */
                    177: void
                    178: inconsetctl(Incon *ip, Block *bp)
                    179: {
                    180:        char *field[3];
                    181:        int n;
                    182:        int del;
                    183:        int cnt;
                    184: 
                    185:        del = 15;
                    186:        n = getfields((char *)bp->rptr, field, 3, " ");
                    187:        switch(n){
                    188:        default:
                    189:                freeb(bp);
                    190:                error(Ebadarg);
                    191:        case 2:
                    192:                del = strtol(field[1], 0, 0);
                    193:                if(del<0 || del>15){
                    194:                        freeb(bp);
                    195:                        error(Ebadarg);
                    196:                }
                    197:                /* fall through */
                    198:        case 1:
                    199:                cnt = strtol(field[0], 0, 0);
                    200:                if(cnt<0 || cnt>15){
                    201:                        freeb(bp);
                    202:                        error(Ebadarg);
                    203:                }
                    204:        }
                    205:        inconset(ip, cnt, del);
                    206:        freeb(bp);
                    207: }
                    208: 
                    209: static void
                    210: nop(void)
                    211: {
                    212: }
                    213: 
                    214: /*
                    215:  *  poll for a station number
                    216:  */
                    217: void 
                    218: inconpoll(Incon *ip, int station)
                    219: {
                    220:        ulong timer;
                    221:        Device *dev;
                    222: 
                    223:        dev = ip->dev;
                    224: 
                    225:        /*
                    226:         *  get us to a known state
                    227:         */
                    228:        ip->state = Notliving;
                    229:        dev->cmd = INCON_STOP;
                    230: 
                    231:        /*
                    232:         * try a station number
                    233:         */
                    234:        dev->cmd = sel_station;
                    235:        *(uchar *)&dev->data_cntl = station;
                    236:        dev->cmd = sel_poll0;
                    237:        *(uchar *)&dev->data_cntl = HT_GNOT;
                    238:        dev->cmd = sel_rcv_cnt;
                    239:        *(uchar *)&dev->data_cntl = 3;
                    240:        dev->cmd = sel_rcv_tim;
                    241:        *(uchar *)&dev->data_cntl = 15;
                    242:        dev->cmd = sel_tx_cnt;
                    243:        *(uchar *)&dev->data_cntl = 1;
                    244:        dev->cmd = sel_polln;
                    245:        *(uchar *)&dev->data_cntl = 0x00;
                    246:        *(uchar *)&dev->data_cntl = ST_UNIX;
                    247:        *(uchar *)&dev->data_cntl = NCHAN;
                    248:        *(uchar *)&dev->data_cntl = 'g';
                    249:        *(uchar *)&dev->data_cntl = 'n';
                    250:        *(uchar *)&dev->data_cntl = 'o';
                    251:        *(uchar *)&dev->data_cntl = 't';
                    252:        dev->cpolln = 0;
                    253: 
                    254:        /*
                    255:         *  poll and wait for ready (or 1/4 second)
                    256:         */
                    257:        ip->state = Selecting;
                    258:        dev->cmd = INCON_RUN | ENABLE_IRQ;
                    259:        timer = NOW + 250;
                    260:        while (NOW < timer) {
                    261:                nop();
                    262:                if(dev->status & INCON_ALIVE){
                    263:                        ip->station = station;
                    264:                        ip->state = Selected;
                    265:                        break;
                    266:                }
                    267:        }
                    268: }
                    269: 
                    270: /*
                    271:  *  reset the chip and find a new staion number
                    272:  */
                    273: void
                    274: inconrestart(Incon *ip)
                    275: {
                    276:        int i;
                    277: 
                    278:        if(!canqlock(&ip->reslock))
                    279:                return;
                    280: 
                    281:        /*
                    282:         *  poll for incon station numbers
                    283:         */
                    284:        for(i = Minstation; i <= Maxstation; i++){
                    285:                inconpoll(ip, i);
                    286:                if(ip->state == Selected)
                    287:                        break;
                    288:        }
                    289:        switch(ip->state) {
                    290:        case Selecting:
                    291:                print("incon[%d] not polled\n", ip-incon);
                    292:                break;
                    293:        case Selected:
                    294:                print("incon[%d] station %d\n", ip-incon, ip->station);
                    295:                inconset(ip, 3, 15);
                    296:                break;
                    297:        default:
                    298:                print("incon[%d] bollixed\n", ip-incon);
                    299:                break;
                    300:        }
                    301:        qunlock(&ip->reslock);
                    302: }
                    303: 
                    304: /*
                    305:  *  reset all incon chips.
                    306:  */
                    307: void
                    308: inconreset(void)
                    309: {
                    310:        int i;
                    311: 
                    312:        incon[0].dev = INCON;
                    313:        incon[0].state = Selected;
                    314:        incon[0].ri = incon[0].wi = 0;
                    315: /*     inconset(&incon[0], 3, 15); /**/
                    316:        for(i=1; i<Nincon; i++){
                    317:                incon[i].dev = INCON+i;
                    318:                incon[i].state = Notliving;
                    319:                incon[i].dev->cmd = INCON_STOP;
                    320:                incon[i].ri = incon[i].wi = 0;
                    321:        }
                    322: }
                    323: 
                    324: void
                    325: inconinit(void)
                    326: {
                    327: }
                    328: 
                    329: /*
                    330:  *  enable the device for interrupts, spec is the device number
                    331:  */
                    332: Chan*
                    333: inconattach(char *spec)
                    334: {
                    335:        Incon *ip;
                    336:        int i;
                    337:        Chan *c;
                    338: 
                    339:        i = strtoul(spec, 0, 0);
                    340:        if(i >= Nincon)
                    341:                error(Ebadarg);
                    342:        ip = &incon[i];
                    343:        if(ip->state != Selected)
                    344:                inconrestart(ip);
                    345: 
                    346:        c = devattach('i', spec);
                    347:        c->dev = i;
                    348:        c->qid.path = CHDIR;
                    349:        c->qid.vers = 0;
                    350:        return c;
                    351: }
                    352: 
                    353: Chan*
                    354: inconclone(Chan *c, Chan *nc)
                    355: {
                    356:        return devclone(c, nc);
                    357: }
                    358: 
                    359: int     
                    360: inconwalk(Chan *c, char *name)
                    361: {
                    362:        return devwalk(c, name, incondir, 1, streamgen);
                    363: }
                    364: 
                    365: void    
                    366: inconstat(Chan *c, char *dp)
                    367: {
                    368:        devstat(c, dp, incondir, 1, streamgen);
                    369: }
                    370: 
                    371: Chan*
                    372: inconopen(Chan *c, int omode)
                    373: {
                    374:        if(c->qid.path == CHDIR || c->qid.path == Qstats){
                    375:                if(omode != OREAD)
                    376:                        error(Eperm);
                    377:        }else
                    378:                streamopen(c, &inconinfo);
                    379:        c->mode = openmode(omode);
                    380:        c->flag |= COPEN;
                    381:        c->offset = 0;
                    382:        return c;
                    383: }
                    384: 
                    385: void    
                    386: inconcreate(Chan *c, char *name, int omode, ulong perm)
                    387: {
                    388:        USED(c, name, omode, perm);
                    389:        error(Eperm);
                    390: }
                    391: 
                    392: void    
                    393: inconclose(Chan *c)
                    394: {
                    395:        if(c->qid.path != CHDIR)
                    396:                streamclose(c);
                    397: }
                    398: 
                    399: long    
                    400: inconread(Chan *c, void *buf, long n, ulong offset)
                    401: {
                    402:        char b[256];
                    403:        Incon *i;
                    404: 
                    405:        if(c->qid.path == CHDIR)
                    406:                return devdirread(c, buf, n, incondir, 1, streamgen);
                    407:        else if(c->qid.path == Qstats){
                    408:                i = &incon[c->dev];
                    409:                sprint(b, "in: %d\nout: %d\noverflow: %d\ncrc: %d\nwait: %d\n", i->in,
                    410:                        i->out, i->overflow, i->crc, i->wait);
                    411:                return readstr(offset, buf, n, b);
                    412:        } else
                    413:                return streamread(c, buf, n);
                    414: }
                    415: 
                    416: long    
                    417: inconwrite(Chan *c, void *buf, long n, ulong offset)
                    418: {
                    419:        USED(offset);
                    420:        return streamwrite(c, buf, n, 0);
                    421: }
                    422: 
                    423: void    
                    424: inconremove(Chan *c)
                    425: {
                    426:        USED(c);
                    427:        error(Eperm);
                    428: }
                    429: 
                    430: void    
                    431: inconwstat(Chan *c, char *dp)
                    432: {
                    433:        USED(c, dp);
                    434:        error(Eperm);
                    435: }
                    436: 
                    437: /*
                    438:  *     the stream routines
                    439:  */
                    440: 
                    441: /*
                    442:  * for sleeping while kproc dies
                    443:  */
                    444: static int
                    445: kNotliving(void *arg)
                    446: {
                    447:        Incon *ip;
                    448: 
                    449:        ip = (Incon *)arg;
                    450:        return ip->kstarted == 0;
                    451: }
                    452: 
                    453: /*
                    454:  *  create the kernel process for input
                    455:  *  first wait for any old ones to die
                    456:  */
                    457: static void
                    458: inconstopen(Queue *q, Stream *s)
                    459: {
                    460:        Incon *ip;
                    461:        char name[32];
                    462: 
                    463:        ip = &incon[s->dev];
                    464:        sprint(name, "incon%d", s->dev);
                    465:        q->ptr = q->other->ptr = ip;
                    466:        wakeup(&ip->kr);
                    467:        sleep(&ip->r, kNotliving, ip);
                    468:        ip->rq = q;
                    469:        kproc(name, inconkproc, ip);
                    470: }
                    471: 
                    472: /*
                    473:  *  kill off the kernel process
                    474:  */
                    475: static void
                    476: inconstclose(Queue * q)
                    477: {
                    478:        Incon *ip;
                    479: 
                    480:        ip = (Incon *)q->ptr;
                    481:        qlock(ip);
                    482:        ip->rq = 0;
                    483:        qunlock(ip);
                    484:        wakeup(&ip->kr);
                    485:        sleep(&ip->r, kNotliving, ip);
                    486: }
                    487: 
                    488: /*
                    489:  *  free all blocks of a message in `q', `bp' is the first block
                    490:  *  of the message
                    491:  */
                    492: static void
                    493: freemsg(Queue *q, Block *bp)
                    494: {
                    495:        for(; bp; bp = getq(q)){
                    496:                if(bp->flags & S_DELIM){
                    497:                        freeb(bp);
                    498:                        return;
                    499:                }
                    500:                freeb(bp);
                    501:        }
                    502: }
                    503: 
                    504: /*
                    505:  *  output a block
                    506:  *
                    507:  *  the first 2 bytes of every message are the channel number,
                    508:  *  low order byte first.  the third is a possible trailing control
                    509:  *  character.
                    510:  */
                    511: void
                    512: inconoput(Queue *q, Block *bp)
                    513: {
                    514:        Device *dev;
                    515:        Incon *ip;
                    516:        ulong start, end;
                    517:        int chan;
                    518:        int ctl;
                    519:        int n, size;
                    520: 
                    521:        ip = (Incon *)q->ptr;
                    522: 
                    523:        if(bp->type != M_DATA){
                    524:                if(streamparse("inconset", bp))
                    525:                        inconsetctl(ip, bp);
                    526:                else
                    527:                        freeb(bp);
                    528:                return;
                    529:        }
                    530:        if(BLEN(bp) < 3){
                    531:                bp = pullup(bp, 3);
                    532:                if(bp == 0){
                    533:                        print("inconoput pullup failed\n");
                    534:                        return;
                    535:                }
                    536:        }
                    537: 
                    538:        /*
                    539:         *  get a whole message before handing bytes to the device
                    540:         */
                    541:        if(!putq(q, bp))
                    542:                return;
                    543: 
                    544:        /*
                    545:         *  one transmitter at a time
                    546:         */
                    547:        qlock(&ip->xmit);
                    548:        dev = ip->dev;
                    549: 
                    550:        /*
                    551:         *  parse message
                    552:         */
                    553:        bp = getq(q);
                    554:        chan = bp->rptr[0] | (bp->rptr[1]<<8);
                    555:        ctl = bp->rptr[2];
                    556:        bp->rptr += 3;
                    557:        if(chan<=0)
                    558:                print("bad channel %d\n", chan);
                    559: 
                    560:        if(incondebug)
                    561:                print("->(%d)%uo %d\n", chan, ctl, bp->wptr - bp->rptr);
                    562: 
                    563:        /*
                    564:         *  make sure there's an incon out there
                    565:         */
                    566:        if(!(dev->status&INCON_ALIVE) || ip->state==Notliving){
                    567:                inconrestart(ip);
                    568:                freemsg(q, bp);
                    569:                qunlock(&ip->xmit);
                    570:                return;
                    571:        }
                    572: 
                    573:        /*
                    574:         *  send the 8 bit data
                    575:         */
                    576:        for(;;){
                    577:                /*
                    578:                 *  spin till there is room
                    579:                 */
                    580:                start = NOW;
                    581:                for(n = 0, end = start+1000; dev->status & TX_FULL; n++){
                    582:                        nop();  /* make sure we don't optimize too much */
                    583:                        if(NOW > end){
                    584:                                print("incon output stuck\n");
                    585:                                freemsg(q, bp);
                    586:                                qunlock(&ip->xmit);
                    587:                                return;
                    588:                        }
                    589:                }
                    590:                ip->wait = (n + ip->wait)>>1;
                    591: 
                    592:                /*
                    593:                 *  put in next packet
                    594:                 */
                    595:                n = bp->wptr - bp->rptr;
                    596:                if(n > 16)
                    597:                        n = 16;
                    598:                size = n;
                    599:                dev->cdata = chan;
                    600:                ip->out += n;
                    601:                while(n--){
                    602:                        *(uchar *)&dev->data_cntl = *bp->rptr++;
                    603:                }
                    604: 
                    605:                /*
                    606:                 *  get next block 
                    607:                 */
                    608:                if(bp->rptr >= bp->wptr){
                    609:                        if(bp->flags & S_DELIM){
                    610:                                freeb(bp);
                    611:                                break;
                    612:                        }
                    613:                        freeb(bp);
                    614:                        bp = getq(q);
                    615:                        if(bp==0)
                    616:                                break;
                    617:                }
                    618: 
                    619:                /*
                    620:                 *  end packet
                    621:                 */
                    622:                dev->cdata = 0;
                    623:        }
                    624: 
                    625:        /*
                    626:         *  send the control byte if there is one
                    627:         */
                    628:        if(ctl){
                    629:                if(size >= 16){
                    630:                        dev->cdata = 0;
                    631:                        MICROSECOND;
                    632:                        for(end = NOW+1000; dev->status & TX_FULL;){
                    633:                                nop();  /* make sure we don't optimize too much */
                    634:                                if(NOW > end){
                    635:                                        print("incon output stuck\n");
                    636:                                        freemsg(q, bp);
                    637:                                        qunlock(&ip->xmit);
                    638:                                        return;
                    639:                                }
                    640:                        }
                    641:                        dev->cdata = chan;
                    642:                        MICROSECOND;
                    643:                }
                    644:                if(dev->status & TX_FULL)
                    645:                        print("inconfull\n");
                    646:                dev->cdata = ctl;
                    647:        }
                    648:        MICROSECOND;
                    649:        dev->cdata = 0;
                    650: 
                    651:        qunlock(&ip->xmit);
                    652:        return;
                    653: }
                    654: 
                    655: /*
                    656:  *  return true if the raw fifo is non-empty
                    657:  */
                    658: static int
                    659: notempty(void *arg)
                    660: {
                    661:        Incon *ip;
                    662: 
                    663:        ip = (Incon *)arg;
                    664:        return ip->ri!=ip->wi;
                    665: }
                    666: 
                    667: /*
                    668:  *  Read bytes from the raw input circular buffer.
                    669:  */
                    670: static void
                    671: inconkproc(void *arg)
                    672: {
                    673:        Incon *ip;
                    674:        Block *bp;
                    675:        int i;
                    676:        int locked;
                    677: 
                    678:        ip = (Incon *)arg;
                    679:        ip->kstarted = 1;
                    680: 
                    681:        /*
                    682:         *  create a number of blocks for input
                    683:         */
                    684:        for(i = 0; i < Nin; i++){
                    685:                bp = ip->inb[i] = allocb(Bsize);
                    686:                bp->wptr += 3;
                    687:        }
                    688: 
                    689:        locked = 0;
                    690:        if(waserror()){
                    691:                if(locked)
                    692:                        qunlock(ip);
                    693:                ip->kstarted = 0;
                    694:                wakeup(&ip->r);
                    695:                return;
                    696:        }
                    697: 
                    698:        for(;;){
                    699:                /*
                    700:                 *  sleep if input fifo empty
                    701:                 */
                    702:                sleep(&ip->kr, notempty, ip);
                    703: 
                    704:                /*
                    705:                 *  die if the device is closed
                    706:                 */
                    707:                USED(locked);
                    708:                qlock(ip);
                    709:                locked = 1;
                    710:                if(ip->rq == 0){
                    711:                        qunlock(ip);
                    712:                        ip->kstarted = 0;
                    713:                        wakeup(&ip->r);
                    714:                        poperror();
                    715:                        return;
                    716:                }
                    717: 
                    718:                /*
                    719:                 *  send blocks upstream and stage new blocks.  if the block is small
                    720:                 *  (< 64 bytes) copy into a smaller buffer.
                    721:                 */
                    722:                while(ip->ri != ip->wi){
                    723:                        bp = ip->inb[ip->ri];
                    724:                        ip->in += BLEN(bp);
                    725:                        PUTNEXT(ip->rq, bp);
                    726:                        bp = ip->inb[ip->ri] = allocb(Bsize);
                    727:                        bp->wptr += 3;
                    728:                        ip->ri = (ip->ri+1)%Nin;
                    729:                }
                    730:                USED(locked);
                    731:                qunlock(ip);
                    732:                locked = 0;
                    733:        }
                    734: }
                    735: 
                    736: /*
                    737:  *  drop a single packet
                    738:  */
                    739: static void
                    740: droppacket(Device *dev)
                    741: {
                    742:        int i;
                    743:        int c;
                    744: 
                    745:        for(i = 0; i < 17; i++){
                    746:                c = dev->data_cntl;
                    747:                if(c==0)
                    748:                        break;
                    749:        }
                    750: }
                    751: 
                    752: /*
                    753:  *  flush the input fifo
                    754:  */
                    755: static void
                    756: flushfifo(Device *dev)
                    757: {
                    758:        while(!(dev->status & RCV_EMPTY))
                    759:                droppacket(dev);
                    760: }
                    761: 
                    762: /*
                    763:  *  advance the queue. if we've run out of staged input blocks,
                    764:  *  drop the packet and return 0.  otherwise return the next input
                    765:  *  block to fill.
                    766:  */
                    767: static Block *
                    768: nextin(Incon *ip, unsigned int c)
                    769: {
                    770:        Block *bp;
                    771:        int next;
                    772: 
                    773:        bp = ip->inb[ip->wi];
                    774:        bp->rptr[0] = ip->chan;
                    775:        bp->rptr[1] = ip->chan>>8;
                    776:        bp->rptr[2] = c;
                    777:        if(incondebug)
                    778:                print("<-(%d)%uo %d\n", ip->chan, c, bp->wptr-bp->rptr);
                    779: 
                    780:        next = (ip->wi+1)%Nin;
                    781:        if(next == ip->ri){
                    782:                bp->wptr = bp->rptr+3;
                    783:                return bp;
                    784:        }
                    785:        ip->wi = next;
                    786: 
                    787:        return ip->inb[ip->wi];
                    788: }
                    789: 
                    790: /*
                    791:  *  read the packets from the device into the staged input blocks.
                    792:  *  we have to do this at interrupt tevel to turn off the interrupts.
                    793:  */
                    794: static void
                    795: rdpackets(Incon *ip)
                    796: {
                    797:        Block *bp;
                    798:        unsigned int c;
                    799:        Device *dev;
                    800:        uchar *p;
                    801:        int first = ip->wi;
                    802: 
                    803:        dev = ip->dev;
                    804:        bp = ip->inb[ip->wi];
                    805:        if(bp==0){
                    806:                flushfifo(ip->dev);
                    807:                return;
                    808:        }
                    809:        p = bp->wptr;
                    810:        while(!(dev->status & RCV_EMPTY)){
                    811:                /*
                    812:                 *  get channel number
                    813:                 */
                    814:                c = (dev->data_cntl)>>8;
                    815:                if(c == 0){
                    816:                        droppacket(dev);
                    817:                        continue;
                    818:                }
                    819:                if(ip->chan != c){
                    820:                        if(p - bp->rptr > 3){
                    821:                                bp->wptr = p;
                    822:                                bp = nextin(ip, 0);
                    823:                                if(bp==0){
                    824:                                        flushfifo(ip->dev);
                    825:                                        return;
                    826:                                }
                    827:                                p = bp->wptr;
                    828:                        }
                    829:                        ip->chan = c;
                    830:                }
                    831: 
                    832:                /*
                    833:                 *  null byte marks end of packet
                    834:                 */
                    835:                for(;;){
                    836:                        if((c=dev->data_cntl)&1) {
                    837:                                /*
                    838:                                 *  data byte, put in local buffer
                    839:                                 */
                    840:                                *p++ = c>>8;
                    841:                        } else if (c>>=8) {
                    842:                                /*
                    843:                                 *  control byte ends block
                    844:                                 */
                    845:                                bp->wptr = p;
                    846:                                bp = nextin(ip, c);
                    847:                                if(bp==0){
                    848:                                        flushfifo(ip->dev);
                    849:                                        return;
                    850:                                }
                    851:                                p = bp->wptr;
                    852:                        } else {
                    853:                                /* end of packet */
                    854:                                break;
                    855:                        }
                    856:                }
                    857: 
                    858:                /*
                    859:                 *  pass a block on if it doesn't have room for one more
                    860:                 *  packet.  this way we don't have to check per byte.
                    861:                 */
                    862:                if(p + 16 > bp->lim){
                    863:                        bp->wptr = p;
                    864:                        bp = nextin(ip, 0);
                    865:                        p = bp->wptr;
                    866:                }
                    867:        }       
                    868:        bp->wptr = p;
                    869:        if(bp->wptr != bp->rptr+3)
                    870:                nextin(ip, 0);
                    871: 
                    872:        if(first != ip->wi)/**/
                    873:                wakeup(&ip->kr);
                    874: }
                    875: 
                    876: /*
                    877:  *  Receive an incon interrupt.  One entry point
                    878:  *  for all types of interrupt.  Until we figure out
                    879:  *  how to use more than one incon, this routine only
                    880:  *  is for incon[0].
                    881:  */
                    882: void
                    883: inconintr(Ureg *ur)
                    884: {
                    885:        uchar status;
                    886:        Incon *ip;
                    887: 
                    888:        USED(ur);
                    889:        ip = &incon[0];
                    890: 
                    891:        status = ip->dev->status;
                    892:        if(!(status & RCV_EMPTY))
                    893:                rdpackets(ip);
                    894: 
                    895:        /* check for exceptional conditions */
                    896:        if(status&(OVERFLOW|CRC_ERROR)){
                    897:                if(status&OVERFLOW)
                    898:                        ip->overflow++;
                    899:                if(status&CRC_ERROR)
                    900:                        ip->crc++;
                    901:        }
                    902: 
                    903:        /* see if it died underneath us */
                    904:        if(!(status&INCON_ALIVE)){
                    905:                switch(ip->state){
                    906:                case Selected:
                    907:                        ip->dev->cmd = INCON_STOP;
                    908:                        print("Incon died\n");
                    909:                        break;
                    910:                case Selecting:
                    911:                        print("rejected\n");
                    912:                        break;
                    913:                default:
                    914:                        ip->dev->cmd = INCON_STOP;
                    915:                        break;
                    916:                }
                    917:                ip->state = Notliving;
                    918:        }
                    919: }
                    920: 
                    921: void
                    922: incontoggle(void)
                    923: {
                    924:        incondebug ^= 1;
                    925: }

unix.superglobalmegacorp.com

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