summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2004-06-01 20:28:42 +0000
committerjhb <jhb@FreeBSD.org>2004-06-01 20:28:42 +0000
commit5b4075da93df7f93929a1838bd2151160a4acd4c (patch)
tree69a6da7aa848d436b5036df45fc3f3f46f6fcf2a
parentb2404db737dccebb0e745505c64a69e52027a18e (diff)
downloadFreeBSD-src-5b4075da93df7f93929a1838bd2151160a4acd4c.zip
FreeBSD-src-5b4075da93df7f93929a1838bd2151160a4acd4c.tar.gz
- Add a function ioapic_program_intpin() that completely programs an I/O
APIC interrupt pin based on the settings in the corresponding interrupt source structure. - Use ioapic_program_intpin() in place of manual frobbing of the intpin configuration in ioapic_program_destination() and ioapic_register(). - Use ioapic_program_intpin() to implement suspend/resume support for I/O APICs.
-rw-r--r--sys/i386/i386/io_apic.c160
1 files changed, 91 insertions, 69 deletions
diff --git a/sys/i386/i386/io_apic.c b/sys/i386/i386/io_apic.c
index b148ac6..c1e3b07 100644
--- a/sys/i386/i386/io_apic.c
+++ b/sys/i386/i386/io_apic.c
@@ -125,6 +125,7 @@ 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);
+static void ioapic_program_intpin(struct ioapic_intsrc *intpin);
static void ioapic_setup_mixed_mode(struct ioapic_intsrc *intpin);
static STAILQ_HEAD(,ioapic) ioapic_list = STAILQ_HEAD_INITIALIZER(ioapic_list);
@@ -134,7 +135,7 @@ struct pic ioapic_template = { ioapic_enable_source, ioapic_disable_source,
ioapic_suspend, ioapic_resume,
ioapic_config_intr };
-static int current_cluster, logical_clusters, next_ioapic_base;
+static int bsp_id, 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;
@@ -207,13 +208,88 @@ ioapic_eoi_source(struct intsrc *isrc)
}
/*
+ * Completely program an intpin based on the data in its interrupt source
+ * structure.
+ */
+static void
+ioapic_program_intpin(struct ioapic_intsrc *intpin)
+{
+ struct ioapic *io = (struct ioapic *)intpin->io_intsrc.is_pic;
+ uint32_t low, high, value;
+
+ /*
+ * For pins routed via mixed mode or disabled, just ensure that
+ * they are masked.
+ */
+ if (intpin->io_dest == DEST_EXTINT ||
+ intpin->io_vector == VECTOR_DISABLED) {
+ low = ioapic_read(io->io_addr,
+ IOAPIC_REDTBL_LO(intpin->io_intpin));
+ if ((low & IOART_INTMASK) == IOART_INTMCLR)
+ ioapic_write(io->io_addr,
+ IOAPIC_REDTBL_LO(intpin->io_intpin),
+ low | IOART_INTMSET);
+ return;
+ }
+
+ /* Set the destination. */
+ if (intpin->io_dest == DEST_NONE) {
+ low = IOART_DESTPHY;
+ high = bsp_id << APIC_ID_SHIFT;
+ } else {
+ low = IOART_DESTLOG;
+ high = (intpin->io_dest << APIC_ID_CLUSTER_SHIFT |
+ APIC_ID_CLUSTER_ID) << APIC_ID_SHIFT;
+ }
+
+ /* Program the rest of the low word. */
+ if (intpin->io_edgetrigger)
+ low |= IOART_TRGREDG;
+ else
+ low |= IOART_TRGRLVL;
+ if (intpin->io_activehi)
+ low |= IOART_INTAHI;
+ else
+ low |= IOART_INTALO;
+ if (intpin->io_masked)
+ low |= IOART_INTMSET;
+ switch (intpin->io_vector) {
+ case VECTOR_EXTINT:
+ KASSERT(intpin->io_edgetrigger,
+ ("EXTINT not edge triggered"));
+ low |= IOART_DELEXINT;
+ break;
+ case VECTOR_NMI:
+ KASSERT(intpin->io_edgetrigger,
+ ("NMI not edge triggered"));
+ low |= IOART_DELNMI;
+ break;
+ case VECTOR_SMI:
+ KASSERT(intpin->io_edgetrigger,
+ ("SMI not edge triggered"));
+ low |= IOART_DELSMI;
+ break;
+ default:
+ low |= IOART_DELLOPRI | apic_irq_to_idt(intpin->io_vector);
+ }
+
+ /* Write the values to the APIC. */
+ mtx_lock_spin(&icu_lock);
+ ioapic_write(io->io_addr, IOAPIC_REDTBL_LO(intpin->io_intpin), low);
+ value = ioapic_read(io->io_addr, IOAPIC_REDTBL_HI(intpin->io_intpin));
+ value &= ~IOART_DEST;
+ value |= high;
+ ioapic_write(io->io_addr, IOAPIC_REDTBL_HI(intpin->io_intpin), value);
+ mtx_unlock_spin(&icu_lock);
+}
+
+/*
* Program an individual intpin's logical destination.
*/
static void
ioapic_program_destination(struct ioapic_intsrc *intpin)
{
struct ioapic *io = (struct ioapic *)intpin->io_intsrc.is_pic;
- uint32_t value;
KASSERT(intpin->io_dest != DEST_NONE,
("intpin not assigned to a cluster"));
@@ -228,17 +304,7 @@ ioapic_program_destination(struct ioapic_intsrc *intpin)
printf("IRQ %u", intpin->io_vector);
printf(") to cluster %u\n", intpin->io_dest);
}
- mtx_lock_spin(&icu_lock);
- value = ioapic_read(io->io_addr, IOAPIC_REDTBL_LO(intpin->io_intpin));
- value &= ~IOART_DESTMOD;
- value |= IOART_DESTLOG;
- ioapic_write(io->io_addr, IOAPIC_REDTBL_LO(intpin->io_intpin), value);
- value = ioapic_read(io->io_addr, IOAPIC_REDTBL_HI(intpin->io_intpin));
- value &= ~IOART_DEST;
- value |= (intpin->io_dest << APIC_ID_CLUSTER_SHIFT |
- APIC_ID_CLUSTER_ID) << APIC_ID_SHIFT;
- ioapic_write(io->io_addr, IOAPIC_REDTBL_HI(intpin->io_intpin), value);
- mtx_unlock_spin(&icu_lock);
+ ioapic_program_intpin(intpin);
}
static void
@@ -338,7 +404,7 @@ static void
ioapic_resume(struct intsrc *isrc)
{
- TODO;
+ ioapic_program_intpin((struct ioapic_intsrc *)isrc);
}
/*
@@ -630,6 +696,7 @@ ioapic_register(void *cookie)
printf("ioapic%u <Version %u.%u> irqs %u-%u on motherboard\n",
io->io_id, flags >> 4, flags & 0xf, io->io_intbase,
io->io_intbase + io->io_numintr - 1);
+ bsp_id = PCPU_GET(apic_id);
for (i = 0, pin = io->io_pins; i < io->io_numintr; i++, pin++) {
/*
* Finish initializing the pins by programming the vectors
@@ -637,63 +704,18 @@ ioapic_register(void *cookie)
*/
if (pin->io_vector == VECTOR_DISABLED)
continue;
- flags = IOART_DESTPHY;
- if (pin->io_edgetrigger)
- flags |= IOART_TRGREDG;
- else
- flags |= IOART_TRGRLVL;
- if (pin->io_activehi)
- flags |= IOART_INTAHI;
- else
- flags |= IOART_INTALO;
- if (pin->io_masked)
- flags |= IOART_INTMSET;
- switch (pin->io_vector) {
- case VECTOR_EXTINT:
- KASSERT(pin->io_edgetrigger,
- ("EXTINT not edge triggered"));
- flags |= IOART_DELEXINT;
- break;
- case VECTOR_NMI:
- KASSERT(pin->io_edgetrigger,
- ("NMI not edge triggered"));
- flags |= IOART_DELNMI;
- break;
- case VECTOR_SMI:
- KASSERT(pin->io_edgetrigger,
- ("SMI not edge triggered"));
- flags |= IOART_DELSMI;
- break;
- default:
- flags |= IOART_DELLOPRI |
- apic_irq_to_idt(pin->io_vector);
- }
- mtx_lock_spin(&icu_lock);
- ioapic_write(apic, IOAPIC_REDTBL_LO(i), flags);
-
+ ioapic_program_intpin(pin);
+ if (pin->io_vector >= NUM_IO_INTS)
+ continue;
/*
- * Route interrupts to the BSP by default using physical
- * addressing. Vectored interrupts get readdressed using
- * logical IDs to CPU clusters when they are enabled.
+ * Route IRQ0 via the 8259A using mixed mode if mixed mode
+ * is available and turned on.
*/
- flags = ioapic_read(apic, IOAPIC_REDTBL_HI(i));
- flags &= ~IOART_DEST;
- flags |= PCPU_GET(apic_id) << APIC_ID_SHIFT;
- ioapic_write(apic, IOAPIC_REDTBL_HI(i), flags);
- mtx_unlock_spin(&icu_lock);
- if (pin->io_vector < NUM_IO_INTS) {
-
- /*
- * 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
- intr_register_source(&pin->io_intsrc);
- }
-
+ if (pin->io_vector == 0 && mixed_mode_active &&
+ mixed_mode_enabled)
+ ioapic_setup_mixed_mode(pin);
+ else
+ intr_register_source(&pin->io_intsrc);
}
}
OpenPOWER on IntegriCloud