Annotation of researchv10no/sys/io/deqna.c, revision 1.1.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.