mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-17 10:26:15 +00:00
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
This commit is contained in:
parent
15575dc0aa
commit
dd08fca3b6
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=139864
@ -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(void);
|
||||||
static void mptable_parse_apics_and_busses_handler(u_char *entry,
|
static void mptable_parse_apics_and_busses_handler(u_char *entry,
|
||||||
void *arg);
|
void *arg);
|
||||||
|
static void mptable_parse_default_config_ints(void);
|
||||||
static void mptable_parse_ints(void);
|
static void mptable_parse_ints(void);
|
||||||
static void mptable_parse_ints_handler(u_char *entry, void *arg);
|
static void mptable_parse_ints_handler(u_char *entry, void *arg);
|
||||||
static void mptable_parse_io_int(int_entry_ptr intr);
|
static void mptable_parse_io_int(int_entry_ptr intr);
|
||||||
@ -251,9 +252,19 @@ mptable_probe(void)
|
|||||||
mpfps = (mpfps_t)(KERNBASE + x);
|
mpfps = (mpfps_t)(KERNBASE + x);
|
||||||
|
|
||||||
/* Map in the configuration table if it exists. */
|
/* 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;
|
mpct = NULL;
|
||||||
else {
|
} else {
|
||||||
if ((uintptr_t)mpfps->pap >= 1024 * 1024) {
|
if ((uintptr_t)mpfps->pap >= 1024 * 1024) {
|
||||||
printf("%s: Unable to map MP Configuration Table\n",
|
printf("%s: Unable to map MP Configuration Table\n",
|
||||||
__func__);
|
__func__);
|
||||||
@ -315,7 +326,7 @@ mptable_setup_local(void)
|
|||||||
printf("MPTable: <");
|
printf("MPTable: <");
|
||||||
if (mpfps->config_type != 0) {
|
if (mpfps->config_type != 0) {
|
||||||
lapic_init(DEFAULT_APIC_BASE);
|
lapic_init(DEFAULT_APIC_BASE);
|
||||||
printf("Preset Config %d", mpfps->config_type);
|
printf("Default Configuration %d", mpfps->config_type);
|
||||||
} else {
|
} else {
|
||||||
lapic_init((uintptr_t)mpct->apic_address);
|
lapic_init((uintptr_t)mpct->apic_address);
|
||||||
printf("%.*s %.*s", (int)sizeof(mpct->oem_id), mpct->oem_id,
|
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? */
|
/* Is this a pre-defined config? */
|
||||||
if (mpfps->config_type != 0) {
|
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_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) {
|
if (mptable_nbusses > 1) {
|
||||||
busses[1].bus_id = 1;
|
busses[1].bus_id = 1;
|
||||||
busses[1].bus_type =
|
busses[1].bus_type =
|
||||||
default_data[mpfps->config_type][4];
|
default_data[mpfps->config_type - 1][4];
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
mptable_walk_table(mptable_parse_apics_and_busses_handler,
|
mptable_walk_table(mptable_parse_apics_and_busses_handler,
|
||||||
@ -760,7 +771,58 @@ mptable_parse_ints_handler(u_char *entry, void *arg __unused)
|
|||||||
break;
|
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
|
* 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);
|
lapic_set_lvt_mode(APIC_ID_ALL, LVT_LINT1, APIC_LVT_DM_NMI);
|
||||||
|
|
||||||
/* Configure I/O APIC pins. */
|
/* Configure I/O APIC pins. */
|
||||||
if (mpfps->config_type != 7)
|
mptable_parse_default_config_ints();
|
||||||
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);
|
|
||||||
} else
|
} else
|
||||||
mptable_walk_table(mptable_parse_ints_handler, NULL);
|
mptable_walk_table(mptable_parse_ints_handler, NULL);
|
||||||
}
|
}
|
||||||
@ -894,7 +947,7 @@ mptable_pci_probe_table(int bus)
|
|||||||
|
|
||||||
if (bus < 0)
|
if (bus < 0)
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
if (pci0 == -1 || pci0 + bus > mptable_maxbusid)
|
if (mpct == NULL || pci0 == -1 || pci0 + bus > mptable_maxbusid)
|
||||||
return (ENXIO);
|
return (ENXIO);
|
||||||
if (busses[pci0 + bus].bus_type != PCI)
|
if (busses[pci0 + bus].bus_type != PCI)
|
||||||
return (ENXIO);
|
return (ENXIO);
|
||||||
|
Loading…
Reference in New Issue
Block a user