diff options
author | peter <peter@FreeBSD.org> | 2004-07-08 01:42:49 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 2004-07-08 01:42:49 +0000 |
commit | e3e493024dec3bde4f375b5e9253880b423771c0 (patch) | |
tree | 9b1a3645cab9fdbceba7847d110ec6a26d3963e3 /sys/amd64 | |
parent | dd3c90cb130487da4a03fb9222df5e64c180e55f (diff) | |
download | FreeBSD-src-e3e493024dec3bde4f375b5e9253880b423771c0.zip FreeBSD-src-e3e493024dec3bde4f375b5e9253880b423771c0.tar.gz |
MFi386: various io apic cleanups
Diffstat (limited to 'sys/amd64')
-rw-r--r-- | sys/amd64/amd64/io_apic.c | 169 | ||||
-rw-r--r-- | sys/amd64/amd64/mptable.c | 25 | ||||
-rw-r--r-- | sys/amd64/include/apicvar.h | 7 |
3 files changed, 147 insertions, 54 deletions
diff --git a/sys/amd64/amd64/io_apic.c b/sys/amd64/amd64/io_apic.c index b734162..4b8568d 100644 --- a/sys/amd64/amd64/io_apic.c +++ b/sys/amd64/amd64/io_apic.c @@ -100,6 +100,7 @@ struct ioapic_intsrc { u_int io_edgetrigger:1; u_int io_masked:1; int io_dest:5; + int io_bus:4; }; struct ioapic { @@ -115,6 +116,8 @@ struct ioapic { static u_int ioapic_read(volatile ioapic_t *apic, int reg); static void ioapic_write(volatile ioapic_t *apic, int reg, u_int val); +static const char *ioapic_bus_string(int bus_type); +static void ioapic_print_vector(struct ioapic_intsrc *intpin); static void ioapic_enable_source(struct intsrc *isrc); static void ioapic_disable_source(struct intsrc *isrc); static void ioapic_eoi_source(struct intsrc *isrc); @@ -163,6 +166,45 @@ ioapic_write(volatile ioapic_t *apic, int reg, u_int val) apic->iowin = val; } +static const char * +ioapic_bus_string(int bus_type) +{ + + switch (bus_type) { + case APIC_BUS_ISA: + return ("ISA"); + case APIC_BUS_EISA: + return ("EISA"); + case APIC_BUS_PCI: + return ("PCI"); + default: + return ("unknown"); + } +} + +static void +ioapic_print_vector(struct ioapic_intsrc *intpin) +{ + + switch (intpin->io_vector) { + case VECTOR_DISABLED: + printf("disabled"); + break; + case VECTOR_EXTINT: + printf("ExtINT"); + break; + case VECTOR_NMI: + printf("NMI"); + break; + case VECTOR_SMI: + printf("SMI"); + break; + default: + printf("%s IRQ %u", ioapic_bus_string(intpin->io_bus), + intpin->io_vector); + } +} + static void ioapic_enable_source(struct intsrc *isrc) { @@ -299,10 +341,7 @@ ioapic_program_destination(struct ioapic_intsrc *intpin) if (bootverbose) { printf("ioapic%u: routing intpin %u (", io->io_id, intpin->io_intpin); - if (intpin->io_vector == VECTOR_EXTINT) - printf("ExtINT"); - else - printf("IRQ %u", intpin->io_vector); + ioapic_print_vector(intpin); printf(") to cluster %u\n", intpin->io_dest); } ioapic_program_intpin(intpin); @@ -365,32 +404,39 @@ ioapic_config_intr(struct intsrc *isrc, enum intr_trigger trig, { struct ioapic_intsrc *intpin = (struct ioapic_intsrc *)isrc; struct ioapic *io = (struct ioapic *)isrc->is_pic; + int changed; KASSERT(!(trig == INTR_TRIGGER_CONFORM || pol == INTR_POLARITY_CONFORM), ("%s: Conforming trigger or polarity\n", __func__)); /* - * For now we ignore any requests but do output any changes that - * would be made to the console it bootverbose is enabled. The only - * known causes of these messages so far is a bug in acpi(4) that - * causes the ISA IRQs used for PCI interrupts in PIC mode to be - * set to level/low when they aren't being used. There are possibly - * legitimate requests, so at some point when the acpi(4) driver is - * fixed this code can be changed to actually change the intpin as - * requested. + * EISA interrupts always use active high polarity, so don't allow + * them to be set to active low. + * + * XXX: Should we write to the ELCR if the trigger mode changes for + * an EISA IRQ? */ - if (!bootverbose) - return (0); - if (intpin->io_edgetrigger != (trig == INTR_TRIGGER_EDGE)) - printf( - "ioapic%u: Request to change trigger for pin %u to %s ignored\n", - io->io_id, intpin->io_intpin, trig == INTR_TRIGGER_EDGE ? - "edge" : "level"); - if (intpin->io_activehi != (pol == INTR_POLARITY_HIGH)) - printf( - "ioapic%u: Request to change polarity for pin %u to %s ignored\n", - io->io_id, intpin->io_intpin, pol == INTR_POLARITY_HIGH ? - "high" : "low"); + if (intpin->io_bus == APIC_BUS_EISA) + pol = INTR_POLARITY_HIGH; + changed = 0; + if (intpin->io_edgetrigger != (trig == INTR_TRIGGER_EDGE)) { + if (bootverbose) + printf("ioapic%u: Changing trigger for pin %u to %s\n", + io->io_id, intpin->io_intpin, + trig == INTR_TRIGGER_EDGE ? "edge" : "level"); + intpin->io_edgetrigger = (trig == INTR_TRIGGER_EDGE); + changed++; + } + if (intpin->io_activehi != (pol == INTR_POLARITY_HIGH)) { + if (bootverbose) + printf("ioapic%u: Changing polarity for pin %u to %s\n", + io->io_id, intpin->io_intpin, + pol == INTR_POLARITY_HIGH ? "high" : "low"); + intpin->io_activehi = (pol == INTR_POLARITY_HIGH); + changed++; + } + if (changed) + ioapic_program_intpin(intpin); return (0); } @@ -491,44 +537,36 @@ ioapic_create(uintptr_t addr, int32_t apic_id, int intbase) intpin->io_vector = intbase + i; /* - * 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 if - * mixed mode is available and active but mask all other pins. + * Assume that pin 0 on the first I/O APIC is an ExtINT pin + * and that pins 1-15 are ISA interrupts. Assume that all + * other pins are PCI interrupts. */ - if (intpin->io_vector == 0) { - intpin->io_activehi = 1; - intpin->io_edgetrigger = 1; - intpin->io_vector = VECTOR_EXTINT; - if (mixed_mode_enabled && mixed_mode_active) - intpin->io_masked = 0; - else - intpin->io_masked = 1; - } else if (intpin->io_vector < IOAPIC_ISA_INTS) { + if (intpin->io_vector == 0) + ioapic_set_extint(io, i); + else if (intpin->io_vector < IOAPIC_ISA_INTS) { + intpin->io_bus = APIC_BUS_ISA; intpin->io_activehi = 1; intpin->io_edgetrigger = 1; intpin->io_masked = 1; } else { + intpin->io_bus = APIC_BUS_PCI; intpin->io_activehi = 0; intpin->io_edgetrigger = 0; intpin->io_masked = 1; } /* - * Start off without a logical cluster destination until - * the pin is enabled. + * Route interrupts to the BSP by default using physical + * addressing. Vectored interrupts get readdressed using + * logical IDs to CPU clusters when they are enabled. */ intpin->io_dest = DEST_NONE; - if (bootverbose) { + if (bootverbose && intpin->io_vector != VECTOR_DISABLED) { printf("ioapic%u: intpin %d -> ", io->io_id, i); - if (intpin->io_vector == VECTOR_EXTINT) - printf("ExtINT"); - else - printf("irq %u", intpin->io_vector); - printf(" (%s, active%s)\n", intpin->io_edgetrigger ? - "edge" : "level", intpin->io_activehi ? "hi" : - "lo"); + ioapic_print_vector(intpin); + printf(" (%s, %s)\n", intpin->io_edgetrigger ? + "edge" : "level", intpin->io_activehi ? "high" : + "low"); } value = ioapic_read(apic, IOAPIC_REDTBL_LO(i)); ioapic_write(apic, IOAPIC_REDTBL_LO(i), value | IOART_INTMSET); @@ -583,6 +621,25 @@ ioapic_remap_vector(void *cookie, u_int pin, int vector) } int +ioapic_set_bus(void *cookie, u_int pin, int bus_type) +{ + struct ioapic *io; + + if (bus_type < 0 || bus_type > APIC_BUS_MAX) + return (EINVAL); + io = (struct ioapic *)cookie; + if (pin >= io->io_numintr) + return (EINVAL); + if (io->io_pins[pin].io_vector >= NUM_IO_INTS) + return (EINVAL); + io->io_pins[pin].io_bus = bus_type; + if (bootverbose) + printf("ioapic%u: intpin %d bus %s\n", io->io_id, pin, + ioapic_bus_string(bus_type)); + return (0); +} + +int ioapic_set_nmi(void *cookie, u_int pin) { struct ioapic *io; @@ -590,8 +647,11 @@ ioapic_set_nmi(void *cookie, u_int pin) io = (struct ioapic *)cookie; if (pin >= io->io_numintr) return (EINVAL); + if (io->io_pins[pin].io_vector == VECTOR_NMI) + return (0); if (io->io_pins[pin].io_vector >= NUM_IO_INTS) return (EINVAL); + io->io_pins[pin].io_bus = APIC_BUS_UNKNOWN; io->io_pins[pin].io_vector = VECTOR_NMI; io->io_pins[pin].io_masked = 0; io->io_pins[pin].io_edgetrigger = 1; @@ -610,8 +670,11 @@ ioapic_set_smi(void *cookie, u_int pin) io = (struct ioapic *)cookie; if (pin >= io->io_numintr) return (EINVAL); + if (io->io_pins[pin].io_vector == VECTOR_SMI) + return (0); if (io->io_pins[pin].io_vector >= NUM_IO_INTS) return (EINVAL); + io->io_pins[pin].io_bus = APIC_BUS_UNKNOWN; io->io_pins[pin].io_vector = VECTOR_SMI; io->io_pins[pin].io_masked = 0; io->io_pins[pin].io_edgetrigger = 1; @@ -630,10 +693,18 @@ ioapic_set_extint(void *cookie, u_int pin) io = (struct ioapic *)cookie; if (pin >= io->io_numintr) return (EINVAL); + if (io->io_pins[pin].io_vector == VECTOR_EXTINT) + return (0); if (io->io_pins[pin].io_vector >= NUM_IO_INTS) return (EINVAL); + io->io_pins[pin].io_bus = APIC_BUS_UNKNOWN; io->io_pins[pin].io_vector = VECTOR_EXTINT; - io->io_pins[pin].io_masked = 0; + + /* Enable this pin if mixed mode is available and active. */ + if (mixed_mode_enabled && mixed_mode_active) + io->io_pins[pin].io_masked = 0; + else + io->io_pins[pin].io_masked = 1; io->io_pins[pin].io_edgetrigger = 1; io->io_pins[pin].io_activehi = 1; if (bootverbose) diff --git a/sys/amd64/amd64/mptable.c b/sys/amd64/amd64/mptable.c index 622aeaa..ac56bf1 100644 --- a/sys/amd64/amd64/mptable.c +++ b/sys/amd64/amd64/mptable.c @@ -639,14 +639,28 @@ mptable_parse_io_int(int_entry_ptr intr) pin = intr->dst_apic_int; switch (intr->int_type) { case INTENTRY_TYPE_INT: - if (busses[intr->src_bus_id].bus_type == NOBUS) + switch (busses[intr->src_bus_id].bus_type) { + case NOBUS: panic("interrupt from missing bus"); - if (busses[intr->src_bus_id].bus_type == ISA && - intr->src_bus_irq != pin) { + case ISA: + case EISA: + if (busses[intr->src_bus_id].bus_type == ISA) + ioapic_set_bus(ioapic, pin, APIC_BUS_ISA); + else + ioapic_set_bus(ioapic, pin, APIC_BUS_EISA); + if (intr->src_bus_irq == pin) + break; ioapic_remap_vector(ioapic, pin, intr->src_bus_irq); if (ioapic_get_vector(ioapic, intr->src_bus_irq) == intr->src_bus_irq) ioapic_disable_pin(ioapic, intr->src_bus_irq); + break; + case PCI: + ioapic_set_bus(ioapic, pin, APIC_BUS_PCI); + break; + default: + ioapic_set_bus(ioapic, pin, APIC_BUS_UNKNOWN); + break; } break; case INTENTRY_TYPE_NMI: @@ -944,7 +958,8 @@ mptable_pci_route_interrupt(device_t pcib, device_t dev, int pin) 'A' + pin); return (PCI_INVALID_IRQ); } - device_printf(pcib, "slot %d INT%c routed to irq %d\n", slot, 'A' + pin, - args.vector); + if (bootverbose) + device_printf(pcib, "slot %d INT%c routed to irq %d\n", slot, + 'A' + pin, args.vector); return (args.vector); } diff --git a/sys/amd64/include/apicvar.h b/sys/amd64/include/apicvar.h index 30b9a8e..e6804d7 100644 --- a/sys/amd64/include/apicvar.h +++ b/sys/amd64/include/apicvar.h @@ -114,6 +114,12 @@ #define APIC_IPI_DEST_ALL -2 #define APIC_IPI_DEST_OTHERS -3 +#define APIC_BUS_UNKNOWN -1 +#define APIC_BUS_ISA 0 +#define APIC_BUS_EISA 1 +#define APIC_BUS_PCI 2 +#define APIC_BUS_MAX APIC_BUS_PCI + /* * An APIC enumerator is a psuedo bus driver that enumerates APIC's including * CPU's and I/O APIC's. @@ -142,6 +148,7 @@ int ioapic_get_vector(void *cookie, u_int pin); int ioapic_next_logical_cluster(void); void ioapic_register(void *cookie); int ioapic_remap_vector(void *cookie, u_int pin, int vector); +int ioapic_set_bus(void *cookie, u_int pin, int bus_type); int ioapic_set_extint(void *cookie, u_int pin); int ioapic_set_nmi(void *cookie, u_int pin); int ioapic_set_polarity(void *cookie, u_int pin, enum intr_polarity pol); |