* Move redirection entry configuration into a separate function and allow to

specify the delivery mode.
* Use that function from ioapic_configure_io_interrupt() and use it when
  configuring NMI sources to actually set the entries to NMI.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@41531 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz 2011-05-16 14:06:27 +00:00
parent 86d59c04c6
commit 9ae3fdcb02
1 changed files with 70 additions and 47 deletions

View File

@ -192,6 +192,35 @@ ioapic_write_64(struct ioapic& ioapic, uint8 registerSelect, uint64 value,
}
static void
ioapic_configure_pin(struct ioapic& ioapic, uint8 pin, uint8 vector,
uint8 triggerPolarity, uint8 deliveryMode)
{
uint64 entry = ioapic_read_64(ioapic, IO_APIC_REDIRECTION_TABLE + pin * 2);
entry &= ~((1 << IO_APIC_TRIGGER_MODE_SHIFT)
| (1 << IO_APIC_PIN_POLARITY_SHIFT)
| (IO_APIC_INTERRUPT_VECTOR_MASK << IO_APIC_INTERRUPT_VECTOR_SHIFT))
| (IO_APIC_DELIVERY_MODE_MASK << IO_APIC_DELIVERY_MODE_SHIFT);
if (triggerPolarity & B_LEVEL_TRIGGERED) {
entry |= (IO_APIC_TRIGGER_MODE_LEVEL << IO_APIC_TRIGGER_MODE_SHIFT);
ioapic.level_triggered_mask |= ((uint64)1 << pin);
} else {
entry |= (IO_APIC_TRIGGER_MODE_EDGE << IO_APIC_TRIGGER_MODE_SHIFT);
ioapic.level_triggered_mask &= ~((uint64)1 << pin);
}
if (triggerPolarity & B_LOW_ACTIVE_POLARITY)
entry |= (IO_APIC_PIN_POLARITY_LOW_ACTIVE << IO_APIC_PIN_POLARITY_SHIFT);
else
entry |= (IO_APIC_PIN_POLARITY_HIGH_ACTIVE << IO_APIC_PIN_POLARITY_SHIFT);
entry |= (uint64)deliveryMode << IO_APIC_DELIVERY_MODE_SHIFT;
entry |= (vector + ARCH_INTERRUPT_BASE) << IO_APIC_INTERRUPT_VECTOR_SHIFT;
ioapic_write_64(ioapic, IO_APIC_REDIRECTION_TABLE + pin * 2, entry, true);
}
static bool
ioapic_is_spurious_interrupt(int32 gsi)
{
@ -273,26 +302,8 @@ ioapic_configure_io_interrupt(int32 gsi, uint32 config)
TRACE(("ioapic_configure_io_interrupt: gsi %ld -> io-apic %u pin %u; "
"config 0x%08lx\n", gsi, ioapic->number, pin, config));
uint64 entry = ioapic_read_64(*ioapic, IO_APIC_REDIRECTION_TABLE + pin * 2);
entry &= ~((1 << IO_APIC_TRIGGER_MODE_SHIFT)
| (1 << IO_APIC_PIN_POLARITY_SHIFT)
| (IO_APIC_INTERRUPT_VECTOR_MASK << IO_APIC_INTERRUPT_VECTOR_SHIFT));
if (config & B_LEVEL_TRIGGERED) {
entry |= (IO_APIC_TRIGGER_MODE_LEVEL << IO_APIC_TRIGGER_MODE_SHIFT);
ioapic->level_triggered_mask |= ((uint64)1 << pin);
} else {
entry |= (IO_APIC_TRIGGER_MODE_EDGE << IO_APIC_TRIGGER_MODE_SHIFT);
ioapic->level_triggered_mask &= ~((uint64)1 << pin);
}
if (config & B_LOW_ACTIVE_POLARITY)
entry |= (IO_APIC_PIN_POLARITY_LOW_ACTIVE << IO_APIC_PIN_POLARITY_SHIFT);
else
entry |= (IO_APIC_PIN_POLARITY_HIGH_ACTIVE << IO_APIC_PIN_POLARITY_SHIFT);
entry |= (gsi + ARCH_INTERRUPT_BASE) << IO_APIC_INTERRUPT_VECTOR_SHIFT;
ioapic_write_64(*ioapic, IO_APIC_REDIRECTION_TABLE + pin * 2, entry, true);
ioapic_configure_pin(*ioapic, pin, gsi, config,
IO_APIC_DELIVERY_MODE_FIXED);
}
@ -450,6 +461,40 @@ acpi_enumerate_ioapics(acpi_table_madt* madt)
}
static inline uint32
acpi_madt_convert_inti_flags(uint16 flags)
{
uint32 config = 0;
switch (flags & ACPI_MADT_POLARITY_MASK) {
case ACPI_MADT_POLARITY_ACTIVE_LOW:
config = B_LOW_ACTIVE_POLARITY;
break;
default:
dprintf("invalid polarity in inti flags\n");
// fall through and assume active high
case ACPI_MADT_POLARITY_ACTIVE_HIGH:
case ACPI_MADT_POLARITY_CONFORMS:
config = B_HIGH_ACTIVE_POLARITY;
break;
}
switch (flags & ACPI_MADT_TRIGGER_MASK) {
case ACPI_MADT_TRIGGER_LEVEL:
config |= B_LEVEL_TRIGGERED;
break;
default:
dprintf("invalid trigger mode in source override\n");
// fall through and assume edge triggered
case ACPI_MADT_TRIGGER_CONFORMS:
case ACPI_MADT_TRIGGER_EDGE:
config |= B_EDGE_TRIGGERED;
break;
}
return config;
}
static void
acpi_configure_source_overrides(acpi_table_madt* madt)
{
@ -482,33 +527,7 @@ acpi_configure_source_overrides(acpi_table_madt* madt)
}
// configure non-standard polarity/trigger modes
uint32 config = 0;
switch (info->IntiFlags & ACPI_MADT_POLARITY_MASK) {
case ACPI_MADT_POLARITY_ACTIVE_LOW:
config = B_LOW_ACTIVE_POLARITY;
break;
default:
dprintf("invalid polarity in source override\n");
// fall through and assume active high
case ACPI_MADT_POLARITY_ACTIVE_HIGH:
case ACPI_MADT_POLARITY_CONFORMS:
config = B_HIGH_ACTIVE_POLARITY;
break;
}
switch (info->IntiFlags & ACPI_MADT_TRIGGER_MASK) {
case ACPI_MADT_TRIGGER_LEVEL:
config |= B_LEVEL_TRIGGERED;
break;
default:
dprintf("invalid trigger mode in source override\n");
// fall through and assume edge triggered
case ACPI_MADT_TRIGGER_CONFORMS:
case ACPI_MADT_TRIGGER_EDGE:
config |= B_EDGE_TRIGGERED;
break;
}
uint32 config = acpi_madt_convert_inti_flags(info->IntiFlags);
ioapic_configure_io_interrupt(info->GlobalIrq, config);
break;
}
@ -529,6 +548,10 @@ acpi_configure_source_overrides(acpi_table_madt* madt)
uint8 pin = info->GlobalIrq - ioapic->global_interrupt_base;
ioapic->nmi_mask |= (uint64)1 << pin;
uint32 config = acpi_madt_convert_inti_flags(info->IntiFlags);
ioapic_configure_pin(*ioapic, pin, info->GlobalIrq, config,
IO_APIC_DELIVERY_MODE_NMI);
break;
}