Serenity Operating System
at master 115 lines 3.5 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/Arch/x86_64/Interrupts.h> 9#include <Kernel/Interrupts/SpuriousInterruptHandler.h> 10#include <Kernel/Sections.h> 11 12namespace Kernel { 13 14UNMAP_AFTER_INIT void SpuriousInterruptHandler::initialize(u8 interrupt_number) 15{ 16 auto* handler = new SpuriousInterruptHandler(interrupt_number); 17 handler->register_interrupt_handler(); 18} 19 20void SpuriousInterruptHandler::initialize_for_disabled_master_pic() 21{ 22 auto* handler = new SpuriousInterruptHandler(7); 23 register_disabled_interrupt_handler(7, *handler); 24 handler->enable_interrupt_vector_for_disabled_pic(); 25} 26 27void SpuriousInterruptHandler::initialize_for_disabled_slave_pic() 28{ 29 auto* handler = new SpuriousInterruptHandler(15); 30 register_disabled_interrupt_handler(15, *handler); 31 handler->enable_interrupt_vector_for_disabled_pic(); 32} 33 34void SpuriousInterruptHandler::register_handler(GenericInterruptHandler& handler) 35{ 36 VERIFY(!m_real_handler); 37 m_real_handler = adopt_own_if_nonnull(&handler); 38} 39void SpuriousInterruptHandler::unregister_handler(GenericInterruptHandler&) 40{ 41 TODO(); 42} 43 44bool SpuriousInterruptHandler::eoi() 45{ 46 // Actually check if IRQ7 or IRQ15 are spurious, and if not, call EOI with the correct interrupt number. 47 if (m_real_irq) { 48 m_responsible_irq_controller->eoi(*this); 49 m_real_irq = false; // return to default state! 50 return true; 51 } 52 m_responsible_irq_controller->spurious_eoi(*this); 53 return false; 54} 55 56StringView SpuriousInterruptHandler::purpose() const 57{ 58 if (!m_real_handler) 59 return "Spurious Interrupt Handler"sv; 60 return m_real_handler->purpose(); 61} 62 63SpuriousInterruptHandler::SpuriousInterruptHandler(u8 irq) 64 : GenericInterruptHandler(irq) 65 , m_responsible_irq_controller(InterruptManagement::the().get_responsible_irq_controller(irq)) 66{ 67} 68 69SpuriousInterruptHandler::~SpuriousInterruptHandler() = default; 70 71bool SpuriousInterruptHandler::handle_interrupt(RegisterState const& state) 72{ 73 // Actually check if IRQ7 or IRQ15 are spurious, and if not, call the real handler to handle the IRQ. 74 if (m_responsible_irq_controller->get_isr() & (1 << interrupt_number())) { 75 m_real_irq = true; // remember that we had a real IRQ, when EOI later! 76 if (m_real_handler->handle_interrupt(state)) { 77 m_real_handler->increment_call_count(); 78 return true; 79 } 80 return false; 81 } 82 dbgln("Spurious interrupt, vector {}", interrupt_number()); 83 return true; 84} 85 86void SpuriousInterruptHandler::enable_interrupt_vector_for_disabled_pic() 87{ 88 m_enabled = true; 89 m_responsible_irq_controller = InterruptManagement::the().get_responsible_irq_controller(IRQControllerType::i8259, interrupt_number()); 90} 91 92void SpuriousInterruptHandler::enable_interrupt_vector() 93{ 94 if (m_enabled) 95 return; 96 m_enabled = true; 97 m_responsible_irq_controller->enable(*this); 98} 99 100void SpuriousInterruptHandler::disable_interrupt_vector() 101{ 102 VERIFY(!m_real_irq); // this flag should not be set when we call this method 103 if (!m_enabled) 104 return; 105 m_enabled = false; 106 m_responsible_irq_controller->disable(*this); 107} 108 109StringView SpuriousInterruptHandler::controller() const 110{ 111 if (m_responsible_irq_controller->type() == IRQControllerType::i82093AA) 112 return ""sv; 113 return m_responsible_irq_controller->model(); 114} 115}