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