diff options
author | jhb <jhb@FreeBSD.org> | 2002-09-06 17:08:07 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2002-09-06 17:08:07 +0000 |
commit | 49487ffa2c56cfdb3f1e348a058e462cc55e336d (patch) | |
tree | 73b1152b62f5dcf5057b2109c99dcf073441767f /sys/i386/pci/pci_cfgreg.c | |
parent | 7b3d4c8729c1e1340aafe9dbec1ef2189bae76df (diff) | |
download | FreeBSD-src-49487ffa2c56cfdb3f1e348a058e462cc55e336d.zip FreeBSD-src-49487ffa2c56cfdb3f1e348a058e462cc55e336d.tar.gz |
- Add a pci_cfgintr_valid() function to see if a given IRQ is a valid
IRQ for an entry in a PCIBIOS interrupt routing ($PIR) table.
- Change pci_cfgintr() to except the current IRQ of a device as a fourth
argument and to use that IRQ for the device if it is valid.
- If an intpin entry in a $PIR entry has a link of 0, it means that that
intpin isn't connected to anything that can trigger an interrupt. Thus,
test the link against 0 to find invalid entries in the table instead of
implicitly relying on the irqs field to be zero. In the machines I have
looked at, intpin entries with a link of 0 often have the bits for all
possible interrupts for PCI devices set.
Diffstat (limited to 'sys/i386/pci/pci_cfgreg.c')
-rw-r--r-- | sys/i386/pci/pci_cfgreg.c | 34 |
1 files changed, 33 insertions, 1 deletions
diff --git a/sys/i386/pci/pci_cfgreg.c b/sys/i386/pci/pci_cfgreg.c index b06316c..9938a52 100644 --- a/sys/i386/pci/pci_cfgreg.c +++ b/sys/i386/pci/pci_cfgreg.c @@ -61,6 +61,7 @@ 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); static int pci_cfgintr_linked(struct PIR_entry *pe, int pin); static int pci_cfgintr_search(struct PIR_entry *pe, int bus, int device, int matchpin, int pin); @@ -272,7 +273,7 @@ pci_cfgregwrite(int bus, int slot, int func, int reg, u_int32_t data, int bytes) * anyway, due to the way PCI interrupts are assigned. */ int -pci_cfgintr(int bus, int device, int pin) +pci_cfgintr(int bus, int device, int pin, int oldirq) { struct PIR_entry *pe; int i, irq; @@ -298,7 +299,20 @@ pci_cfgintr(int bus, int device, int pin) i++, pe++) { if ((bus != pe->pe_bus) || (device != pe->pe_device)) continue; + /* + * A link of 0 means that this intpin is not connected to + * any other device's interrupt pins and is not connected to + * any of the Interrupt Router's interrupt pins, so we can't + * route it. + */ + if (pe->pe_intpin[pin - 1].link == 0) + continue; + if (pci_cfgintr_valid(pe, pin, oldirq)) { + printf("pci_cfgintr: %d:%d INT%c BIOS irq %d\n", bus, + device, 'A' + pin - 1, oldirq); + return (oldirq); + } irq = pci_cfgintr_linked(pe, pin); if (irq == PCI_INVALID_IRQ) irq = pci_cfgintr_unique(pe, pin); @@ -338,6 +352,24 @@ pci_cfgintr(int bus, int device, int pin) } /* + * Check to see if an existing IRQ setting is valid. + */ +static int +pci_cfgintr_valid(struct PIR_entry *pe, int pin, int irq) +{ + uint32_t irqmask; + + if (!PCI_INTERRUPT_VALID(irq)) + return (0); + irqmask = pe->pe_intpin[pin - 1].irqs; + if (irqmask & (1 << irq)) { + PRVERB(("pci_cfgintr_valid: BIOS irq %d is valid\n", irq)); + return (1); + } + return (0); +} + +/* * Look to see if the routing table claims this pin is uniquely routed. */ static int |