1*1b8adde7SWilliam Kucharski /* 2*1b8adde7SWilliam Kucharski ** Support for NE2000 PCI clones added David Monro June 1997 3*1b8adde7SWilliam Kucharski ** Generalised to other NICs by Ken Yap July 1997 4*1b8adde7SWilliam Kucharski ** 5*1b8adde7SWilliam Kucharski ** Most of this is taken from: 6*1b8adde7SWilliam Kucharski ** 7*1b8adde7SWilliam Kucharski ** /usr/src/linux/drivers/pci/pci.c 8*1b8adde7SWilliam Kucharski ** /usr/src/linux/include/linux/pci.h 9*1b8adde7SWilliam Kucharski ** /usr/src/linux/arch/i386/bios32.c 10*1b8adde7SWilliam Kucharski ** /usr/src/linux/include/linux/bios32.h 11*1b8adde7SWilliam Kucharski ** /usr/src/linux/drivers/net/ne.c 12*1b8adde7SWilliam Kucharski */ 13*1b8adde7SWilliam Kucharski #define PCBIOS 14*1b8adde7SWilliam Kucharski #include "grub.h" 15*1b8adde7SWilliam Kucharski #include "pci.h" 16*1b8adde7SWilliam Kucharski 17*1b8adde7SWilliam Kucharski #ifdef CONFIG_PCI_DIRECT 18*1b8adde7SWilliam Kucharski #define PCIBIOS_SUCCESSFUL 0x00 19*1b8adde7SWilliam Kucharski 20*1b8adde7SWilliam Kucharski #define DEBUG 0 21*1b8adde7SWilliam Kucharski 22*1b8adde7SWilliam Kucharski /* 23*1b8adde7SWilliam Kucharski * Functions for accessing PCI configuration space with type 1 accesses 24*1b8adde7SWilliam Kucharski */ 25*1b8adde7SWilliam Kucharski 26*1b8adde7SWilliam Kucharski #define CONFIG_CMD(bus, device_fn, where) (0x80000000 | (bus << 16) | (device_fn << 8) | (where & ~3)) 27*1b8adde7SWilliam Kucharski 28*1b8adde7SWilliam Kucharski int pcibios_read_config_byte(unsigned int bus, unsigned int device_fn, 29*1b8adde7SWilliam Kucharski unsigned int where, uint8_t *value) 30*1b8adde7SWilliam Kucharski { 31*1b8adde7SWilliam Kucharski outl(CONFIG_CMD(bus,device_fn,where), 0xCF8); 32*1b8adde7SWilliam Kucharski *value = inb(0xCFC + (where&3)); 33*1b8adde7SWilliam Kucharski return PCIBIOS_SUCCESSFUL; 34*1b8adde7SWilliam Kucharski } 35*1b8adde7SWilliam Kucharski 36*1b8adde7SWilliam Kucharski int pcibios_read_config_word (unsigned int bus, 37*1b8adde7SWilliam Kucharski unsigned int device_fn, unsigned int where, uint16_t *value) 38*1b8adde7SWilliam Kucharski { 39*1b8adde7SWilliam Kucharski outl(CONFIG_CMD(bus,device_fn,where), 0xCF8); 40*1b8adde7SWilliam Kucharski *value = inw(0xCFC + (where&2)); 41*1b8adde7SWilliam Kucharski return PCIBIOS_SUCCESSFUL; 42*1b8adde7SWilliam Kucharski } 43*1b8adde7SWilliam Kucharski 44*1b8adde7SWilliam Kucharski int pcibios_read_config_dword (unsigned int bus, unsigned int device_fn, 45*1b8adde7SWilliam Kucharski unsigned int where, uint32_t *value) 46*1b8adde7SWilliam Kucharski { 47*1b8adde7SWilliam Kucharski outl(CONFIG_CMD(bus,device_fn,where), 0xCF8); 48*1b8adde7SWilliam Kucharski *value = inl(0xCFC); 49*1b8adde7SWilliam Kucharski return PCIBIOS_SUCCESSFUL; 50*1b8adde7SWilliam Kucharski } 51*1b8adde7SWilliam Kucharski 52*1b8adde7SWilliam Kucharski int pcibios_write_config_byte (unsigned int bus, unsigned int device_fn, 53*1b8adde7SWilliam Kucharski unsigned int where, uint8_t value) 54*1b8adde7SWilliam Kucharski { 55*1b8adde7SWilliam Kucharski outl(CONFIG_CMD(bus,device_fn,where), 0xCF8); 56*1b8adde7SWilliam Kucharski outb(value, 0xCFC + (where&3)); 57*1b8adde7SWilliam Kucharski return PCIBIOS_SUCCESSFUL; 58*1b8adde7SWilliam Kucharski } 59*1b8adde7SWilliam Kucharski 60*1b8adde7SWilliam Kucharski int pcibios_write_config_word (unsigned int bus, unsigned int device_fn, 61*1b8adde7SWilliam Kucharski unsigned int where, uint16_t value) 62*1b8adde7SWilliam Kucharski { 63*1b8adde7SWilliam Kucharski outl(CONFIG_CMD(bus,device_fn,where), 0xCF8); 64*1b8adde7SWilliam Kucharski outw(value, 0xCFC + (where&2)); 65*1b8adde7SWilliam Kucharski return PCIBIOS_SUCCESSFUL; 66*1b8adde7SWilliam Kucharski } 67*1b8adde7SWilliam Kucharski 68*1b8adde7SWilliam Kucharski int pcibios_write_config_dword (unsigned int bus, unsigned int device_fn, unsigned int where, uint32_t value) 69*1b8adde7SWilliam Kucharski { 70*1b8adde7SWilliam Kucharski outl(CONFIG_CMD(bus,device_fn,where), 0xCF8); 71*1b8adde7SWilliam Kucharski outl(value, 0xCFC); 72*1b8adde7SWilliam Kucharski return PCIBIOS_SUCCESSFUL; 73*1b8adde7SWilliam Kucharski } 74*1b8adde7SWilliam Kucharski 75*1b8adde7SWilliam Kucharski #undef CONFIG_CMD 76*1b8adde7SWilliam Kucharski 77*1b8adde7SWilliam Kucharski #else /* CONFIG_PCI_DIRECT not defined */ 78*1b8adde7SWilliam Kucharski 79*1b8adde7SWilliam Kucharski #if !defined(PCBIOS) 80*1b8adde7SWilliam Kucharski #error "The pcibios can only be used when the PCBIOS support is compiled in" 81*1b8adde7SWilliam Kucharski #endif 82*1b8adde7SWilliam Kucharski 83*1b8adde7SWilliam Kucharski 84*1b8adde7SWilliam Kucharski #define KERN_CODE_SEG 0X8 85*1b8adde7SWilliam Kucharski /* Stuff for asm */ 86*1b8adde7SWilliam Kucharski #define save_flags(x) \ 87*1b8adde7SWilliam Kucharski __asm__ __volatile__("pushfl ; popl %0":"=g" (x): /* no input */ :"memory") 88*1b8adde7SWilliam Kucharski 89*1b8adde7SWilliam Kucharski #define cli() __asm__ __volatile__ ("cli": : :"memory") 90*1b8adde7SWilliam Kucharski 91*1b8adde7SWilliam Kucharski #define restore_flags(x) \ 92*1b8adde7SWilliam Kucharski __asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory") 93*1b8adde7SWilliam Kucharski 94*1b8adde7SWilliam Kucharski 95*1b8adde7SWilliam Kucharski 96*1b8adde7SWilliam Kucharski static struct { 97*1b8adde7SWilliam Kucharski unsigned long address; 98*1b8adde7SWilliam Kucharski unsigned short segment; 99*1b8adde7SWilliam Kucharski } bios32_indirect = { 0, KERN_CODE_SEG }; 100*1b8adde7SWilliam Kucharski 101*1b8adde7SWilliam Kucharski static long pcibios_entry = 0; 102*1b8adde7SWilliam Kucharski static struct { 103*1b8adde7SWilliam Kucharski unsigned long address; 104*1b8adde7SWilliam Kucharski unsigned short segment; 105*1b8adde7SWilliam Kucharski } pci_indirect = { 0, KERN_CODE_SEG }; 106*1b8adde7SWilliam Kucharski 107*1b8adde7SWilliam Kucharski static unsigned long bios32_service(unsigned long service) 108*1b8adde7SWilliam Kucharski { 109*1b8adde7SWilliam Kucharski unsigned char return_code; /* %al */ 110*1b8adde7SWilliam Kucharski unsigned long address; /* %ebx */ 111*1b8adde7SWilliam Kucharski unsigned long length; /* %ecx */ 112*1b8adde7SWilliam Kucharski unsigned long entry; /* %edx */ 113*1b8adde7SWilliam Kucharski unsigned long flags; 114*1b8adde7SWilliam Kucharski 115*1b8adde7SWilliam Kucharski save_flags(flags); 116*1b8adde7SWilliam Kucharski __asm__( 117*1b8adde7SWilliam Kucharski #ifdef ABSOLUTE_WITHOUT_ASTERISK 118*1b8adde7SWilliam Kucharski "lcall (%%edi)" 119*1b8adde7SWilliam Kucharski #else 120*1b8adde7SWilliam Kucharski "lcall *(%%edi)" 121*1b8adde7SWilliam Kucharski #endif 122*1b8adde7SWilliam Kucharski : "=a" (return_code), 123*1b8adde7SWilliam Kucharski "=b" (address), 124*1b8adde7SWilliam Kucharski "=c" (length), 125*1b8adde7SWilliam Kucharski "=d" (entry) 126*1b8adde7SWilliam Kucharski : "0" (service), 127*1b8adde7SWilliam Kucharski "1" (0), 128*1b8adde7SWilliam Kucharski "D" (&bios32_indirect)); 129*1b8adde7SWilliam Kucharski restore_flags(flags); 130*1b8adde7SWilliam Kucharski 131*1b8adde7SWilliam Kucharski switch (return_code) { 132*1b8adde7SWilliam Kucharski case 0: 133*1b8adde7SWilliam Kucharski return address + entry; 134*1b8adde7SWilliam Kucharski case 0x80: /* Not present */ 135*1b8adde7SWilliam Kucharski printf("bios32_service(%d) : not present\n", service); 136*1b8adde7SWilliam Kucharski return 0; 137*1b8adde7SWilliam Kucharski default: /* Shouldn't happen */ 138*1b8adde7SWilliam Kucharski printf("bios32_service(%d) : returned %#X, mail drew@colorado.edu\n", 139*1b8adde7SWilliam Kucharski service, return_code); 140*1b8adde7SWilliam Kucharski return 0; 141*1b8adde7SWilliam Kucharski } 142*1b8adde7SWilliam Kucharski } 143*1b8adde7SWilliam Kucharski 144*1b8adde7SWilliam Kucharski int pcibios_read_config_byte(unsigned int bus, 145*1b8adde7SWilliam Kucharski unsigned int device_fn, unsigned int where, uint8_t *value) 146*1b8adde7SWilliam Kucharski { 147*1b8adde7SWilliam Kucharski unsigned long ret; 148*1b8adde7SWilliam Kucharski unsigned long bx = (bus << 8) | device_fn; 149*1b8adde7SWilliam Kucharski unsigned long flags; 150*1b8adde7SWilliam Kucharski 151*1b8adde7SWilliam Kucharski save_flags(flags); 152*1b8adde7SWilliam Kucharski __asm__( 153*1b8adde7SWilliam Kucharski #ifdef ABSOLUTE_WITHOUT_ASTERISK 154*1b8adde7SWilliam Kucharski "lcall (%%esi)\n\t" 155*1b8adde7SWilliam Kucharski #else 156*1b8adde7SWilliam Kucharski "lcall *(%%esi)\n\t" 157*1b8adde7SWilliam Kucharski #endif 158*1b8adde7SWilliam Kucharski "jc 1f\n\t" 159*1b8adde7SWilliam Kucharski "xor %%ah, %%ah\n" 160*1b8adde7SWilliam Kucharski "1:" 161*1b8adde7SWilliam Kucharski : "=c" (*value), 162*1b8adde7SWilliam Kucharski "=a" (ret) 163*1b8adde7SWilliam Kucharski : "1" (PCIBIOS_READ_CONFIG_BYTE), 164*1b8adde7SWilliam Kucharski "b" (bx), 165*1b8adde7SWilliam Kucharski "D" ((long) where), 166*1b8adde7SWilliam Kucharski "S" (&pci_indirect)); 167*1b8adde7SWilliam Kucharski restore_flags(flags); 168*1b8adde7SWilliam Kucharski return (int) (ret & 0xff00) >> 8; 169*1b8adde7SWilliam Kucharski } 170*1b8adde7SWilliam Kucharski 171*1b8adde7SWilliam Kucharski int pcibios_read_config_word(unsigned int bus, 172*1b8adde7SWilliam Kucharski unsigned int device_fn, unsigned int where, uint16_t *value) 173*1b8adde7SWilliam Kucharski { 174*1b8adde7SWilliam Kucharski unsigned long ret; 175*1b8adde7SWilliam Kucharski unsigned long bx = (bus << 8) | device_fn; 176*1b8adde7SWilliam Kucharski unsigned long flags; 177*1b8adde7SWilliam Kucharski 178*1b8adde7SWilliam Kucharski save_flags(flags); 179*1b8adde7SWilliam Kucharski __asm__( 180*1b8adde7SWilliam Kucharski #ifdef ABSOLUTE_WITHOUT_ASTERISK 181*1b8adde7SWilliam Kucharski "lcall (%%esi)\n\t" 182*1b8adde7SWilliam Kucharski #else 183*1b8adde7SWilliam Kucharski "lcall *(%%esi)\n\t" 184*1b8adde7SWilliam Kucharski #endif 185*1b8adde7SWilliam Kucharski "jc 1f\n\t" 186*1b8adde7SWilliam Kucharski "xor %%ah, %%ah\n" 187*1b8adde7SWilliam Kucharski "1:" 188*1b8adde7SWilliam Kucharski : "=c" (*value), 189*1b8adde7SWilliam Kucharski "=a" (ret) 190*1b8adde7SWilliam Kucharski : "1" (PCIBIOS_READ_CONFIG_WORD), 191*1b8adde7SWilliam Kucharski "b" (bx), 192*1b8adde7SWilliam Kucharski "D" ((long) where), 193*1b8adde7SWilliam Kucharski "S" (&pci_indirect)); 194*1b8adde7SWilliam Kucharski restore_flags(flags); 195*1b8adde7SWilliam Kucharski return (int) (ret & 0xff00) >> 8; 196*1b8adde7SWilliam Kucharski } 197*1b8adde7SWilliam Kucharski 198*1b8adde7SWilliam Kucharski int pcibios_read_config_dword(unsigned int bus, 199*1b8adde7SWilliam Kucharski unsigned int device_fn, unsigned int where, uint32_t *value) 200*1b8adde7SWilliam Kucharski { 201*1b8adde7SWilliam Kucharski unsigned long ret; 202*1b8adde7SWilliam Kucharski unsigned long bx = (bus << 8) | device_fn; 203*1b8adde7SWilliam Kucharski unsigned long flags; 204*1b8adde7SWilliam Kucharski 205*1b8adde7SWilliam Kucharski save_flags(flags); 206*1b8adde7SWilliam Kucharski __asm__( 207*1b8adde7SWilliam Kucharski #ifdef ABSOLUTE_WITHOUT_ASTERISK 208*1b8adde7SWilliam Kucharski "lcall (%%esi)\n\t" 209*1b8adde7SWilliam Kucharski #else 210*1b8adde7SWilliam Kucharski "lcall *(%%esi)\n\t" 211*1b8adde7SWilliam Kucharski #endif 212*1b8adde7SWilliam Kucharski "jc 1f\n\t" 213*1b8adde7SWilliam Kucharski "xor %%ah, %%ah\n" 214*1b8adde7SWilliam Kucharski "1:" 215*1b8adde7SWilliam Kucharski : "=c" (*value), 216*1b8adde7SWilliam Kucharski "=a" (ret) 217*1b8adde7SWilliam Kucharski : "1" (PCIBIOS_READ_CONFIG_DWORD), 218*1b8adde7SWilliam Kucharski "b" (bx), 219*1b8adde7SWilliam Kucharski "D" ((long) where), 220*1b8adde7SWilliam Kucharski "S" (&pci_indirect)); 221*1b8adde7SWilliam Kucharski restore_flags(flags); 222*1b8adde7SWilliam Kucharski return (int) (ret & 0xff00) >> 8; 223*1b8adde7SWilliam Kucharski } 224*1b8adde7SWilliam Kucharski 225*1b8adde7SWilliam Kucharski int pcibios_write_config_byte (unsigned int bus, 226*1b8adde7SWilliam Kucharski unsigned int device_fn, unsigned int where, uint8_t value) 227*1b8adde7SWilliam Kucharski { 228*1b8adde7SWilliam Kucharski unsigned long ret; 229*1b8adde7SWilliam Kucharski unsigned long bx = (bus << 8) | device_fn; 230*1b8adde7SWilliam Kucharski unsigned long flags; 231*1b8adde7SWilliam Kucharski 232*1b8adde7SWilliam Kucharski save_flags(flags); cli(); 233*1b8adde7SWilliam Kucharski __asm__( 234*1b8adde7SWilliam Kucharski #ifdef ABSOLUTE_WITHOUT_ASTERISK 235*1b8adde7SWilliam Kucharski "lcall (%%esi)\n\t" 236*1b8adde7SWilliam Kucharski #else 237*1b8adde7SWilliam Kucharski "lcall *(%%esi)\n\t" 238*1b8adde7SWilliam Kucharski #endif 239*1b8adde7SWilliam Kucharski "jc 1f\n\t" 240*1b8adde7SWilliam Kucharski "xor %%ah, %%ah\n" 241*1b8adde7SWilliam Kucharski "1:" 242*1b8adde7SWilliam Kucharski : "=a" (ret) 243*1b8adde7SWilliam Kucharski : "0" (PCIBIOS_WRITE_CONFIG_BYTE), 244*1b8adde7SWilliam Kucharski "c" (value), 245*1b8adde7SWilliam Kucharski "b" (bx), 246*1b8adde7SWilliam Kucharski "D" ((long) where), 247*1b8adde7SWilliam Kucharski "S" (&pci_indirect)); 248*1b8adde7SWilliam Kucharski restore_flags(flags); 249*1b8adde7SWilliam Kucharski return (int) (ret & 0xff00) >> 8; 250*1b8adde7SWilliam Kucharski } 251*1b8adde7SWilliam Kucharski 252*1b8adde7SWilliam Kucharski int pcibios_write_config_word (unsigned int bus, 253*1b8adde7SWilliam Kucharski unsigned int device_fn, unsigned int where, uint16_t value) 254*1b8adde7SWilliam Kucharski { 255*1b8adde7SWilliam Kucharski unsigned long ret; 256*1b8adde7SWilliam Kucharski unsigned long bx = (bus << 8) | device_fn; 257*1b8adde7SWilliam Kucharski unsigned long flags; 258*1b8adde7SWilliam Kucharski 259*1b8adde7SWilliam Kucharski save_flags(flags); cli(); 260*1b8adde7SWilliam Kucharski __asm__( 261*1b8adde7SWilliam Kucharski #ifdef ABSOLUTE_WITHOUT_ASTERISK 262*1b8adde7SWilliam Kucharski "lcall (%%esi)\n\t" 263*1b8adde7SWilliam Kucharski #else 264*1b8adde7SWilliam Kucharski "lcall *(%%esi)\n\t" 265*1b8adde7SWilliam Kucharski #endif 266*1b8adde7SWilliam Kucharski "jc 1f\n\t" 267*1b8adde7SWilliam Kucharski "xor %%ah, %%ah\n" 268*1b8adde7SWilliam Kucharski "1:" 269*1b8adde7SWilliam Kucharski : "=a" (ret) 270*1b8adde7SWilliam Kucharski : "0" (PCIBIOS_WRITE_CONFIG_WORD), 271*1b8adde7SWilliam Kucharski "c" (value), 272*1b8adde7SWilliam Kucharski "b" (bx), 273*1b8adde7SWilliam Kucharski "D" ((long) where), 274*1b8adde7SWilliam Kucharski "S" (&pci_indirect)); 275*1b8adde7SWilliam Kucharski restore_flags(flags); 276*1b8adde7SWilliam Kucharski return (int) (ret & 0xff00) >> 8; 277*1b8adde7SWilliam Kucharski } 278*1b8adde7SWilliam Kucharski 279*1b8adde7SWilliam Kucharski int pcibios_write_config_dword (unsigned int bus, 280*1b8adde7SWilliam Kucharski unsigned int device_fn, unsigned int where, uint32_t value) 281*1b8adde7SWilliam Kucharski { 282*1b8adde7SWilliam Kucharski unsigned long ret; 283*1b8adde7SWilliam Kucharski unsigned long bx = (bus << 8) | device_fn; 284*1b8adde7SWilliam Kucharski unsigned long flags; 285*1b8adde7SWilliam Kucharski 286*1b8adde7SWilliam Kucharski save_flags(flags); cli(); 287*1b8adde7SWilliam Kucharski __asm__( 288*1b8adde7SWilliam Kucharski #ifdef ABSOLUTE_WITHOUT_ASTERISK 289*1b8adde7SWilliam Kucharski "lcall (%%esi)\n\t" 290*1b8adde7SWilliam Kucharski #else 291*1b8adde7SWilliam Kucharski "lcall *(%%esi)\n\t" 292*1b8adde7SWilliam Kucharski #endif 293*1b8adde7SWilliam Kucharski "jc 1f\n\t" 294*1b8adde7SWilliam Kucharski "xor %%ah, %%ah\n" 295*1b8adde7SWilliam Kucharski "1:" 296*1b8adde7SWilliam Kucharski : "=a" (ret) 297*1b8adde7SWilliam Kucharski : "0" (PCIBIOS_WRITE_CONFIG_DWORD), 298*1b8adde7SWilliam Kucharski "c" (value), 299*1b8adde7SWilliam Kucharski "b" (bx), 300*1b8adde7SWilliam Kucharski "D" ((long) where), 301*1b8adde7SWilliam Kucharski "S" (&pci_indirect)); 302*1b8adde7SWilliam Kucharski restore_flags(flags); 303*1b8adde7SWilliam Kucharski return (int) (ret & 0xff00) >> 8; 304*1b8adde7SWilliam Kucharski } 305*1b8adde7SWilliam Kucharski 306*1b8adde7SWilliam Kucharski static void check_pcibios(void) 307*1b8adde7SWilliam Kucharski { 308*1b8adde7SWilliam Kucharski unsigned long signature; 309*1b8adde7SWilliam Kucharski unsigned char present_status; 310*1b8adde7SWilliam Kucharski unsigned char major_revision; 311*1b8adde7SWilliam Kucharski unsigned char minor_revision; 312*1b8adde7SWilliam Kucharski unsigned long flags; 313*1b8adde7SWilliam Kucharski int pack; 314*1b8adde7SWilliam Kucharski 315*1b8adde7SWilliam Kucharski if ((pcibios_entry = bios32_service(PCI_SERVICE))) { 316*1b8adde7SWilliam Kucharski pci_indirect.address = pcibios_entry; 317*1b8adde7SWilliam Kucharski 318*1b8adde7SWilliam Kucharski save_flags(flags); 319*1b8adde7SWilliam Kucharski __asm__( 320*1b8adde7SWilliam Kucharski #ifdef ABSOLUTE_WITHOUT_ASTERISK 321*1b8adde7SWilliam Kucharski "lcall (%%edi)\n\t" 322*1b8adde7SWilliam Kucharski #else 323*1b8adde7SWilliam Kucharski "lcall *(%%edi)\n\t" 324*1b8adde7SWilliam Kucharski #endif 325*1b8adde7SWilliam Kucharski "jc 1f\n\t" 326*1b8adde7SWilliam Kucharski "xor %%ah, %%ah\n" 327*1b8adde7SWilliam Kucharski "1:\tshl $8, %%eax\n\t" 328*1b8adde7SWilliam Kucharski "movw %%bx, %%ax" 329*1b8adde7SWilliam Kucharski : "=d" (signature), 330*1b8adde7SWilliam Kucharski "=a" (pack) 331*1b8adde7SWilliam Kucharski : "1" (PCIBIOS_PCI_BIOS_PRESENT), 332*1b8adde7SWilliam Kucharski "D" (&pci_indirect) 333*1b8adde7SWilliam Kucharski : "bx", "cx"); 334*1b8adde7SWilliam Kucharski restore_flags(flags); 335*1b8adde7SWilliam Kucharski 336*1b8adde7SWilliam Kucharski present_status = (pack >> 16) & 0xff; 337*1b8adde7SWilliam Kucharski major_revision = (pack >> 8) & 0xff; 338*1b8adde7SWilliam Kucharski minor_revision = pack & 0xff; 339*1b8adde7SWilliam Kucharski if (present_status || (signature != PCI_SIGNATURE)) { 340*1b8adde7SWilliam Kucharski printf("ERROR: BIOS32 says PCI BIOS, but no PCI " 341*1b8adde7SWilliam Kucharski "BIOS????\n"); 342*1b8adde7SWilliam Kucharski pcibios_entry = 0; 343*1b8adde7SWilliam Kucharski } 344*1b8adde7SWilliam Kucharski #if DEBUG 345*1b8adde7SWilliam Kucharski if (pcibios_entry) { 346*1b8adde7SWilliam Kucharski printf ("pcibios_init : PCI BIOS revision %hhX.%hhX" 347*1b8adde7SWilliam Kucharski " entry at %#X\n", major_revision, 348*1b8adde7SWilliam Kucharski minor_revision, pcibios_entry); 349*1b8adde7SWilliam Kucharski } 350*1b8adde7SWilliam Kucharski #endif 351*1b8adde7SWilliam Kucharski } 352*1b8adde7SWilliam Kucharski } 353*1b8adde7SWilliam Kucharski 354*1b8adde7SWilliam Kucharski static void pcibios_init(void) 355*1b8adde7SWilliam Kucharski { 356*1b8adde7SWilliam Kucharski union bios32 *check; 357*1b8adde7SWilliam Kucharski unsigned char sum; 358*1b8adde7SWilliam Kucharski int i, length; 359*1b8adde7SWilliam Kucharski unsigned long bios32_entry = 0; 360*1b8adde7SWilliam Kucharski 361*1b8adde7SWilliam Kucharski EnterFunction("pcibios_init"); 362*1b8adde7SWilliam Kucharski /* 363*1b8adde7SWilliam Kucharski * Follow the standard procedure for locating the BIOS32 Service 364*1b8adde7SWilliam Kucharski * directory by scanning the permissible address range from 365*1b8adde7SWilliam Kucharski * 0xe0000 through 0xfffff for a valid BIOS32 structure. 366*1b8adde7SWilliam Kucharski * 367*1b8adde7SWilliam Kucharski */ 368*1b8adde7SWilliam Kucharski 369*1b8adde7SWilliam Kucharski for (check = (union bios32 *) 0xe0000; check <= (union bios32 *) 0xffff0; ++check) { 370*1b8adde7SWilliam Kucharski if (check->fields.signature != BIOS32_SIGNATURE) 371*1b8adde7SWilliam Kucharski continue; 372*1b8adde7SWilliam Kucharski length = check->fields.length * 16; 373*1b8adde7SWilliam Kucharski if (!length) 374*1b8adde7SWilliam Kucharski continue; 375*1b8adde7SWilliam Kucharski sum = 0; 376*1b8adde7SWilliam Kucharski for (i = 0; i < length ; ++i) 377*1b8adde7SWilliam Kucharski sum += check->chars[i]; 378*1b8adde7SWilliam Kucharski if (sum != 0) 379*1b8adde7SWilliam Kucharski continue; 380*1b8adde7SWilliam Kucharski if (check->fields.revision != 0) { 381*1b8adde7SWilliam Kucharski printf("pcibios_init : unsupported revision %d at %#X, mail drew@colorado.edu\n", 382*1b8adde7SWilliam Kucharski check->fields.revision, check); 383*1b8adde7SWilliam Kucharski continue; 384*1b8adde7SWilliam Kucharski } 385*1b8adde7SWilliam Kucharski #if DEBUG 386*1b8adde7SWilliam Kucharski printf("pcibios_init : BIOS32 Service Directory " 387*1b8adde7SWilliam Kucharski "structure at %#X\n", check); 388*1b8adde7SWilliam Kucharski #endif 389*1b8adde7SWilliam Kucharski if (!bios32_entry) { 390*1b8adde7SWilliam Kucharski if (check->fields.entry >= 0x100000) { 391*1b8adde7SWilliam Kucharski printf("pcibios_init: entry in high " 392*1b8adde7SWilliam Kucharski "memory, giving up\n"); 393*1b8adde7SWilliam Kucharski return; 394*1b8adde7SWilliam Kucharski } else { 395*1b8adde7SWilliam Kucharski bios32_entry = check->fields.entry; 396*1b8adde7SWilliam Kucharski #if DEBUG 397*1b8adde7SWilliam Kucharski printf("pcibios_init : BIOS32 Service Directory" 398*1b8adde7SWilliam Kucharski " entry at %#X\n", bios32_entry); 399*1b8adde7SWilliam Kucharski #endif 400*1b8adde7SWilliam Kucharski bios32_indirect.address = bios32_entry; 401*1b8adde7SWilliam Kucharski } 402*1b8adde7SWilliam Kucharski } 403*1b8adde7SWilliam Kucharski } 404*1b8adde7SWilliam Kucharski if (bios32_entry) 405*1b8adde7SWilliam Kucharski check_pcibios(); 406*1b8adde7SWilliam Kucharski LeaveFunction("pcibios_init"); 407*1b8adde7SWilliam Kucharski } 408*1b8adde7SWilliam Kucharski 409*1b8adde7SWilliam Kucharski #endif /* CONFIG_PCI_DIRECT not defined*/ 410*1b8adde7SWilliam Kucharski 411*1b8adde7SWilliam Kucharski unsigned long pcibios_bus_base(unsigned int bus __unused) 412*1b8adde7SWilliam Kucharski { 413*1b8adde7SWilliam Kucharski /* architecturally this must be 0 */ 414*1b8adde7SWilliam Kucharski return 0; 415*1b8adde7SWilliam Kucharski } 416*1b8adde7SWilliam Kucharski 417*1b8adde7SWilliam Kucharski void find_pci(int type, struct pci_device *dev) 418*1b8adde7SWilliam Kucharski { 419*1b8adde7SWilliam Kucharski EnterFunction("find_pci"); 420*1b8adde7SWilliam Kucharski #ifndef CONFIG_PCI_DIRECT 421*1b8adde7SWilliam Kucharski if (!pcibios_entry) { 422*1b8adde7SWilliam Kucharski pcibios_init(); 423*1b8adde7SWilliam Kucharski } 424*1b8adde7SWilliam Kucharski if (!pcibios_entry) { 425*1b8adde7SWilliam Kucharski printf("pci_init: no BIOS32 detected\n"); 426*1b8adde7SWilliam Kucharski return; 427*1b8adde7SWilliam Kucharski } 428*1b8adde7SWilliam Kucharski #endif 429*1b8adde7SWilliam Kucharski LeaveFunction("find_pci"); 430*1b8adde7SWilliam Kucharski return scan_pci_bus(type, dev); 431*1b8adde7SWilliam Kucharski } 432