4 Initialization of PCI DP8390-based ethernet cards
6 Created: April 2000 by Philip Homburg <philip@f-mnx.phicoh.com>
9 #include "../drivers.h"
12 #include <sys/types.h>
13 #include <net/gen/ether.h>
14 #include <net/gen/eth_io.h>
25 #define MICROS_TO_TICKS(m) (((m)*HZ/1000000)+1)
34 { 0x10ec, 0x8029, 0 }, /* Realtek RTL8029 */
39 _PROTOTYPE( static void rtl_init
, (struct dpeth
*dep
) );
40 _PROTOTYPE( static u16_t get_ee_word
, (dpeth_t
*dep
, int a
) );
41 _PROTOTYPE( static void ee_wen
, (dpeth_t
*dep
) );
42 _PROTOTYPE( static void set_ee_word
, (dpeth_t
*dep
, int a
, U16_t w
) );
43 _PROTOTYPE( static void ee_wds
, (dpeth_t
*dep
) );
44 _PROTOTYPE( static void micro_delay
, (unsigned long usecs
) );
46 PUBLIC
int rtl_probe(dep
)
49 int i
, r
, devind
, just_one
;
57 if ((dep
->de_pcibus
| dep
->de_pcidev
| dep
->de_pcifunc
) != 0)
59 /* Look for specific PCI device */
60 r
= pci_find_dev(dep
->de_pcibus
, dep
->de_pcidev
,
61 dep
->de_pcifunc
, &devind
);
64 printf("%s: no PCI found at %d.%d.%d\n",
65 dep
->de_name
, dep
->de_pcibus
,
66 dep
->de_pcidev
, dep
->de_pcifunc
);
69 pci_ids(devind
, &vid
, &did
);
74 r
= pci_first_dev(&devind
, &vid
, &did
);
82 for (i
= 0; pcitab
[i
].vid
!= 0; i
++)
84 if (pcitab
[i
].vid
!= vid
)
86 if (pcitab
[i
].did
!= did
)
88 if (pcitab
[i
].checkclass
)
91 "rtl_probe: class check not implemented",
96 if (pcitab
[i
].vid
!= 0)
102 "%s: wrong PCI device (%04X/%04X) found at %d.%d.%d\n",
103 dep
->de_name
, vid
, did
,
105 dep
->de_pcidev
, dep
->de_pcifunc
);
109 r
= pci_next_dev(&devind
, &vid
, &did
);
114 dname
= pci_dev_name(vid
, did
);
116 dname
= "unknown device";
117 printf("%s: %s (%04X/%04X) at %s\n",
118 dep
->de_name
, dname
, vid
, did
, pci_slot_name(devind
));
120 /* printf("cr = 0x%x\n", pci_attr_r16(devind, PCI_CR)); */
121 bar
= pci_attr_r32(devind
, PCI_BAR
) & 0xffffffe0;
124 panic("", "base address is not properly configured", NO_NUM
);
126 dep
->de_base_port
= bar
;
128 ilr
= pci_attr_r8(devind
, PCI_ILR
);
132 printf("%s: using I/O address 0x%lx, IRQ %d\n",
133 dep
->de_name
, (unsigned long)bar
, ilr
);
135 dep
->de_initf
= rtl_init
;
140 static void rtl_init(dep
)
143 u8_t reg_a
, reg_b
, cr
, config0
, config2
, config3
;
147 printf("rtl_init called\n");
152 outb_reg0(dep
, DP_CR
, CR_PS_P0
);
153 reg_a
= inb_reg0(dep
, DP_DUM1
);
154 reg_b
= inb_reg0(dep
, DP_DUM2
);
157 printf("rtl_init: '%c', '%c'\n", reg_a
, reg_b
);
160 outb_reg0(dep
, DP_CR
, CR_PS_P3
);
161 config0
= inb_reg3(dep
, 3);
162 config2
= inb_reg3(dep
, 5);
163 config3
= inb_reg3(dep
, 6);
164 outb_reg0(dep
, DP_CR
, CR_PS_P0
);
167 printf("rtl_init: config 0/2/3 = %x/%x/%x\n",
168 config0
, config2
, config3
);
171 if (getenv("RTL8029FD"))
173 printf("rtl_init: setting full-duplex mode\n");
174 outb_reg0(dep
, DP_CR
, CR_PS_P3
);
176 cr
= inb_reg3(dep
, 1);
177 outb_reg3(dep
, 1, cr
| 0xc0);
179 outb_reg3(dep
, 6, config3
| 0x40);
180 config3
= inb_reg3(dep
, 6);
182 config2
= inb_reg3(dep
, 5);
183 outb_reg3(dep
, 5, config2
| 0x20);
184 config2
= inb_reg3(dep
, 5);
186 outb_reg3(dep
, 1, cr
);
188 outb_reg0(dep
, DP_CR
, CR_PS_P0
);
191 printf("rtl_init: config 2 = %x\n", config2
);
192 printf("rtl_init: config 3 = %x\n", config3
);
197 for (i
= 0; i
<64; i
++)
198 printf("%x ", get_ee_word(dep
, i
));
202 if (getenv("RTL8029MN"))
206 set_ee_word(dep
, 0x78/2, 0x10ec);
207 set_ee_word(dep
, 0x7A/2, 0x8029);
208 set_ee_word(dep
, 0x7C/2, 0x10ec);
209 set_ee_word(dep
, 0x7E/2, 0x8029);
213 assert(get_ee_word(dep
, 0x78/2) == 0x10ec);
214 assert(get_ee_word(dep
, 0x7A/2) == 0x8029);
215 assert(get_ee_word(dep
, 0x7C/2) == 0x10ec);
216 assert(get_ee_word(dep
, 0x7E/2) == 0x8029);
219 if (getenv("RTL8029XXX"))
223 set_ee_word(dep
, 0x76/2, 0x8029);
227 assert(get_ee_word(dep
, 0x76/2) == 0x8029);
231 static u16_t
get_ee_word(dep
, a
)
238 outb_reg0(dep
, DP_CR
, CR_PS_P3
); /* Bank 3 */
240 /* Switch to 9346 mode and enable CS */
241 outb_reg3(dep
, 1, 0x80 | 0x8);
243 cmd
= 0x180 | (a
& 0x3f); /* 1 1 0 a5 a4 a3 a2 a1 a0 */
244 for (i
= 8; i
>= 0; i
--)
249 /* Cmd goes out on the rising edge of the clock */
250 outb_reg3(dep
, 1, 0x80 | 0x8 | b
);
251 outb_reg3(dep
, 1, 0x80 | 0x8 | 0x4 | b
);
253 outb_reg3(dep
, 1, 0x80 | 0x8); /* End of cmd */
256 for (i
= 0; i
<16; i
++)
260 /* Data is shifted out on the rising edge. Read at the
263 outb_reg3(dep
, 1, 0x80 | 0x8 | 0x4);
264 outb_reg3(dep
, 1, 0x80 | 0x8 | b
);
269 outb_reg3(dep
, 1, 0x80); /* drop CS */
270 outb_reg3(dep
, 1, 0x00); /* back to normal */
271 outb_reg0(dep
, DP_CR
, CR_PS_P0
); /* back to bank 0 */
276 static void ee_wen(dep
)
281 outb_reg0(dep
, DP_CR
, CR_PS_P3
); /* Bank 3 */
283 /* Switch to 9346 mode and enable CS */
284 outb_reg3(dep
, 1, 0x80 | 0x8);
286 cmd
= 0x130; /* 1 0 0 1 1 x x x x */
287 for (i
= 8; i
>= 0; i
--)
292 /* Cmd goes out on the rising edge of the clock */
293 outb_reg3(dep
, 1, 0x80 | 0x8 | b
);
294 outb_reg3(dep
, 1, 0x80 | 0x8 | 0x4 | b
);
296 outb_reg3(dep
, 1, 0x80 | 0x8); /* End of cmd */
297 outb_reg3(dep
, 1, 0x80); /* Drop CS */
298 micro_delay(1); /* Is this required? */
301 static void set_ee_word(dep
, a
, w
)
308 outb_reg3(dep
, 1, 0x80 | 0x8); /* Set CS */
310 cmd
= 0x140 | (a
& 0x3f); /* 1 0 1 a5 a4 a3 a2 a1 a0 */
311 for (i
= 8; i
>= 0; i
--)
316 /* Cmd goes out on the rising edge of the clock */
317 outb_reg3(dep
, 1, 0x80 | 0x8 | b
);
318 outb_reg3(dep
, 1, 0x80 | 0x8 | 0x4 | b
);
320 for (i
= 15; i
>= 0; i
--)
325 /* Cmd goes out on the rising edge of the clock */
326 outb_reg3(dep
, 1, 0x80 | 0x8 | b
);
327 outb_reg3(dep
, 1, 0x80 | 0x8 | 0x4 | b
);
329 outb_reg3(dep
, 1, 0x80 | 0x8); /* End of data */
330 outb_reg3(dep
, 1, 0x80); /* Drop CS */
331 micro_delay(1); /* Is this required? */
332 outb_reg3(dep
, 1, 0x80 | 0x8); /* Set CS */
333 for (i
= 0; i
<10000; i
++)
335 if (inb_reg3(dep
, 1) & 1)
339 if (!(inb_reg3(dep
, 1) & 1))
340 panic("", "set_ee_word: device remains busy", NO_NUM
);
343 static void ee_wds(dep
)
348 outb_reg0(dep
, DP_CR
, CR_PS_P3
); /* Bank 3 */
350 /* Switch to 9346 mode and enable CS */
351 outb_reg3(dep
, 1, 0x80 | 0x8);
353 cmd
= 0x100; /* 1 0 0 0 0 x x x x */
354 for (i
= 8; i
>= 0; i
--)
359 /* Cmd goes out on the rising edge of the clock */
360 outb_reg3(dep
, 1, 0x80 | 0x8 | b
);
361 outb_reg3(dep
, 1, 0x80 | 0x8 | 0x4 | b
);
363 outb_reg3(dep
, 1, 0x80 | 0x8); /* End of cmd */
364 outb_reg3(dep
, 1, 0x80); /* Drop CS */
365 outb_reg3(dep
, 1, 0x00); /* back to normal */
366 outb_reg0(dep
, DP_CR
, CR_PS_P0
); /* back to bank 0 */
369 static void micro_delay(unsigned long usecs
)
371 tickdelay(MICROS_TO_TICKS(usecs
));
374 #endif /* ENABLE_PCI */
377 * $PchId: rtl8029.c,v 1.7 2004/08/03 12:16:58 philip Exp $