summaryrefslogtreecommitdiffstats
path: root/sys/i386/pci
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2005-04-14 18:25:09 +0000
committerjhb <jhb@FreeBSD.org>2005-04-14 18:25:09 +0000
commitd6a800e5926c0c3aff8d4e1edea3220c21ec2d2e (patch)
treef9b55d2f089ae96090fda21e2173847e4459669b /sys/i386/pci
parentd3ad4828d61536a544fb3011197e8c19433449e3 (diff)
downloadFreeBSD-src-d6a800e5926c0c3aff8d4e1edea3220c21ec2d2e.zip
FreeBSD-src-d6a800e5926c0c3aff8d4e1edea3220c21ec2d2e.tar.gz
Trust the settings programmed by the BIOS over what the $PIR says.
Specifically, if the BIOS has programmed an IRQ for a device that doesn't match the list of valid IRQs for the link, use it anyway as some BIOSes don't correctly list the valid IRQs in the $PIR. Also, allow the user to specify an IRQ that $PIR claims is invalid as an override, but emit a warning in that case.
Diffstat (limited to 'sys/i386/pci')
-rw-r--r--sys/i386/pci/pci_pir.c66
1 files changed, 48 insertions, 18 deletions
diff --git a/sys/i386/pci/pci_pir.c b/sys/i386/pci/pci_pir.c
index 89e8356..faeb0a7 100644
--- a/sys/i386/pci/pci_pir.c
+++ b/sys/i386/pci/pci_pir.c
@@ -324,22 +324,50 @@ pci_pir_initial_irqs(struct PIR_entry *entry, struct PIR_intpin *intpin,
pin = intpin - entry->pe_intpin;
pci_link = pci_pir_find_link(intpin->link);
irq = pci_pir_search_irq(entry->pe_bus, entry->pe_device, pin);
- if (irq == PCI_INVALID_IRQ)
+ if (irq == PCI_INVALID_IRQ || irq == pci_link->pl_irq)
return;
- if (pci_pir_valid_irq(pci_link, irq)) {
- if (pci_link->pl_irq == PCI_INVALID_IRQ) {
- pci_link->pl_irq = irq;
- pci_link->pl_routed = 1;
- } else if (pci_link->pl_irq != irq)
+
+ /*
+ * If we don't have an IRQ for this link yet, then we trust the
+ * BIOS, even if it seems invalid from the $PIR entries.
+ */
+ if (pci_link->pl_irq == PCI_INVALID_IRQ) {
+ if (!pci_pir_valid_irq(pci_link, irq))
printf(
- "$PIR: BIOS IRQ %d for %d.%d.INT%c does not match link %#x irq %d\n",
+ "$PIR: Using invalid BIOS IRQ %d from %d.%d.INT%c is for link %#x\n",
irq, entry->pe_bus, entry->pe_device, pin + 'A',
- pci_link->pl_id, pci_link->pl_irq);
- } else
+ pci_link->pl_id);
+ pci_link->pl_irq = irq;
+ pci_link->pl_routed = 1;
+ return;
+ }
+
+ /*
+ * We have an IRQ and it doesn't match the current IRQ for this
+ * link. If the new IRQ is invalid, then warn about it and ignore
+ * it. If the old IRQ is invalid and the new IRQ is valid, then
+ * prefer the new IRQ instead. If both IRQs are valid, then just
+ * use the first one. Note that if we ever get into this situation
+ * we are having to guess which setting the BIOS actually routed.
+ * Perhaps we should just give up instead.
+ */
+ if (!pci_pir_valid_irq(pci_link, irq)) {
printf(
"$PIR: BIOS IRQ %d for %d.%d.INT%c is not valid for link %#x\n",
irq, entry->pe_bus, entry->pe_device, pin + 'A',
pci_link->pl_id);
+ } else if (!pci_pir_valid_irq(pci_link, pci_link->pl_irq)) {
+ printf(
+"$PIR: Preferring valid BIOS IRQ %d from %d.%d.INT%c for link %#x to IRQ %d\n",
+ irq, entry->pe_bus, entry->pe_device, pin + 'A',
+ pci_link->pl_id, pci_link->pl_irq);
+ pci_link->pl_irq = irq;
+ pci_link->pl_routed = 1;
+ } else
+ printf(
+ "$PIR: BIOS IRQ %d for %d.%d.INT%c does not match link %#x irq %d\n",
+ irq, entry->pe_bus, entry->pe_device, pin + 'A',
+ pci_link->pl_id, pci_link->pl_irq);
}
/*
@@ -386,9 +414,9 @@ pci_pir_parse(void)
}
/*
- * Allow the user to override the IRQ for a given link device as
- * long as the override is valid or is 255 or 0 to clear a preset
- * IRQ.
+ * Allow the user to override the IRQ for a given link device. We
+ * allow invalid IRQs to be specified but warn about them. An IRQ
+ * of 255 or 0 clears any preset IRQ.
*/
i = 0;
TAILQ_FOREACH(pci_link, &pci_links, pl_links) {
@@ -398,12 +426,14 @@ pci_pir_parse(void)
continue;
if (irq == 0)
irq = PCI_INVALID_IRQ;
- if (irq == PCI_INVALID_IRQ ||
- pci_pir_valid_irq(pci_link, irq)) {
- pci_link->pl_routed = 0;
- pci_link->pl_irq = irq;
- i = 1;
- }
+ if (irq != PCI_INVALID_IRQ &&
+ !pci_pir_valid_irq(pci_link, irq) && bootverbose)
+ printf(
+ "$PIR: Warning, IRQ %d for link %#x is not listed as valid\n",
+ irq, pci_link->pl_id);
+ pci_link->pl_routed = 0;
+ pci_link->pl_irq = irq;
+ i = 1;
}
if (bootverbose && i) {
printf("$PIR: Links after tunable overrides:\n");
OpenPOWER on IntegriCloud