|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1985 by Sun Microsystems, Inc. ! 3: */ ! 4: #include "le.h" ! 5: ! 6: /* ! 7: * AMD Am7990 LANCE Ethernet Controller driver ! 8: */ ! 9: #include "../h/param.h" ! 10: #include "../h/systm.h" ! 11: #include "../machine/pte.h" ! 12: #include "../h/map.h" ! 13: #include "../h/buf.h" ! 14: #include "../h/vmmac.h" ! 15: #include "../h/conf.h" ! 16: #include "../h/ttyio.h" ! 17: #include "../h/enio.h" ! 18: #include "../h/ttyld.h" ! 19: #include "../h/stream.h" ! 20: #include "../h/ethernet.h" ! 21: ! 22: #include "../sundev/mbvar.h" ! 23: #include "../sundev/lereg.h" ! 24: ! 25: #define ETHERMAXP (1500 + sizeof(struct etherpup)) ! 26: ! 27: /* corresponds to minor device numbers (# of servers) */ ! 28: #define CHANS_PER_UNIT 8 ! 29: ! 30: int leprobe(), leattach(), leintr(); ! 31: struct mb_device *leinfo[NLE]; ! 32: struct mb_driver ledriver = { ! 33: leprobe, 0, leattach, 0, 0, leintr, ! 34: sizeof (struct le_device), "le", leinfo, 0, 0, 0, ! 35: }; ! 36: ! 37: /* ! 38: * Transmit and receive buffer layout. ! 39: * The buffer size is chosen to give room for the maximum ether ! 40: * transmission unit, an overrun consisting of the entire fifo ! 41: * contents, and slop that experience indicates is necessary. ! 42: * (The exact amount of slop required is still unknown.) ! 43: */ ! 44: struct lebuf { ! 45: char buffer[MAXBUF]; /* Packet's data */ ! 46: }; ! 47: ! 48: struct leu { ! 49: struct le_device *dev; /* hardware pointer */ ! 50: struct le_init_block *ib; /* Initialization block */ ! 51: struct le_md *rdrp; /* Receive Descriptor Ring Ptr */ ! 52: struct le_md *tdrp; /* Transmit Descriptor Ring Ptr */ ! 53: struct le_md *rdrend; /* Receive Descriptor Ring End */ ! 54: struct le_md *his_rmd; /* Next descriptor in ring */ ! 55: int nrmdp2; /* log(2) Num. Rcv. Msg. Descs. */ ! 56: int ntmdp2; /* log(2) Num. Tran. Msg. Descs. */ ! 57: int nrmds; /* Num. Rcv. Msg. Descs. */ ! 58: int ntmds; /* Num. Xmit. Msg. Descs. */ ! 59: struct lebuf *rbufs; /* Receive Buffers */ ! 60: struct lebuf *tbufs; /* Transmit Buffers */ ! 61: /* Error counters */ ! 62: int frame; /* Receive Framing Errors (dribble) */ ! 63: int crc; /* Receive CRC Errors */ ! 64: int oflo; /* Receive overruns */ ! 65: int uflo; /* Transmit underruns */ ! 66: int retries; /* Transmit retries */ ! 67: int missed; /* Number of missed packets */ ! 68: int noheartbeat; /* Number of nonexistent heartbeats */ ! 69: int ierrors, oerrors; ! 70: int ipackets, opackets; ! 71: char myetheradr[6]; ! 72: char attached; ! 73: char active; ! 74: } leu[NLE]; ! 75: ! 76: #define NLECHAN (CHANS_PER_UNIT * NLE) ! 77: struct lechan { ! 78: struct leu *leu; ! 79: int packets; ! 80: struct queue *q; ! 81: int type; ! 82: } lechan[NLECHAN]; ! 83: ! 84: int nodev(), leopen(), leclose(), leput(); ! 85: static struct qinit lerinit = { nodev, NULL, leopen, leclose, 0, 0 }; ! 86: static struct qinit lewinit = { leput, NULL, leopen, leclose, 1514, 0 }; ! 87: /* 1514 bytes is minimum highwater mark to send 1514 byte packets */ ! 88: struct streamtab lesinfo = { &lerinit, &lewinit }; ! 89: ! 90: /* ! 91: * Resource amounts. ! 92: */ ! 93: /* Numbers of ring descriptors */ ! 94: int le_ntmdp2 = 0; /* 2 ^ 0 = 1 */ ! 95: int le_nrmdp2 = 4; /* 2 ^ 4 = 16 */ ! 96: ! 97: /* ! 98: * Return the address of an adjacent descriptor in the given ring. ! 99: */ ! 100: #define next_rmd(lu,rmdp) ((rmdp) == (lu)->rdrend \ ! 101: ? (lu)->rdrp : ((rmdp) + 1)) ! 102: ! 103: /* ! 104: * Probe for device. ! 105: */ ! 106: leprobe(reg) ! 107: caddr_t reg; ! 108: { ! 109: register struct le_device *le = (struct le_device *)reg; ! 110: ! 111: if (pokec((char *)&le->le_rdp, 0)) ! 112: return (0); ! 113: return (sizeof (struct le_device)); ! 114: } ! 115: ! 116: /* ! 117: * Interface exists: make available by filling in network interface ! 118: * record. System will initialize the interface when it is ready ! 119: * to accept packets. ! 120: */ ! 121: leattach(md) ! 122: struct mb_device *md; ! 123: { ! 124: struct leu *lu = &leu[md->md_unit]; ! 125: ! 126: /* Reset the chip. */ ! 127: lu->dev = (struct le_device *)md->md_addr; ! 128: lu->dev->le_rap = LE_CSR0; ! 129: lu->dev->le_csr = LE_STOP; ! 130: localetheraddr(NULL, lu->myetheradr); ! 131: le_alloc_buffers(lu); ! 132: lu->attached = 1; ! 133: } ! 134: ! 135: /* ARGSUSED */ ! 136: leopen(q, dev) ! 137: register struct queue *q; ! 138: register dev_t dev; ! 139: { ! 140: register struct lechan *led; ! 141: register struct leu *lu; ! 142: register unit; ! 143: ! 144: dev = minor(dev); ! 145: unit = dev / CHANS_PER_UNIT; ! 146: ! 147: if (dev >= NLECHAN) ! 148: return(0); ! 149: if (unit >= NLE) ! 150: return(0); ! 151: ! 152: lu = &leu[unit]; ! 153: if(!lu->attached) ! 154: return(0); ! 155: led = &lechan[dev]; ! 156: if (led->q) ! 157: return(0); ! 158: led->leu = lu; ! 159: led->q = q; ! 160: q->ptr = (caddr_t)led; ! 161: q->flag |= QBIGB | QDELIM; ! 162: WR(q)->ptr = (caddr_t)led; ! 163: WR(q)->flag |= QBIGB|QDELIM; ! 164: return(1); ! 165: } ! 166: ! 167: leclose(q) ! 168: register struct queue *q; ! 169: { ! 170: register struct lechan *led; ! 171: ! 172: led = (struct lechan *)q->ptr; ! 173: flushq(WR(q), 1); ! 174: lechan->q = NULL; ! 175: } ! 176: ! 177: leput(q, bp) ! 178: register struct queue *q; ! 179: register struct block *bp; ! 180: { ! 181: register struct lechan *led; ! 182: register struct leu *lu; ! 183: register s; ! 184: ! 185: led = (struct lechan *)q->ptr; ! 186: lu = led->leu; ! 187: ! 188: switch(bp->type) { ! 189: ! 190: case M_IOCTL: ! 191: leioctl(q, bp); ! 192: return; ! 193: ! 194: case M_DATA: ! 195: putq(q, bp); ! 196: return; ! 197: ! 198: case M_DELIM: ! 199: break; ! 200: ! 201: default: ! 202: freeb(bp); ! 203: return; ! 204: } ! 205: ! 206: putq(q, bp); ! 207: s = splimp(); ! 208: led->packets++; ! 209: if (lu->active == 0) ! 210: lestart(lu); ! 211: splx(s); ! 212: } ! 213: ! 214: /* ! 215: * Grab memory for message descriptors and buffers and set fields ! 216: * in the interfaces's software status structure accordingly. ! 217: */ ! 218: le_alloc_buffers(lu) ! 219: register struct leu *lu; ! 220: { ! 221: int size; ! 222: int memall(); ! 223: caddr_t wmemall(), v; ! 224: ! 225: /* Set numbers of message descriptors. */ ! 226: lu->nrmdp2 = le_nrmdp2; ! 227: lu->ntmdp2 = le_ntmdp2; ! 228: lu->nrmds = 1 << lu->nrmdp2; ! 229: lu->ntmds = 1 << lu->ntmdp2; ! 230: ! 231: size = sizeof(struct le_md) * (lu->nrmds + lu->ntmds) + ! 232: sizeof(struct lebuf) * (lu->nrmds + lu->ntmds) + ! 233: sizeof(struct le_init_block); ! 234: v = wmemall(memall, size); ! 235: ! 236: #define valloc(name, type, num) \ ! 237: (name) = (type *)(v); (v) = (caddr_t)((name)+(num)) ! 238: ! 239: valloc(lu->rdrp, struct le_md , lu->nrmds); ! 240: valloc(lu->tdrp, struct le_md , lu->ntmds); ! 241: valloc(lu->ib, struct le_init_block , 1); ! 242: valloc(lu->rbufs, struct lebuf , lu->nrmds); ! 243: valloc(lu->tbufs, struct lebuf , lu->ntmds); ! 244: ! 245: /* ! 246: * Remember address of last descriptor in the ring for ! 247: * ease of bumping pointers around the ring. ! 248: */ ! 249: lu->rdrend = &((lu->rdrp)[lu->nrmds-1]); ! 250: leinit(lu); ! 251: } ! 252: ! 253: /* ! 254: * Initialization of interface; clear recorded pending ! 255: * operations. ! 256: */ ! 257: leinit(lu) ! 258: register struct leu *lu; ! 259: { ! 260: register struct le_device *le; ! 261: register struct le_init_block *ib; ! 262: register int s; ! 263: register struct lebuf *bp; ! 264: register struct le_md *md; ! 265: int i; ! 266: ! 267: s = splimp(); ! 268: ! 269: le = lu->dev; ! 270: le->le_csr = LE_STOP; /* reset the chip */ ! 271: ! 272: /* ! 273: * Reset message descriptors. ! 274: */ ! 275: lu->his_rmd = lu->rdrp; ! 276: ! 277: /* Construct the initialization block */ ! 278: ib = lu->ib; ! 279: bzero((caddr_t)ib, sizeof (struct le_init_block)); ! 280: ! 281: ib->ib_padr[0] = lu->myetheradr[1]; ! 282: ib->ib_padr[1] = lu->myetheradr[0]; ! 283: ib->ib_padr[2] = lu->myetheradr[3]; ! 284: ib->ib_padr[3] = lu->myetheradr[2]; ! 285: ib->ib_padr[4] = lu->myetheradr[5]; ! 286: ib->ib_padr[5] = lu->myetheradr[4]; ! 287: ! 288: /* No multicast filter yet, FIXME MULTICAST, leave zeros. */ ! 289: ! 290: ib->ib_rdrp.drp_laddr = (long)lu->rdrp; ! 291: ib->ib_rdrp.drp_haddr = (long)lu->rdrp >> 16; ! 292: ib->ib_rdrp.drp_len = (long)lu->nrmdp2; ! 293: ib->ib_tdrp.drp_laddr = (long)lu->tdrp; ! 294: ib->ib_tdrp.drp_haddr = (long)lu->tdrp >> 16; ! 295: ib->ib_tdrp.drp_len = (long)lu->ntmdp2; ! 296: ! 297: /* Clear all the descriptors */ ! 298: bzero((caddr_t)lu->rdrp, lu->nrmds * sizeof (struct le_md)); ! 299: bzero((caddr_t)lu->tdrp, lu->ntmds * sizeof (struct le_md)); ! 300: ! 301: /* Hang out the receive buffers. */ ! 302: for(i = 0; i < lu->nrmds; i++) { ! 303: bp = &lu->rbufs[i]; ! 304: md = &lu->rdrp[i]; ! 305: md->lmd_ladr = (u_short) bp; ! 306: md->lmd_hadr = (long)bp >> 16; ! 307: md->lmd_bcnt = -MAXBUF; ! 308: md->lmd_mcnt = 0; ! 309: md->lmd_flags = LMD_OWN; ! 310: } ! 311: lu->his_rmd == lu->rdrp; ! 312: ! 313: /* Transmit md intialization */ ! 314: for(i = 0; i < lu->ntmds; i++) { ! 315: bp = &lu->tbufs[i]; ! 316: md = &lu->tdrp[i]; ! 317: md->lmd_ladr = (u_short) bp; ! 318: md->lmd_hadr = (long)bp >> 16; ! 319: } ! 320: ! 321: /* Give the init block to the chip */ ! 322: le->le_rap = LE_CSR1; /* select the low address register */ ! 323: le->le_rdp = (long)ib & 0xffff; ! 324: ! 325: le->le_rap = LE_CSR2; /* select the high address register */ ! 326: le->le_rdp = ((long)ib >> 16) & 0xff; ! 327: ! 328: le->le_rap = LE_CSR3; /* Bus Master control register */ ! 329: le->le_rdp = LE_BSWP; ! 330: ! 331: le->le_rap = LE_CSR0; /* main control/status register */ ! 332: le->le_csr = LE_INIT; ! 333: ! 334: for (i = 10000; ! (le->le_csr & LE_IDON); i-- ) ! 335: if (i <= 0) ! 336: panic("le: chip didn't initialize"); ! 337: le->le_csr = LE_IDON; /* Now reset the interrupt */ ! 338: lu->active = 0; ! 339: /* (Re)start the chip. */ ! 340: le->le_csr = LE_STRT | LE_INEA; ! 341: (void) splx(s); ! 342: } ! 343: ! 344: /* ! 345: * Start or restart output on interface. ! 346: * If interface is already active, then this is a nop. ! 347: * If interface is not already active, get another packet ! 348: * to send from the interface queue, and map it to the ! 349: * interface before starting the output. ! 350: */ ! 351: lestart(lu) ! 352: register struct leu *lu; ! 353: { ! 354: register char *to; ! 355: register struct lechan *led; ! 356: register struct queue *q; ! 357: register struct block *bp; ! 358: register count, i; ! 359: struct le_device *le; ! 360: register struct le_md *t; ! 361: ! 362: led = &lechan[(lu - leu) * CHANS_PER_UNIT]; ! 363: for(i = 0; i < CHANS_PER_UNIT; i++, led++) ! 364: if (led->q && led->packets > 0) ! 365: break; ! 366: if (i >= CHANS_PER_UNIT) ! 367: return; ! 368: ! 369: led->packets--; ! 370: q = WR(led->q); ! 371: ! 372: le = (struct le_device *)lu->dev; ! 373: to = lu->tbufs->buffer; ! 374: count = 0; ! 375: while (bp = getq(q)) { ! 376: if (bp->type == M_DELIM) { ! 377: freeb(bp); ! 378: break; ! 379: } ! 380: i = bp->wptr - bp->rptr; ! 381: /* ! 382: * If larger than maximum packet, throw out extra ! 383: */ ! 384: if (count + i > ETHERMAXP) { ! 385: i = ETHERMAXP - count; ! 386: bcopy(bp->rptr, to, i); ! 387: count += i; ! 388: freeb(bp); ! 389: while (bp = getq(q)) { ! 390: if (bp->type == M_DELIM) { ! 391: freeb(bp); ! 392: break; ! 393: } ! 394: freeb(bp); ! 395: } ! 396: break; ! 397: } ! 398: bcopy(bp->rptr, to, i); ! 399: to += i; ! 400: count += i; ! 401: freeb(bp); ! 402: } ! 403: ! 404: /* if there is no ethernet header in packet, throw it out */ ! 405: if (count < sizeof(struct etherpup)) ! 406: return; ! 407: if (count < 60) ! 408: count = 60; ! 409: ! 410: to = lu->tbufs->buffer + 6; ! 411: bcopy(lu->myetheradr, to, 6); ! 412: t = lu->tdrp; ! 413: if (t->lmd_flags & LMD_OWN) ! 414: panic("lestart: tmd ownership conflict"); ! 415: t->lmd_bcnt = -count; ! 416: t->lmd_flags3 = 0; ! 417: t->lmd_flags = 0; ! 418: t->lmd_flags = LMD_STP|LMD_ENP; ! 419: t->lmd_flags |= LMD_OWN; ! 420: lu->active = 1; ! 421: le->le_csr = LE_TDMD | LE_INEA; ! 422: ! 423: } ! 424: ! 425: /* ! 426: * interrupt routine ! 427: */ ! 428: leintr() ! 429: { ! 430: register struct leu *lu; ! 431: register struct le_device *le; ! 432: register struct le_md *lmd; ! 433: register struct mb_device *md; ! 434: int serviced = 0; ! 435: ! 436: lu = leu; ! 437: for (lu = leu; lu < &leu[NLE]; lu++) { ! 438: if (!lu->attached) ! 439: continue; ! 440: le = lu->dev; ! 441: if (!(le->le_csr & LE_INTR)) ! 442: continue; ! 443: ! 444: /* Keep statistics for lack of heartbeat */ ! 445: if (le->le_csr & LE_CERR) { ! 446: le->le_csr = LE_CERR | LE_INEA; ! 447: lu->noheartbeat++; ! 448: } ! 449: ! 450: /* Check for receive activity */ ! 451: if ( (le->le_csr & LE_RINT) && (le->le_csr & LE_RXON) ) { ! 452: /* Pull packets off interface */ ! 453: for (lmd = lu->his_rmd; ! 454: !(lmd->lmd_flags & LMD_OWN); ! 455: lu->his_rmd = lmd = next_rmd(lu, lmd)) { ! 456: serviced = 1; ! 457: le->le_csr = LE_RINT | LE_INEA; ! 458: leread(lu, lmd); ! 459: lmd->lmd_mcnt = 0; ! 460: lmd->lmd_flags = LMD_OWN; ! 461: } ! 462: if (!serviced) ! 463: panic("RINT with buffer owned by chip"); ! 464: } ! 465: ! 466: /* Check for transmit activity */ ! 467: if ((le->le_csr & LE_TINT) && (le->le_csr & LE_TXON)) { ! 468: lmd = lu->tdrp; ! 469: if (lmd->lmd_flags & (TMD_MORE | TMD_ONE)) ! 470: lu->retries++; ! 471: if (lmd->lmd_flags3 & ! 472: (TMD_BUFF|TMD_UFLO|TMD_LCOL|TMD_LCAR|TMD_RTRY)) ! 473: le_xmit_error(lu, lmd->lmd_flags3, le); ! 474: le->le_csr = LE_TINT | LE_INEA; ! 475: lu->active = 0; ! 476: lu->opackets++; ! 477: lestart(lu); ! 478: serviced = 1; ! 479: } ! 480: ! 481: /* ! 482: * Check for errors not specifically related ! 483: * to transmission or reception. ! 484: */ ! 485: if ( (le->le_csr & (LE_BABL|LE_MERR|LE_MISS|LE_TXON|LE_RXON)) ! 486: != (LE_RXON|LE_TXON) ) { ! 487: serviced = 1; ! 488: le_chip_error(lu, le); ! 489: } ! 490: } ! 491: return (serviced); ! 492: } ! 493: ! 494: /* ! 495: * Move info from driver toward protocol interface ! 496: */ ! 497: leread(lu, rmd) ! 498: register struct leu *lu; ! 499: register struct le_md *rmd; ! 500: { ! 501: register struct lechan *led; ! 502: register struct queue *q; ! 503: register struct block *bp; ! 504: register short type; ! 505: register caddr_t from; ! 506: register len, i; ! 507: ! 508: /* Check for packet errors. */ ! 509: if ((rmd->lmd_flags & ~RMD_OFLO) != (LMD_STP|LMD_ENP)) { ! 510: le_rcv_error(lu, rmd->lmd_flags); ! 511: lu->ierrors++; ! 512: return; ! 513: } ! 514: ! 515: /* ! 516: * Get input data length (minus crc) ! 517: */ ! 518: len = rmd->lmd_mcnt - 4; /* subtract off trailing crc */ ! 519: if (len == 0) { ! 520: printf("runt packet\n"); ! 521: lu->ierrors++; ! 522: return; ! 523: } ! 524: ! 525: from = (caddr_t)lu->rbufs[rmd - lu->rdrp].buffer; ! 526: type = ((struct etherpup *)from)->type; ! 527: led = &lechan[(lu - leu) * CHANS_PER_UNIT]; ! 528: for (i = 0; i < CHANS_PER_UNIT; i++, led++) ! 529: if (led->q && led->type == type) ! 530: break; ! 531: if (i >= CHANS_PER_UNIT) ! 532: return; ! 533: q = led->q; ! 534: if (q->next->flag & QFULL) { ! 535: lu->ierrors++; ! 536: return; ! 537: } ! 538: while (len > 0) { ! 539: bp = allocb(len); ! 540: i = MIN((bp->lim - bp->base), len); ! 541: len -= i; ! 542: bcopy(from, bp->wptr, i); ! 543: bp->wptr += i; ! 544: from += i; ! 545: (*q->next->qinfo->putp)(q->next, bp); ! 546: } ! 547: if (putctl(q->next, M_DELIM)) ! 548: lu->ipackets++; ! 549: else ! 550: printf("leread no DELIM bp\n"); ! 551: } ! 552: ! 553: /* ! 554: * Process an ioctl request. ! 555: */ ! 556: leioctl(q, bp) ! 557: register struct queue *q; ! 558: register struct block *bp; ! 559: { ! 560: register struct lechan *led; ! 561: register struct leu *lu; ! 562: register u_char *msg; ! 563: int cmd; ! 564: ! 565: led = (struct lechan *)q->ptr; ! 566: lu = led->leu; ! 567: cmd = ((union stmsg *)(bp->rptr))->ioc1.com; ! 568: msg = (u_char *)&((union stmsg *)(bp->rptr))->ioc1.sb; ! 569: ! 570: bp->type = M_IOCACK; ! 571: switch (cmd) { ! 572: case ENIOADDR: /* get my Ethernet address */ ! 573: bcopy(lu->myetheradr, (int *)msg, 6); ! 574: break; ! 575: ! 576: case ENIOTYPE: ! 577: led->type = *(int *)msg; ! 578: break; ! 579: ! 580: default: ! 581: bp->type = M_IOCNAK; ! 582: break; ! 583: } ! 584: qreply(q, bp); ! 585: } ! 586: ! 587: le_rcv_error(lu, flags) ! 588: struct leu *lu; ! 589: u_char flags; ! 590: { ! 591: if (flags & RMD_FRAM) ! 592: lu->frame++; ! 593: if (flags & RMD_CRC ) ! 594: lu->crc++; ! 595: if (flags & RMD_OFLO) ! 596: lu->oflo++; ! 597: if (flags & RMD_BUFF) ! 598: printf("Receive buffer error - BUFF bit set in rmd\n"); ! 599: if (!(flags & LMD_STP)) ! 600: printf("Received packet with STP bit in rmd cleared\n"); ! 601: if (!(flags & LMD_ENP)) ! 602: printf("Received packet with ENP bit in rmd cleared\n"); ! 603: } ! 604: ! 605: le_xmit_error(lu, flags, le) ! 606: struct leu *lu; ! 607: u_short flags; ! 608: struct le_device *le; ! 609: { ! 610: /* ! 611: * The BUFF bit isn't valid if the RTRY bit is set. ! 612: */ ! 613: if ((flags & (TMD_BUFF | TMD_RTRY)) == TMD_BUFF) ! 614: printf("Transmit buffer error - BUFF bit set in tmd\n"); ! 615: if (flags & TMD_UFLO) { ! 616: printf("Transmit underflow error\n"); ! 617: lu->uflo++; ! 618: } ! 619: if (flags & TMD_LCOL) ! 620: printf("Transmit late collision - net problem?\n"); ! 621: if (flags & TMD_LCAR) ! 622: printf("No carrier - transceiver cable problem?\n"); ! 623: if (flags & TMD_RTRY) ! 624: printf("Transmit retried more than 16 times - net jammed\n"); ! 625: } ! 626: ! 627: /* Handles errors that are reported in the chip's status register */ ! 628: /* ARGSUSED */ ! 629: le_chip_error(lu, le) ! 630: struct leu *lu; ! 631: struct le_device *le; ! 632: { ! 633: register u_short csr = le->le_csr; ! 634: int restart = 0; ! 635: ! 636: if (csr & LE_MISS) { ! 637: lu->missed++; ! 638: le->le_csr = LE_MISS | LE_INEA; ! 639: } ! 640: ! 641: if (csr & LE_BABL) { ! 642: printf("Babble error - sent a packet longer than the maximum length\n"); ! 643: le->le_csr = LE_BABL | LE_INEA; ! 644: } ! 645: /* ! 646: * If a memory error has occurred, both the transmitter ! 647: * and the receiver will have shut down. ! 648: */ ! 649: if (csr & LE_MERR) { ! 650: printf("Memory Error! Ethernet chip memory access timed out\n"); ! 651: le->le_csr = LE_MERR | LE_INEA; ! 652: } ! 653: if ( !(csr & LE_RXON) ) { ! 654: printf("Reception stopped\n"); ! 655: restart++; ! 656: } ! 657: if ( !(csr & LE_TXON) ) { ! 658: printf("Transmission stopped\n"); ! 659: restart++; ! 660: } ! 661: if (restart) { ! 662: le_print_csr(csr); ! 663: leinit(lu); ! 664: } ! 665: } ! 666: ! 667: /* ! 668: * Print out a csr value in a nicely formatted way. ! 669: */ ! 670: le_print_csr (csr) ! 671: register u_short csr; ! 672: { ! 673: printf("csr: %b\n", csr, ! 674: "\20\20ERR\17BABL\16CERR\15MISS\14MERR\13RINT\12TINT\11IDON\10INTR\7INEA\6RXON\5TXON\4TDMD\3STOP\2STRT\1INIT\n"); ! 675: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.