summaryrefslogtreecommitdiff
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
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
-rw-r--r--sys/arch/i386/i386/mpbios.c52
-rw-r--r--sys/arch/i386/include/i82093var.h3
-rw-r--r--sys/arch/i386/include/mpbiosreg.h9
-rw-r--r--sys/arch/i386/include/mpbiosvar.h3
-rw-r--r--sys/arch/i386/isa/isa_machdep.c8
-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
10 files changed, 102 insertions, 53 deletions
diff --git a/sys/arch/i386/i386/mpbios.c b/sys/arch/i386/i386/mpbios.c
index 79112f60419..968bf6b12bd 100644
--- a/sys/arch/i386/i386/mpbios.c
+++ b/sys/arch/i386/i386/mpbios.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mpbios.c,v 1.5 2005/11/13 14:23:26 martin Exp $ */
+/* $OpenBSD: mpbios.c,v 1.6 2005/11/23 09:24:46 mickey Exp $ */
/* $NetBSD: mpbios.c,v 1.2 2002/10/01 12:56:57 fvdl Exp $ */
/*-
@@ -175,7 +175,7 @@ void mp_print_isa_intr (int);
void mpbios_cpu(const u_int8_t *, struct device *);
void mpbios_bus(const u_int8_t *, struct device *);
void mpbios_ioapic(const u_int8_t *, struct device *);
-void mpbios_int(const u_int8_t *, int, struct mp_intr_map *);
+void mpbios_int(const u_int8_t *, struct mp_intr_map *);
const void *mpbios_map(paddr_t, int, struct mp_map *);
static __inline void mpbios_unmap(struct mp_map *);
@@ -457,6 +457,7 @@ static struct mpbios_baseentry mp_conf[] =
struct mp_bus *mp_busses;
int mp_nbus;
struct mp_intr_map *mp_intrs;
+int mp_nintrs;
struct mp_intr_map *lapic_ints[2]; /* XXX */
int mp_isa_bus = -1; /* XXX */
@@ -506,7 +507,7 @@ mpbios_scan(self)
const u_int8_t *position, *end;
int count;
int type;
- int intr_cnt, cur_intr;
+ int intr_cnt;
paddr_t lapic_base;
printf("%s: Intel MP Specification ", self->dv_xname);
@@ -580,7 +581,7 @@ mpbios_scan(self)
position += sizeof(*mp_cth);
count = mp_cth->entry_count;
- intr_cnt = 0;
+ intr_cnt = 15; /* presume all isa irqs being missing */
while ((count--) && (position < end)) {
type = *position;
@@ -626,7 +627,7 @@ mpbios_scan(self)
/* re-walk the table, recording info of interest */
position = (const u_int8_t *)mp_cth + sizeof(*mp_cth);
count = mp_cth->entry_count;
- cur_intr = 0;
+ mp_nintrs = 0;
while ((count--) && (position < end)) {
switch (type = *(u_char *)position) {
@@ -641,9 +642,7 @@ mpbios_scan(self)
break;
case MPS_MCT_IOINT:
case MPS_MCT_LINT:
- mpbios_int(position, type,
- &mp_intrs[cur_intr]);
- cur_intr++;
+ mpbios_int(position, &mp_intrs[mp_nintrs++]);
break;
default:
printf("%s: unknown entry type %x "
@@ -669,6 +668,38 @@ mpbios_scan(self)
}
}
+int
+mpbios_invent(int irq, int type, int bus)
+{
+ struct mp_intr_map *mip;
+ struct mpbios_int e;
+
+ e.type = MPS_MCT_IOINT;
+ e.int_type = MPS_INTTYPE_INT;
+ switch (type) {
+ case IST_EDGE:
+ e.int_flags = MPS_INT(MPS_INTPO_ACTHI, MPS_INTTR_EDGE);
+ break;
+
+ case IST_LEVEL:
+ e.int_flags = MPS_INT(MPS_INTPO_ACTLO, MPS_INTTR_LEVEL);
+ break;
+
+ case IST_NONE:
+ case IST_PULSE:
+ e.int_flags = MPS_INT(MPS_INTPO_DEF, MPS_INTTR_DEF);
+ break;
+ }
+ e.src_bus_id = bus;
+ e.src_bus_irq = irq;
+ e.dst_apic_id = mp_busses[bus].mb_intrs->ioapic->sc_apicid;
+ e.dst_apic_int = irq;
+
+ mpbios_int((const u_int8_t *)&e, (mip = &mp_intrs[mp_nintrs++]));
+
+ return (mip->ioapic_ih | irq);
+}
+
void
mpbios_cpu(ent, self)
const u_int8_t *ent;
@@ -1005,9 +1036,8 @@ static const char flagtype_fmt[] = "\177\020"
"f\2\2trig\0" "=\1Edge\0" "=\3Level\0";
void
-mpbios_int(ent, enttype, mpi)
+mpbios_int(ent, mpi)
const u_int8_t *ent;
- int enttype;
struct mp_intr_map *mpi;
{
const struct mpbios_int *entry = (const struct mpbios_int *)ent;
@@ -1059,7 +1089,7 @@ mpbios_int(ent, enttype, mpi)
(*mpb->mb_intr_cfg)(&rw_entry, &mpi->redir);
- if (enttype == MPS_MCT_IOINT) {
+ if (entry->type == MPS_MCT_IOINT) {
sc = ioapic_find(id);
if (sc == NULL) {
printf("mpbios: can't find ioapic %d\n", id);
diff --git a/sys/arch/i386/include/i82093var.h b/sys/arch/i386/include/i82093var.h
index 56a7553be43..58ead2893dc 100644
--- a/sys/arch/i386/include/i82093var.h
+++ b/sys/arch/i386/include/i82093var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: i82093var.h,v 1.3 2004/06/23 17:14:31 niklas Exp $ */
+/* $OpenBSD: i82093var.h,v 1.4 2005/11/23 09:24:52 mickey Exp $ */
/* $NetBSD: i82093var.h,v 1.1 2003/02/26 21:26:10 fvdl Exp $ */
/*-
@@ -81,6 +81,7 @@ struct ioapic_softc {
#define APIC_INT_APIC_SHIFT 16
#define APIC_INT_PIN_MASK 0x0000ff00
#define APIC_INT_PIN_SHIFT 8
+#define APIC_INT_LINE_MASK 0x000000ff
#define APIC_IRQ_APIC(x) ((x & APIC_INT_APIC_MASK) >> APIC_INT_APIC_SHIFT)
#define APIC_IRQ_PIN(x) ((x & APIC_INT_PIN_MASK) >> APIC_INT_PIN_SHIFT)
diff --git a/sys/arch/i386/include/mpbiosreg.h b/sys/arch/i386/include/mpbiosreg.h
index d42aed04cdc..b9346c03cf0 100644
--- a/sys/arch/i386/include/mpbiosreg.h
+++ b/sys/arch/i386/include/mpbiosreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: mpbiosreg.h,v 1.2 2004/06/13 21:49:16 niklas Exp $ */
+/* $OpenBSD: mpbiosreg.h,v 1.3 2005/11/23 09:24:52 mickey Exp $ */
/* $NetBSD: mpbiosreg.h,v 1.1.2.3 2000/02/29 13:17:51 sommerfeld Exp $ */
/*-
@@ -70,11 +70,18 @@
#define MPS_INTPO_DEF 0
#define MPS_INTPO_ACTHI 1
#define MPS_INTPO_ACTLO 3
+#define MPS_INTPO_SHIFT 0
+#define MPS_INTPO_MASK 3
#define MPS_INTTR_DEF 0
#define MPS_INTTR_EDGE 1
#define MPS_INTTR_LEVEL 3
+#define MPS_INTTR_SHIFT 2
+#define MPS_INTTR_MASK 3
+#define MPS_INT(p,t) \
+ ((((p) & MPS_INTPO_MASK) << MPS_INTPO_SHIFT) | \
+ (((t) & MPS_INTTR_MASK) << MPS_INTTR_SHIFT))
/* MP Floating Pointer Structure */
struct mpbios_fps {
diff --git a/sys/arch/i386/include/mpbiosvar.h b/sys/arch/i386/include/mpbiosvar.h
index b617041b4d9..b281c3e381f 100644
--- a/sys/arch/i386/include/mpbiosvar.h
+++ b/sys/arch/i386/include/mpbiosvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: mpbiosvar.h,v 1.2 2004/06/13 21:49:16 niklas Exp $ */
+/* $OpenBSD: mpbiosvar.h,v 1.3 2005/11/23 09:24:52 mickey Exp $ */
/* $NetBSD: mpbiosvar.h,v 1.1.2.3 2000/02/29 13:17:20 sommerfeld Exp $ */
/*-
@@ -81,6 +81,7 @@ extern int mp_eisa_bus;
void mpbios_scan(struct device *);
int mpbios_probe(struct device *);
+int mpbios_invent(int, int, int);
#endif
#endif
diff --git a/sys/arch/i386/isa/isa_machdep.c b/sys/arch/i386/isa/isa_machdep.c
index 5581d4848d5..6598f51e810 100644
--- a/sys/arch/i386/isa/isa_machdep.c
+++ b/sys/arch/i386/isa/isa_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: isa_machdep.c,v 1.51 2004/11/29 20:15:40 pat Exp $ */
+/* $OpenBSD: isa_machdep.c,v 1.52 2005/11/23 09:24:54 mickey Exp $ */
/* $NetBSD: isa_machdep.c,v 1.22 1997/06/12 23:57:32 thorpej Exp $ */
#define ISA_DMA_STATS
@@ -558,9 +558,11 @@ isa_intr_establish(ic, irq, type, level, ih_fun, ih_arg, ih_what)
}
}
}
+
+ /* no MP mapping found -- invent! */
if (mip == NULL)
- printf("isa_intr_establish: no MP mapping found\n");
- else
+ airq = mpbios_invent(irq, type, mp_isa_bus);
+
return (apic_intr_establish(airq, type, level, ih_fun,
ih_arg, ih_what));
}
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