mirror of
https://github.com/fergalmoran/ladybird.git
synced 2026-02-22 23:55:12 +00:00
Kernel: Introduce PCIIRQHandler
PCIIRQHandler is a generic IRQ handler that the device driver can inherit to use either Pin or MSI(x) based interrupt mechanism. The PCIIRQHandler can do what the existing IRQHandler can do for pin based interrupts but also deal with MSI based interrupts. We can hopefully convert all the PCI based devices to use this handler so that MSI(x) can be used.
This commit is contained in:
committed by
Jelle Raaijmakers
parent
82cf0bfb75
commit
feb48cbc7c
66
Kernel/Interrupts/PCIIRQHandler.cpp
Normal file
66
Kernel/Interrupts/PCIIRQHandler.cpp
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 2023, Pankaj R <dev@pankajraghav.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <Kernel/Arch/InterruptManagement.h>
|
||||
#include <Kernel/Arch/PCIMSI.h>
|
||||
#include <Kernel/Debug.h>
|
||||
#include <Kernel/Interrupts/PCIIRQHandler.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
PCIIRQHandler::PCIIRQHandler(PCI::Device& device, u8 irq)
|
||||
: GenericInterruptHandler(irq)
|
||||
, device(device)
|
||||
{
|
||||
auto type = device.get_interrupt_type();
|
||||
|
||||
if (type == PCI::InterruptType::PIN)
|
||||
m_responsible_irq_controller = InterruptManagement::the().get_responsible_irq_controller(irq);
|
||||
|
||||
if (is_registered())
|
||||
disable_irq();
|
||||
}
|
||||
|
||||
bool PCIIRQHandler::eoi()
|
||||
{
|
||||
dbgln_if(IRQ_DEBUG, "EOI IRQ {}", interrupt_number());
|
||||
if (m_shared_with_others)
|
||||
return false;
|
||||
if (!m_responsible_irq_controller.is_null())
|
||||
m_responsible_irq_controller->eoi(*this);
|
||||
else
|
||||
msi_signal_eoi();
|
||||
return true;
|
||||
}
|
||||
|
||||
void PCIIRQHandler::enable_irq()
|
||||
{
|
||||
dbgln_if(IRQ_DEBUG, "Enable IRQ {}", interrupt_number());
|
||||
if (!is_registered())
|
||||
register_interrupt_handler();
|
||||
m_enabled = true;
|
||||
if (m_shared_with_others)
|
||||
return;
|
||||
if (!m_responsible_irq_controller.is_null())
|
||||
m_responsible_irq_controller->enable(*this);
|
||||
else
|
||||
device.enable_interrupt(interrupt_number());
|
||||
}
|
||||
|
||||
void PCIIRQHandler::disable_irq()
|
||||
{
|
||||
dbgln_if(IRQ_DEBUG, "Disable IRQ {}", interrupt_number());
|
||||
m_enabled = false;
|
||||
|
||||
if (m_shared_with_others)
|
||||
return;
|
||||
if (!m_responsible_irq_controller.is_null())
|
||||
m_responsible_irq_controller->disable(*this);
|
||||
else
|
||||
device.disable_interrupt(interrupt_number());
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user