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