|
|
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: * Western Digital/Standard Microsystems Corporation cards (WD80[01]3). ! 14: * Configuration code based on that provided by SMC. ! 15: */ ! 16: enum { /* 83C584 Bus Interface Controller */ ! 17: Msr = 0x00, /* Memory Select Register */ ! 18: Icr = 0x01, /* Interface Configuration Register */ ! 19: Iar = 0x02, /* I/O Address Register */ ! 20: Bio = 0x03, /* BIOS ROM Address Register */ ! 21: Ear = 0x03, /* EEROM Address Register (shared with Bio) */ ! 22: Irr = 0x04, /* Interrupt Request Register */ ! 23: Laar = 0x05, /* LA Address Register */ ! 24: Ijr = 0x06, /* Initialisation Jumpers */ ! 25: Gp2 = 0x07, /* General Purpose Data Register */ ! 26: Lar = 0x08, /* LAN Address Registers */ ! 27: Id = 0x0E, /* Card ID byte */ ! 28: Cksum = 0x0F, /* Checksum */ ! 29: }; ! 30: ! 31: enum { /* Msr */ ! 32: Rst = 0x80, /* software reset */ ! 33: Menb = 0x40, /* memory enable */ ! 34: }; ! 35: ! 36: enum { /* Icr */ ! 37: Bit16 = 0x01, /* 16-bit bus */ ! 38: Other = 0x02, /* other register access */ ! 39: Ir2 = 0x04, /* IR2 */ ! 40: Msz = 0x08, /* SRAM size */ ! 41: Rla = 0x10, /* recall LAN address */ ! 42: Rx7 = 0x20, /* recall all but I/O and LAN address */ ! 43: Rio = 0x40, /* recall I/O address from EEROM */ ! 44: Sto = 0x80, /* non-volatile EEROM store */ ! 45: }; ! 46: ! 47: enum { /* Laar */ ! 48: ZeroWS16 = (1<<5), /* zero wait states for 16-bit ops */ ! 49: L16en = (1<<6), /* enable 16-bit LAN operation */ ! 50: M16en = (1<<7), /* enable 16-bit memory access */ ! 51: }; ! 52: ! 53: /* ! 54: * Mapping from configuration bits to interrupt level. ! 55: */ ! 56: static int intrmap[] = { ! 57: 9, 3, 5, 7, 10, 11, 15, 4, ! 58: }; ! 59: ! 60: static void* ! 61: read(Ctlr *ctlr, void *to, ulong from, ulong len) ! 62: { ! 63: /* ! 64: * In this case, 'from' is an index into the shared memory. ! 65: */ ! 66: memmove(to, (void*)(ctlr->card.mem+from), len); ! 67: return to; ! 68: } ! 69: ! 70: static void* ! 71: write(Ctlr *ctlr, ulong to, void *from, ulong len) ! 72: { ! 73: /* ! 74: * In this case, 'to' is an index into the shared memory. ! 75: */ ! 76: memmove((void*)(ctlr->card.mem+to), from, len); ! 77: return (void*)to; ! 78: } ! 79: ! 80: static void ! 81: watch(Ctlr *ctlr) ! 82: { ! 83: uchar msr; ! 84: int s; ! 85: ! 86: s = splhi(); ! 87: msr = inb(ctlr->card.port+Msr); ! 88: /* ! 89: * If the card has reset itself, ! 90: * start again. ! 91: */ ! 92: if((msr & Menb) == 0){ ! 93: delay(100); ! 94: ! 95: dp8390reset(ctlr); ! 96: etherinit(); ! 97: ! 98: wakeup(&ctlr->tr); ! 99: wakeup(&ctlr->rr); ! 100: } ! 101: splx(s); ! 102: } ! 103: ! 104: /* ! 105: * Get configuration parameters, enable memory. ! 106: * There are opportunities here for buckets of code. ! 107: * We'll try to resist. ! 108: */ ! 109: int ! 110: wd8003reset(Ctlr *ctlr) ! 111: { ! 112: int i; ! 113: uchar ea[Eaddrlen], ic[8], sum; ! 114: ulong wd8003; ! 115: ! 116: /* ! 117: * Set up the software configuration. ! 118: * Use defaults for port, irq, mem and size if not specified. ! 119: * Defaults are set for the dumb 8003E which can't be ! 120: * autoconfigured. ! 121: */ ! 122: if(ctlr->card.port == 0) ! 123: ctlr->card.port = 0x280; ! 124: if(ctlr->card.irq == 0) ! 125: ctlr->card.irq = 3; ! 126: if(ctlr->card.mem == 0) ! 127: ctlr->card.mem = 0xD0000; ! 128: if(ctlr->card.size == 0) ! 129: ctlr->card.size = 8*1024; ! 130: ! 131: ctlr->card.reset = wd8003reset; ! 132: ctlr->card.attach = dp8390attach; ! 133: ctlr->card.mode = dp8390mode; ! 134: ctlr->card.read = read; ! 135: ctlr->card.write = write; ! 136: ctlr->card.receive = dp8390receive; ! 137: ctlr->card.transmit = dp8390transmit; ! 138: ctlr->card.intr = dp8390intr; ! 139: ctlr->card.watch = watch; ! 140: ctlr->card.ram = 1; ! 141: ! 142: wd8003 = ctlr->card.port; ! 143: /* ! 144: * Look for the interface. We read the LAN address ROM ! 145: * and validate the checksum - the sum of all 8 bytes ! 146: * should be 0xFF. ! 147: * While we're at it, get the (possible) interface chip ! 148: * registers, we'll use them to check for aliasing later. ! 149: */ ! 150: sum = 0; ! 151: for(i = 0; i < sizeof(ctlr->ea); i++){ ! 152: ea[i] = inb(wd8003+Lar+i); ! 153: sum += ea[i]; ! 154: ic[i] = inb(wd8003+i); ! 155: } ! 156: sum += inb(wd8003+Id); ! 157: sum += inb(wd8003+Cksum); ! 158: if(sum != 0xFF) ! 159: return -1; ! 160: ! 161: /* ! 162: * Check for old, dumb 8003E, which doesn't have an interface ! 163: * chip. Only the msr exists out of the 1st eight registers, reads ! 164: * of the others just alias the 2nd eight registers, the LAN ! 165: * address ROM. We can check icr, irr and laar against the ethernet ! 166: * address read above and if they match it's an 8003E (or an ! 167: * 8003EBT, 8003S, 8003SH or 8003WT, we don't care), in which ! 168: * case the default irq gets used. ! 169: */ ! 170: if(memcmp(&ctlr->ea[1], &ic[1], 5) == 0){ ! 171: memset(ic, 0, sizeof(ic)); ! 172: ic[Msr] = (((ulong)ctlr->card.mem)>>13) & 0x3F; ! 173: ctlr->card.watch = 0; ! 174: } ! 175: else{ ! 176: /* ! 177: * As a final sanity check for the 8013EBT, which doesn't have ! 178: * the 83C584 interface chip, but has 2 real registers, write Gp2 and if ! 179: * it reads back the same, it's not an 8013EBT. ! 180: */ ! 181: outb(wd8003+Gp2, 0xAA); ! 182: inb(wd8003+Msr); /* wiggle bus */ ! 183: if(inb(wd8003+Gp2) != 0xAA){ ! 184: memset(ic, 0, sizeof(ic)); ! 185: ic[Msr] = (((ulong)ctlr->card.mem)>>13) & 0x3F; ! 186: ctlr->card.watch = 0; ! 187: } ! 188: else ! 189: ctlr->card.irq = intrmap[((ic[Irr]>>5) & 0x3)|(ic[Icr] & Ir2)]; ! 190: ! 191: /* ! 192: * Check if 16-bit card. ! 193: * If Bit16 is read/write, then we have an 8-bit card. ! 194: * If Bit16 is set, we're in a 16-bit slot. ! 195: */ ! 196: outb(wd8003+Icr, ic[Icr]^Bit16); ! 197: inb(wd8003+Msr); /* wiggle bus */ ! 198: if((inb(wd8003+Icr) & Bit16) == (ic[Icr] & Bit16)){ ! 199: ctlr->card.bit16 = 1; ! 200: ic[Icr] &= ~Bit16; ! 201: } ! 202: outb(wd8003+Icr, ic[Icr]); ! 203: ! 204: if(ctlr->card.bit16 && (inb(wd8003+Icr) & Bit16) == 0) ! 205: ctlr->card.bit16 = 0; ! 206: ! 207: /* ! 208: * Force the memory size. ! 209: */ ! 210: if(ctlr->card.bit16) ! 211: ctlr->card.size = 16*1024; ! 212: else ! 213: ctlr->card.size = 8*1024; ! 214: } ! 215: ! 216: ctlr->card.mem = KZERO|((ic[Msr] & 0x3F)<<13); ! 217: if(ctlr->card.bit16) ! 218: ctlr->card.mem |= (ic[Laar] & 0x1F)<<19; ! 219: else ! 220: ctlr->card.mem |= 0x80000; ! 221: ! 222: if(ic[Icr] & Msz) ! 223: ctlr->card.size <<= 2; ! 224: ! 225: /* ! 226: * Set the DP8390 ring addresses. ! 227: */ ! 228: ctlr->card.dp8390 = wd8003+0x10; ! 229: ctlr->card.tstart = 0; ! 230: ctlr->card.pstart = HOWMANY(sizeof(Etherpkt), Dp8390BufSz); ! 231: ctlr->card.pstop = HOWMANY(ctlr->card.size, Dp8390BufSz); ! 232: ! 233: /* ! 234: * Enable interface RAM, set interface width. ! 235: */ ! 236: outb(wd8003+Msr, ic[Msr]|Menb); ! 237: if(ctlr->card.bit16) ! 238: outb(wd8003+Laar, ic[Laar]|L16en|M16en|ZeroWS16); ! 239: ! 240: /* ! 241: * Finally, init the 8390 and set the ! 242: * ethernet address. ! 243: */ ! 244: dp8390reset(ctlr); ! 245: if((ctlr->ea[0]|ctlr->ea[1]|ctlr->ea[2]|ctlr->ea[3]|ctlr->ea[4]|ctlr->ea[5]) == 0) ! 246: memmove(ctlr->ea, ea, Eaddrlen); ! 247: dp8390setea(ctlr); ! 248: ! 249: if(getisa(ctlr->card.mem, ctlr->card.size, 0) == 0) ! 250: panic("ether8003: 0x%lux reused", ctlr->card.mem); ! 251: ! 252: return 0; ! 253: } ! 254: ! 255: void ! 256: ether8003link(void) ! 257: { ! 258: addethercard("WD8003", wd8003reset); ! 259: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.