diff --git a/Kernel/ACPI/DynamicParser.cpp b/Kernel/ACPI/DynamicParser.cpp index 2d143348d27164..7c6d6c6a60a9a7 100644 --- a/Kernel/ACPI/DynamicParser.cpp +++ b/Kernel/ACPI/DynamicParser.cpp @@ -17,7 +17,7 @@ UNMAP_AFTER_INIT DynamicParser::DynamicParser(PhysicalAddress rsdp) dmesgln("ACPI: Dynamic Parsing Enabled, Can parse AML"); } -void DynamicParser::handle_irq(const RegisterState&) +bool DynamicParser::handle_irq(const RegisterState&) { // FIXME: Implement IRQ handling of ACPI signals! VERIFY_NOT_REACHED(); diff --git a/Kernel/ACPI/DynamicParser.h b/Kernel/ACPI/DynamicParser.h index f97f8f8a96a4d4..f2c61176e38bbd 100644 --- a/Kernel/ACPI/DynamicParser.h +++ b/Kernel/ACPI/DynamicParser.h @@ -36,7 +36,7 @@ class DynamicParser final private: void build_namespace(); // ^IRQHandler - virtual void handle_irq(const RegisterState&) override; + virtual bool handle_irq(const RegisterState&) override; OwnPtr m_acpi_namespace; }; diff --git a/Kernel/Devices/HID/I8042Controller.cpp b/Kernel/Devices/HID/I8042Controller.cpp index 4f100fc4314fab..1a45a3532632e8 100644 --- a/Kernel/Devices/HID/I8042Controller.cpp +++ b/Kernel/Devices/HID/I8042Controller.cpp @@ -129,25 +129,26 @@ UNMAP_AFTER_INIT void I8042Controller::detect_devices() m_mouse_device->enable_interrupts(); } -void I8042Controller::irq_process_input_buffer(HIDDevice::Type) +bool I8042Controller::irq_process_input_buffer(HIDDevice::Type) { VERIFY(Processor::current().in_irq()); u8 status = IO::in8(I8042_STATUS); if (!(status & I8042_BUFFER_FULL)) - return; + return false; HIDDevice::Type data_for_device = ((status & I8042_WHICH_BUFFER) == I8042_MOUSE_BUFFER) ? HIDDevice::Type::Mouse : HIDDevice::Type::Keyboard; u8 byte = IO::in8(I8042_BUFFER); if (data_for_device == HIDDevice::Type::Mouse) { VERIFY(m_mouse_device); static_cast(*m_mouse_device).irq_handle_byte_read(byte); - return; + return true; } if (data_for_device == HIDDevice::Type::Keyboard) { VERIFY(m_keyboard_device); static_cast(*m_keyboard_device).irq_handle_byte_read(byte); - return; + return true; } + return false; } void I8042Controller::do_drain() diff --git a/Kernel/Devices/HID/I8042Controller.h b/Kernel/Devices/HID/I8042Controller.h index ed274c91d8660b..a828a7261a236c 100644 --- a/Kernel/Devices/HID/I8042Controller.h +++ b/Kernel/Devices/HID/I8042Controller.h @@ -89,7 +89,7 @@ class I8042Controller : public RefCounted { void prepare_for_output(); void prepare_for_input(HIDDevice::Type); - void irq_process_input_buffer(HIDDevice::Type); + bool irq_process_input_buffer(HIDDevice::Type); RefPtr mouse() const; RefPtr keyboard() const; diff --git a/Kernel/Devices/HID/PS2KeyboardDevice.cpp b/Kernel/Devices/HID/PS2KeyboardDevice.cpp index 608ea94b371a56..ea739ab6beda3f 100644 --- a/Kernel/Devices/HID/PS2KeyboardDevice.cpp +++ b/Kernel/Devices/HID/PS2KeyboardDevice.cpp @@ -85,11 +85,11 @@ void PS2KeyboardDevice::irq_handle_byte_read(u8 byte) } } -void PS2KeyboardDevice::handle_irq(const RegisterState&) +bool PS2KeyboardDevice::handle_irq(const RegisterState&) { // The controller will read the data and call irq_handle_byte_read // for the appropriate device - m_i8042_controller->irq_process_input_buffer(HIDDevice::Type::Keyboard); + return m_i8042_controller->irq_process_input_buffer(HIDDevice::Type::Keyboard); } UNMAP_AFTER_INIT RefPtr PS2KeyboardDevice::try_to_initialize(const I8042Controller& ps2_controller) diff --git a/Kernel/Devices/HID/PS2KeyboardDevice.h b/Kernel/Devices/HID/PS2KeyboardDevice.h index 6b8be0a36b2f1c..ceed7793d66c15 100644 --- a/Kernel/Devices/HID/PS2KeyboardDevice.h +++ b/Kernel/Devices/HID/PS2KeyboardDevice.h @@ -39,7 +39,7 @@ class PS2KeyboardDevice final : public IRQHandler explicit PS2KeyboardDevice(const I8042Controller&); // ^IRQHandler - virtual void handle_irq(const RegisterState&) override; + virtual bool handle_irq(const RegisterState&) override; // ^CharacterDevice virtual const char* class_name() const override { return "KeyboardDevice"; } diff --git a/Kernel/Devices/HID/PS2MouseDevice.cpp b/Kernel/Devices/HID/PS2MouseDevice.cpp index 48bfcdcfd48d2c..a565e8525297ce 100644 --- a/Kernel/Devices/HID/PS2MouseDevice.cpp +++ b/Kernel/Devices/HID/PS2MouseDevice.cpp @@ -40,11 +40,11 @@ UNMAP_AFTER_INIT PS2MouseDevice::~PS2MouseDevice() { } -void PS2MouseDevice::handle_irq(const RegisterState&) +bool PS2MouseDevice::handle_irq(const RegisterState&) { // The controller will read the data and call irq_handle_byte_read // for the appropriate device - m_i8042_controller->irq_process_input_buffer(instrument_type()); + return m_i8042_controller->irq_process_input_buffer(instrument_type()); } void PS2MouseDevice::irq_handle_byte_read(u8 byte) diff --git a/Kernel/Devices/HID/PS2MouseDevice.h b/Kernel/Devices/HID/PS2MouseDevice.h index 3a08a995f8608d..fa736c541edb9a 100644 --- a/Kernel/Devices/HID/PS2MouseDevice.h +++ b/Kernel/Devices/HID/PS2MouseDevice.h @@ -35,7 +35,7 @@ class PS2MouseDevice : public IRQHandler protected: explicit PS2MouseDevice(const I8042Controller&); // ^IRQHandler - virtual void handle_irq(const RegisterState&) override; + virtual bool handle_irq(const RegisterState&) override; struct RawPacket { union { diff --git a/Kernel/Devices/SB16.cpp b/Kernel/Devices/SB16.cpp index 2ae61c8ad2a180..ec29fe28b0d0bb 100644 --- a/Kernel/Devices/SB16.cpp +++ b/Kernel/Devices/SB16.cpp @@ -205,8 +205,10 @@ void SB16::dma_start(uint32_t length) IO::out8(0xd4, (channel % 4)); } -void SB16::handle_irq(const RegisterState&) +bool SB16::handle_irq(const RegisterState&) { + // FIXME: Check if the interrupt was actually for us or not... (shared IRQs) + // Stop sound output ready for the next block. dsp_write(0xd5); @@ -215,6 +217,7 @@ void SB16::handle_irq(const RegisterState&) IO::in8(DSP_R_ACK); // 16 bit interrupt m_irq_queue.wake_all(); + return true; } void SB16::wait_for_irq() diff --git a/Kernel/Devices/SB16.h b/Kernel/Devices/SB16.h index 8754e4e6d4ab8e..9c248716e608fb 100644 --- a/Kernel/Devices/SB16.h +++ b/Kernel/Devices/SB16.h @@ -40,7 +40,7 @@ class SB16 final : public IRQHandler private: // ^IRQHandler - virtual void handle_irq(const RegisterState&) override; + virtual bool handle_irq(const RegisterState&) override; // ^CharacterDevice virtual const char* class_name() const override { return "SB16"; } diff --git a/Kernel/Devices/USB/UHCIController.cpp b/Kernel/Devices/USB/UHCIController.cpp index a1a497c3cedaac..d11a887789d8e5 100644 --- a/Kernel/Devices/USB/UHCIController.cpp +++ b/Kernel/Devices/USB/UHCIController.cpp @@ -586,13 +586,13 @@ void UHCIController::spawn_port_proc() }); } -void UHCIController::handle_irq(const RegisterState&) +bool UHCIController::handle_irq(const RegisterState&) { u32 status = read_usbsts(); // Shared IRQ. Not ours! if (!status) - return; + return false; if constexpr (UHCI_DEBUG) { dbgln("UHCI: Interrupt happened!"); @@ -601,6 +601,7 @@ void UHCIController::handle_irq(const RegisterState&) // Write back USBSTS to clear bits write_usbsts(status); + return true; } } diff --git a/Kernel/Devices/USB/UHCIController.h b/Kernel/Devices/USB/UHCIController.h index 39ba8757d8d815..8ebbc907989603 100644 --- a/Kernel/Devices/USB/UHCIController.h +++ b/Kernel/Devices/USB/UHCIController.h @@ -60,7 +60,7 @@ class UHCIController final : public PCI::Device { void write_portsc1(u16 value) { m_io_base.offset(0x10).out(value); } void write_portsc2(u16 value) { m_io_base.offset(0x12).out(value); } - virtual void handle_irq(const RegisterState&) override; + virtual bool handle_irq(const RegisterState&) override; void create_structures(); void setup_schedule(); diff --git a/Kernel/Interrupts/APIC.cpp b/Kernel/Interrupts/APIC.cpp index 4c8b8ab6433e7a..89303cee3d4462 100644 --- a/Kernel/Interrupts/APIC.cpp +++ b/Kernel/Interrupts/APIC.cpp @@ -70,7 +70,7 @@ class APICIPIInterruptHandler final : public GenericInterruptHandler { handler->register_interrupt_handler(); } - virtual void handle_interrupt(const RegisterState&) override; + virtual bool handle_interrupt(const RegisterState&) override; virtual bool eoi() override; @@ -101,7 +101,7 @@ class APICErrInterruptHandler final : public GenericInterruptHandler { handler->register_interrupt_handler(); } - virtual void handle_interrupt(const RegisterState&) override; + virtual bool handle_interrupt(const RegisterState&) override; virtual bool eoi() override; @@ -555,9 +555,10 @@ u32 APIC::get_timer_divisor() return 16; } -void APICIPIInterruptHandler::handle_interrupt(const RegisterState&) +bool APICIPIInterruptHandler::handle_interrupt(const RegisterState&) { dbgln_if(APIC_SMP_DEBUG, "APIC IPI on CPU #{}", Processor::id()); + return true; } bool APICIPIInterruptHandler::eoi() @@ -567,9 +568,10 @@ bool APICIPIInterruptHandler::eoi() return true; } -void APICErrInterruptHandler::handle_interrupt(const RegisterState&) +bool APICErrInterruptHandler::handle_interrupt(const RegisterState&) { dbgln("APIC: SMP error on CPU #{}", Processor::id()); + return true; } bool APICErrInterruptHandler::eoi() diff --git a/Kernel/Interrupts/GenericInterruptHandler.h b/Kernel/Interrupts/GenericInterruptHandler.h index 368d03c0f07e08..b37c67772fa576 100644 --- a/Kernel/Interrupts/GenericInterruptHandler.h +++ b/Kernel/Interrupts/GenericInterruptHandler.h @@ -27,7 +27,9 @@ class GenericInterruptHandler { { VERIFY(!m_registered); } - virtual void handle_interrupt(const RegisterState& regs) = 0; + // Note: this method returns boolean value, to indicate if the handler handled + // the interrupt or not. This is useful for shared handlers mostly. + virtual bool handle_interrupt(const RegisterState& regs) = 0; void will_be_destroyed(); bool is_registered() const { return m_registered; } diff --git a/Kernel/Interrupts/IRQHandler.h b/Kernel/Interrupts/IRQHandler.h index a4c1fc47990fd6..c89e0d8f9020c6 100644 --- a/Kernel/Interrupts/IRQHandler.h +++ b/Kernel/Interrupts/IRQHandler.h @@ -19,8 +19,8 @@ class IRQHandler : public GenericInterruptHandler { public: virtual ~IRQHandler(); - virtual void handle_interrupt(const RegisterState& regs) { handle_irq(regs); } - virtual void handle_irq(const RegisterState&) = 0; + virtual bool handle_interrupt(const RegisterState& regs) { return handle_irq(regs); } + virtual bool handle_irq(const RegisterState&) = 0; void enable_irq(); void disable_irq(); diff --git a/Kernel/Interrupts/SharedIRQHandler.cpp b/Kernel/Interrupts/SharedIRQHandler.cpp index 8f2235fceb18e3..4eea1ae79e356f 100644 --- a/Kernel/Interrupts/SharedIRQHandler.cpp +++ b/Kernel/Interrupts/SharedIRQHandler.cpp @@ -63,7 +63,7 @@ SharedIRQHandler::~SharedIRQHandler() disable_interrupt_vector(); } -void SharedIRQHandler::handle_interrupt(const RegisterState& regs) +bool SharedIRQHandler::handle_interrupt(const RegisterState& regs) { VERIFY_INTERRUPTS_DISABLED(); @@ -71,16 +71,19 @@ void SharedIRQHandler::handle_interrupt(const RegisterState& regs) dbgln("Interrupt @ {}", interrupt_number()); dbgln("Interrupt Handlers registered - {}", m_handlers.size()); } - int i = 0; + bool was_handled = false; for (auto* handler : m_handlers) { dbgln_if(INTERRUPT_DEBUG, "Going for Interrupt Handling @ {}, Shared Interrupt {}", i, interrupt_number()); VERIFY(handler != nullptr); - handler->increment_invoking_counter(); - handler->handle_interrupt(regs); + if (handler->handle_interrupt(regs)) { + handler->increment_invoking_counter(); + was_handled = true; + } dbgln_if(INTERRUPT_DEBUG, "Going for Interrupt Handling @ {}, Shared Interrupt {} - End", i, interrupt_number()); i++; } + return was_handled; } void SharedIRQHandler::enable_interrupt_vector() diff --git a/Kernel/Interrupts/SharedIRQHandler.h b/Kernel/Interrupts/SharedIRQHandler.h index 86272a16235cab..a5ccfc497ed219 100644 --- a/Kernel/Interrupts/SharedIRQHandler.h +++ b/Kernel/Interrupts/SharedIRQHandler.h @@ -19,7 +19,7 @@ class SharedIRQHandler final : public GenericInterruptHandler { public: static void initialize(u8 interrupt_number); virtual ~SharedIRQHandler(); - virtual void handle_interrupt(const RegisterState& regs) override; + virtual bool handle_interrupt(const RegisterState& regs) override; void register_handler(GenericInterruptHandler&); void unregister_handler(GenericInterruptHandler&); diff --git a/Kernel/Interrupts/SpuriousInterruptHandler.cpp b/Kernel/Interrupts/SpuriousInterruptHandler.cpp index c032f44b3c2969..979a157fa5a8fa 100644 --- a/Kernel/Interrupts/SpuriousInterruptHandler.cpp +++ b/Kernel/Interrupts/SpuriousInterruptHandler.cpp @@ -54,16 +54,19 @@ SpuriousInterruptHandler::~SpuriousInterruptHandler() { } -void SpuriousInterruptHandler::handle_interrupt(const RegisterState& state) +bool SpuriousInterruptHandler::handle_interrupt(const RegisterState& state) { // Actually check if IRQ7 or IRQ15 are spurious, and if not, call the real handler to handle the IRQ. if (m_responsible_irq_controller->get_isr() & (1 << interrupt_number())) { m_real_irq = true; // remember that we had a real IRQ, when EOI later! - m_real_handler->increment_invoking_counter(); - m_real_handler->handle_interrupt(state); - return; + if (m_real_handler->handle_interrupt(state)) { + m_real_handler->increment_invoking_counter(); + return true; + } + return false; } dbgln("Spurious interrupt, vector {}", interrupt_number()); + return true; } void SpuriousInterruptHandler::enable_interrupt_vector() diff --git a/Kernel/Interrupts/SpuriousInterruptHandler.h b/Kernel/Interrupts/SpuriousInterruptHandler.h index a4d35f787516ae..af9648e391fc4d 100644 --- a/Kernel/Interrupts/SpuriousInterruptHandler.h +++ b/Kernel/Interrupts/SpuriousInterruptHandler.h @@ -18,7 +18,7 @@ class SpuriousInterruptHandler final : public GenericInterruptHandler { public: static void initialize(u8 interrupt_number); virtual ~SpuriousInterruptHandler(); - virtual void handle_interrupt(const RegisterState& regs) override; + virtual bool handle_interrupt(const RegisterState& regs) override; void register_handler(GenericInterruptHandler&); void unregister_handler(GenericInterruptHandler&); diff --git a/Kernel/Interrupts/UnhandledInterruptHandler.cpp b/Kernel/Interrupts/UnhandledInterruptHandler.cpp index baae02560041cc..b899a5223712db 100644 --- a/Kernel/Interrupts/UnhandledInterruptHandler.cpp +++ b/Kernel/Interrupts/UnhandledInterruptHandler.cpp @@ -13,7 +13,7 @@ UnhandledInterruptHandler::UnhandledInterruptHandler(u8 interrupt_vector) { } -void UnhandledInterruptHandler::handle_interrupt(const RegisterState&) +bool UnhandledInterruptHandler::handle_interrupt(const RegisterState&) { PANIC("Interrupt: Unhandled vector {} was invoked for handle_interrupt(RegisterState&).", interrupt_number()); } diff --git a/Kernel/Interrupts/UnhandledInterruptHandler.h b/Kernel/Interrupts/UnhandledInterruptHandler.h index f016b628b51430..8e1c33577b6cd0 100644 --- a/Kernel/Interrupts/UnhandledInterruptHandler.h +++ b/Kernel/Interrupts/UnhandledInterruptHandler.h @@ -17,7 +17,7 @@ class UnhandledInterruptHandler final : public GenericInterruptHandler { explicit UnhandledInterruptHandler(u8 interrupt_vector); virtual ~UnhandledInterruptHandler(); - virtual void handle_interrupt(const RegisterState&) override; + virtual bool handle_interrupt(const RegisterState&) override; [[noreturn]] virtual bool eoi() override; diff --git a/Kernel/Net/E1000NetworkAdapter.cpp b/Kernel/Net/E1000NetworkAdapter.cpp index ce2a72d568ac07..e51cd6878d60e9 100644 --- a/Kernel/Net/E1000NetworkAdapter.cpp +++ b/Kernel/Net/E1000NetworkAdapter.cpp @@ -230,12 +230,15 @@ UNMAP_AFTER_INIT E1000NetworkAdapter::~E1000NetworkAdapter() { } -void E1000NetworkAdapter::handle_irq(const RegisterState&) +bool E1000NetworkAdapter::handle_irq(const RegisterState&) { u32 status = in32(REG_INTERRUPT_CAUSE_READ); m_entropy_source.add_random_event(status); + if (status == 0) + return false; + if (status & INTERRUPT_LSC) { u32 flags = in32(REG_CTRL); out32(REG_CTRL, flags | ECTRL_SLU); @@ -253,6 +256,7 @@ void E1000NetworkAdapter::handle_irq(const RegisterState&) m_wait_queue.wake_all(); out32(REG_INTERRUPT_CAUSE_READ, 0xffffffff); + return true; } UNMAP_AFTER_INIT void E1000NetworkAdapter::detect_eeprom() diff --git a/Kernel/Net/E1000NetworkAdapter.h b/Kernel/Net/E1000NetworkAdapter.h index 21389fc4125a60..b2533f79953e0f 100644 --- a/Kernel/Net/E1000NetworkAdapter.h +++ b/Kernel/Net/E1000NetworkAdapter.h @@ -36,7 +36,7 @@ class E1000NetworkAdapter : public NetworkAdapter void setup_link(); E1000NetworkAdapter(PCI::Address, u8 irq); - virtual void handle_irq(const RegisterState&) override; + virtual bool handle_irq(const RegisterState&) override; virtual const char* class_name() const override { return "E1000NetworkAdapter"; } struct [[gnu::packed]] e1000_rx_desc { diff --git a/Kernel/Net/NE2000NetworkAdapter.cpp b/Kernel/Net/NE2000NetworkAdapter.cpp index 9c542579e77b5c..596882825bbac7 100644 --- a/Kernel/Net/NE2000NetworkAdapter.cpp +++ b/Kernel/Net/NE2000NetworkAdapter.cpp @@ -184,10 +184,13 @@ UNMAP_AFTER_INIT NE2000NetworkAdapter::~NE2000NetworkAdapter() { } -void NE2000NetworkAdapter::handle_irq(const RegisterState&) +bool NE2000NetworkAdapter::handle_irq(const RegisterState&) { u8 status = in8(REG_RW_INTERRUPTSTATUS); dbgln_if(NE2000_DEBUG, "NE2000NetworkAdapter: Got interrupt, status={:#02x}", status); + if (status == 0) { + return false; + } if (status & BIT_INTERRUPTMASK_PRX) { dbgln_if(NE2000_DEBUG, "NE2000NetworkAdapter: Interrupt for packet received"); @@ -223,6 +226,7 @@ void NE2000NetworkAdapter::handle_irq(const RegisterState&) m_wait_queue.wake_all(); out8(REG_RW_INTERRUPTSTATUS, status); + return true; } UNMAP_AFTER_INIT int NE2000NetworkAdapter::ram_test() diff --git a/Kernel/Net/NE2000NetworkAdapter.h b/Kernel/Net/NE2000NetworkAdapter.h index 2bab3cc0edd9b5..e923707bb7bf77 100644 --- a/Kernel/Net/NE2000NetworkAdapter.h +++ b/Kernel/Net/NE2000NetworkAdapter.h @@ -29,7 +29,7 @@ class NE2000NetworkAdapter final : public NetworkAdapter private: NE2000NetworkAdapter(PCI::Address, u8 irq); - virtual void handle_irq(const RegisterState&) override; + virtual bool handle_irq(const RegisterState&) override; virtual const char* class_name() const override { return "NE2000NetworkAdapter"; } int ram_test(); diff --git a/Kernel/Net/RTL8139NetworkAdapter.cpp b/Kernel/Net/RTL8139NetworkAdapter.cpp index e78bd931808821..a5a655467c58c5 100644 --- a/Kernel/Net/RTL8139NetworkAdapter.cpp +++ b/Kernel/Net/RTL8139NetworkAdapter.cpp @@ -155,8 +155,9 @@ UNMAP_AFTER_INIT RTL8139NetworkAdapter::~RTL8139NetworkAdapter() { } -void RTL8139NetworkAdapter::handle_irq(const RegisterState&) +bool RTL8139NetworkAdapter::handle_irq(const RegisterState&) { + bool was_handled = false; for (;;) { int status = in16(REG_ISR); out16(REG_ISR, status); @@ -168,6 +169,7 @@ void RTL8139NetworkAdapter::handle_irq(const RegisterState&) if ((status & (INT_RXOK | INT_RXERR | INT_TXOK | INT_TXERR | INT_RX_BUFFER_OVERFLOW | INT_LINK_CHANGE | INT_RX_FIFO_OVERFLOW | INT_LENGTH_CHANGE | INT_SYSTEM_ERROR)) == 0) break; + was_handled = true; if (status & INT_RXOK) { dbgln_if(RTL8139_DEBUG, "RTL8139: RX ready"); receive(); @@ -201,6 +203,7 @@ void RTL8139NetworkAdapter::handle_irq(const RegisterState&) reset(); } } + return was_handled; } void RTL8139NetworkAdapter::reset() diff --git a/Kernel/Net/RTL8139NetworkAdapter.h b/Kernel/Net/RTL8139NetworkAdapter.h index b04ec65d1f6639..751c8e52340955 100644 --- a/Kernel/Net/RTL8139NetworkAdapter.h +++ b/Kernel/Net/RTL8139NetworkAdapter.h @@ -31,7 +31,7 @@ class RTL8139NetworkAdapter final : public NetworkAdapter private: RTL8139NetworkAdapter(PCI::Address, u8 irq); - virtual void handle_irq(const RegisterState&) override; + virtual bool handle_irq(const RegisterState&) override; virtual const char* class_name() const override { return "RTL8139NetworkAdapter"; } void reset(); diff --git a/Kernel/Net/RTL8168NetworkAdapter.cpp b/Kernel/Net/RTL8168NetworkAdapter.cpp index 3432ad74033240..ae3aebe86e4884 100644 --- a/Kernel/Net/RTL8168NetworkAdapter.cpp +++ b/Kernel/Net/RTL8168NetworkAdapter.cpp @@ -1073,8 +1073,9 @@ UNMAP_AFTER_INIT RTL8168NetworkAdapter::~RTL8168NetworkAdapter() { } -void RTL8168NetworkAdapter::handle_irq(const RegisterState&) +bool RTL8168NetworkAdapter::handle_irq(const RegisterState&) { + bool was_handled = false; for (;;) { int status = in16(REG_ISR); out16(REG_ISR, status); @@ -1086,6 +1087,7 @@ void RTL8168NetworkAdapter::handle_irq(const RegisterState&) if ((status & (INT_RXOK | INT_RXERR | INT_TXOK | INT_TXERR | INT_RX_OVERFLOW | INT_LINK_CHANGE | INT_RX_FIFO_OVERFLOW | INT_SYS_ERR)) == 0) break; + was_handled = true; if (status & INT_RXOK) { dbgln_if(RTL8168_DEBUG, "RTL8168: RX ready"); receive(); @@ -1116,6 +1118,7 @@ void RTL8168NetworkAdapter::handle_irq(const RegisterState&) dmesgln("RTL8168: Fatal system error"); } } + return was_handled; } void RTL8168NetworkAdapter::reset() diff --git a/Kernel/Net/RTL8168NetworkAdapter.h b/Kernel/Net/RTL8168NetworkAdapter.h index c8f7c04e15866c..24d093bb4e5ce3 100644 --- a/Kernel/Net/RTL8168NetworkAdapter.h +++ b/Kernel/Net/RTL8168NetworkAdapter.h @@ -36,7 +36,7 @@ class RTL8168NetworkAdapter final : public NetworkAdapter RTL8168NetworkAdapter(PCI::Address, u8 irq); - virtual void handle_irq(const RegisterState&) override; + virtual bool handle_irq(const RegisterState&) override; virtual const char* class_name() const override { return "RTL8168NetworkAdapter"; } struct [[gnu::packed]] TXDescriptor { diff --git a/Kernel/Storage/AHCI.h b/Kernel/Storage/AHCI.h index d014aa0ecdc270..b0ae6da88a4747 100644 --- a/Kernel/Storage/AHCI.h +++ b/Kernel/Storage/AHCI.h @@ -158,6 +158,11 @@ class MaskedBitField { return m_bitfield & ((1 << port_index) & m_bit_mask); } + bool is_zeroed() const + { + return (m_bitfield & m_bit_mask) == 0; + } + Vector to_vector() const { // FIXME: Add a sync mechanism! diff --git a/Kernel/Storage/AHCIPortHandler.cpp b/Kernel/Storage/AHCIPortHandler.cpp index e3dcaa9bcf9c75..1dc74190b94b4b 100644 --- a/Kernel/Storage/AHCIPortHandler.cpp +++ b/Kernel/Storage/AHCIPortHandler.cpp @@ -82,9 +82,11 @@ AHCIPortHandler::~AHCIPortHandler() { } -void AHCIPortHandler::handle_irq(const RegisterState&) +bool AHCIPortHandler::handle_irq(const RegisterState&) { dbgln_if(AHCI_DEBUG, "AHCI Port Handler: IRQ received"); + if (m_pending_ports_interrupts.is_zeroed()) + return false; for (auto port_index : m_pending_ports_interrupts.to_vector()) { auto port = m_handled_ports.get(port_index); VERIFY(port.has_value()); @@ -93,6 +95,7 @@ void AHCIPortHandler::handle_irq(const RegisterState&) // We do this to clear the pending interrupt after we handled it. m_pending_ports_interrupts.set_at(port_index); } + return true; } } diff --git a/Kernel/Storage/AHCIPortHandler.h b/Kernel/Storage/AHCIPortHandler.h index 0a7578d9afd9e7..48673b39479ad9 100644 --- a/Kernel/Storage/AHCIPortHandler.h +++ b/Kernel/Storage/AHCIPortHandler.h @@ -48,7 +48,7 @@ class AHCIPortHandler final : public RefCounted UNMAP_AFTER_INIT AHCIPortHandler(AHCIController&, u8 irq, AHCI::MaskedBitField taken_ports); //^ IRQHandler - virtual void handle_irq(const RegisterState&) override; + virtual bool handle_irq(const RegisterState&) override; enum class Direction : u8 { Read, diff --git a/Kernel/Storage/BMIDEChannel.cpp b/Kernel/Storage/BMIDEChannel.cpp index 62c3654700ca13..b1e9c34a4521df 100644 --- a/Kernel/Storage/BMIDEChannel.cpp +++ b/Kernel/Storage/BMIDEChannel.cpp @@ -63,7 +63,7 @@ static void print_ide_status(u8 status) (status & ATA_SR_ERR) != 0); } -void BMIDEChannel::handle_irq(const RegisterState&) +bool BMIDEChannel::handle_irq(const RegisterState&) { u8 status = m_io_group.io_base().offset(ATA_REG_STATUS).in(); @@ -74,7 +74,7 @@ void BMIDEChannel::handle_irq(const RegisterState&) if (!(bstatus & 0x4)) { // interrupt not from this device, ignore dbgln_if(PATA_DEBUG, "BMIDEChannel: ignore interrupt"); - return; + return false; } // clear bus master interrupt status m_io_group.bus_master_base().value().offset(2).out(m_io_group.bus_master_base().value().offset(2).in() | 4); @@ -87,7 +87,7 @@ void BMIDEChannel::handle_irq(const RegisterState&) if (!m_current_request) { dbgln("BMIDEChannel: IRQ but no pending request!"); - return; + return false; } if (status & ATA_SR_ERR) { @@ -96,10 +96,11 @@ void BMIDEChannel::handle_irq(const RegisterState&) dbgln("BMIDEChannel: Error {:#02x}!", (u8)m_device_error); try_disambiguate_error(); complete_current_request(AsyncDeviceRequest::Failure); - return; + return true; } m_device_error = 0; complete_current_request(AsyncDeviceRequest::Success); + return true; } void BMIDEChannel::complete_current_request(AsyncDeviceRequest::RequestResult result) diff --git a/Kernel/Storage/BMIDEChannel.h b/Kernel/Storage/BMIDEChannel.h index 02dd63e5afb76c..2a8309dbdf65f2 100644 --- a/Kernel/Storage/BMIDEChannel.h +++ b/Kernel/Storage/BMIDEChannel.h @@ -39,7 +39,7 @@ class BMIDEChannel final : public IDEChannel { void complete_current_request(AsyncDeviceRequest::RequestResult); //^ IRQHandler - virtual void handle_irq(const RegisterState&) override; + virtual bool handle_irq(const RegisterState&) override; //* IDEChannel virtual void send_ata_io_command(LBAMode lba_mode, Direction direction) const; diff --git a/Kernel/Storage/IDEChannel.cpp b/Kernel/Storage/IDEChannel.cpp index 5b5a54da33d597..6239f7c83431e8 100644 --- a/Kernel/Storage/IDEChannel.cpp +++ b/Kernel/Storage/IDEChannel.cpp @@ -190,7 +190,7 @@ void IDEChannel::try_disambiguate_error() } } -void IDEChannel::handle_irq(const RegisterState&) +bool IDEChannel::handle_irq(const RegisterState&) { u8 status = m_io_group.io_base().offset(ATA_REG_STATUS).in(); @@ -204,7 +204,7 @@ void IDEChannel::handle_irq(const RegisterState&) if (!m_current_request) { dbgln("IDEChannel: IRQ but no pending request!"); - return; + return false; } if (status & ATA_SR_ERR) { @@ -213,7 +213,7 @@ void IDEChannel::handle_irq(const RegisterState&) dbgln("IDEChannel: Error {:#02x}!", (u8)m_device_error); try_disambiguate_error(); complete_current_request(AsyncDeviceRequest::Failure); - return; + return true; } m_device_error = 0; @@ -251,6 +251,7 @@ void IDEChannel::handle_irq(const RegisterState&) } } }); + return true; } static void io_delay() diff --git a/Kernel/Storage/IDEChannel.h b/Kernel/Storage/IDEChannel.h index 610ae47ef0e37c..5c64cf32ba75e8 100644 --- a/Kernel/Storage/IDEChannel.h +++ b/Kernel/Storage/IDEChannel.h @@ -122,7 +122,7 @@ class IDEChannel : public RefCounted IDEChannel(const IDEController&, IOAddressGroup, ChannelType type); IDEChannel(const IDEController&, u8 irq, IOAddressGroup, ChannelType type); //^ IRQHandler - virtual void handle_irq(const RegisterState&) override; + virtual bool handle_irq(const RegisterState&) override; virtual void send_ata_io_command(LBAMode lba_mode, Direction direction) const; diff --git a/Kernel/Time/HPETComparator.cpp b/Kernel/Time/HPETComparator.cpp index 8292719c31b1a6..6f2aab6c17ef7b 100644 --- a/Kernel/Time/HPETComparator.cpp +++ b/Kernel/Time/HPETComparator.cpp @@ -51,11 +51,12 @@ void HPETComparator::set_non_periodic() HPET::the().disable_periodic_interrupt(*this); } -void HPETComparator::handle_irq(const RegisterState& regs) +bool HPETComparator::handle_irq(const RegisterState& regs) { - HardwareTimer::handle_irq(regs); + auto result = HardwareTimer::handle_irq(regs); if (!is_periodic()) set_new_countdown(); + return result; } void HPETComparator::set_new_countdown() diff --git a/Kernel/Time/HPETComparator.h b/Kernel/Time/HPETComparator.h index 5fa0d0cdd150a4..9d2bd5e14112cf 100644 --- a/Kernel/Time/HPETComparator.h +++ b/Kernel/Time/HPETComparator.h @@ -43,7 +43,7 @@ class HPETComparator final : public HardwareTimer { private: void set_new_countdown(); - virtual void handle_irq(const RegisterState&) override; + virtual bool handle_irq(const RegisterState&) override; HPETComparator(u8 number, u8 irq, bool periodic_capable, bool is_64bit_capable); bool m_periodic : 1; bool m_periodic_capable : 1; diff --git a/Kernel/Time/HardwareTimer.h b/Kernel/Time/HardwareTimer.h index b442d377f871c8..ce555075e35e31 100644 --- a/Kernel/Time/HardwareTimer.h +++ b/Kernel/Time/HardwareTimer.h @@ -92,10 +92,14 @@ class HardwareTimer { } - virtual void handle_irq(const RegisterState& regs) override + virtual bool handle_irq(const RegisterState& regs) override { - if (m_callback) + // Note: if we have an IRQ on this line, it's going to be the timer always + if (m_callback) { m_callback(regs); + return true; + } + return false; } u64 m_frequency { OPTIMAL_TICKS_PER_SECOND_RATE }; @@ -142,10 +146,14 @@ class HardwareTimer { } - virtual void handle_interrupt(const RegisterState& regs) override + virtual bool handle_interrupt(const RegisterState& regs) override { - if (m_callback) + // Note: if we have an IRQ on this line, it's going to be the timer always + if (m_callback) { m_callback(regs); + return true; + } + return false; } u64 m_frequency { OPTIMAL_TICKS_PER_SECOND_RATE }; diff --git a/Kernel/Time/RTC.cpp b/Kernel/Time/RTC.cpp index 31c1f09e02009c..d2052b501d00dc 100644 --- a/Kernel/Time/RTC.cpp +++ b/Kernel/Time/RTC.cpp @@ -27,10 +27,11 @@ RealTimeClock::RealTimeClock(Function callback) CMOS::write(0x8B, CMOS::read(0xB) | 0x40); reset_to_default_ticks_per_second(); } -void RealTimeClock::handle_irq(const RegisterState& regs) +bool RealTimeClock::handle_irq(const RegisterState& regs) { - HardwareTimer::handle_irq(regs); + auto result = HardwareTimer::handle_irq(regs); CMOS::read(0x8C); + return result; } size_t RealTimeClock::ticks_per_second() const diff --git a/Kernel/Time/RTC.h b/Kernel/Time/RTC.h index 1005ae7109ac74..748f8e28a16ef6 100644 --- a/Kernel/Time/RTC.h +++ b/Kernel/Time/RTC.h @@ -31,6 +31,6 @@ class RealTimeClock final : public HardwareTimer { private: explicit RealTimeClock(Function callback); - virtual void handle_irq(const RegisterState&) override; + virtual bool handle_irq(const RegisterState&) override; }; } diff --git a/Kernel/VirtIO/VirtIO.cpp b/Kernel/VirtIO/VirtIO.cpp index fcc20071fdc014..ba6b95f1a61395 100644 --- a/Kernel/VirtIO/VirtIO.cpp +++ b/Kernel/VirtIO/VirtIO.cpp @@ -342,11 +342,13 @@ u8 VirtIODevice::isr_status() return config_read8(*m_isr_cfg, 0); } -void VirtIODevice::handle_irq(const RegisterState&) +bool VirtIODevice::handle_irq(const RegisterState&) { u8 isr_type = isr_status(); - if ((isr_type & (QUEUE_INTERRUPT | DEVICE_CONFIG_INTERRUPT)) == 0) + if ((isr_type & (QUEUE_INTERRUPT | DEVICE_CONFIG_INTERRUPT)) == 0) { dbgln_if(VIRTIO_DEBUG, "{}: Handling interrupt with unknown type: {}", m_class_name, isr_type); + return false; + } if (isr_type & DEVICE_CONFIG_INTERRUPT) { dbgln_if(VIRTIO_DEBUG, "{}: VirtIO Device config interrupt!", m_class_name); if (!handle_device_config_change()) { @@ -357,11 +359,14 @@ void VirtIODevice::handle_irq(const RegisterState&) if (isr_type & QUEUE_INTERRUPT) { dbgln_if(VIRTIO_DEBUG, "{}: VirtIO Queue interrupt!", m_class_name); for (size_t i = 0; i < m_queues.size(); i++) { - if (get_queue(i).new_data_available()) - return handle_queue_update(i); + if (get_queue(i).new_data_available()) { + handle_queue_update(i); + return true; + } } dbgln_if(VIRTIO_DEBUG, "{}: Got queue interrupt but all queues are up to date!", m_class_name); } + return true; } void VirtIODevice::supply_chain_and_notify(u16 queue_index, VirtIOQueueChain& chain) diff --git a/Kernel/VirtIO/VirtIO.h b/Kernel/VirtIO/VirtIO.h index 9fe71637a7c940..9b49926722946e 100644 --- a/Kernel/VirtIO/VirtIO.h +++ b/Kernel/VirtIO/VirtIO.h @@ -222,7 +222,7 @@ class VirtIODevice : public PCI::Device { void reset_device(); u8 isr_status(); - virtual void handle_irq(const RegisterState&) override; + virtual bool handle_irq(const RegisterState&) override; NonnullOwnPtrVector m_queues; NonnullOwnPtrVector m_configs;