X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/blobdiff_plain/3a69c11390d99471e9b961a15a8958752350e9a4..b551073687d461dc8b9e6d3a34dd285de40a26a6:/sys/platform/pc64/apic/ioapic.c diff --git a/sys/platform/pc64/apic/ioapic.c b/sys/platform/pc64/apic/ioapic.c index 63e084d18d..2ff9d581c5 100644 --- a/sys/platform/pc64/apic/ioapic.c +++ b/sys/platform/pc64/apic/ioapic.c @@ -30,21 +30,15 @@ #include #include #include -#include -#include -#include +#include + #include +#include +#include #include #include #include -#include -#include -#include -#include - -#include - -#include "apicvar.h" +#include #define IOAPIC_COUNT_MAX 16 #define IOAPIC_ID_MASK (IOAPIC_COUNT_MAX - 1) @@ -68,9 +62,10 @@ struct ioapic_intsrc { struct ioapic_conf { struct ioapic_info_list ioc_list; - struct ioapic_intsrc ioc_intsrc[16]; /* XXX magic number */ + struct ioapic_intsrc ioc_intsrc[ISA_IRQ_CNT]; }; +static int ioapic_config(void); static void ioapic_setup(const struct ioapic_info *); static int ioapic_alloc_apic_id(int); static void ioapic_set_apic_id(const struct ioapic_info *); @@ -78,7 +73,7 @@ static void ioapic_gsi_setup(int); static const struct ioapic_info * ioapic_gsi_search(int); static void ioapic_pin_prog(void *, int, int, - enum intr_trigger, enum intr_polarity, uint32_t); + enum intr_trigger, enum intr_polarity, uint32_t, int); static struct ioapic_conf ioapic_conf; @@ -87,7 +82,7 @@ static TAILQ_HEAD(, ioapic_enumerator) ioapic_enumerators = int ioapic_enable = 1; /* I/O APIC is enabled by default */ -int +static int ioapic_config(void) { struct ioapic_enumerator *e; @@ -97,8 +92,7 @@ ioapic_config(void) register_t ef = 0; TAILQ_INIT(&ioapic_conf.ioc_list); - /* XXX magic number */ - for (i = 0; i < 16; ++i) + for (i = 0; i < ISA_IRQ_CNT; ++i) ioapic_conf.ioc_intsrc[i].int_gsi = -1; probe = 1; @@ -139,7 +133,7 @@ ioapic_config(void) TAILQ_FOREACH(info, &ioapic_conf.ioc_list, io_link) info->io_idx = i++; - if (i > IOAPIC_COUNT_MAX) /* XXX magic number */ + if (i > IOAPIC_COUNT_MAX) panic("ioapic_config: more than 16 I/O APIC\n"); /* @@ -276,7 +270,7 @@ ioapic_intsrc(int irq, int gsi, enum intr_trigger trig, enum intr_polarity pola) { struct ioapic_intsrc *int_src; - KKASSERT(irq < 16); + KKASSERT(irq < ISA_IRQ_CNT); int_src = &ioapic_conf.ioc_intsrc[irq]; if (gsi == 0) { @@ -353,7 +347,7 @@ ioapic_gsi_setup(int gsi) return; } - for (irq = 0; irq < 16; ++irq) { + for (irq = 0; irq < ISA_IRQ_CNT; ++irq) { const struct ioapic_intsrc *int_src = &ioapic_conf.ioc_intsrc[irq]; @@ -364,15 +358,35 @@ ioapic_gsi_setup(int gsi) } } - if (irq == 16) { - if (gsi < 16) { + if (irq == ISA_IRQ_CNT) { + /* + * No explicit IRQ to GSI mapping; + * use the default 1:1 mapping + */ + irq = gsi; + if (irq < ISA_IRQ_CNT) { + if (ioapic_conf.ioc_intsrc[irq].int_gsi >= 0) { + /* + * This IRQ is mapped to different GSI, + * don't do the default configuration. + * The configuration of the target GSI + * will finally setup this IRQ. + * + * This GSI is not used, disable it. + */ + imen_lock(); + ioapic_pin_setup(ioapic_gsi_ioaddr(gsi), + ioapic_gsi_pin(gsi), 0, + INTR_TRIGGER_EDGE, INTR_POLARITY_HIGH, 0); + imen_unlock(); + return; + } trig = INTR_TRIGGER_EDGE; pola = INTR_POLARITY_HIGH; } else { trig = INTR_TRIGGER_LEVEL; pola = INTR_POLARITY_LOW; } - irq = gsi; } ioapic_abi_set_irqmap(irq, gsi, trig, pola); @@ -429,7 +443,7 @@ void ioapic_extpin_setup(void *addr, int pin, int vec) { ioapic_pin_prog(addr, pin, vec, - INTR_TRIGGER_CONFORM, INTR_POLARITY_CONFORM, IOART_DELEXINT); + INTR_TRIGGER_CONFORM, INTR_POLARITY_CONFORM, IOART_DELEXINT, 0); } int @@ -440,7 +454,7 @@ ioapic_extpin_gsi(void) void ioapic_pin_setup(void *addr, int pin, int vec, - enum intr_trigger trig, enum intr_polarity pola) + enum intr_trigger trig, enum intr_polarity pola, int cpuid) { /* * Always clear an I/O APIC pin before [re]programming it. This is @@ -455,13 +469,14 @@ ioapic_pin_setup(void *addr, int pin, int vec, * interrupt. */ ioapic_pin_prog(addr, pin, vec, INTR_TRIGGER_EDGE, INTR_POLARITY_HIGH, - IOART_DELFIXED); - ioapic_pin_prog(addr, pin, vec, trig, pola, IOART_DELFIXED); + IOART_DELFIXED, cpuid); + ioapic_pin_prog(addr, pin, vec, trig, pola, IOART_DELFIXED, cpuid); } static void ioapic_pin_prog(void *addr, int pin, int vec, - enum intr_trigger trig, enum intr_polarity pola, uint32_t del_mode) + enum intr_trigger trig, enum intr_polarity pola, + uint32_t del_mode, int cpuid) { uint32_t flags, target; int select; @@ -517,7 +532,7 @@ ioapic_pin_prog(void *addr, int pin, int vec, } target = ioapic_read(addr, select + 1) & IOART_HI_DEST_RESV; - target |= (CPUID_TO_APICID(0) << IOART_HI_DEST_SHIFT) & + target |= (CPUID_TO_APICID(cpuid) << IOART_HI_DEST_SHIFT) & IOART_HI_DEST_MASK; ioapic_write(addr, select, flags | vec);