1*1b8adde7SWilliam Kucharski 2*1b8adde7SWilliam Kucharski /* 3*1b8adde7SWilliam Kucharski * This program is free software; you can redistribute it and/or 4*1b8adde7SWilliam Kucharski * modify it under the terms of the GNU General Public License as 5*1b8adde7SWilliam Kucharski * published by the Free Software Foundation; either version 2, or (at 6*1b8adde7SWilliam Kucharski * your option) any later version. 7*1b8adde7SWilliam Kucharski */ 8*1b8adde7SWilliam Kucharski 9*1b8adde7SWilliam Kucharski #include "grub.h" 10*1b8adde7SWilliam Kucharski #include "pci.h" 11*1b8adde7SWilliam Kucharski 12*1b8adde7SWilliam Kucharski unsigned long virt_offset = 0; 13*1b8adde7SWilliam Kucharski unsigned long virt_to_phys(volatile const void *virt_addr) 14*1b8adde7SWilliam Kucharski { 15*1b8adde7SWilliam Kucharski return ((unsigned long)virt_addr) + virt_offset; 16*1b8adde7SWilliam Kucharski } 17*1b8adde7SWilliam Kucharski 18*1b8adde7SWilliam Kucharski void *phys_to_virt(unsigned long phys_addr) 19*1b8adde7SWilliam Kucharski { 20*1b8adde7SWilliam Kucharski return (void *)(phys_addr - virt_offset); 21*1b8adde7SWilliam Kucharski } 22*1b8adde7SWilliam Kucharski 23*1b8adde7SWilliam Kucharski #ifdef INCLUDE_3C595 24*1b8adde7SWilliam Kucharski extern struct pci_driver t595_driver; 25*1b8adde7SWilliam Kucharski #endif /* INCLUDE_3C595 */ 26*1b8adde7SWilliam Kucharski 27*1b8adde7SWilliam Kucharski #ifdef INCLUDE_3C90X 28*1b8adde7SWilliam Kucharski extern struct pci_driver a3c90x_driver; 29*1b8adde7SWilliam Kucharski #endif /* INCLUDE_3C90X */ 30*1b8adde7SWilliam Kucharski 31*1b8adde7SWilliam Kucharski #ifdef INCLUDE_DAVICOM 32*1b8adde7SWilliam Kucharski extern struct pci_driver davicom_driver; 33*1b8adde7SWilliam Kucharski #endif /* INCLUDE_DAVICOM */ 34*1b8adde7SWilliam Kucharski 35*1b8adde7SWilliam Kucharski #ifdef INCLUDE_E1000 36*1b8adde7SWilliam Kucharski extern struct pci_driver e1000_driver; 37*1b8adde7SWilliam Kucharski #endif /* INCLUDE_E1000 */ 38*1b8adde7SWilliam Kucharski 39*1b8adde7SWilliam Kucharski #ifdef INCLUDE_EEPRO100 40*1b8adde7SWilliam Kucharski extern struct pci_driver eepro100_driver; 41*1b8adde7SWilliam Kucharski #endif /* INCLUDE_EEPRO100 */ 42*1b8adde7SWilliam Kucharski 43*1b8adde7SWilliam Kucharski #ifdef INCLUDE_EPIC100 44*1b8adde7SWilliam Kucharski extern struct pci_driver epic100_driver; 45*1b8adde7SWilliam Kucharski #endif /* INCLUDE_EPIC100 */ 46*1b8adde7SWilliam Kucharski 47*1b8adde7SWilliam Kucharski #ifdef INCLUDE_FORCEDETH 48*1b8adde7SWilliam Kucharski extern struct pci_driver forcedeth_driver; 49*1b8adde7SWilliam Kucharski #endif /* INCLUDE_FORCEDETH */ 50*1b8adde7SWilliam Kucharski 51*1b8adde7SWilliam Kucharski #ifdef INCLUDE_NATSEMI 52*1b8adde7SWilliam Kucharski extern struct pci_driver natsemi_driver; 53*1b8adde7SWilliam Kucharski #endif /* INCLUDE_NATSEMI */ 54*1b8adde7SWilliam Kucharski 55*1b8adde7SWilliam Kucharski #ifdef INCLUDE_NS83820 56*1b8adde7SWilliam Kucharski extern struct pci_driver ns83820_driver; 57*1b8adde7SWilliam Kucharski #endif /* INCLUDE_NS83820 */ 58*1b8adde7SWilliam Kucharski 59*1b8adde7SWilliam Kucharski #ifdef INCLUDE_NS8390 60*1b8adde7SWilliam Kucharski extern struct pci_driver nepci_driver; 61*1b8adde7SWilliam Kucharski #endif /* INCLUDE_NS8390 */ 62*1b8adde7SWilliam Kucharski 63*1b8adde7SWilliam Kucharski #ifdef INCLUDE_PCNET32 64*1b8adde7SWilliam Kucharski extern struct pci_driver pcnet32_driver; 65*1b8adde7SWilliam Kucharski #endif /* INCLUDE_PCNET32 */ 66*1b8adde7SWilliam Kucharski 67*1b8adde7SWilliam Kucharski #ifdef INCLUDE_PNIC 68*1b8adde7SWilliam Kucharski extern struct pci_driver pnic_driver; 69*1b8adde7SWilliam Kucharski #endif /* INCLUDE_PNIC */ 70*1b8adde7SWilliam Kucharski 71*1b8adde7SWilliam Kucharski #ifdef INCLUDE_RTL8139 72*1b8adde7SWilliam Kucharski extern struct pci_driver rtl8139_driver; 73*1b8adde7SWilliam Kucharski #endif /* INCLUDE_RTL8139 */ 74*1b8adde7SWilliam Kucharski 75*1b8adde7SWilliam Kucharski #ifdef INCLUDE_SIS900 76*1b8adde7SWilliam Kucharski extern struct pci_driver sis900_driver; 77*1b8adde7SWilliam Kucharski extern struct pci_driver sis_bridge_driver; 78*1b8adde7SWilliam Kucharski #endif /* INCLUDE_SIS900 */ 79*1b8adde7SWilliam Kucharski 80*1b8adde7SWilliam Kucharski #ifdef INCLUDE_SUNDANCE 81*1b8adde7SWilliam Kucharski extern struct pci_driver sundance_driver; 82*1b8adde7SWilliam Kucharski #endif /* INCLUDE_SUNDANCE */ 83*1b8adde7SWilliam Kucharski 84*1b8adde7SWilliam Kucharski #ifdef INCLUDE_TG3 85*1b8adde7SWilliam Kucharski extern struct pci_driver tg3_driver; 86*1b8adde7SWilliam Kucharski #endif /* INCLUDE_TG3 */ 87*1b8adde7SWilliam Kucharski 88*1b8adde7SWilliam Kucharski #ifdef INCLUDE_TLAN 89*1b8adde7SWilliam Kucharski extern struct pci_driver tlan_driver; 90*1b8adde7SWilliam Kucharski #endif /* INCLUDE_TLAN */ 91*1b8adde7SWilliam Kucharski 92*1b8adde7SWilliam Kucharski #ifdef INCLUDE_TULIP 93*1b8adde7SWilliam Kucharski extern struct pci_driver tulip_driver; 94*1b8adde7SWilliam Kucharski #endif /* INCLUDE_TULIP */ 95*1b8adde7SWilliam Kucharski 96*1b8adde7SWilliam Kucharski #ifdef INCLUDE_UNDI 97*1b8adde7SWilliam Kucharski extern struct pci_driver undi_driver; 98*1b8adde7SWilliam Kucharski #endif /* INCLUDE_UNDI */ 99*1b8adde7SWilliam Kucharski 100*1b8adde7SWilliam Kucharski #ifdef INCLUDE_VIA_RHINE 101*1b8adde7SWilliam Kucharski extern struct pci_driver rhine_driver; 102*1b8adde7SWilliam Kucharski #endif/* INCLUDE_VIA_RHINE */ 103*1b8adde7SWilliam Kucharski 104*1b8adde7SWilliam Kucharski #ifdef INCLUDE_W89C840 105*1b8adde7SWilliam Kucharski extern struct pci_driver w89c840_driver; 106*1b8adde7SWilliam Kucharski #endif /* INCLUDE_W89C840 */ 107*1b8adde7SWilliam Kucharski 108*1b8adde7SWilliam Kucharski #ifdef INCLUDE_R8169 109*1b8adde7SWilliam Kucharski extern struct pci_driver r8169_driver; 110*1b8adde7SWilliam Kucharski #endif /* INCLUDE_R8169 */ 111*1b8adde7SWilliam Kucharski 112*1b8adde7SWilliam Kucharski static const struct pci_driver *pci_drivers[] = { 113*1b8adde7SWilliam Kucharski 114*1b8adde7SWilliam Kucharski #ifdef INCLUDE_3C595 115*1b8adde7SWilliam Kucharski &t595_driver, 116*1b8adde7SWilliam Kucharski #endif /* INCLUDE_3C595 */ 117*1b8adde7SWilliam Kucharski 118*1b8adde7SWilliam Kucharski #ifdef INCLUDE_3C90X 119*1b8adde7SWilliam Kucharski &a3c90x_driver, 120*1b8adde7SWilliam Kucharski #endif /* INCLUDE_3C90X */ 121*1b8adde7SWilliam Kucharski 122*1b8adde7SWilliam Kucharski #ifdef INCLUDE_DAVICOM 123*1b8adde7SWilliam Kucharski &davicom_driver, 124*1b8adde7SWilliam Kucharski #endif /* INCLUDE_DAVICOM */ 125*1b8adde7SWilliam Kucharski 126*1b8adde7SWilliam Kucharski #ifdef INCLUDE_E1000 127*1b8adde7SWilliam Kucharski &e1000_driver, 128*1b8adde7SWilliam Kucharski #endif /* INCLUDE_E1000 */ 129*1b8adde7SWilliam Kucharski 130*1b8adde7SWilliam Kucharski #ifdef INCLUDE_EEPRO100 131*1b8adde7SWilliam Kucharski &eepro100_driver, 132*1b8adde7SWilliam Kucharski #endif /* INCLUDE_EEPRO100 */ 133*1b8adde7SWilliam Kucharski 134*1b8adde7SWilliam Kucharski #ifdef INCLUDE_EPIC100 135*1b8adde7SWilliam Kucharski &epic100_driver, 136*1b8adde7SWilliam Kucharski #endif /* INCLUDE_EPIC100 */ 137*1b8adde7SWilliam Kucharski 138*1b8adde7SWilliam Kucharski #ifdef INCLUDE_FORCEDETH 139*1b8adde7SWilliam Kucharski &forcedeth_driver, 140*1b8adde7SWilliam Kucharski #endif /* INCLUDE_FORCEDETH */ 141*1b8adde7SWilliam Kucharski 142*1b8adde7SWilliam Kucharski #ifdef INCLUDE_NATSEMI 143*1b8adde7SWilliam Kucharski &natsemi_driver, 144*1b8adde7SWilliam Kucharski #endif /* INCLUDE_NATSEMI */ 145*1b8adde7SWilliam Kucharski 146*1b8adde7SWilliam Kucharski #ifdef INCLUDE_NS83820 147*1b8adde7SWilliam Kucharski &ns83820_driver, 148*1b8adde7SWilliam Kucharski #endif /* INCLUDE_NS83820 */ 149*1b8adde7SWilliam Kucharski 150*1b8adde7SWilliam Kucharski #ifdef INCLUDE_NS8390 151*1b8adde7SWilliam Kucharski &nepci_driver, 152*1b8adde7SWilliam Kucharski #endif /* INCLUDE_NS8390 */ 153*1b8adde7SWilliam Kucharski 154*1b8adde7SWilliam Kucharski #ifdef INCLUDE_PCNET32 155*1b8adde7SWilliam Kucharski &pcnet32_driver, 156*1b8adde7SWilliam Kucharski #endif /* INCLUDE_PCNET32 */ 157*1b8adde7SWilliam Kucharski 158*1b8adde7SWilliam Kucharski #ifdef INCLUDE_PNIC 159*1b8adde7SWilliam Kucharski &pnic_driver, 160*1b8adde7SWilliam Kucharski #endif /* INCLUDE_PNIC */ 161*1b8adde7SWilliam Kucharski 162*1b8adde7SWilliam Kucharski #ifdef INCLUDE_RTL8139 163*1b8adde7SWilliam Kucharski &rtl8139_driver, 164*1b8adde7SWilliam Kucharski #endif /* INCLUDE_RTL8139 */ 165*1b8adde7SWilliam Kucharski 166*1b8adde7SWilliam Kucharski #ifdef INCLUDE_SIS900 167*1b8adde7SWilliam Kucharski &sis900_driver, 168*1b8adde7SWilliam Kucharski &sis_bridge_driver, 169*1b8adde7SWilliam Kucharski #endif /* INCLUDE_SIS900 */ 170*1b8adde7SWilliam Kucharski 171*1b8adde7SWilliam Kucharski #ifdef INCLUDE_SUNDANCE 172*1b8adde7SWilliam Kucharski &sundance_driver, 173*1b8adde7SWilliam Kucharski #endif /* INCLUDE_SUNDANCE */ 174*1b8adde7SWilliam Kucharski 175*1b8adde7SWilliam Kucharski #ifdef INCLUDE_TG3 176*1b8adde7SWilliam Kucharski & tg3_driver, 177*1b8adde7SWilliam Kucharski #endif /* INCLUDE_TG3 */ 178*1b8adde7SWilliam Kucharski 179*1b8adde7SWilliam Kucharski #ifdef INCLUDE_TLAN 180*1b8adde7SWilliam Kucharski &tlan_driver, 181*1b8adde7SWilliam Kucharski #endif /* INCLUDE_TLAN */ 182*1b8adde7SWilliam Kucharski 183*1b8adde7SWilliam Kucharski #ifdef INCLUDE_TULIP 184*1b8adde7SWilliam Kucharski & tulip_driver, 185*1b8adde7SWilliam Kucharski #endif /* INCLUDE_TULIP */ 186*1b8adde7SWilliam Kucharski 187*1b8adde7SWilliam Kucharski #ifdef INCLUDE_VIA_RHINE 188*1b8adde7SWilliam Kucharski &rhine_driver, 189*1b8adde7SWilliam Kucharski #endif/* INCLUDE_VIA_RHINE */ 190*1b8adde7SWilliam Kucharski 191*1b8adde7SWilliam Kucharski #ifdef INCLUDE_W89C840 192*1b8adde7SWilliam Kucharski &w89c840_driver, 193*1b8adde7SWilliam Kucharski #endif /* INCLUDE_W89C840 */ 194*1b8adde7SWilliam Kucharski 195*1b8adde7SWilliam Kucharski #ifdef INCLUDE_R8169 196*1b8adde7SWilliam Kucharski &r8169_driver, 197*1b8adde7SWilliam Kucharski #endif /* INCLUDE_R8169 */ 198*1b8adde7SWilliam Kucharski 199*1b8adde7SWilliam Kucharski /* We must be the last one */ 200*1b8adde7SWilliam Kucharski #ifdef INCLUDE_UNDI 201*1b8adde7SWilliam Kucharski &undi_driver, 202*1b8adde7SWilliam Kucharski #endif /* INCLUDE_UNDI */ 203*1b8adde7SWilliam Kucharski 204*1b8adde7SWilliam Kucharski 0 205*1b8adde7SWilliam Kucharski }; 206*1b8adde7SWilliam Kucharski 207*1b8adde7SWilliam Kucharski static void scan_drivers( 208*1b8adde7SWilliam Kucharski int type, 209*1b8adde7SWilliam Kucharski uint32_t class, uint16_t vendor, uint16_t device, 210*1b8adde7SWilliam Kucharski const struct pci_driver *last_driver, struct pci_device *dev) 211*1b8adde7SWilliam Kucharski { 212*1b8adde7SWilliam Kucharski const struct pci_driver *skip_driver = last_driver; 213*1b8adde7SWilliam Kucharski /* Assume there is only one match of the correct type */ 214*1b8adde7SWilliam Kucharski const struct pci_driver *driver; 215*1b8adde7SWilliam Kucharski int i, j; 216*1b8adde7SWilliam Kucharski 217*1b8adde7SWilliam Kucharski for(j = 0; pci_drivers[j] != 0; j++){ 218*1b8adde7SWilliam Kucharski driver = pci_drivers[j]; 219*1b8adde7SWilliam Kucharski if (driver->type != type) 220*1b8adde7SWilliam Kucharski continue; 221*1b8adde7SWilliam Kucharski if (skip_driver) { 222*1b8adde7SWilliam Kucharski if (skip_driver == driver) 223*1b8adde7SWilliam Kucharski skip_driver = 0; 224*1b8adde7SWilliam Kucharski continue; 225*1b8adde7SWilliam Kucharski } 226*1b8adde7SWilliam Kucharski for(i = 0; i < driver->id_count; i++) { 227*1b8adde7SWilliam Kucharski if ((vendor == driver->ids[i].vendor) && 228*1b8adde7SWilliam Kucharski (device == driver->ids[i].dev_id)) { 229*1b8adde7SWilliam Kucharski 230*1b8adde7SWilliam Kucharski dev->driver = driver; 231*1b8adde7SWilliam Kucharski dev->name = driver->ids[i].name; 232*1b8adde7SWilliam Kucharski 233*1b8adde7SWilliam Kucharski goto out; 234*1b8adde7SWilliam Kucharski } 235*1b8adde7SWilliam Kucharski } 236*1b8adde7SWilliam Kucharski } 237*1b8adde7SWilliam Kucharski if (!class) { 238*1b8adde7SWilliam Kucharski goto out; 239*1b8adde7SWilliam Kucharski } 240*1b8adde7SWilliam Kucharski for(j = 0; pci_drivers[j] != 0; j++){ 241*1b8adde7SWilliam Kucharski driver = pci_drivers[j]; 242*1b8adde7SWilliam Kucharski if (driver->type != type) 243*1b8adde7SWilliam Kucharski continue; 244*1b8adde7SWilliam Kucharski if (skip_driver) { 245*1b8adde7SWilliam Kucharski if (skip_driver == driver) 246*1b8adde7SWilliam Kucharski skip_driver = 0; 247*1b8adde7SWilliam Kucharski continue; 248*1b8adde7SWilliam Kucharski } 249*1b8adde7SWilliam Kucharski if (last_driver == driver) 250*1b8adde7SWilliam Kucharski continue; 251*1b8adde7SWilliam Kucharski if ((class >> 8) == driver->class) { 252*1b8adde7SWilliam Kucharski dev->driver = driver; 253*1b8adde7SWilliam Kucharski dev->name = driver->name; 254*1b8adde7SWilliam Kucharski goto out; 255*1b8adde7SWilliam Kucharski } 256*1b8adde7SWilliam Kucharski } 257*1b8adde7SWilliam Kucharski out: 258*1b8adde7SWilliam Kucharski return; 259*1b8adde7SWilliam Kucharski } 260*1b8adde7SWilliam Kucharski 261*1b8adde7SWilliam Kucharski void scan_pci_bus(int type, struct pci_device *dev) 262*1b8adde7SWilliam Kucharski { 263*1b8adde7SWilliam Kucharski unsigned int first_bus, first_devfn; 264*1b8adde7SWilliam Kucharski const struct pci_driver *first_driver; 265*1b8adde7SWilliam Kucharski unsigned int devfn, bus, buses; 266*1b8adde7SWilliam Kucharski unsigned char hdr_type = 0; 267*1b8adde7SWilliam Kucharski uint32_t class; 268*1b8adde7SWilliam Kucharski uint16_t vendor, device; 269*1b8adde7SWilliam Kucharski uint32_t l, membase, ioaddr, romaddr; 270*1b8adde7SWilliam Kucharski int reg; 271*1b8adde7SWilliam Kucharski 272*1b8adde7SWilliam Kucharski EnterFunction("scan_pci_bus"); 273*1b8adde7SWilliam Kucharski first_bus = 0; 274*1b8adde7SWilliam Kucharski first_devfn = 0; 275*1b8adde7SWilliam Kucharski first_driver = 0; 276*1b8adde7SWilliam Kucharski if (dev->driver) { 277*1b8adde7SWilliam Kucharski first_driver = dev->driver; 278*1b8adde7SWilliam Kucharski first_bus = dev->bus; 279*1b8adde7SWilliam Kucharski first_devfn = dev->devfn; 280*1b8adde7SWilliam Kucharski /* Re read the header type on a restart */ 281*1b8adde7SWilliam Kucharski pcibios_read_config_byte(first_bus, first_devfn & ~0x7, 282*1b8adde7SWilliam Kucharski PCI_HEADER_TYPE, &hdr_type); 283*1b8adde7SWilliam Kucharski dev->driver = 0; 284*1b8adde7SWilliam Kucharski dev->bus = 0; 285*1b8adde7SWilliam Kucharski dev->devfn = 0; 286*1b8adde7SWilliam Kucharski } 287*1b8adde7SWilliam Kucharski 288*1b8adde7SWilliam Kucharski /* Scan all PCI buses, until we find our card. 289*1b8adde7SWilliam Kucharski * We could be smart only scan the required buses but that 290*1b8adde7SWilliam Kucharski * is error prone, and tricky. 291*1b8adde7SWilliam Kucharski * By scanning all possible pci buses in order we should find 292*1b8adde7SWilliam Kucharski * our card eventually. 293*1b8adde7SWilliam Kucharski */ 294*1b8adde7SWilliam Kucharski buses=256; 295*1b8adde7SWilliam Kucharski for (bus = first_bus; bus < buses; ++bus) { 296*1b8adde7SWilliam Kucharski for (devfn = first_devfn; devfn < 0xff; ++devfn, first_driver = 0) { 297*1b8adde7SWilliam Kucharski if (PCI_FUNC (devfn) == 0) 298*1b8adde7SWilliam Kucharski pcibios_read_config_byte(bus, devfn, PCI_HEADER_TYPE, &hdr_type); 299*1b8adde7SWilliam Kucharski else if (!(hdr_type & 0x80)) /* not a multi-function device */ 300*1b8adde7SWilliam Kucharski continue; 301*1b8adde7SWilliam Kucharski pcibios_read_config_dword(bus, devfn, PCI_VENDOR_ID, &l); 302*1b8adde7SWilliam Kucharski /* some broken boards return 0 if a slot is empty: */ 303*1b8adde7SWilliam Kucharski if (l == 0xffffffff || l == 0x00000000) { 304*1b8adde7SWilliam Kucharski continue; 305*1b8adde7SWilliam Kucharski } 306*1b8adde7SWilliam Kucharski vendor = l & 0xffff; 307*1b8adde7SWilliam Kucharski device = (l >> 16) & 0xffff; 308*1b8adde7SWilliam Kucharski 309*1b8adde7SWilliam Kucharski pcibios_read_config_dword(bus, devfn, PCI_REVISION, &l); 310*1b8adde7SWilliam Kucharski class = (l >> 8) & 0xffffff; 311*1b8adde7SWilliam Kucharski #if DEBUG 312*1b8adde7SWilliam Kucharski { 313*1b8adde7SWilliam Kucharski int i; 314*1b8adde7SWilliam Kucharski printf("%hhx:%hhx.%hhx [%hX/%hX] ---- ", 315*1b8adde7SWilliam Kucharski bus, PCI_SLOT(devfn), PCI_FUNC(devfn), 316*1b8adde7SWilliam Kucharski vendor, device); 317*1b8adde7SWilliam Kucharski #if DEBUG > 1 318*1b8adde7SWilliam Kucharski for(i = 0; i < 256; i++) { 319*1b8adde7SWilliam Kucharski unsigned char byte; 320*1b8adde7SWilliam Kucharski if ((i & 0xf) == 0) { 321*1b8adde7SWilliam Kucharski printf("%hhx: ", i); 322*1b8adde7SWilliam Kucharski } 323*1b8adde7SWilliam Kucharski pcibios_read_config_byte(bus, devfn, i, &byte); 324*1b8adde7SWilliam Kucharski printf("%hhx ", byte); 325*1b8adde7SWilliam Kucharski if ((i & 0xf) == 0xf) { 326*1b8adde7SWilliam Kucharski printf("\n"); 327*1b8adde7SWilliam Kucharski } 328*1b8adde7SWilliam Kucharski } 329*1b8adde7SWilliam Kucharski #endif 330*1b8adde7SWilliam Kucharski 331*1b8adde7SWilliam Kucharski } 332*1b8adde7SWilliam Kucharski #endif 333*1b8adde7SWilliam Kucharski scan_drivers(type, class, vendor, device, first_driver, dev); 334*1b8adde7SWilliam Kucharski if (!dev->driver){ 335*1b8adde7SWilliam Kucharski #if DEBUG 336*1b8adde7SWilliam Kucharski printf("No driver fit.\n"); 337*1b8adde7SWilliam Kucharski #endif 338*1b8adde7SWilliam Kucharski continue; 339*1b8adde7SWilliam Kucharski } 340*1b8adde7SWilliam Kucharski #if DEBUG 341*1b8adde7SWilliam Kucharski printf("Get Driver:\n"); 342*1b8adde7SWilliam Kucharski #endif 343*1b8adde7SWilliam Kucharski dev->devfn = devfn; 344*1b8adde7SWilliam Kucharski dev->bus = bus; 345*1b8adde7SWilliam Kucharski dev->class = class; 346*1b8adde7SWilliam Kucharski dev->vendor = vendor; 347*1b8adde7SWilliam Kucharski dev->dev_id = device; 348*1b8adde7SWilliam Kucharski 349*1b8adde7SWilliam Kucharski 350*1b8adde7SWilliam Kucharski /* Get the ROM base address */ 351*1b8adde7SWilliam Kucharski pcibios_read_config_dword(bus, devfn, 352*1b8adde7SWilliam Kucharski PCI_ROM_ADDRESS, &romaddr); 353*1b8adde7SWilliam Kucharski romaddr >>= 10; 354*1b8adde7SWilliam Kucharski dev->romaddr = romaddr; 355*1b8adde7SWilliam Kucharski 356*1b8adde7SWilliam Kucharski /* Get the ``membase'' */ 357*1b8adde7SWilliam Kucharski pcibios_read_config_dword(bus, devfn, 358*1b8adde7SWilliam Kucharski PCI_BASE_ADDRESS_1, &membase); 359*1b8adde7SWilliam Kucharski dev->membase = membase; 360*1b8adde7SWilliam Kucharski 361*1b8adde7SWilliam Kucharski /* Get the ``ioaddr'' */ 362*1b8adde7SWilliam Kucharski for (reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg += 4) { 363*1b8adde7SWilliam Kucharski pcibios_read_config_dword(bus, devfn, reg, &ioaddr); 364*1b8adde7SWilliam Kucharski if ((ioaddr & PCI_BASE_ADDRESS_IO_MASK) == 0 || (ioaddr & PCI_BASE_ADDRESS_SPACE_IO) == 0) 365*1b8adde7SWilliam Kucharski continue; 366*1b8adde7SWilliam Kucharski 367*1b8adde7SWilliam Kucharski 368*1b8adde7SWilliam Kucharski /* Strip the I/O address out of the returned value */ 369*1b8adde7SWilliam Kucharski ioaddr &= PCI_BASE_ADDRESS_IO_MASK; 370*1b8adde7SWilliam Kucharski 371*1b8adde7SWilliam Kucharski /* Take the first one or the one that matches in boot ROM address */ 372*1b8adde7SWilliam Kucharski dev->ioaddr = ioaddr; 373*1b8adde7SWilliam Kucharski } 374*1b8adde7SWilliam Kucharski #if DEBUG > 2 375*1b8adde7SWilliam Kucharski printf("Found %s ROM address %#hx\n", 376*1b8adde7SWilliam Kucharski dev->name, romaddr); 377*1b8adde7SWilliam Kucharski #endif 378*1b8adde7SWilliam Kucharski LeaveFunction("scan_pci_bus"); 379*1b8adde7SWilliam Kucharski return; 380*1b8adde7SWilliam Kucharski } 381*1b8adde7SWilliam Kucharski first_devfn = 0; 382*1b8adde7SWilliam Kucharski } 383*1b8adde7SWilliam Kucharski first_bus = 0; 384*1b8adde7SWilliam Kucharski LeaveFunction("scan_pci_bus"); 385*1b8adde7SWilliam Kucharski } 386*1b8adde7SWilliam Kucharski 387*1b8adde7SWilliam Kucharski 388*1b8adde7SWilliam Kucharski 389*1b8adde7SWilliam Kucharski /* 390*1b8adde7SWilliam Kucharski * Set device to be a busmaster in case BIOS neglected to do so. 391*1b8adde7SWilliam Kucharski * Also adjust PCI latency timer to a reasonable value, 32. 392*1b8adde7SWilliam Kucharski */ 393*1b8adde7SWilliam Kucharski void adjust_pci_device(struct pci_device *p) 394*1b8adde7SWilliam Kucharski { 395*1b8adde7SWilliam Kucharski unsigned short new_command, pci_command; 396*1b8adde7SWilliam Kucharski unsigned char pci_latency; 397*1b8adde7SWilliam Kucharski 398*1b8adde7SWilliam Kucharski pcibios_read_config_word(p->bus, p->devfn, PCI_COMMAND, &pci_command); 399*1b8adde7SWilliam Kucharski new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO; 400*1b8adde7SWilliam Kucharski if (pci_command != new_command) { 401*1b8adde7SWilliam Kucharski #if DEBUG > 0 402*1b8adde7SWilliam Kucharski printf( 403*1b8adde7SWilliam Kucharski "The PCI BIOS has not enabled this device!\n" 404*1b8adde7SWilliam Kucharski "Updating PCI command %hX->%hX. pci_bus %hhX pci_device_fn %hhX\n", 405*1b8adde7SWilliam Kucharski pci_command, new_command, p->bus, p->devfn); 406*1b8adde7SWilliam Kucharski #endif 407*1b8adde7SWilliam Kucharski pcibios_write_config_word(p->bus, p->devfn, PCI_COMMAND, new_command); 408*1b8adde7SWilliam Kucharski } 409*1b8adde7SWilliam Kucharski pcibios_read_config_byte(p->bus, p->devfn, PCI_LATENCY_TIMER, &pci_latency); 410*1b8adde7SWilliam Kucharski if (pci_latency < 32) { 411*1b8adde7SWilliam Kucharski #if DEBUG > 0 412*1b8adde7SWilliam Kucharski printf("PCI latency timer (CFLT) is unreasonably low at %d. Setting to 32 clocks.\n", 413*1b8adde7SWilliam Kucharski pci_latency); 414*1b8adde7SWilliam Kucharski #endif 415*1b8adde7SWilliam Kucharski pcibios_write_config_byte(p->bus, p->devfn, PCI_LATENCY_TIMER, 32); 416*1b8adde7SWilliam Kucharski } 417*1b8adde7SWilliam Kucharski } 418*1b8adde7SWilliam Kucharski 419*1b8adde7SWilliam Kucharski /* 420*1b8adde7SWilliam Kucharski * Find the start of a pci resource. 421*1b8adde7SWilliam Kucharski */ 422*1b8adde7SWilliam Kucharski unsigned long pci_bar_start(struct pci_device *dev, unsigned int index) 423*1b8adde7SWilliam Kucharski { 424*1b8adde7SWilliam Kucharski uint32_t lo, hi; 425*1b8adde7SWilliam Kucharski unsigned long bar; 426*1b8adde7SWilliam Kucharski pci_read_config_dword(dev, index, &lo); 427*1b8adde7SWilliam Kucharski if (lo & PCI_BASE_ADDRESS_SPACE_IO) { 428*1b8adde7SWilliam Kucharski bar = lo & PCI_BASE_ADDRESS_IO_MASK; 429*1b8adde7SWilliam Kucharski } else { 430*1b8adde7SWilliam Kucharski bar = 0; 431*1b8adde7SWilliam Kucharski if ((lo & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64) { 432*1b8adde7SWilliam Kucharski pci_read_config_dword(dev, index + 4, &hi); 433*1b8adde7SWilliam Kucharski if (hi) { 434*1b8adde7SWilliam Kucharski if (sizeof(unsigned long) > sizeof(uint32_t)) { 435*1b8adde7SWilliam Kucharski /* It's REALLY interesting:-) */ 436*1b8adde7SWilliam Kucharski bar = (uint64_t)hi << 32; 437*1b8adde7SWilliam Kucharski } 438*1b8adde7SWilliam Kucharski else { 439*1b8adde7SWilliam Kucharski printf("Unhandled 64bit BAR\n"); 440*1b8adde7SWilliam Kucharski return -1UL; 441*1b8adde7SWilliam Kucharski } 442*1b8adde7SWilliam Kucharski } 443*1b8adde7SWilliam Kucharski } 444*1b8adde7SWilliam Kucharski bar |= lo & PCI_BASE_ADDRESS_MEM_MASK; 445*1b8adde7SWilliam Kucharski } 446*1b8adde7SWilliam Kucharski return bar + pcibios_bus_base(dev->bus); 447*1b8adde7SWilliam Kucharski } 448*1b8adde7SWilliam Kucharski 449*1b8adde7SWilliam Kucharski /* 450*1b8adde7SWilliam Kucharski * Find the size of a pci resource. 451*1b8adde7SWilliam Kucharski */ 452*1b8adde7SWilliam Kucharski unsigned long pci_bar_size(struct pci_device *dev, unsigned int bar) 453*1b8adde7SWilliam Kucharski { 454*1b8adde7SWilliam Kucharski uint32_t start, size; 455*1b8adde7SWilliam Kucharski /* Save the original bar */ 456*1b8adde7SWilliam Kucharski pci_read_config_dword(dev, bar, &start); 457*1b8adde7SWilliam Kucharski /* Compute which bits can be set */ 458*1b8adde7SWilliam Kucharski pci_write_config_dword(dev, bar, ~0); 459*1b8adde7SWilliam Kucharski pci_read_config_dword(dev, bar, &size); 460*1b8adde7SWilliam Kucharski /* Restore the original size */ 461*1b8adde7SWilliam Kucharski pci_write_config_dword(dev, bar, start); 462*1b8adde7SWilliam Kucharski /* Find the significant bits */ 463*1b8adde7SWilliam Kucharski if (start & PCI_BASE_ADDRESS_SPACE_IO) { 464*1b8adde7SWilliam Kucharski size &= PCI_BASE_ADDRESS_IO_MASK; 465*1b8adde7SWilliam Kucharski } else { 466*1b8adde7SWilliam Kucharski size &= PCI_BASE_ADDRESS_MEM_MASK; 467*1b8adde7SWilliam Kucharski } 468*1b8adde7SWilliam Kucharski /* Find the lowest bit set */ 469*1b8adde7SWilliam Kucharski size = size & ~(size - 1); 470*1b8adde7SWilliam Kucharski return size; 471*1b8adde7SWilliam Kucharski } 472*1b8adde7SWilliam Kucharski 473*1b8adde7SWilliam Kucharski /** 474*1b8adde7SWilliam Kucharski * pci_find_capability - query for devices' capabilities 475*1b8adde7SWilliam Kucharski * @dev: PCI device to query 476*1b8adde7SWilliam Kucharski * @cap: capability code 477*1b8adde7SWilliam Kucharski * 478*1b8adde7SWilliam Kucharski * Tell if a device supports a given PCI capability. 479*1b8adde7SWilliam Kucharski * Returns the address of the requested capability structure within the 480*1b8adde7SWilliam Kucharski * device's PCI configuration space or 0 in case the device does not 481*1b8adde7SWilliam Kucharski * support it. Possible values for @cap: 482*1b8adde7SWilliam Kucharski * 483*1b8adde7SWilliam Kucharski * %PCI_CAP_ID_PM Power Management 484*1b8adde7SWilliam Kucharski * 485*1b8adde7SWilliam Kucharski * %PCI_CAP_ID_AGP Accelerated Graphics Port 486*1b8adde7SWilliam Kucharski * 487*1b8adde7SWilliam Kucharski * %PCI_CAP_ID_VPD Vital Product Data 488*1b8adde7SWilliam Kucharski * 489*1b8adde7SWilliam Kucharski * %PCI_CAP_ID_SLOTID Slot Identification 490*1b8adde7SWilliam Kucharski * 491*1b8adde7SWilliam Kucharski * %PCI_CAP_ID_MSI Message Signalled Interrupts 492*1b8adde7SWilliam Kucharski * 493*1b8adde7SWilliam Kucharski * %PCI_CAP_ID_CHSWP CompactPCI HotSwap 494*1b8adde7SWilliam Kucharski */ 495*1b8adde7SWilliam Kucharski int pci_find_capability(struct pci_device *dev, int cap) 496*1b8adde7SWilliam Kucharski { 497*1b8adde7SWilliam Kucharski uint16_t status; 498*1b8adde7SWilliam Kucharski uint8_t pos, id; 499*1b8adde7SWilliam Kucharski uint8_t hdr_type; 500*1b8adde7SWilliam Kucharski int ttl = 48; 501*1b8adde7SWilliam Kucharski 502*1b8adde7SWilliam Kucharski pci_read_config_word(dev, PCI_STATUS, &status); 503*1b8adde7SWilliam Kucharski if (!(status & PCI_STATUS_CAP_LIST)) 504*1b8adde7SWilliam Kucharski return 0; 505*1b8adde7SWilliam Kucharski pci_read_config_byte(dev, PCI_HEADER_TYPE, &hdr_type); 506*1b8adde7SWilliam Kucharski switch (hdr_type & 0x7F) { 507*1b8adde7SWilliam Kucharski case PCI_HEADER_TYPE_NORMAL: 508*1b8adde7SWilliam Kucharski case PCI_HEADER_TYPE_BRIDGE: 509*1b8adde7SWilliam Kucharski default: 510*1b8adde7SWilliam Kucharski pci_read_config_byte(dev, PCI_CAPABILITY_LIST, &pos); 511*1b8adde7SWilliam Kucharski break; 512*1b8adde7SWilliam Kucharski case PCI_HEADER_TYPE_CARDBUS: 513*1b8adde7SWilliam Kucharski pci_read_config_byte(dev, PCI_CB_CAPABILITY_LIST, &pos); 514*1b8adde7SWilliam Kucharski break; 515*1b8adde7SWilliam Kucharski } 516*1b8adde7SWilliam Kucharski while (ttl-- && pos >= 0x40) { 517*1b8adde7SWilliam Kucharski pos &= ~3; 518*1b8adde7SWilliam Kucharski pci_read_config_byte(dev, pos + PCI_CAP_LIST_ID, &id); 519*1b8adde7SWilliam Kucharski #if DEBUG > 0 520*1b8adde7SWilliam Kucharski printf("Capability: %d\n", id); 521*1b8adde7SWilliam Kucharski #endif 522*1b8adde7SWilliam Kucharski if (id == 0xff) 523*1b8adde7SWilliam Kucharski break; 524*1b8adde7SWilliam Kucharski if (id == cap) 525*1b8adde7SWilliam Kucharski return pos; 526*1b8adde7SWilliam Kucharski pci_read_config_byte(dev, pos + PCI_CAP_LIST_NEXT, &pos); 527*1b8adde7SWilliam Kucharski } 528*1b8adde7SWilliam Kucharski return 0; 529*1b8adde7SWilliam Kucharski } 530*1b8adde7SWilliam Kucharski 531