summaryrefslogtreecommitdiffstats
path: root/sys/i386/pci
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>2003-02-18 03:36:49 +0000
committerpeter <peter@FreeBSD.org>2003-02-18 03:36:49 +0000
commitc8ccde80634ad03a47022b779945a560de87ff45 (patch)
tree270743a1e37313780e77b69f0a64688c6a9451e2 /sys/i386/pci
parent6fe1c30dbcd92f7fc8f668bcaa4b2a0e07ad1eaa (diff)
downloadFreeBSD-src-c8ccde80634ad03a47022b779945a560de87ff45.zip
FreeBSD-src-c8ccde80634ad03a47022b779945a560de87ff45.tar.gz
Initiate de-orbit burn for USE_PCI_BIOS_FOR_READ_WRITE. This has been
#if'ed out for a while. Complete the deed and tidy up some other bits. We need to be able to call this stuff from outer edges of interrupt handlers for devices that have the ISR bits in pci config space. Making the bios code mpsafe was just too hairy. We had also stubbed it out some time ago due to there simply being too much brokenness in too many systems. This adds a leaf lock so that it is safe to use pci_read_config() and pci_write_config() from interrupt handlers. We still will use pcibios to do interrupt routing if there is no acpi.. [yes, I tested this] Briefly glanced at by: imp
Diffstat (limited to 'sys/i386/pci')
-rw-r--r--sys/i386/pci/pci_bus.c18
-rw-r--r--sys/i386/pci/pci_cfgreg.c157
-rw-r--r--sys/i386/pci/pci_pir.c157
3 files changed, 56 insertions, 276 deletions
diff --git a/sys/i386/pci/pci_bus.c b/sys/i386/pci/pci_bus.c
index 7830406..9e28868 100644
--- a/sys/i386/pci/pci_bus.c
+++ b/sys/i386/pci/pci_bus.c
@@ -310,7 +310,6 @@ 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;
@@ -402,23 +401,6 @@ 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 8306922..4a174bd 100644
--- a/sys/i386/pci/pci_cfgreg.c
+++ b/sys/i386/pci/pci_cfgreg.c
@@ -35,6 +35,8 @@
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/malloc.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <machine/md_var.h>
@@ -58,10 +60,6 @@
static int cfgmech;
static int devmax;
-static int usebios;
-static int enable_pcibios = 0;
-
-TUNABLE_INT("hw.pci.enable_pcibios", &enable_pcibios);
static int pci_cfgintr_valid(struct PIR_entry *pe, int pin, int irq);
static int pci_cfgintr_unique(struct PIR_entry *pe, int pin);
@@ -71,11 +69,6 @@ static int pci_cfgintr_virgin(struct PIR_entry *pe, int pin);
static void pci_print_irqmask(u_int16_t irqs);
static void pci_print_route_table(struct PIR_table *prt, int size);
-#ifdef USE_PCI_BIOS_FOR_READ_WRITE
-static int pcibios_cfgread(int bus, int slot, int func, int reg, int bytes);
-static void pcibios_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes);
-#endif
-static int pcibios_cfgopen(void);
static int pcireg_cfgread(int bus, int slot, int func, int reg, int bytes);
static void pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes);
static int pcireg_cfgopen(void);
@@ -83,6 +76,8 @@ static int pcireg_cfgopen(void);
static struct PIR_table *pci_route_table;
static int pci_route_count;
+static struct mtx pcicfg_mtx;
+
/*
* Some BIOS writers seem to want to ignore the spec and put
* 0 in the intline rather than 255 to indicate none. Some use
@@ -98,19 +93,6 @@ pci_i386_map_intline(int line)
return (line);
}
-int
-pci_pcibios_active(void)
-{
- return (usebios);
-}
-
-int
-pci_kill_pcibios(void)
-{
- usebios = 0;
- return (pcireg_cfgopen() != 0);
-}
-
static u_int16_t
pcibios_get_version(void)
{
@@ -141,19 +123,21 @@ pci_cfgregopen(void)
static int opened = 0;
u_long sigaddr;
static struct PIR_table *pt;
+ u_int16_t v;
u_int8_t ck, *cv;
int i;
if (opened)
return(1);
- if (pcibios_cfgopen() != 0)
- usebios = 1;
- else if (pcireg_cfgopen() != 0)
- usebios = 0;
- else
+ if (pcireg_cfgopen() == 0)
return(0);
+ v = pcibios_get_version();
+ if (v > 0)
+ printf("pcibios: BIOS version %x.%02x\n", (v & 0xff00) >> 8,
+ v & 0xff);
+
/*
* Look for the interrupt routing table.
*
@@ -187,6 +171,7 @@ pci_cfgregopen(void)
}
}
}
+ mtx_init(&pcicfg_mtx, "pcicfg", NULL, MTX_SPIN);
opened = 1;
return(1);
}
@@ -194,18 +179,6 @@ pci_cfgregopen(void)
/*
* Read configuration space register
*/
-static u_int32_t
-pci_do_cfgregread(int bus, int slot, int func, int reg, int bytes)
-{
-#ifdef USE_PCI_BIOS_FOR_READ_WRITE
- return(usebios ?
- pcibios_cfgread(bus, slot, func, reg, bytes) :
- pcireg_cfgread(bus, slot, func, reg, bytes));
-#else
- return (pcireg_cfgread(bus, slot, func, reg, bytes));
-#endif
-}
-
u_int32_t
pci_cfgregread(int bus, int slot, int func, int reg, int bytes)
{
@@ -222,8 +195,8 @@ pci_cfgregread(int bus, int slot, int func, int reg, int bytes)
*/
if ((reg == PCIR_INTLINE) && (bytes == 1)) {
- pin = pci_do_cfgregread(bus, slot, func, PCIR_INTPIN, 1);
- line = pci_do_cfgregread(bus, slot, func, PCIR_INTLINE, 1);
+ pin = pcireg_cfgread(bus, slot, func, PCIR_INTPIN, 1);
+ line = pcireg_cfgread(bus, slot, func, PCIR_INTLINE, 1);
if (pin != 0) {
int airq;
@@ -259,11 +232,11 @@ pci_cfgregread(int bus, int slot, int func, int reg, int bytes)
* the code uses 255 as an invalid IRQ.
*/
if (reg == PCIR_INTLINE && bytes == 1) {
- line = pci_do_cfgregread(bus, slot, func, PCIR_INTLINE, 1);
+ line = pcireg_cfgread(bus, slot, func, PCIR_INTLINE, 1);
return pci_i386_map_intline(line);
}
#endif /* APIC_IO */
- return(pci_do_cfgregread(bus, slot, func, reg, bytes));
+ return(pcireg_cfgread(bus, slot, func, reg, bytes));
}
/*
@@ -272,14 +245,8 @@ pci_cfgregread(int bus, int slot, int func, int reg, int bytes)
void
pci_cfgregwrite(int bus, int slot, int func, int reg, u_int32_t data, int bytes)
{
-#ifdef USE_PCI_BIOS_FOR_READ_WRITE
- if (usebios)
- pcibios_cfgwrite(bus, slot, func, reg, data, bytes);
- else
- pcireg_cfgwrite(bus, slot, func, reg, data, bytes);
-#else
+
pcireg_cfgwrite(bus, slot, func, reg, data, bytes);
-#endif
}
/*
@@ -626,81 +593,6 @@ pci_probe_route_table(int bus)
return (0);
}
-#ifdef USE_PCI_BIOS_FOR_READ_WRITE
-/*
- * Config space access using BIOS functions
- */
-static int
-pcibios_cfgread(int bus, int slot, int func, int reg, int bytes)
-{
- struct bios_regs args;
- u_int mask;
-
- switch(bytes) {
- case 1:
- args.eax = PCIBIOS_READ_CONFIG_BYTE;
- mask = 0xff;
- break;
- case 2:
- args.eax = PCIBIOS_READ_CONFIG_WORD;
- mask = 0xffff;
- break;
- case 4:
- args.eax = PCIBIOS_READ_CONFIG_DWORD;
- mask = 0xffffffff;
- break;
- default:
- return(-1);
- }
- args.ebx = (bus << 8) | (slot << 3) | func;
- args.edi = reg;
- bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL));
- /* check call results? */
- return(args.ecx & mask);
-}
-
-static void
-pcibios_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes)
-{
- struct bios_regs args;
-
- switch(bytes) {
- case 1:
- args.eax = PCIBIOS_WRITE_CONFIG_BYTE;
- break;
- case 2:
- args.eax = PCIBIOS_WRITE_CONFIG_WORD;
- break;
- case 4:
- args.eax = PCIBIOS_WRITE_CONFIG_DWORD;
- break;
- default:
- return;
- }
- args.ebx = (bus << 8) | (slot << 3) | func;
- args.ecx = data;
- args.edi = reg;
- bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL));
-}
-#endif
-
-/*
- * Determine whether there is a PCI BIOS present
- */
-static int
-pcibios_cfgopen(void)
-{
- u_int16_t v = 0;
-
- if (PCIbios.ventry != 0 && enable_pcibios) {
- v = pcibios_get_version();
- if (v > 0)
- printf("pcibios: BIOS version %x.%02x\n",
- (v & 0xff00) >> 8, v & 0xff);
- }
- return (v > 0);
-}
-
/*
* Configuration space access using direct register operations
*/
@@ -756,8 +648,8 @@ pcireg_cfgread(int bus, int slot, int func, int reg, int bytes)
int data = -1;
int port;
+ mtx_lock_spin(&pcicfg_mtx);
port = pci_cfgenable(bus, slot, func, reg, bytes);
-
if (port != 0) {
switch (bytes) {
case 1:
@@ -772,6 +664,7 @@ pcireg_cfgread(int bus, int slot, int func, int reg, int bytes)
}
pci_cfgdisable();
}
+ mtx_unlock_spin(&pcicfg_mtx);
return (data);
}
@@ -780,6 +673,7 @@ pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes)
{
int port;
+ mtx_lock_spin(&pcicfg_mtx);
port = pci_cfgenable(bus, slot, func, reg, bytes);
if (port != 0) {
switch (bytes) {
@@ -795,6 +689,7 @@ pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes)
}
pci_cfgdisable();
}
+ mtx_unlock_spin(&pcicfg_mtx);
}
/* check whether the configuration mechanism has been correctly identified */
@@ -804,6 +699,7 @@ pci_cfgcheck(int maxdev)
uint32_t id, class;
uint8_t header;
uint8_t device;
+ int port;
if (bootverbose)
printf("pci_cfgcheck:\tdevice ");
@@ -812,17 +708,20 @@ pci_cfgcheck(int maxdev)
if (bootverbose)
printf("%d ", device);
- id = inl(pci_cfgenable(0, device, 0, 0, 4));
+ port = pci_cfgenable(0, device, 0, 0, 4);
+ id = inl(port);
if (id == 0 || id == 0xffffffff)
continue;
- class = inl(pci_cfgenable(0, device, 0, 8, 4)) >> 8;
+ port = pci_cfgenable(0, device, 0, 8, 4);
+ class = inl(port) >> 8;
if (bootverbose)
printf("[class=%06x] ", class);
if (class == 0 || (class & 0xf870ff) != 0)
continue;
- header = inb(pci_cfgenable(0, device, 0, 14, 1));
+ port = pci_cfgenable(0, device, 0, 14, 1);
+ header = inb(port);
if (bootverbose)
printf("[hdr=%02x] ", header);
if ((header & 0x7e) != 0)
diff --git a/sys/i386/pci/pci_pir.c b/sys/i386/pci/pci_pir.c
index 8306922..4a174bd 100644
--- a/sys/i386/pci/pci_pir.c
+++ b/sys/i386/pci/pci_pir.c
@@ -35,6 +35,8 @@
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/malloc.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <machine/md_var.h>
@@ -58,10 +60,6 @@
static int cfgmech;
static int devmax;
-static int usebios;
-static int enable_pcibios = 0;
-
-TUNABLE_INT("hw.pci.enable_pcibios", &enable_pcibios);
static int pci_cfgintr_valid(struct PIR_entry *pe, int pin, int irq);
static int pci_cfgintr_unique(struct PIR_entry *pe, int pin);
@@ -71,11 +69,6 @@ static int pci_cfgintr_virgin(struct PIR_entry *pe, int pin);
static void pci_print_irqmask(u_int16_t irqs);
static void pci_print_route_table(struct PIR_table *prt, int size);
-#ifdef USE_PCI_BIOS_FOR_READ_WRITE
-static int pcibios_cfgread(int bus, int slot, int func, int reg, int bytes);
-static void pcibios_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes);
-#endif
-static int pcibios_cfgopen(void);
static int pcireg_cfgread(int bus, int slot, int func, int reg, int bytes);
static void pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes);
static int pcireg_cfgopen(void);
@@ -83,6 +76,8 @@ static int pcireg_cfgopen(void);
static struct PIR_table *pci_route_table;
static int pci_route_count;
+static struct mtx pcicfg_mtx;
+
/*
* Some BIOS writers seem to want to ignore the spec and put
* 0 in the intline rather than 255 to indicate none. Some use
@@ -98,19 +93,6 @@ pci_i386_map_intline(int line)
return (line);
}
-int
-pci_pcibios_active(void)
-{
- return (usebios);
-}
-
-int
-pci_kill_pcibios(void)
-{
- usebios = 0;
- return (pcireg_cfgopen() != 0);
-}
-
static u_int16_t
pcibios_get_version(void)
{
@@ -141,19 +123,21 @@ pci_cfgregopen(void)
static int opened = 0;
u_long sigaddr;
static struct PIR_table *pt;
+ u_int16_t v;
u_int8_t ck, *cv;
int i;
if (opened)
return(1);
- if (pcibios_cfgopen() != 0)
- usebios = 1;
- else if (pcireg_cfgopen() != 0)
- usebios = 0;
- else
+ if (pcireg_cfgopen() == 0)
return(0);
+ v = pcibios_get_version();
+ if (v > 0)
+ printf("pcibios: BIOS version %x.%02x\n", (v & 0xff00) >> 8,
+ v & 0xff);
+
/*
* Look for the interrupt routing table.
*
@@ -187,6 +171,7 @@ pci_cfgregopen(void)
}
}
}
+ mtx_init(&pcicfg_mtx, "pcicfg", NULL, MTX_SPIN);
opened = 1;
return(1);
}
@@ -194,18 +179,6 @@ pci_cfgregopen(void)
/*
* Read configuration space register
*/
-static u_int32_t
-pci_do_cfgregread(int bus, int slot, int func, int reg, int bytes)
-{
-#ifdef USE_PCI_BIOS_FOR_READ_WRITE
- return(usebios ?
- pcibios_cfgread(bus, slot, func, reg, bytes) :
- pcireg_cfgread(bus, slot, func, reg, bytes));
-#else
- return (pcireg_cfgread(bus, slot, func, reg, bytes));
-#endif
-}
-
u_int32_t
pci_cfgregread(int bus, int slot, int func, int reg, int bytes)
{
@@ -222,8 +195,8 @@ pci_cfgregread(int bus, int slot, int func, int reg, int bytes)
*/
if ((reg == PCIR_INTLINE) && (bytes == 1)) {
- pin = pci_do_cfgregread(bus, slot, func, PCIR_INTPIN, 1);
- line = pci_do_cfgregread(bus, slot, func, PCIR_INTLINE, 1);
+ pin = pcireg_cfgread(bus, slot, func, PCIR_INTPIN, 1);
+ line = pcireg_cfgread(bus, slot, func, PCIR_INTLINE, 1);
if (pin != 0) {
int airq;
@@ -259,11 +232,11 @@ pci_cfgregread(int bus, int slot, int func, int reg, int bytes)
* the code uses 255 as an invalid IRQ.
*/
if (reg == PCIR_INTLINE && bytes == 1) {
- line = pci_do_cfgregread(bus, slot, func, PCIR_INTLINE, 1);
+ line = pcireg_cfgread(bus, slot, func, PCIR_INTLINE, 1);
return pci_i386_map_intline(line);
}
#endif /* APIC_IO */
- return(pci_do_cfgregread(bus, slot, func, reg, bytes));
+ return(pcireg_cfgread(bus, slot, func, reg, bytes));
}
/*
@@ -272,14 +245,8 @@ pci_cfgregread(int bus, int slot, int func, int reg, int bytes)
void
pci_cfgregwrite(int bus, int slot, int func, int reg, u_int32_t data, int bytes)
{
-#ifdef USE_PCI_BIOS_FOR_READ_WRITE
- if (usebios)
- pcibios_cfgwrite(bus, slot, func, reg, data, bytes);
- else
- pcireg_cfgwrite(bus, slot, func, reg, data, bytes);
-#else
+
pcireg_cfgwrite(bus, slot, func, reg, data, bytes);
-#endif
}
/*
@@ -626,81 +593,6 @@ pci_probe_route_table(int bus)
return (0);
}
-#ifdef USE_PCI_BIOS_FOR_READ_WRITE
-/*
- * Config space access using BIOS functions
- */
-static int
-pcibios_cfgread(int bus, int slot, int func, int reg, int bytes)
-{
- struct bios_regs args;
- u_int mask;
-
- switch(bytes) {
- case 1:
- args.eax = PCIBIOS_READ_CONFIG_BYTE;
- mask = 0xff;
- break;
- case 2:
- args.eax = PCIBIOS_READ_CONFIG_WORD;
- mask = 0xffff;
- break;
- case 4:
- args.eax = PCIBIOS_READ_CONFIG_DWORD;
- mask = 0xffffffff;
- break;
- default:
- return(-1);
- }
- args.ebx = (bus << 8) | (slot << 3) | func;
- args.edi = reg;
- bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL));
- /* check call results? */
- return(args.ecx & mask);
-}
-
-static void
-pcibios_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes)
-{
- struct bios_regs args;
-
- switch(bytes) {
- case 1:
- args.eax = PCIBIOS_WRITE_CONFIG_BYTE;
- break;
- case 2:
- args.eax = PCIBIOS_WRITE_CONFIG_WORD;
- break;
- case 4:
- args.eax = PCIBIOS_WRITE_CONFIG_DWORD;
- break;
- default:
- return;
- }
- args.ebx = (bus << 8) | (slot << 3) | func;
- args.ecx = data;
- args.edi = reg;
- bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL));
-}
-#endif
-
-/*
- * Determine whether there is a PCI BIOS present
- */
-static int
-pcibios_cfgopen(void)
-{
- u_int16_t v = 0;
-
- if (PCIbios.ventry != 0 && enable_pcibios) {
- v = pcibios_get_version();
- if (v > 0)
- printf("pcibios: BIOS version %x.%02x\n",
- (v & 0xff00) >> 8, v & 0xff);
- }
- return (v > 0);
-}
-
/*
* Configuration space access using direct register operations
*/
@@ -756,8 +648,8 @@ pcireg_cfgread(int bus, int slot, int func, int reg, int bytes)
int data = -1;
int port;
+ mtx_lock_spin(&pcicfg_mtx);
port = pci_cfgenable(bus, slot, func, reg, bytes);
-
if (port != 0) {
switch (bytes) {
case 1:
@@ -772,6 +664,7 @@ pcireg_cfgread(int bus, int slot, int func, int reg, int bytes)
}
pci_cfgdisable();
}
+ mtx_unlock_spin(&pcicfg_mtx);
return (data);
}
@@ -780,6 +673,7 @@ pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes)
{
int port;
+ mtx_lock_spin(&pcicfg_mtx);
port = pci_cfgenable(bus, slot, func, reg, bytes);
if (port != 0) {
switch (bytes) {
@@ -795,6 +689,7 @@ pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes)
}
pci_cfgdisable();
}
+ mtx_unlock_spin(&pcicfg_mtx);
}
/* check whether the configuration mechanism has been correctly identified */
@@ -804,6 +699,7 @@ pci_cfgcheck(int maxdev)
uint32_t id, class;
uint8_t header;
uint8_t device;
+ int port;
if (bootverbose)
printf("pci_cfgcheck:\tdevice ");
@@ -812,17 +708,20 @@ pci_cfgcheck(int maxdev)
if (bootverbose)
printf("%d ", device);
- id = inl(pci_cfgenable(0, device, 0, 0, 4));
+ port = pci_cfgenable(0, device, 0, 0, 4);
+ id = inl(port);
if (id == 0 || id == 0xffffffff)
continue;
- class = inl(pci_cfgenable(0, device, 0, 8, 4)) >> 8;
+ port = pci_cfgenable(0, device, 0, 8, 4);
+ class = inl(port) >> 8;
if (bootverbose)
printf("[class=%06x] ", class);
if (class == 0 || (class & 0xf870ff) != 0)
continue;
- header = inb(pci_cfgenable(0, device, 0, 14, 1));
+ port = pci_cfgenable(0, device, 0, 14, 1);
+ header = inb(port);
if (bootverbose)
printf("[hdr=%02x] ", header);
if ((header & 0x7e) != 0)
OpenPOWER on IntegriCloud