Annotation of lucent/sys/src/9/gnot/devincon.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       "../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.