diff --git a/Kernel/InterruptHandler.cpp b/Kernel/InterruptHandler.cpp new file mode 100644 index 0000000000..0d30ce94d1 --- /dev/null +++ b/Kernel/InterruptHandler.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2020, Liav A. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +InterruptHandler::InterruptHandler(u8 irq) + : m_irq_number(irq) +{ + SharedInterruptHandler::from(m_irq_number).register_handler(*this); + disable_interrupts(); +} + +InterruptHandler::~InterruptHandler() +{ + disable_interrupts(); + SharedInterruptHandler::from(m_irq_number).unregister_handler(*this); +} + +void InterruptHandler::enable_interrupts() +{ + m_enabled = true; +} + +void InterruptHandler::change_irq_number(u8 irq_number) +{ + bool was_enabled = m_enabled; + disable_interrupts(); + SharedInterruptHandler::from(m_irq_number).unregister_handler(*this); + m_irq_number = irq_number; + SharedInterruptHandler::from(m_irq_number).register_handler(*this); + if (was_enabled) + enable_interrupts(); +} + +void InterruptHandler::disable_interrupts() +{ + m_enabled = false; +} + +InterruptHandler::Enabler::Enabler(InterruptHandler& handler) + : m_handler(handler) + , m_was_enabled(m_handler.is_enabled()) +{ + m_handler.enable_interrupts(); +} +InterruptHandler::Enabler::~Enabler() +{ + if (!m_was_enabled) + m_handler.disable_interrupts(); +} diff --git a/Kernel/InterruptHandler.h b/Kernel/InterruptHandler.h new file mode 100644 index 0000000000..45e20b92a8 --- /dev/null +++ b/Kernel/InterruptHandler.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2020, Liav A. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include + +class InterruptHandler { +public: + class Enabler { + public: + explicit Enabler(InterruptHandler&); + ~Enabler(); + + private: + InterruptHandler& m_handler; + bool m_was_enabled; + }; + friend class Enabler; + +public: + virtual ~InterruptHandler(); + virtual void handle_interrupt() = 0; + + u8 irq_number() const { return m_irq_number; } + bool is_enabled() const { return m_enabled; } + +protected: + void enable_interrupts(); + void change_irq_number(u8 irq_number); + void disable_interrupts(); + explicit InterruptHandler(u8 irq); + +private: + bool m_enabled { false }; + u8 m_irq_number { 0 }; +}; diff --git a/Kernel/PCI/Definitions.h b/Kernel/PCI/Definitions.h index d3dcf49d74..76344d77e2 100644 --- a/Kernel/PCI/Definitions.h +++ b/Kernel/PCI/Definitions.h @@ -178,5 +178,6 @@ class Access; class MMIOAccess; class IOAccess; class MMIOSegment; +class Device; } diff --git a/Kernel/PCI/Device.cpp b/Kernel/PCI/Device.cpp new file mode 100644 index 0000000000..4a8e096b7a --- /dev/null +++ b/Kernel/PCI/Device.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2020, Liav A. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +PCI::Device::Device(PCI::Address address) + : InterruptHandler(PCI::get_interrupt_line(address)) + , m_pci_address(address) +{ + // FIXME: Register PCI device somewhere... +} + +PCI::Device::Device(PCI::Address address, u8 interrupt_vector) + : InterruptHandler(interrupt_vector) + , m_pci_address(address) +{ + // FIXME: Register PCI device somewhere... +} + +PCI::Device::~Device() +{ + // FIXME: Unregister the device +} diff --git a/Kernel/PCI/Device.h b/Kernel/PCI/Device.h new file mode 100644 index 0000000000..edcc435407 --- /dev/null +++ b/Kernel/PCI/Device.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2020, Liav A. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include +#include +#include + +class PCI::Device : public InterruptHandler { +public: + Address get_pci_address() const { return m_pci_address; }; + +protected: + Device(Address pci_address); + Device(Address pci_address, u8 interrupt_vector); + ~Device(); + +private: + Address m_pci_address; +}; diff --git a/Kernel/SharedInterruptHandler.cpp b/Kernel/SharedInterruptHandler.cpp new file mode 100644 index 0000000000..b1f91ad523 --- /dev/null +++ b/Kernel/SharedInterruptHandler.cpp @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2020, Liav A. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + +//#define INTERRUPT_DEBUG + +SharedInterruptHandler& SharedInterruptHandler::from(u8 interrupt_number) +{ + return get_interrupt_handler(interrupt_number); +} + +void SharedInterruptHandler::initialize(u8 interrupt_number) +{ + new SharedInterruptHandler(interrupt_number); +} + +void SharedInterruptHandler::register_handler(InterruptHandler& handler) +{ +#ifdef INTERRUPT_DEBUG + kprintf("Interrupt Handler registered @ Shared Interrupt Handler %d\n", m_interrupt_number); +#endif + m_handlers.set(&handler); + enable_interrupt_vector(); +} +void SharedInterruptHandler::unregister_handler(InterruptHandler& handler) +{ +#ifdef INTERRUPT_DEBUG + kprintf("Interrupt Handler unregistered @ Shared Interrupt Handler %d\n", m_interrupt_number); +#endif + m_handlers.remove(&handler); + if (m_handlers.is_empty()) + disable_interrupt_vector(); +} + +SharedInterruptHandler::SharedInterruptHandler(u8 interrupt_number) + : m_interrupt_number(interrupt_number) + , m_enabled(true) +{ +#ifdef INTERRUPT_DEBUG + kprintf("Shared Interrupt Handler registered @ %d\n", m_interrupt_number); +#endif + register_shared_interrupt_handler(m_interrupt_number, *this); + disable_interrupt_vector(); +} + +SharedInterruptHandler::~SharedInterruptHandler() +{ +#ifdef INTERRUPT_DEBUG + kprintf("Shared Interrupt Handler unregistered @ %d\n", m_interrupt_number); +#endif + disable_interrupt_vector(); + unregister_shared_interrupt_handler(m_interrupt_number, *this); +} + +void SharedInterruptHandler::handle_interrupt() +{ +#ifdef INTERRUPT_DEBUG + kprintf("Interrupt @ %d\n", m_interrupt_number); + kprintf("Interrupt Handlers registered - %d\n", m_handlers.size()); +#endif + int i = 0; + for (auto* handler : m_handlers) { +#ifdef INTERRUPT_DEBUG + kprintf("Going for Interrupt Handling @ %d, Shared Interrupt %d\n", i, m_interrupt_number); +#endif + ASSERT(handler != nullptr); + if (handler->is_enabled()) + handler->handle_interrupt(); + +#ifdef INTERRUPT_DEBUG + kprintf("Going for Interrupt Handling @ %d, Shared Interrupt %d - End\n", i, m_interrupt_number); +#endif + i++; + } + // FIXME: Determine if we use IRQs or MSIs (in the future) to send EOI... +} + +void SharedInterruptHandler::enable_interrupt_vector() +{ + if (m_enabled) + return; + m_enabled = true; + // FIXME: Determine if we use IRQs or MSIs (in the future) to enable the interrupt vector... + PIC::enable(m_interrupt_number); +} + +void SharedInterruptHandler::disable_interrupt_vector() +{ + if (!m_enabled) + return; + m_enabled = false; + // FIXME: Determine if we use IRQs or MSIs (in the future) to disable the interrupt vector... + PIC::disable(m_interrupt_number); +} diff --git a/Kernel/SharedInterruptHandler.h b/Kernel/SharedInterruptHandler.h new file mode 100644 index 0000000000..701147c5c6 --- /dev/null +++ b/Kernel/SharedInterruptHandler.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2020, Liav A. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include +#include +#include + +class InterruptHandler; +class SharedInterruptHandler final { +public: + static void initialize(u8 interrupt_number); + static SharedInterruptHandler& from(u8 interrupt_number); + ~SharedInterruptHandler(); + void handle_interrupt(); + + u8 interrupt_number() const { return m_interrupt_number; } + + void register_handler(InterruptHandler&); + void unregister_handler(InterruptHandler&); + +private: + void enable_interrupt_vector(); + void disable_interrupt_vector(); + explicit SharedInterruptHandler(u8 interrupt_number); + HashTable m_handlers; + u8 m_interrupt_number { 0 }; + bool m_enabled { false }; +};