|
|
1.1 ! root 1: /* ! 2: * National Semiconductor DP8390 ! 3: * and SMC 83C90 ! 4: * Network Interface Controller. ! 5: */ ! 6: #include "u.h" ! 7: #include "lib.h" ! 8: #include "mem.h" ! 9: #include "dat.h" ! 10: #include "fns.h" ! 11: #include "io.h" ! 12: ! 13: #include "ether.h" ! 14: ! 15: enum { ! 16: Cr = 0x00, /* command register, all pages */ ! 17: ! 18: Stp = 0x01, /* stop */ ! 19: Sta = 0x02, /* start */ ! 20: Txp = 0x04, /* transmit packet */ ! 21: RDMAread = (1<<3), /* remote DMA read */ ! 22: RDMAwrite = (2<<3), /* remote DMA write */ ! 23: RDMAsend = (3<<3), /* remote DMA send packet */ ! 24: RDMAabort = (4<<3), /* abort/complete remote DMA */ ! 25: Ps0 = 0x40, /* page select */ ! 26: Ps1 = 0x80, /* page select */ ! 27: Page0 = 0x00, ! 28: Page1 = Ps0, ! 29: Page2 = Ps1, ! 30: }; ! 31: ! 32: enum { /* Page 0, read */ ! 33: Clda0 = 0x01, /* current local DMA address 0 */ ! 34: Clda1 = 0x02, /* current local DMA address 1 */ ! 35: Bnry = 0x03, /* boundary pointer (R/W) */ ! 36: Tsr = 0x04, /* transmit status register */ ! 37: Ncr = 0x05, /* number of collisions register */ ! 38: Fifo = 0x06, /* FIFO */ ! 39: Isr = 0x07, /* interrupt status register (R/W) */ ! 40: Crda0 = 0x08, /* current remote DMA address 0 */ ! 41: Crda1 = 0x09, /* current remote DMA address 1 */ ! 42: Rsr = 0x0C, /* receive status register */ ! 43: Cntr0 = 0x0D, /* frame alignment errors */ ! 44: Cntr1 = 0x0E, /* CRC errors */ ! 45: Cntr2 = 0x0F, /* missed packet errors */ ! 46: }; ! 47: ! 48: enum { /* Page 0, write */ ! 49: Pstart = 0x01, /* page start register */ ! 50: Pstop = 0x02, /* page stop register */ ! 51: Tpsr = 0x04, /* transmit page start address */ ! 52: Tbcr0 = 0x05, /* transmit byte count register 0 */ ! 53: Tbcr1 = 0x06, /* transmit byte count register 1 */ ! 54: Rsar0 = 0x08, /* remote start address register 0 */ ! 55: Rsar1 = 0x09, /* remote start address register 1 */ ! 56: Rbcr0 = 0x0A, /* remote byte count register 0 */ ! 57: Rbcr1 = 0x0B, /* remote byte count register 1 */ ! 58: Rcr = 0x0C, /* receive configuration register */ ! 59: Tcr = 0x0D, /* transmit configuration register */ ! 60: Dcr = 0x0E, /* data configuration register */ ! 61: Imr = 0x0F, /* interrupt mask */ ! 62: }; ! 63: ! 64: enum { /* Page 1, read/write */ ! 65: Par0 = 0x01, /* physical address register 0 */ ! 66: Curr = 0x07, /* current page register */ ! 67: Mar0 = 0x08, /* multicast address register 0 */ ! 68: }; ! 69: ! 70: enum { /* Interrupt Status Register */ ! 71: Prx = 0x01, /* packet received */ ! 72: Ptx = 0x02, /* packet transmitted */ ! 73: Rxe = 0x04, /* receive error */ ! 74: Txe = 0x08, /* transmit error */ ! 75: Ovw = 0x10, /* overwrite warning */ ! 76: Cnt = 0x20, /* counter overflow */ ! 77: Rdc = 0x40, /* remote DMA complete */ ! 78: Rst = 0x80, /* reset status */ ! 79: }; ! 80: ! 81: enum { /* Interrupt Mask Register */ ! 82: Prxe = 0x01, /* packet received interrupt enable */ ! 83: Ptxe = 0x02, /* packet transmitted interrupt enable */ ! 84: Rxee = 0x04, /* receive error interrupt enable */ ! 85: Txee = 0x08, /* transmit error interrupt enable */ ! 86: Ovwe = 0x10, /* overwrite warning interrupt enable */ ! 87: Cnte = 0x20, /* counter overflow interrupt enable */ ! 88: Rdce = 0x40, /* DMA complete interrupt enable */ ! 89: }; ! 90: ! 91: enum { /* Data Configuration register */ ! 92: Wts = 0x01, /* word transfer select */ ! 93: Bos = 0x02, /* byte order select */ ! 94: Las = 0x04, /* long address select */ ! 95: Ls = 0x08, /* loopback select */ ! 96: Arm = 0x10, /* auto-initialise remote */ ! 97: Ft1 = (0x00<<5), /* FIFO threshhold select 1 byte/word */ ! 98: Ft2 = (0x01<<5), /* FIFO threshhold select 2 bytes/words */ ! 99: Ft4 = (0x02<<5), /* FIFO threshhold select 4 bytes/words */ ! 100: Ft6 = (0x03<<5), /* FIFO threshhold select 6 bytes/words */ ! 101: }; ! 102: ! 103: enum { /* Transmit Configuration Register */ ! 104: Crc = 0x01, /* inhibit CRC */ ! 105: Lb = 0x02, /* internal loopback */ ! 106: Atd = 0x08, /* auto transmit disable */ ! 107: Ofst = 0x10, /* collision offset enable */ ! 108: }; ! 109: ! 110: enum { /* Transmit Status Register */ ! 111: Ptxok = 0x01, /* packet transmitted */ ! 112: Col = 0x04, /* transmit collided */ ! 113: Abt = 0x08, /* tranmit aborted */ ! 114: Crs = 0x10, /* carrier sense lost */ ! 115: Fu = 0x20, /* FIFO underrun */ ! 116: Cdh = 0x40, /* CD heartbeat */ ! 117: Owc = 0x80, /* out of window collision */ ! 118: }; ! 119: ! 120: enum { /* Receive Configuration Register */ ! 121: Sep = 0x01, /* save errored packets */ ! 122: Ar = 0x02, /* accept runt packets */ ! 123: Ab = 0x04, /* accept broadcast */ ! 124: Am = 0x08, /* accept multicast */ ! 125: Pro = 0x10, /* promiscuous physical */ ! 126: Mon = 0x20, /* monitor mode */ ! 127: }; ! 128: ! 129: enum { /* Receive Status Register */ ! 130: Prxok = 0x01, /* packet received intact */ ! 131: Crce = 0x02, /* CRC error */ ! 132: Fae = 0x04, /* frame alignment error */ ! 133: Fo = 0x08, /* FIFO overrun */ ! 134: Mpa = 0x10, /* missed packet */ ! 135: Phy = 0x20, /* physical/multicast address */ ! 136: Dis = 0x40, /* receiver disabled */ ! 137: Dfr = 0x80, /* deferring */ ! 138: }; ! 139: ! 140: typedef struct { ! 141: uchar status; ! 142: uchar next; ! 143: uchar len0; ! 144: uchar len1; ! 145: } Hdr; ! 146: ! 147: static void ! 148: dp8390disable(Ctlr *ctlr) ! 149: { ! 150: ulong dp8390; ! 151: int timo; ! 152: ! 153: dp8390 = ctlr->card.dp8390; ! 154: /* ! 155: * Stop the chip. Set the Stp bit and wait for the chip ! 156: * to finish whatever was on its tiny mind before it sets ! 157: * the Rst bit. ! 158: * We need the timeout because there may not be a real ! 159: * chip there if this is called when probing for a device ! 160: * at boot. ! 161: */ ! 162: dp8390outb(dp8390+Cr, Page0|RDMAabort|Stp); ! 163: dp8390outb(dp8390+Rbcr0, 0); ! 164: dp8390outb(dp8390+Rbcr1, 0); ! 165: for(timo = 10000; (dp8390inb(dp8390+Isr) & Rst) == 0 && timo; timo--) ! 166: ; ! 167: } ! 168: ! 169: static void ! 170: dp8390ring(Ctlr *ctlr) ! 171: { ! 172: ulong dp8390; ! 173: ! 174: dp8390 = ctlr->card.dp8390; ! 175: dp8390outb(dp8390+Pstart, ctlr->card.pstart); ! 176: dp8390outb(dp8390+Pstop, ctlr->card.pstop); ! 177: dp8390outb(dp8390+Bnry, ctlr->card.pstop-1); ! 178: ! 179: dp8390outb(dp8390+Cr, Page1|RDMAabort|Stp); ! 180: dp8390outb(dp8390+Curr, ctlr->card.pstart); ! 181: dp8390outb(dp8390+Cr, Page0|RDMAabort|Stp); ! 182: ! 183: ctlr->card.nxtpkt = ctlr->card.pstart; ! 184: } ! 185: ! 186: void ! 187: dp8390reset(Ctlr *ctlr) ! 188: { ! 189: ulong dp8390; ! 190: ! 191: dp8390 = ctlr->card.dp8390; ! 192: /* ! 193: * This is the initialisation procedure described ! 194: * as 'mandatory' in the datasheet, with references ! 195: * to the 3Com503 technical reference manual. ! 196: */ ! 197: dp8390disable(ctlr); ! 198: if(ctlr->card.bit16) ! 199: dp8390outb(dp8390+Dcr, Ft4|Ls|Wts); ! 200: else ! 201: dp8390outb(dp8390+Dcr, Ft4|Ls); ! 202: ! 203: dp8390outb(dp8390+Rbcr0, 0); ! 204: dp8390outb(dp8390+Rbcr1, 0); ! 205: ! 206: dp8390outb(dp8390+Tcr, 0); ! 207: dp8390outb(dp8390+Rcr, Mon); ! 208: ! 209: /* ! 210: * Init the ring hardware and software ring pointers. ! 211: * Can't initialise ethernet address as we may not know ! 212: * it yet. ! 213: */ ! 214: dp8390ring(ctlr); ! 215: dp8390outb(dp8390+Tpsr, ctlr->card.tstart); ! 216: ! 217: dp8390outb(dp8390+Isr, 0xFF); ! 218: dp8390outb(dp8390+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe); ! 219: ! 220: /* ! 221: * Leave the chip initialised, ! 222: * but in monitor mode. ! 223: */ ! 224: dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta); ! 225: } ! 226: ! 227: void ! 228: dp8390attach(Ctlr *ctlr) ! 229: { ! 230: /* ! 231: * Enable the chip for transmit/receive. ! 232: * The init routine leaves the chip in monitor ! 233: * mode. Clear the missed-packet counter, it ! 234: * increments while in monitor mode. ! 235: */ ! 236: dp8390outb(ctlr->card.dp8390+Rcr, Ab); ! 237: dp8390inb(ctlr->card.dp8390+Cntr2); ! 238: } ! 239: ! 240: void ! 241: dp8390mode(Ctlr *ctlr, int on) ! 242: { ! 243: /* ! 244: * Set/reset promiscuous mode. ! 245: */ ! 246: if(on) ! 247: dp8390outb(ctlr->card.dp8390+Rcr, Pro|Ab); ! 248: else ! 249: dp8390outb(ctlr->card.dp8390+Rcr, Ab); ! 250: } ! 251: ! 252: void ! 253: dp8390setea(Ctlr *ctlr) ! 254: { ! 255: ulong dp8390; ! 256: uchar cr; ! 257: int i; ! 258: ! 259: dp8390 = ctlr->card.dp8390; ! 260: /* ! 261: * Set the ethernet address into the chip. ! 262: * Take care to restore the command register ! 263: * afterwards. We don't care about multicast ! 264: * addresses as we never set the multicast ! 265: * enable. ! 266: */ ! 267: cr = dp8390inb(dp8390+Cr) & ~Txp; ! 268: dp8390outb(dp8390+Cr, Page1|(~(Ps1|Ps0) & cr)); ! 269: for(i = 0; i < sizeof(ctlr->card.ea); i++) ! 270: dp8390outb(dp8390+Par0+i, ctlr->card.ea[i]); ! 271: dp8390outb(dp8390+Cr, cr); ! 272: } ! 273: ! 274: void ! 275: dp8390getea(Ctlr *ctlr) ! 276: { ! 277: ulong dp8390; ! 278: uchar cr; ! 279: int i; ! 280: ! 281: dp8390 = ctlr->card.dp8390; ! 282: /* ! 283: * Set the ethernet address into the chip. ! 284: * Take care to restore the command register ! 285: * afterwards. We don't care about multicast ! 286: * addresses as we never set the multicast ! 287: * enable. ! 288: */ ! 289: cr = dp8390inb(dp8390+Cr) & ~Txp; ! 290: dp8390outb(dp8390+Cr, Page1|(~(Ps1|Ps0) & cr)); ! 291: for(i = 0; i < sizeof(ctlr->card.ea); i++) ! 292: ctlr->card.ea[i] = dp8390inb(dp8390+Par0+i); ! 293: dp8390outb(dp8390+Cr, cr); ! 294: } ! 295: ! 296: void* ! 297: dp8390read(Ctlr *ctlr, void *to, ulong from, ulong len) ! 298: { ! 299: ulong dp8390; ! 300: uchar cr; ! 301: int timo; ! 302: ! 303: dp8390 = ctlr->card.dp8390; ! 304: /* ! 305: * Read some data at offset 'from' in the card's memory ! 306: * using the DP8390 remote DMA facility, and place it at ! 307: * 'to' in main memory, via the I/O data port. ! 308: */ ! 309: cr = dp8390inb(dp8390+Cr) & ~Txp; ! 310: dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta); ! 311: dp8390outb(dp8390+Isr, Rdc); ! 312: ! 313: /* ! 314: * Set up the remote DMA address and count. ! 315: */ ! 316: if(ctlr->card.bit16) ! 317: len = ROUNDUP(len, 2); ! 318: dp8390outb(dp8390+Rbcr0, len & 0xFF); ! 319: dp8390outb(dp8390+Rbcr1, (len>>8) & 0xFF); ! 320: dp8390outb(dp8390+Rsar0, from & 0xFF); ! 321: dp8390outb(dp8390+Rsar1, (from>>8) & 0xFF); ! 322: ! 323: /* ! 324: * Start the remote DMA read and suck the data ! 325: * out of the I/O port. ! 326: */ ! 327: dp8390outb(dp8390+Cr, Page0|RDMAread|Sta); ! 328: if(ctlr->card.bit16) ! 329: inss(ctlr->card.data, to, len/2); ! 330: else ! 331: insb(ctlr->card.data, to, len); ! 332: ! 333: /* ! 334: * Wait for the remote DMA to complete. The timeout ! 335: * is necessary because we may call this routine on ! 336: * a non-existent chip during initialisation and, due ! 337: * to the miracles of the bus, we could get this far ! 338: * and still be talking to a slot full of nothing. ! 339: */ ! 340: for(timo = 10000; (dp8390inb(dp8390+Isr) & Rdc) == 0 && timo; timo--) ! 341: ; ! 342: ! 343: dp8390outb(dp8390+Isr, Rdc); ! 344: dp8390outb(dp8390+Cr, cr); ! 345: return to; ! 346: } ! 347: ! 348: void* ! 349: dp8390write(Ctlr *ctlr, ulong to, void *from, ulong len) ! 350: { ! 351: ulong dp8390, crda; ! 352: uchar cr; ! 353: ! 354: dp8390 = ctlr->card.dp8390; ! 355: /* ! 356: * Write some data to offset 'to' in the card's memory ! 357: * using the DP8390 remote DMA facility, reading it at ! 358: * 'from' in main memory, via the I/O data port. ! 359: */ ! 360: cr = dp8390inb(dp8390+Cr) & ~Txp; ! 361: dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta); ! 362: dp8390outb(dp8390+Isr, Rdc); ! 363: ! 364: if(ctlr->card.bit16) ! 365: len = ROUNDUP(len, 2); ! 366: ! 367: /* ! 368: * Set up the remote DMA address and count. ! 369: * This is straight from the DP8390[12D] datasheet, hence ! 370: * the initial set up for read. ! 371: */ ! 372: crda = to-1-ctlr->card.bit16; ! 373: dp8390outb(dp8390+Rbcr0, (len+1+ctlr->card.bit16) & 0xFF); ! 374: dp8390outb(dp8390+Rbcr1, ((len+1+ctlr->card.bit16)>>8) & 0xFF); ! 375: dp8390outb(dp8390+Rsar0, crda & 0xFF); ! 376: dp8390outb(dp8390+Rsar1, (crda>>8) & 0xFF); ! 377: dp8390outb(dp8390+Cr, Page0|RDMAread|Sta); ! 378: ! 379: for(;;){ ! 380: crda = dp8390inb(dp8390+Crda0); ! 381: crda |= dp8390inb(dp8390+Crda1)<<8; ! 382: if(crda == to){ ! 383: /* ! 384: * Start the remote DMA write and make sure ! 385: * the registers are correct. ! 386: */ ! 387: dp8390outb(dp8390+Cr, Page0|RDMAwrite|Sta); ! 388: ! 389: crda = dp8390inb(dp8390+Crda0); ! 390: crda |= dp8390inb(dp8390+Crda1)<<8; ! 391: if(crda != to) ! 392: panic("crda write %d to %d\n", crda, to); ! 393: ! 394: break; ! 395: } ! 396: } ! 397: ! 398: /* ! 399: * Pump the data into the I/O port. ! 400: */ ! 401: if(ctlr->card.bit16) ! 402: outss(ctlr->card.data, from, len/2); ! 403: else ! 404: outsb(ctlr->card.data, from, len); ! 405: ! 406: /* ! 407: * Wait for the remote DMA to finish. We'll need ! 408: * a timeout here if this ever gets called before ! 409: * we know there really is a chip there. ! 410: */ ! 411: while((dp8390inb(dp8390+Isr) & Rdc) == 0) ! 412: ; ! 413: ! 414: dp8390outb(dp8390+Isr, Rdc); ! 415: dp8390outb(dp8390+Cr, cr); ! 416: return (void*)to; ! 417: } ! 418: ! 419: static uchar ! 420: getcurr(ulong dp8390) ! 421: { ! 422: uchar cr, curr; ! 423: ! 424: cr = dp8390inb(dp8390+Cr) & ~Txp; ! 425: dp8390outb(dp8390+Cr, Page1|(~(Ps1|Ps0) & cr)); ! 426: curr = dp8390inb(dp8390+Curr); ! 427: dp8390outb(dp8390+Cr, cr); ! 428: return curr; ! 429: } ! 430: ! 431: void ! 432: dp8390receive(Ctlr *ctlr) ! 433: { ! 434: RingBuf *ring; ! 435: uchar curr, len1, *pkt; ! 436: Hdr hdr; ! 437: ulong dp8390, data, len; ! 438: ! 439: dp8390 = ctlr->card.dp8390; ! 440: for(curr = getcurr(dp8390); ctlr->card.nxtpkt != curr; curr = getcurr(dp8390)){ ! 441: ctlr->inpackets++; ! 442: ! 443: data = ctlr->card.nxtpkt*Dp8390BufSz; ! 444: (*ctlr->card.read)(ctlr, &hdr, data, sizeof(Hdr)); ! 445: ! 446: /* ! 447: * Don't believe the upper byte count, work it ! 448: * out from the software next-page pointer and ! 449: * the current next-page pointer. ! 450: */ ! 451: if(hdr.next > ctlr->card.nxtpkt) ! 452: len1 = hdr.next - ctlr->card.nxtpkt - 1; ! 453: else ! 454: len1 = (ctlr->card.pstop-ctlr->card.nxtpkt) + (hdr.next-ctlr->card.pstart) - 1; ! 455: if(hdr.len0 > (Dp8390BufSz-sizeof(Hdr))) ! 456: len1--; ! 457: ! 458: len = ((len1<<8)|hdr.len0)-4; ! 459: ! 460: /* ! 461: * Chip is badly scrogged, reinitialise the ring. ! 462: */ ! 463: if(hdr.next < ctlr->card.pstart || hdr.next >= ctlr->card.pstop ! 464: || len < 60 || len > sizeof(Etherpkt)){ ! 465: print("H#%2.2ux#%2.2ux#%2.2ux#%2.2ux,%d|", ! 466: hdr.status, hdr.next, hdr.len0, hdr.len1, len); ! 467: dp8390outb(dp8390+Cr, Page0|RDMAabort|Stp); ! 468: dp8390ring(ctlr); ! 469: dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta); ! 470: return; ! 471: } ! 472: ! 473: /* ! 474: * If it's a good packet and we have a place to put it, ! 475: * read it in to the software ring. ! 476: * If the packet wraps round the hardware ring, read it ! 477: * in two pieces. ! 478: */ ! 479: ring = &ctlr->rb[ctlr->ri]; ! 480: if((hdr.status & (Fo|Fae|Crce|Prxok)) == Prxok && ring->owner == Interface){ ! 481: pkt = ring->pkt; ! 482: data += sizeof(Hdr); ! 483: ring->len = len; ! 484: ! 485: if((data+len) >= ctlr->card.pstop*Dp8390BufSz){ ! 486: ulong count = ctlr->card.pstop*Dp8390BufSz - data; ! 487: ! 488: (*ctlr->card.read)(ctlr, pkt, data, count); ! 489: pkt += count; ! 490: data = ctlr->card.pstart*Dp8390BufSz; ! 491: len -= count; ! 492: } ! 493: if(len) ! 494: (*ctlr->card.read)(ctlr, pkt, data, len); ! 495: ! 496: ring->owner = Host; ! 497: ctlr->ri = NEXT(ctlr->ri, ctlr->nrb); ! 498: } ! 499: ! 500: /* ! 501: * Finished woth this packet, update the ! 502: * hardware and software ring pointers. ! 503: */ ! 504: ctlr->card.nxtpkt = hdr.next; ! 505: ! 506: hdr.next--; ! 507: if(hdr.next < ctlr->card.pstart) ! 508: hdr.next = ctlr->card.pstop-1; ! 509: dp8390outb(dp8390+Bnry, hdr.next); ! 510: } ! 511: } ! 512: ! 513: /* ! 514: * Initiate a transmission. Must be called splhi(). ! 515: */ ! 516: void ! 517: dp8390transmit(Ctlr *ctlr) ! 518: { ! 519: ulong dp8390; ! 520: RingBuf *ring; ! 521: ! 522: dp8390 = ctlr->card.dp8390; ! 523: ring = &ctlr->tb[ctlr->ti]; ! 524: if(ctlr->tbusy == 0 && ring->owner == Interface){ ! 525: ! 526: ctlr->tbusy = 1; ! 527: ! 528: (*ctlr->card.write)(ctlr, ctlr->card.tstart*Dp8390BufSz, ring->pkt, ring->len); ! 529: ! 530: dp8390outb(dp8390+Tbcr0, ring->len & 0xFF); ! 531: dp8390outb(dp8390+Tbcr1, (ring->len>>8) & 0xFF); ! 532: dp8390outb(dp8390+Cr, Page0|RDMAabort|Txp|Sta); ! 533: } ! 534: } ! 535: ! 536: void ! 537: dp8390overflow(Ctlr *ctlr) ! 538: { ! 539: ulong dp8390; ! 540: uchar txp; ! 541: int resend; ! 542: ! 543: dp8390 = ctlr->card.dp8390; ! 544: /* ! 545: * The following procedure is taken from the DP8390[12D] datasheet, ! 546: * it seems pretty adamant that this is what has to be done. ! 547: */ ! 548: txp = dp8390inb(dp8390+Cr) & Txp; ! 549: dp8390outb(dp8390+Cr, Page0|RDMAabort|Stp); ! 550: delay(2); ! 551: dp8390outb(dp8390+Rbcr0, 0); ! 552: dp8390outb(dp8390+Rbcr1, 0); ! 553: ! 554: resend = 0; ! 555: if(txp && (dp8390inb(dp8390+Isr) & (Txe|Ptx)) == 0) ! 556: resend = 1; ! 557: ! 558: dp8390outb(dp8390+Tcr, Lb); ! 559: dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta); ! 560: (*ctlr->card.receive)(ctlr); ! 561: dp8390outb(dp8390+Isr, Ovw); ! 562: dp8390outb(dp8390+Tcr, 0); ! 563: ! 564: if(resend) ! 565: dp8390outb(dp8390+Cr, Page0|RDMAabort|Txp|Sta); ! 566: } ! 567: ! 568: void ! 569: dp8390intr(Ureg*, Ctlr *ctlr) ! 570: { ! 571: ulong dp8390; ! 572: RingBuf *ring; ! 573: uchar isr, r; ! 574: ! 575: dp8390 = ctlr->card.dp8390; ! 576: /* ! 577: * While there is something of interest, ! 578: * clear all the interrupts and process. ! 579: */ ! 580: dp8390outb(dp8390+Imr, 0x00); ! 581: while(isr = dp8390inb(dp8390+Isr)){ ! 582: ! 583: if(isr & Ovw){ ! 584: if(ctlr->card.overflow) ! 585: (*ctlr->card.overflow)(ctlr); ! 586: dp8390outb(dp8390+Isr, Ovw); ! 587: ctlr->overflows++; ! 588: } ! 589: ! 590: /* ! 591: * We have received packets. ! 592: * Take a spin round the ring and ! 593: * wakeup the kproc. ! 594: */ ! 595: if(isr & (Rxe|Prx)){ ! 596: (*ctlr->card.receive)(ctlr); ! 597: dp8390outb(dp8390+Isr, Rxe|Prx); ! 598: } ! 599: ! 600: /* ! 601: * A packet completed transmission, successfully or ! 602: * not. Start transmission on the next buffered packet, ! 603: * and wake the output routine. ! 604: */ ! 605: if(isr & (Txe|Ptx)){ ! 606: r = dp8390inb(dp8390+Tsr); ! 607: if(isr & Txe){ ! 608: if((r & (Cdh|Fu|Crs|Abt))) ! 609: print("Tsr#%2.2ux|", r); ! 610: ctlr->oerrs++; ! 611: } ! 612: ! 613: if(isr & Ptx) ! 614: ctlr->outpackets++; ! 615: ! 616: dp8390outb(dp8390+Isr, Txe|Ptx); ! 617: ! 618: ring = &ctlr->tb[ctlr->ti]; ! 619: ring->owner = Host; ! 620: ctlr->tbusy = 0; ! 621: ctlr->ti = NEXT(ctlr->ti, ctlr->ntb); ! 622: (*ctlr->card.transmit)(ctlr); ! 623: } ! 624: ! 625: if(isr & Cnt){ ! 626: ctlr->frames += dp8390inb(dp8390+Cntr0); ! 627: ctlr->crcs += dp8390inb(dp8390+Cntr1); ! 628: ctlr->buffs += dp8390inb(dp8390+Cntr2); ! 629: dp8390outb(dp8390+Isr, Cnt); ! 630: } ! 631: } ! 632: dp8390outb(dp8390+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe); ! 633: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.