diff options
author | msmith <msmith@FreeBSD.org> | 2000-10-19 08:06:50 +0000 |
---|---|---|
committer | msmith <msmith@FreeBSD.org> | 2000-10-19 08:06:50 +0000 |
commit | c9b6c92cc901e3f75bf123860844d35355f26147 (patch) | |
tree | 9ee41720bb28275c35ba82f25d966b827ad4249a /sys/i386/pci/pci_pir.c | |
parent | 22c3105dfabd7b712d92609b09a52568dd392d85 (diff) | |
download | FreeBSD-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/i386/pci/pci_pir.c')
-rw-r--r-- | sys/i386/pci/pci_pir.c | 26 |
1 files changed, 22 insertions, 4 deletions
diff --git a/sys/i386/pci/pci_pir.c b/sys/i386/pci/pci_pir.c index 0de51ed..56107fc 100644 --- a/sys/i386/pci/pci_pir.c +++ b/sys/i386/pci/pci_pir.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); } |