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

1.1     ! root        1: /*
        !             2:  * DEQNA Ethernet Communications Controller interface,
        !             3:  * vaguely derived from the driver in Ultrix.
        !             4:  * Each DEQNA has eight minor devices starting at N*8;
        !             5:  * the different channels may be caused to receive different
        !             6:  * Ethernet protocols via ENIOTYPE.
        !             7:  * Packets read or written have the Ethernet header in front.
        !             8:  */
        !             9: 
        !            10: #include "sys/param.h"
        !            11: #include "sys/buf.h"
        !            12: #include "sys/stream.h"
        !            13: #include "sys/ubaddr.h"
        !            14: #include "sys/conf.h"
        !            15: #include "sys/enio.h"
        !            16: #include "sys/deqna.h"
        !            17: #include "sys/ethernet.h"
        !            18: 
        !            19: struct qedevice {
        !            20:        unsigned short qe_sta_addr[2];  /* ethernet addr; 6 shorts, overlaid */
        !            21:        unsigned short qe_rcvlist_lo;   /* rcv list addr */
        !            22:        unsigned short qe_rcvlist_hi;
        !            23:        unsigned short qe_xmtlist_lo;   /* xmt list addr */
        !            24:        unsigned short qe_xmtlist_hi;
        !            25:        unsigned short qe_vector;
        !            26:        unsigned short qe_csr;
        !            27: };
        !            28: 
        !            29: /*
        !            30:  * qe_csr
        !            31:  */
        !            32: #define QE_RCV_ENABLE  0x0001          /* receiver enable */
        !            33: #define QE_RESET       0x0002          /* controller reset */
        !            34: #define QE_NEX_MEM_INT 0x0004          /* non-existent memory */
        !            35: #define QE_XL_INVALID  0x0010          /* nothing left to transmit */
        !            36: #define QE_RL_INVALID  0x0020          /* no buffers left to receive */
        !            37: #define QE_INT_ENABLE  0x0040          /* interrupt enable */
        !            38: #define QE_XMIT_INT    0x0080          /* intr because xmit finished */
        !            39: #define QE_ILOOP       0x0100          /* internal loopback disable */
        !            40: #define QE_ELOOP       0x0200          /* external loopback enable */
        !            41: #define QE_RCV_INT     0x8000          /* intr because rcv finished */
        !            42: 
        !            43: /*
        !            44:  * bits to shove into qe_csr for normal operation
        !            45:  */
        !            46: int qebits = QE_RCV_ENABLE|QE_INT_ENABLE|QE_ILOOP;
        !            47: /*
        !            48:  * interrupt request bits:
        !            49:  * after an interrupt, write the ones that are set
        !            50:  * to allow the next interrupt
        !            51:  */
        !            52: #define        INTFLAGS        (QE_XMIT_INT|QE_RCV_INT)
        !            53: 
        !            54: /*
        !            55:  * buffer descriptor
        !            56:  * flag is who owns it;
        !            57:  * the rest is where the data is, and how big
        !            58:  * they may be a list, or a chain.
        !            59:  * we just use a ring; the DEQNA thinks it's a list,
        !            60:  * but the chain flag is used to sew the ring together that the end
        !            61:  */
        !            62: 
        !            63: struct qe_ring {
        !            64:        short flag;
        !            65:        short hiaddr;   /* and descriptor type flags */
        !            66:        short loaddr;
        !            67:        short len;      /* negative length */
        !            68:        unsigned short status1;
        !            69:        unsigned short status2;
        !            70: };
        !            71: 
        !            72: /*
        !            73:  * flags: just descriptor ownership
        !            74:  */
        !            75: 
        !            76: #define        FREADY  0x8000  /* descriptor ready, port not using yet */
        !            77: 
        !            78: /*
        !            79:  * descriptor type flags, in hiaddr
        !            80:  */
        !            81: 
        !            82: #define        DVALID  0x8000  /* valid descriptor */
        !            83: #define        DCHAIN  0x4000  /* chain: address is that of next descriptor */
        !            84: #define        DEND    0x2000  /* end of message; push output packet */
        !            85: #define        DSETUP  0x1000  /* this is a setup packet */
        !            86: #define        DENDODD 0x80    /* buffer ends on odd address */
        !            87: #define        DBEGODD 0x40    /* buffer begins on odd address */
        !            88: 
        !            89: /*
        !            90:  * status1 when we write it
        !            91:  */
        !            92: #define        NOTYET  0x8000  /* descriptor ready, but DEQNA hasn't taken it */
        !            93: /*
        !            94:  * status1 when DEQNA is through
        !            95:  */
        !            96: #define        NOTLAST 0x8000  /* rcv: not the last descriptor of a packet */
        !            97: #define        ERROR   0x4000  /* either: some error happened */
        !            98: #define        ESETUP  0x2000  /* rcv: setup packet acknowledgement */
        !            99: #define        RHILEN  0x0700  /* rcv: high bits of received packet length */
        !           100: 
        !           101: /*
        !           102:  * status2 when we write it
        !           103:  */
        !           104: #define        S2MAGIC 1       /* write this there to make descriptor ready.  why? */
        !           105: /*
        !           106:  * status2 when DEQNA is through
        !           107:  */
        !           108: #define RLOLEN 0x00ff  /* rcv: low bits of received length */
        !           109: 
        !           110: #define        RMINLEN 60      /* add this to get real received packet length */
        !           111: 
        !           112: /*
        !           113:  *  operating condition set-up bits
        !           114:  */
        !           115: #define ALLM   0x1     /* match all multicast addresses */
        !           116: #define PROM   0x2     /* match all addresses (promiscuous mode) */
        !           117: 
        !           118: /*
        !           119:  * setup packet:
        !           120:  * lists the addresses we may receive
        !           121:  * each column (sic) of the array contains an address
        !           122:  * e.g. setup[1][0..5]
        !           123:  * setup[0][*] and setup[*][6..7] are junk
        !           124:  */
        !           125: 
        !           126: struct setup {
        !           127:        char d[16][8];
        !           128: };
        !           129: 
        !           130: /*
        !           131:  * data accessed directly by the DEQNA:
        !           132:  * the buffer descriptors and the setup packet
        !           133:  */
        !           134: 
        !           135: struct qeio {
        !           136:        struct qe_ring rring[QENRCV+1];
        !           137:        struct qe_ring xring[QENXMT+1];
        !           138:        struct setup setup;
        !           139: };
        !           140: 
        !           141: /*
        !           142:  * This constant should really be 60 because the qna adds 4 bytes of crc.
        !           143:  * However when set to 60 our packets are ignored by deuna's , 3coms are
        !           144:  * okay ??????????????????????????????????????????
        !           145:  */
        !           146: #define ETHERMINTU 64
        !           147: #define ETHERMAXTU 1564
        !           148: #define MAX_RCV_BYTES (3*ETHERMAXTU)   /* maximum bytes in receive ring */
        !           149: int    nRCV = QENRCV;
        !           150: int    nXMT = QENXMT;
        !           151: 
        !           152: struct qechan *qefindchan();
        !           153: 
        !           154: extern int qecnt;
        !           155: extern struct qe qe[];
        !           156: extern struct ubaddr qeaddr[];
        !           157: 
        !           158: #define NEXTCH(c) (((c)+1)%QENCHAN)    /* next channel */
        !           159: 
        !           160: /* flag settings */
        !           161: #define ATTACHED       0x4
        !           162: #define SETUPQD                0x8
        !           163: 
        !           164: /* handy macros for ring management */
        !           165: #define NFREE(s) ((s)->xindex>=(s)->oxindex?(QENXMT-((s)->xindex-(s)->oxindex)-1):\
        !           166:                                            ((s)->oxindex-(s)->xindex-1))
        !           167: #define NEXTRCV(c) (((c)+1)%QENRCV)
        !           168: #define NEXTXMT(c) (((c)+1)%QENXMT)
        !           169: 
        !           170: long   qeopen();
        !           171: int    qeclose(), qeput();
        !           172: static struct qinit qerinit = { noput, NULL, qeopen, qeclose, 0, 0 };
        !           173: static struct qinit qewinit = { qeput, NULL, qeopen, qeclose, 4*ETHERMAXTU, 64 };
        !           174: static struct streamtab qesinfo = { &qerinit, &qewinit };
        !           175: struct cdevsw qecdev = cstrinit(&qesinfo);
        !           176: 
        !           177: /* open a channel */
        !           178: long
        !           179: qeopen(q, dev)
        !           180: register struct queue *q;
        !           181: register dev_t dev;
        !           182: {
        !           183:        register struct qechan *cp;
        !           184:        register struct qe *qp;
        !           185:        int unit, chan;
        !           186: 
        !           187:        dev = minor(dev);
        !           188:        chan = dev % QENCHAN;
        !           189:        unit = dev / QENCHAN;
        !           190:        if(unit >= qecnt)
        !           191:                return(0);
        !           192:        if (qeinit(unit) == 0)
        !           193:                return (0);
        !           194:        qp = &qe[unit];
        !           195:        cp = &qp->chan[chan];
        !           196:        if(cp->rq)
        !           197:                return(0);
        !           198:        cp->unit = unit;
        !           199:        cp->type = 0;
        !           200:        q->ptr = (caddr_t)cp;
        !           201:        WR(q)->ptr = (caddr_t)cp;
        !           202:        WR(q)->flag |= QDELIM|QBIGB;
        !           203:        q->flag |= QDELIM;
        !           204:        cp->rq = q;
        !           205:        return(1);
        !           206: }
        !           207: 
        !           208: qeclose(q)
        !           209: register struct queue *q;
        !           210: {
        !           211:        register struct qechan *cp;
        !           212: 
        !           213:        cp = (struct qechan *)q->ptr;
        !           214:        cp->rq = 0;
        !           215:        cp->type = 0;
        !           216: }
        !           217: 
        !           218: /*
        !           219:  * init a controller--
        !           220:  * grab and map a buffer for qeio
        !           221:  * reset the device and send it a setup packet
        !           222:  */
        !           223: qeinit(unit)
        !           224: int unit;
        !           225: {
        !           226:        register struct qedevice *addr;
        !           227:        register struct qe *qp;
        !           228:        register uaddr_t ua;
        !           229: 
        !           230:        qp = &qe[unit];
        !           231:        if (qp->addr)
        !           232:                return (1);
        !           233:        if ((addr = (struct qedevice *)ubaddr(&qeaddr[unit])) == 0
        !           234:        ||  badaddr(&addr->qe_sta_addr[0], sizeof(short))) {
        !           235:                printf("deqna %d absent\n", unit);
        !           236:                return (0);
        !           237:        }
        !           238:        qp->intvec = qeaddr[unit].vec;
        !           239:        qp->ubno = qeaddr[unit].ubno;
        !           240:        if (qp->iobuf == NULL) {
        !           241:                qp->iobuf = geteblk();
        !           242:                qp->iobm = ubmbuf(qp->ubno, qp->iobuf, 0);
        !           243:                ua = ubadbuf(qp->ubno, qp->iobuf, qp->iobm);
        !           244:                qp->rring = ((struct qeio *)(qp->iobuf->b_un.b_addr))->rring;
        !           245:                qp->xring = ((struct qeio *)(qp->iobuf->b_un.b_addr))->xring;
        !           246:                qp->setup = &((struct qeio *)(qp->iobuf->b_un.b_addr))->setup;
        !           247:                qp->raddr = (uaddr_t)((struct qeio *)ua)->rring;
        !           248:                qp->xaddr = (uaddr_t)((struct qeio *)ua)->xring;
        !           249:                qp->setupaddr = (uaddr_t)&((struct qeio *)ua)->setup;
        !           250:        }
        !           251:        qp->addr = addr;
        !           252:        addr->qe_csr = QE_RESET;
        !           253:        addr->qe_csr = 0;       /* clear RESET to make reset happen */
        !           254:        qemkrings(qp);
        !           255:        qemksetup(qp);
        !           256:        qeenable(qp);
        !           257:        return (1);
        !           258: }
        !           259: 
        !           260: /*
        !           261:  * make the setup packet
        !           262:  * receive from our address, and from the broadcast address
        !           263:  */
        !           264: qemksetup(qp)
        !           265:        register struct qe *qp;
        !           266: {
        !           267:        register struct setup *sp;
        !           268:        register int i, j;
        !           269: 
        !           270:        sp = qp->setup;
        !           271:        /*
        !           272:         * fetch our Ethernet address into column 1
        !           273:         * toss the broadcast address into column 2
        !           274:         * copy our address into the rest of the first half
        !           275:         * duplicate first half into second
        !           276:         * columns 0 and 8 are junk
        !           277:         */
        !           278:        for (i = 0; i < ETHERALEN; i++)
        !           279:                sp->d[i][1] = qp->addr->qe_sta_addr[i];
        !           280: #ifndef NOTDEF
        !           281:        for (i = 0; i < ETHERALEN; i++)
        !           282:                sp->d[i][2] = 0xff;             /* the broadcast addr */
        !           283:        for (i = 0; i < ETHERALEN; i++)
        !           284:                for (j = 3; j < 8; j++)
        !           285:                        sp->d[i][j] = sp->d[i][1];
        !           286: #else
        !           287:        for (i = 0; i < ETHERALEN; i++)
        !           288:                for (j = 2; j < 8; j++)
        !           289:                        sp->d[i][j] = sp->d[i][1];
        !           290: #endif
        !           291:        bcopy(&sp->d[0][0], &sp->d[8][0], 8*8);
        !           292: }
        !           293: 
        !           294: /*
        !           295:  * output put routine
        !           296:  * treasure up data till a DELIM comes,
        !           297:  * then send it all as one packet
        !           298:  */
        !           299: qeput(q, bp)
        !           300:        register struct queue *q;
        !           301:        struct block *bp;
        !           302: {
        !           303:        register struct qechan *cp=(struct qechan *)q->ptr;
        !           304:        int s;
        !           305: 
        !           306:        switch (bp->type) {
        !           307:        case M_IOCTL:
        !           308:                qeioctl(q, bp);
        !           309:                return;
        !           310: 
        !           311:        case M_DATA:
        !           312:                putq(q, bp);
        !           313:                if (bp->class&S_DELIM)
        !           314:                        break;
        !           315:                return;
        !           316: 
        !           317:        default:
        !           318:                freeb(bp);
        !           319:                return;
        !           320:        }
        !           321:        s = spl6();
        !           322:        qestagepacket(cp);
        !           323:        while (qexmtpacket(&qe[cp->unit])==0)
        !           324:                ;
        !           325:        splx(s);
        !           326: }
        !           327: 
        !           328: qeioctl(q, bp)
        !           329: register struct queue *q;
        !           330: register struct block *bp;
        !           331: {
        !           332:        register struct qechan *cp;
        !           333:        int i;
        !           334:        char *ap;
        !           335: 
        !           336:        cp = (struct qechan *)q->ptr;
        !           337:        bp->type = M_IOCACK;
        !           338:        switch(stiocom(bp)){
        !           339:        case ENIOTYPE:
        !           340:                cp->type = *((int *)stiodata(bp));
        !           341:                break;
        !           342: 
        !           343:        case ENIOPROM:
        !           344:                qexmtsetup(&qe[cp->unit], PROM, 1);
        !           345:                break;
        !           346: 
        !           347:        case ENIOADDR:
        !           348:                for (ap=stiodata(bp), i=0; i<ETHERALEN; i++) 
        !           349:                        *ap++ = qe[cp->unit].addr->qe_sta_addr[i];
        !           350:                bp->wptr = bp->rptr + ETHERALEN + STIOCHDR;
        !           351:                break;
        !           352: 
        !           353:        default:
        !           354:                bp->type = M_IOCNAK;
        !           355:                break;
        !           356:        }
        !           357:        qreply(q, bp);
        !           358: }
        !           359: 
        !           360: /*
        !           361:  * primitives for sending/receiving packets
        !           362:  */
        !           363: 
        !           364: /*
        !           365:  * make a descriptor invalid
        !           366:  */
        !           367: qeinvaldesc(rp)
        !           368:        register struct qe_ring *rp;
        !           369: {
        !           370:        bzero((caddr_t)rp, sizeof(struct qe_ring));
        !           371: }
        !           372: 
        !           373: /*
        !           374:  * set up a buffer descriptor
        !           375:  * tflags are the ones in hiaddr,
        !           376:  * like `setup packet'
        !           377:  */
        !           378: qefilldesc(rp, addr, len, tflags)
        !           379:        register struct qe_ring *rp;
        !           380:        uaddr_t addr;
        !           381:        int len;
        !           382:        int tflags;
        !           383: {
        !           384: 
        !           385:        rp->hiaddr = tflags;
        !           386:        if (addr & 1) {
        !           387:                len++;
        !           388:                addr--;
        !           389:                rp->hiaddr |= DBEGODD;
        !           390:        }
        !           391:        if (len & 1) {
        !           392:                len++;
        !           393:                rp->hiaddr |= DENDODD;
        !           394:        }
        !           395:        rp->len = -(len/2);
        !           396:        rp->loaddr = addr;
        !           397:        rp->hiaddr |= addr >> 16;
        !           398:        rp->status2 = S2MAGIC;          /* something meaningless */
        !           399:        rp->status1 = NOTYET;
        !           400:        rp->flag = FREADY;
        !           401:        rp->hiaddr |= DVALID;
        !           402: }
        !           403: 
        !           404: /*
        !           405:  * allocate a receive buffer
        !           406:  * and give it to the DEQNA
        !           407:  * if we're out of descriptors or are using too much memory,
        !           408:  * return quietly
        !           409:  */
        !           410: qercvblock(qp)
        !           411:        register struct qe *qp;
        !           412: {
        !           413:        register uaddr_t a;
        !           414:        register int len;
        !           415:        register struct block *bp;
        !           416: 
        !           417:        if (qp->rbytes>MAX_RCV_BYTES || NEXTRCV(qp->rindex)==qp->orindex)
        !           418:                return -1;
        !           419:        if ((bp = allocb(ETHERMAXTU))==NULL)
        !           420:                panic("qercvblock");
        !           421:        qp->rbp[qp->rindex] = bp;
        !           422:        a = ubadwptr(qp->ubno, bp, ubmblk(qe->ubno, bp, 0));
        !           423:        len = bp->lim - bp->wptr;
        !           424:        qefilldesc(&qp->rring[qp->rindex], a, len, 0);
        !           425:        qp->rbytes += len;
        !           426:        if ((qp->addr->qe_csr&QE_RL_INVALID) &&
        !           427:            qp->rring[qp->rindex].status1 == NOTYET) {  /* wake up device */
        !           428:                a = qp->raddr + qp->rindex*sizeof(struct qe_ring);
        !           429:                qp->addr->qe_rcvlist_lo = a;
        !           430:                qp->addr->qe_rcvlist_hi = a >> 16;
        !           431:        }
        !           432:        qp->rindex = NEXTRCV(qp->rindex);
        !           433:        return 0;
        !           434: }
        !           435: 
        !           436: /*
        !           437:  * send a block
        !           438:  */
        !           439: qexmtblock(qp, bp, tflags)
        !           440:        register struct qe *qp;
        !           441:        struct block *bp;
        !           442:        int tflags;
        !           443: {
        !           444:        register uaddr_t a;
        !           445: 
        !           446:        if (qp->xring[qp->xindex].status1 == NOTYET)
        !           447:                panic("qexmitbp");
        !           448:        qp->xbp[qp->xindex] = bp;
        !           449:        a = ubadrptr(qp->ubno, bp, ubmblk(qe->ubno, bp, 0));
        !           450:        qefilldesc(&qp->xring[qp->xindex], a, bp->wptr - bp->rptr, tflags);
        !           451:        if ((qp->addr->qe_csr&QE_XL_INVALID) &&
        !           452:            qp->xring[qp->xindex].status1==NOTYET) {    /* wake up device */
        !           453:                a = qp->xaddr + qp->xindex*sizeof(struct qe_ring);
        !           454:                qp->addr->qe_xmtlist_lo = (short)a;
        !           455:                qp->addr->qe_xmtlist_hi = (short)(a >> 16);
        !           456:        }
        !           457:        qp->xindex = NEXTXMT(qp->xindex);
        !           458: }
        !           459: 
        !           460: /*
        !           461:  * send the setup packet
        !           462:  * -- knows it's the first packet ever sent
        !           463:  */
        !           464: qexmtsetup(qp, cmd, docmd)
        !           465:        register struct qe *qp;
        !           466:        int cmd;
        !           467:        int docmd;
        !           468: {
        !           469:        register uaddr_t a;
        !           470: 
        !           471:        qefilldesc(&qp->xring[qp->xindex], qp->setupaddr,
        !           472:                docmd ? (128+cmd) : sizeof(struct setup), DSETUP|DEND);
        !           473:        if ((qp->addr->qe_csr&QE_XL_INVALID) &&
        !           474:            qp->xring[qp->xindex].status1==NOTYET) {    /* presumably always */
        !           475:                a = qp->xaddr + qp->xindex*sizeof(struct qe_ring);
        !           476:                qp->addr->qe_xmtlist_lo = a;
        !           477:                qp->addr->qe_xmtlist_hi = a >> 16;
        !           478:        }
        !           479:        qp->xindex = NEXTXMT(qp->xindex);
        !           480: }
        !           481: 
        !           482: /*
        !           483:  * init the descriptor rings:
        !           484:  * clear out any stale blocks
        !           485:  * zap all the descriptors
        !           486:  * point the last descriptor at the first,
        !           487:  * forming the ring
        !           488:  */
        !           489: qemkrings(qp)
        !           490:        register struct qe *qp;
        !           491: {
        !           492:        register int i, ch;
        !           493: 
        !           494:        for (i=0; i<QENRCV; i++)
        !           495:                if (qp->rbp[i]) {
        !           496:                        freeb(qp->rbp[i]);
        !           497:                        qp->rbp[i] = NULL;
        !           498:                }
        !           499:        for (i=0; i<QENXMT; i++)
        !           500:                if (qp->xbp[i]) {
        !           501:                        freeb(qp->xbp[i]);
        !           502:                        qp->xbp[i] = NULL;
        !           503:                }
        !           504:        for (ch=0; ch<QENCHAN; ch++) {
        !           505:                qp->chan[ch].nxmt = 0;
        !           506:                for (i=0; i<QENXMT; i++)
        !           507:                        if (qp->chan[ch].xmt[i]) {
        !           508:                                freeb(qp->chan[ch].xmt[i]);
        !           509:                                qp->chan[ch].xmt[i] = NULL;
        !           510:                        }
        !           511:        }
        !           512:        for (i = 0 ; i < QENRCV ; i++)
        !           513:                qeinvaldesc(&qp->rring[i]);
        !           514:        qefilldesc(&qp->rring[QENRCV], qp->raddr, 0, DCHAIN);
        !           515:        for (i = 0 ; i < QENXMT ; i++)
        !           516:                qeinvaldesc(&qp->xring[i]);
        !           517:        qefilldesc(&qp->xring[QENRCV], qp->xaddr, 0, DCHAIN);
        !           518:        qp->lastch = qp->orindex = qp->oxindex = qp->xindex = qp->rindex = 0;
        !           519:        qp->rbytes = 0;
        !           520: }
        !           521: 
        !           522: /*
        !           523:  * turn the receiver on:
        !           524:  * enable the hardware, set up receive buffers
        !           525:  * send a setup packet
        !           526:  */
        !           527: 
        !           528: qeenable(qp)
        !           529: register struct qe *qp;
        !           530: {
        !           531: 
        !           532:        qp->addr->qe_vector = qp->intvec;
        !           533:        qp->addr->qe_csr = qebits;
        !           534:        while (qercvblock(qp)==0)
        !           535:                ;
        !           536:        qexmtsetup(qp, 0, 0);
        !           537:        /*printf("qe csr after enable: %x\n", qp->addr->qe_csr);*/
        !           538: }
        !           539: 
        !           540: /*
        !           541:  * find a staged packet and send it
        !           542:  */
        !           543: qexmtpacket(qp)
        !           544:        register struct qe *qp;
        !           545: {
        !           546:        register int i;
        !           547:        register struct qechan *cp;
        !           548: 
        !           549:        /* Look for a channel that has a packet that will fit */
        !           550:        for(i=NEXTCH(qp->lastch); ; i=NEXTCH(i)) {
        !           551:                cp = &qp->chan[i];
        !           552:                if (cp->nxmt && cp->nxmt<=NFREE(qp))
        !           553:                        break;
        !           554:                if (i==qp->lastch)
        !           555:                        return -1;
        !           556:        }
        !           557:        qp->lastch = i;
        !           558:        qedebug(cp->xmt[0], 1, cp->nbytes);
        !           559:        for (i=0; i<cp->nxmt-1; i++) {          /* send any partial pieces */
        !           560:                qexmtblock(qp, cp->xmt[i], 0);  
        !           561:                cp->xmt[i] = NULL;
        !           562:        }
        !           563:        qexmtblock(qp, cp->xmt[i], DEND);       /* send the last piece */
        !           564:        cp->xmt[i] = NULL;
        !           565:        cp->nxmt = 0;
        !           566:        qestagepacket(cp);      /* stage the next packet for this channel */
        !           567:        return 0;
        !           568: 
        !           569: }
        !           570: 
        !           571: /*
        !           572:  * Here on any interrupt
        !           573:  */
        !           574: qe0int(unit)
        !           575:        int unit;
        !           576: {
        !           577:        register struct qe *qp = &qe[unit];
        !           578:        register int csr;
        !           579: 
        !           580:        csr = qp->addr->qe_csr;
        !           581:        qp->addr->qe_csr = qebits|(csr&INTFLAGS);
        !           582:        if( csr & QE_RCV_INT ) 
        !           583:                qerint(qp);
        !           584:        if( csr & QE_XMIT_INT )
        !           585:                qexint(qp);
        !           586:        if( csr & QE_NEX_MEM_INT )
        !           587:                printf("deqna %d: nxm\n", unit);
        !           588: }
        !           589: 
        !           590: /*
        !           591:  * transmit interrupt:
        !           592:  * free up descriptors and blocks
        !           593:  * DEQNA doesn't hear its own broadcasts,
        !           594:  * so loop them around by hand here
        !           595:  */
        !           596: qexint(qp)
        !           597:        register struct qe *qp;
        !           598: {
        !           599:        register int last;              /* last block of packet */
        !           600:        register int first;             /* first block of packet */
        !           601:        register struct qechan *cp;
        !           602: 
        !           603:        /* loop once per packet */
        !           604:        for(;;) {
        !           605:                /* loop once per block */
        !           606:                first = qp->oxindex;
        !           607:                for (last=first; ; last=NEXTXMT(last)) {
        !           608:                        if (last==qp->xindex || qp->xring[last].status1==NOTYET){
        !           609:                                /*
        !           610:                                 * nothing left
        !           611:                                 */
        !           612:                                while (qexmtpacket(qp)==0)
        !           613:                                        ;
        !           614:                                return;
        !           615:                        }
        !           616:                        if (qp->xring[last].hiaddr & DEND)
        !           617:                                break;
        !           618:                }
        !           619:                /*
        !           620:                 * first -> first descriptor for some packet
        !           621:                 * last -> last descriptor for the same packet
        !           622:                 */
        !           623:                if ((qp->xring[last].status1&ERROR) == 0)
        !           624:                        qp->opackets++;
        !           625:                else {
        !           626:                        printf("deqna %d: xmt err st1 %x st2 %x\n",
        !           627:                                qp - qe,
        !           628:                                qp->xring[last].status1,
        !           629:                                qp->xring[last].status2);
        !           630:                        qp->oerrors++;
        !           631:                }
        !           632:                if (qp->xring[first].hiaddr & DSETUP) { /* skip over setup packet */
        !           633:                        qeinvaldesc(&qp->xring[first]); /* just one desc */
        !           634:                        qp->oxindex = NEXTXMT(last);
        !           635:                        continue;
        !           636:                }
        !           637:                if (qebits&QE_ELOOP)    /* debuggery */
        !           638:                        cp = NULL;
        !           639:                else
        !           640:                        cp = qefindchan(qp, qp->xbp[first], 1);
        !           641: 
        !           642:                /* loop once per block to free (or loop back) packet */
        !           643:                for(last=NEXTXMT(last); first!=last; first=NEXTXMT(first)) {
        !           644:                        /*printf("qexint: removing %d to %x\n", first, cp);*/
        !           645:                        if (cp)
        !           646:                                (*cp->rq->next->qinfo->putp)(cp->rq->next,qp->xbp[first]);
        !           647:                        else
        !           648:                                freeb(qp->xbp[first]);
        !           649:                        qeinvaldesc(&qp->xring[first]);
        !           650:                        qp->xbp[first] = NULL;
        !           651:                }
        !           652:                qp->oxindex = last;
        !           653:        }
        !           654: }
        !           655: 
        !           656: /*
        !           657:  * receiver interrupt:
        !           658:  * hand packet to the channel
        !           659:  * that wants that protocol
        !           660:  */
        !           661: qerint(qp)
        !           662:        register struct qe *qp;
        !           663: {
        !           664:        register int last;              /* last block of packet */
        !           665:        register int first;             /* first block of packet */
        !           666:        register struct qechan *cp;
        !           667:        struct qe_ring *rp;
        !           668:        struct block *bp;
        !           669:        int len;
        !           670: 
        !           671:        /* loop once per packet */
        !           672:        for(;;) {
        !           673:                /* loop once per block */
        !           674:                first = qp->orindex;
        !           675:                for (last=first; ; last=NEXTRCV(last)) {
        !           676:                        if (last==qp->rindex ||
        !           677:                            qp->rring[last].status1==NOTYET) {
        !           678:                                /*
        !           679:                                 * nothing left
        !           680:                                 */
        !           681:                                while(qercvblock(qp)==0)
        !           682:                                        ;
        !           683:                                return;
        !           684:                        }
        !           685:                        if ((qp->rring[last].status1&NOTLAST) == 0)
        !           686:                                break;
        !           687:                }
        !           688:                /*
        !           689:                 * first -> first block of received packet
        !           690:                 * last -> last block of that packet
        !           691:                 */
        !           692:                if (qp->rring[last].status1&ERROR) {
        !           693: #if NOTDEF             /* usually boring */
        !           694:                        printf("deqna %d: rcv err st1 %x st2 %x\n",
        !           695:                                qp - qe,
        !           696:                                qp->rring[last].status1,
        !           697:                                qp->rring[last].status2);
        !           698: #endif
        !           699:                        cp = NULL;
        !           700:                        qp->ierrors++;
        !           701:                } else if (qp->rring[last].status1&ESETUP) { 
        !           702:                        /* printf("qerint: setup\n");*/
        !           703:                        cp = NULL;
        !           704:                } else {
        !           705:                        cp = qefindchan(qp, qp->rbp[first], 0);
        !           706:                        qp->ipackets++;
        !           707:                }
        !           708: 
        !           709:                /* loop once per block to receive packet */
        !           710:                if (cp) {
        !           711:                        rp = &qp->rring[last];
        !           712:                        len = ((rp->status1&RHILEN)|(rp->status2&RLOLEN))+RMINLEN;
        !           713:                        qedebug(qp->rbp[first], 0, len);
        !           714:                }
        !           715:                /* install delimiter */
        !           716: if (qp->rbp[last] == NULL)
        !           717: panic("qerint");
        !           718:                qp->rbp[last]->class |= S_DELIM;
        !           719:                for(last=NEXTRCV(last); first!=last; first=NEXTRCV(first)) {
        !           720:                        /*printf("qerint: received %d to %x\n", first, cp);*/
        !           721:                        bp = qp->rbp[first];
        !           722:                        qp->rbytes -= bp->lim - bp->wptr;
        !           723:                        if (cp) {
        !           724:                                rp = &qp->rring[first];
        !           725:                                if (rp->status1&NOTLAST) {
        !           726:                                        len -= bp->lim-bp->wptr;
        !           727:                                        bp->wptr = bp->lim;
        !           728:                                } else {
        !           729:                                        bp->wptr += len;
        !           730:                                        if (bp->wptr > bp->lim)
        !           731:                                                panic("qerint: length");
        !           732:                                }
        !           733:                                bp = cramb(bp);
        !           734:                                if(cp->rq->next->flag & QFULL)
        !           735:                                        freeb(bp);
        !           736:                                else
        !           737:                                        (*cp->rq->next->qinfo->putp)(cp->rq->next, bp);
        !           738:                        } else
        !           739:                                freeb(bp);
        !           740:                        qeinvaldesc(&qp->rring[first]);
        !           741:                        qp->rbp[first] = NULL;
        !           742:                }
        !           743:                qp->orindex = last;
        !           744:        }
        !           745: }
        !           746: 
        !           747: /*
        !           748:  * find the channel for this input packet
        !           749:  * checklocal means check that the packet was
        !           750:  * addressed to us; used for loopback
        !           751:  */
        !           752: struct qechan *
        !           753: qefindchan(qp, bp, checklocal)
        !           754:        register struct qe *qp;
        !           755:        struct block *bp;
        !           756:        int checklocal;
        !           757: {
        !           758:        register int i;
        !           759:        register struct etherpup *ep=(struct etherpup *)bp->rptr;
        !           760:        register struct qechan *ch;
        !           761: 
        !           762:        /*printf("qefindchan: %x,%x,%x,%x,%x,%x:%d\n", 
        !           763:                ep->dhost[0], ep->dhost[1], ep->dhost[2],
        !           764:                ep->dhost[3], ep->dhost[4], ep->dhost[5],
        !           765:                ep->type);*/
        !           766:        if (checklocal) {
        !           767:                for (i=0; i<ETHERALEN; i++) {
        !           768:                        if (ep->dhost[i]!=qp->setup->d[i][1]
        !           769:                        &&  ep->dhost[i]!=0xff)         /* broadcast */
        !           770:                                return NULL;
        !           771:                }
        !           772:        }
        !           773:        for (i=0, ch=qp->chan; i<QENCHAN; i++, ch++)
        !           774:                if (ch->rq!=NULL && ch->type==ep->type)
        !           775:                        return (ch);
        !           776:        return NULL;
        !           777: }
        !           778: 
        !           779: /*
        !           780:  * stage the next packet for this channel:
        !           781:  * gather the blocks, make sure they look sensible
        !           782:  * printfs are a bit silly
        !           783:  */
        !           784: qestagepacket(cp)
        !           785:        register struct qechan *cp;
        !           786: {
        !           787:        register struct block *bp;
        !           788:        register int blk;
        !           789:        int nbytes;
        !           790:        register struct etherpup *ep;
        !           791:        register struct setup *sp;
        !           792: 
        !           793:        if (cp->nxmt)           /* already have one staged */
        !           794:                return;
        !           795:        blk = 0;
        !           796:        nbytes = 0;
        !           797:        while ((bp = getq(WR(cp->rq))) != NULL) {
        !           798:                if (bp->type != M_DATA)
        !           799:                        panic("qestagepkt");
        !           800:                if (blk >= QENXMT-1) {
        !           801:                        blk = qepullup(cp);
        !           802:                        if (blk >= QENXMT-1) {
        !           803:                                freeb(bp);      /* wrong! but too hard for now */
        !           804:                                continue;
        !           805:                        }
        !           806:                }
        !           807:                cp->xmt[blk++] = bp;
        !           808:                nbytes += bp->wptr-bp->rptr;
        !           809:                if ((bp->class & S_DELIM) == 0)
        !           810:                        continue;
        !           811:                /*
        !           812:                 * have a whole packet
        !           813:                 */
        !           814:                if (nbytes > ETHERMAXTU) {
        !           815:                        printf("deqna %d: packet too long\n", cp->unit);
        !           816:                        break;
        !           817:                }
        !           818:                if (cp->xmt[0]->wptr-cp->xmt[0]->rptr < sizeof(struct etherpup)) {
        !           819:                        printf("deqna %d: too fragmented\n", cp->unit);
        !           820:                        break;
        !           821:                }
        !           822:                if (nbytes < ETHERMINTU)        /* wrong, but do it anyway */
        !           823:                        cp->xmt[blk-1]->wptr += ETHERMINTU-nbytes;
        !           824:                /*
        !           825:                 * force our address into the packet
        !           826:                 * why doesn't the hardware do this?
        !           827:                 */
        !           828:                ep = (struct etherpup *)cp->xmt[0]->rptr;
        !           829:                ep->type = cp->type;
        !           830:                cp->nxmt = blk;
        !           831:                sp = qe[cp->unit].setup;
        !           832:                for(blk=0; blk < ETHERALEN; blk++)
        !           833:                        ep->shost[blk] = sp->d[blk][1];
        !           834:                /*printf("qestagepacket: staged %d\n", cp->nxmt);*/
        !           835:                cp->nbytes = nbytes;
        !           836:                return;
        !           837:        }
        !           838:        /*
        !           839:         * if we come here, something went wrong
        !           840:         * any useful packet has already been removed from the queue
        !           841:         */
        !           842:        if (bp)
        !           843:                freeb(bp);
        !           844:        else if (blk!=0)
        !           845:                printf("deqna %d: stage no delim\n", cp->unit);
        !           846:        while (--blk >= 0)
        !           847:                freeb(cp->xmt[blk]);
        !           848:        cp->nxmt = 0;
        !           849: }
        !           850: 
        !           851: /*
        !           852:  * transmit packet came in too many pieces
        !           853:  * to fit in staging area
        !           854:  * allocate a big block,
        !           855:  * and try to squeeze some pieces into it
        !           856:  * returns the first slot now available for a block,
        !           857:  * QENXMT-1 if no space could be made
        !           858:  *
        !           859:  * assertion: no block we replace is S_DELIM
        !           860:  */
        !           861: 
        !           862: int
        !           863: qepullup(cp)
        !           864: register struct qechan *cp;
        !           865: {
        !           866:        register struct block *newbp, *bp;
        !           867:        register int blk, rep, space;
        !           868:        register int n;
        !           869: 
        !           870:        if ((newbp = allocb(ETHERMAXTU/2)) == NULL)
        !           871:                return (QENXMT-1);
        !           872:        space = newbp->lim - newbp->wptr;
        !           873:        for (blk = 0; blk < QENXMT-1; blk++) {
        !           874:                bp = cp->xmt[blk];
        !           875:                if (bp->wptr - bp->rptr < space)
        !           876:                        break;
        !           877:        }
        !           878:        if (blk >= QENXMT - 1) {        /* no block small enough to fit */
        !           879:                freeb(newbp);
        !           880:                return (blk);
        !           881:        }
        !           882:        /*
        !           883:         * pack as much as possible into newbp
        !           884:         */
        !           885:        rep = blk;
        !           886:        for (; blk < QENXMT-1; blk++) {
        !           887:                bp = cp->xmt[blk];
        !           888:                n = bp->wptr - bp->rptr;
        !           889:                if (n > space)
        !           890:                        break;
        !           891:                bcopy(bp->rptr, newbp->wptr, n);
        !           892:                freeb(bp);
        !           893:                newbp->wptr += n;
        !           894:                space -= n;
        !           895:        }
        !           896:        /*
        !           897:         * slide remaining blocks up
        !           898:         */
        !           899:        cp->xmt[rep++] = newbp;
        !           900:        for (; blk < QENXMT-1; blk++, rep++)
        !           901:                cp->xmt[rep] = cp->xmt[blk];
        !           902:        return (rep);
        !           903: }
        !           904: 
        !           905: /*
        !           906:  * tracing stuff
        !           907:  */
        !           908: 
        !           909: #include "sys/systm.h"         /* for time */
        !           910: 
        !           911: #define QEDEBSIZE 64
        !           912: struct {
        !           913:        time_t  time;
        !           914:        unsigned short code;
        !           915:        struct etherpup pup;
        !           916:        short len;
        !           917: } qed[QEDEBSIZE];
        !           918: 
        !           919: int qei = 0;
        !           920: 
        !           921: qedebug(bp, code, len)
        !           922: register struct block *bp;
        !           923: {
        !           924:        qed[qei].time = time;
        !           925:        qed[qei].code = code;
        !           926:        qed[qei].len = len;
        !           927:        bcopy(bp->rptr, &qed[qei].pup, sizeof(qed[qei].pup));
        !           928:        qei = (qei + 1) % QEDEBSIZE;
        !           929: }

unix.superglobalmegacorp.com

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