summaryrefslogtreecommitdiffstats
path: root/sys/i386/pci/pci_pir.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/i386/pci/pci_pir.c')
-rw-r--r--sys/i386/pci/pci_pir.c54
1 files changed, 52 insertions, 2 deletions
diff --git a/sys/i386/pci/pci_pir.c b/sys/i386/pci/pci_pir.c
index d83591a..ef5f65b 100644
--- a/sys/i386/pci/pci_pir.c
+++ b/sys/i386/pci/pci_pir.c
@@ -46,6 +46,10 @@
#include <machine/segments.h>
#include <machine/pc/bios.h>
+#ifdef APIC_IO
+#include <machine/smp.h>
+#endif /* APIC_IO */
+
#include "pcib_if.h"
static int cfgmech;
@@ -112,16 +116,62 @@ pci_cfgregopen(void)
}
/*
- * Read configuration space register
+ * Read configuration space register
*/
u_int32_t
-pci_cfgregread(int bus, int slot, int func, int reg, int bytes)
+pci_do_cfgregread(int bus, int slot, int func, int reg, int bytes)
{
return(usebios ?
pcibios_cfgread(bus, slot, func, reg, bytes) :
pcireg_cfgread(bus, slot, func, reg, bytes));
}
+u_int32_t
+pci_cfgregread(int bus, int slot, int func, int reg, int bytes)
+{
+#ifdef APIC_IO
+ /*
+ * If we are using the APIC, the contents of the intline register will probably
+ * be wrong (since they are set up for use with the PIC.
+ * Rather than rewrite these registers (maybe that would be smarter) we trap
+ * attempts to read them and translate to our private vector numbers.
+ */
+ if ((reg == PCIR_INTLINE) && (bytes == 1)) {
+ int pin, line, airq;
+
+ pin = pci_do_cfgregread(bus, slot, func, PCIR_INTPIN, 1);
+ line = pci_do_cfgregread(bus, slot, func, PCIR_INTLINE, 1);
+
+ if (pin != 0) {
+ int airq;
+
+ airq = pci_apic_irq(bus, slot, pin);
+ if (airq >= 0) {
+ /* PCI specific entry found in MP table */
+ if (airq != line)
+ undirect_pci_irq(line);
+ return(airq);
+ } else {
+ /*
+ * PCI interrupts might be redirected to the
+ * ISA bus according to some MP tables. Use the
+ * same methods as used by the ISA devices
+ * devices to find the proper IOAPIC int pin.
+ */
+ airq = isa_apic_irq(line);
+ if ((airq >= 0) && (airq != line)) {
+ /* XXX: undirect_pci_irq() ? */
+ undirect_isa_irq(line);
+ return(airq);
+ }
+ }
+ }
+ return(line);
+ }
+#endif /* APIC_IO */
+ return(pci_do_cfgregread(bus, slot, func, reg, bytes));
+}
+
/*
* Write configuration space register
*/
OpenPOWER on IntegriCloud