diff --git a/sys/i386/acpica/madt.c b/sys/i386/acpica/madt.c index 81dd05881298..3bccc4a9a891 100644 --- a/sys/i386/acpica/madt.c +++ b/sys/i386/acpica/madt.c @@ -368,6 +368,8 @@ madt_setup_io(void) } /* First, we run through adding I/O APIC's. */ + if (madt->PCATCompat) + ioapic_enable_mixed_mode(); madt_walk_table(madt_parse_apics, NULL); /* Second, we run through the table tweaking interrupt sources. */ diff --git a/sys/i386/i386/io_apic.c b/sys/i386/i386/io_apic.c index 272ebaea0956..daa33728dc4d 100644 --- a/sys/i386/i386/io_apic.c +++ b/sys/i386/i386/io_apic.c @@ -50,10 +50,6 @@ __FBSDID("$FreeBSD$"); #include #include -#if defined(DEV_ISA) && !defined(NO_MIXED_MODE) -#define MIXED_MODE -#endif - #define IOAPIC_ISA_INTS 16 #define IOAPIC_MEM_REGION 32 #define IOAPIC_REDTBL_LO(i) (IOAPIC_REDTBL + (i) * 2) @@ -116,8 +112,6 @@ struct ioapic { struct ioapic_intsrc io_pins[0]; }; -static STAILQ_HEAD(,ioapic) ioapic_list = STAILQ_HEAD_INITIALIZER(ioapic_list); -static u_int next_id, program_logical_dest; static u_int ioapic_read(volatile ioapic_t *apic, int reg); static void ioapic_write(volatile ioapic_t *apic, int reg, u_int val); @@ -132,17 +126,23 @@ static int ioapic_config_intr(struct intsrc *isrc, enum intr_trigger trig, static void ioapic_suspend(struct intsrc *isrc); static void ioapic_resume(struct intsrc *isrc); static void ioapic_program_destination(struct ioapic_intsrc *intpin); -#ifdef MIXED_MODE static void ioapic_setup_mixed_mode(struct ioapic_intsrc *intpin); -#endif +static STAILQ_HEAD(,ioapic) ioapic_list = STAILQ_HEAD_INITIALIZER(ioapic_list); struct pic ioapic_template = { ioapic_enable_source, ioapic_disable_source, ioapic_eoi_source, ioapic_enable_intr, ioapic_vector, ioapic_source_pending, ioapic_suspend, ioapic_resume, ioapic_config_intr }; -static int next_ioapic_base, logical_clusters, current_cluster; +static int current_cluster, logical_clusters, next_ioapic_base; +static u_int mixed_mode_enabled, next_id, program_logical_dest; +#ifdef NO_MIXED_MODE +static int mixed_mode_active = 0; +#else +static int mixed_mode_active = 1; +#endif +TUNABLE_INT("hw.apic.mixed_mode", &mixed_mode_active); static u_int ioapic_read(volatile ioapic_t *apic, int reg) @@ -342,6 +342,17 @@ ioapic_resume(struct intsrc *isrc) TODO; } +/* + * APIC enumerators call this function to indicate that the 8259A AT PICs + * are available and that mixed mode can be used. + */ +void +ioapic_enable_mixed_mode(void) +{ + + mixed_mode_enabled = 1; +} + /* * Allocate and return a logical cluster ID. Note that the first time * this is called, it returns cluster 0. ioapic_enable_intr() treats @@ -417,14 +428,17 @@ ioapic_create(uintptr_t addr, int32_t apic_id, int intbase) * Assume that pin 0 on the first IO APIC is an ExtINT pin by * default. Assume that intpins 1-15 are ISA interrupts and * use suitable defaults for those. Assume that all other - * intpins are PCI interrupts. Enable the ExtINT pin by - * default but mask all other pins. + * intpins are PCI interrupts. Enable the ExtINT pin if + * mixed mode is available and active but mask all other pins. */ if (intpin->io_vector == 0) { intpin->io_activehi = 1; intpin->io_edgetrigger = 1; intpin->io_vector = VECTOR_EXTINT; - intpin->io_masked = 0; + if (mixed_mode_enabled && mixed_mode_active) + intpin->io_masked = 0; + else + intpin->io_masked = 1; } else if (intpin->io_vector < IOAPIC_ISA_INTS) { intpin->io_activehi = 1; intpin->io_edgetrigger = 1; @@ -669,12 +683,15 @@ ioapic_register(void *cookie) ioapic_write(apic, IOAPIC_REDTBL_HI(i), flags); mtx_unlock_spin(&icu_lock); if (pin->io_vector < NUM_IO_INTS) { -#ifdef MIXED_MODE - /* Route IRQ0 via the 8259A using mixed mode. */ - if (pin->io_vector == 0) + + /* + * Route IRQ0 via the 8259A using mixed mode if + * mixed mode is available and turned on. + */ + if (pin->io_vector == 0 && mixed_mode_active && + mixed_mode_enabled) ioapic_setup_mixed_mode(pin); else -#endif intr_register_source(&pin->io_intsrc); } @@ -701,7 +718,6 @@ ioapic_set_logical_destinations(void *arg __unused) SYSINIT(ioapic_destinations, SI_SUB_SMP, SI_ORDER_SECOND, ioapic_set_logical_destinations, NULL) -#ifdef MIXED_MODE /* * Support for mixed-mode interrupt sources. These sources route an ISA * IRQ through the 8259A's via the ExtINT on pin 0 of the I/O APIC that @@ -730,5 +746,3 @@ ioapic_setup_mixed_mode(struct ioapic_intsrc *intpin) ioapic_assign_cluster(extint); #endif } - -#endif /* MIXED_MODE */ diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c index f8a740f1e90d..880f90573f52 100644 --- a/sys/i386/i386/machdep.c +++ b/sys/i386/i386/machdep.c @@ -2778,6 +2778,11 @@ ioapic_disable_pin(void *cookie, u_int pin) return (ENXIO); } +void +ioapic_enable_mixed_mode(void) +{ +} + int ioapic_get_vector(void *cookie, u_int pin) { diff --git a/sys/i386/i386/mptable.c b/sys/i386/i386/mptable.c index 2ed0b4ac5880..37684d77adea 100644 --- a/sys/i386/i386/mptable.c +++ b/sys/i386/i386/mptable.c @@ -342,6 +342,7 @@ mptable_setup_io(void) busses[i].bus_type = NOBUS; /* Second, we run through adding I/O APIC's and busses. */ + ioapic_enable_mixed_mode(); mptable_parse_apics_and_busses(); /* Third, we run through the table tweaking interrupt sources. */ diff --git a/sys/i386/include/apicvar.h b/sys/i386/include/apicvar.h index f387969082ee..7bdcc7f75803 100644 --- a/sys/i386/include/apicvar.h +++ b/sys/i386/include/apicvar.h @@ -136,6 +136,7 @@ u_int apic_idt_to_irq(u_int vector); void apic_register_enumerator(struct apic_enumerator *enumerator); void *ioapic_create(uintptr_t addr, int32_t id, int intbase); int ioapic_disable_pin(void *cookie, u_int pin); +void ioapic_enable_mixed_mode(void); int ioapic_get_vector(void *cookie, u_int pin); int ioapic_next_logical_cluster(void); void ioapic_register(void *cookie);