1 /* 2 ** Support for NE2000 PCI clones added David Monro June 1997 3 ** Generalised to other NICs by Ken Yap July 1997 4 ** 5 ** Most of this is taken from: 6 ** 7 ** /usr/src/linux/drivers/pci/pci.c 8 ** /usr/src/linux/include/linux/pci.h 9 ** /usr/src/linux/arch/i386/bios32.c 10 ** /usr/src/linux/include/linux/bios32.h 11 ** /usr/src/linux/drivers/net/ne.c 12 */ 13 14 /* 15 * This program is free software; you can redistribute it and/or 16 * modify it under the terms of the GNU General Public License as 17 * published by the Free Software Foundation; either version 2, or (at 18 * your option) any later version. 19 */ 20 21 #include "etherboot.h" 22 #include "pci.h" 23 24 /*#define DEBUG 1*/ 25 #define DEBUG 0 26 27 #ifdef CONFIG_PCI_DIRECT 28 #define PCIBIOS_SUCCESSFUL 0x00 29 30 /* 31 * Functions for accessing PCI configuration space with type 1 accesses 32 */ 33 34 #define CONFIG_CMD(bus, device_fn, where) (0x80000000 | (bus << 16) | (device_fn << 8) | (where & ~3)) 35 36 int pcibios_read_config_byte(unsigned int bus, unsigned int device_fn, 37 unsigned int where, unsigned char *value) 38 { 39 outl(CONFIG_CMD(bus,device_fn,where), 0xCF8); 40 *value = inb(0xCFC + (where&3)); 41 return PCIBIOS_SUCCESSFUL; 42 } 43 44 int pcibios_read_config_word (unsigned int bus, 45 unsigned int device_fn, unsigned int where, unsigned short *value) 46 { 47 outl(CONFIG_CMD(bus,device_fn,where), 0xCF8); 48 *value = inw(0xCFC + (where&2)); 49 return PCIBIOS_SUCCESSFUL; 50 } 51 52 int pcibios_read_config_dword (unsigned int bus, unsigned int device_fn, 53 unsigned int where, unsigned int *value) 54 { 55 outl(CONFIG_CMD(bus,device_fn,where), 0xCF8); 56 *value = inl(0xCFC); 57 return PCIBIOS_SUCCESSFUL; 58 } 59 60 int pcibios_write_config_byte (unsigned int bus, unsigned int device_fn, 61 unsigned int where, unsigned char value) 62 { 63 outl(CONFIG_CMD(bus,device_fn,where), 0xCF8); 64 outb(value, 0xCFC + (where&3)); 65 return PCIBIOS_SUCCESSFUL; 66 } 67 68 int pcibios_write_config_word (unsigned int bus, unsigned int device_fn, 69 unsigned int where, unsigned short value) 70 { 71 outl(CONFIG_CMD(bus,device_fn,where), 0xCF8); 72 outw(value, 0xCFC + (where&2)); 73 return PCIBIOS_SUCCESSFUL; 74 } 75 76 int pcibios_write_config_dword (unsigned int bus, unsigned int device_fn, unsigned int where, unsigned int value) 77 { 78 outl(CONFIG_CMD(bus,device_fn,where), 0xCF8); 79 outl(value, 0xCFC); 80 return PCIBIOS_SUCCESSFUL; 81 } 82 83 #undef CONFIG_CMD 84 85 #else /* CONFIG_PCI_DIRECT not defined */ 86 87 static struct { 88 unsigned long address; 89 unsigned short segment; 90 } bios32_indirect = { 0, KERN_CODE_SEG }; 91 92 static long pcibios_entry; 93 static struct { 94 unsigned long address; 95 unsigned short segment; 96 } pci_indirect = { 0, KERN_CODE_SEG }; 97 98 static unsigned long bios32_service(unsigned long service) 99 { 100 unsigned char return_code; /* %al */ 101 unsigned long address; /* %ebx */ 102 unsigned long length; /* %ecx */ 103 unsigned long entry; /* %edx */ 104 unsigned long flags; 105 106 save_flags(flags); 107 __asm__( 108 #ifdef ABSOLUTE_WITHOUT_ASTERISK 109 "lcall (%%edi)" 110 #else 111 "lcall *(%%edi)" 112 #endif 113 : "=a" (return_code), 114 "=b" (address), 115 "=c" (length), 116 "=d" (entry) 117 : "0" (service), 118 "1" (0), 119 "D" (&bios32_indirect)); 120 restore_flags(flags); 121 122 switch (return_code) { 123 case 0: 124 return address + entry; 125 case 0x80: /* Not present */ 126 printf("bios32_service(%d) : not present\n", service); 127 return 0; 128 default: /* Shouldn't happen */ 129 printf("bios32_service(%d) : returned %#X, mail drew (at) colorado.edu\n", 130 service, return_code); 131 return 0; 132 } 133 } 134 135 int pcibios_read_config_byte(unsigned int bus, 136 unsigned int device_fn, unsigned int where, unsigned char *value) 137 { 138 unsigned long ret; 139 unsigned long bx = (bus << 8) | device_fn; 140 unsigned long flags; 141 142 save_flags(flags); 143 __asm__( 144 #ifdef ABSOLUTE_WITHOUT_ASTERISK 145 "lcall (%%esi)\n\t" 146 #else 147 "lcall *(%%esi)\n\t" 148 #endif 149 "jc 1f\n\t" 150 "xor %%ah, %%ah\n" 151 "1:" 152 : "=c" (*value), 153 "=a" (ret) 154 : "1" (PCIBIOS_READ_CONFIG_BYTE), 155 "b" (bx), 156 "D" ((long) where), 157 "S" (&pci_indirect)); 158 restore_flags(flags); 159 return (int) (ret & 0xff00) >> 8; 160 } 161 162 int pcibios_read_config_word(unsigned int bus, 163 unsigned int device_fn, unsigned int where, unsigned short *value) 164 { 165 unsigned long ret; 166 unsigned long bx = (bus << 8) | device_fn; 167 unsigned long flags; 168 169 save_flags(flags); 170 __asm__( 171 #ifdef ABSOLUTE_WITHOUT_ASTERISK 172 "lcall (%%esi)\n\t" 173 #else 174 "lcall *(%%esi)\n\t" 175 #endif 176 "jc 1f\n\t" 177 "xor %%ah, %%ah\n" 178 "1:" 179 : "=c" (*value), 180 "=a" (ret) 181 : "1" (PCIBIOS_READ_CONFIG_WORD), 182 "b" (bx), 183 "D" ((long) where), 184 "S" (&pci_indirect)); 185 restore_flags(flags); 186 return (int) (ret & 0xff00) >> 8; 187 } 188 189 int pcibios_read_config_dword(unsigned int bus, 190 unsigned int device_fn, unsigned int where, unsigned int *value) 191 { 192 unsigned long ret; 193 unsigned long bx = (bus << 8) | device_fn; 194 unsigned long flags; 195 196 save_flags(flags); 197 __asm__( 198 #ifdef ABSOLUTE_WITHOUT_ASTERISK 199 "lcall (%%esi)\n\t" 200 #else 201 "lcall *(%%esi)\n\t" 202 #endif 203 "jc 1f\n\t" 204 "xor %%ah, %%ah\n" 205 "1:" 206 : "=c" (*value), 207 "=a" (ret) 208 : "1" (PCIBIOS_READ_CONFIG_DWORD), 209 "b" (bx), 210 "D" ((long) where), 211 "S" (&pci_indirect)); 212 restore_flags(flags); 213 return (int) (ret & 0xff00) >> 8; 214 } 215 216 int pcibios_write_config_byte (unsigned int bus, 217 unsigned int device_fn, unsigned int where, unsigned char value) 218 { 219 unsigned long ret; 220 unsigned long bx = (bus << 8) | device_fn; 221 unsigned long flags; 222 223 save_flags(flags); cli(); 224 __asm__( 225 #ifdef ABSOLUTE_WITHOUT_ASTERISK 226 "lcall (%%esi)\n\t" 227 #else 228 "lcall *(%%esi)\n\t" 229 #endif 230 "jc 1f\n\t" 231 "xor %%ah, %%ah\n" 232 "1:" 233 : "=a" (ret) 234 : "0" (PCIBIOS_WRITE_CONFIG_BYTE), 235 "c" (value), 236 "b" (bx), 237 "D" ((long) where), 238 "S" (&pci_indirect)); 239 restore_flags(flags); 240 return (int) (ret & 0xff00) >> 8; 241 } 242 243 int pcibios_write_config_word (unsigned int bus, 244 unsigned int device_fn, unsigned int where, unsigned short value) 245 { 246 unsigned long ret; 247 unsigned long bx = (bus << 8) | device_fn; 248 unsigned long flags; 249 250 save_flags(flags); cli(); 251 __asm__( 252 #ifdef ABSOLUTE_WITHOUT_ASTERISK 253 "lcall (%%esi)\n\t" 254 #else 255 "lcall *(%%esi)\n\t" 256 #endif 257 "jc 1f\n\t" 258 "xor %%ah, %%ah\n" 259 "1:" 260 : "=a" (ret) 261 : "0" (PCIBIOS_WRITE_CONFIG_WORD), 262 "c" (value), 263 "b" (bx), 264 "D" ((long) where), 265 "S" (&pci_indirect)); 266 restore_flags(flags); 267 return (int) (ret & 0xff00) >> 8; 268 } 269 270 int pcibios_write_config_dword (unsigned int bus, 271 unsigned int device_fn, unsigned int where, unsigned int value) 272 { 273 unsigned long ret; 274 unsigned long bx = (bus << 8) | device_fn; 275 unsigned long flags; 276 277 save_flags(flags); cli(); 278 __asm__( 279 #ifdef ABSOLUTE_WITHOUT_ASTERISK 280 "lcall (%%esi)\n\t" 281 #else 282 "lcall *(%%esi)\n\t" 283 #endif 284 "jc 1f\n\t" 285 "xor %%ah, %%ah\n" 286 "1:" 287 : "=a" (ret) 288 : "0" (PCIBIOS_WRITE_CONFIG_DWORD), 289 "c" (value), 290 "b" (bx), 291 "D" ((long) where), 292 "S" (&pci_indirect)); 293 restore_flags(flags); 294 return (int) (ret & 0xff00) >> 8; 295 } 296 297 static void check_pcibios(void) 298 { 299 unsigned long signature; 300 unsigned char present_status; 301 unsigned char major_revision; 302 unsigned char minor_revision; 303 unsigned long flags; 304 int pack; 305 306 if ((pcibios_entry = bios32_service(PCI_SERVICE))) { 307 pci_indirect.address = pcibios_entry; 308 309 save_flags(flags); 310 __asm__( 311 #ifdef ABSOLUTE_WITHOUT_ASTERISK 312 "lcall (%%edi)\n\t" 313 #else 314 "lcall *(%%edi)\n\t" 315 #endif 316 "jc 1f\n\t" 317 "xor %%ah, %%ah\n" 318 "1:\tshl $8, %%eax\n\t" 319 "movw %%bx, %%ax" 320 : "=d" (signature), 321 "=a" (pack) 322 : "1" (PCIBIOS_PCI_BIOS_PRESENT), 323 "D" (&pci_indirect) 324 : "bx", "cx"); 325 restore_flags(flags); 326 327 present_status = (pack >> 16) & 0xff; 328 major_revision = (pack >> 8) & 0xff; 329 minor_revision = pack & 0xff; 330 if (present_status || (signature != PCI_SIGNATURE)) { 331 printf("ERROR: BIOS32 says PCI BIOS, but no PCI " 332 "BIOS????\n"); 333 pcibios_entry = 0; 334 } 335 #if DEBUG 336 if (pcibios_entry) { 337 printf ("pcibios_init : PCI BIOS revision %hhX.%hhX" 338 " entry at %#X\n", major_revision, 339 minor_revision, pcibios_entry); 340 } 341 #endif 342 } 343 } 344 345 static void pcibios_init(void) 346 { 347 union bios32 *check; 348 unsigned char sum; 349 int i, length; 350 unsigned long bios32_entry = 0; 351 352 /* 353 * Follow the standard procedure for locating the BIOS32 Service 354 * directory by scanning the permissible address range from 355 * 0xe0000 through 0xfffff for a valid BIOS32 structure. 356 * 357 */ 358 359 for (check = (union bios32 *) 0xe0000; check <= (union bios32 *) 0xffff0; ++check) { 360 if (check->fields.signature != BIOS32_SIGNATURE) 361 continue; 362 length = check->fields.length * 16; 363 if (!length) 364 continue; 365 sum = 0; 366 for (i = 0; i < length ; ++i) 367 sum += check->chars[i]; 368 if (sum != 0) 369 continue; 370 if (check->fields.revision != 0) { 371 printf("pcibios_init : unsupported revision %d at %#X, mail drew (at) colorado.edu\n", 372 check->fields.revision, check); 373 continue; 374 } 375 #if DEBUG 376 printf("pcibios_init : BIOS32 Service Directory " 377 "structure at %#X\n", check); 378 #endif 379 if (!bios32_entry) { 380 if (check->fields.entry >= 0x100000) { 381 printf("pcibios_init: entry in high " 382 "memory, giving up\n"); 383 return; 384 } else { 385 bios32_entry = check->fields.entry; 386 #if DEBUG 387 printf("pcibios_init : BIOS32 Service Directory" 388 " entry at %#X\n", bios32_entry); 389 #endif 390 bios32_indirect.address = bios32_entry; 391 } 392 } 393 } 394 if (bios32_entry) 395 check_pcibios(); 396 } 397 #endif /* CONFIG_PCI_DIRECT not defined*/ 398 399 static void scan_bus(struct pci_device *pcidev) 400 { 401 unsigned int devfn, l, bus, buses; 402 unsigned char hdr_type = 0; 403 unsigned short vendor, device; 404 unsigned int membase, ioaddr, romaddr; 405 int i, reg; 406 unsigned int pci_ioaddr = 0; 407 408 /* Scan all PCI buses, until we find our card. 409 * We could be smart only scan the required busses but that 410 * is error prone, and tricky. 411 * By scanning all possible pci busses in order we should find 412 * our card eventually. 413 */ 414 buses=256; 415 for (bus = 0; bus < buses; ++bus) { 416 for (devfn = 0; devfn < 0xff; ++devfn) { 417 if (PCI_FUNC (devfn) == 0) 418 pcibios_read_config_byte(bus, devfn, PCI_HEADER_TYPE, &hdr_type); 419 else if (!(hdr_type & 0x80)) /* not a multi-function device */ 420 continue; 421 pcibios_read_config_dword(bus, devfn, PCI_VENDOR_ID, &l); 422 /* some broken boards return 0 if a slot is empty: */ 423 if (l == 0xffffffff || l == 0x00000000) { 424 hdr_type = 0; 425 continue; 426 } 427 vendor = l & 0xffff; 428 device = (l >> 16) & 0xffff; 429 430 #if DEBUG 431 printf("bus %hhX, function %hhX, vendor %hX, device %hX\n", 432 bus, devfn, vendor, device); 433 #endif 434 for (i = 0; pcidev[i].vendor != 0; i++) { 435 if (vendor != pcidev[i].vendor 436 || device != pcidev[i].dev_id) 437 continue; 438 pcidev[i].devfn = devfn; 439 pcidev[i].bus = bus; 440 for (reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg += 4) { 441 pcibios_read_config_dword(bus, devfn, reg, &ioaddr); 442 443 if ((ioaddr & PCI_BASE_ADDRESS_IO_MASK) == 0 || (ioaddr & PCI_BASE_ADDRESS_SPACE_IO) == 0) 444 continue; 445 /* Strip the I/O address out of the returned value */ 446 ioaddr &= PCI_BASE_ADDRESS_IO_MASK; 447 /* Get the memory base address */ 448 pcibios_read_config_dword(bus, devfn, 449 PCI_BASE_ADDRESS_1, &membase); 450 /* Get the ROM base address */ 451 pcibios_read_config_dword(bus, devfn, PCI_ROM_ADDRESS, &romaddr); 452 romaddr >>= 10; 453 printf("Found %s at %#hx, ROM address %#hx\n", 454 pcidev[i].name, ioaddr, romaddr); 455 /* Take the first one or the one that matches in boot ROM address */ 456 if (pci_ioaddr == 0 || romaddr == ((unsigned long) rom.rom_segment << 4)) { 457 pcidev[i].membase = membase; 458 pcidev[i].ioaddr = ioaddr; 459 return; 460 } 461 } 462 } 463 } 464 } 465 } 466 467 void eth_pci_init(struct pci_device *pcidev) 468 { 469 #ifndef CONFIG_PCI_DIRECT 470 pcibios_init(); 471 if (!pcibios_entry) { 472 printf("pci_init: no BIOS32 detected\n"); 473 return; 474 } 475 #endif 476 scan_bus(pcidev); 477 /* return values are in pcidev structures */ 478 } 479 480 /* 481 * Set device to be a busmaster in case BIOS neglected to do so. 482 * Also adjust PCI latency timer to a reasonable value, 32. 483 */ 484 void adjust_pci_device(struct pci_device *p) 485 { 486 unsigned short new_command, pci_command; 487 unsigned char pci_latency; 488 489 pcibios_read_config_word(p->bus, p->devfn, PCI_COMMAND, &pci_command); 490 new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO; 491 if (pci_command != new_command) { 492 printf("The PCI BIOS has not enabled this device!\nUpdating PCI command %hX->%hX. pci_bus %hhX pci_device_fn %hhX\n", 493 pci_command, new_command, p->bus, p->devfn); 494 pcibios_write_config_word(p->bus, p->devfn, PCI_COMMAND, new_command); 495 } 496 pcibios_read_config_byte(p->bus, p->devfn, PCI_LATENCY_TIMER, &pci_latency); 497 if (pci_latency < 32) { 498 printf("PCI latency timer (CFLT) is unreasonably low at %d. Setting to 32 clocks.\n", pci_latency); 499 pcibios_write_config_byte(p->bus, p->devfn, PCI_LATENCY_TIMER, 32); 500 } 501 } 502