mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 15:40:19 +00:00
Kernel: Add MSI support in PCI Device
Extend reserve_irqs, allocate_irq, enable_interrupt and disable_interrupt API to add MSI support in PCI device. The current changes only implement single MSI message support. TODOs have been added to support Multiple MSI Message (MME) support in the future.
This commit is contained in:
parent
35a844ac75
commit
8f62e62cfe
Notes:
sideshowbarker
2024-07-17 05:02:42 +09:00
Author: https://github.com/Panky-codes Commit: https://github.com/SerenityOS/serenity/commit/8f62e62cfe Pull-request: https://github.com/SerenityOS/serenity/pull/18732 Reviewed-by: https://github.com/gmta ✅ Reviewed-by: https://github.com/supercomputer7 ✅
2 changed files with 34 additions and 4 deletions
|
@ -81,6 +81,9 @@ static constexpr size_t memory_range_per_bus = mmio_device_space_size * to_under
|
||||||
static constexpr u32 bar_address_mask = 0xfffffff0;
|
static constexpr u32 bar_address_mask = 0xfffffff0;
|
||||||
static constexpr u8 msi_control_offset = 2;
|
static constexpr u8 msi_control_offset = 2;
|
||||||
static constexpr u16 msi_control_enable = 0x0001;
|
static constexpr u16 msi_control_enable = 0x0001;
|
||||||
|
static constexpr u8 msi_address_low_offset = 4;
|
||||||
|
static constexpr u8 msi_address_high_or_data_offset = 8;
|
||||||
|
static constexpr u8 msi_data_offset = 0xc;
|
||||||
static constexpr u16 msi_address_format_mask = 0x80;
|
static constexpr u16 msi_address_format_mask = 0x80;
|
||||||
static constexpr u8 msi_mmc_format_mask = 0xe;
|
static constexpr u8 msi_mmc_format_mask = 0xe;
|
||||||
static constexpr u16 msix_control_table_mask = 0x07ff;
|
static constexpr u16 msix_control_table_mask = 0x07ff;
|
||||||
|
|
|
@ -91,7 +91,15 @@ ErrorOr<InterruptType> Device::reserve_irqs(u8 number_of_irqs, bool msi)
|
||||||
disable_pin_based_interrupts();
|
disable_pin_based_interrupts();
|
||||||
enable_extended_message_signalled_interrupts();
|
enable_extended_message_signalled_interrupts();
|
||||||
} else if (msi && is_msi_capable()) {
|
} else if (msi && is_msi_capable()) {
|
||||||
TODO();
|
// TODO: Add MME support. Fallback to pin-based until this support is added.
|
||||||
|
if (number_of_irqs > 1)
|
||||||
|
return m_interrupt_range.m_type;
|
||||||
|
|
||||||
|
m_interrupt_range.m_start_irq = TRY(reserve_interrupt_handlers(number_of_irqs));
|
||||||
|
m_interrupt_range.m_irq_count = number_of_irqs;
|
||||||
|
m_interrupt_range.m_type = InterruptType::MSI;
|
||||||
|
disable_pin_based_interrupts();
|
||||||
|
enable_message_signalled_interrupts();
|
||||||
}
|
}
|
||||||
return m_interrupt_range.m_type;
|
return m_interrupt_range.m_type;
|
||||||
}
|
}
|
||||||
|
@ -132,7 +140,26 @@ ErrorOr<u8> Device::allocate_irq(u8 index)
|
||||||
|
|
||||||
return m_interrupt_range.m_start_irq + index;
|
return m_interrupt_range.m_start_irq + index;
|
||||||
} else if ((m_interrupt_range.m_type == InterruptType::MSI) && is_msi_capable()) {
|
} else if ((m_interrupt_range.m_type == InterruptType::MSI) && is_msi_capable()) {
|
||||||
TODO();
|
// TODO: Add MME support.
|
||||||
|
if (index > 0)
|
||||||
|
return Error::from_errno(EINVAL);
|
||||||
|
|
||||||
|
auto data = msi_data_register(m_interrupt_range.m_start_irq + index, false, false);
|
||||||
|
auto addr = msi_address_register(0, false, false);
|
||||||
|
for (auto& capability : m_pci_identifier->capabilities()) {
|
||||||
|
if (capability.id().value() == PCI::Capabilities::ID::MSI) {
|
||||||
|
capability.write32(msi_address_low_offset, addr & 0xffffffff);
|
||||||
|
|
||||||
|
if (!m_pci_identifier->is_msi_64bit_address_format()) {
|
||||||
|
capability.write16(msi_address_high_or_data_offset, data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
capability.write32(msi_address_high_or_data_offset, addr >> 32);
|
||||||
|
capability.write16(msi_data_offset, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m_interrupt_range.m_start_irq + index;
|
||||||
}
|
}
|
||||||
// For pin based interrupts, we share the IRQ.
|
// For pin based interrupts, we share the IRQ.
|
||||||
return m_interrupt_range.m_start_irq;
|
return m_interrupt_range.m_start_irq;
|
||||||
|
@ -152,7 +179,7 @@ void Device::enable_interrupt(u8 irq)
|
||||||
u32 vector_ctrl = msix_vector_control_register(entry_ptr->vector_control, false);
|
u32 vector_ctrl = msix_vector_control_register(entry_ptr->vector_control, false);
|
||||||
entry_ptr->vector_control = vector_ctrl;
|
entry_ptr->vector_control = vector_ctrl;
|
||||||
} else if ((m_interrupt_range.m_type == InterruptType::MSI) && is_msi_capable()) {
|
} else if ((m_interrupt_range.m_type == InterruptType::MSI) && is_msi_capable()) {
|
||||||
TODO();
|
enable_message_signalled_interrupts();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,7 +197,7 @@ void Device::disable_interrupt(u8 irq)
|
||||||
u32 vector_ctrl = msix_vector_control_register(entry_ptr->vector_control, true);
|
u32 vector_ctrl = msix_vector_control_register(entry_ptr->vector_control, true);
|
||||||
entry_ptr->vector_control = vector_ctrl;
|
entry_ptr->vector_control = vector_ctrl;
|
||||||
} else if ((m_interrupt_range.m_type == InterruptType::MSI) && is_msi_capable()) {
|
} else if ((m_interrupt_range.m_type == InterruptType::MSI) && is_msi_capable()) {
|
||||||
TODO();
|
disable_message_signalled_interrupts();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue