xref: /minix3/minix/drivers/net/dp8390/rtl8029.c (revision 433d6423c39e34ec4b79c950597bb2d236f886be)
1*433d6423SLionel Sambuc /*
2*433d6423SLionel Sambuc rtl8029.c
3*433d6423SLionel Sambuc 
4*433d6423SLionel Sambuc Initialization of PCI DP8390-based ethernet cards
5*433d6423SLionel Sambuc 
6*433d6423SLionel Sambuc Created:	April 2000 by Philip Homburg <philip@f-mnx.phicoh.com>
7*433d6423SLionel Sambuc */
8*433d6423SLionel Sambuc 
9*433d6423SLionel Sambuc #include <minix/drivers.h>
10*433d6423SLionel Sambuc 
11*433d6423SLionel Sambuc #include <stdlib.h>
12*433d6423SLionel Sambuc #include <sys/types.h>
13*433d6423SLionel Sambuc #include <net/gen/ether.h>
14*433d6423SLionel Sambuc #include <net/gen/eth_io.h>
15*433d6423SLionel Sambuc #include <machine/pci.h>
16*433d6423SLionel Sambuc 
17*433d6423SLionel Sambuc #include "assert.h"
18*433d6423SLionel Sambuc 
19*433d6423SLionel Sambuc #include "local.h"
20*433d6423SLionel Sambuc #include "dp8390.h"
21*433d6423SLionel Sambuc #include "rtl8029.h"
22*433d6423SLionel Sambuc 
23*433d6423SLionel Sambuc #if ENABLE_PCI
24*433d6423SLionel Sambuc 
25*433d6423SLionel Sambuc static void rtl_init(struct dpeth *dep);
26*433d6423SLionel Sambuc #if 0
27*433d6423SLionel Sambuc static u16_t get_ee_word(dpeth_t *dep, int a);
28*433d6423SLionel Sambuc static void ee_wen(dpeth_t *dep);
29*433d6423SLionel Sambuc static void set_ee_word(dpeth_t *dep, int a, u16_t w);
30*433d6423SLionel Sambuc static void ee_wds(dpeth_t *dep);
31*433d6423SLionel Sambuc #endif
32*433d6423SLionel Sambuc 
33*433d6423SLionel Sambuc int rtl_probe(dep, skip)
34*433d6423SLionel Sambuc struct dpeth *dep;
35*433d6423SLionel Sambuc int skip;
36*433d6423SLionel Sambuc {
37*433d6423SLionel Sambuc 	int r, devind;
38*433d6423SLionel Sambuc 	u16_t vid, did;
39*433d6423SLionel Sambuc 	u32_t bar;
40*433d6423SLionel Sambuc 	u8_t ilr;
41*433d6423SLionel Sambuc 	char *dname;
42*433d6423SLionel Sambuc 
43*433d6423SLionel Sambuc 	pci_init();
44*433d6423SLionel Sambuc 
45*433d6423SLionel Sambuc 	r= pci_first_dev(&devind, &vid, &did);
46*433d6423SLionel Sambuc 	if (r == 0)
47*433d6423SLionel Sambuc 		return 0;
48*433d6423SLionel Sambuc 
49*433d6423SLionel Sambuc 	while (skip--)
50*433d6423SLionel Sambuc 	{
51*433d6423SLionel Sambuc 		r= pci_next_dev(&devind, &vid, &did);
52*433d6423SLionel Sambuc 		if (!r)
53*433d6423SLionel Sambuc 			return 0;
54*433d6423SLionel Sambuc 	}
55*433d6423SLionel Sambuc 
56*433d6423SLionel Sambuc 	dname= pci_dev_name(vid, did);
57*433d6423SLionel Sambuc 	if (!dname)
58*433d6423SLionel Sambuc 		dname= "unknown device";
59*433d6423SLionel Sambuc 	printf("%s: %s (%04X/%04X) at %s\n",
60*433d6423SLionel Sambuc 		dep->de_name, dname, vid, did, pci_slot_name(devind));
61*433d6423SLionel Sambuc         if(pci_reserve_ok(devind) != OK)
62*433d6423SLionel Sambuc                return 0;
63*433d6423SLionel Sambuc 	/* printf("cr = 0x%x\n", pci_attr_r16(devind, PCI_CR)); */
64*433d6423SLionel Sambuc 	bar= pci_attr_r32(devind, PCI_BAR) & 0xffffffe0;
65*433d6423SLionel Sambuc 
66*433d6423SLionel Sambuc 	if (bar < 0x400)
67*433d6423SLionel Sambuc 		panic("base address is not properly configured");
68*433d6423SLionel Sambuc 
69*433d6423SLionel Sambuc 	dep->de_base_port= bar;
70*433d6423SLionel Sambuc 
71*433d6423SLionel Sambuc 	ilr= pci_attr_r8(devind, PCI_ILR);
72*433d6423SLionel Sambuc 	dep->de_irq= ilr;
73*433d6423SLionel Sambuc 	if (debug)
74*433d6423SLionel Sambuc 	{
75*433d6423SLionel Sambuc 		printf("%s: using I/O address 0x%lx, IRQ %d\n",
76*433d6423SLionel Sambuc 			dep->de_name, (unsigned long)bar, ilr);
77*433d6423SLionel Sambuc 	}
78*433d6423SLionel Sambuc 	dep->de_initf= rtl_init;
79*433d6423SLionel Sambuc 
80*433d6423SLionel Sambuc 	return TRUE;
81*433d6423SLionel Sambuc }
82*433d6423SLionel Sambuc 
83*433d6423SLionel Sambuc static void rtl_init(dep)
84*433d6423SLionel Sambuc dpeth_t *dep;
85*433d6423SLionel Sambuc {
86*433d6423SLionel Sambuc 	u8_t reg_a, reg_b, cr, config0, config2, config3;
87*433d6423SLionel Sambuc 
88*433d6423SLionel Sambuc #if DEBUG
89*433d6423SLionel Sambuc 	printf("rtl_init called\n");
90*433d6423SLionel Sambuc #endif
91*433d6423SLionel Sambuc 	ne_init(dep);
92*433d6423SLionel Sambuc 
93*433d6423SLionel Sambuc 	/* ID */
94*433d6423SLionel Sambuc 	outb_reg0(dep, DP_CR, CR_PS_P0);
95*433d6423SLionel Sambuc 	reg_a = inb_reg0(dep, DP_DUM1);
96*433d6423SLionel Sambuc 	reg_b = inb_reg0(dep, DP_DUM2);
97*433d6423SLionel Sambuc 
98*433d6423SLionel Sambuc #if DEBUG
99*433d6423SLionel Sambuc 	printf("rtl_init: '%c', '%c'\n", reg_a, reg_b);
100*433d6423SLionel Sambuc #endif
101*433d6423SLionel Sambuc 
102*433d6423SLionel Sambuc 	outb_reg0(dep, DP_CR, CR_PS_P3);
103*433d6423SLionel Sambuc 	config0 = inb_reg3(dep, 3);
104*433d6423SLionel Sambuc 	config2 = inb_reg3(dep, 5);
105*433d6423SLionel Sambuc 	config3 = inb_reg3(dep, 6);
106*433d6423SLionel Sambuc 	outb_reg0(dep, DP_CR, CR_PS_P0);
107*433d6423SLionel Sambuc 
108*433d6423SLionel Sambuc #if DEBUG
109*433d6423SLionel Sambuc 	printf("rtl_init: config 0/2/3 = %x/%x/%x\n",
110*433d6423SLionel Sambuc 		config0, config2, config3);
111*433d6423SLionel Sambuc #endif
112*433d6423SLionel Sambuc 
113*433d6423SLionel Sambuc 	if (getenv("RTL8029FD"))
114*433d6423SLionel Sambuc 	{
115*433d6423SLionel Sambuc 		printf("rtl_init: setting full-duplex mode\n");
116*433d6423SLionel Sambuc 		outb_reg0(dep, DP_CR, CR_PS_P3);
117*433d6423SLionel Sambuc 
118*433d6423SLionel Sambuc 		cr= inb_reg3(dep, 1);
119*433d6423SLionel Sambuc 		outb_reg3(dep, 1, cr | 0xc0);
120*433d6423SLionel Sambuc 
121*433d6423SLionel Sambuc 		outb_reg3(dep, 6, config3 | 0x40);
122*433d6423SLionel Sambuc 		config3 = inb_reg3(dep, 6);
123*433d6423SLionel Sambuc 
124*433d6423SLionel Sambuc 		config2= inb_reg3(dep, 5);
125*433d6423SLionel Sambuc 		outb_reg3(dep, 5, config2 | 0x20);
126*433d6423SLionel Sambuc 		config2= inb_reg3(dep, 5);
127*433d6423SLionel Sambuc 
128*433d6423SLionel Sambuc 		outb_reg3(dep, 1, cr);
129*433d6423SLionel Sambuc 
130*433d6423SLionel Sambuc 		outb_reg0(dep, DP_CR, CR_PS_P0);
131*433d6423SLionel Sambuc 
132*433d6423SLionel Sambuc #if DEBUG
133*433d6423SLionel Sambuc 		printf("rtl_init: config 2 = %x\n", config2);
134*433d6423SLionel Sambuc 		printf("rtl_init: config 3 = %x\n", config3);
135*433d6423SLionel Sambuc #endif
136*433d6423SLionel Sambuc 	}
137*433d6423SLionel Sambuc 
138*433d6423SLionel Sambuc #if 0
139*433d6423SLionel Sambuc 	for (i= 0; i<64; i++)
140*433d6423SLionel Sambuc 		printf("%x ", get_ee_word(dep, i));
141*433d6423SLionel Sambuc 	printf("\n");
142*433d6423SLionel Sambuc #endif
143*433d6423SLionel Sambuc 
144*433d6423SLionel Sambuc #if 0
145*433d6423SLionel Sambuc 	if (getenv("RTL8029MN"))
146*433d6423SLionel Sambuc 	{
147*433d6423SLionel Sambuc 		ee_wen(dep);
148*433d6423SLionel Sambuc 
149*433d6423SLionel Sambuc 		set_ee_word(dep, 0x78/2, 0x10ec);
150*433d6423SLionel Sambuc 		set_ee_word(dep, 0x7A/2, 0x8029);
151*433d6423SLionel Sambuc 		set_ee_word(dep, 0x7C/2, 0x10ec);
152*433d6423SLionel Sambuc 		set_ee_word(dep, 0x7E/2, 0x8029);
153*433d6423SLionel Sambuc 
154*433d6423SLionel Sambuc 		ee_wds(dep);
155*433d6423SLionel Sambuc 
156*433d6423SLionel Sambuc 		assert(get_ee_word(dep, 0x78/2) == 0x10ec);
157*433d6423SLionel Sambuc 		assert(get_ee_word(dep, 0x7A/2) == 0x8029);
158*433d6423SLionel Sambuc 		assert(get_ee_word(dep, 0x7C/2) == 0x10ec);
159*433d6423SLionel Sambuc 		assert(get_ee_word(dep, 0x7E/2) == 0x8029);
160*433d6423SLionel Sambuc 	}
161*433d6423SLionel Sambuc 
162*433d6423SLionel Sambuc 	if (getenv("RTL8029XXX"))
163*433d6423SLionel Sambuc 	{
164*433d6423SLionel Sambuc 		ee_wen(dep);
165*433d6423SLionel Sambuc 
166*433d6423SLionel Sambuc 		set_ee_word(dep, 0x76/2, 0x8029);
167*433d6423SLionel Sambuc 
168*433d6423SLionel Sambuc 		ee_wds(dep);
169*433d6423SLionel Sambuc 
170*433d6423SLionel Sambuc 		assert(get_ee_word(dep, 0x76/2) == 0x8029);
171*433d6423SLionel Sambuc 	}
172*433d6423SLionel Sambuc #endif
173*433d6423SLionel Sambuc }
174*433d6423SLionel Sambuc 
175*433d6423SLionel Sambuc #if 0
176*433d6423SLionel Sambuc static u16_t get_ee_word(dep, a)
177*433d6423SLionel Sambuc dpeth_t *dep;
178*433d6423SLionel Sambuc int a;
179*433d6423SLionel Sambuc {
180*433d6423SLionel Sambuc 	int b, i, cmd;
181*433d6423SLionel Sambuc 	u16_t w;
182*433d6423SLionel Sambuc 
183*433d6423SLionel Sambuc 	outb_reg0(dep, DP_CR, CR_PS_P3);	/* Bank 3 */
184*433d6423SLionel Sambuc 
185*433d6423SLionel Sambuc 	/* Switch to 9346 mode and enable CS */
186*433d6423SLionel Sambuc 	outb_reg3(dep, 1, 0x80 | 0x8);
187*433d6423SLionel Sambuc 
188*433d6423SLionel Sambuc 	cmd= 0x180 | (a & 0x3f);	/* 1 1 0 a5 a4 a3 a2 a1 a0 */
189*433d6423SLionel Sambuc 	for (i= 8; i >= 0; i--)
190*433d6423SLionel Sambuc 	{
191*433d6423SLionel Sambuc 		b= (cmd & (1 << i));
192*433d6423SLionel Sambuc 		b= (b ? 2 : 0);
193*433d6423SLionel Sambuc 
194*433d6423SLionel Sambuc 		/* Cmd goes out on the rising edge of the clock */
195*433d6423SLionel Sambuc 		outb_reg3(dep, 1, 0x80 | 0x8 | b);
196*433d6423SLionel Sambuc 		outb_reg3(dep, 1, 0x80 | 0x8 | 0x4 | b);
197*433d6423SLionel Sambuc 	}
198*433d6423SLionel Sambuc 	outb_reg3(dep, 1, 0x80 | 0x8);	/* End of cmd */
199*433d6423SLionel Sambuc 
200*433d6423SLionel Sambuc 	w= 0;
201*433d6423SLionel Sambuc 	for (i= 0; i<16; i++)
202*433d6423SLionel Sambuc 	{
203*433d6423SLionel Sambuc 		w <<= 1;
204*433d6423SLionel Sambuc 
205*433d6423SLionel Sambuc 		/* Data is shifted out on the rising edge. Read at the
206*433d6423SLionel Sambuc 		 * falling edge.
207*433d6423SLionel Sambuc 		 */
208*433d6423SLionel Sambuc 		outb_reg3(dep, 1, 0x80 | 0x8 | 0x4);
209*433d6423SLionel Sambuc 		outb_reg3(dep, 1, 0x80 | 0x8 | b);
210*433d6423SLionel Sambuc 		b= inb_reg3(dep, 1);
211*433d6423SLionel Sambuc 		w |= (b & 1);
212*433d6423SLionel Sambuc 	}
213*433d6423SLionel Sambuc 
214*433d6423SLionel Sambuc 	outb_reg3(dep, 1, 0x80);		/* drop CS */
215*433d6423SLionel Sambuc 	outb_reg3(dep, 1, 0x00);		/* back to normal */
216*433d6423SLionel Sambuc 	outb_reg0(dep, DP_CR, CR_PS_P0);	/* back to bank 0 */
217*433d6423SLionel Sambuc 
218*433d6423SLionel Sambuc 	return w;
219*433d6423SLionel Sambuc }
220*433d6423SLionel Sambuc 
221*433d6423SLionel Sambuc static void ee_wen(dep)
222*433d6423SLionel Sambuc dpeth_t *dep;
223*433d6423SLionel Sambuc {
224*433d6423SLionel Sambuc 	int b, i, cmd;
225*433d6423SLionel Sambuc 
226*433d6423SLionel Sambuc 	outb_reg0(dep, DP_CR, CR_PS_P3);	/* Bank 3 */
227*433d6423SLionel Sambuc 
228*433d6423SLionel Sambuc 	/* Switch to 9346 mode and enable CS */
229*433d6423SLionel Sambuc 	outb_reg3(dep, 1, 0x80 | 0x8);
230*433d6423SLionel Sambuc 
231*433d6423SLionel Sambuc 	cmd= 0x130;		/* 1 0 0 1 1 x x x x */
232*433d6423SLionel Sambuc 	for (i= 8; i >= 0; i--)
233*433d6423SLionel Sambuc 	{
234*433d6423SLionel Sambuc 		b= (cmd & (1 << i));
235*433d6423SLionel Sambuc 		b= (b ? 2 : 0);
236*433d6423SLionel Sambuc 
237*433d6423SLionel Sambuc 		/* Cmd goes out on the rising edge of the clock */
238*433d6423SLionel Sambuc 		outb_reg3(dep, 1, 0x80 | 0x8 | b);
239*433d6423SLionel Sambuc 		outb_reg3(dep, 1, 0x80 | 0x8 | 0x4 | b);
240*433d6423SLionel Sambuc 	}
241*433d6423SLionel Sambuc 	outb_reg3(dep, 1, 0x80 | 0x8);	/* End of cmd */
242*433d6423SLionel Sambuc 	outb_reg3(dep, 1, 0x80);	/* Drop CS */
243*433d6423SLionel Sambuc 	micro_delay(1);			/* Is this required? */
244*433d6423SLionel Sambuc }
245*433d6423SLionel Sambuc 
246*433d6423SLionel Sambuc static void set_ee_word(dep, a, w)
247*433d6423SLionel Sambuc dpeth_t *dep;
248*433d6423SLionel Sambuc int a;
249*433d6423SLionel Sambuc u16_t w;
250*433d6423SLionel Sambuc {
251*433d6423SLionel Sambuc 	int b, i, cmd;
252*433d6423SLionel Sambuc 
253*433d6423SLionel Sambuc 	outb_reg3(dep, 1, 0x80 | 0x8);		/* Set CS */
254*433d6423SLionel Sambuc 
255*433d6423SLionel Sambuc 	cmd= 0x140 | (a & 0x3f);		/* 1 0 1 a5 a4 a3 a2 a1 a0 */
256*433d6423SLionel Sambuc 	for (i= 8; i >= 0; i--)
257*433d6423SLionel Sambuc 	{
258*433d6423SLionel Sambuc 		b= (cmd & (1 << i));
259*433d6423SLionel Sambuc 		b= (b ? 2 : 0);
260*433d6423SLionel Sambuc 
261*433d6423SLionel Sambuc 		/* Cmd goes out on the rising edge of the clock */
262*433d6423SLionel Sambuc 		outb_reg3(dep, 1, 0x80 | 0x8 | b);
263*433d6423SLionel Sambuc 		outb_reg3(dep, 1, 0x80 | 0x8 | 0x4 | b);
264*433d6423SLionel Sambuc 	}
265*433d6423SLionel Sambuc 	for (i= 15; i >= 0; i--)
266*433d6423SLionel Sambuc 	{
267*433d6423SLionel Sambuc 		b= (w & (1 << i));
268*433d6423SLionel Sambuc 		b= (b ? 2 : 0);
269*433d6423SLionel Sambuc 
270*433d6423SLionel Sambuc 		/* Cmd goes out on the rising edge of the clock */
271*433d6423SLionel Sambuc 		outb_reg3(dep, 1, 0x80 | 0x8 | b);
272*433d6423SLionel Sambuc 		outb_reg3(dep, 1, 0x80 | 0x8 | 0x4 | b);
273*433d6423SLionel Sambuc 	}
274*433d6423SLionel Sambuc 	outb_reg3(dep, 1, 0x80 | 0x8);	/* End of data */
275*433d6423SLionel Sambuc 	outb_reg3(dep, 1, 0x80);	/* Drop CS */
276*433d6423SLionel Sambuc 	micro_delay(1);			/* Is this required? */
277*433d6423SLionel Sambuc 	outb_reg3(dep, 1, 0x80 | 0x8);		/* Set CS */
278*433d6423SLionel Sambuc 	for (i= 0; i<10000; i++)
279*433d6423SLionel Sambuc 	{
280*433d6423SLionel Sambuc 		if (inb_reg3(dep, 1) & 1)
281*433d6423SLionel Sambuc 			break;
282*433d6423SLionel Sambuc 		micro_delay(1);
283*433d6423SLionel Sambuc 	}
284*433d6423SLionel Sambuc 	if (!(inb_reg3(dep, 1) & 1))
285*433d6423SLionel Sambuc 		panic("set_ee_word: device remains busy");
286*433d6423SLionel Sambuc }
287*433d6423SLionel Sambuc 
288*433d6423SLionel Sambuc static void ee_wds(dep)
289*433d6423SLionel Sambuc dpeth_t *dep;
290*433d6423SLionel Sambuc {
291*433d6423SLionel Sambuc 	int b, i, cmd;
292*433d6423SLionel Sambuc 
293*433d6423SLionel Sambuc 	outb_reg0(dep, DP_CR, CR_PS_P3);	/* Bank 3 */
294*433d6423SLionel Sambuc 
295*433d6423SLionel Sambuc 	/* Switch to 9346 mode and enable CS */
296*433d6423SLionel Sambuc 	outb_reg3(dep, 1, 0x80 | 0x8);
297*433d6423SLionel Sambuc 
298*433d6423SLionel Sambuc 	cmd= 0x100;		/* 1 0 0 0 0 x x x x */
299*433d6423SLionel Sambuc 	for (i= 8; i >= 0; i--)
300*433d6423SLionel Sambuc 	{
301*433d6423SLionel Sambuc 		b= (cmd & (1 << i));
302*433d6423SLionel Sambuc 		b= (b ? 2 : 0);
303*433d6423SLionel Sambuc 
304*433d6423SLionel Sambuc 		/* Cmd goes out on the rising edge of the clock */
305*433d6423SLionel Sambuc 		outb_reg3(dep, 1, 0x80 | 0x8 | b);
306*433d6423SLionel Sambuc 		outb_reg3(dep, 1, 0x80 | 0x8 | 0x4 | b);
307*433d6423SLionel Sambuc 	}
308*433d6423SLionel Sambuc 	outb_reg3(dep, 1, 0x80 | 0x8);	/* End of cmd */
309*433d6423SLionel Sambuc 	outb_reg3(dep, 1, 0x80);	/* Drop CS */
310*433d6423SLionel Sambuc 	outb_reg3(dep, 1, 0x00);		/* back to normal */
311*433d6423SLionel Sambuc 	outb_reg0(dep, DP_CR, CR_PS_P0);	/* back to bank 0 */
312*433d6423SLionel Sambuc }
313*433d6423SLionel Sambuc #endif
314*433d6423SLionel Sambuc 
315*433d6423SLionel Sambuc #endif /* ENABLE_PCI */
316*433d6423SLionel Sambuc 
317*433d6423SLionel Sambuc /*
318*433d6423SLionel Sambuc  * $PchId: rtl8029.c,v 1.7 2004/08/03 12:16:58 philip Exp $
319*433d6423SLionel Sambuc  */
320