1 /*
2 wdeth.c
3
4 Created: March 14, 1994 by Philip Homburg
5 */
6
7 #include <minix/drivers.h>
8 #include <minix/netdriver.h>
9
10 #include <assert.h>
11
12 #include "local.h"
13 #include "dp8390.h"
14 #include "wdeth.h"
15
16 #if ENABLE_WDETH
17
18 #define WET_ETHERNET 0x01 /* Ethernet transceiver */
19 #define WET_STARLAN 0x02 /* Starlan transceiver */
20 #define WET_INTERF_CHIP 0x04 /* has a WD83C583 interface chip */
21 #define WET_BRD_16BIT 0x08 /* 16 bit board */
22 #define WET_SLT_16BIT 0x10 /* 16 bit slot */
23 #define WET_790 0x20 /* '790 chip */
24
25 static int we_int_table[8]= { 9, 3, 5, 7, 10, 11, 15, 4 };
26 static int we_790int_table[8]= { 0, 9, 3, 5, 7, 10, 11, 15 };
27
28 static void we_init(dpeth_t *dep);
29 static void we_stop(dpeth_t *dep);
30 static int we_aliasing(dpeth_t *dep);
31 static int we_interface_chip(dpeth_t *dep);
32 static int we_16bitboard(dpeth_t *dep);
33 static int we_16bitslot(dpeth_t *dep);
34 static int we_ultra(dpeth_t *dep);
35
36 /*===========================================================================*
37 * wdeth_probe *
38 *===========================================================================*/
wdeth_probe(dep)39 int wdeth_probe(dep)
40 dpeth_t *dep;
41 {
42 int sum;
43
44 if (dep->de_linmem == 0)
45 return 0; /* No shared memory, so no WD board */
46
47 sum = inb_we(dep, EPL_EA0) + inb_we(dep, EPL_EA1) +
48 inb_we(dep, EPL_EA2) + inb_we(dep, EPL_EA3) +
49 inb_we(dep, EPL_EA4) + inb_we(dep, EPL_EA5) +
50 inb_we(dep, EPL_TLB) + inb_we(dep, EPL_CHKSUM);
51 if ((sum & 0xFF) != 0xFF)
52 return 0; /* No ethernet board at this address */
53
54 dep->de_initf= we_init;
55 dep->de_stopf= we_stop;
56 dep->de_prog_IO= 0;
57 return 1;
58 }
59
60 /*===========================================================================*
61 * we_init *
62 *===========================================================================*/
we_init(dep)63 static void we_init(dep)
64 dpeth_t *dep;
65 {
66 int i, int_indx, int_nr;
67 int tlb, rambit, revision;
68 int icr, irr, hwr, b, gcr;
69 int we_type;
70 int sendq_nr;
71
72 dep->de_address.na_addr[0] = inb_we(dep, EPL_EA0);
73 dep->de_address.na_addr[1] = inb_we(dep, EPL_EA1);
74 dep->de_address.na_addr[2] = inb_we(dep, EPL_EA2);
75 dep->de_address.na_addr[3] = inb_we(dep, EPL_EA3);
76 dep->de_address.na_addr[4] = inb_we(dep, EPL_EA4);
77 dep->de_address.na_addr[5] = inb_we(dep, EPL_EA5);
78
79 dep->de_dp8390_port= dep->de_base_port + EPL_DP8390;
80
81 dep->de_16bit= 0;
82
83 we_type= 0;
84 we_type |= WET_ETHERNET; /* assume ethernet */
85 if (we_ultra(dep))
86 we_type |= WET_790;
87 if (!we_aliasing(dep))
88 {
89 if (we_interface_chip(dep))
90 we_type |= WET_INTERF_CHIP;
91 if (we_16bitboard(dep))
92 {
93 we_type |= WET_BRD_16BIT;
94 if (we_16bitslot(dep))
95 we_type |= WET_SLT_16BIT;
96 }
97 }
98 if (we_type & WET_SLT_16BIT)
99 dep->de_16bit= 1;
100
101 /* look at the on board ram size. */
102 tlb= inb_we(dep, EPL_TLB);
103 revision= tlb & E_TLB_REV;
104 rambit= tlb & E_TLB_RAM;
105
106 if (dep->de_ramsize != 0)
107 {
108 /* size set from boot environment. */
109 }
110 else if (revision < 2)
111 {
112 dep->de_ramsize= 0x2000; /* 8K */
113 if (we_type & WET_BRD_16BIT)
114 dep->de_ramsize= 0x4000; /* 16K */
115 else if ((we_type & WET_INTERF_CHIP) &&
116 inb_we(dep, EPL_ICR) & E_ICR_MEMBIT)
117 {
118 dep->de_ramsize= 0x8000; /* 32K */
119 }
120 }
121 else
122 {
123 if (we_type & WET_BRD_16BIT)
124 {
125 /* 32K or 16K */
126 dep->de_ramsize= rambit ? 0x8000 : 0x4000;
127 }
128 else
129 {
130 /* 32K or 8K */
131 dep->de_ramsize= rambit ? 0x8000 : 0x2000;
132 }
133 }
134
135 if (we_type & WET_790)
136 {
137 outb_we(dep, EPL_MSR, E_MSR_RESET);
138 if ((we_type & (WET_BRD_16BIT|WET_SLT_16BIT)) ==
139 (WET_BRD_16BIT|WET_SLT_16BIT))
140 {
141 outb_we(dep, EPL_LAAR, E_LAAR_LAN16E | E_LAAR_MEM16E);
142 }
143 }
144 else if (we_type & WET_BRD_16BIT)
145 {
146 if (we_type & WET_SLT_16BIT)
147 {
148 outb_we(dep, EPL_LAAR, E_LAAR_A19 | E_LAAR_SOFTINT |
149 E_LAAR_LAN16E | E_LAAR_MEM16E);
150 }
151 else
152 {
153 outb_we(dep, EPL_LAAR, E_LAAR_A19 | E_LAAR_SOFTINT |
154 E_LAAR_LAN16E);
155 }
156 }
157
158 if (we_type & WET_790)
159 {
160 outb_we(dep, EPL_MSR, E_MSR_MENABLE);
161 hwr= inb_we(dep, EPL_790_HWR);
162 outb_we(dep, EPL_790_HWR, hwr | E_790_HWR_SWH);
163 b= inb_we(dep, EPL_790_B);
164 outb_we(dep, EPL_790_B, ((dep->de_linmem >> 13) & 0x0f) |
165 ((dep->de_linmem >> 11) & 0x40) | (b & 0xb0));
166 outb_we(dep, EPL_790_HWR, hwr & ~E_790_HWR_SWH);
167 }
168 else
169 {
170 outb_we(dep, EPL_MSR, E_MSR_RESET);
171 outb_we(dep, EPL_MSR, E_MSR_MENABLE |
172 ((dep->de_linmem >> 13) & E_MSR_MEMADDR));
173 }
174
175 if ((we_type & WET_INTERF_CHIP) && !(we_type & WET_790))
176 {
177 icr= inb_we(dep, EPL_ICR);
178 irr= inb_we(dep, EPL_IRR);
179 int_indx= (icr & E_ICR_IR2) |
180 ((irr & (E_IRR_IR0|E_IRR_IR1)) >> 5);
181 int_nr= we_int_table[int_indx];
182 #if DEBUG
183 printf("%s: encoded irq= %d\n", netdriver_name(), int_nr);
184 #endif
185 if (dep->de_irq & DEI_DEFAULT) dep->de_irq= int_nr;
186
187 outb_we(dep, EPL_IRR, irr | E_IRR_IEN);
188 }
189 if (we_type & WET_790)
190 {
191 hwr= inb_we(dep, EPL_790_HWR);
192 outb_we(dep, EPL_790_HWR, hwr | E_790_HWR_SWH);
193
194 gcr= inb_we(dep, EPL_790_GCR);
195
196 outb_we(dep, EPL_790_HWR, hwr & ~E_790_HWR_SWH);
197
198 int_indx= ((gcr & E_790_GCR_IR2) >> 4) |
199 ((gcr & (E_790_GCR_IR1|E_790_GCR_IR0)) >> 2);
200 int_nr= we_790int_table[int_indx];
201 #if DEBUG
202 printf("%s: encoded irq= %d\n", netdriver_name(), int_nr);
203 #endif
204 if (dep->de_irq & DEI_DEFAULT) dep->de_irq= int_nr;
205
206 icr= inb_we(dep, EPL_790_ICR);
207 outb_we(dep, EPL_790_ICR, icr | E_790_ICR_EIL);
208 }
209
210 /* Strip the "default flag." */
211 dep->de_irq &= ~DEI_DEFAULT;
212
213 if (!debug)
214 {
215 printf("%s: WD80%d3 at %X:%d:%lX\n",
216 netdriver_name(), we_type & WET_BRD_16BIT ? 1 : 0,
217 dep->de_base_port, dep->de_irq, dep->de_linmem);
218 }
219 else
220 {
221 printf("%s: Western Digital %s%s card %s%s at I/O "
222 "address 0x%X, memory address 0x%lX, "
223 "memory size 0x%X, irq %d\n",
224 netdriver_name(),
225 we_type & WET_BRD_16BIT ? "16-bit " : "",
226 we_type & WET_ETHERNET ? "Ethernet" :
227 we_type & WET_STARLAN ? "Starlan" : "Network",
228 we_type & WET_INTERF_CHIP ? "with an interface chip " : "",
229 we_type & WET_SLT_16BIT ? "in a 16-bit slot " : "",
230 dep->de_base_port, dep->de_linmem, dep->de_ramsize,
231 dep->de_irq);
232 }
233
234 dep->de_offset_page= 0; /* Shared memory starts at 0 */
235
236 /* Allocate one send buffer (1.5KB) per 8KB of on board memory. */
237 sendq_nr= dep->de_ramsize / 0x2000;
238 if (sendq_nr < 1)
239 sendq_nr= 1;
240 else if (sendq_nr > SENDQ_NR)
241 sendq_nr= SENDQ_NR;
242 dep->de_sendq_nr= sendq_nr;
243 for (i= 0; i<sendq_nr; i++)
244 dep->de_sendq[i].sq_sendpage= i*SENDQ_PAGES;
245
246 dep->de_startpage= i*SENDQ_PAGES;
247 dep->de_stoppage= dep->de_ramsize / DP_PAGESIZE;
248 }
249
250 /*===========================================================================*
251 * we_stop *
252 *===========================================================================*/
we_stop(dep)253 static void we_stop(dep)
254 dpeth_t *dep;
255 {
256 if (dep->de_16bit)
257 outb_we(dep, EPL_LAAR, E_LAAR_A19 | E_LAAR_LAN16E);
258 outb_we(dep, EPL_MSR, E_MSR_RESET);
259 outb_we(dep, EPL_MSR, 0);
260 }
261
262 /*===========================================================================*
263 * we_aliasing *
264 *===========================================================================*/
we_aliasing(dep)265 static int we_aliasing(dep)
266 dpeth_t *dep;
267 {
268 /* Determine whether wd8003 hardware performs register aliasing. This implies
269 * an old WD8003E board. */
270
271 if (inb_we(dep, EPL_REG1) != inb_we(dep, EPL_EA1))
272 return 0;
273 if (inb_we(dep, EPL_REG2) != inb_we(dep, EPL_EA2))
274 return 0;
275 if (inb_we(dep, EPL_REG3) != inb_we(dep, EPL_EA3))
276 return 0;
277 if (inb_we(dep, EPL_REG4) != inb_we(dep, EPL_EA4))
278 return 0;
279 if (inb_we(dep, EPL_REG7) != inb_we(dep, EPL_CHKSUM))
280 return 0;
281 return 1;
282 }
283
284 /*===========================================================================*
285 * we_interface_chip *
286 *===========================================================================*/
we_interface_chip(dep)287 static int we_interface_chip(dep)
288 dpeth_t *dep;
289 {
290 /* Determine if the board has an interface chip. */
291
292 outb_we(dep, EPL_GP2, 0x35);
293 if (inb_we(dep, EPL_GP2) != 0x35)
294 return 0;
295 outb_we(dep, EPL_GP2, 0x3A);
296 if (inb_we(dep, EPL_GP2) != 0x3A)
297 return 0;
298 return 1;
299 }
300
301 /*===========================================================================*
302 * we_16bitboard *
303 *===========================================================================*/
we_16bitboard(dep)304 static int we_16bitboard(dep)
305 dpeth_t *dep;
306 {
307 /* Determine whether the board is capable of doing 16 bit memory moves.
308 * If the 16 bit enable bit is unchangable by software we'll assume an
309 * 8 bit board.
310 */
311 int icr;
312 u8_t tlb;
313
314 icr= inb_we(dep, EPL_ICR);
315
316 outb_we(dep, EPL_ICR, icr ^ E_ICR_16BIT);
317 if (inb_we(dep, EPL_ICR) == icr)
318 {
319 tlb= inb_we(dep, EPL_TLB);
320 #if DEBUG
321 printf("%s: tlb= 0x%x\n", netdriver_name(), tlb);
322 #endif
323 return tlb == E_TLB_EB || tlb == E_TLB_E ||
324 tlb == E_TLB_SMCE || tlb == E_TLB_SMC8216T ||
325 tlb == E_TLB_SMC8216C;
326 }
327 outb_we(dep, EPL_ICR, icr);
328 return (icr & E_ICR_16BIT);
329 }
330
331 /*===========================================================================*
332 * we_16bitslot *
333 *===========================================================================*/
we_16bitslot(dep)334 static int we_16bitslot(dep)
335 dpeth_t *dep;
336 {
337 /* Determine if the 16 bit board in plugged into a 16 bit slot. */
338 return !!(inb_we(dep, EPL_ICR) & E_ICR_16BIT);
339 }
340
341 /*===========================================================================*
342 * we_ultra *
343 *===========================================================================*/
we_ultra(dep)344 static int we_ultra(dep)
345 dpeth_t *dep;
346 {
347 /* Determine if we has an '790 chip. */
348 u8_t tlb;
349
350 tlb= inb_we(dep, EPL_TLB);
351 return tlb == E_TLB_SMC8216T || tlb == E_TLB_SMC8216C;
352 }
353
354 #endif /* ENABLE_WDETH */
355
356 /*
357 * $PchId: wdeth.c,v 1.10 2003/09/10 19:31:50 philip Exp $
358 */
359