diff --git a/sys/i386/i386/mptable.c b/sys/i386/i386/mptable.c index fe8bf4538a2..c327c07abe0 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);