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