mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 08:48:11 +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:
parent
82cf0bfb75
commit
feb48cbc7c
3 changed files with 114 additions and 0 deletions
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());
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue