aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorJohn Baldwin <jhb@FreeBSD.org>2005-01-07 18:42:59 +0000
committerJohn Baldwin <jhb@FreeBSD.org>2005-01-07 18:42:59 +0000
commitdd08fca3b66f24a32c0ea25f8c32999df6ef484a (patch)
treec36d6b9875afb1933714e1b686d7a7ae6d8ff7a7 /sys
parent15575dc0aac2ab83f0fb2709546f79440db4dfb8 (diff)
downloadsrc-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.c89
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);