Annotation of researchv8dc/sys/dev/ill.c, revision 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.