Annotation of researchv10no/sys/io/ni1010a.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Interlan NI1010A Ethernet interface.
        !             3:  * Each hardware device has eight minor devices starting at N*8;
        !             4:  * the different channels may be caused to receive different
        !             5:  * Ethernet protocols via ENIOTYPE.
        !             6:  * Packets read or written have the Ethernet header in front.
        !             7:  */
        !             8: #include "sys/param.h"
        !             9: #include "sys/stream.h"
        !            10: #include "sys/conf.h"
        !            11: #include "sys/ubaddr.h"
        !            12: #include "sys/enio.h"
        !            13: #include "sys/ethernet.h"
        !            14: #include "sys/ni1010a.h"
        !            15: 
        !            16: /*
        !            17:  * hardware registers
        !            18:  */
        !            19: struct ildevice {
        !            20:        unsigned short il_csr;
        !            21:        short il_bar;
        !            22:        short il_bcr;
        !            23: };
        !            24: 
        !            25: /*
        !            26:  * il_csr
        !            27:  */
        !            28: #define        IL_EUA          0xc000  /* buffer address high bits */
        !            29: #define        IL_CDONE        0x0080  /* command done */
        !            30: #define        IL_CIE          0x0040  /* command intr enable */
        !            31: #define        IL_RDONE        0x0020  /* receive data arrived */
        !            32: #define        IL_RIE          0x0010  /* receive intr enable */
        !            33: #define        IL_STATUS       0x000f  /* mask for command status */
        !            34: 
        !            35: /*
        !            36:  * commands, already shifted into place
        !            37:  */
        !            38: #define        ILC_ONLINE      0x0900  /* speak to the network */
        !            39: #define        ILC_STAT        0x1800  /* return statistics and address */
        !            40: #define        ILC_RCV         0x2000  /* here's a receive buffer */
        !            41: #define        ILC_LDXMIT      0x2800  /* take this data */
        !            42: #define        ILC_XMIT        0x2900  /* take this data, start sending */
        !            43: #define        ILC_RESET       0x3f00  /* reset */
        !            44: 
        !            45: /*
        !            46:  * status values (some)
        !            47:  */
        !            48: #define        ILERR_SUCCESS   0       /* ok */
        !            49: #define        ILERR_RETRIES   1       /* ok, but retried */
        !            50: /* other values mean it didn't work */
        !            51: 
        !            52: /*
        !            53:  * status after diagnostics
        !            54:  */
        !            55: #define        ILDIAG_SUCCESS  0       /* ok */
        !            56: 
        !            57: /*
        !            58:  * frame status bits in received packet
        !            59:  */
        !            60: #define        FS_LOST         04      /* some earlier packet was lost */
        !            61: #define        FS_ALIGN        02      /* alignment error */
        !            62: #define        FS_CRC          01      /* CRC error */
        !            63: 
        !            64: #define        CRCSIZE 4               /* size of the pointless CRC on received pkt */
        !            65: #define        MAXRBUFS 16             /* max number of rcv buffers allowed */
        !            66: 
        !            67: /*
        !            68:  * enormous statistics record
        !            69:  * we get it only for the ethernet address address
        !            70:  */
        !            71: struct il_stats {
        !            72:        short   ils_fill1;
        !            73:        short   ils_length;             /* Length (should be 62) */
        !            74:        char    ils_addr[6];            /* Ethernet Address */
        !            75:        short   ils_frames;             /* Number of Frames Received */
        !            76:        short   ils_rfifo;              /* Number of Frames in Receive FIFO */
        !            77:        short   ils_xmit;               /* Number of Frames Transmitted */
        !            78:        short   ils_xcollis;            /* Number of Excess Collisions */
        !            79:        short   ils_frag;               /* Number of Fragments Received */
        !            80:        short   ils_lost;               /* Number of Times Frames Lost */
        !            81:        short   ils_multi;              /* Number of Multicasts Accepted */
        !            82:        short   ils_rmulti;             /* Number of Multicasts Rejected */
        !            83:        short   ils_crc;                /* Number of CRC Errors */
        !            84:        short   ils_align;              /* Number of Alignment Errors */
        !            85:        short   ils_collis;             /* Number of Collisions */
        !            86:        short   ils_owcollis;           /* Number of Out-of-window Collisions */
        !            87:        short   ils_fill2[8];
        !            88:        char    ils_module[8];          /* Module ID */
        !            89:        char    ils_firmware[8];        /* Firmware ID */
        !            90: };
        !            91: 
        !            92: extern int ilcnt;
        !            93: extern struct il il[];
        !            94: extern struct ubaddr iladdr[];
        !            95: 
        !            96: /*
        !            97:  * il.flags
        !            98:  */
        !            99: 
        !           100: #define        CMDACT  01      /* some command active -- can't issue another yet */
        !           101: #define        INITDONE 02     /* finished init */
        !           102: #define        INITING 04      /* halfway through init; just wakeup on intr */
        !           103: 
        !           104: #define        NEXTCH(i)       (((i)+1)%NILCHAN)
        !           105: 
        !           106: #define        ETHERMAXTU      1500    /* max packet size */
        !           107: #define        ILRBYTES        (ETHERMAXTU*2)  /* desired receive buffer size */
        !           108: #define        ILRSIZE         1024    /* preferred receive block size */
        !           109: 
        !           110: #define        ISCHAIN(l)      (((l)&07) == 0)
        !           111: #define        MKCHAIN(l)      ((l)&~07)       /* force length to allow rbuf chaining */
        !           112: #define        MKTRUNC(l)      (MKCHAIN(l)-2)  /* force to disallow */
        !           113: 
        !           114: long ilopen();
        !           115: int ilclose(), ilput();
        !           116: static struct qinit ilrinit = { noput, NULL, ilopen, ilclose, 0, 0 };
        !           117: static struct qinit ilwinit = { ilput, NULL, ilopen, ilclose, 4*ETHERMAXTU, 64 };
        !           118: static struct streamtab ilsinfo = { &ilrinit, &ilwinit };
        !           119: struct cdevsw ilcdev = cstrinit(&ilsinfo);
        !           120: 
        !           121: long
        !           122: ilopen(q, dev)
        !           123: register struct queue *q;
        !           124: register dev_t dev;
        !           125: {
        !           126:        register struct ilchan *cp;
        !           127:        register struct il *is;
        !           128:        int unit;
        !           129: 
        !           130:        dev = minor(dev);
        !           131:        unit = dev / NILCHAN;
        !           132:        if (unit >= ilcnt || ilinit(unit) == 0)
        !           133:                return(0);
        !           134:        is = &il[unit];
        !           135:        cp = &is->chan[dev%NILCHAN];
        !           136:        if(cp->rq)
        !           137:                return(0);
        !           138:        cp->rq = q;
        !           139:        q->ptr = (caddr_t)cp;
        !           140:        WR(q)->ptr = (caddr_t)cp;
        !           141:        WR(q)->flag |= QDELIM|QBIGB;
        !           142:        q->flag |= QDELIM;
        !           143:        cp->unit = unit;                /* needed? */
        !           144:        cp->type = 0;
        !           145:        return(1);
        !           146: }
        !           147: 
        !           148: /*
        !           149:  * init the hardware
        !           150:  */
        !           151: static struct il_stats ilstats;
        !           152: static char ilsbusy;
        !           153: 
        !           154: ilinit(dev)
        !           155: int dev;
        !           156: {
        !           157:        register struct il *is;
        !           158:        register struct ildevice *addr;
        !           159:        ubm_t ubm;
        !           160:        uaddr_t uad;
        !           161:        register int sts;
        !           162:        int s;
        !           163: 
        !           164:        is = &il[dev];
        !           165:        s = spl6();
        !           166:        while (is->flags & INITING)
        !           167:                tsleep((caddr_t)is, PZERO+1, 5);
        !           168:        splx(s);
        !           169:        if (is->flags & INITDONE)
        !           170:                return (1);
        !           171:        is->flags |= INITING;
        !           172:        if ((addr = (struct ildevice *)ubaddr(&iladdr[dev])) == NULL
        !           173:        ||  badaddr(&addr->il_csr, sizeof(short))) {
        !           174:                printf("ni1010a %d absent\n", dev);
        !           175:                is->flags &=~ INITING;
        !           176:                return (0);
        !           177:        }
        !           178:        is->ubno = iladdr[dev].ubno;
        !           179:        is->addr = addr;
        !           180:        if ((sts = ilincmd(is, ILC_RESET)) == 0
        !           181:        ||  (sts & IL_STATUS) != ILDIAG_SUCCESS) {
        !           182:                printf("ni1010a %d: reset failed csr %x\n", dev, is->lastcsr);
        !           183:                is->flags &=~ INITING;
        !           184:                return (0);
        !           185:        }
        !           186:        s = spl6();
        !           187:        while (ilsbusy)
        !           188:                tsleep((caddr_t)&ilsbusy, PZERO, 5);
        !           189:        ilsbusy = 1;
        !           190:        splx(s);
        !           191:        ubm = ubmalloc(is->ubno, sizeof(ilstats), USLP);
        !           192:        uad = ubmaddr(is->ubno, (char *)&ilstats, sizeof(ilstats), ubm);
        !           193:        addr->il_bar = uad;
        !           194:        addr->il_bcr = sizeof(ilstats);
        !           195:        sts = ilincmd(is, (int)((uad >> 2) & IL_EUA) | ILC_STAT);
        !           196:        ubmfree(is->ubno, ubm);
        !           197:        if (sts == 0 || (sts & IL_STATUS) != ILERR_SUCCESS) {
        !           198:                ilsbusy = 0;
        !           199:                wakeup((caddr_t)&ilsbusy);
        !           200:                printf("ni1010a %d: stat failed csr %x\n", dev, is->lastcsr);
        !           201:                is->flags &=~ INITING;
        !           202:                return (0);
        !           203:        }
        !           204:        bcopy(ilstats.ils_addr, is->enaddr, sizeof(is->enaddr));
        !           205:        ilsbusy = 0;
        !           206:        wakeup((caddr_t)&ilsbusy);
        !           207:        if ((sts = ilincmd(is, ILC_ONLINE)) == 0
        !           208:        ||  (sts & IL_STATUS) != ILERR_SUCCESS) {
        !           209:                printf("ni1010a %d: online failed csr %x\n", dev, sts);
        !           210:                is->flags &=~ INITING;
        !           211:                return (0);
        !           212:        }
        !           213:        is->flags &=~ INITING;
        !           214:        is->flags |= INITDONE;
        !           215:        wakeup((caddr_t)is);            /* in case someone is waiting */
        !           216:        s = spl6();
        !           217:        ilrcvbufs(is);
        !           218:        splx(s);
        !           219:        return (1);
        !           220: }
        !           221: 
        !           222: int
        !           223: ilincmd(is, csr)
        !           224: register struct il *is;
        !           225: register short csr;
        !           226: {
        !           227:        register int s;
        !           228: 
        !           229:        s = spl6();
        !           230:        is->flags |= CMDACT;
        !           231:        is->addr->il_csr = csr|IL_CIE;
        !           232:        while (is->flags & CMDACT)
        !           233:                if (tsleep((caddr_t)is, PZERO, 5) != TS_OK) {
        !           234:                        is->flags &=~ CMDACT;
        !           235:                        splx(s);
        !           236:                        return (0);
        !           237:                }
        !           238:        csr = is->lastcsr;      /* probably unnecessary */
        !           239:        splx(s);
        !           240:        return (csr);
        !           241: }
        !           242: 
        !           243: ilclose(q)
        !           244: struct queue *q;
        !           245: {
        !           246:        struct ilchan *cp;
        !           247: 
        !           248:        cp = (struct ilchan *)q->ptr;
        !           249:        cp->rq = 0;
        !           250: }
        !           251: 
        !           252: /*
        !           253:  * stash data
        !           254:  */
        !           255: ilput(q, bp)
        !           256: struct queue *q;
        !           257: register struct block *bp;
        !           258: {
        !           259:        register struct ilchan *cp;
        !           260:        register int s;
        !           261: 
        !           262:        cp = (struct ilchan *)q->ptr;
        !           263:        switch (bp->type) {
        !           264:        case M_DATA:
        !           265:                cp->xlast = bp;
        !           266:                putq(q, bp);
        !           267:                if (bp->class&S_DELIM)
        !           268:                        break;
        !           269:                return;
        !           270: 
        !           271:        case M_IOCTL:
        !           272:                ilioctl(q, bp);
        !           273:                return;
        !           274: 
        !           275:        default:
        !           276:                freeb(bp);
        !           277:                return;
        !           278:        }
        !           279:        /*
        !           280:         * S_DELIM: end of packet
        !           281:         */
        !           282:        if (cp->xlast == NULL)  /* empty record */
        !           283:                return;
        !           284:        cp->xlast = NULL;
        !           285:        cp->ndelims++;
        !           286:        s = spl6();
        !           287:        ilsendpkt(&il[cp->unit]);
        !           288:        splx(s);
        !           289: }
        !           290: 
        !           291: /*
        !           292:  * pick a channel with a packet to send, and start sending it
        !           293:  * first block goes to the device here;
        !           294:  * interrupt code will feed it more
        !           295:  * adjust ethernet header in first block --
        !           296:  * interlan expects no source address
        !           297:  */
        !           298: ilsendpkt(is)
        !           299: register struct il *is;
        !           300: {
        !           301:        register struct ilchan *cp;
        !           302:        register struct block *bp;
        !           303:        register int i;
        !           304:        register struct etherpup *ep;
        !           305: 
        !           306:        if (is->flags & CMDACT)
        !           307:                return;
        !           308: again:
        !           309:        for (i = NEXTCH(is->lastch); ; i = NEXTCH(i)) {
        !           310:                cp = &is->chan[i];
        !           311:                if (cp->ndelims)
        !           312:                        break;
        !           313:                if (i == is->lastch)
        !           314:                        return;
        !           315:        }
        !           316:        is->lastch = i;
        !           317:        if ((bp = getq(WR(cp->rq))) == NULL)
        !           318:                panic("ilsendpkt");
        !           319:        cp->ndelims--;
        !           320:        if (bp->wptr - bp->rptr < sizeof(struct etherpup)) {
        !           321:                /* should probably try to pull packets together here */
        !           322:                printf("ni1010a %d: short header\n", cp->unit);
        !           323:                for (; (bp && bp->class&S_DELIM)==0; bp = getq(WR(cp->rq)))
        !           324:                        freeb(bp);
        !           325:                goto again;
        !           326:        }
        !           327:        ep = (struct etherpup *)(bp->rptr);
        !           328:        bcopy(ep->dhost, ep->shost, sizeof(ep->dhost));
        !           329:        bp->rptr += sizeof(ep->dhost);
        !           330:        cp->xcur = bp;
        !           331:        ildebug(bp, 1, 0);      /* how can we generate length cheaply? */
        !           332:        ilsendblock(is, bp);
        !           333: }
        !           334: 
        !           335: /*
        !           336:  * command done interrupt
        !           337:  * if in init code, just wakeup
        !           338:  * if need receive buffers, make one
        !           339:  * else finish any pending transmit
        !           340:  */
        !           341: il1int(unit)
        !           342: {
        !           343:        register struct il *is;
        !           344:        register struct ilchan *cp;
        !           345:        register int type;
        !           346: 
        !           347:        is = &il[unit];
        !           348:        if (is->addr == NULL) {
        !           349:                printf("ni1010a %d: spurious interrupt\n", unit);
        !           350:                return;
        !           351:        }
        !           352:        is->lastcsr = is->addr->il_csr;
        !           353:        if ((is->flags & CMDACT) == 0) {
        !           354:                printf("ni1010a %d: stray cmd interrupt, csr %x\n", unit, is->lastcsr);
        !           355:                return;
        !           356:        }
        !           357:        is->flags &=~ CMDACT;
        !           358:        if (is->flags & INITING) {
        !           359:                wakeup((caddr_t)is);
        !           360:                return;
        !           361:        }
        !           362:        if (is->rbytes < ILRBYTES)
        !           363:                if (ilrcvbufs(is))
        !           364:                        return;
        !           365:        cp = &is->chan[is->lastch];
        !           366:        if (cp->xcur) {                 /* sending something */
        !           367:                type = cp->xcur->class;
        !           368:                freeb(cp->xcur);
        !           369:                cp->xcur = NULL;
        !           370:                if ((type&S_DELIM)==0
        !           371:                &&  (cp->xcur = getq(WR(cp->rq))) != NULL) {
        !           372:                        ilsendblock(is, cp->xcur);
        !           373:                        return;
        !           374:                }
        !           375:                switch (is->lastcsr & IL_STATUS) {
        !           376:                case ILERR_RETRIES:
        !           377:                        is->collisions++;
        !           378:                case ILERR_SUCCESS:
        !           379:                        is->opackets++;
        !           380:                        break;
        !           381:        
        !           382:                default:
        !           383:                        is->oerrors++;
        !           384:                        printf("ni1010a %d: xmt error 0x%x\n", unit, is->lastcsr&IL_STATUS);
        !           385:                        break;
        !           386:                }
        !           387:        }
        !           388:        ilsendpkt(is);
        !           389: }
        !           390: 
        !           391: /*
        !           392:  * feed a block to the controller
        !           393:  */
        !           394: ilsendblock(is, bp)
        !           395: struct il *is;
        !           396: register struct block *bp;
        !           397: {
        !           398:        register struct ildevice *addr;
        !           399:        uaddr_t uad;
        !           400:        register int i;
        !           401: 
        !           402:        addr = is->addr;
        !           403:        uad = ubadrptr(is->ubno, bp, ubmblk(is->ubno, bp, 0));
        !           404:        addr->il_bar = uad;
        !           405:        addr->il_bcr = bp->wptr - bp->rptr;
        !           406:        is->flags |= CMDACT;
        !           407:        i = ((uad>>2)&IL_EUA)|IL_RIE|IL_CIE;
        !           408:        if ((bp->class&S_DELIM)==0)     /* not last piece of packet */
        !           409:                addr->il_csr = i | ILC_LDXMIT;
        !           410:        else
        !           411:                addr->il_csr = i | ILC_XMIT;
        !           412: }
        !           413: 
        !           414: /*
        !           415:  * add receive buffer space if needed
        !           416:  * -- let it be an ordinary command, interrupt when complete, for now.
        !           417:  * this is probably too slow
        !           418:  * returns nonzero if a command was started
        !           419:  */
        !           420: ilrcvbufs(is)
        !           421: register struct il *is;
        !           422: {
        !           423:        register struct block *bp;
        !           424:        register struct ildevice *addr;
        !           425:        register int len;
        !           426:        register uaddr_t uad;
        !           427: 
        !           428:        if (is->flags & CMDACT)
        !           429:                return (0);
        !           430:        if (is->rbytes >= ILRBYTES || is->rbufs >= MAXRBUFS)
        !           431:                return (0);
        !           432:        if ((bp = allocb(ILRSIZE)) == NULL)
        !           433:                return (0);
        !           434:        bp->next = NULL;
        !           435:        if (is->rfirst == NULL)
        !           436:                is->rfirst = bp;
        !           437:        else
        !           438:                is->rlast->next = bp;
        !           439:        is->rlast = bp;
        !           440:        len = bp->lim - bp->wptr;
        !           441:        /* assume at least eight bytes in bp */
        !           442:        len = MKCHAIN(len);
        !           443:        is->rbytes += len;
        !           444:        bp->wptr = bp->rptr + len;
        !           445:        is->rbufs++;
        !           446:        *(long *)bp->rptr = 0x80818283; /* debuggery */
        !           447:        uad = ubadrptr(is->ubno, bp, ubmblk(is->ubno, bp, 0));
        !           448:        is->flags |= CMDACT;
        !           449:        addr = is->addr;
        !           450:        addr->il_bar = uad;
        !           451:        addr->il_bcr = len;
        !           452:        addr->il_csr = ((uad>>2)&IL_EUA)|ILC_RCV|IL_RIE|IL_CIE;
        !           453:        return (1);
        !           454: }
        !           455: 
        !           456: /*
        !           457:  * receive done interrupt
        !           458:  * -- (is->rfirst, is->rlast) is the set of buffers involved in receiving
        !           459:  * is->rnext, if non-empty, points to the next one we expect data in
        !           460:  * hence (is->rfirst, is->rnext) is the current incomplete packet
        !           461:  * is->rcur is the number of bytes not yet received in the current packet
        !           462:  */
        !           463: il0int(unit)
        !           464: int unit;
        !           465: {
        !           466:        register struct il *is;
        !           467:        register struct block *bp;
        !           468:        register struct block *lbp;
        !           469:        register struct ilchan *cp;
        !           470:        register struct queue *nq;
        !           471:        register int i;
        !           472:        int proto;
        !           473: 
        !           474:        is = &il[unit];
        !           475:        if (is->addr)
        !           476:                is->lastcsr = is->addr->il_csr;
        !           477:        if (is->addr == NULL || is->rfirst == NULL) {
        !           478:                printf("ni1010a %d: spurious rcv intr csr %x\n", unit, is->lastcsr);
        !           479:                return;
        !           480:        }
        !           481:        if ((lbp = is->rnext) == NULL) {
        !           482:                lbp = is->rfirst;
        !           483:                lbp->rptr += 2;         /* frame status, junk */
        !           484:                is->rcur = *lbp->rptr++;
        !           485:                is->rcur += *lbp->rptr++ << 8;
        !           486:                /* assume header is all in first block */
        !           487:                ildebug(lbp, 0, is->rcur - CRCSIZE);
        !           488:        }
        !           489:        is->rbytes -= lbp->wptr - lbp->base;    /* sic -- in case first block */
        !           490:        is->rbufs--;
        !           491:        ilrcvbufs(is);
        !           492:        i = lbp->wptr - lbp->rptr;
        !           493:        if (is->rcur < i)
        !           494:                i = is->rcur;
        !           495:        lbp->wptr = lbp->rptr + i;
        !           496:        is->rcur -= i;
        !           497:        if (is->rcur > 0) {     /* more expected */
        !           498:                if ((is->rnext = lbp->next) == NULL)
        !           499:                        panic("il0int");        /* too draconian */
        !           500:                return;
        !           501:        }
        !           502:        /*
        !           503:         * complete packet:
        !           504:         * first block is is->rfirst,
        !           505:         * last is is->rnext == lbp
        !           506:         */
        !           507:        lbp->wptr -= CRCSIZE;   /* discard boring CRC */
        !           508:        lbp->class |= S_DELIM;  /* make delimiter */
        !           509:        if (lbp->wptr < lbp->rptr) {
        !           510:                i = lbp->rptr - lbp->wptr;
        !           511:                lbp->rptr = lbp->wptr;
        !           512:                for (bp = is->rfirst; bp != lbp; bp = bp->next)
        !           513:                        if (bp->next == lbp) {
        !           514:                                bp->wptr -= i;  /* and assume it stops here */
        !           515:                                break;
        !           516:                        }
        !           517:        }
        !           518:        bp = is->rfirst;        /* first piece of this packet */
        !           519:        if (bp->rptr[-4] & (FS_ALIGN|FS_CRC)) { /* [-4] == frame status */
        !           520:                is->ierrors++;
        !           521:                cp = NULL;
        !           522:        } else {
        !           523:                is->ipackets++;
        !           524:                if (bp->rptr[-4] & FS_LOST)
        !           525:                        is->ilost++;
        !           526:                /* assume the whole ethernet header is in the first block */
        !           527:                proto = ((struct etherpup *)(bp->rptr))->type;
        !           528:                for (i = 0; i < NILCHAN; i++) {
        !           529:                        cp = &is->chan[i];
        !           530:                        if (cp->rq && cp->type == proto)
        !           531:                                break;
        !           532:                }
        !           533:                if (i >= NILCHAN)
        !           534:                        cp = NULL;
        !           535:        }
        !           536:        lbp = lbp->next;                /* one past the end */
        !           537:        if (cp == NULL || cp->rq->next->flag & QFULL) {
        !           538:                while (is->rfirst != lbp) {
        !           539:                        bp = is->rfirst;
        !           540:                        is->rfirst = bp->next;
        !           541:                        freeb(bp);
        !           542:                }
        !           543:        } else {
        !           544:                nq = cp->rq->next;
        !           545:                while (is->rfirst != lbp) {
        !           546:                        bp = is->rfirst;
        !           547:                        is->rfirst = bp->next;
        !           548:                        (*nq->qinfo->putp)(nq, bp);
        !           549:                }
        !           550:        }
        !           551:        is->rnext = NULL;
        !           552: }
        !           553: 
        !           554: ilioctl(q, bp)
        !           555: register struct queue *q;
        !           556: register struct block *bp;
        !           557: {
        !           558:        register struct ilchan *cp;
        !           559: 
        !           560:        cp = (struct ilchan *)q->ptr;
        !           561:        bp->type = M_IOCACK;
        !           562:        switch(stiocom(bp)){
        !           563:        case ENIOTYPE:
        !           564:                cp->type = *((int *)stiodata(bp));
        !           565:                break;
        !           566: 
        !           567:        case ENIOADDR:
        !           568:                bcopy(il[cp->unit].enaddr, stiodata(bp), ETHERALEN);
        !           569:                bp->wptr = bp->rptr + ETHERALEN + STIOCHDR;
        !           570:                break;
        !           571: 
        !           572:        default:
        !           573:                bp->type = M_IOCNAK;
        !           574:                break;
        !           575:        }
        !           576:        qreply(q, bp);
        !           577: }
        !           578: 
        !           579: #define ILLDEBSIZE 64
        !           580: struct ild {
        !           581:        time_t  time;
        !           582:        unsigned short code;
        !           583:        struct etherpup pup;
        !           584:        short len;
        !           585: } ild[ILLDEBSIZE];
        !           586: 
        !           587: int ili = 0;
        !           588: 
        !           589: #include "sys/systm.h" /* just for time */
        !           590: 
        !           591: ildebug(bp, code, len)
        !           592: struct block *bp;
        !           593: int code, len;
        !           594: {
        !           595:        register struct ild *ip;
        !           596: 
        !           597:        ip = &ild[ili];
        !           598:        ip->time = time;
        !           599:        ip->code = code;
        !           600:        ip->len = len;
        !           601:        bcopy(bp->rptr, &ip->pup, sizeof(struct etherpup));
        !           602:        if (++ili >= ILLDEBSIZE)
        !           603:                ili = 0;
        !           604: }

unix.superglobalmegacorp.com

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