mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 15:40:19 +00:00
Kernel: Allow to install a real IRQ handler on a spurious one
IRQ 7 and 15 on the PIC architecture are used for spurious interrupts. IRQ 7 could also be used for LPT connection, and IRQ 15 can be used for the secondary IDE channel. Therefore, we need to allow to install a real IRQ handler and check if a real IRQ was asserted. If so, we handle them in the usual way. A note on this fix - unregistering or registering a new IRQ handler after we already registered one in the spurious interrupt handler is not supported yet.
This commit is contained in:
parent
cf0a12c68f
commit
39c1783387
Notes:
sideshowbarker
2024-07-19 00:42:28 +09:00
Author: https://github.com/supercomputer7 Commit: https://github.com/SerenityOS/serenity/commit/39c17833872 Pull-request: https://github.com/SerenityOS/serenity/pull/4462
3 changed files with 25 additions and 5 deletions
|
@ -583,6 +583,10 @@ void register_generic_interrupt_handler(u8 interrupt_number, GenericInterruptHan
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!s_interrupt_handler[interrupt_number]->is_shared_handler()) {
|
if (!s_interrupt_handler[interrupt_number]->is_shared_handler()) {
|
||||||
|
if (s_interrupt_handler[interrupt_number]->type() == HandlerType::SpuriousInterruptHandler) {
|
||||||
|
static_cast<SpuriousInterruptHandler*>(s_interrupt_handler[interrupt_number])->register_handler(handler);
|
||||||
|
return;
|
||||||
|
}
|
||||||
ASSERT(s_interrupt_handler[interrupt_number]->type() == HandlerType::IRQHandler);
|
ASSERT(s_interrupt_handler[interrupt_number]->type() == HandlerType::IRQHandler);
|
||||||
auto& previous_handler = *s_interrupt_handler[interrupt_number];
|
auto& previous_handler = *s_interrupt_handler[interrupt_number];
|
||||||
s_interrupt_handler[interrupt_number] = nullptr;
|
s_interrupt_handler[interrupt_number] = nullptr;
|
||||||
|
|
|
@ -34,17 +34,25 @@ void SpuriousInterruptHandler::initialize(u8 interrupt_number)
|
||||||
new SpuriousInterruptHandler(interrupt_number);
|
new SpuriousInterruptHandler(interrupt_number);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpuriousInterruptHandler::register_handler(GenericInterruptHandler&)
|
void SpuriousInterruptHandler::register_handler(GenericInterruptHandler& handler)
|
||||||
{
|
{
|
||||||
|
ASSERT(!m_real_handler);
|
||||||
|
m_real_handler = &handler;
|
||||||
}
|
}
|
||||||
void SpuriousInterruptHandler::unregister_handler(GenericInterruptHandler&)
|
void SpuriousInterruptHandler::unregister_handler(GenericInterruptHandler&)
|
||||||
{
|
{
|
||||||
|
TODO();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SpuriousInterruptHandler::eoi()
|
bool SpuriousInterruptHandler::eoi()
|
||||||
{
|
{
|
||||||
// FIXME: Actually check if IRQ7 or IRQ15 are spurious, and if not, call EOI with the correct interrupt number.
|
// Actually check if IRQ7 or IRQ15 are spurious, and if not, call EOI with the correct interrupt number.
|
||||||
m_responsible_irq_controller->eoi(*this);
|
if (m_real_irq) {
|
||||||
|
m_responsible_irq_controller->eoi(*this);
|
||||||
|
m_real_irq = false; // return to default state!
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
m_responsible_irq_controller->spurious_eoi(*this);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,9 +66,15 @@ SpuriousInterruptHandler::~SpuriousInterruptHandler()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpuriousInterruptHandler::handle_interrupt(const RegisterState&)
|
void SpuriousInterruptHandler::handle_interrupt(const RegisterState& state)
|
||||||
{
|
{
|
||||||
// FIXME: Actually check if IRQ7 or IRQ15 are spurious, and if not, call the real handler to handle the IRQ.
|
// Actually check if IRQ7 or IRQ15 are spurious, and if not, call the real handler to handle the IRQ.
|
||||||
|
if (m_responsible_irq_controller->get_isr() & (1 << 15)) {
|
||||||
|
m_real_irq = true; // remember that we had a real IRQ, when EOI later!
|
||||||
|
m_real_handler->increment_invoking_counter();
|
||||||
|
m_real_handler->handle_interrupt(state);
|
||||||
|
return;
|
||||||
|
}
|
||||||
klog() << "Spurious Interrupt, vector " << interrupt_number();
|
klog() << "Spurious Interrupt, vector " << interrupt_number();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,6 +88,7 @@ void SpuriousInterruptHandler::enable_interrupt_vector()
|
||||||
|
|
||||||
void SpuriousInterruptHandler::disable_interrupt_vector()
|
void SpuriousInterruptHandler::disable_interrupt_vector()
|
||||||
{
|
{
|
||||||
|
ASSERT(!m_real_irq); // this flag should not be set when we call this method
|
||||||
if (!m_enabled)
|
if (!m_enabled)
|
||||||
return;
|
return;
|
||||||
m_enabled = false;
|
m_enabled = false;
|
||||||
|
|
|
@ -58,6 +58,7 @@ private:
|
||||||
void disable_interrupt_vector();
|
void disable_interrupt_vector();
|
||||||
explicit SpuriousInterruptHandler(u8 interrupt_number);
|
explicit SpuriousInterruptHandler(u8 interrupt_number);
|
||||||
bool m_enabled;
|
bool m_enabled;
|
||||||
|
bool m_real_irq { false };
|
||||||
RefPtr<IRQController> m_responsible_irq_controller;
|
RefPtr<IRQController> m_responsible_irq_controller;
|
||||||
OwnPtr<GenericInterruptHandler> m_real_handler;
|
OwnPtr<GenericInterruptHandler> m_real_handler;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue