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:
jhb 2004-06-23 15:29:20 +00:00
parent b1c1a50c42
commit 02335c45bd
3 changed files with 117 additions and 32 deletions

View File

@ -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)

View File

@ -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:

View File

@ -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);