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