summaryrefslogtreecommitdiffstats
path: root/sys/amd64/pci/pci_cfgreg.c
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2002-09-06 17:08:07 +0000
committerjhb <jhb@FreeBSD.org>2002-09-06 17:08:07 +0000
commit49487ffa2c56cfdb3f1e348a058e462cc55e336d (patch)
tree73b1152b62f5dcf5057b2109c99dcf073441767f /sys/amd64/pci/pci_cfgreg.c
parent7b3d4c8729c1e1340aafe9dbec1ef2189bae76df (diff)
downloadFreeBSD-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/amd64/pci/pci_cfgreg.c')
-rw-r--r--sys/amd64/pci/pci_cfgreg.c34
1 files changed, 33 insertions, 1 deletions
diff --git a/sys/amd64/pci/pci_cfgreg.c b/sys/amd64/pci/pci_cfgreg.c
index b06316c..9938a52 100644
--- a/sys/amd64/pci/pci_cfgreg.c
+++ b/sys/amd64/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
OpenPOWER on IntegriCloud