diff options
author | John Baldwin <jhb@FreeBSD.org> | 2005-01-07 18:42:59 +0000 |
---|---|---|
committer | John Baldwin <jhb@FreeBSD.org> | 2005-01-07 18:42:59 +0000 |
commit | dd08fca3b66f24a32c0ea25f8c32999df6ef484a (patch) | |
tree | c36d6b9875afb1933714e1b686d7a7ae6d8ff7a7 /sys | |
parent | 15575dc0aac2ab83f0fb2709546f79440db4dfb8 (diff) | |
download | src-dd08fca3b66f24a32c0ea25f8c32999df6ef484a.tar.gz src-dd08fca3b66f24a32c0ea25f8c32999df6ef484a.zip |
Fix support for machines with default MP Table configurations:
- Fix the MP Table pci bridge drivers to not probe the configuration table
unless we actually have one. Machines using a default configuration do
not have such a table.
- Only allow default configuration types of 5 (ISA + PCI) and 6 (EISA +
PCI) as the others are not likely to work. Types 1 through 4 use an
external APIC (probably with 80486 processors) which we certainly do not
support, and type 7 uses an MCA bus which has not been tested with the
new MP Table code.
- Correct the fact that the single I/O APIC in a default configuration has
an ID of 2, not 0.
- Fix off by one errors in setting the bus types from the default_data[]
arrays for default configurations.
- Explicitly configure each of the 16 interrupt pins on the sole I/O APIC
when using a default configuration. This is especially helpful for type
6 (EISA + PCI) since the EISA interrupts need to have their polarity
programmed based on the values in the ELCR.
Much thanks to the submitter and tester who endured several rounds of
testing to get this fixed.
MFC after: 1 week
Tested by: Georg Schwarz georg dot schwarz at freenet dot de
Notes
Notes:
svn path=/head/; revision=139864
Diffstat (limited to 'sys')
-rw-r--r-- | sys/i386/i386/mptable.c | 89 |
1 files changed, 71 insertions, 18 deletions
diff --git a/sys/i386/i386/mptable.c b/sys/i386/i386/mptable.c index fe8bf4538a24..c327c07abe06 100644 --- a/sys/i386/i386/mptable.c +++ b/sys/i386/i386/mptable.c @@ -163,6 +163,7 @@ static void mptable_hyperthread_fixup(u_int id_mask); static void mptable_parse_apics_and_busses(void); static void mptable_parse_apics_and_busses_handler(u_char *entry, void *arg); +static void mptable_parse_default_config_ints(void); static void mptable_parse_ints(void); static void mptable_parse_ints_handler(u_char *entry, void *arg); static void mptable_parse_io_int(int_entry_ptr intr); @@ -251,9 +252,19 @@ found: mpfps = (mpfps_t)(KERNBASE + x); /* Map in the configuration table if it exists. */ - if (mpfps->config_type != 0) + if (mpfps->config_type != 0) { + if (bootverbose) + printf( + "MP Table version 1.%d found using Default Configuration %d\n", + mpfps->spec_rev, mpfps->config_type); + if (mpfps->config_type != 5 && mpfps->config_type != 6) { + printf( + "MP Table Default Configuration %d is unsupported\n", + mpfps->config_type); + return (ENXIO); + } mpct = NULL; - else { + } else { if ((uintptr_t)mpfps->pap >= 1024 * 1024) { printf("%s: Unable to map MP Configuration Table\n", __func__); @@ -315,7 +326,7 @@ mptable_setup_local(void) printf("MPTable: <"); if (mpfps->config_type != 0) { lapic_init(DEFAULT_APIC_BASE); - printf("Preset Config %d", mpfps->config_type); + printf("Default Configuration %d", mpfps->config_type); } else { lapic_init((uintptr_t)mpct->apic_address); printf("%.*s %.*s", (int)sizeof(mpct->oem_id), mpct->oem_id, @@ -526,13 +537,13 @@ mptable_parse_apics_and_busses(void) /* Is this a pre-defined config? */ if (mpfps->config_type != 0) { - ioapics[0] = ioapic_create(DEFAULT_IO_APIC_BASE, 2, 0); + ioapics[2] = ioapic_create(DEFAULT_IO_APIC_BASE, 2, 0); busses[0].bus_id = 0; - busses[0].bus_type = default_data[mpfps->config_type][2]; + busses[0].bus_type = default_data[mpfps->config_type - 1][2]; if (mptable_nbusses > 1) { busses[1].bus_id = 1; busses[1].bus_type = - default_data[mpfps->config_type][4]; + default_data[mpfps->config_type - 1][4]; } } else mptable_walk_table(mptable_parse_apics_and_busses_handler, @@ -760,7 +771,58 @@ mptable_parse_ints_handler(u_char *entry, void *arg __unused) break; } } - + +/* + * Configure interrupt pins for a default configuration. For details see + * Table 5-2 in Section 5 of the MP Table specification. + */ +static void +mptable_parse_default_config_ints(void) +{ + struct INTENTRY entry; + int pin; + + /* + * All default configs route IRQs from bus 0 to the first 16 pins + * of the first I/O APIC with an APIC ID of 2. + */ + entry.type = MPCT_ENTRY_INT; + entry.int_flags = INTENTRY_FLAGS_POLARITY_CONFORM | + INTENTRY_FLAGS_TRIGGER_CONFORM; + entry.src_bus_id = 0; + entry.dst_apic_id = 2; + + /* Run through all 16 pins. */ + for (pin = 0; pin < 16; pin++) { + entry.dst_apic_int = pin; + switch (pin) { + case 0: + /* Pin 0 is an ExtINT pin. */ + entry.int_type = INTENTRY_TYPE_EXTINT; + break; + case 2: + /* IRQ 0 is routed to pin 2. */ + entry.int_type = INTENTRY_TYPE_INT; + entry.src_bus_irq = 0; + break; + default: + /* All other pins are identity mapped. */ + entry.int_type = INTENTRY_TYPE_INT; + entry.src_bus_irq = pin; + break; + } + mptable_parse_io_int(&entry); + } + + /* Certain configs disable certain pins. */ + if (mpfps->config_type == 7) + ioapic_disable_pin(ioapics[2], 0); + if (mpfps->config_type == 2) { + ioapic_disable_pin(ioapics[2], 2); + ioapic_disable_pin(ioapics[2], 13); + } +} + /* * Configure the interrupt pins */ @@ -775,16 +837,7 @@ mptable_parse_ints(void) lapic_set_lvt_mode(APIC_ID_ALL, LVT_LINT1, APIC_LVT_DM_NMI); /* Configure I/O APIC pins. */ - if (mpfps->config_type != 7) - ioapic_set_extint(ioapics[0], 0); - else - ioapic_disable_pin(ioapics[0], 0); - if (mpfps->config_type != 2) - ioapic_remap_vector(ioapics[0], 2, 0); - else - ioapic_disable_pin(ioapics[0], 2); - if (mpfps->config_type == 2) - ioapic_disable_pin(ioapics[0], 13); + mptable_parse_default_config_ints(); } else mptable_walk_table(mptable_parse_ints_handler, NULL); } @@ -894,7 +947,7 @@ mptable_pci_probe_table(int bus) if (bus < 0) return (EINVAL); - if (pci0 == -1 || pci0 + bus > mptable_maxbusid) + if (mpct == NULL || pci0 == -1 || pci0 + bus > mptable_maxbusid) return (ENXIO); if (busses[pci0 + bus].bus_type != PCI) return (ENXIO); |