1
Fork 0
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:
Pankaj Raghav 2023-04-29 21:50:01 +02:00 committed by Jelle Raaijmakers
parent 82cf0bfb75
commit feb48cbc7c
3 changed files with 114 additions and 0 deletions

View 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());
}
}