|
|
1.1 ! root 1: #include "u.h" ! 2: #include "../port/lib.h" ! 3: #include "mem.h" ! 4: #include "dat.h" ! 5: #include "fns.h" ! 6: #include "../port/error.h" ! 7: #include "io.h" ! 8: #include "devtab.h" ! 9: ! 10: #include "ether.h" ! 11: ! 12: /* ! 13: * 3Com 503 (EtherLink II). ! 14: * This driver doesn't work under load, the card gets blasted by ! 15: * overwrite-warning interrupts and eventually just hangs. Always clearing ! 16: * the Ovw bit in the DP8390 Isr along with the Rxe and Prx bits stops ! 17: * the overwrite-warning interrupts, but the card eventually hangs anyway. ! 18: * I really don't understand why this card doesn't work, ! 19: * there is plenty of evidence that other systems manage to use it. ! 20: * The only good thing about this driver is that both shared ! 21: * memory and polled I/O work (given the above restraints), although ! 22: * the polled I/O should be tuned. ! 23: */ ! 24: enum { /* Gate Array Registers */ ! 25: Pstr = 0x400, /* Page Start Register */ ! 26: Pspr = 0x401, /* Page Stop Register */ ! 27: Dqtr = 0x402, /* Drq Timer Register */ ! 28: Bcfr = 0x403, /* Base Configuration Register */ ! 29: Pcfr = 0x404, /* EPROM Configuration Register */ ! 30: Gacfr = 0x405, /* GA Configuration Register */ ! 31: Ctrl = 0x406, /* Control Register */ ! 32: Streg = 0x407, /* Status Register */ ! 33: Idcfr = 0x408, /* Interrupt/DMA Configuration Register */ ! 34: Damsb = 0x409, /* DMA Address Register MSB */ ! 35: Dalsb = 0x40A, /* DMA Address Register LSB */ ! 36: Vptr2 = 0x40B, /* Vector Pointer Register 2 */ ! 37: Vptr1 = 0x40C, /* Vector Pointer Register 1 */ ! 38: Vptr0 = 0x40D, /* Vector Pointer Register 0 */ ! 39: Rfmsb = 0x40E, /* Register File Access MSB */ ! 40: Rflsb = 0x40F, /* Register File Access LSB */ ! 41: }; ! 42: ! 43: enum { /* Pcfr */ ! 44: C8xxx = 0x10, /* memory address 0xC8000 */ ! 45: CCxxx = 0x20, /* memory address 0xCC000 */ ! 46: D8xxx = 0x40, /* memory address 0xD8000 */ ! 47: DCxxx = 0x80, /* memory address 0xDC000 */ ! 48: }; ! 49: ! 50: enum { /* Gacfr */ ! 51: Mbs0 = 0x01, /* memory bank select 0 */ ! 52: Mbs1 = 0x02, /* memory bank select 1 */ ! 53: Mbs2 = 0x04, /* memory bank select 2 */ ! 54: Rsel = 0x08, /* RAM select */ ! 55: Test = 0x10, /* test */ ! 56: Ows = 0x20, /* 0 wait state */ ! 57: Tcm = 0x40, /* terminal count mask */ ! 58: Nim = 0x80, /* MIC interrupt mask */ ! 59: }; ! 60: ! 61: enum { /* Ctrl */ ! 62: Rst = 0x01, /* software reset */ ! 63: Xsel = 0x02, /* transceiver select (BNC = 1, AUI = 0) */ ! 64: Ealo = 0x04, /* ethernet address low */ ! 65: Eahi = 0x08, /* ethernet address high */ ! 66: Share = 0x10, /* interrupt share */ ! 67: Dbsel = 0x20, /* double buffer select */ ! 68: Ddir = 0x40, /* DMA direction */ ! 69: Start = 0x80, /* DMA start */ ! 70: }; ! 71: ! 72: enum { /* Streg */ ! 73: Rev0 = 0x01, /* gate array revision bit 0 */ ! 74: Rev1 = 0x02, /* gate array revision bit 1 */ ! 75: Rev2 = 0x04, /* gate array revision bit 2 */ ! 76: Dip = 0x08, /* DMA in progress */ ! 77: Dtc = 0x10, /* DMA terminal count */ ! 78: Oflw = 0x20, /* overflow */ ! 79: Uflw = 0x40, /* underflow */ ! 80: Dprdy = 0x80, /* data port ready */ ! 81: }; ! 82: ! 83: enum { /* Idcfr */ ! 84: Drq1 = 0x01, /* DMA request 1 */ ! 85: Drq2 = 0x02, /* DMA request 2 */ ! 86: Drq3 = 0x04, /* DMA request 3 */ ! 87: Irq2 = 0x10, /* interrupt request 2 */ ! 88: Irq3 = 0x20, /* interrupt request 3 */ ! 89: Irq4 = 0x40, /* interrupt request 4 */ ! 90: Irq5 = 0x80, /* interrupt request 5 */ ! 91: }; ! 92: ! 93: enum { ! 94: RamOffset = 0x2000, /* where the card sees the shared memory */ ! 95: }; ! 96: ! 97: typedef struct { ! 98: ulong io; /* I/O base address */ ! 99: uchar irq; /* interrupt level */ ! 100: uchar bnc; /* use BNC connector */ ! 101: } Table; ! 102: ! 103: /* ! 104: * The only configuration info we can get from the card is the ! 105: * I/O base address and the shared-memory address. So let's make ! 106: * a little hard-wired configuration table. ! 107: */ ! 108: static Table table[] = { ! 109: { 0x300, Irq2, 0, }, /* external transceiver */ ! 110: { 0x310, Irq3, 0, }, ! 111: { 0x330, Irq4, 0, }, ! 112: { 0x350, Irq5, 0, }, ! 113: ! 114: { 0x250, Irq2, Xsel, }, /* BNC */ ! 115: { 0x280, Irq3, Xsel, }, ! 116: { 0x2A0, Irq4, Xsel, }, ! 117: { 0x2E0, Irq5, Xsel, }, ! 118: ! 119: { 0 }, ! 120: }; ! 121: ! 122: ! 123: static int ! 124: reset(Ctlr *ctlr) ! 125: { ! 126: Table *tp; ! 127: int i; ! 128: uchar cfr; ! 129: ! 130: /* ! 131: * The Gate Array Ctrl register bits <3,2> determine what is ! 132: * mapped at the I/O base address. The options are the DP8390, ! 133: * PROM bytes 0-15 or PROM bytes 16-31. ! 134: * At power-on, the I/O base address contains PROM bytes 16-31. ! 135: */ ! 136: for(tp = table; ctlr->card.io = tp->io; tp++){ ! 137: /* ! 138: * Toggle the software reset bit, this should initialise the ! 139: * Ctrl register to 0x0A (Eahi|Xsel). ! 140: * Hopefully there is no other card at the gate-array address. ! 141: */ ! 142: outb(ctlr->card.io+Ctrl, Rst); ! 143: delay(1); ! 144: outb(ctlr->card.io+Ctrl, 0); ! 145: if(inb(ctlr->card.io+Ctrl) == (Eahi|Xsel)) ! 146: break; ! 147: } ! 148: if(ctlr->card.io == 0) ! 149: return -1; ! 150: ! 151: /* ! 152: * Map PROM bytes 0-15 to the I/O base address ! 153: * and read the ethernet address. ! 154: * When done, map the DP8390 at the I/O base address ! 155: * and set the transceiver type and irq. ! 156: */ ! 157: outb(ctlr->card.io+Ctrl, Ealo|Xsel); ! 158: for(i = 0; i < sizeof(ctlr->ea); i++) ! 159: ctlr->ea[i] = inb(ctlr->card.io+i); ! 160: ! 161: outb(ctlr->card.io+Gacfr, Nim|Tcm); ! 162: ! 163: outb(ctlr->card.io+Ctrl, 0|tp->bnc); ! 164: outb(ctlr->card.io+Idcfr, tp->irq); ! 165: ! 166: if(tp->irq == Irq2) ! 167: ctlr->card.irq = 2; ! 168: else if(tp->irq == Irq3) ! 169: ctlr->card.irq = 3; ! 170: else if(tp->irq == Irq4) ! 171: ctlr->card.irq = 4; ! 172: else if(tp->irq == Irq5) ! 173: ctlr->card.irq = 5; ! 174: else ! 175: return -1; ! 176: ! 177: /* ! 178: * Try to configure the shared memory. ! 179: * Assume this is an 8K card. ! 180: */ ! 181: ctlr->card.ram = 1; ! 182: cfr = inb(ctlr->card.io+Pcfr); ! 183: if(cfr & C8xxx) ! 184: ctlr->card.ramstart = KZERO|0xC8000; ! 185: else if(cfr & CCxxx) ! 186: ctlr->card.ramstart = KZERO|0xCC000; ! 187: else if(cfr & D8xxx) ! 188: ctlr->card.ramstart = KZERO|0xD8000; ! 189: else if(cfr & DCxxx) ! 190: ctlr->card.ramstart = KZERO|0xDC000; ! 191: else ! 192: ctlr->card.ram = 0; ! 193: ! 194: ctlr->card.ramstop = ctlr->card.ramstart + 8*1024; ! 195: ! 196: /* ! 197: * Finish initialising the gate-array. ! 198: * The Pstr and Pspr registers must be the same as those ! 199: * given to the DP8390. ! 200: * Gacfr is set to enable shared memory and block DMA ! 201: * interrupts. ! 202: */ ! 203: outb(ctlr->card.io+Pstr, ctlr->card.pstart); ! 204: outb(ctlr->card.io+Pspr, ctlr->card.pstop); ! 205: ! 206: outb(ctlr->card.io+Dqtr, 8); ! 207: outb(ctlr->card.io+Damsb, ctlr->card.tstart); ! 208: outb(ctlr->card.io+Dalsb, 0); ! 209: ! 210: outb(ctlr->card.io+Vptr2, 0xFF); ! 211: outb(ctlr->card.io+Vptr1, 0xFF); ! 212: outb(ctlr->card.io+Vptr0, 0x00); ! 213: ! 214: /* ! 215: * Finally, init the 8390, set the ethernet address ! 216: * and turn on the shared memory if any. ! 217: */ ! 218: ctlr->card.dp8390 = ctlr->card.io; ! 219: dp8390reset(ctlr); ! 220: dp8390setea(ctlr); ! 221: ! 222: if(ctlr->card.ram) ! 223: outb(ctlr->card.io+Gacfr, Tcm|Rsel|Mbs0); ! 224: else ! 225: outb(ctlr->card.io+Gacfr, Tcm); ! 226: ! 227: return 0; ! 228: } ! 229: ! 230: static void* ! 231: read(Ctlr *ctlr, void *to, ulong from, ulong len) ! 232: { ! 233: uchar *addr, ctrl; ! 234: ! 235: /* ! 236: * If the interface has shared memory, just do a memmove. ! 237: * In this case, 'from' is an index into the shared memory. ! 238: * Due to 'hardware considerations', the memory is seen by ! 239: * the adapter at RamOffset, so we have to adjust. ! 240: */ ! 241: if(ctlr->card.ram) ! 242: return memmove(to, (void*)(ctlr->card.ramstart+from-RamOffset), len); ! 243: ! 244: /* ! 245: * Polled I/O. This should be tuned. ! 246: * Set up the dma registers and pump the fifo. ! 247: */ ! 248: outb(ctlr->card.io+Dalsb, from & 0xFF); ! 249: outb(ctlr->card.io+Damsb, (from>>8) & 0xFF); ! 250: ctrl = inb(ctlr->card.io+Ctrl); ! 251: outb(ctlr->card.io+Ctrl, Start|ctrl); ! 252: addr = to; ! 253: while(len){ ! 254: /* ! 255: * The fifo is 8 bytes deep, we have to wait ! 256: * until it's ready before stuffing it. ! 257: * The fifo is in its default configuration, ! 258: * so we can do word accesses. ! 259: */ ! 260: while((inb(ctlr->card.io+Streg) & Dprdy) == 0) ! 261: ; ! 262: if(len >= 8){ ! 263: inss(ctlr->card.io+Rfmsb, addr, 4); ! 264: addr += 8; ! 265: len -= 8; ! 266: } ! 267: else{ ! 268: insb(ctlr->card.io+Rfmsb, addr, len); ! 269: break; ! 270: } ! 271: } ! 272: outb(ctlr->card.io+Ctrl, ctrl); ! 273: return to; ! 274: } ! 275: ! 276: static void* ! 277: write(Ctlr *ctlr, ulong to, void *from, ulong len) ! 278: { ! 279: uchar *addr, ctrl; ! 280: ! 281: /* ! 282: * See the comments in 'read()' above. ! 283: */ ! 284: if(ctlr->card.ram) ! 285: return memmove((void*)(ctlr->card.ramstart+to-RamOffset), from, len); ! 286: ! 287: outb(ctlr->card.io+Dalsb, to & 0xFF); ! 288: outb(ctlr->card.io+Damsb, (to>>8) & 0xFF); ! 289: ctrl = inb(ctlr->card.io+Ctrl); ! 290: outb(ctlr->card.io+Ctrl, Start|Ddir|ctrl); ! 291: addr = from; ! 292: while(len){ ! 293: while((inb(ctlr->card.io+Streg) & Dprdy) == 0) ! 294: ; ! 295: if(len >= 8){ ! 296: outss(ctlr->card.io+Rfmsb, addr, 4); ! 297: addr += 8; ! 298: len -= 8; ! 299: } ! 300: else{ ! 301: outsb(ctlr->card.io+Rfmsb, addr, len); ! 302: break; ! 303: } ! 304: } ! 305: outb(ctlr->card.io+Ctrl, ctrl); ! 306: return (void*)to; ! 307: } ! 308: ! 309: Card ether503 = { ! 310: "3Com503", /* ident */ ! 311: ! 312: reset, /* reset */ ! 313: 0, /* init */ ! 314: dp8390attach, /* attach */ ! 315: dp8390mode, /* mode */ ! 316: ! 317: read, /* read */ ! 318: write, /* write */ ! 319: ! 320: dp8390receive, /* receive */ ! 321: dp8390transmit, /* transmit */ ! 322: dp8390intr, /* interrupt */ ! 323: dp8390watch, /* watch */ ! 324: dp8390overflow, /* overflow */ ! 325: ! 326: 0, /* io */ ! 327: 0, /* irq */ ! 328: 0, /* bit16 */ ! 329: ! 330: 0, /* ram */ ! 331: 0, /* ramstart */ ! 332: 0, /* ramstop */ ! 333: ! 334: 0, /* dp8390 */ ! 335: 0, /* data */ ! 336: 0, /* software bndry */ ! 337: RamOffset/Dp8390BufSz, /* tstart */ ! 338: (RamOffset+0x600)/Dp8390BufSz, /* pstart */ ! 339: (RamOffset+8*1024)/Dp8390BufSz, /* pstop */ ! 340: }; ! 341: ! 342: void ! 343: ether503link(void) ! 344: { ! 345: addethercard("3C503", ccc503reset); ! 346: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.