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