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