diff options
author | Michael Shalayeff <mickey@cvs.openbsd.org> | 2005-11-23 09:24:58 +0000 |
---|---|---|
committer | Michael Shalayeff <mickey@cvs.openbsd.org> | 2005-11-23 09:24:58 +0000 |
commit | b798e30277e3f181d9ea559fa8f352c70f5bbcb9 (patch) | |
tree | a6d8f3334d4f670787880b4709e724a4fc3c0b43 | |
parent | c56c28566cdd540950b965d8db45d6e49cc60434 (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.c | 52 | ||||
-rw-r--r-- | sys/arch/i386/include/i82093var.h | 3 | ||||
-rw-r--r-- | sys/arch/i386/include/mpbiosreg.h | 9 | ||||
-rw-r--r-- | sys/arch/i386/include/mpbiosvar.h | 3 | ||||
-rw-r--r-- | sys/arch/i386/isa/isa_machdep.c | 8 | ||||
-rw-r--r-- | sys/arch/i386/pci/pci_intr_fixup.c | 31 | ||||
-rw-r--r-- | sys/arch/i386/pci/pci_machdep.c | 28 | ||||
-rw-r--r-- | sys/arch/i386/pci/pcibiosvar.h | 4 | ||||
-rw-r--r-- | sys/arch/i386/pci/rccosb4.c | 14 | ||||
-rw-r--r-- | sys/arch/i386/pci/rccosb4reg.h | 3 |
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 |