summaryrefslogtreecommitdiffstats
path: root/sys/amd64/pci
diff options
context:
space:
mode:
authorimp <imp@FreeBSD.org>2001-08-27 20:44:38 +0000
committerimp <imp@FreeBSD.org>2001-08-27 20:44:38 +0000
commit8375ce85c2b31a7d940f0679d1e289ba5fee680e (patch)
treeca2ee026ca1a2fc140b517898521a8f1d20d9b58 /sys/amd64/pci
parentee73e559d2aad5011b278ac91e43887d15c2a49c (diff)
downloadFreeBSD-src-8375ce85c2b31a7d940f0679d1e289ba5fee680e.zip
FreeBSD-src-8375ce85c2b31a7d940f0679d1e289ba5fee680e.tar.gz
MFS: IRQ ordering, PRVERB and more whining in pcibios_get_version on failure.
Check return value from bios32. [[ Yes, I was bad and committed this to stable first. I should have done the commit in the other order. ]]
Diffstat (limited to 'sys/amd64/pci')
-rw-r--r--sys/amd64/pci/pci_cfgreg.c90
1 files changed, 60 insertions, 30 deletions
diff --git a/sys/amd64/pci/pci_cfgreg.c b/sys/amd64/pci/pci_cfgreg.c
index 1913075..d60241f 100644
--- a/sys/amd64/pci/pci_cfgreg.c
+++ b/sys/amd64/pci/pci_cfgreg.c
@@ -52,6 +52,8 @@
#include "pcib_if.h"
+#define PRVERB(a) printf a
+
static int cfgmech;
static int devmax;
static int usebios;
@@ -87,6 +89,27 @@ pci_kill_pcibios(void)
return pcireg_cfgopen() != 0;
}
+static u_int16_t
+pcibios_get_version(void)
+{
+ struct bios_regs args;
+
+ if (PCIbios.entry == 0) {
+ PRVERB(("pcibios: No call entry point\n"));
+ return (0);
+ }
+ args.eax = PCIBIOS_BIOS_PRESENT;
+ if (bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL))) {
+ PRVERB(("pcibios: BIOS_PRESENT call failed\n"));
+ return (0);
+ }
+ if (args.edx != 0x20494350) {
+ PRVERB(("pcibios: BIOS_PRESENT didn't return 'PCI ' in edx\n"));
+ return (0);
+ }
+ return (args.ebx & 0xffff);
+}
+
/*
* Initialise access to PCI configuration space
*/
@@ -113,9 +136,9 @@ pci_cfgregopen(void)
/*
* Look for the interrupt routing table.
*/
- /* XXX use PCI BIOS if it's available */
-
- if ((pt == NULL) && ((sigaddr = bios_sigsearch(0, "$PIR", 4, 16, 0)) != 0)) {
+ /* We use PCI BIOS's PIR table if it's available */
+ if (pcibios_get_version() >= 0x0210 && pt == NULL &&
+ (sigaddr = bios_sigsearch(0, "$PIR", 4, 16, 0)) != 0) {
pt = (struct PIR_table *)(uintptr_t)BIOS_PADDRTOVADDR(sigaddr);
for (cv = (u_int8_t *)pt, ck = 0, i = 0; i < (pt->pt_header.ph_length); i++) {
ck += cv[i];
@@ -212,7 +235,15 @@ pci_cfgintr(int bus, int device, int pin)
struct PIR_entry *pe;
int i, irq;
struct bios_regs args;
+ u_int16_t v;
+ v = pcibios_get_version();
+ if (v < 0x0210) {
+ PRVERB((
+ "pci_cfgintr: BIOS %x.%02x doesn't support interrupt routing\n",
+ (v & 0xff00) >> 8, v & 0xff));
+ return (255);
+ }
if ((bus < 0) || (bus > 255) || (device < 0) || (device > 255) ||
(pin < 1) || (pin > 4))
return(255);
@@ -224,10 +255,14 @@ pci_cfgintr(int bus, int device, int pin)
if ((bus != pe->pe_bus) || (device != pe->pe_device))
continue;
+ irq = pci_cfgintr_linked(pe, pin);
+ if (irq != 255) {
+ PRVERB(("pci_cfgintr: %d:%d INT%c already routed to irq %d\n",
+ bus, device, 'A' + pin - 1, irq));
+ return (irq);
+ }
irq = pci_cfgintr_unique(pe, pin);
if (irq == 255)
- irq = pci_cfgintr_linked(pe, pin);
- if (irq == 255)
irq = pci_cfgintr_virgin(pe, pin);
if (irq == 255)
@@ -240,18 +275,26 @@ pci_cfgintr(int bus, int device, int pin)
args.eax = PCIBIOS_ROUTE_INTERRUPT;
args.ebx = (bus << 8) | (device << 3);
args.ecx = (irq << 8) | (0xa + pin - 1); /* pin value is 0xa - 0xd */
- bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL));
+ if (bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL))) {
+ /*
+ * XXX if it fails, we should try to smack the router
+ * hardware directly.
+ * XXX Also, there may be other choices that we can try that
+ * will work.
+ */
+ PRVERB(("pci_cfgintr: ROUTE_INTERRUPT failured.\n"));
+ return(255);
+ }
/*
* XXX if it fails, we should try to smack the router hardware directly
*/
-
- printf("pci_cfgintr: %d:%d INT%c routed to irq %d\n",
- bus, device, 'A' + pin - 1, irq);
+ PRVERB(("pci_cfgintr: %d:%d INT%c routed to irq %d\n",
+ bus, device, 'A' + pin - 1, irq));
return(irq);
}
- printf("pci_cfgintr: can't route an interrupt to %d:%d INT%c\n", bus, device, 'A' + pin - 1);
+ PRVERB(("pci_cfgintr: can't route an interrupt to %d:%d INT%c\n", bus, device, 'A' + pin - 1));
return(255);
}
@@ -265,7 +308,7 @@ pci_cfgintr_unique(struct PIR_entry *pe, int pin)
if (powerof2(pe->pe_intpin[pin - 1].irqs)) {
irq = ffs(pe->pe_intpin[pin - 1].irqs) - 1;
- printf("pci_cfgintr_unique: hard-routed to irq %d\n", irq);
+ PRVERB(("pci_cfgintr_unique: hard-routed to irq %d\n", irq));
return(irq);
}
return(255);
@@ -301,8 +344,8 @@ pci_cfgintr_linked(struct PIR_entry *pe, int pin)
/* link destination mapped to a unique interrupt? */
if (powerof2(pi->irqs)) {
irq = ffs(pi->irqs) - 1;
- printf("pci_cfgintr_linked: linked (%x) to hard-routed irq %d\n",
- pi->link, irq);
+ PRVERB(("pci_cfgintr_linked: linked (%x) to hard-routed irq %d\n",
+ pi->link, irq));
return(irq);
}
@@ -349,9 +392,9 @@ pci_cfgintr_search(struct PIR_entry *pe, int bus, int device, int matchpin, int
(pci_get_slot(*childp) == device) &&
(pci_get_intpin(*childp) == matchpin) &&
((irq = pci_get_irq(*childp)) != 255)) {
- printf("pci_cfgintr_search: linked (%x) to configured irq %d at %d:%d:%d\n",
+ PRVERB(("pci_cfgintr_search: linked (%x) to configured irq %d at %d:%d:%d\n",
pe->pe_intpin[pin - 1].link, irq,
- pci_get_bus(*childp), pci_get_slot(*childp), pci_get_function(*childp));
+ pci_get_bus(*childp), pci_get_slot(*childp), pci_get_function(*childp)));
break;
}
}
@@ -378,7 +421,7 @@ pci_cfgintr_virgin(struct PIR_entry *pe, int pin)
/* can we use this interrupt? */
if ((pci_route_table->pt_header.ph_pci_irqs & ibit) &&
(pe->pe_intpin[pin - 1].irqs & ibit)) {
- printf("pci_cfgintr_virgin: using routable PCI-only interrupt %d\n", irq);
+ PRVERB(("pci_cfgintr_virgin: using routable PCI-only interrupt %d\n", irq));
return(irq);
}
}
@@ -388,7 +431,7 @@ pci_cfgintr_virgin(struct PIR_entry *pe, int pin)
ibit = (1 << irq);
if (pe->pe_intpin[pin - 1].irqs & ibit) {
- printf("pci_cfgintr_virgin: using routable interrupt %d\n", irq);
+ PRVERB(("pci_cfgintr_virgin: using routable interrupt %d\n", irq));
return(irq);
}
}
@@ -452,19 +495,6 @@ pcibios_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes)
bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL));
}
-static u_int16_t
-pcibios_get_version(void)
-{
- struct bios_regs args;
-
- args.eax = PCIBIOS_BIOS_PRESENT;
- if (bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL)))
- return (0x0000);
- if (args.edx != 0x20494350)
- return (0x0000);
- return (args.ebx & 0xffff);
-}
-
/*
* Determine whether there is a PCI BIOS present
*/
OpenPOWER on IntegriCloud