|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1985 by Sun Microsystems, Inc. ! 3: */ ! 4: ! 5: #include "ie.h" ! 6: #if NIE > 0 ! 7: /* ! 8: * Sun Intel Ethernet Controller interface ! 9: */ ! 10: ! 11: #include "../h/param.h" ! 12: #include "../h/systm.h" ! 13: #include "../machine/pte.h" ! 14: #include "../h/map.h" ! 15: #include "../h/buf.h" ! 16: #include "../h/vmmac.h" ! 17: #include "../h/conf.h" ! 18: #include "../h/ttyio.h" ! 19: #include "../h/enio.h" ! 20: #include "../h/ttyld.h" ! 21: #include "../h/stream.h" ! 22: #include "../h/ethernet.h" ! 23: ! 24: #include "../sundev/mbvar.h" ! 25: #include "../sundev/iereg.h" ! 26: #include "../sundev/iem.h" ! 27: #include "../sundev/ieob.h" ! 28: ! 29: /* controller types */ ! 30: #define IE_MB 1 /* Multibus */ ! 31: #define IE_OB 2 /* Onboard I/O */ ! 32: ! 33: #define IEOBMEMDFT (40*1024) /* default memory allocated for obie */ ! 34: #define CBCACHESIZ (80) /* size of control block cache */ ! 35: #define OVFLWARNMASK (3) /* overflow count mask before warning */ ! 36: #define NPOOL_RBD 50 ! 37: #define NTRANSBUF 4 /* NUmber of transmit buffers */ ! 38: ! 39: int ieprobe(), ieattach(), iepoll(); ! 40: struct mb_device *ieinfo[NIE]; ! 41: struct mb_driver iedriver = { ! 42: ieprobe, 0, ieattach, 0, 0, iepoll, ! 43: /* take the larger of the two devices */ ! 44: sizeof (struct mie_device), "ie", ieinfo, ! 45: }; ! 46: ! 47: int iebark(), iedog(); ! 48: caddr_t from_ieaddr(); ! 49: ieoff_t to_ieoff(); ! 50: caddr_t from_ieoff(); ! 51: ieaddr_t to_ieaddr(); ! 52: long escbget(), escbput(); ! 53: ieint_t to_ieint(); ! 54: #define from_ieint to_ieint ! 55: ! 56: #define iepages(x) (((x) + IEPAGSIZ-1)>>IEPAGSHIFT) ! 57: ! 58: int iecbcsmall; ! 59: int iecbclarge; ! 60: ! 61: /* ! 62: * Ethernet software status per interface. ! 63: */ ! 64: struct ie_softc { ! 65: /* Added by D.A.K for version 9 compatability */ ! 66: char myetheradr[6]; ! 67: char attached; /* Non zero when ie has been attached */ ! 68: int state; ! 69: int collisions; ! 70: int ierrors, oerrors; ! 71: int ipackets, opackets; ! 72: struct ietfd *es_tfd[NTRANSBUF]; /* transmit TFD */ ! 73: struct ietbd *es_tbd[NTRANSBUF]; /* transmit TBD */ ! 74: caddr_t es_tbuffer[NTRANSBUF]; /* transmit buffer */ ! 75: int es_tfree; /* transmitter bit map */ ! 76: /* Supplied by SUN */ ! 77: struct mie_device *es_mie; /* Multibus board registers */ ! 78: struct obie_device *es_obie; /* On-board registers */ ! 79: caddr_t es_memspace; /* + chip addr = kernel addr */ ! 80: int es_paddr; /* starting page number for board */ ! 81: int es_vmemsize; /* size of multibus mem port */ ! 82: caddr_t es_base; /* our addr of control block base */ ! 83: struct map *es_cbmap; /* rmap for control blocks */ ! 84: struct map *es_memmap; /* rmap for memory */ ! 85: struct map *es_pgmap; /* rmap for 1K page (ND) memory ! 86: accessed thru if_memmap */ ! 87: struct iescb *es_scb; /* SCB ptr */ ! 88: struct iescp *es_scp; /* SCP ptr */ ! 89: struct iecb *es_cbhead; /* CBL head */ ! 90: struct iecb *es_cbtail; /* CBL tail */ ! 91: struct ierfd *es_rfdhead; /* head of RFD list */ ! 92: struct ierfd *es_rfdtail; /* tail of RFD list */ ! 93: struct ierbd *es_rbdhead; /* head of RBD list */ ! 94: struct ierbd *es_rbdtail; /* tail of RBD list */ ! 95: struct ieipack *es_iepavail; /* standby input packets */ ! 96: time_t es_latest; /* latest packet arrival time */ ! 97: int es_obmem; /* total IE_OB main memory */ ! 98: char es_type; /* type of controller */ ! 99: char es_simple; /* doing simple flag */ ! 100: u_int es_runotready; /* RU was not ready counter */ ! 101: u_int es_xmiturun; /* xmit DMA underrun counter */ ! 102: u_int es_dogreset; /* iedog reset counter */ ! 103: u_int es_ieheart; /* heartbeat counter */ ! 104: u_int es_iedefer; /* deferred transmission counter */ ! 105: struct ieierr { ! 106: u_int crc; ! 107: u_int aln; ! 108: u_int rsc; ! 109: u_int ovr; ! 110: } es_ierr; /* input error counters */ ! 111: int es_cbsize; /* control block area size */ ! 112: int es_cbc_lo; /* small block cache pointer */ ! 113: int es_cbc_hi; /* large block cache pointer */ ! 114: u_int es_cbc_ovfl; /* overflow counter */ ! 115: int es_cbcbusy; /* cache is loaded */ ! 116: long es_cbcache[CBCACHESIZ]; /* control block cache */ ! 117: } ie_softc[NIE]; ! 118: ! 119: #define NIECHAN (CHANS_PER_UNIT * NIE) ! 120: struct iechan { ! 121: int unit; ! 122: int packets; ! 123: struct queue *ieq; ! 124: int type; ! 125: } iechan[NIECHAN]; ! 126: ! 127: int nodev(), ieopen(), ieclose(), ieput(), iesrv(); ! 128: static struct qinit ierinit = { nodev, NULL, ieopen, ieclose, 0, 0 }; ! 129: static struct qinit iewinit = { ieput, NULL, ieopen, ieclose, 1514, 0 }; ! 130: /* 1514 bytes is minimum highwater mark to send 1514 byte packets */ ! 131: struct streamtab iesinfo = { &ierinit, &iewinit }; ! 132: ! 133: #define IEMAPSIZ 100 ! 134: struct map iecbmap[NIE][IEMAPSIZ]; ! 135: struct map iememmap[NIE][IEMAPSIZ]; ! 136: struct map iepgmap[NIE][IEMAPSIZ]; ! 137: #define escballoc(es, type, cached) (type *)escbget(es, sizeof(type), cached) ! 138: #define escbfree(es, ptr) escbput(es, sizeof(*ptr), (long)ptr); ! 139: #define escbpin(es, len, addr) rmget(es->es_cbmap, (int)len, (int)addr) ! 140: #define esmemalloc(es, len) rmalloc(es->es_memmap, (long)len) ! 141: #define esmemfree(es, len, ptr) rmfree(es->es_memmap, (long)len, (long)ptr) ! 142: #define esmempin(es, len, addr) rmget(es->es_memmap, (int)len, (int)addr) ! 143: ! 144: /* ! 145: * fixed header size for page alignment of received data buffers ! 146: * this is sizeof(struct ndpack) for ND. (doesn't include ether header) ! 147: */ ! 148: #define OPTHDRSIZ 48 ! 149: #define IPACKOVH 8 /* struct ieipack header overhead */ ! 150: struct ieipack { ! 151: struct ieipack *iep_next; /* next in list; MUST BE FIRST FIELD */ ! 152: struct ie_softc *iep_es; /* assoc ie_softc */ ! 153: char iep_data[1500]; /* the packet */ ! 154: }; ! 155: ! 156: #define IEDELAY 400000 /* delay period (in ms) before giving up */ ! 157: #define IEKLUDGE 20 /* delay period (in ms) to make chip work */ ! 158: ! 159: /* ! 160: * Probe for device. ! 161: */ ! 162: ieprobe(reg, unit) ! 163: caddr_t reg; ! 164: { ! 165: register short *sp; ! 166: struct ie_softc *es = &ie_softc[unit]; ! 167: ! 168: if ((getkpgmap(reg) & PGT_MASK) == PGT_OBIO) { ! 169: register struct obie_device *obie = (struct obie_device *)reg; ! 170: ! 171: /* onboard Ethernet */ ! 172: if (pokec(reg, 0)) ! 173: return (0); ! 174: if (peekc(reg) == -1) ! 175: return (0); ! 176: if (obie->obie_noreset) ! 177: return (0); ! 178: es->es_type = IE_OB; ! 179: } else { ! 180: register struct mie_device *mie = (struct mie_device *)reg; ! 181: ! 182: /* Multibus Ethernet */ ! 183: sp = (short *)mie; ! 184: if (poke(sp, 0)) ! 185: return (0); ! 186: sp = &mie->mie_prom[0]; ! 187: if (poke(sp, 0x6789)) ! 188: return (0); ! 189: if (peek(sp) == 0x6789) ! 190: return (0); ! 191: es->es_type = IE_MB; ! 192: } ! 193: return (1); ! 194: } ! 195: ! 196: /* ! 197: * Interface exists; make available by filling in network interface ! 198: * record. System will initialize the interface when it is ready ! 199: * to accept packets. ! 200: */ ! 201: ieattach(md) ! 202: struct mb_device *md; ! 203: { ! 204: struct ie_softc *es = &ie_softc[md->md_unit]; ! 205: ! 206: if (md->md_intr) /* set up vectored interrupts */ ! 207: *(md->md_intr->v_vptr) = (int)es; ! 208: ! 209: if (es->es_type == IE_OB) { ! 210: es->es_obie = (struct obie_device *)md->md_addr; ! 211: es->es_obmem = IEOBMEMDFT; ! 212: } else { ! 213: es->es_mie = (struct mie_device *)md->md_addr; ! 214: /* ! 215: * magic thru config used to artificially restrict ! 216: * the amount of MBMEM used, as there is only 1 Mb ! 217: * available, making it a scarce resource. ! 218: */ ! 219: switch (md->md_flags) { ! 220: case 0: ! 221: default: ! 222: es->es_vmemsize = 256*1024; ! 223: break; ! 224: case 1: ! 225: es->es_vmemsize = 128*1024; ! 226: break; ! 227: case 2: ! 228: es->es_vmemsize = 64*1024; ! 229: break; ! 230: } ! 231: } ! 232: iechipreset(es); ! 233: localetheraddr(NULL, es->myetheradr); ! 234: ieinit(md->md_unit); ! 235: es->attached = 1; ! 236: } ! 237: ! 238: /* ARGSUSED */ ! 239: ieopen(q, dev) ! 240: register struct queue *q; ! 241: register dev_t dev; ! 242: { ! 243: register struct iechan *ied; ! 244: register struct ie_softc *es; ! 245: register unit; ! 246: ! 247: dev = minor(dev); ! 248: unit = dev / CHANS_PER_UNIT; ! 249: ! 250: if (dev >= NIECHAN) ! 251: return(0); ! 252: if (unit >= NIE) ! 253: return(0); ! 254: ! 255: es = &ie_softc[unit]; ! 256: if(!es->attached) ! 257: return(0); ! 258: ied = &iechan[dev]; ! 259: if (ied->ieq) ! 260: return(0); ! 261: ! 262: ied->unit = unit; ! 263: ied->ieq = q; ! 264: q->ptr = (caddr_t)ied; ! 265: q->flag |= QBIGB | QDELIM; ! 266: WR(q)->ptr = (caddr_t)ied; ! 267: WR(q)->flag |= QBIGB|QDELIM; ! 268: return(1); ! 269: } ! 270: ! 271: ieclose(q) ! 272: register struct queue *q; ! 273: { ! 274: register struct iechan *ied; ! 275: ! 276: ied = (struct iechan *)q->ptr; ! 277: flushq(WR(q), 1); ! 278: ied->ieq = NULL; ! 279: } ! 280: ! 281: ieput(q, bp) ! 282: register struct queue *q; ! 283: register struct block *bp; ! 284: { ! 285: register struct iechan *ied; ! 286: register struct ie_softc *es; ! 287: register unit, s; ! 288: ! 289: ied = (struct iechan *)q->ptr; ! 290: unit = ied->unit; ! 291: es = &ie_softc[unit]; ! 292: ! 293: switch(bp->type) { ! 294: ! 295: case M_IOCTL: ! 296: ieioctl(q, bp); ! 297: return; ! 298: ! 299: case M_DATA: ! 300: putq(q, bp); ! 301: return; ! 302: ! 303: case M_DELIM: ! 304: break; ! 305: ! 306: default: ! 307: freeb(bp); ! 308: return; ! 309: } ! 310: ! 311: putq(q, bp); ! 312: s = splie(); ! 313: ied->packets++; ! 314: if (es->es_tfree) ! 315: iestartout(unit); ! 316: splx(s); ! 317: } ! 318: ! 319: /* ! 320: * Process an ioctl request. ! 321: */ ! 322: ieioctl(q, bp) ! 323: register struct queue *q; ! 324: register struct block *bp; ! 325: { ! 326: register struct iechan *ied; ! 327: register struct ie_softc *es; ! 328: register u_char *msg; ! 329: int unit, cmd; ! 330: ! 331: ied = (struct iechan *)q->ptr; ! 332: unit = ied->unit; ! 333: es = &ie_softc[unit]; ! 334: cmd = ((union stmsg *)(bp->rptr))->ioc1.com; ! 335: msg = (u_char *)&((union stmsg *)(bp->rptr))->ioc1.sb; ! 336: ! 337: bp->type = M_IOCACK; ! 338: switch (cmd) { ! 339: case ENIOADDR: /* get my Ethernet address */ ! 340: bcopy(es->myetheradr, (int *)msg, 6); ! 341: break; ! 342: ! 343: case ENIOTYPE: ! 344: ied->type = *(int *)msg; ! 345: break; ! 346: ! 347: default: ! 348: bp->type = M_IOCNAK; ! 349: break; ! 350: } ! 351: qreply(q, bp); ! 352: } ! 353: ! 354: /* ! 355: * Unresponsive chip alarm. Scheduled by iedog; chip has some number ! 356: * of seconds to execute a nop, else alarm goes off. ! 357: */ ! 358: iebark(es) ! 359: struct ie_softc *es; ! 360: { ! 361: int unit = es - ie_softc; ! 362: ! 363: printf("ie%d: iebark reset\n", unit); ! 364: ieinit(unit); ! 365: } ! 366: ! 367: /* ! 368: * Watchdog (deadman) timer routine, invoked every 10 seconds. ! 369: */ ! 370: iedog(es) ! 371: struct ie_softc *es; ! 372: { ! 373: int unit = es - ie_softc; ! 374: int s = splie(); ! 375: struct iecb *cb; ! 376: int fatal = 0; ! 377: ! 378: /* poll for bus error on obie */ ! 379: if (es->es_type == IE_OB) ! 380: if (es->es_obie->obie_buserr) { ! 381: printf("ie%d: obie buserr reset\n", unit); ! 382: fatal = 1; ! 383: goto reset; ! 384: } ! 385: ! 386: /* ensure cu ok with a nop */ ! 387: cb = escballoc(es, struct iecb, 1); ! 388: if (cb == NULL) ! 389: goto reset; ! 390: bzero((caddr_t)cb, sizeof (struct iecb)); ! 391: cb->ie_cmd = IE_NOP; ! 392: iedocb(es, cb); ! 393: iecustart(es); ! 394: /* some number of seconds delay before iebark */ ! 395: timeout(iebark, (caddr_t)es, hz<<2); ! 396: ! 397: /* ensure ru ok with recent reception */ ! 398: if (es->es_latest + 90 < time) { ! 399: /* restart timeout period */ ! 400: es->es_latest = time; ! 401: goto reset; ! 402: } ! 403: ! 404: timeout(iedog, (caddr_t)es, 10*hz); ! 405: goto exit; ! 406: reset: ! 407: es->es_dogreset++; ! 408: ieinit(unit); ! 409: if (fatal) ! 410: panic("iedog"); ! 411: /* FALL THRU */ ! 412: exit: ! 413: (void) splx(s); ! 414: } ! 415: ! 416: /* ! 417: * Unconditionally restart the interface from ground zero. ! 418: */ ! 419: ieinit(unit) ! 420: int unit; ! 421: { ! 422: struct ie_softc *es = &ie_softc[unit]; ! 423: int s = splie(); ! 424: ! 425: iechipreset(es); ! 426: untimeout(iebark, (caddr_t)es); ! 427: untimeout(iedog, (caddr_t)es); ! 428: ! 429: iedomaps(es); ! 430: if (!iechipinit(es)) ! 431: goto exit; ! 432: iedoaddr(es); ! 433: /* ! 434: * Hang out receive buffers and start any pending writes. ! 435: */ ! 436: ierustart(es); ! 437: iesplice(es); ! 438: iestartout(unit); ! 439: timeout(iedog, (caddr_t)es, 10*hz); ! 440: es->es_latest = time; ! 441: exit: ! 442: (void) splx(s); ! 443: } ! 444: ! 445: /* ! 446: * Handle Polling Ethernet interrupts ! 447: */ ! 448: iepoll() ! 449: { ! 450: register struct ie_softc *es; ! 451: register int found = 0; ! 452: ! 453: for (es = ie_softc; es < &ie_softc[NIE]; es++) { ! 454: switch (es->es_type) { ! 455: case IE_MB: ! 456: if (es->es_mie->mie_pie && es->es_mie->mie_pe) { ! 457: ieparity(es); ! 458: return (1); ! 459: } ! 460: if (es->es_mie->mie_ie == 0) ! 461: continue; ! 462: if (es->es_mie->mie_intr) ! 463: found = 1; ! 464: break; ! 465: case IE_OB: ! 466: if (es->es_obie->obie_buserr) ! 467: panic("ie: bus error"); ! 468: if (es->es_obie->obie_ie == 0) ! 469: continue; ! 470: if (es->es_obie->obie_intr) ! 471: found = 1; ! 472: break; ! 473: default: /* not present */ ! 474: continue; ! 475: } ! 476: /* ! 477: * Since the 82586 can take away an interrupt ! 478: * request after presenting it to the processsor ! 479: * (to facilitate an update of a new interrupt ! 480: * condition in the scb), we also have to check ! 481: * the scb to see if it indicates an interrupt ! 482: * condition from the chip. ! 483: */ ! 484: if (found == 0) { ! 485: register struct iescb *scb = es->es_scb; ! 486: ! 487: if (scb->ie_cx || scb->ie_fr || ! 488: scb->ie_cnr || scb->ie_rnr) ! 489: found = 1; ! 490: } ! 491: if (found) { ! 492: ieintr(es); ! 493: break; ! 494: } ! 495: } ! 496: return (found); ! 497: } ! 498: ! 499: /* ! 500: * Handle Ethernet interrupts ! 501: */ ! 502: ieintr(es) ! 503: register struct ie_softc *es; ! 504: { ! 505: register struct iescb *scb; ! 506: register int cmd, unit; ! 507: ! 508: unit = es - ie_softc; ! 509: scb = es->es_scb; ! 510: iechkcca(scb); ! 511: if (scb->ie_cmd != 0) { ! 512: register struct mb_device *md; ! 513: ! 514: printf("ie%d: lost synch\n", unit); ! 515: iestat(es); ! 516: if (unit >= NIE || (md = ieinfo[unit]) == 0 || ! 517: md->md_alive == 0) ! 518: return; ! 519: ieinit(unit); ! 520: return; ! 521: } ! 522: cmd = 0; ! 523: /* ! 524: * This can be done faster with something like: ! 525: * cmd = (*(short *)scb->ie_cx) & ! 526: * (IECMD_ACK_CX|IECMD_ACK_FR|IECMD_ACK_CNR|IECMD_ACK_RNR); ! 527: */ ! 528: ! 529: if (scb->ie_cx) ! 530: cmd |= IECMD_ACK_CX; ! 531: if (scb->ie_fr) ! 532: cmd |= IECMD_ACK_FR; ! 533: if (scb->ie_cnr) ! 534: cmd |= IECMD_ACK_CNR; ! 535: if (scb->ie_rnr) ! 536: cmd |= IECMD_ACK_RNR; ! 537: if (cmd == 0) { ! 538: printf("ie%d: spurious intr\n", unit); ! 539: cmd = IECMD_ACK_CX+IECMD_ACK_FR+IECMD_ACK_CNR+IECMD_ACK_RNR; ! 540: } ! 541: scb->ie_cmd = cmd; ! 542: ieca(es); ! 543: ! 544: if (cmd & (IECMD_ACK_RNR|IECMD_ACK_FR)) ! 545: ierecv(es); ! 546: if (cmd & (IECMD_ACK_CNR|IECMD_ACK_CX)) ! 547: iecbdone(es); ! 548: ! 549: if (es->es_cbhead && scb->ie_cus == IECUS_IDLE) { ! 550: iechkcca(scb); ! 551: if (es->es_cbhead && scb->ie_cus == IECUS_IDLE && ! 552: !scb->ie_cx && !scb->ie_cnr) ! 553: printf("ie%d: CU out of synch\n", unit); ! 554: } ! 555: } ! 556: ! 557: /* ! 558: * Tell the chip its ethernet address ! 559: */ ! 560: iedoaddr(es) ! 561: register struct ie_softc *es; ! 562: { ! 563: register struct ieiaddr *iad; ! 564: ! 565: iad = escballoc(es, struct ieiaddr, 1); ! 566: if (iad == 0) ! 567: panic("iedoaddr: iad"); ! 568: bzero((caddr_t)iad, sizeof (struct ieiaddr)); ! 569: iad->ieia_cb.ie_cmd = IE_IADDR; ! 570: bcopy(es->myetheradr, iad->ieia_addr, sizeof(es->myetheradr)); ! 571: iesimple(es, &iad->ieia_cb); ! 572: escbfree(es, iad); ! 573: } ! 574: ! 575: /* ! 576: * Move info from driver toward protocol interface ! 577: */ ! 578: ieread(es, rfd) ! 579: register struct ie_softc *es; ! 580: register struct ierfd *rfd; ! 581: { ! 582: int unit = es - ie_softc; ! 583: register struct etherpup *header; ! 584: register struct ierbd *rbd; ! 585: register struct iechan *ied; ! 586: register struct queue *q; ! 587: register struct block *bp; ! 588: register len, min, i; ! 589: register u_char *p; ! 590: short type; ! 591: ! 592: if (!rfd->ierfd_ok) { ! 593: es->ierrors++; ! 594: printf("ie%d: receive error\n", unit); ! 595: return; ! 596: } ! 597: if (rfd->ierfd_rbd == IENORBD) { ! 598: printf("ie%d: runt packet\n", unit); ! 599: es->ierrors++; ! 600: return; ! 601: } ! 602: rbd = (struct ierbd *)from_ieoff(es, (ieoff_t)rfd->ierfd_rbd); ! 603: if (!rbd->ierbd_eof) { /* length > 1500 */ ! 604: printf("ie%d: giant packet\n", unit); ! 605: es->ierrors++; ! 606: return; ! 607: } ! 608: /* ! 609: * Pull packet off interface. ! 610: */ ! 611: header = (struct etherpup *)rfd->ierfd_dhost; ! 612: type = header->type; ! 613: ied = &iechan[unit * CHANS_PER_UNIT]; ! 614: for (i = 0; i < CHANS_PER_UNIT; i++, ied++) ! 615: if (ied->ieq && ied->type == type) ! 616: break; ! 617: if (i >= CHANS_PER_UNIT) ! 618: return; ! 619: q = ied->ieq; ! 620: if (q->next->flag & QFULL) { ! 621: es->ierrors++; ! 622: return; ! 623: } ! 624: len = (rbd->ierbd_cnthi << 8) + rbd->ierbd_cntlo; ! 625: ! 626: /* ! 627: * Splice in the ethernet header ! 628: * Assumes allocb will return a block at least as big as etherpup. ! 629: */ ! 630: bp = allocb(len + sizeof(struct etherpup)); ! 631: *(struct etherpup *)bp->wptr = *header; ! 632: bp->wptr += sizeof(struct etherpup); ! 633: ! 634: /* ! 635: * Now copy the data ! 636: */ ! 637: p = (u_char *)from_ieaddr(es, rbd->ierbd_buf); ! 638: i = MIN(((bp->lim - bp->base) - sizeof(struct etherpup)), len); ! 639: for(;;) { ! 640: len -= i; ! 641: while (i-- > 0) ! 642: *bp->wptr++ = *p++; ! 643: (*q->next->qinfo->putp)(q->next, bp); ! 644: if (len <= 0) ! 645: break; ! 646: bp = allocb(len); ! 647: i = MIN((bp->lim - bp->base), len); ! 648: } ! 649: if (putctl(q->next, M_DELIM)) ! 650: es->ipackets++; ! 651: else ! 652: printf("ierint no DELIM bp\n"); ! 653: } ! 654: ! 655: /* ! 656: * Process completed input packets ! 657: * and recycle resources; ! 658: * only called from interrupt level by ieintr ! 659: */ ! 660: ierecv(es) ! 661: register struct ie_softc *es; ! 662: { ! 663: register struct ierfd *rfd, *nrfd; ! 664: register struct ierbd *rbd, *nrbd; ! 665: register struct iescb *scb = es->es_scb; ! 666: int eof, e; ! 667: ! 668: es->es_latest = time; /* latch arrival time */ ! 669: ! 670: rfd = es->es_rfdhead; ! 671: if (rfd == NULL) /* not initialized */ ! 672: return; ! 673: top: ! 674: while (rfd && rfd->ierfd_done) { ! 675: ieread(es, rfd); ! 676: if (rfd->ierfd_rbd != IENORBD) { ! 677: rbd = (struct ierbd *)from_ieoff(es, ! 678: (ieoff_t)rfd->ierfd_rbd); ! 679: if (rbd != es->es_rbdhead) ! 680: panic("ierecv rbd"); ! 681: while (rbd && rbd->ierbd_used) { ! 682: if (rbd != (struct ierbd *)from_ieoff(es, ! 683: (ieoff_t)es->es_rbdtail->ierbd_next)) ! 684: panic("ierecv rbd list"); ! 685: nrbd = (struct ierbd *)from_ieoff(es, ! 686: (ieoff_t)rbd->ierbd_next); ! 687: rbd->ierbd_el = 1; ! 688: eof = rbd->ierbd_eof; ! 689: *(short *)rbd = 0; ! 690: es->es_rbdtail->ierbd_el = 0; ! 691: es->es_rbdtail = rbd; ! 692: rbd = es->es_rbdhead = nrbd; ! 693: if (eof) ! 694: break; ! 695: } ! 696: } ! 697: if (rfd != (struct ierfd *)from_ieoff(es, ! 698: (ieoff_t)es->es_rfdtail->ierfd_next)) ! 699: panic("ierecv rfd list"); ! 700: nrfd = (struct ierfd *)from_ieoff(es, (ieoff_t)rfd->ierfd_next); ! 701: rfd->ierfd_rbd = IENORBD; ! 702: rfd->ierfd_el = 1; ! 703: *(short *)rfd = 0; ! 704: es->es_rfdtail->ierfd_el = 0; ! 705: es->es_rfdtail = rfd; ! 706: rfd = es->es_rfdhead = nrfd; ! 707: } ! 708: if (e = scb->ie_crcerrs) { /* count of CRC errors */ ! 709: scb->ie_crcerrs = 0; ! 710: e = from_ieint(e); ! 711: es->ierrors += e; ! 712: es->es_ierr.crc += e; ! 713: } ! 714: if (e = scb->ie_alnerrs) { /* count of alignment errors */ ! 715: scb->ie_alnerrs = 0; ! 716: e = from_ieint(e); ! 717: es->ierrors += e; ! 718: es->es_ierr.aln += e; ! 719: } ! 720: if (e = scb->ie_rscerrs) { /* count of discarded packets */ ! 721: scb->ie_rscerrs = 0; ! 722: e = from_ieint(e); ! 723: es->ierrors += e; ! 724: es->es_ierr.rsc += e; ! 725: } ! 726: if (e = scb->ie_ovrnerrs) { /* count of overrun packets */ ! 727: scb->ie_ovrnerrs = 0; ! 728: e = from_ieint(e); ! 729: es->ierrors += e; ! 730: es->es_ierr.ovr += e; ! 731: } ! 732: if (scb->ie_rus == IERUS_READY) /* as expected */ ! 733: return; ! 734: es->es_runotready++; ! 735: /* following test must be made when we know chip is quiet */ ! 736: if (es->es_rfdhead->ierfd_done) /* more snuck in */ ! 737: goto top; ! 738: es->es_rfdhead->ierfd_rbd = to_ieoff(es, (caddr_t)es->es_rbdhead); ! 739: iechkcca(scb); ! 740: scb->ie_rfa = to_ieoff(es, (caddr_t)es->es_rfdhead); ! 741: scb->ie_cmd = IECMD_RU_START; ! 742: ieca(es); ! 743: } ! 744: ! 745: /* ! 746: * Free up the resources after transmitting a packet. ! 747: * Called by iecuclean at splie or hardware level 3. ! 748: */ ! 749: iexmitdone(es, td) ! 750: register struct ie_softc *es; ! 751: register struct ietfd *td; ! 752: { ! 753: int unit = es - ie_softc; ! 754: register int i; ! 755: ! 756: if (td->ietfd_ok) { ! 757: es->collisions += td->ietfd_ncoll; ! 758: es->opackets++; ! 759: if (td->ietfd_defer) es->es_iedefer++; ! 760: if (td->ietfd_heart) es->es_ieheart++; ! 761: } else { ! 762: es->oerrors++; ! 763: if (td->ietfd_xcoll) ! 764: printf("ie%d: Ethernet jammed\n", unit); ! 765: if (td->ietfd_nocarr) ! 766: printf("ie%d: no carrier\n", unit); ! 767: if (td->ietfd_nocts) ! 768: printf("ie%d: no CTS\n", unit); ! 769: if (td->ietfd_underrun) ! 770: es->es_xmiturun++; ! 771: } ! 772: if (!td->ietfd_tbd) ! 773: panic("ie%d: iexmitdone: no tbd"); ! 774: for(i = 0; i < NTRANSBUF; i++) ! 775: if (td == es->es_tfd[i]) ! 776: break; ! 777: if (es->es_tfree & (1 << i)) ! 778: printf("ie%d stray xmit interrupt\n", unit); ! 779: es->es_tfree |= (1 << i); ! 780: } ! 781: ! 782: #define rndtoeven(x) (((x)+1) & ~1) ! 783: /* ! 784: * Start or restart output to wire. ! 785: */ ! 786: iestartout(unit) ! 787: int unit; ! 788: { ! 789: register struct ie_softc *es = &ie_softc[unit]; ! 790: register struct iechan *ied; ! 791: register cnt, i; ! 792: register caddr_t to; ! 793: int count, bufnum; ! 794: struct ietfd *td; ! 795: register struct ietbd *tbd; ! 796: register struct queue *q; ! 797: register struct block *bp, *nbp; ! 798: struct block *head, **bnext; ! 799: ! 800: if (!es->es_tfree) ! 801: goto out; ! 802: ied = &iechan[unit * CHANS_PER_UNIT]; ! 803: for(i = 0; i < CHANS_PER_UNIT; i++, ied++) ! 804: if (ied->ieq && ied->packets > 0) ! 805: break; ! 806: if (i >= CHANS_PER_UNIT) ! 807: goto out; ! 808: ! 809: ied->packets--; ! 810: q = WR(ied->ieq); ! 811: ! 812: /* The packet must be justified to the end of the buffer. ! 813: * Therefore, we have to count the bytes before copying. ! 814: */ ! 815: bnext = &head; ! 816: while (*bnext = bp = getq(q)) { ! 817: if (bp->type == M_DELIM) { ! 818: bp->next = 0; ! 819: break; ! 820: } ! 821: cnt += bp->wptr - bp->rptr; ! 822: bnext = &bp->next; ! 823: } ! 824: bp = head; ! 825: ! 826: /* if there is no ethernet header in packet, throw it out */ ! 827: if (cnt < sizeof(struct etherpup) || ! 828: (bp->wptr - bp->rptr) < sizeof(struct etherpup)) { ! 829: while(bp) { ! 830: nbp = bp->next; ! 831: freeb(bp); ! 832: bp = nbp; ! 833: } ! 834: goto out; ! 835: } ! 836: ! 837: bufnum = ffs(es->es_tfree); ! 838: es->es_tfree &= ~(1 << bufnum); ! 839: td = es->es_tfd[bufnum]; ! 840: tbd = es->es_tbd[bufnum]; ! 841: ! 842: /* Setup the header */ ! 843: bcopy(bp->rptr, (caddr_t)td->ietfd_dhost, 6); /* Dest */ ! 844: bp->rptr += 12; /* Skip src */ ! 845: bcopy(bp->rptr, (caddr_t)&td->ietfd_type, 2); /* Type */ ! 846: bp->rptr += 2; /* Skip src */ ! 847: cnt -= sizeof(struct etherpup); ! 848: ! 849: /* Setup the data */ ! 850: if (cnt > 1500) /* test for too large packets */ ! 851: cnt = 1500; ! 852: count = cnt; ! 853: to = es->es_tbuffer[bufnum]; ! 854: while (cnt > 0 && bp != 0) { ! 855: i = bp->wptr - bp->rptr; ! 856: bcopy(bp->rptr, to, i); ! 857: cnt -= i; ! 858: to += i; ! 859: nbp = bp->next; ! 860: freeb(bp); ! 861: bp = nbp; ! 862: } ! 863: ! 864: if (count < 46) /* test for small packets */ ! 865: count = 46; ! 866: ! 867: /* flush remaining buffers, if any (too large packet: count > 1500) */ ! 868: while (bp) { ! 869: nbp = bp->next; ! 870: freeb(bp); ! 871: bp = nbp; ! 872: } ! 873: ! 874: /* Setup the buffer descriptor */ ! 875: tbd->ietbd_eof = 1; ! 876: tbd->ietbd_next = 0; ! 877: tbd->ietbd_buf = to_ieaddr(es, es->es_tbuffer[bufnum]); ! 878: tbd->ietbd_cntlo = count & 0xFF; ! 879: tbd->ietbd_cnthi = count >> 8; ! 880: td->ietfd_tbd = to_ieoff(es, (caddr_t)tbd); ! 881: td->ietfd_cmd = IE_TRANSMIT; ! 882: iedocb(es, (struct iecb *)td); ! 883: out: ! 884: iecustart(es); ! 885: return; ! 886: } ! 887: ! 888: /* ! 889: * Set the control block area size ! 890: */ ! 891: iesetcbsize(es) ! 892: register struct ie_softc *es; ! 893: { ! 894: int tfds; /* number of tfd's */ ! 895: int tfdsize; /* cbsize for each tfd */ ! 896: int tbufsize; /* cbsize for each tbuf */ ! 897: int rbufs; /* number of rbuf's in cb area */ ! 898: int rbufsize; /* cbsize for each rbuf */ ! 899: int rfds; /* number of rfd's */ ! 900: int rfdsize; /* cbsize for each rfd */ ! 901: int fixed; /* fixed overhead, including slop */ ! 902: ! 903: fixed = sizeof (struct iescp) + sizeof (struct ieiscp) ! 904: + sizeof (struct iescb) + sizeof (struct ieconf) ! 905: + 100; ! 906: tfdsize = sizeof (struct ietfd) + sizeof (struct ietbd); ! 907: tbufsize = sizeof (struct ieipack); ! 908: rbufsize = sizeof (struct ieipack); ! 909: rfdsize = sizeof (struct ierfd) + sizeof (struct ierbd); ! 910: ! 911: switch (es->es_type) { ! 912: case IE_OB: ! 913: tfds = NTRANSBUF; ! 914: rbufs = (es->es_obmem - fixed - tfds * (tfdsize+tbufsize)) / ! 915: (rbufsize + rfdsize); ! 916: break; ! 917: case IE_MB: ! 918: tfds = 50; /* maximum if_snd */ ! 919: /* each rbuf eats into a 2K section of vmemsize */ ! 920: rbufs = min(NPOOL_RBD, (u_int)(es->es_vmemsize>>11)); ! 921: break; ! 922: } ! 923: rfds = rbufs; ! 924: ! 925: es->es_cbsize = fixed ! 926: + tfds * tfdsize ! 927: + rfds * rfdsize; ! 928: } ! 929: ! 930: /* ! 931: * Called by ieinit to (allocate and re)initialize rmap's ! 932: * We need to be careful, since the board may be in use ! 933: * (ieipacks loaned out, pages swapped) ! 934: */ ! 935: iedomaps(es) ! 936: register struct ie_softc *es; ! 937: { ! 938: int unit = es - ie_softc; ! 939: ! 940: iesetcbsize(es); ! 941: bzero((caddr_t)iecbmap[unit], sizeof iecbmap[unit]); ! 942: bzero((caddr_t)iememmap[unit], sizeof iememmap[unit]); ! 943: es->es_cbhead = NULL; ! 944: es->es_cbcbusy = NULL; ! 945: iecbcinit(es); ! 946: ! 947: if (es->es_type == IE_OB) { ! 948: int memall(); ! 949: caddr_t va; ! 950: ! 951: if (es->es_base == 0) { ! 952: va = wmemall(memall, es->es_obmem); ! 953: if (va == 0) ! 954: panic("ieattach: no memory"); ! 955: es->es_base = va; ! 956: } ! 957: va = es->es_base; ! 958: es->es_cbmap = &iecbmap[unit][0]; ! 959: es->es_memmap = es->es_cbmap; ! 960: rminit(es->es_cbmap, (long)es->es_obmem, ! 961: (long)es->es_base, "iecb", IEMAPSIZ); ! 962: es->es_memspace = (caddr_t)KERNELBASE; ! 963: #ifdef sun3 ! 964: /* use the page already set up by the prom monitor */ ! 965: es->es_scp = (struct iescp *)(IESCPADDR+es->es_memspace); ! 966: #else ! 967: /* ! 968: * Remap the [preallocated] virtual page containing ! 969: * the SCP to make it point to the same physical ! 970: * location as va, so that we can muck with the ! 971: * control blocks using the address returned from ! 972: * memall, and the chip can locate the scp at its ! 973: * fixed address ! 974: * Cache note: since we can not, in general, enforce ! 975: * the cache antialiasing separation requirement, we ! 976: * would need to avoid caching this physical page ! 977: */ ! 978: { ! 979: struct pte dummypte; /* for mapin to write on */ ! 980: int paddr = getkpgmap(va) & PG_PFNUM; ! 981: ! 982: mapin(&dummypte, (u_int)btop(IESCPADDR+ ! 983: es->es_memspace), (u_int)paddr, 1, PG_V | PG_KW); ! 984: es->es_scp = (struct iescp *)escbpin(es, ! 985: (long)sizeof (struct iescp), ! 986: (long)es->es_base + (IESCPADDR & PGOFSET)); ! 987: } ! 988: #endif sun3 ! 989: } else { /* IE_MB */ ! 990: register struct mie_device *mie = es->es_mie; ! 991: struct miepg *pg; ! 992: short *ap; ! 993: int i; ! 994: int a, vaddr, paddr; ! 995: int firsttime = es->es_memspace == 0; ! 996: ! 997: if (firsttime) { ! 998: if ((a = rmalloc(kernelmap,(long)btoc(es->es_vmemsize))) ! 999: == 0) { ! 1000: printf("ie%d: no kernelmap for ie memory\n", ! 1001: unit); ! 1002: panic("iedomaps"); ! 1003: } ! 1004: es->es_memspace = (caddr_t)kmxtob(a); ! 1005: } ! 1006: vaddr = (int)es->es_memspace; ! 1007: a = btokmx((struct pte *)vaddr); ! 1008: /* board's mem boundary to byte addr */ ! 1009: paddr = mie->mie_mbmhi << 16; ! 1010: /* preserve pagetype bits and which megabyte its in (for VME) */ ! 1011: es->es_paddr = getkpgmap((caddr_t)mie) & PG_PFNUM; ! 1012: es->es_paddr &= ~(0x100000/NBPG -1); ! 1013: es->es_paddr |= btop(paddr); ! 1014: mapin(&Usrptmap[a], (u_int)btop(vaddr), (u_int)es->es_paddr, ! 1015: (int)btoc(es->es_vmemsize), PG_V | PG_KW); ! 1016: ! 1017: /* clear the board unless in use */ ! 1018: if (firsttime) { ! 1019: ap = (short *)mie->mie_pgmap; ! 1020: for (i=0; i<IEVVSIZ; i++) /* clears mp_p2mem */ ! 1021: *ap++ = 0; ! 1022: for (i=0; i<IEPMEMSIZ/IEPAGSIZ; i++) { ! 1023: mie->mie_pgmap[0].mp_pfnum = i; ! 1024: bzero(es->es_memspace, IEPAGSIZ); ! 1025: } ! 1026: pg = &mie->mie_pgmap[0]; ! 1027: for (i=0; i<es->es_vmemsize/IEPAGSIZ; i++) { ! 1028: pg->mp_swab = 1; ! 1029: pg->mp_pfnum = i; ! 1030: pg++; ! 1031: } ! 1032: ! 1033: /* use last onboard ie page for chip init */ ! 1034: /* (no need to reclaim, since beyond vmemsize) */ ! 1035: pg = &mie->mie_pgmap[IEVVSIZ-1]; ! 1036: pg->mp_swab = 1; ! 1037: pg->mp_pfnum = 0; ! 1038: ! 1039: /* patch potential powerup parity problem */ ! 1040: mie->mie_peack = 1; ! 1041: } ! 1042: ! 1043: es->es_base = es->es_memspace; ! 1044: es->es_cbmap = &iecbmap[unit][0]; ! 1045: rminit(es->es_cbmap, (long)es->es_cbsize, ! 1046: (long)es->es_base, "iecb", IEMAPSIZ); ! 1047: es->es_scp = (struct iescp *)escbpin(es, ! 1048: (long)sizeof (struct iescp), ! 1049: (long)es->es_base + (IESCPADDR & (IEPAGSIZ-1))); ! 1050: es->es_memmap = &iememmap[unit][0]; ! 1051: es->es_pgmap = &iepgmap[unit][0]; ! 1052: /* ! 1053: * if we have enough memory, create a page pool which ! 1054: * can manipulated via if_memmap, say by ND ! 1055: */ ! 1056: if (es->es_vmemsize == 256*1024) { ! 1057: rminit(es->es_memmap, (long)(128*1024-es->es_cbsize), ! 1058: (long)(es->es_memspace+es->es_cbsize), ! 1059: "iemem", IEMAPSIZ); ! 1060: if (firsttime) ! 1061: rminit(es->es_pgmap, (long)(128*1024), ! 1062: (long)(es->es_memspace+128*1024), ! 1063: "iepg", IEMAPSIZ); ! 1064: } else { ! 1065: rminit(es->es_memmap, ! 1066: (long)(es->es_vmemsize-es->es_cbsize), ! 1067: (long)(es->es_memspace+es->es_cbsize), ! 1068: "iemem", IEMAPSIZ); ! 1069: rminit(es->es_pgmap, (long)0, (long)0, ! 1070: "iepg", IEMAPSIZ); ! 1071: } ! 1072: } ! 1073: } ! 1074: ! 1075: /* ! 1076: * Basic 82586 initialization ! 1077: */ ! 1078: int ! 1079: iechipinit(es) ! 1080: register struct ie_softc *es; ! 1081: { ! 1082: int unit = es - ie_softc; ! 1083: struct ieiscp *iscp; ! 1084: struct iescb *scb; ! 1085: struct iecb *cb; ! 1086: struct ieconf *ic; ! 1087: int ok = 0; ! 1088: int gotintr; ! 1089: int i; ! 1090: #ifdef notdef ! 1091: struct ietdr *tdr; ! 1092: #endif ! 1093: ! 1094: if (es->es_scp == 0) { ! 1095: printf("ie%d: scp alloc failed\n", unit); ! 1096: goto exit; ! 1097: } ! 1098: iscp = escballoc(es, struct ieiscp, 0); ! 1099: if (iscp == 0) { ! 1100: printf("ie%d: iscp alloc failed\n", unit); ! 1101: goto exit; ! 1102: } ! 1103: scb = escballoc(es, struct iescb, 0); ! 1104: if (scb == 0) { ! 1105: printf("ie%d: scb alloc failed\n", unit); ! 1106: goto exit; ! 1107: } ! 1108: es->es_scb = scb; ! 1109: ! 1110: reset: ! 1111: bzero((caddr_t)es->es_scp, sizeof (struct iescp)); ! 1112: es->es_scp->ie_iscp = to_ieaddr(es, (caddr_t)iscp); ! 1113: bzero((caddr_t)iscp, sizeof (struct ieiscp)); ! 1114: iscp->ie_busy = 1; ! 1115: iscp->ie_cbbase = to_ieaddr(es, es->es_base); ! 1116: iscp->ie_scb = to_ieoff(es, (caddr_t)scb); ! 1117: bzero((caddr_t)scb, sizeof (struct iescb)); ! 1118: scb->ie_magic = IEMAGIC; ! 1119: /* ! 1120: * Hardware reset the chip. We make the interval from ! 1121: * reset to initial channel attention as small as reasonable ! 1122: * to reduce the risk of scribbling chips getting us. ! 1123: */ ! 1124: switch (es->es_type) { ! 1125: case IE_MB: ! 1126: /* hardware reset already occurred in iechipreset */ ! 1127: break; ! 1128: ! 1129: case IE_OB: ! 1130: es->es_obie->obie_noreset = 1; ! 1131: DELAY(IEKLUDGE); /* REQUIRED */ ! 1132: break; ! 1133: } ! 1134: ieca(es); ! 1135: CDELAY(!iscp->ie_busy, IEDELAY); /* ensure chip eats iscp */ ! 1136: CDELAY(scb->ie_cnr, IEDELAY); /* ensure scb updated too */ ! 1137: gotintr = iewaitintr(es); /* wait for interrupt */ ! 1138: if (iscp->ie_busy || !scb->ie_cnr || !gotintr) { ! 1139: printf("ie%d: init failed:%s%s%s\n", unit, ! 1140: iscp->ie_busy?" iscp busy":"", ! 1141: !scb->ie_cnr ?" no cnr":"", ! 1142: !gotintr ?" no intr":""); ! 1143: goto exit; ! 1144: } ! 1145: if (scb->ie_cus != IECUS_IDLE ) { ! 1146: printf("ie%d: cus not idle after reset\n", unit); ! 1147: iechipreset(es); ! 1148: goto reset; ! 1149: } ! 1150: ! 1151: cb = escballoc(es, struct iecb, 1); ! 1152: if (cb == NULL) { ! 1153: printf("ie%d: cb alloc failed\n", unit); ! 1154: goto exit; ! 1155: } ! 1156: bzero((caddr_t)cb, sizeof (struct iecb)); ! 1157: cb->ie_cmd = IE_DIAGNOSE; ! 1158: iesimple(es, cb); ! 1159: if (!cb->ie_ok) { ! 1160: printf("ie%d: Intel 82586 failed diagnostics\n", unit); ! 1161: escbfree(es, cb); ! 1162: goto exit; ! 1163: } ! 1164: escbfree(es, cb); ! 1165: #ifdef notdef ! 1166: /* skip, since hardware requires quiet net to work */ ! 1167: tdr = escballoc(es, struct ietdr, 1); ! 1168: if (tdr == NULL) { ! 1169: printf("ie%d: tdr alloc failed\n", unit); ! 1170: goto exit; ! 1171: } ! 1172: bzero((caddr_t)tdr, sizeof (struct ietdr)); ! 1173: tdr->ietdr_cb.ie_cmd = IE_TDR; ! 1174: iesimple(es, &tdr->ietdr_cb); ! 1175: if (!tdr->ietdr_ok) { ! 1176: #define TDRCONST 12 /* approx 0.77c/10Mhz */ ! 1177: int dist = (tdr->ietdr_timhi<<8)+tdr->ietdr_timlo; ! 1178: if (dist != 0x7FF) ! 1179: printf("ie%d: link not OK - distance = ~%dm\n", ! 1180: unit, TDRCONST*dist); ! 1181: else ! 1182: printf("ie%d: link not OK\n", unit); ! 1183: escbfree(es, tdr); ! 1184: goto exit; ! 1185: } ! 1186: if (tdr->ietdr_xcvr) printf("ie%d: transceiver bad\n", unit); ! 1187: if (tdr->ietdr_open) printf("ie%d: net not terminated\n", unit); ! 1188: if (tdr->ietdr_shrt) printf("ie%d: net shorted\n", unit); ! 1189: escbfree(es, tdr); ! 1190: #endif notdef ! 1191: ic = escballoc(es, struct ieconf, 1); ! 1192: if (ic == NULL) { ! 1193: printf("ie%d: ic alloc failed\n", unit); ! 1194: goto exit; ! 1195: } ! 1196: iedefaultconf(ic); ! 1197: iesimple(es, &ic->ieconf_cb); ! 1198: escbfree(es, ic); ! 1199: for (i = 0; i < NTRANSBUF; i++) { ! 1200: if ((es->es_tfd[i] = escballoc(es, struct ietfd, 0)) == NULL) { ! 1201: printf("ie%d: tfd alloc failed\n", unit); ! 1202: goto exit; ! 1203: } ! 1204: if ((es->es_tbd[i] = escballoc(es, struct ietbd, 0)) == NULL) { ! 1205: printf("ie%d: tbd alloc failed\n", unit); ! 1206: goto exit; ! 1207: } ! 1208: if ((es->es_tbuffer[i]=(caddr_t)esmemalloc(es, 1500)) ==NULL) { ! 1209: printf("ie%d: tbuffer alloc failed\n", unit); ! 1210: goto exit; ! 1211: } ! 1212: es->es_tfree |= (1 << i); ! 1213: } ! 1214: ok = 1; ! 1215: exit: ! 1216: return (ok); ! 1217: } ! 1218: ! 1219: /* ! 1220: * called by ierustart to create the receiver buffer list ! 1221: */ ! 1222: iegetrbufs(es) ! 1223: register struct ie_softc *es; ! 1224: { ! 1225: caddr_t addr; ! 1226: int count, avail; ! 1227: register int page, last; ! 1228: register struct ieipack *iep; ! 1229: ! 1230: es->es_iepavail = NULL; ! 1231: if (es->es_type == IE_OB) { ! 1232: last = (es->es_obmem-es->es_cbsize) / ! 1233: (sizeof (struct ieipack)) - NTRANSBUF; ! 1234: for (count = 0; count < last; count++) { ! 1235: iep = (struct ieipack *)esmemalloc(es, ! 1236: sizeof (struct ieipack)); ! 1237: if (iep == 0) ! 1238: break; ! 1239: iep->iep_es = es; ! 1240: iep->iep_next = es->es_iepavail; ! 1241: es->es_iepavail = iep; ! 1242: } ! 1243: avail = count; ! 1244: } else { /* IE_MB */ ! 1245: count = NPOOL_RBD; ! 1246: /* XXX not really, since there could be page pool */ ! 1247: last = es->es_vmemsize >> IEPAGSHIFT; ! 1248: /* 2 pages for xmit (vice receive) buffer */ ! 1249: page = iepages(es->es_cbsize) + 2; ! 1250: for (; count > 0 && page < last; page++) { ! 1251: addr = es->es_memspace + page*IEPAGSIZ; ! 1252: addr += IEPAGSIZ - (IPACKOVH + OPTHDRSIZ); ! 1253: if (!esmempin(es, sizeof (struct ieipack), (int)addr)) ! 1254: continue; ! 1255: count--; ! 1256: iep = (struct ieipack *)addr; ! 1257: iep->iep_es = es; ! 1258: iep->iep_next = es->es_iepavail; ! 1259: es->es_iepavail = iep; ! 1260: } ! 1261: avail = NPOOL_RBD - count; ! 1262: } ! 1263: ! 1264: return (avail); ! 1265: } ! 1266: ! 1267: /* ! 1268: * Initialize and start the Receive Unit ! 1269: */ ! 1270: ierustart(es) ! 1271: register struct ie_softc *es; ! 1272: { ! 1273: int unit = es - ie_softc; ! 1274: register struct ierbd *rbd; ! 1275: register struct ierfd *rfd; ! 1276: register struct iescb *scb; ! 1277: register struct ieipack *iep; ! 1278: register int i, nrfd, ninit_rbd; ! 1279: ! 1280: ninit_rbd = iegetrbufs(es); ! 1281: es->es_rbdhead = NULL; ! 1282: for (i = 0; i < ninit_rbd; i++) { ! 1283: if ((iep = es->es_iepavail) == NULL) ! 1284: break; ! 1285: rbd = escballoc(es, struct ierbd, 0); ! 1286: if (rbd == NULL) ! 1287: break; ! 1288: es->es_iepavail = iep->iep_next; ! 1289: *(short *)rbd = 0; ! 1290: if (es->es_rbdhead) { ! 1291: rbd->ierbd_next = to_ieoff(es, (caddr_t)es->es_rbdhead); ! 1292: rbd->ierbd_el = 0; ! 1293: } else { ! 1294: es->es_rbdtail = rbd; ! 1295: rbd->ierbd_next = 0; ! 1296: rbd->ierbd_el = 1; ! 1297: } ! 1298: es->es_rbdhead = rbd; ! 1299: rbd->ierbd_buf = to_ieaddr(es, iep->iep_data); ! 1300: rbd->ierbd_sizehi = 1500 >> 8; ! 1301: rbd->ierbd_sizelo = 1500 & 0xFF; ! 1302: rbd->ierbd_iep = iep; ! 1303: } ! 1304: /* ! 1305: * We allocate one fewer RFD than RBD to ! 1306: * avoid a suspected microcode bug in the chip ! 1307: */ ! 1308: nrfd = i-1; ! 1309: es->es_rbdtail->ierbd_next = to_ieoff(es, (caddr_t)es->es_rbdhead); ! 1310: es->es_rfdhead = NULL; ! 1311: for (i=0; i<nrfd; i++) { ! 1312: rfd = escballoc(es, struct ierfd, 0); ! 1313: if (rfd == NULL) { ! 1314: break; ! 1315: } ! 1316: *(short *)rfd = 0; ! 1317: if (es->es_rfdhead) { ! 1318: rfd->ierfd_next = to_ieoff(es, (caddr_t)es->es_rfdhead); ! 1319: rfd->ierfd_el = 0; ! 1320: } else { ! 1321: es->es_rfdtail = rfd; ! 1322: rfd->ierfd_next = 0; ! 1323: rfd->ierfd_el = 1; ! 1324: } ! 1325: es->es_rfdhead = rfd; ! 1326: rfd->ierfd_susp = 0; ! 1327: rfd->ierfd_rbd = IENORBD; ! 1328: } ! 1329: if (i != nrfd) ! 1330: printf("ie%d: fewer RFD's were allocated than expected\n", ! 1331: unit); ! 1332: es->es_rfdtail->ierfd_next = to_ieoff(es, (caddr_t)es->es_rfdhead); ! 1333: rfd = es->es_rfdhead; ! 1334: rfd->ierfd_rbd = to_ieoff(es, (caddr_t)rbd); ! 1335: scb = es->es_scb; ! 1336: if (scb->ie_rus != IERUS_IDLE) { ! 1337: printf("ie%d: RU not idle??\n", unit); ! 1338: iestat(es); ! 1339: iechkcca(scb); ! 1340: scb->ie_cmd = IECMD_RU_ABORT; ! 1341: ieca(es); ! 1342: } ! 1343: iechkcca(scb); ! 1344: scb->ie_rfa = to_ieoff(es, (caddr_t)rfd); ! 1345: scb->ie_cmd = IECMD_RU_START; ! 1346: ieca(es); ! 1347: CDELAY(scb->ie_rus == IERUS_READY, IEDELAY); ! 1348: if (scb->ie_rus != IERUS_READY) ! 1349: printf("ie%d: RU did not become ready\n", unit); ! 1350: } ! 1351: ! 1352: /* ! 1353: * Put a CB on the CBL ! 1354: */ ! 1355: iedocb(es, cb) ! 1356: register struct ie_softc *es; ! 1357: register struct iecb *cb; ! 1358: { ! 1359: int s = splie(); ! 1360: ! 1361: *(short *)cb = 0; /* clear status bits */ ! 1362: cb->ie_susp = 0; /* clear suspend bit */ ! 1363: cb->ie_el = 1; /* will be reset in iecustart */ ! 1364: cb->ie_intr = 1; ! 1365: cb->ie_next = 0; ! 1366: if (es->es_cbhead) { ! 1367: es->es_cbtail->ie_next = to_ieoff(es, (caddr_t)cb); ! 1368: es->es_cbtail = cb; ! 1369: } else { ! 1370: es->es_cbhead = es->es_cbtail = cb; ! 1371: } ! 1372: (void) splx(s); ! 1373: } ! 1374: ! 1375: /* ! 1376: * Process completed CBs, reclaiming specified storage. ! 1377: * Allocator is responsible for reclaiming other storage. ! 1378: * Called by iecustart at splie. ! 1379: * Called by iecbdone at splie or hardware level 3. ! 1380: */ ! 1381: iecuclean(es) ! 1382: register struct ie_softc *es; ! 1383: { ! 1384: register struct iecb *cb; ! 1385: ! 1386: while ((cb = es->es_cbhead) && cb->ie_done) { ! 1387: if (cb->ie_next) ! 1388: es->es_cbhead = (struct iecb *)from_ieoff(es, ! 1389: (ieoff_t)cb->ie_next); ! 1390: else ! 1391: es->es_cbhead = NULL; ! 1392: switch (cb->ie_cmd) { ! 1393: case IE_TRANSMIT: ! 1394: iexmitdone(es, (struct ietfd *)cb); ! 1395: break; ! 1396: case IE_NOP: ! 1397: untimeout(iebark, (caddr_t)es); ! 1398: escbfree(es, cb); ! 1399: break; ! 1400: default: ! 1401: if (!es->es_simple) ! 1402: printf("ie%d: unknown cmd %x done\n", ! 1403: es-ie_softc, cb->ie_cmd); ! 1404: break; ! 1405: } ! 1406: } ! 1407: } ! 1408: ! 1409: /* ! 1410: * Start the CU with the current CBL ! 1411: */ ! 1412: iecustart(es) ! 1413: register struct ie_softc *es; ! 1414: { ! 1415: register struct iecb *cb; ! 1416: register struct iescb *scb = es->es_scb; ! 1417: int s = splie(); ! 1418: ! 1419: iechkcca(scb); ! 1420: if (es->es_cbhead == NULL || ! 1421: scb->ie_cus == IECUS_READY) { /* still going */ ! 1422: (void) splx(s); ! 1423: return; ! 1424: } ! 1425: iecuclean(es); ! 1426: /* link remaining CBs into continuous list */ ! 1427: if ((cb = es->es_cbhead) == NULL) { ! 1428: (void) splx(s); ! 1429: return; ! 1430: } ! 1431: while (cb && cb->ie_next) { ! 1432: cb->ie_el = 0; ! 1433: cb = (struct iecb *)from_ieoff(es, (ieoff_t)cb->ie_next); ! 1434: } ! 1435: /* start CU */ ! 1436: scb->ie_cbl = to_ieoff(es, (caddr_t)es->es_cbhead); ! 1437: scb->ie_cmd = IECMD_CU_START; ! 1438: ieca(es); ! 1439: (void) splx(s); ! 1440: } ! 1441: ! 1442: /* ! 1443: * Clean up and restart the CBs on the CBL ! 1444: * Called by ieintr at hardware level 3. ! 1445: * Called by iesimple at splie. ! 1446: */ ! 1447: iecbdone(es) ! 1448: register struct ie_softc *es; ! 1449: { ! 1450: ! 1451: iecuclean(es); ! 1452: /* generate more CBs */ ! 1453: iestartout(es - ie_softc); ! 1454: } ! 1455: ! 1456: /* ! 1457: * Do the command simply. ! 1458: * Attempted sleep/wakeup calls, but it refused to work. ! 1459: */ ! 1460: iesimple(es, cb) ! 1461: register struct ie_softc *es; ! 1462: register struct iecb *cb; ! 1463: { ! 1464: register struct iescb *scb = es->es_scb; ! 1465: int s, cmd = 0; ! 1466: ! 1467: es->es_simple++; ! 1468: iedocb(es, cb); ! 1469: iecustart(es); ! 1470: CDELAY(cb->ie_done, IEDELAY); ! 1471: if (!cb->ie_done) { ! 1472: iestat(es); ! 1473: panic("iesimple"); ! 1474: } ! 1475: s = splie(); ! 1476: iechkcca(scb); ! 1477: if (scb->ie_cx) ! 1478: cmd |= IECMD_ACK_CX; ! 1479: if (scb->ie_cnr) ! 1480: cmd |= IECMD_ACK_CNR; ! 1481: scb->ie_cmd = cmd; ! 1482: ieca(es); ! 1483: if (cmd & (IECMD_ACK_CNR|IECMD_ACK_CX)) ! 1484: iecbdone(es); ! 1485: es->es_simple--; ! 1486: (void) splx(s); ! 1487: } ! 1488: ! 1489: /* ! 1490: * Return chip's idea of given address or 0 if not chip accessible ! 1491: */ ! 1492: ieaddr(es, cp) ! 1493: register struct ie_softc *es; ! 1494: caddr_t cp; ! 1495: { ! 1496: int pte; ! 1497: ! 1498: if (es->es_type == IE_OB) { ! 1499: /* onboard ie may only reference obmem */ ! 1500: if ((getkpgmap(cp) & PGT_MASK) != PGT_OBMEM) ! 1501: cp = (caddr_t)0; ! 1502: #ifdef sun3 ! 1503: else if (cp < es->es_memspace) ! 1504: cp = (caddr_t)0; ! 1505: else ! 1506: cp -= (u_long)es->es_memspace; ! 1507: #endif sun3 ! 1508: return ((int)cp); ! 1509: } ! 1510: pte = getkpgmap(cp) & PG_PFNUM; ! 1511: if (pte >= es->es_paddr && pte < es->es_paddr + btoc(es->es_vmemsize)) ! 1512: return ((pte - es->es_paddr) << BSHIFT(0)) + ((int)cp & CLOFSET); ! 1513: return (0); ! 1514: } ! 1515: ! 1516: /* ! 1517: * Check Control Command Acceptance by 82586 ! 1518: */ ! 1519: iechkcca(scb) ! 1520: register struct iescb *scb; ! 1521: { ! 1522: register i; ! 1523: ! 1524: for (i=0; i < IEDELAY; i++) { ! 1525: if (scb->ie_magic != IEMAGIC) ! 1526: panic("ie: scb overwritten"); ! 1527: if (scb->ie_cmd == 0) ! 1528: break; ! 1529: } ! 1530: if (i >= IEDELAY) { ! 1531: printf("ie: cmd not accepted\n"); ! 1532: panic("iechkcca"); ! 1533: } ! 1534: } ! 1535: ! 1536: /* ! 1537: * The control block caching code to bypass rmalloc/rmfree. ! 1538: * It also allows us to check allocated lengths, as well ! 1539: * as aiding instrumentation for verification and tuning. ! 1540: * We have two sizes, small and large. ! 1541: * If the request exceeds the small threshold, we allocate ! 1542: * the larger block. ! 1543: */ ! 1544: ! 1545: #define lo es->es_cbc_lo ! 1546: #define hi es->es_cbc_hi ! 1547: #define cache es->es_cbcache ! 1548: #define ovfl es->es_cbc_ovfl ! 1549: #define small iecbcsmall ! 1550: #define large iecbclarge ! 1551: #define head es->es_cbchain.next ! 1552: #define chain es->es_cbchain ! 1553: ! 1554: /* ! 1555: * Initialize the control block cache ! 1556: */ ! 1557: iecbcinit(es) ! 1558: register struct ie_softc *es; ! 1559: { ! 1560: if (es->es_cbcbusy) ! 1561: iecbcflush(es); ! 1562: lo = -1; ! 1563: hi = CBCACHESIZ; ! 1564: small = sizeof (struct ietbd); ! 1565: large = sizeof (struct ietfd); ! 1566: } ! 1567: ! 1568: /* ! 1569: * cached is a flag used to indicate that the block must be ! 1570: * cached, as it will be freed (for reallocation.) ! 1571: */ ! 1572: long ! 1573: escbget(es, len0, cached) ! 1574: register struct ie_softc *es; ! 1575: int len0; ! 1576: int cached; ! 1577: { ! 1578: long result; ! 1579: int len = rndtoeven(len0); ! 1580: if (!cached) ! 1581: result = (rmalloc(es->es_cbmap, (long)len)); ! 1582: else if (len <= small) ! 1583: if (lo > -1) ! 1584: result = (cache[lo--]); ! 1585: else ! 1586: result = (rmalloc(es->es_cbmap, (long)small)); ! 1587: else if (len <= large) ! 1588: if (hi < CBCACHESIZ) ! 1589: result = (cache[hi++]); ! 1590: else ! 1591: result = (rmalloc(es->es_cbmap, (long)large)); ! 1592: else ! 1593: panic ("escbget"); /* len too large */ ! 1594: ! 1595: if (result == 0 && es->es_cbcbusy) { ! 1596: iecbcflush(es); ! 1597: result = escbget(es, len0, cached); ! 1598: } ! 1599: return (result); ! 1600: } ! 1601: ! 1602: /* ! 1603: * flush the cb cache ! 1604: */ ! 1605: iecbcflush(es) ! 1606: struct ie_softc *es; ! 1607: { ! 1608: printf("WARNING: ie%d: flushing cb cache\n", es - ie_softc); ! 1609: while (lo > -1) ! 1610: rmfree(es->es_cbmap, (long)small, (long)cache[lo--]); ! 1611: while (hi < CBCACHESIZ) ! 1612: rmfree(es->es_cbmap, (long)large, (long)cache[hi++]); ! 1613: es->es_cbcbusy = 0; ! 1614: } ! 1615: ! 1616: long ! 1617: escbput(es, len, ptr) ! 1618: register struct ie_softc *es; ! 1619: int len; ! 1620: long ptr; ! 1621: { ! 1622: int overflow = 0; ! 1623: ! 1624: es->es_cbcbusy = 1; ! 1625: len = rndtoeven(len); ! 1626: if (len <= small) ! 1627: if (lo < hi - 1) ! 1628: cache[++lo] = ptr; ! 1629: else { ! 1630: overflow++; ! 1631: rmfree(es->es_cbmap, (long)small, (long)ptr); ! 1632: } ! 1633: else if (len <= large) ! 1634: if (hi > lo + 1) ! 1635: cache[--hi] = ptr; ! 1636: else { ! 1637: overflow++; ! 1638: rmfree(es->es_cbmap, (long)large, (long)ptr); ! 1639: } ! 1640: else ! 1641: panic("escbput"); ! 1642: ! 1643: if (overflow) { ! 1644: ovfl++; ! 1645: if ((ovfl & OVFLWARNMASK) == 0) { ! 1646: ovfl = 0; ! 1647: printf("ie%d: cache overflowed\n", es - ie_softc); ! 1648: } ! 1649: } ! 1650: } ! 1651: ! 1652: #undef lo ! 1653: #undef hi ! 1654: #undef cache ! 1655: #undef ovfl ! 1656: #undef small ! 1657: #undef large ! 1658: ! 1659: int iefifolim = 12; ! 1660: /* ! 1661: * Set default configuration parameters ! 1662: */ ! 1663: iedefaultconf(ic) ! 1664: register struct ieconf *ic; ! 1665: { ! 1666: bzero((caddr_t)ic, sizeof (struct ieconf)); ! 1667: ic->ieconf_cb.ie_cmd = IE_CONFIG; ! 1668: ic->ieconf_bytes = 12; ! 1669: ic->ieconf_fifolim = iefifolim; ! 1670: ic->ieconf_pream = 2; /* 8 byte preamble */ ! 1671: ic->ieconf_alen = 6; ! 1672: ic->ieconf_acloc = 0; ! 1673: ic->ieconf_space = 96; ! 1674: ic->ieconf_slttmh = 512 >> 8; ! 1675: ic->ieconf_minfrm = 64; ! 1676: ic->ieconf_retry = 15; ! 1677: ic->ieconf_crfilt = 3; ! 1678: } ! 1679: ! 1680: iestat(es) ! 1681: struct ie_softc *es; ! 1682: { ! 1683: register struct iescb *scb = es->es_scb; ! 1684: static char *cus[] = { "idle", "suspended", "ready", "<3>", ! 1685: "<4>", "<5>", "<6>", "<7>" }; ! 1686: static char *rus[] = { "idle", "suspended", "no resources", ! 1687: "<3>", "ready", "<5>", "<6>", "<7>" }; ! 1688: ! 1689: printf("ie%d: scb: ", es - ie_softc); ! 1690: if (scb->ie_cx) printf("cx "); ! 1691: if (scb->ie_fr) printf("fr "); ! 1692: if (scb->ie_cnr) printf("cnr "); ! 1693: if (scb->ie_rnr) printf("rnr "); ! 1694: printf("cus=%s ", cus[scb->ie_cus]); ! 1695: printf("rus=%s\n", rus[scb->ie_rus]); ! 1696: printf("cbl=0x%x rfa=0x%x crc=0x%x aln=0x%x rsc=0x%x ovrn=0x%x\n", ! 1697: scb->ie_cbl, scb->ie_rfa, ! 1698: scb->ie_crcerrs, scb->ie_alnerrs, scb->ie_rscerrs, ! 1699: scb->ie_ovrnerrs); ! 1700: if (scb->ie_cmd) printf("cmd=0x%x\n", scb->ie_cmd & 0xFFFF); ! 1701: } ! 1702: ! 1703: /* ! 1704: * Parity error! Scan entire memory for errors ! 1705: */ ! 1706: ieparity(es) ! 1707: register struct ie_softc *es; ! 1708: { ! 1709: register struct mie_device *mie = es->es_mie; ! 1710: register u_short *s, *e, x; ! 1711: ! 1712: printf("ie%d: parity error src=%d byte=%d addr=%x\n", es-ie_softc, ! 1713: mie->mie_pesrc, mie->mie_pebyte, mie->mie_erraddr); ! 1714: mie->mie_peack = 1; ! 1715: s = (u_short *)es->es_memspace; ! 1716: e = (u_short *)(es->es_memspace + es->es_vmemsize); ! 1717: printf("scanning...\n"); ! 1718: while (s < e) { ! 1719: x = *s; ! 1720: #ifdef lint ! 1721: x = x; ! 1722: #endif ! 1723: if (mie->mie_pe) { ! 1724: printf("off=%x src=%d byte=%d addr=%x\n", ! 1725: (int)s - (int)es->es_memspace, ! 1726: mie->mie_pesrc, mie->mie_pebyte, ! 1727: mie->mie_erraddr); ! 1728: mie->mie_peack = 1; ! 1729: } ! 1730: s++; ! 1731: } ! 1732: printf("done\n"); ! 1733: } ! 1734: ! 1735: /* ! 1736: * Activate the channel attention line ! 1737: */ ! 1738: ieca(es) ! 1739: register struct ie_softc *es; ! 1740: { ! 1741: if (es->es_type == IE_MB) { ! 1742: es->es_mie->mie_ca = 1; ! 1743: es->es_mie->mie_ca = 0; ! 1744: } else { ! 1745: es->es_obie->obie_ca = 1; ! 1746: es->es_obie->obie_ca = 0; ! 1747: } ! 1748: } ! 1749: ! 1750: /* ! 1751: * Wait for an interrupt and relay results ! 1752: */ ! 1753: int ! 1754: iewaitintr(es) ! 1755: register struct ie_softc *es; ! 1756: { ! 1757: register struct obie_device *obie = es->es_obie; ! 1758: register struct mie_device *mie = es->es_mie; ! 1759: int ok; ! 1760: ! 1761: switch (es->es_type) { ! 1762: case IE_OB: ! 1763: CDELAY(obie->obie_intr, IEDELAY); ! 1764: ok = obie->obie_intr; ! 1765: break; ! 1766: ! 1767: case IE_MB: ! 1768: CDELAY(mie->mie_intr, IEDELAY); ! 1769: ok = mie->mie_intr; ! 1770: break; ! 1771: } ! 1772: return (ok); ! 1773: } ! 1774: ! 1775: /* ! 1776: * Cut the chip out of the loop and halt it by starting the reset cycle. ! 1777: * For IE_MB, we must enable pagemaps, hence we complete the reset cycle. ! 1778: */ ! 1779: iechipreset(es) ! 1780: register struct ie_softc *es; ! 1781: { ! 1782: ! 1783: switch (es->es_type) { ! 1784: case IE_MB: ! 1785: es->es_mie->mie_reset = 1; ! 1786: DELAY(IEKLUDGE); /* REQUIRED */ ! 1787: *(char *)&es->es_mie->mie_status = 0; /* power on reset */ ! 1788: break; ! 1789: ! 1790: case IE_OB: ! 1791: *(char *)es->es_obie = 0; /* power on reset */ ! 1792: break; ! 1793: ! 1794: default: ! 1795: panic("iechipreset"); ! 1796: } ! 1797: } ! 1798: ! 1799: /* ! 1800: * Splice the chip into the loop ! 1801: */ ! 1802: iesplice(es) ! 1803: register struct ie_softc *es; ! 1804: { ! 1805: switch (es->es_type) { ! 1806: case IE_MB: ! 1807: es->es_mie->mie_ie = 1; /* enable chip interrupts */ ! 1808: es->es_mie->mie_pie = 1; /* enable parity interrupts */ ! 1809: es->es_mie->mie_noloop = 1; /* enable cable */ ! 1810: break; ! 1811: ! 1812: case IE_OB: ! 1813: es->es_obie->obie_ie = 1; /* enable interrupts */ ! 1814: es->es_obie->obie_noloop = 1; /* enable cable */ ! 1815: break; ! 1816: } ! 1817: } ! 1818: ! 1819: /* ! 1820: * Change 68000 address to Intel 24-bit address. ! 1821: * We take advantage of the fact that all 82586 blocks with 24-bit ! 1822: * addresses have an adjacent unused 8-bit field, and store 32 bits. ! 1823: */ ! 1824: ieaddr_t ! 1825: to_ieaddr(es, cp) ! 1826: struct ie_softc *es; ! 1827: caddr_t cp; ! 1828: { ! 1829: union { ! 1830: int n; ! 1831: char c[4]; ! 1832: } a, b; ! 1833: ! 1834: a.n = ieaddr(es, cp); /* necessary for double mapping */ ! 1835: b.c[0] = a.c[3]; ! 1836: b.c[1] = a.c[2]; ! 1837: b.c[2] = a.c[1]; ! 1838: b.c[3] = 0; ! 1839: return (b.n); ! 1840: } ! 1841: ! 1842: caddr_t ! 1843: from_ieaddr(es, n) ! 1844: struct ie_softc *es; ! 1845: ieaddr_t n; ! 1846: { ! 1847: union { ! 1848: int n; ! 1849: char c[4]; ! 1850: } a, b; ! 1851: ! 1852: a.n = n; ! 1853: b.c[0] = 0; ! 1854: b.c[1] = a.c[2]; ! 1855: b.c[2] = a.c[1]; ! 1856: b.c[3] = a.c[0]; ! 1857: return (es->es_memspace + b.n); ! 1858: } ! 1859: ! 1860: ieoff_t ! 1861: to_ieoff(es, addr) ! 1862: register struct ie_softc *es; ! 1863: caddr_t addr; ! 1864: { ! 1865: union { ! 1866: ieoff_t s; ! 1867: char c[2]; ! 1868: } a, b; ! 1869: ! 1870: a.s = (ieoff_t)(addr - es->es_base); ! 1871: b.c[0] = a.c[1]; ! 1872: b.c[1] = a.c[0]; ! 1873: return (b.s); ! 1874: } ! 1875: ! 1876: caddr_t ! 1877: from_ieoff(es, off) ! 1878: register struct ie_softc *es; ! 1879: ieoff_t off; ! 1880: { ! 1881: union { ! 1882: ieoff_t s; ! 1883: char c[2]; ! 1884: } a, b; ! 1885: ! 1886: a.s = off; ! 1887: b.c[0] = a.c[1]; ! 1888: b.c[1] = a.c[0]; ! 1889: return (es->es_base + b.s); ! 1890: } ! 1891: ! 1892: ieint_t ! 1893: to_ieint(n) ! 1894: ieint_t n; ! 1895: { ! 1896: union { ! 1897: ieint_t s; ! 1898: char c[2]; ! 1899: } a, b; ! 1900: ! 1901: a.s = n; ! 1902: b.c[0] = a.c[1]; ! 1903: b.c[1] = a.c[0]; ! 1904: return (b.s); ! 1905: } ! 1906: #endif NIE > 0
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.