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