vBulletin Search Engine Optimization
| |||||||
| Register | FAQ | Members List | Calendar | Search | Today's Posts | Mark Forums Read |
| ||||
| re here we start to apply some magic to some brokem mpbios implementations. this diff in particular solves two pravlems with mpbios interrupt tables. missing pci pin mappings are thus routed thru "fixed" isa pins (via pci intr router). for rcc osb chipsets we can also assume isa routing for some specially wired interrupts irregardless of pci mappings. functionally equal diff had been in snapshots for past two weeks but those who have not tried their SMP machines please do now. 10x cu -- paranoic mickey (my employers have changed but, the name has remained) Index: i386/mpbios.c ================================================== ================= RCS file: /cvs/src/sys/arch/i386/i386/mpbios.c,v retrieving revision 1.5 diff -u -r1.5 mpbios.c --- i386/mpbios.c 13 Nov 2005 14:23:26 -0000 1.5 +++ i386/mpbios.c 22 Nov 2005 09:54:29 -0000 @@ -175,7 +175,7 @@ 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 @@ 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 @@ 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 @@ 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 @@ /* 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 @@ 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 @@ } } +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 @@ "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 @@ (*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); Index: include/i82093var.h ================================================== ================= RCS file: /cvs/src/sys/arch/i386/include/i82093var.h,v retrieving revision 1.3 diff -u -r1.3 i82093var.h --- include/i82093var.h 23 Jun 2004 17:14:31 -0000 1.3 +++ include/i82093var.h 22 Nov 2005 09:44:14 -0000 @@ -81,6 +81,7 @@ #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) Index: include/mpbiosreg.h ================================================== ================= RCS file: /cvs/src/sys/arch/i386/include/mpbiosreg.h,v retrieving revision 1.2 diff -u -r1.2 mpbiosreg.h --- include/mpbiosreg.h 13 Jun 2004 21:49:16 -0000 1.2 +++ include/mpbiosreg.h 22 Nov 2005 09:56:27 -0000 @@ -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 { Index: include/mpbiosvar.h ================================================== ================= RCS file: /cvs/src/sys/arch/i386/include/mpbiosvar.h,v retrieving revision 1.2 diff -u -r1.2 mpbiosvar.h --- include/mpbiosvar.h 13 Jun 2004 21:49:16 -0000 1.2 +++ include/mpbiosvar.h 22 Nov 2005 09:44:14 -0000 @@ -81,6 +81,7 @@ void mpbios_scan(struct device *); int mpbios_probe(struct device *); +int mpbios_invent(int, int, int); #endif #endif Index: isa/isa_machdep.c ================================================== ================= RCS file: /cvs/src/sys/arch/i386/isa/isa_machdep.c,v retrieving revision 1.51 diff -u -r1.51 isa_machdep.c --- isa/isa_machdep.c 29 Nov 2004 20:15:40 -0000 1.51 +++ isa/isa_machdep.c 22 Nov 2005 09:44:14 -0000 @@ -558,9 +558,11 @@ } } } + + /* 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)); } Index: pci/pci_intr_fixup.c ================================================== ================= RCS file: /cvs/src/sys/arch/i386/pci/pci_intr_fixup.c,v retrieving revision 1.48 diff -u -r1.48 pci_intr_fixup.c --- pci/pci_intr_fixup.c 21 Nov 2005 22:28:13 -0000 1.48 +++ pci/pci_intr_fixup.c 22 Nov 2005 09:44:14 -0000 @@ -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 @@ { 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 @@ * 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 @@ 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 @@ /* * 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 @@ } 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 @@ } 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) { Index: pci/pci_machdep.c ================================================== ================= RCS file: /cvs/src/sys/arch/i386/pci/pci_machdep.c,v retrieving revision 1.29 diff -u -r1.29 pci_machdep.c --- pci/pci_machdep.c 28 Jul 2005 17:22:28 -0000 1.29 +++ pci/pci_machdep.c 22 Nov 2005 10:50:30 -0000 @@ -107,8 +107,8 @@ #include "ioapic.h" -#if NIOAPIC > 0 #include <machine/i82093var.h> +#if NIOAPIC > 0 #include <machine/mpbiosvar.h> #endif @@ -510,7 +510,7 @@ 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 @@ #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_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 @@ 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); Index: pci/pcibiosvar.h ================================================== ================= RCS file: /cvs/src/sys/arch/i386/pci/pcibiosvar.h,v retrieving revision 1.14 diff -u -r1.14 pcibiosvar.h --- pci/pcibiosvar.h 26 Sep 2004 20:17:42 -0000 1.14 +++ pci/pcibiosvar.h 22 Nov 2005 09:44:15 -0000 @@ -146,6 +146,8 @@ #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); Index: pci/rccosb4.c ================================================== ================= RCS file: /cvs/src/sys/arch/i386/pci/rccosb4.c,v retrieving revision 1.3 diff -u -r1.3 rccosb4.c --- pci/rccosb4.c 10 Nov 2005 15:14:09 -0000 1.3 +++ pci/rccosb4.c 22 Nov 2005 10:58:40 -0000 @@ -98,6 +98,8 @@ { if (OSB4_LEGAL_LINK(link - 1)) { *clinkp = link; + if (link <= OSB4_PISP) + *clinkp |= PCI_INT_VIA_ISA; return (0); } @@ -108,11 +110,12 @@ 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 @@ 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); |