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