|
|
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.