Various cleanups in support of a future ioapic_config_intr() function:
- Allow ioapic_set_{nmi,smi,extint}() to be called multiple times on the same pin so long as the pin's mode is the same as the mode being requested. - Add a notion of bus type for the interrupt associated with interrupt pin. This is needed so that we can force all EISA interrupts to be active high in the forthcoming ioapic_config_intr(). - Fix a bug for EISA systems that didn't remap IRQs. This would have broken EISA systems that tried to disable mixed mode for IRQ 0.
This commit is contained in:
parent
b1c1a50c42
commit
02335c45bd
@ -99,6 +99,7 @@ struct ioapic_intsrc {
|
||||
u_int io_edgetrigger:1;
|
||||
u_int io_masked:1;
|
||||
int io_dest:5;
|
||||
int io_bus:4;
|
||||
};
|
||||
|
||||
struct ioapic {
|
||||
@ -114,6 +115,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);
|
||||
@ -162,6 +165,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)
|
||||
{
|
||||
@ -298,10 +340,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);
|
||||
@ -490,44 +529,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);
|
||||
@ -581,6 +612,25 @@ ioapic_remap_vector(void *cookie, u_int pin, int vector)
|
||||
return (0);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@ -589,8 +639,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;
|
||||
@ -609,8 +662,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;
|
||||
@ -629,10 +685,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)
|
||||
|
@ -646,14 +646,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:
|
||||
|
@ -113,6 +113,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.
|
||||
@ -141,6 +147,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);
|
||||
|
Loading…
Reference in New Issue
Block a user