1
0
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:
John Baldwin 2005-01-07 18:42:59 +00:00
parent 15575dc0aa
commit dd08fca3b6
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=139864

View File

@ -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);