diff options
-rw-r--r-- | sys/amd64/include/pci_cfgreg.h | 2 | ||||
-rw-r--r-- | sys/amd64/pci/pci_bus.c | 18 | ||||
-rw-r--r-- | sys/amd64/pci/pci_cfgreg.c | 13 | ||||
-rw-r--r-- | sys/i386/include/pci_cfgreg.h | 2 | ||||
-rw-r--r-- | sys/i386/pci/pci_bus.c | 18 | ||||
-rw-r--r-- | sys/i386/pci/pci_cfgreg.c | 13 | ||||
-rw-r--r-- | sys/i386/pci/pci_pir.c | 13 |
7 files changed, 79 insertions, 0 deletions
diff --git a/sys/amd64/include/pci_cfgreg.h b/sys/amd64/include/pci_cfgreg.h index 6e79a22..78287cb 100644 --- a/sys/amd64/include/pci_cfgreg.h +++ b/sys/amd64/include/pci_cfgreg.h @@ -51,3 +51,5 @@ extern int pci_cfgregopen(void); extern u_int32_t pci_cfgregread(int bus, int slot, int func, int reg, int bytes); extern void pci_cfgregwrite(int bus, int slot, int func, int reg, u_int32_t data, int bytes); extern int pci_cfgintr(int bus, int device, int pin); +extern int pci_kill_pcibios(void); +extern int pci_pcibios_active(void); diff --git a/sys/amd64/pci/pci_bus.c b/sys/amd64/pci/pci_bus.c index dfd4967..b01cc2d 100644 --- a/sys/amd64/pci/pci_bus.c +++ b/sys/amd64/pci/pci_bus.c @@ -268,6 +268,7 @@ nexus_pcib_identify(driver_t *driver, device_t parent) int pcifunchigh; int found824xx = 0; int found_orion = 0; + int found_pcibios_flaming_death = 0; device_t child; devclass_t pci_devclass; @@ -359,6 +360,23 @@ nexus_pcib_identify(driver_t *driver, device_t parent) } /* + * This is just freaking brilliant! Some BIOS writers have + * decided that we must be forcibly prevented from using + * PCIBIOS to query the host->pci bridges. If you try and + * access configuration registers, it pretends there is + * no pci device at that bus:device:function address. + */ + if (!found && pci_pcibios_active() && !found_pcibios_flaming_death) { + /* retry with the old mechanism, or fail */ + if (pci_kill_pcibios() == 0) + return; + printf("nexus_pcib_identify: found broken PCIBIOS - disabling it and retrying.\n"); + printf("nexus_pcib_identify: it is bogusly censoring host->pci bridges.\n"); + found_pcibios_flaming_death = 1; + goto retry; + } + + /* * Make sure we add at least one bridge since some old * hardware doesn't actually have a host-pci bridge device. * Note that pci_cfgregopen() thinks we have PCI devices.. diff --git a/sys/amd64/pci/pci_cfgreg.c b/sys/amd64/pci/pci_cfgreg.c index 7b73486..3538969 100644 --- a/sys/amd64/pci/pci_cfgreg.c +++ b/sys/amd64/pci/pci_cfgreg.c @@ -71,6 +71,19 @@ static int pcireg_cfgopen(void); static struct PIR_table *pci_route_table; static int pci_route_count; +int +pci_pcibios_active(void) +{ + return usebios; +} + +int +pci_kill_pcibios(void) +{ + usebios = 0; + return pcireg_cfgopen() != 0; +} + /* * Initialise access to PCI configuration space */ diff --git a/sys/i386/include/pci_cfgreg.h b/sys/i386/include/pci_cfgreg.h index 6e79a22..78287cb 100644 --- a/sys/i386/include/pci_cfgreg.h +++ b/sys/i386/include/pci_cfgreg.h @@ -51,3 +51,5 @@ extern int pci_cfgregopen(void); extern u_int32_t pci_cfgregread(int bus, int slot, int func, int reg, int bytes); extern void pci_cfgregwrite(int bus, int slot, int func, int reg, u_int32_t data, int bytes); extern int pci_cfgintr(int bus, int device, int pin); +extern int pci_kill_pcibios(void); +extern int pci_pcibios_active(void); diff --git a/sys/i386/pci/pci_bus.c b/sys/i386/pci/pci_bus.c index dfd4967..b01cc2d 100644 --- a/sys/i386/pci/pci_bus.c +++ b/sys/i386/pci/pci_bus.c @@ -268,6 +268,7 @@ nexus_pcib_identify(driver_t *driver, device_t parent) int pcifunchigh; int found824xx = 0; int found_orion = 0; + int found_pcibios_flaming_death = 0; device_t child; devclass_t pci_devclass; @@ -359,6 +360,23 @@ nexus_pcib_identify(driver_t *driver, device_t parent) } /* + * This is just freaking brilliant! Some BIOS writers have + * decided that we must be forcibly prevented from using + * PCIBIOS to query the host->pci bridges. If you try and + * access configuration registers, it pretends there is + * no pci device at that bus:device:function address. + */ + if (!found && pci_pcibios_active() && !found_pcibios_flaming_death) { + /* retry with the old mechanism, or fail */ + if (pci_kill_pcibios() == 0) + return; + printf("nexus_pcib_identify: found broken PCIBIOS - disabling it and retrying.\n"); + printf("nexus_pcib_identify: it is bogusly censoring host->pci bridges.\n"); + found_pcibios_flaming_death = 1; + goto retry; + } + + /* * Make sure we add at least one bridge since some old * hardware doesn't actually have a host-pci bridge device. * Note that pci_cfgregopen() thinks we have PCI devices.. diff --git a/sys/i386/pci/pci_cfgreg.c b/sys/i386/pci/pci_cfgreg.c index 7b73486..3538969 100644 --- a/sys/i386/pci/pci_cfgreg.c +++ b/sys/i386/pci/pci_cfgreg.c @@ -71,6 +71,19 @@ static int pcireg_cfgopen(void); static struct PIR_table *pci_route_table; static int pci_route_count; +int +pci_pcibios_active(void) +{ + return usebios; +} + +int +pci_kill_pcibios(void) +{ + usebios = 0; + return pcireg_cfgopen() != 0; +} + /* * Initialise access to PCI configuration space */ diff --git a/sys/i386/pci/pci_pir.c b/sys/i386/pci/pci_pir.c index 7b73486..3538969 100644 --- a/sys/i386/pci/pci_pir.c +++ b/sys/i386/pci/pci_pir.c @@ -71,6 +71,19 @@ static int pcireg_cfgopen(void); static struct PIR_table *pci_route_table; static int pci_route_count; +int +pci_pcibios_active(void) +{ + return usebios; +} + +int +pci_kill_pcibios(void) +{ + usebios = 0; + return pcireg_cfgopen() != 0; +} + /* * Initialise access to PCI configuration space */ |