diff options
Diffstat (limited to 'sys/amd64/pci')
-rw-r--r-- | sys/amd64/pci/pci_bus.c | 18 | ||||
-rw-r--r-- | sys/amd64/pci/pci_cfgreg.c | 157 |
2 files changed, 28 insertions, 147 deletions
diff --git a/sys/amd64/pci/pci_bus.c b/sys/amd64/pci/pci_bus.c index 7830406..9e28868 100644 --- a/sys/amd64/pci/pci_bus.c +++ b/sys/amd64/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/amd64/pci/pci_cfgreg.c b/sys/amd64/pci/pci_cfgreg.c index 8306922..4a174bd 100644 --- a/sys/amd64/pci/pci_cfgreg.c +++ b/sys/amd64/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) |