summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2004-05-10 18:49:58 +0000
committerjhb <jhb@FreeBSD.org>2004-05-10 18:49:58 +0000
commit3564a3448df2230819f217420bb3856b51fd64c8 (patch)
tree784f1513fbbb25175f0b3292accf66533f5c0077
parent15cc971bcf0f8e77efc49cd1250fc4a311897e47 (diff)
downloadFreeBSD-src-3564a3448df2230819f217420bb3856b51fd64c8.zip
FreeBSD-src-3564a3448df2230819f217420bb3856b51fd64c8.tar.gz
Rework the APIC mixed mode support a bit:
- Require the APIC enumerators to explicitly enable mixed mode by calling ioapic_enable_mixed_mode(). Calling this function tells the apic driver that the PC-AT 8259A PICs are present and routable through the first I/O APIC via an ExtINT pin. The mptable enumerator always calls this function for now. The MADT enumerator only enables mixed mode if the PC-AT compatability flag is set in the MADT header. - Allow mixed mode to be enabled or disabled via a 'hw.apic.mixed_mode' tunable. By default this tunable is set to 1 (true). The kernel option NO_MIXED_MODE changes the default to 0 to preserve existing behavior, but adding 'hw.apic.mixed_mode=0' to loader.conf achieves the same effect. - Only use mixed mode to route IRQ 0 if it is both enabled by the APIC enumerator and activated by the loader tunable. Note that both conditions must be true, so if the APIC enumerator does not enable mixed mode, then you can't set the tunable to try to override the enumerator.
-rw-r--r--sys/i386/acpica/madt.c2
-rw-r--r--sys/i386/i386/io_apic.c52
-rw-r--r--sys/i386/i386/machdep.c5
-rw-r--r--sys/i386/i386/mptable.c1
-rw-r--r--sys/i386/include/apicvar.h1
5 files changed, 42 insertions, 19 deletions
diff --git a/sys/i386/acpica/madt.c b/sys/i386/acpica/madt.c
index 81dd058..3bccc4a 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 272ebae..daa3372 100644
--- a/sys/i386/i386/io_apic.c
+++ b/sys/i386/i386/io_apic.c
@@ -50,10 +50,6 @@ __FBSDID("$FreeBSD$");
#include <machine/apicvar.h>
#include <machine/segments.h>
-#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)
@@ -343,6 +343,17 @@ ioapic_resume(struct intsrc *isrc)
}
/*
+ * 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
* the two cases of logical_clusters == 0 and logical_clusters == 1 the
@@ -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 f8a740f..880f905 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 2ed0b4a..37684d7 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 f387969..7bdcc7f 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);
OpenPOWER on IntegriCloud