summaryrefslogtreecommitdiffstats
path: root/sys/amd64
diff options
context:
space:
mode:
authormsmith <msmith@FreeBSD.org>2000-10-19 08:06:50 +0000
committermsmith <msmith@FreeBSD.org>2000-10-19 08:06:50 +0000
commitc9b6c92cc901e3f75bf123860844d35355f26147 (patch)
tree9ee41720bb28275c35ba82f25d966b827ad4249a /sys/amd64
parent22c3105dfabd7b712d92609b09a52568dd392d85 (diff)
downloadFreeBSD-src-c9b6c92cc901e3f75bf123860844d35355f26147.zip
FreeBSD-src-c9b6c92cc901e3f75bf123860844d35355f26147.tar.gz
Call the BIOS to route the selected interrupt. Correctly calculate the
interrupt from the PCI routing table (ffs returns 1 for the rightmost bit, not 0).
Diffstat (limited to 'sys/amd64')
-rw-r--r--sys/amd64/pci/pci_cfgreg.c26
1 files changed, 22 insertions, 4 deletions
diff --git a/sys/amd64/pci/pci_cfgreg.c b/sys/amd64/pci/pci_cfgreg.c
index 0de51ed..56107fc 100644
--- a/sys/amd64/pci/pci_cfgreg.c
+++ b/sys/amd64/pci/pci_cfgreg.c
@@ -133,12 +133,16 @@ pci_cfgregwrite(int bus, int slot, int func, int reg, u_int32_t data, int bytes)
*
* XXX this needs to learn to actually route uninitialised interrupts as well
* as just returning interrupts for stuff that's already initialised.
+ *
+ * XXX we don't do anything "right" with the function number in the PIR table
+ * (because the consumer isn't currently passing it in).
*/
int
pci_cfgintr(int bus, int device, int pin)
{
struct PIR_entry *pe;
- int i;
+ int i, irq;
+ struct bios_regs args;
if ((bus < 0) || (bus > 255) || (device < 0) || (device > 255) ||
(pin < 1) || (pin > 4))
@@ -151,11 +155,25 @@ pci_cfgintr(int bus, int device, int pin)
if ((bus != pe->pe_bus) || (device != pe->pe_device))
continue;
if (!powerof2(pe->pe_intpin[pin - 1].irqs)) {
- printf("pci_cfgintr: %d:%d:%c is not routed to a unique interrupt\n", bus, device, 'A' + pin - 1);
+ printf("pci_cfgintr: %d:%d:%c is not routed to a unique interrupt\n",
+ bus, device, 'A' + pin - 1);
break;
}
- printf("pci_cfgintr: %d:%d:%c routed to irq %d\n", bus, device, 'A' + pin - 1, ffs(pe->pe_intpin[pin - 1].irqs));
- return(ffs(pe->pe_intpin[pin - 1].irqs));
+ irq = ffs(pe->pe_intpin[pin - 1].irqs) - 1;
+ printf("pci_cfgintr: %d:%d:%c routed to irq %d\n",
+ bus, device, 'A' + pin - 1, irq);
+
+ /*
+ * Ask the BIOS to route the interrupt
+ */
+ 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));
+
+ /* XXX if it fails, we should smack the router hardware directly */
+
+ return(irq);
}
return(255);
}
OpenPOWER on IntegriCloud