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