diff options
author | peter <peter@FreeBSD.org> | 2001-08-21 03:10:55 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 2001-08-21 03:10:55 +0000 |
commit | a6fa1409cbc02046d100fc143d019e076e5ca3e0 (patch) | |
tree | ca5e78a7629795acc383adf7359d25c41c82255c /sys | |
parent | 4694b279a2481f10ddcc8cd86ff0e76951aadbb3 (diff) | |
download | FreeBSD-src-a6fa1409cbc02046d100fc143d019e076e5ca3e0.zip FreeBSD-src-a6fa1409cbc02046d100fc143d019e076e5ca3e0.tar.gz |
Detect a certain type of PCIBIOS brain damage. For some reason,
some bios vendors took it apon themselves to "censor" the
host->pci bridges from PCIBIOS callers, even when the caller
explicitly asks for them. This includes certain Compaq machines
(eg: DL360) and some laptops.
If we detect this, shut down pcibios and revert to using IO
port bashing.
Under -current, apcica does a better job anyway.
Diffstat (limited to 'sys')
-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 */ |