X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/blobdiff_plain/a960442f08857d21d946b4ec4e73c32360553a7c..d1ae7328fe6d956bb1f35aae7b169a0b95ebc5eb:/sys/platform/pc32/icu/icu_abi.c diff --git a/sys/platform/pc32/icu/icu_abi.c b/sys/platform/pc32/icu/icu_abi.c index cc253c4905..67b4f00d57 100644 --- a/sys/platform/pc32/icu/icu_abi.c +++ b/sys/platform/pc32/icu/icu_abi.c @@ -48,193 +48,271 @@ #include #include -#include +#include #include +#include #include +#include +#include + #include "icu.h" #include "icu_ipl.h" -#ifndef APIC_IO - -extern void ICU_INTREN(int); -extern void ICU_INTRDIS(int); - extern inthand_t - IDTVEC(icu_fastintr0), IDTVEC(icu_fastintr1), - IDTVEC(icu_fastintr2), IDTVEC(icu_fastintr3), - IDTVEC(icu_fastintr4), IDTVEC(icu_fastintr5), - IDTVEC(icu_fastintr6), IDTVEC(icu_fastintr7), - IDTVEC(icu_fastintr8), IDTVEC(icu_fastintr9), - IDTVEC(icu_fastintr10), IDTVEC(icu_fastintr11), - IDTVEC(icu_fastintr12), IDTVEC(icu_fastintr13), - IDTVEC(icu_fastintr14), IDTVEC(icu_fastintr15); + IDTVEC(icu_intr0), IDTVEC(icu_intr1), + IDTVEC(icu_intr2), IDTVEC(icu_intr3), + IDTVEC(icu_intr4), IDTVEC(icu_intr5), + IDTVEC(icu_intr6), IDTVEC(icu_intr7), + IDTVEC(icu_intr8), IDTVEC(icu_intr9), + IDTVEC(icu_intr10), IDTVEC(icu_intr11), + IDTVEC(icu_intr12), IDTVEC(icu_intr13), + IDTVEC(icu_intr14), IDTVEC(icu_intr15); -extern inthand_t - IDTVEC(icu_slowintr0), IDTVEC(icu_slowintr1), - IDTVEC(icu_slowintr2), IDTVEC(icu_slowintr3), - IDTVEC(icu_slowintr4), IDTVEC(icu_slowintr5), - IDTVEC(icu_slowintr6), IDTVEC(icu_slowintr7), - IDTVEC(icu_slowintr8), IDTVEC(icu_slowintr9), - IDTVEC(icu_slowintr10), IDTVEC(icu_slowintr11), - IDTVEC(icu_slowintr12), IDTVEC(icu_slowintr13), - IDTVEC(icu_slowintr14), IDTVEC(icu_slowintr15); - -static int icu_vectorctl(int, int, int); -static int icu_setvar(int, const void *); -static int icu_getvar(int, void *); -static void icu_finalize(void); -static void icu_cleanup(void); - -static inthand_t *icu_fastintr[ICU_HWI_VECTORS] = { - &IDTVEC(icu_fastintr0), &IDTVEC(icu_fastintr1), - &IDTVEC(icu_fastintr2), &IDTVEC(icu_fastintr3), - &IDTVEC(icu_fastintr4), &IDTVEC(icu_fastintr5), - &IDTVEC(icu_fastintr6), &IDTVEC(icu_fastintr7), - &IDTVEC(icu_fastintr8), &IDTVEC(icu_fastintr9), - &IDTVEC(icu_fastintr10), &IDTVEC(icu_fastintr11), - &IDTVEC(icu_fastintr12), &IDTVEC(icu_fastintr13), - &IDTVEC(icu_fastintr14), &IDTVEC(icu_fastintr15) +static inthand_t *icu_intr[ICU_HWI_VECTORS] = { + &IDTVEC(icu_intr0), &IDTVEC(icu_intr1), + &IDTVEC(icu_intr2), &IDTVEC(icu_intr3), + &IDTVEC(icu_intr4), &IDTVEC(icu_intr5), + &IDTVEC(icu_intr6), &IDTVEC(icu_intr7), + &IDTVEC(icu_intr8), &IDTVEC(icu_intr9), + &IDTVEC(icu_intr10), &IDTVEC(icu_intr11), + &IDTVEC(icu_intr12), &IDTVEC(icu_intr13), + &IDTVEC(icu_intr14), &IDTVEC(icu_intr15) }; -static inthand_t *icu_slowintr[ICU_HWI_VECTORS] = { - &IDTVEC(icu_slowintr0), &IDTVEC(icu_slowintr1), - &IDTVEC(icu_slowintr2), &IDTVEC(icu_slowintr3), - &IDTVEC(icu_slowintr4), &IDTVEC(icu_slowintr5), - &IDTVEC(icu_slowintr6), &IDTVEC(icu_slowintr7), - &IDTVEC(icu_slowintr8), &IDTVEC(icu_slowintr9), - &IDTVEC(icu_slowintr10), &IDTVEC(icu_slowintr11), - &IDTVEC(icu_slowintr12), &IDTVEC(icu_slowintr13), - &IDTVEC(icu_slowintr14), &IDTVEC(icu_slowintr15) -}; +static struct icu_irqmap { + int im_type; /* ICU_IMT_ */ + enum intr_trigger im_trig; +} icu_irqmaps[MAX_HARDINTS]; /* XXX MAX_HARDINTS may not be correct */ + +#define ICU_IMT_UNUSED 0 /* KEEP THIS */ +#define ICU_IMT_RESERVED 1 +#define ICU_IMT_LINE 2 +#define ICU_IMT_SYSCALL 3 -struct machintr_abi MachIntrABI = { - MACHINTR_ICU, - .intrdis = ICU_INTRDIS, - .intren = ICU_INTREN, - .vectorctl =icu_vectorctl, - .setvar = icu_setvar, - .getvar = icu_getvar, - .finalize = icu_finalize, - .cleanup = icu_cleanup +extern void ICU_INTREN(int); +extern void ICU_INTRDIS(int); + +static int icu_vectorctl(int, int, int); +static int icu_setvar(int, const void *); +static int icu_getvar(int, void *); +static void icu_finalize(void); +static void icu_cleanup(void); +static void icu_setdefault(void); +static void icu_stabilize(void); +static void icu_initmap(void); +static void icu_intr_config(int, enum intr_trigger, enum intr_polarity); + +struct machintr_abi MachIntrABI_ICU = { + MACHINTR_ICU, + .intrdis = ICU_INTRDIS, + .intren = ICU_INTREN, + .vectorctl = icu_vectorctl, + .setvar = icu_setvar, + .getvar = icu_getvar, + .finalize = icu_finalize, + .cleanup = icu_cleanup, + .setdefault = icu_setdefault, + .stabilize = icu_stabilize, + .initmap = icu_initmap, + .intr_config = icu_intr_config }; -static int icu_imcr_present; +static int icu_imcr_present; /* * WARNING! SMP builds can use the ICU now so this code must be MP safe. */ -static -int +static int icu_setvar(int varid, const void *buf) { - int error = 0; + int error = 0; - switch(varid) { - case MACHINTR_VAR_IMCR_PRESENT: - icu_imcr_present = *(const int *)buf; - break; - default: - error = ENOENT; - break; - } - return (error); + switch (varid) { + case MACHINTR_VAR_IMCR_PRESENT: + icu_imcr_present = *(const int *)buf; + break; + + default: + error = ENOENT; + break; + } + return error; } -static -int +static int icu_getvar(int varid, void *buf) { - int error = 0; + int error = 0; - switch(varid) { - case MACHINTR_VAR_IMCR_PRESENT: - *(int *)buf = icu_imcr_present; - break; - default: - error = ENOENT; - break; - } - return (error); + switch (varid) { + case MACHINTR_VAR_IMCR_PRESENT: + *(int *)buf = icu_imcr_present; + break; + + default: + error = ENOENT; + break; + } + return error; } /* * Called before interrupts are physically enabled */ static void -icu_finalize(void) +icu_stabilize(void) { - int intr; - - for (intr = 0; intr < ICU_HWI_VECTORS; ++intr) { - machintr_intrdis(intr); - } - machintr_intren(ICU_IRQ_SLAVE); - - /* - * If an IMCR is present, programming bit 0 disconnects the 8259 - * from the BSP. The 8259 may still be connected to LINT0 on the BSP's - * LAPIC. - * - * If we are running SMP the LAPIC is active, try to use virtual wire - * mode so we can use other interrupt sources within the LAPIC in - * addition to the 8259. - */ - if (icu_imcr_present) { -#if defined(SMP) - outb(0x22, 0x70); - outb(0x23, 0x01); -#endif - } + int intr; + + for (intr = 0; intr < ICU_HWI_VECTORS; ++intr) + machintr_intrdis(intr); + machintr_intren(ICU_IRQ_SLAVE); } /* * Called after interrupts physically enabled but before the * critical section is released. */ -static -void +static void icu_cleanup(void) { - mdcpu->gd_fpending = 0; - mdcpu->gd_ipending = 0; + bzero(mdcpu->gd_ipending, sizeof(mdcpu->gd_ipending)); } +/* + * Called after stablize and cleanup; critical section is not + * held and interrupts are not physically disabled. + * + * For SMP: + * Further delayed after BSP's LAPIC is initialized + */ +static void +icu_finalize(void) +{ + KKASSERT(MachIntrABI.type == MACHINTR_ICU); + +#ifdef SMP + if (apic_io_enable) { + /* + * MachIntrABI switching will happen in + * MachIntrABI_IOAPIC.finalize() + */ + MachIntrABI_IOAPIC.setvar(MACHINTR_VAR_IMCR_PRESENT, + &icu_imcr_present); + MachIntrABI_IOAPIC.finalize(); + return; + } + + /* + * If an IMCR is present, programming bit 0 disconnects the 8259 + * from the BSP. The 8259 may still be connected to LINT0 on the + * BSP's LAPIC. + * + * If we are running SMP the LAPIC is active, try to use virtual + * wire mode so we can use other interrupt sources within the LAPIC + * in addition to the 8259. + */ + if (icu_imcr_present) { + u_long ef; + + crit_enter(); + + ef = read_eflags(); + cpu_disable_intr(); + + outb(0x22, 0x70); + outb(0x23, 0x01); -static -int + write_eflags(ef); + + crit_exit(); + } +#endif /* SMP */ +} + +static int icu_vectorctl(int op, int intr, int flags) { - int error; - u_long ef; - - if (intr < 0 || intr >= ICU_HWI_VECTORS || intr == ICU_IRQ_SLAVE) - return (EINVAL); - - ef = read_eflags(); - cpu_disable_intr(); - error = 0; - - switch(op) { - case MACHINTR_VECTOR_SETUP: - setidt(IDT_OFFSET + intr, - flags & INTR_FAST ? icu_fastintr[intr] : icu_slowintr[intr], - SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); - machintr_intren(intr); - break; - case MACHINTR_VECTOR_TEARDOWN: - case MACHINTR_VECTOR_SETDEFAULT: - setidt(IDT_OFFSET + intr, icu_slowintr[intr], SDT_SYS386IGT, SEL_KPL, - GSEL(GCODE_SEL, SEL_KPL)); - machintr_intrdis(intr); - break; - default: - error = EOPNOTSUPP; - break; - } - write_eflags(ef); - return (error); + int error; + u_long ef; + + if (intr < 0 || intr >= ICU_HWI_VECTORS || intr == ICU_IRQ_SLAVE) + return EINVAL; + + ef = read_eflags(); + cpu_disable_intr(); + error = 0; + + switch (op) { + case MACHINTR_VECTOR_SETUP: + setidt(IDT_OFFSET + intr, icu_intr[intr], SDT_SYS386IGT, + SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); + machintr_intren(intr); + break; + + case MACHINTR_VECTOR_TEARDOWN: + machintr_intrdis(intr); + setidt(IDT_OFFSET + intr, icu_intr[intr], SDT_SYS386IGT, + SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); + break; + + default: + error = EOPNOTSUPP; + break; + } + write_eflags(ef); + return error; } -#endif +static void +icu_setdefault(void) +{ + int intr; + + for (intr = 0; intr < ICU_HWI_VECTORS; ++intr) { + if (intr == ICU_IRQ_SLAVE) + continue; + setidt(IDT_OFFSET + intr, icu_intr[intr], SDT_SYS386IGT, + SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); + } +} + +static void +icu_initmap(void) +{ + int i; + + for (i = 0; i < ICU_HWI_VECTORS; ++i) + icu_irqmaps[i].im_type = ICU_IMT_LINE; + icu_irqmaps[ICU_IRQ_SLAVE].im_type = ICU_IMT_RESERVED; + + if (elcr_found) { + for (i = 0; i < ICU_HWI_VECTORS; ++i) + icu_irqmaps[i].im_trig = elcr_read_trigger(i); + } else { + for (i = 0; i < ICU_HWI_VECTORS; ++i) { + switch (i) { + case 0: + case 1: + case 2: + case 8: + case 13: + icu_irqmaps[i].im_trig = INTR_TRIGGER_EDGE; + break; + + default: + icu_irqmaps[i].im_trig = INTR_TRIGGER_LEVEL; + break; + } + } + } + icu_irqmaps[IDT_OFFSET_SYSCALL - IDT_OFFSET].im_type = ICU_IMT_SYSCALL; +} + +static void +icu_intr_config(int irq __unused, enum intr_trigger trig __unused, + enum intr_polarity pola __unused) +{ +}