Annotation of researchv8dc/sys/dev/ill.c, revision 1.1.1.1

1.1       root        1: 
                      2: /*
                      3:  * Interlan Ethernet Communications Controller interface.
                      4:  * Provides fairly raw access to a number of Interlan controllers.
                      5:  * Minor device N talks to unit N / 8. Each written record should
                      6:  * be an interlan output packet - 6 bytes addr, 2 bytes type, data.
                      7:  * An ethernet packet type may be associated with a minor device with
                      8:  * the ENIOTYPE ioctl; input packets of that type will be sent to
                      9:  * the minor device in question. Input packets include 6 bytes src addr,
                     10:  * 6 bytes dest, 2 bytes type, and data.
                     11:  *
                     12:  * The physical address of a controller may be fetched with the ENIOADDR
                     13:  * ioctl on a minor device associated with that unit.
                     14:  */
                     15: #include "il.h"
                     16: #if NIL > 0
                     17: 
                     18: #include "../h/param.h"
                     19: #include "../h/systm.h"
                     20: #include "../h/stream.h"
                     21: #include "../h/map.h"
                     22: #include "../h/buf.h"
                     23: #include "../h/ubavar.h"
                     24: #include "../h/conf.h"
                     25: #include "../h/ioctl.h"
                     26: #include "../h/ttyld.h"
                     27: #include "../h/ill_reg.h"
                     28: #include "../h/ethernet.h"
                     29: 
                     30: int    ilprobe(), ilattach(), ilrint(), ilcint();
                     31: struct uba_device *ilinfo[NIL];
                     32: u_short        ilstd[] = { 0 };
                     33: struct uba_driver ildriver =
                     34:        { ilprobe, 0, ilattach, 0, ilstd, "il", ilinfo };
                     35: 
                     36: #define ILOUTSTANDING  1       /* max # of rcv bufs in controller q */
                     37: #define BOGUS          1       /* CDONE doesn't work */
                     38: 
                     39: struct il {    /* per controller */
                     40:        int attached;
                     41:        int active;
                     42:        int rcvpending;
                     43:        int ipackets, opackets;
                     44:        int ierrors, oerrors;
                     45:        int collisions;
                     46:        struct block *bp;       /* waiting to be filled */
                     47:        struct block *nbp;      /* next block to be filled in this packet */
                     48:        int len;                /* amount left in this packet */
                     49:        struct queue *tq;       /* current transmit q */
                     50:        struct block *freebp;
                     51:        unsigned char addr[6];
                     52: } il[NIL];
                     53: 
                     54: extern u_char blkdata[];       /* stream.c */
                     55: extern long blkubad;
                     56: int ilprintfs = 0;
                     57: 
                     58: struct il_stats ilstats;
                     59: 
                     60: #define CHANS_PER_UNIT 8
                     61: #define NILCHAN                (CHANS_PER_UNIT * NIL)
                     62: struct ilchan{ /* per stream */
                     63:        int unit;
                     64:        int packets;    /* # of packets on q to output */
                     65:        struct queue *rq;
                     66:        int type;       /* ethernet protocol # */
                     67:        int haveheader; /* ethernet header has gone by */
                     68: } ilchan[NILCHAN];
                     69: 
                     70: ilprobe(reg)
                     71: caddr_t reg;
                     72: {
                     73:        register int br, cvec;  /* r11, r10 */
                     74:        register struct ildevice *addr = (struct ildevice *) reg;
                     75:        register i;
                     76: 
                     77: #ifdef lint
                     78:        br = 0; cvec = br; br = cvec; i = br; br = i;
                     79: #endif
                     80: 
                     81:        addr->il_csr = ILC_OFFLINE|IL_CIE;
                     82:        DELAY(100000);
                     83:        i = addr->il_csr;       /* clear CDONE */
                     84:        if(cvec > 0 && cvec != 0x200)
                     85:                cvec -= 4;
                     86:        return(1);
                     87: }
                     88: 
                     89: ilattach(ui)
                     90: struct uba_device *ui;
                     91: {
                     92:        register struct il *is = &il[ui->ui_unit];
                     93:        register struct ildevice *addr = (struct ildevice *)ui->ui_addr;
                     94:        int ubaddr, s;
                     95: 
                     96: 
                     97:        s = spl6();
                     98: 
                     99:        addr->il_csr = ILC_RESET;
                    100:        while((addr->il_csr&IL_CDONE) == 0)
                    101:                ;
                    102:        if(addr->il_csr&IL_STATUS)
                    103:                printf("il%d: reset failed, csr=%b\n", ui->ui_unit,
                    104:                        addr->il_csr, IL_BITS);
                    105:        
                    106:        ubaddr = uballoc(ui->ui_ubanum, (caddr_t)&ilstats,
                    107:                         sizeof(ilstats), 0);
                    108:        if(ubaddr == 0){
                    109:                printf(" no uballoc\n");
                    110:                goto nostats;
                    111:        }
                    112:        addr->il_bar = ubaddr&0xffff;
                    113:        addr->il_bcr = sizeof(ilstats);
                    114:        addr->il_csr = ((ubaddr >> 2) & IL_EUA) | ILC_STAT;
                    115:        while((addr->il_csr&IL_CDONE) == 0)
                    116:                ;
                    117: 
                    118:        ubarelse(ui->ui_ubanum, &ubaddr);
                    119:        bcopy(ilstats.ils_addr, is->addr, sizeof(is->addr));
                    120: 
                    121: nostats:
                    122:        addr->il_csr = ILC_ONLINE;
                    123:        while((addr->il_csr&IL_CDONE) == 0)
                    124:                ;
                    125:        /*
                    126:         * ask ilcint to set up the first rcv buffer,
                    127:         * since the block stuff doesn't seem to be
                    128:         * initialized yet.
                    129:         */
                    130:        is->rcvpending = ETHERMTU;
                    131: 
                    132:        is->active = 0;
                    133:        is->attached = 1;
                    134:        splx(s);
                    135: }
                    136: 
                    137: ilstart(unit)
                    138: {
                    139:        int ubaddr, count;
                    140:        struct uba_device *ui = ilinfo[unit];
                    141:        register struct il *is = &il[unit];
                    142:        register struct ildevice *addr;
                    143:        struct ilchan *icp;
                    144:        struct block *bp;
                    145:        register struct queue *q;
                    146: 
                    147:        if(is->active){
                    148:                printf(" start but active\n", unit);
                    149:                is->active = 0;
                    150:        }
                    151: 
                    152:        for(icp = ilchan; icp < &ilchan[NILCHAN]; icp++)
                    153:                if(icp->rq && icp->unit == unit && icp->packets > 0)
                    154:                        break;
                    155:        if(icp >= &ilchan[NILCHAN])
                    156:                return;
                    157:        q = WR(icp->rq);
                    158: 
                    159:        is->active = 1;
                    160:        addr = (struct ildevice *)ui->ui_addr;
                    161: #ifdef BOGUS
                    162:        is->tq = q;
                    163:        bp = getq(q);
                    164:        if(bp == 0){
                    165:                printf("ilstart no bp\n");
                    166:                is->active = 0;
                    167:                return;
                    168:        }
                    169:        ildebug(bp, 1);
                    170:        ubaddr = iladdr((caddr_t)(bp->rptr));
                    171:        addr->il_bar = ubaddr&0xffff;
                    172:        addr->il_bcr = bp->wptr - bp->rptr;
                    173:        addr->il_csr = ((ubaddr>>2)&IL_EUA)|ILC_LDXMIT|IL_RIE|IL_CIE;
                    174:        is->freebp = bp;
                    175:        /*
                    176:         * I would have given the entire packet to the controller,
                    177:         * but it's brain-damaged. So I wait for the interrupt to
                    178:         * put the next one on.
                    179:         */
                    180: #else
                    181:        while(bp = getq(q)){
                    182:                if(bp->type != M_DATA){
                    183:                        /* don't free, it's re-used */
                    184:                        break;
                    185:                }
                    186:                ubaddr = iladdr((caddr_t)bp->rptr);
                    187:                addr->il_bar = ubaddr&0xffff;
                    188:                addr->il_bcr = bp->wptr - bp->rptr;
                    189:                addr->il_csr = ((ubaddr>>2)&IL_EUA)|ILC_LDXMIT|IL_RIE;
                    190:                ilcdone(addr, "LDX");
                    191:                freeb(bp);
                    192:        }
                    193:        if(bp == 0){
                    194:                printf("ilstart no delim?\n");
                    195:                bp = allocb(1);
                    196:        }
                    197:        bp->wptr = bp->rptr;
                    198:        --(icp->packets);
                    199:        ubaddr = iladdr((caddr_t)bp->base);
                    200:        addr->il_bar = ubaddr&0xffff;
                    201:        addr->il_bcr = 0;
                    202:        addr->il_csr = ((ubaddr>>2)&IL_EUA)|ILC_XMIT|IL_CIE|IL_RIE;
                    203:        /* go, baby */
                    204:        is->opackets++;
                    205:        freeb(bp);
                    206: #endif BOGUS
                    207: }
                    208: 
                    209: /*
                    210:  * transmit done
                    211:  */
                    212: ilcint(unit)
                    213: {
                    214:        int ubaddr;
                    215:        register struct il *is = &il[unit];
                    216:        struct uba_device *ui = ilinfo[unit];
                    217:        register struct ildevice *addr = (struct ildevice *)ui->ui_addr;
                    218:        short csr;
                    219:        register struct block *bp;
                    220: 
                    221:        if(is->active == 0){
                    222:                printf("il%d: stray xmit interrupt, csr=%b\n", unit,
                    223:                        addr->il_csr, IL_BITS);
                    224:                return;
                    225:        }
                    226: #ifdef BOGUS
                    227:        if(is->tq){
                    228:                if(is->freebp)
                    229:                        freeb(is->freebp);
                    230:                is->freebp = 0;
                    231:                if((bp = getq(is->tq)) == 0){
                    232:                        printf("gak\n");
                    233:                        is->active = 0;
                    234:                        is->tq = 0;
                    235:                        return;
                    236:                }
                    237:                ubaddr = iladdr((caddr_t)(bp->rptr));
                    238:                addr->il_bar = ubaddr&0xffff;
                    239:                addr->il_bcr = bp->wptr - bp->rptr;
                    240:                if(bp->type == M_DELIM){
                    241:                        addr->il_csr = ((ubaddr>>2)&IL_EUA)|ILC_XMIT|IL_RIE|IL_CIE;
                    242:                        ((struct ilchan *)(is->tq->ptr))->packets -= 1;
                    243:                        is->tq = 0;
                    244:                        freeb(bp);
                    245:                } else {
                    246:                        addr->il_csr = ((ubaddr>>2)&IL_EUA)|ILC_LDXMIT|IL_RIE|IL_CIE;
                    247:                        is->freebp = bp;
                    248:                }
                    249:                return;
                    250:        }
                    251: #endif BOGUS
                    252:        csr = addr->il_csr;
                    253:        is->active = 0;
                    254:        if(is->rcvpending)
                    255:                ilsetup(is, addr, is->rcvpending);
                    256: 
                    257:        /* check status of last xmit */
                    258:        csr &= IL_STATUS;
                    259:        if(csr > ILERR_RETRIES){
                    260:                printf("il%d: tx error 0x%x\n", unit, csr);
                    261:                is->oerrors++;
                    262:        } else if(csr > ILERR_SUCCESS){
                    263:                is->collisions++;
                    264:        }
                    265: #ifdef BOGUS
                    266:        else is->opackets++;
                    267: #endif
                    268:        ilstart(unit);
                    269: }
                    270: 
                    271: ilrint(unit)
                    272: {
                    273:        register struct il *is = &il[unit];
                    274:        register struct ildevice *addr = (struct ildevice *)ilinfo[unit]->ui_addr;
                    275:        register struct il_rheader *hp;
                    276:        int len;
                    277:        struct block *bp, *bp1;
                    278:        register struct ilchan *icp;
                    279:        register struct queue *q;
                    280: 
                    281:        if(is->bp == 0)
                    282:                panic("ilrint no is->bp");
                    283:        if(is->nbp == 0)
                    284:                panic("ilrint no is->nbp");
                    285:        bp = is->nbp;
                    286:        if(bp == is->bp){
                    287:                /* first buffer of a packet */
                    288:                hp = (struct il_rheader *)bp->rptr;
                    289:                is->len = hp->ilr_length;
                    290:                is->len += 4;
                    291:        }
                    292:        is->len -= (bp->wptr - bp->rptr);
                    293:        is->nbp = bp->next;
                    294:        /* ilsetup will take care of huge packets by asking
                    295:         * the controller to truncate.
                    296:         */
                    297:        if(is->len <= 0)
                    298:                goto done;
                    299:        if((bp->wptr - bp->rptr) % 8)   /* not chaining */
                    300:                goto done;
                    301:        if(is->nbp == 0){
                    302:                /* more, more */
                    303:                if(is->active){
                    304:                        is->rcvpending = is->len;
                    305:                } else {
                    306:                        ilsetup(is, addr, is->len);
                    307:                }
                    308:        }
                    309:        return;
                    310: 
                    311: done:
                    312:        bp = is->bp;
                    313:        hp = (struct il_rheader *)bp->rptr;
                    314:        len = hp->ilr_length - sizeof(struct il_rheader);
                    315: 
                    316:        if(len < 46 || len > ETHERMTU || is->len > 0){
                    317:                if(ilprintfs)
                    318:                        printf("il%d: ilr_length %d is-len %d\n",
                    319:                                unit, hp->ilr_length, is->len);
                    320:                is->ierrors++;
                    321:                goto setup;
                    322:        }
                    323:        if(hp->ilr_status&ILFSTAT_L)
                    324:                is->ierrors++;
                    325:        len += sizeof(struct il_rheader) - 4;
                    326: 
                    327:        for(icp = ilchan; icp < &ilchan[NILCHAN]; icp++)
                    328:                if(icp->rq && icp->unit == unit && icp->type == hp->ilr_type)
                    329:                        break;
                    330:        if(icp >= &ilchan[NILCHAN]){
                    331:                if(ilprintfs)
                    332:                        printf("type %x?\n", hp->ilr_type);
                    333:                goto setup;
                    334:        }
                    335:        q = icp->rq;
                    336:        if(q->next->flag&QFULL){
                    337:                if(ilprintfs)
                    338:                        printf(" q full\n");
                    339:                is->ierrors++;
                    340:                goto setup;
                    341:        }
                    342:        bp->rptr = &(hp->ilr_dhost[0]);
                    343:        ildebug(bp, 0);
                    344:        len = hp->ilr_length - 4;
                    345:        while(bp && bp != is->nbp){
                    346:                if (bp->wptr - bp->rptr > len)
                    347:                        bp->wptr = bp->rptr + len;
                    348:                len -= bp->wptr - bp->rptr;
                    349:                bp1 = bp->next;
                    350:                if (bp->wptr > bp->rptr)
                    351:                        (*q->next->qinfo->putp)(q->next, bp);
                    352:                else
                    353:                        freeb(bp);
                    354:                bp = bp1;
                    355:        }
                    356:        is->bp = is->nbp;
                    357:        bp = allocb(1);
                    358:        if(bp){
                    359:                bp->type = M_DELIM;
                    360:                (*q->next->qinfo->putp)(q->next, bp);
                    361:                is->ipackets++;
                    362:        } else {
                    363:                printf("ilrint no DELIM bp\n");
                    364:        }
                    365: setup:
                    366:        /* free up blocks in a rejected packet */
                    367:        bp = is->bp;
                    368:        while(bp && bp != is->nbp){
                    369:                bp1 = bp->next;
                    370:                freeb(bp);
                    371:                bp = bp1;
                    372:        }
                    373:        is->bp = bp;
                    374:        if(is->active){         /* don't interfere w/ output */
                    375:                is->rcvpending = ETHERMTU;
                    376:                return;
                    377:        }
                    378:        ilsetup(is, addr, ETHERMTU);
                    379: }
                    380: 
                    381: iladdr(memaddr)
                    382: caddr_t memaddr;
                    383: {
                    384:        register long a;
                    385: 
                    386:        if((unsigned)memaddr < (unsigned)blkdata){
                    387:                printf("memaddr %x blkdata %x\n", memaddr, blkdata);
                    388:                panic("iladdr");
                    389:        }
                    390:        a = (long)memaddr - (long)(caddr_t)blkdata + ((long)blkubad&0x03ffff);
                    391:        /* sure */
                    392:        return(a);
                    393: }
                    394: 
                    395: int    nodev(), ilopen(), ilclose(), ilput();
                    396: struct qinit ilrinit = { nodev, NULL, ilopen, ilclose, 0, 0 };
                    397: struct qinit ilwinit = { ilput, NULL, ilopen, ilclose, ETHERMTU-6, 64 };
                    398: struct streamtab ilsinfo = { &ilrinit, &ilwinit };
                    399: 
                    400: ilopen(q, dev)
                    401: register struct queue *q;
                    402: register dev_t dev;
                    403: {
                    404:        register struct ilchan *icp;
                    405:        register struct il *is;
                    406:        int unit, s;
                    407: 
                    408:        dev = minor(dev);
                    409:        unit = dev / CHANS_PER_UNIT;
                    410:        if(dev >= NILCHAN)
                    411:                return(0);
                    412:        if(unit >= NIL)
                    413:                return(0);
                    414:        is = &il[unit];
                    415:        if(is->attached == 0)
                    416:                return(0);
                    417:        icp = &ilchan[dev];
                    418:        if(icp->rq)
                    419:                return(0);
                    420: 
                    421:        icp->rq = q;
                    422:        q->ptr = (caddr_t)icp;
                    423:        WR(q)->ptr = (caddr_t)icp;
                    424:        WR(q)->flag |= QDELIM|QBIGB;
                    425:        q->flag |= QDELIM;
                    426: 
                    427:        icp->unit = unit;
                    428:        icp->type = 0;
                    429:        icp->packets = 0;
                    430: 
                    431:        s = spl6();
                    432:        if(is->rcvpending && is->active == 0){
                    433:                /* first open, supply rcv buffer */
                    434:                is->active = 1;
                    435:                ilcint(unit);
                    436:        }
                    437:        splx(s);
                    438:        return(1);
                    439: }
                    440: 
                    441: ilclose(q)
                    442: register struct queue *q;
                    443: {
                    444:        register struct ilchan *icp;
                    445: 
                    446:        icp = (struct ilchan *)q->ptr;
                    447:        icp->rq = 0;
                    448:        icp->packets = 0;
                    449: }
                    450: 
                    451: /*
                    452:  * Ilput expects the first block of each packet to contain a six byte
                    453:  * ethernet address followed by a two byte packet type number in
                    454:  * network byte order.
                    455:  */
                    456: ilput(q, bp)
                    457: register struct queue *q;
                    458:        struct block *bp;
                    459: {
                    460:        register struct il *is;
                    461:        int unit, s;
                    462:        register struct ilchan *icp;
                    463: 
                    464:        icp = (struct ilchan *)q->ptr;
                    465:        unit = icp->unit;
                    466: 
                    467:        if(bp->type == M_DATA){
                    468:                if (!icp->haveheader) {
                    469:                        icp->haveheader = 1;
                    470:                        ilfixheader(bp);
                    471:                }
                    472:                putq(q, bp);
                    473:                return;
                    474:        } else if(bp->type == M_IOCTL){
                    475:                ilioctl(q, bp);
                    476:                return;
                    477:        } else if(bp->type != M_DELIM){
                    478:                freeb(bp);
                    479:                return;
                    480:        }
                    481:        /* have end of packet */
                    482:        icp->haveheader = 0;
                    483:        putq(q, bp);
                    484:        is = &il[unit];
                    485:        s = spl6();
                    486:        icp->packets++;
                    487:        if(is->active == 0)
                    488:                ilstart(unit);
                    489:        splx(s);
                    490: }
                    491: 
                    492: /*
                    493:  *     Interlan drivers accept a strange type of ethernet header.
                    494:  *     It is the normal ethernet header with the source field removed.
                    495:  */
                    496: ilfixheader(bp)
                    497: register struct block *bp;
                    498: {
                    499:        register struct ether_in *ep;
                    500: 
                    501:        if (bp->wptr - bp->rptr < sizeof(struct ether_out)) {
                    502:                printf("ether_header too short\n");
                    503:                return;
                    504:        }
                    505:        ep = (struct ether_in *)(bp->rptr);
                    506:        bcopy(ep->dhost, ep->shost, 6);
                    507:        bp->rptr += 6;
                    508: }
                    509: 
                    510: #define ILLDEBSIZE 64
                    511: struct {
                    512:        time_t  time;
                    513:        unsigned short code;
                    514:        unsigned char addr[6];
                    515: } illdebarr[ILLDEBSIZE];
                    516: 
                    517: int illindex = 0;
                    518: 
                    519: ildebug(bp, code)
                    520: register struct block *bp;
                    521: {
                    522:        illdebarr[illindex].time = time;
                    523:        illdebarr[illindex].code = code;
                    524:        bcopy(bp->rptr, illdebarr[illindex].addr, 6);
                    525:        illindex = (illindex + 1) % ILLDEBSIZE;
                    526: }
                    527: 
                    528: ilioctl(q, bp)
                    529: register struct queue *q;
                    530: register struct block *bp;
                    531: {
                    532:        union stmsg *sp;
                    533:        register struct ilchan *icp;
                    534:        int unit;
                    535:        struct uba_device *ui;
                    536:        struct ildevice *addr;
                    537: 
                    538:        icp = (struct ilchan *)q->ptr;
                    539:        sp = (union stmsg *)bp->rptr;
                    540:        bp->type = M_IOCACK;
                    541:        switch(sp->ioc0.com){
                    542:        case ENIOTYPE:
                    543:                icp->type = *((int *)(sp->iocx.xxx));
                    544:                break;
                    545:        case ENIOADDR:
                    546:                bcopy(il[icp->unit].addr, sp->iocx.xxx, 6);
                    547:                break;
                    548:        case ENIOCMD:           /* perform a non-dma interlan command */
                    549:                unit = icp->unit;
                    550:                ui = ilinfo[unit];
                    551:                addr = (struct ildevice *)ui->ui_addr;
                    552:                addr->il_csr = *((int *)(sp->iocx.xxx));
                    553:                *((int *)(sp->iocx.xxx)) = ilcdone(addr, "CMD");
                    554:                break;
                    555:        default:
                    556:                bp->type = M_IOCNAK;
                    557:                break;
                    558:        }
                    559:        qreply(q, bp);
                    560: }
                    561: 
                    562: ilsetup(is, addr, n)
                    563: register struct il *is;
                    564: register struct ildevice *addr;
                    565: {
                    566:        register struct block *bp;
                    567:        int ubaddr, count;
                    568: 
                    569:        if(is->active)
                    570:                panic("ilsetup active");
                    571:        /*
                    572:         * is->bp is start of buffer chain, is->nbp is next buffer
                    573:         * to be DMA'd into. if is->bp is zero, there is no chain
                    574:         * yet, else if is->nbp is zero, add stuff to the end of
                    575:         * the chain, else only add stuff if we need to.
                    576:         */
                    577:        if(is->nbp && is->bp == 0){
                    578:                printf("il: nbp but no bp in ilsetup\n");
                    579:                is->nbp = 0;
                    580:        }
                    581:        count = 0;
                    582:        /* count bytes and buffers already loaded into controller */
                    583:        for(bp = is->nbp; bp; bp = bp->next){
                    584:                n -= bp->wptr - bp->rptr;
                    585:                count++;
                    586:        }
                    587:        if(n <= 0)
                    588:                return;
                    589:        if(count > ILOUTSTANDING)
                    590:                printf("ilsetup: already %d in bar/bcr q!\n", count);
                    591:        if(is->bp == 0){
                    592:                bp = is->nbp = 0;
                    593:        } else {
                    594:                for(bp = is->bp; bp->next; bp = bp->next)
                    595:                        ;
                    596:        }
                    597:        /* now bp is 0 or else the last block in the chain */
                    598:        while(count < ILOUTSTANDING && n > 0){
                    599:                if(bp == 0){
                    600:                        is->bp = is->nbp = bp = allocb(n);
                    601:                } else {
                    602:                        bp->next = allocb(n);
                    603:                        bp = bp->next;
                    604:                }
                    605:                if(bp == 0){
                    606:                        is->rcvpending = n;
                    607:                        return;
                    608:                }
                    609:                bp->next = 0;
                    610:                if(is->nbp == 0)
                    611:                        is->nbp = bp;
                    612:                bp->rptr = bp->base;
                    613:                bp->wptr = bp->lim;
                    614:                if(n > ETHERMTU){       /* tell controller to truncate */
                    615:                        bp->wptr -= 2;
                    616:                        n = 0;
                    617:                }
                    618:                n -= bp->wptr - bp->rptr;
                    619:                count++;
                    620:                ubaddr = iladdr((caddr_t)(bp->rptr));
                    621:                addr->il_bar = ubaddr & 0xffff;
                    622:                addr->il_bcr = bp->wptr - bp->rptr;
                    623:                addr->il_csr = ((ubaddr>>2)&IL_EUA)|ILC_RCV|IL_RIE;
                    624:                ilcdone(addr, "RCV");
                    625:        }
                    626:        is->rcvpending = 0;
                    627: }
                    628: 
                    629: ilcdone(addr, s)
                    630: struct ildevice *addr;
                    631: char *s;
                    632: {
                    633:        int count;
                    634: 
                    635:        count = 0;
                    636:        while((addr->il_csr & IL_CDONE) == 0){
                    637:                count++;
                    638:                if(count > 200000)
                    639:                        break;
                    640:        }
                    641:        if(count > 200000){
                    642:                printf("%s: addr 0%o csr 0x%x\n", s, addr, addr->il_csr);
                    643:                return(1);
                    644:        }
                    645:        return(addr->il_csr & 0xf);
                    646: }
                    647: #endif NIL

unix.superglobalmegacorp.com

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