Serenity Operating System
at master 102 lines 3.0 kB view raw
1/* 2 * Copyright (c) 2020, Liav A. <liavalb@hotmail.co.il> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <Kernel/Arch/InterruptManagement.h> 8#include <Kernel/Assertions.h> 9#include <Kernel/Debug.h> 10#include <Kernel/Interrupts/IRQHandler.h> 11#include <Kernel/Interrupts/SharedIRQHandler.h> 12#include <Kernel/Sections.h> 13 14namespace Kernel { 15 16UNMAP_AFTER_INIT void SharedIRQHandler::initialize(u8 interrupt_number) 17{ 18 auto* handler = new SharedIRQHandler(interrupt_number); 19 handler->register_interrupt_handler(); 20 handler->disable_interrupt_vector(); 21} 22 23void SharedIRQHandler::register_handler(GenericInterruptHandler& handler) 24{ 25 dbgln_if(INTERRUPT_DEBUG, "Interrupt Handler registered @ Shared Interrupt Handler {}", interrupt_number()); 26 m_handlers.append(handler); 27 enable_interrupt_vector(); 28} 29void SharedIRQHandler::unregister_handler(GenericInterruptHandler& handler) 30{ 31 dbgln_if(INTERRUPT_DEBUG, "Interrupt Handler unregistered @ Shared Interrupt Handler {}", interrupt_number()); 32 m_handlers.remove(handler); 33 if (m_handlers.is_empty()) 34 disable_interrupt_vector(); 35} 36 37bool SharedIRQHandler::eoi() 38{ 39 dbgln_if(INTERRUPT_DEBUG, "EOI IRQ {}", interrupt_number()); 40 m_responsible_irq_controller->eoi(*this); 41 return true; 42} 43 44void SharedIRQHandler::enumerate_handlers(Function<void(GenericInterruptHandler&)>& callback) 45{ 46 for (auto& handler : m_handlers) { 47 callback(handler); 48 } 49} 50 51SharedIRQHandler::SharedIRQHandler(u8 irq) 52 : GenericInterruptHandler(irq) 53 , m_responsible_irq_controller(InterruptManagement::the().get_responsible_irq_controller(irq)) 54{ 55 dbgln_if(INTERRUPT_DEBUG, "Shared Interrupt Handler registered @ {}", interrupt_number()); 56} 57 58SharedIRQHandler::~SharedIRQHandler() 59{ 60 dbgln_if(INTERRUPT_DEBUG, "Shared Interrupt Handler unregistered @ {}", interrupt_number()); 61 disable_interrupt_vector(); 62} 63 64bool SharedIRQHandler::handle_interrupt(RegisterState const& regs) 65{ 66 VERIFY_INTERRUPTS_DISABLED(); 67 68 if constexpr (INTERRUPT_DEBUG) { 69 dbgln("Interrupt @ {}", interrupt_number()); 70 dbgln("Interrupt Handlers registered - {}", m_handlers.size_slow()); 71 } 72 int i = 0; 73 bool was_handled = false; 74 for (auto& handler : m_handlers) { 75 dbgln_if(INTERRUPT_DEBUG, "Going for Interrupt Handling @ {}, Shared Interrupt {}", i, interrupt_number()); 76 if (handler.handle_interrupt(regs)) { 77 handler.increment_call_count(); 78 was_handled = true; 79 } 80 dbgln_if(INTERRUPT_DEBUG, "Going for Interrupt Handling @ {}, Shared Interrupt {} - End", i, interrupt_number()); 81 i++; 82 } 83 return was_handled; 84} 85 86void SharedIRQHandler::enable_interrupt_vector() 87{ 88 if (m_enabled) 89 return; 90 m_enabled = true; 91 m_responsible_irq_controller->enable(*this); 92} 93 94void SharedIRQHandler::disable_interrupt_vector() 95{ 96 if (!m_enabled) 97 return; 98 m_enabled = false; 99 m_responsible_irq_controller->disable(*this); 100} 101 102}