|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.