summaryrefslogtreecommitdiff
path: root/sys/arch/i386/pci
diff options
context:
space:
mode:
authorMichael Shalayeff <mickey@cvs.openbsd.org>2005-11-23 09:24:58 +0000
committerMichael Shalayeff <mickey@cvs.openbsd.org>2005-11-23 09:24:58 +0000
commitb798e30277e3f181d9ea559fa8f352c70f5bbcb9 (patch)
treea6d8f3334d4f670787880b4709e724a4fc3c0b43 /sys/arch/i386/pci
parentc56c28566cdd540950b965d8db45d6e49cc60434 (diff)
resolve a couple of problems in mpbios-mapped interrupts:
- synthesise isa mappings (as 1-1) should those be missing in mpbios; - for rcc osb* firce "special" ints into isa mappings always. niklas@ ok and testing by many since
Diffstat (limited to 'sys/arch/i386/pci')
-rw-r--r--sys/arch/i386/pci/pci_intr_fixup.c31
-rw-r--r--sys/arch/i386/pci/pci_machdep.c28
-rw-r--r--sys/arch/i386/pci/pcibiosvar.h4
-rw-r--r--sys/arch/i386/pci/rccosb4.c14
-rw-r--r--sys/arch/i386/pci/rccosb4reg.h3
5 files changed, 44 insertions, 36 deletions
diff --git a/sys/arch/i386/pci/pci_intr_fixup.c b/sys/arch/i386/pci/pci_intr_fixup.c
index 5a1be5e0c3b..7fd8492e10e 100644
--- a/sys/arch/i386/pci/pci_intr_fixup.c
+++ b/sys/arch/i386/pci/pci_intr_fixup.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pci_intr_fixup.c,v 1.48 2005/11/21 22:28:13 brad Exp $ */
+/* $OpenBSD: pci_intr_fixup.c,v 1.49 2005/11/23 09:24:57 mickey Exp $ */
/* $NetBSD: pci_intr_fixup.c,v 1.10 2000/08/10 21:18:27 soda Exp $ */
/*
@@ -101,6 +101,7 @@
#include <machine/bus.h>
#include <machine/intr.h>
#include <machine/i8259.h>
+#include <machine/i82093var.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
@@ -535,15 +536,15 @@ pci_intr_route_link(pc, ihp)
{
struct pciintr_link_map *l;
pcireg_t intr;
- int rv = 1;
+ int irq, rv = 1;
char *p = NULL;
if (pcibios_flags & PCIBIOS_INTR_FIXUP)
return 1;
- if (ihp->line != 0 &&
- ihp->line != I386_PCI_INTERRUPT_LINE_NO_CONNECTION)
- pcibios_pir_header.exclusive_irq |= (1 << ihp->line);
+ irq = ihp->line & APIC_INT_LINE_MASK;
+ if (irq != 0 && irq != I386_PCI_INTERRUPT_LINE_NO_CONNECTION)
+ pcibios_pir_header.exclusive_irq |= 1 << irq;
l = ihp->link;
if (!l || pciintr_icu_tag == NULL)
@@ -584,13 +585,13 @@ pci_intr_route_link(pc, ihp)
* IRQs 14 and 15 are reserved for PCI IDE interrupts; don't muck
* with them.
*/
- if (ihp->line == 14 || ihp->line == 15)
+ if (irq == 14 || irq == 15)
return (1);
intr = pci_conf_read(pc, ihp->tag, PCI_INTERRUPT_REG);
- if (ihp->line != PCI_INTERRUPT_LINE(intr)) {
+ if (irq != PCI_INTERRUPT_LINE(intr)) {
intr &= ~(PCI_INTERRUPT_LINE_MASK << PCI_INTERRUPT_LINE_SHIFT);
- intr |= (ihp->line << PCI_INTERRUPT_LINE_SHIFT);
+ intr |= irq << PCI_INTERRUPT_LINE_SHIFT;
pci_conf_write(pc, ihp->tag, PCI_INTERRUPT_REG, intr);
}
@@ -651,7 +652,7 @@ pci_intr_header_fixup(pc, tag, ihp)
if (pcibios_flags & PCIBIOS_INTR_FIXUP)
return 1;
- irq = ihp->line;
+ irq = ihp->line & APIC_INT_LINE_MASK;
ihp->link = NULL;
ihp->tag = tag;
pci_decompose_tag(pc, tag, &bus, &device, &function);
@@ -666,7 +667,7 @@ pci_intr_header_fixup(pc, tag, ihp)
/*
* No link map entry.
* Probably pciintr_icu_getclink() or pciintr_icu_get_intr()
- * was failed.
+ * has failed.
*/
if (pcibios_flags & PCIBIOS_INTRDEBUG)
printf("pci_intr_header_fixup: no entry for link "
@@ -682,8 +683,8 @@ pci_intr_header_fixup(pc, tag, ihp)
} else if (l->irq == I386_PCI_INTERRUPT_LINE_NO_CONNECTION) {
/* Appropriate interrupt was not found. */
- if (pciintr_icu_tag == NULL && ihp->line != 0 &&
- ihp->line != I386_PCI_INTERRUPT_LINE_NO_CONNECTION)
+ if (pciintr_icu_tag == NULL && irq != 0 &&
+ irq != I386_PCI_INTERRUPT_LINE_NO_CONNECTION)
/*
* Do not print warning,
* if no compatible PCI ICU found,
@@ -695,17 +696,17 @@ pci_intr_header_fixup(pc, tag, ihp)
} else if (irq == 0 || irq == I386_PCI_INTERRUPT_LINE_NO_CONNECTION) {
p = " fixed up";
- ihp->line = l->irq;
+ ihp->line = irq = l->irq;
} else if (pcibios_flags & PCIBIOS_FIXUP_FORCE) {
/* routed by BIOS, but inconsistent */
/* believe PCI IRQ Routing table */
p = " WARNING: overriding";
- ihp->line = l->irq;
+ ihp->line = irq = l->irq;
} else {
/* believe PCI Interrupt Configuration Register (default) */
p = " WARNING: preserving";
- ihp->line = l->irq = irq;
+ ihp->line = (l->irq = irq) | (l->clink & PCI_INT_VIA_ISA);
}
if (pcibios_flags & PCIBIOS_INTRDEBUG) {
diff --git a/sys/arch/i386/pci/pci_machdep.c b/sys/arch/i386/pci/pci_machdep.c
index 8e8764428f8..a84bd091173 100644
--- a/sys/arch/i386/pci/pci_machdep.c
+++ b/sys/arch/i386/pci/pci_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pci_machdep.c,v 1.29 2005/07/28 17:22:28 brad Exp $ */
+/* $OpenBSD: pci_machdep.c,v 1.30 2005/11/23 09:24:57 mickey Exp $ */
/* $NetBSD: pci_machdep.c,v 1.28 1997/06/06 23:29:17 thorpej Exp $ */
/*-
@@ -107,8 +107,8 @@ extern bios_pciinfo_t *bios_pciinfo;
#include "ioapic.h"
-#if NIOAPIC > 0
#include <machine/i82093var.h>
+#if NIOAPIC > 0
#include <machine/mpbiosvar.h>
#endif
@@ -510,7 +510,7 @@ pci_intr_map(pa, ihp)
ihp->pin = pin;
#if NPCIBIOS > 0
pci_intr_header_fixup(pc, intrtag, ihp);
- line = ihp->line;
+ line = ihp->line & APIC_INT_LINE_MASK;
#endif
/*
@@ -543,7 +543,7 @@ pci_intr_map(pa, ihp)
#if NIOAPIC > 0
pci_decompose_tag (pc, intrtag, &bus, &dev, &func);
- if (mp_busses != NULL) {
+ if (!(ihp->line & PCI_INT_VIA_ISA) && mp_busses != NULL) {
/*
* Assumes 1:1 mapping between PCI bus numbers and
* the numbers given by the MP bios.
@@ -597,20 +597,20 @@ pci_intr_string(pc, ih)
pci_intr_handle_t ih;
{
static char irqstr[64];
+ int line = ih.line & APIC_INT_LINE_MASK;
- if (ih.line == 0 || (ih.line & 0xff) >= ICU_LEN || ih.line == 2)
- panic("pci_intr_string: bogus handle 0x%x", ih.line);
+ if (line == 0 || line >= ICU_LEN || line == 2)
+ panic("pci_intr_string: bogus handle 0x%x", line);
#if NIOAPIC > 0
if (ih.line & APIC_INT_VIA_APIC) {
snprintf(irqstr, sizeof irqstr, "apic %d int %d (irq %d)",
- APIC_IRQ_APIC(ih.line), APIC_IRQ_PIN(ih.line),
- ih.line & 0xff);
+ APIC_IRQ_APIC(ih.line), APIC_IRQ_PIN(ih.line), line);
return (irqstr);
}
#endif
- snprintf(irqstr, sizeof irqstr, "irq %d", ih.line);
+ snprintf(irqstr, sizeof irqstr, "irq %d", line);
return (irqstr);
}
@@ -623,17 +623,17 @@ pci_intr_establish(pc, ih, level, func, arg, what)
char *what;
{
void *ret;
+ int l = ih.line & APIC_INT_LINE_MASK;
#if NIOAPIC > 0
- if (ih.line != -1 && ih.line & APIC_INT_VIA_APIC)
+ if (l != -1 && ih.line & APIC_INT_VIA_APIC)
return (apic_intr_establish(ih.line, IST_LEVEL, level, func,
arg, what));
#endif
- if (ih.line == 0 || ih.line >= ICU_LEN || ih.line == 2)
- panic("pci_intr_establish: bogus handle 0x%x", ih.line);
+ if (l == 0 || l >= ICU_LEN || l == 2)
+ panic("pci_intr_establish: bogus handle 0x%x", l);
- ret = isa_intr_establish(NULL, ih.line, IST_LEVEL, level, func, arg,
- what);
+ ret = isa_intr_establish(NULL, l, IST_LEVEL, level, func, arg, what);
#if NPCIBIOS > 0
if (ret)
pci_intr_route_link(pc, &ih);
diff --git a/sys/arch/i386/pci/pcibiosvar.h b/sys/arch/i386/pci/pcibiosvar.h
index 41ec746be6b..e0ec0d7bfee 100644
--- a/sys/arch/i386/pci/pcibiosvar.h
+++ b/sys/arch/i386/pci/pcibiosvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pcibiosvar.h,v 1.14 2004/09/26 20:17:42 mickey Exp $ */
+/* $OpenBSD: pcibiosvar.h,v 1.15 2005/11/23 09:24:57 mickey Exp $ */
/* $NetBSD: pcibios.h,v 1.2 2000/04/28 17:15:16 uch Exp $ */
/*
@@ -146,6 +146,8 @@ typedef const struct pciintr_icu *pciintr_icu_tag_t;
#define PCIADDR_SEARCH_MEM 1
struct extent *pciaddr_search(int, bus_addr_t *, bus_size_t);
+#define PCI_INT_VIA_ISA 0x20000000 /* XXX see APIC_INT_VIA_APIC */
+
int pci_intr_fixup(struct pcibios_softc *, pci_chipset_tag_t, bus_space_tag_t);
int pci_bus_fixup(pci_chipset_tag_t, int);
void pci_addr_fixup(struct pcibios_softc *, pci_chipset_tag_t, int);
diff --git a/sys/arch/i386/pci/rccosb4.c b/sys/arch/i386/pci/rccosb4.c
index fcef7bbcc6b..160b4772a2a 100644
--- a/sys/arch/i386/pci/rccosb4.c
+++ b/sys/arch/i386/pci/rccosb4.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rccosb4.c,v 1.3 2005/11/10 15:14:09 mickey Exp $ */
+/* $OpenBSD: rccosb4.c,v 1.4 2005/11/23 09:24:57 mickey Exp $ */
/*
* Copyright (c) 2004,2005 Michael Shalayeff
@@ -98,6 +98,8 @@ osb4_getclink(pciintr_icu_handle_t v, int link, int *clinkp)
{
if (OSB4_LEGAL_LINK(link - 1)) {
*clinkp = link;
+ if (link <= OSB4_PISP)
+ *clinkp |= PCI_INT_VIA_ISA;
return (0);
}
@@ -108,11 +110,12 @@ int
osb4_get_intr(pciintr_icu_handle_t v, int clink, int *irqp)
{
struct osb4_handle *ph = v;
+ int link = clink & 0xff;
- if (!OSB4_LEGAL_LINK(clink))
+ if (!OSB4_LEGAL_LINK(link))
return (1);
- bus_space_write_1(ph->osb4_iot, ph->osb4_ioh, 0, clink);
+ bus_space_write_1(ph->osb4_iot, ph->osb4_ioh, 0, link);
*irqp = bus_space_read_1(ph->osb4_iot, ph->osb4_ioh, 1) & 0xf;
if (*irqp == 0)
*irqp = I386_PCI_INTERRUPT_LINE_NO_CONNECTION;
@@ -124,11 +127,12 @@ int
osb4_set_intr(pciintr_icu_handle_t v, int clink, int irq)
{
struct osb4_handle *ph = v;
+ int link = clink & 0xff;
- if (!OSB4_LEGAL_LINK(clink) || !OSB4_LEGAL_IRQ(irq & 0xf))
+ if (!OSB4_LEGAL_LINK(link) || !OSB4_LEGAL_IRQ(irq & 0xf))
return (1);
- bus_space_write_1(ph->osb4_iot, ph->osb4_ioh, 0, clink);
+ bus_space_write_1(ph->osb4_iot, ph->osb4_ioh, 0, link);
bus_space_write_1(ph->osb4_iot, ph->osb4_ioh, 1, irq & 0xf);
return (0);
diff --git a/sys/arch/i386/pci/rccosb4reg.h b/sys/arch/i386/pci/rccosb4reg.h
index bc38b9653d6..69a9407e156 100644
--- a/sys/arch/i386/pci/rccosb4reg.h
+++ b/sys/arch/i386/pci/rccosb4reg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: rccosb4reg.h,v 1.2 2005/10/27 20:01:13 mickey Exp $ */
+/* $OpenBSD: rccosb4reg.h,v 1.3 2005/11/23 09:24:57 mickey Exp $ */
/*
* Copyright (c) 2004,2005 Michael Shalayeff
@@ -41,6 +41,7 @@
*/
#define OSB4_PIAIR 0xc00
#define OSB4_PIRR 0xc01
+#define OSB4_PISP 3 /* special lines assumed to route thru ISA */
/*
* ELCR - EDGE/LEVEL CONTROL REGISTER