From 6c72736b26a81a8f03d8dd47989bfffe26bb1c95 Mon Sep 17 00:00:00 2001 From: Liav A Date: Tue, 21 Jan 2020 13:23:03 +0200 Subject: [PATCH] Kernel: Replace IRQHandler with the new InterruptHandler class System components that need an IRQ handling are now inheriting the InterruptHandler class. In addition to that, the initialization process of PATAChannel was changed to fit the changes. PATAChannel, E1000NetworkAdapter and RTL8139NetworkAdapter are now inheriting from PCI::Device instead of InterruptHandler directly. --- Kernel/ACPI/ACPIDynamicParser.cpp | 8 ++-- Kernel/ACPI/ACPIDynamicParser.h | 8 ++-- Kernel/Arch/i386/CPU.cpp | 24 +++++++---- Kernel/Arch/i386/CPU.h | 7 ++-- Kernel/Arch/i386/PIC.cpp | 14 +++++++ Kernel/Arch/i386/PIC.h | 1 + Kernel/Devices/BlockDevice.h | 3 +- Kernel/Devices/CharacterDevice.h | 2 +- Kernel/Devices/Device.cpp | 34 ++++----------- Kernel/Devices/Device.h | 12 ++++-- Kernel/Devices/FloppyDiskDevice.cpp | 14 +++---- Kernel/Devices/FloppyDiskDevice.h | 6 +-- .../HardwareEventsManager.cpp} | 41 +++++++++++++------ .../HardwareEventsManager.h} | 24 +++++------ Kernel/Devices/KeyboardDevice.cpp | 6 +-- Kernel/Devices/KeyboardDevice.h | 6 +-- Kernel/Devices/PATAChannel.cpp | 34 +++++++-------- Kernel/Devices/PATAChannel.h | 12 +++--- Kernel/Devices/PATADiskDevice.h | 2 +- Kernel/Devices/PS2MouseDevice.cpp | 6 +-- Kernel/Devices/PS2MouseDevice.h | 6 +-- Kernel/Devices/SB16.cpp | 9 ++-- Kernel/Devices/SB16.h | 6 +-- Kernel/Makefile | 5 ++- Kernel/Net/E1000NetworkAdapter.cpp | 25 ++++++----- Kernel/Net/E1000NetworkAdapter.h | 9 ++-- Kernel/Net/RTL8139NetworkAdapter.cpp | 15 ++++--- Kernel/Net/RTL8139NetworkAdapter.h | 9 ++-- Kernel/init.cpp | 14 +++---- 29 files changed, 193 insertions(+), 169 deletions(-) rename Kernel/{IRQHandler.cpp => Devices/HardwareEventsManager.cpp} (57%) rename Kernel/{IRQHandler.h => Devices/HardwareEventsManager.h} (76%) diff --git a/Kernel/ACPI/ACPIDynamicParser.cpp b/Kernel/ACPI/ACPIDynamicParser.cpp index 52084e7e945..2a2a75744a9 100644 --- a/Kernel/ACPI/ACPIDynamicParser.cpp +++ b/Kernel/ACPI/ACPIDynamicParser.cpp @@ -41,20 +41,20 @@ void ACPIDynamicParser::initialize_without_rsdp() } ACPIDynamicParser::ACPIDynamicParser() - : IRQHandler(9) + : InterruptHandler(9) , ACPIStaticParser() { kprintf("ACPI: Dynamic Parsing Enabled, Can parse AML\n"); } ACPIDynamicParser::ACPIDynamicParser(ACPI_RAW::RSDPDescriptor20& rsdp) - : IRQHandler(9) + : InterruptHandler(9) , ACPIStaticParser(rsdp) { kprintf("ACPI: Dynamic Parsing Enabled, Can parse AML\n"); } -void ACPIDynamicParser::handle_irq() +void ACPIDynamicParser::handle_interrupt() { // FIXME: Implement IRQ handling of ACPI signals! ASSERT_NOT_REACHED(); @@ -90,4 +90,4 @@ void ACPIDynamicParser::build_namespace() { // FIXME: Implement AML Interpretation to build the ACPI namespace ASSERT_NOT_REACHED(); -} \ No newline at end of file +} diff --git a/Kernel/ACPI/ACPIDynamicParser.h b/Kernel/ACPI/ACPIDynamicParser.h index eb87f18fc83..a4dee415fc9 100644 --- a/Kernel/ACPI/ACPIDynamicParser.h +++ b/Kernel/ACPI/ACPIDynamicParser.h @@ -29,12 +29,12 @@ #include #include #include -#include +#include #include #include #include -class ACPIDynamicParser final : public IRQHandler +class ACPIDynamicParser final : public InterruptHandler , ACPIStaticParser { public: static void initialize(ACPI_RAW::RSDPDescriptor20& rsdp); @@ -53,7 +53,7 @@ protected: private: void build_namespace(); // ^IRQHandler - virtual void handle_irq() override; + virtual void handle_interrupt() override; OwnPtr m_acpi_namespace; -}; \ No newline at end of file +}; diff --git a/Kernel/Arch/i386/CPU.cpp b/Kernel/Arch/i386/CPU.cpp index d1ef90e6a44..56d9aaf8d87 100644 --- a/Kernel/Arch/i386/CPU.cpp +++ b/Kernel/Arch/i386/CPU.cpp @@ -26,12 +26,12 @@ #include "APIC.h" #include "Assertions.h" -#include "IRQHandler.h" #include "PIC.h" #include "Process.h" #include #include #include +#include #include #include @@ -48,7 +48,7 @@ static DescriptorTablePointer s_gdtr; static Descriptor s_idt[256]; static Descriptor s_gdt[256]; -static IRQHandler* s_irq_handler[16]; +static SharedInterruptHandler* s_irq_handler[256]; static Vector* s_gdt_freelist; @@ -435,18 +435,25 @@ static void unimp_trap() hang(); } -void register_irq_handler(u8 irq, IRQHandler& handler) +void register_shared_interrupt_handler(u8 irq, SharedInterruptHandler& handler) { ASSERT(!s_irq_handler[irq]); s_irq_handler[irq] = &handler; } -void unregister_irq_handler(u8 irq, IRQHandler& handler) +void unregister_shared_interrupt_handler(u8 irq, SharedInterruptHandler& handler) { ASSERT(s_irq_handler[irq] == &handler); s_irq_handler[irq] = nullptr; } +SharedInterruptHandler& get_interrupt_handler(u8 number) +{ + ASSERT(number < 256); + ASSERT(s_irq_handler[number] != nullptr); + return *s_irq_handler[number]; +} + void register_interrupt_handler(u8 index, void (*f)()) { s_idt[index].low = 0x00080000 | LSW((f)); @@ -524,8 +531,8 @@ void idt_init() register_interrupt_handler(0x5e, irq_14_asm_entry); register_interrupt_handler(0x5f, irq_15_asm_entry); - for (u8 i = 0; i < 16; ++i) { - s_irq_handler[i] = nullptr; + for (u8 i = 0; i < 255; ++i) { + SharedInterruptHandler::initialize(i); } flush_idt(); @@ -541,8 +548,9 @@ void handle_irq(RegisterDump regs) clac(); ASSERT(regs.isr_number >= 0x50 && regs.isr_number <= 0x5f); u8 irq = (u8)(regs.isr_number - 0x50); - if (s_irq_handler[irq]) - s_irq_handler[irq]->handle_irq(); + ASSERT(s_irq_handler[irq] != nullptr); + s_irq_handler[irq]->handle_interrupt(); + // FIXME: Determine if we use IRQs or MSIs (in the future) to send EOI... PIC::eoi(irq); } diff --git a/Kernel/Arch/i386/CPU.h b/Kernel/Arch/i386/CPU.h index 11fb73881c0..3eebbc3156f 100644 --- a/Kernel/Arch/i386/CPU.h +++ b/Kernel/Arch/i386/CPU.h @@ -240,7 +240,7 @@ public: u64 raw[4]; }; -class IRQHandler; +class SharedInterruptHandler; struct RegisterDump; void gdt_init(); @@ -248,8 +248,9 @@ void idt_init(); void sse_init(); void register_interrupt_handler(u8 number, void (*f)()); void register_user_callable_interrupt_handler(u8 number, void (*f)()); -void register_irq_handler(u8 number, IRQHandler&); -void unregister_irq_handler(u8 number, IRQHandler&); +void register_shared_interrupt_handler(u8 number, SharedInterruptHandler&); +SharedInterruptHandler& get_interrupt_handler(u8 number); +void unregister_shared_interrupt_handler(u8 number, SharedInterruptHandler&); void flush_idt(); void flush_gdt(); void load_task_register(u16 selector); diff --git a/Kernel/Arch/i386/PIC.cpp b/Kernel/Arch/i386/PIC.cpp index 2b62494b5a2..c500ef8c95d 100644 --- a/Kernel/Arch/i386/PIC.cpp +++ b/Kernel/Arch/i386/PIC.cpp @@ -75,6 +75,20 @@ void enable(u8 irq) } } +bool is_enabled(u8 irq) +{ + InterruptDisabler disabler; + u8 imr; + if (irq & 8) { + imr = IO::in8(PIC1_CMD); + imr &= (1 << (irq - 8)); + } else { + imr = IO::in8(PIC0_CMD); + imr &= (1 << irq); + } + return (!!imr); +} + void eoi(u8 irq) { if (irq & 8) diff --git a/Kernel/Arch/i386/PIC.h b/Kernel/Arch/i386/PIC.h index ecac1c31012..4746fb4a4b0 100644 --- a/Kernel/Arch/i386/PIC.h +++ b/Kernel/Arch/i386/PIC.h @@ -34,6 +34,7 @@ void enable(u8 number); void disable(u8 number); void eoi(u8 number); void initialize(); +bool is_enabled(u8 number); u16 get_isr(); u16 get_irr(); diff --git a/Kernel/Devices/BlockDevice.h b/Kernel/Devices/BlockDevice.h index fd8c2fb4955..483ca90fd9c 100644 --- a/Kernel/Devices/BlockDevice.h +++ b/Kernel/Devices/BlockDevice.h @@ -34,10 +34,9 @@ public: size_t block_size() const { return m_block_size; } virtual bool is_seekable() const override { return true; } - protected: BlockDevice(unsigned major, unsigned minor, size_t block_size = PAGE_SIZE) - : Device(major, minor) + : Device(major, minor, (u8)DEVICE_TYPE::BLOCK_DEVICE) , m_block_size(block_size) { } diff --git a/Kernel/Devices/CharacterDevice.h b/Kernel/Devices/CharacterDevice.h index 6d52eed55e8..09fd7f92e8b 100644 --- a/Kernel/Devices/CharacterDevice.h +++ b/Kernel/Devices/CharacterDevice.h @@ -34,7 +34,7 @@ public: protected: CharacterDevice(unsigned major, unsigned minor) - : Device(major, minor) + : Device(major, minor, (u8)DEVICE_TYPE::CHAR_DEVICE) { } diff --git a/Kernel/Devices/Device.cpp b/Kernel/Devices/Device.cpp index 833e9da0f32..09b1419d1c7 100644 --- a/Kernel/Devices/Device.cpp +++ b/Kernel/Devices/Device.cpp @@ -25,48 +25,32 @@ */ #include -#include +#include #include -static HashMap* s_all_devices; - -HashMap& Device::all_devices() -{ - if (s_all_devices == nullptr) - s_all_devices = new HashMap; - return *s_all_devices; -} - void Device::for_each(Function callback) { - for (auto& entry : all_devices()) - callback(*entry.value); + for (auto* entry : HardwareEventsManager::the().get_devices_list()) { + ASSERT(entry != nullptr); + callback(*entry); + } } Device* Device::get_device(unsigned major, unsigned minor) { - auto it = all_devices().find(encoded_device(major, minor)); - if (it == all_devices().end()) - return nullptr; - return it->value; + return HardwareEventsManager::the().get_device(major, minor); } -Device::Device(unsigned major, unsigned minor) +Device::Device(unsigned major, unsigned minor, u8 device_type) : m_major(major) , m_minor(minor) { - u32 device_id = encoded_device(major, minor); - auto it = all_devices().find(device_id); - if (it != all_devices().end()) { - dbg() << "Already registered " << major << "," << minor << ": " << it->value->class_name(); - } - ASSERT(!all_devices().contains(device_id)); - all_devices().set(device_id, this); + HardwareEventsManager::the().register_device(*this, device_type); } Device::~Device() { - all_devices().remove(encoded_device(m_major, m_minor)); + HardwareEventsManager::the().unregister_device(*this); } String Device::absolute_path() const diff --git a/Kernel/Devices/Device.h b/Kernel/Devices/Device.h index 2ddd7720c8d..4aadf49a9a1 100644 --- a/Kernel/Devices/Device.h +++ b/Kernel/Devices/Device.h @@ -39,6 +39,11 @@ #include #include +enum class DEVICE_TYPE { + BLOCK_DEVICE = 1, + CHAR_DEVICE = 2 +}; + class Device : public File { public: virtual ~Device() override; @@ -55,16 +60,17 @@ public: virtual bool is_device() const override { return true; } virtual bool is_disk_device() const { return false; } + virtual bool is_block_device() const override { return false; } + virtual bool is_character_device() const override { return true; } + static void for_each(Function); static Device* get_device(unsigned major, unsigned minor); protected: - Device(unsigned major, unsigned minor); + Device(unsigned major, unsigned minor, u8 device_type); void set_uid(uid_t uid) { m_uid = uid; } void set_gid(gid_t gid) { m_gid = gid; } - static HashMap& all_devices(); - private: unsigned m_major { 0 }; unsigned m_minor { 0 }; diff --git a/Kernel/Devices/FloppyDiskDevice.cpp b/Kernel/Devices/FloppyDiskDevice.cpp index 9cd38c31ab2..adee42eaa7c 100644 --- a/Kernel/Devices/FloppyDiskDevice.cpp +++ b/Kernel/Devices/FloppyDiskDevice.cpp @@ -109,7 +109,7 @@ const char* FloppyDiskDevice::class_name() const } FloppyDiskDevice::FloppyDiskDevice(FloppyDiskDevice::DriveType type) - : IRQHandler(IRQ_FLOPPY_DRIVE) + : InterruptHandler(IRQ_FLOPPY_DRIVE) , DiskDevice(89, (type == FloppyDiskDevice::DriveType::Master) ? 0 : 1, BYTES_PER_SECTOR) , m_io_base_addr((type == FloppyDiskDevice::DriveType::Master) ? 0x3F0 : 0x370) { @@ -167,7 +167,7 @@ bool FloppyDiskDevice::read_sectors_with_dma(u16 lba, u16 count, u8* outbuf) //while(start < PIT::seconds_since_boot() + 1) // ; - disable_irq(); + disable_interrupts(); IO::out8(0xA, FLOPPY_DMA_CHANNEL | 0x4); // Channel 2 SEL, MASK_ON = 1 IO::out8(0x0B, 0x56); // Begin DMA, Single Transfer, Increment, Auto, FDC -> RAM, Channel 2 @@ -195,7 +195,7 @@ bool FloppyDiskDevice::read_sectors_with_dma(u16 lba, u16 count, u8* outbuf) send_byte(0x1b); // GPL3 value. The Datasheet doesn't really specify the values for this properly... send_byte(0xff); - enable_irq(); + enable_interrupts(); wait_for_irq(); // TODO: See if there was a lockup here via some "timeout counter" m_interrupted = false; @@ -269,7 +269,7 @@ bool FloppyDiskDevice::write_sectors_with_dma(u16 lba, u16 count, const u8* inbu //while(start < PIT::seconds_since_boot() + 1) // ; - disable_irq(); + disable_interrupts(); IO::out8(0xA, FLOPPY_DMA_CHANNEL | 0x4); // Channel 2 SEL, MASK_ON = 1 IO::out8(0x0B, 0x5A); // Begin DMA, Single Transfer, Increment, Auto, RAM -> FDC, Channel 2 @@ -295,7 +295,7 @@ bool FloppyDiskDevice::write_sectors_with_dma(u16 lba, u16 count, const u8* inbu send_byte(0x1b); // GPL3 value. The Datasheet doesn't really specify the values for this properly... send_byte(0xff); - enable_irq(); + enable_interrupts(); wait_for_irq(); // TODO: See if there was a lockup here via some "timeout counter" m_interrupted = false; @@ -358,7 +358,7 @@ bool FloppyDiskDevice::wait_for_irq() return true; } -void FloppyDiskDevice::handle_irq() +void FloppyDiskDevice::handle_interrupt() { // The only thing we need to do is acknowledge the IRQ happened m_interrupted = true; @@ -512,7 +512,7 @@ void FloppyDiskDevice::initialize() kprintf("fdc: m_io_base = 0x%x IRQn = %d\n", m_io_base_addr, IRQ_FLOPPY_DRIVE); #endif - enable_irq(); + enable_interrupts(); // Get the version of the Floppy Disk Controller send_byte(FloppyCommand::Version); diff --git a/Kernel/Devices/FloppyDiskDevice.h b/Kernel/Devices/FloppyDiskDevice.h index a505bc027c2..b2349387bbd 100644 --- a/Kernel/Devices/FloppyDiskDevice.h +++ b/Kernel/Devices/FloppyDiskDevice.h @@ -101,7 +101,7 @@ #include #include -#include +#include #include #include #include @@ -122,7 +122,7 @@ struct FloppyControllerCommand { // uses the Intel 82077A controller. More about this controller can // be found here: http://www.buchty.net/casio/files/82077.pdf // -class FloppyDiskDevice final : public IRQHandler +class FloppyDiskDevice final : public InterruptHandler , public DiskDevice { AK_MAKE_ETERNAL @@ -178,7 +178,7 @@ protected: private: // ^IRQHandler - void handle_irq(); + void handle_interrupt(); // ^DiskDevice virtual const char* class_name() const override; diff --git a/Kernel/IRQHandler.cpp b/Kernel/Devices/HardwareEventsManager.cpp similarity index 57% rename from Kernel/IRQHandler.cpp rename to Kernel/Devices/HardwareEventsManager.cpp index 0a2ff3aeb52..f586ee0322b 100644 --- a/Kernel/IRQHandler.cpp +++ b/Kernel/Devices/HardwareEventsManager.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2020, Andreas Kling + * Copyright (c) 2020, Liav A. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,27 +24,42 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "IRQHandler.h" -#include -#include +#include -IRQHandler::IRQHandler(u8 irq) - : m_irq_number(irq) +static HardwareEventsManager* s_hardware_events_manager; + +HardwareEventsManager& HardwareEventsManager::the() { - register_irq_handler(m_irq_number, *this); + if (s_hardware_events_manager == nullptr) { + s_hardware_events_manager = new HardwareEventsManager(); + } + return *s_hardware_events_manager; } -IRQHandler::~IRQHandler() +HashTable& HardwareEventsManager::get_devices_list() { - unregister_irq_handler(m_irq_number, *this); + return m_devices; } -void IRQHandler::enable_irq() +void HardwareEventsManager::unregister_device(Device& device) { - PIC::enable(m_irq_number); + get_devices_list().remove(&device); } -void IRQHandler::disable_irq() +HardwareEventsManager::HardwareEventsManager() { - PIC::disable(m_irq_number); +} + +Device* HardwareEventsManager::get_device(unsigned major, unsigned minor) +{ + for (auto* entry : HardwareEventsManager::get_devices_list()) { + ASSERT(entry != nullptr); + if (entry->major() == major && entry->minor() == minor) + return entry; + } + return nullptr; +} +void HardwareEventsManager::register_device(Device& device, u8) +{ + get_devices_list().set(&device); } diff --git a/Kernel/IRQHandler.h b/Kernel/Devices/HardwareEventsManager.h similarity index 76% rename from Kernel/IRQHandler.h rename to Kernel/Devices/HardwareEventsManager.h index dbf0821704b..b8b6c1f1129 100644 --- a/Kernel/IRQHandler.h +++ b/Kernel/Devices/HardwareEventsManager.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2020, Andreas Kling + * Copyright (c) 2020, Liav A. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,20 +27,18 @@ #pragma once #include +#include -class IRQHandler { +class HardwareEventsManager { public: - virtual ~IRQHandler(); - virtual void handle_irq() = 0; - - u8 irq_number() const { return m_irq_number; } - - void enable_irq(); - void disable_irq(); - -protected: - explicit IRQHandler(u8 irq); + static HardwareEventsManager& the(); + void register_device(Device&, u8); + void unregister_device(Device&); + void register_device_event(); + Device* get_device(unsigned, unsigned); + HashTable& get_devices_list(); private: - u8 m_irq_number { 0 }; + HashTable m_devices; + HardwareEventsManager(); }; diff --git a/Kernel/Devices/KeyboardDevice.cpp b/Kernel/Devices/KeyboardDevice.cpp index 86c862057e8..5996e875666 100644 --- a/Kernel/Devices/KeyboardDevice.cpp +++ b/Kernel/Devices/KeyboardDevice.cpp @@ -483,7 +483,7 @@ void KeyboardDevice::key_state_changed(u8 raw, bool pressed) m_has_e0_prefix = false; } -void KeyboardDevice::handle_irq() +void KeyboardDevice::handle_interrupt() { for (;;) { u8 status = IO::in8(I8042_STATUS); @@ -551,7 +551,7 @@ KeyboardDevice& KeyboardDevice::the() } KeyboardDevice::KeyboardDevice() - : IRQHandler(IRQ_KEYBOARD) + : InterruptHandler(IRQ_KEYBOARD) , CharacterDevice(85, 1) { s_the = this; @@ -563,7 +563,7 @@ KeyboardDevice::KeyboardDevice() while (IO::in8(I8042_STATUS) & I8042_BUFFER_FULL) IO::in8(I8042_BUFFER); - enable_irq(); + enable_interrupts(); } KeyboardDevice::~KeyboardDevice() diff --git a/Kernel/Devices/KeyboardDevice.h b/Kernel/Devices/KeyboardDevice.h index a2c9b4e3a3b..a5b24b7b2d5 100644 --- a/Kernel/Devices/KeyboardDevice.h +++ b/Kernel/Devices/KeyboardDevice.h @@ -26,16 +26,16 @@ #pragma once -#include "IRQHandler.h" #include "KeyCode.h" #include #include #include #include +#include class KeyboardClient; -class KeyboardDevice final : public IRQHandler +class KeyboardDevice final : public InterruptHandler , public CharacterDevice { AK_MAKE_ETERNAL public: @@ -57,7 +57,7 @@ public: private: // ^IRQHandler - virtual void handle_irq() override; + virtual void handle_interrupt() override; // ^CharacterDevice virtual const char* class_name() const override { return "KeyboardDevice"; } diff --git a/Kernel/Devices/PATAChannel.cpp b/Kernel/Devices/PATAChannel.cpp index b57fe42c1c6..ee67eb7ff76 100644 --- a/Kernel/Devices/PATAChannel.cpp +++ b/Kernel/Devices/PATAChannel.cpp @@ -112,18 +112,25 @@ static Lock& s_lock() return *lock; }; -OwnPtr PATAChannel::create(ChannelType type, bool force_pio) +OwnPtr PATAChannel::autodetect(ChannelType type, bool force_pio) { - return make(type, force_pio); + PCI::Address found_address; + PCI::enumerate_all([&](const PCI::Address& address, PCI::ID id) { + if (PCI::get_class(address) == PCI_Mass_Storage_Class && PCI::get_subclass(address) == PCI_IDE_Controller_Subclass) { + found_address = address; + kprintf("PATAChannel: PATA Controller found! id=%w:%w\n", id.vendor_id, id.device_id); + } + }); + return make(found_address, type, force_pio); } -PATAChannel::PATAChannel(ChannelType type, bool force_pio) - : IRQHandler((type == ChannelType::Primary ? PATA_PRIMARY_IRQ : PATA_SECONDARY_IRQ)) +PATAChannel::PATAChannel(PCI::Address pci_address, ChannelType type, bool force_pio) + : PCI::Device(pci_address, (type == ChannelType::Primary ? PATA_PRIMARY_IRQ : PATA_SECONDARY_IRQ)) , m_channel_number((type == ChannelType::Primary ? 0 : 1)) , m_io_base((type == ChannelType::Primary ? 0x1F0 : 0x170)) , m_control_base((type == ChannelType::Primary ? 0x3f6 : 0x376)) { - disable_irq(); + disable_interrupts(); m_dma_enabled.resource() = true; ProcFS::add_sys_bool("ide_dma", m_dma_enabled); @@ -140,14 +147,8 @@ PATAChannel::~PATAChannel() void PATAChannel::initialize(bool force_pio) { - PCI::enumerate_all([this](const PCI::Address& address, PCI::ID id) { - if (PCI::get_class(address) == PCI_Mass_Storage_Class && PCI::get_subclass(address) == PCI_IDE_Controller_Subclass) { - m_pci_address = address; - kprintf("PATAChannel: PATA Controller found! id=%w:%w\n", id.vendor_id, id.device_id); - } - }); - if (m_pci_address.is_null()) { + if (get_pci_address().is_null()) { kprintf("PATAChannel: PCI address was null; can not set up DMA\n"); return; } @@ -158,9 +159,9 @@ void PATAChannel::initialize(bool force_pio) } // Let's try to set up DMA transfers. - PCI::enable_bus_mastering(m_pci_address); + PCI::enable_bus_mastering(get_pci_address()); prdt().end_of_table = 0x8000; - m_bus_master_base = PCI::get_BAR4(m_pci_address) & 0xfffc; + m_bus_master_base = PCI::get_BAR4(get_pci_address()) & 0xfffc; m_dma_buffer_page = MM.allocate_supervisor_physical_page(); kprintf("PATAChannel: Bus master IDE: I/O @ %x\n", m_bus_master_base); } @@ -181,12 +182,11 @@ static void print_ide_status(u8 status) void PATAChannel::wait_for_irq() { cli(); - enable_irq(); + InterruptHandler::Enabler enabler(*this); current->wait_on(m_irq_queue); - disable_irq(); } -void PATAChannel::handle_irq() +void PATAChannel::handle_interrupt() { u8 status = IO::in8(m_io_base + ATA_REG_STATUS); if (status & ATA_SR_ERR) { diff --git a/Kernel/Devices/PATAChannel.h b/Kernel/Devices/PATAChannel.h index 829def7558b..cee50d39280 100644 --- a/Kernel/Devices/PATAChannel.h +++ b/Kernel/Devices/PATAChannel.h @@ -38,9 +38,10 @@ #include #include -#include +#include #include #include +#include #include #include #include @@ -52,7 +53,7 @@ struct PhysicalRegionDescriptor { }; class PATADiskDevice; -class PATAChannel final : public IRQHandler { +class PATAChannel final : public PCI::Device { friend class PATADiskDevice; AK_MAKE_ETERNAL public: @@ -62,8 +63,8 @@ public: }; public: - static OwnPtr create(ChannelType type, bool force_pio); - PATAChannel(ChannelType type, bool force_pio); + static OwnPtr autodetect(ChannelType type, bool force_pio); + PATAChannel(PCI::Address pci_address, ChannelType type, bool force_pio); virtual ~PATAChannel() override; RefPtr master_device() { return m_master; }; @@ -71,7 +72,7 @@ public: private: //^ IRQHandler - virtual void handle_irq() override; + virtual void handle_interrupt() override; void initialize(bool force_pio); void detect_disks(); @@ -90,7 +91,6 @@ private: WaitQueue m_irq_queue; - PCI::Address m_pci_address; PhysicalRegionDescriptor& prdt() { return *reinterpret_cast(m_prdt_page->paddr().offset(0xc0000000).as_ptr()); } RefPtr m_prdt_page; RefPtr m_dma_buffer_page; diff --git a/Kernel/Devices/PATADiskDevice.h b/Kernel/Devices/PATADiskDevice.h index 086c6d84679..d99de6518fd 100644 --- a/Kernel/Devices/PATADiskDevice.h +++ b/Kernel/Devices/PATADiskDevice.h @@ -31,7 +31,7 @@ #pragma once #include -#include +#include #include class PATAChannel; diff --git a/Kernel/Devices/PS2MouseDevice.cpp b/Kernel/Devices/PS2MouseDevice.cpp index 6a1e1785600..fca93204127 100644 --- a/Kernel/Devices/PS2MouseDevice.cpp +++ b/Kernel/Devices/PS2MouseDevice.cpp @@ -54,7 +54,7 @@ static PS2MouseDevice* s_the; PS2MouseDevice::PS2MouseDevice() - : IRQHandler(IRQ_MOUSE) + : InterruptHandler(IRQ_MOUSE) , CharacterDevice(10, 1) { s_the = this; @@ -70,7 +70,7 @@ PS2MouseDevice& PS2MouseDevice::the() return *s_the; } -void PS2MouseDevice::handle_irq() +void PS2MouseDevice::handle_interrupt() { for (;;) { u8 status = IO::in8(I8042_STATUS); @@ -242,7 +242,7 @@ void PS2MouseDevice::initialize_device() kprintf("PS2MouseDevice: No mouse wheel detected!\n"); } - enable_irq(); + enable_interrupts(); } void PS2MouseDevice::expect_ack() diff --git a/Kernel/Devices/PS2MouseDevice.h b/Kernel/Devices/PS2MouseDevice.h index 6010bb6cefc..e806b7fa839 100644 --- a/Kernel/Devices/PS2MouseDevice.h +++ b/Kernel/Devices/PS2MouseDevice.h @@ -28,10 +28,10 @@ #include #include -#include +#include #include -class PS2MouseDevice final : public IRQHandler +class PS2MouseDevice final : public InterruptHandler , public CharacterDevice { public: PS2MouseDevice(); @@ -47,7 +47,7 @@ public: private: // ^IRQHandler - virtual void handle_irq() override; + virtual void handle_interrupt() override; // ^CharacterDevice virtual const char* class_name() const override { return "PS2MouseDevice"; } diff --git a/Kernel/Devices/SB16.cpp b/Kernel/Devices/SB16.cpp index f015adcc107..8150aaacda7 100644 --- a/Kernel/Devices/SB16.cpp +++ b/Kernel/Devices/SB16.cpp @@ -74,7 +74,7 @@ void SB16::set_sample_rate(uint16_t hz) static SB16* s_the; SB16::SB16() - : IRQHandler(5) + : InterruptHandler(5) , CharacterDevice(42, 42) // ### ? { s_the = this; @@ -92,7 +92,7 @@ SB16& SB16::the() void SB16::initialize() { - disable_irq(); + disable_interrupts(); IO::out8(0x226, 1); IO::delay(); @@ -153,7 +153,7 @@ void SB16::dma_start(uint32_t length) IO::out8(0xd4, (channel % 4)); } -void SB16::handle_irq() +void SB16::handle_interrupt() { // Stop sound output ready for the next block. dsp_write(0xd5); @@ -168,9 +168,8 @@ void SB16::handle_irq() void SB16::wait_for_irq() { cli(); - enable_irq(); + InterruptHandler::Enabler enabler(*this); current->wait_on(m_irq_queue); - disable_irq(); } ssize_t SB16::write(FileDescription&, const u8* data, ssize_t length) diff --git a/Kernel/Devices/SB16.h b/Kernel/Devices/SB16.h index 21df353222c..25c91cf59f8 100644 --- a/Kernel/Devices/SB16.h +++ b/Kernel/Devices/SB16.h @@ -28,14 +28,14 @@ #include #include -#include +#include #include #include #include class SB16; -class SB16 final : public IRQHandler +class SB16 final : public InterruptHandler , public CharacterDevice { public: SB16(); @@ -51,7 +51,7 @@ public: private: // ^IRQHandler - virtual void handle_irq() override; + virtual void handle_interrupt() override; // ^CharacterDevice virtual const char* class_name() const override { return "SB16"; } diff --git a/Kernel/Makefile b/Kernel/Makefile index 7cf989c555a..08387216823 100644 --- a/Kernel/Makefile +++ b/Kernel/Makefile @@ -15,6 +15,7 @@ OBJS = \ Arch/i386/PIT.o \ CMOS.o \ Console.o \ + Devices/HardwareEventsManager.o \ Devices/BXVGADevice.o \ Devices/BlockDevice.o \ Devices/CharacterDevice.o \ @@ -54,7 +55,8 @@ OBJS = \ FileSystem/VirtualFileSystem.o \ Heap/SlabAllocator.o \ Heap/kmalloc.o \ - IRQHandler.o \ + InterruptHandler.o \ + SharedInterruptHandler.o \ KBufferBuilder.o \ KParams.o \ KSyms.o \ @@ -74,6 +76,7 @@ OBJS = \ PCI/IOAccess.o \ PCI/MMIOAccess.o \ PCI/Initializer.o \ + PCI/Device.o \ Process.o \ ProcessTracer.o \ Profiling.o \ diff --git a/Kernel/Net/E1000NetworkAdapter.cpp b/Kernel/Net/E1000NetworkAdapter.cpp index 8ab2937fb9b..9f58334498e 100644 --- a/Kernel/Net/E1000NetworkAdapter.cpp +++ b/Kernel/Net/E1000NetworkAdapter.cpp @@ -135,24 +135,23 @@ OwnPtr E1000NetworkAdapter::autodetect() return make(found_address, irq); } -E1000NetworkAdapter::E1000NetworkAdapter(PCI::Address pci_address, u8 irq) - : IRQHandler(irq) - , m_pci_address(pci_address) +E1000NetworkAdapter::E1000NetworkAdapter(PCI::Address pci_address, u8 interrupt_vector) + : PCI::Device(pci_address, interrupt_vector) { set_interface_name("e1k"); kprintf("E1000: Found at PCI address @ %w:%b:%b.%b\n", pci_address.seg(), pci_address.bus(), pci_address.slot(), pci_address.function()); - enable_bus_mastering(m_pci_address); + enable_bus_mastering(get_pci_address()); size_t mmio_base_size = PCI::get_BAR_Space_Size(pci_address, 0); - m_mmio_region = MM.allocate_kernel_region(PhysicalAddress(page_base_of(PCI::get_BAR0(m_pci_address))), PAGE_ROUND_UP(mmio_base_size), "E1000 MMIO", Region::Access::Read | Region::Access::Write, false, false); + m_mmio_region = MM.allocate_kernel_region(PhysicalAddress(page_base_of(PCI::get_BAR0(get_pci_address()))), PAGE_ROUND_UP(mmio_base_size), "E1000 MMIO", Region::Access::Read | Region::Access::Write, false, false); m_mmio_base = m_mmio_region->vaddr(); m_use_mmio = true; - m_io_base = PCI::get_BAR1(m_pci_address) & ~1; - m_interrupt_line = PCI::get_interrupt_line(m_pci_address); + m_io_base = PCI::get_BAR1(get_pci_address()) & ~1; + m_interrupt_line = PCI::get_interrupt_line(get_pci_address()); kprintf("E1000: IO port base: %w\n", m_io_base); - kprintf("E1000: MMIO base: P%x\n", PCI::get_BAR0(pci_address) & 0xfffffffc); + kprintf("E1000: MMIO base: P%x\n", PCI::get_BAR0(get_pci_address()) & 0xfffffffc); kprintf("E1000: MMIO base size: %u bytes\n", mmio_base_size); kprintf("E1000: Interrupt line: %u\n", m_interrupt_line); detect_eeprom(); @@ -171,14 +170,14 @@ E1000NetworkAdapter::E1000NetworkAdapter(PCI::Address pci_address, u8 irq) out32(REG_IMASK, 0xff & ~4); in32(0xc0); - enable_irq(); + enable_interrupts(); } E1000NetworkAdapter::~E1000NetworkAdapter() { } -void E1000NetworkAdapter::handle_irq() +void E1000NetworkAdapter::handle_interrupt() { out32(REG_IMASK, 0x1); @@ -373,14 +372,14 @@ u32 E1000NetworkAdapter::in32(u16 address) void E1000NetworkAdapter::send_raw(const u8* data, int length) { - disable_irq(); + disable_interrupts(); u32 tx_current = in32(REG_TXDESCTAIL); #ifdef E1000_DEBUG kprintf("E1000: Sending packet (%d bytes)\n", length); #endif auto& descriptor = m_tx_descriptors[tx_current]; ASSERT(length <= 8192); - auto *vptr = (void*)(descriptor.addr + 0xc0000000); + auto* vptr = (void*)(descriptor.addr + 0xc0000000); memcpy(vptr, data, length); descriptor.length = length; descriptor.status = 0; @@ -391,7 +390,7 @@ void E1000NetworkAdapter::send_raw(const u8* data, int length) tx_current = (tx_current + 1) % number_of_tx_descriptors; out32(REG_TXDESCTAIL, tx_current); cli(); - enable_irq(); + enable_interrupts(); for (;;) { if (descriptor.status) { sti(); diff --git a/Kernel/Net/E1000NetworkAdapter.h b/Kernel/Net/E1000NetworkAdapter.h index 93efc84fafd..fb1fbb58b94 100644 --- a/Kernel/Net/E1000NetworkAdapter.h +++ b/Kernel/Net/E1000NetworkAdapter.h @@ -27,23 +27,23 @@ #pragma once #include -#include #include #include +#include class E1000NetworkAdapter final : public NetworkAdapter - , public IRQHandler { + , public PCI::Device { public: static OwnPtr autodetect(); - E1000NetworkAdapter(PCI::Address, u8 irq); + E1000NetworkAdapter(PCI::Address, u8 interrupt_vector); virtual ~E1000NetworkAdapter() override; virtual void send_raw(const u8*, int) override; virtual bool link_up() override; private: - virtual void handle_irq() override; + virtual void handle_interrupt() override; virtual const char* class_name() const override { return "E1000NetworkAdapter"; } struct [[gnu::packed]] e1000_rx_desc @@ -86,7 +86,6 @@ private: void receive(); - PCI::Address m_pci_address; u16 m_io_base { 0 }; VirtualAddress m_mmio_base; OwnPtr m_mmio_region; diff --git a/Kernel/Net/RTL8139NetworkAdapter.cpp b/Kernel/Net/RTL8139NetworkAdapter.cpp index c24704f3d9d..6604f5bed2f 100644 --- a/Kernel/Net/RTL8139NetworkAdapter.cpp +++ b/Kernel/Net/RTL8139NetworkAdapter.cpp @@ -139,18 +139,17 @@ OwnPtr RTL8139NetworkAdapter::autodetect() return make(found_address, irq); } -RTL8139NetworkAdapter::RTL8139NetworkAdapter(PCI::Address pci_address, u8 irq) - : IRQHandler(irq) - , m_pci_address(pci_address) +RTL8139NetworkAdapter::RTL8139NetworkAdapter(PCI::Address pci_address, u8 interrupt_vector) + : PCI::Device(pci_address, interrupt_vector) { set_interface_name("rtl8139"); kprintf("RTL8139: Found at PCI address %b:%b:%b\n", pci_address.bus(), pci_address.slot(), pci_address.function()); - enable_bus_mastering(m_pci_address); + enable_bus_mastering(get_pci_address()); - m_io_base = PCI::get_BAR0(m_pci_address) & ~1; - m_interrupt_line = PCI::get_interrupt_line(m_pci_address); + m_io_base = PCI::get_BAR0(get_pci_address()) & ~1; + m_interrupt_line = PCI::get_interrupt_line(get_pci_address()); kprintf("RTL8139: IO port base: %w\n", m_io_base); kprintf("RTL8139: Interrupt line: %u\n", m_interrupt_line); @@ -174,14 +173,14 @@ RTL8139NetworkAdapter::RTL8139NetworkAdapter(PCI::Address pci_address, u8 irq) const auto& mac = mac_address(); kprintf("RTL8139: MAC address: %s\n", mac.to_string().characters()); - enable_irq(); + enable_interrupts(); } RTL8139NetworkAdapter::~RTL8139NetworkAdapter() { } -void RTL8139NetworkAdapter::handle_irq() +void RTL8139NetworkAdapter::handle_interrupt() { for (;;) { int status = in16(REG_ISR); diff --git a/Kernel/Net/RTL8139NetworkAdapter.h b/Kernel/Net/RTL8139NetworkAdapter.h index a9d941a0fe6..c998db0fb21 100644 --- a/Kernel/Net/RTL8139NetworkAdapter.h +++ b/Kernel/Net/RTL8139NetworkAdapter.h @@ -27,25 +27,25 @@ #pragma once #include -#include #include #include +#include #define RTL8139_TX_BUFFER_COUNT 4 class RTL8139NetworkAdapter final : public NetworkAdapter - , public IRQHandler { + , public PCI::Device { public: static OwnPtr autodetect(); - RTL8139NetworkAdapter(PCI::Address, u8 irq); + RTL8139NetworkAdapter(PCI::Address, u8 interrupt_vector); virtual ~RTL8139NetworkAdapter() override; virtual void send_raw(const u8*, int) override; virtual bool link_up() override { return m_link_up; } private: - virtual void handle_irq() override; + virtual void handle_interrupt() override; virtual const char* class_name() const override { return "RTL8139NetworkAdapter"; } void reset(); @@ -60,7 +60,6 @@ private: u16 in16(u16 address); u32 in32(u16 address); - PCI::Address m_pci_address; u16 m_io_base { 0 }; u8 m_interrupt_line { 0 }; u32 m_rx_buffer_addr { 0 }; diff --git a/Kernel/init.cpp b/Kernel/init.cpp index 2f69a6e5768..66ea5150dc9 100644 --- a/Kernel/init.cpp +++ b/Kernel/init.cpp @@ -101,8 +101,14 @@ extern "C" [[noreturn]] void init() bool text_debug = KParams::the().has("text_debug"); + gdt_init(); + idt_init(); + setup_acpi(); + // Sample test to see if the ACPI parser is working... + kprintf("ACPI: HPET table @ P 0x%x\n", ACPIParser::the().find_table("HPET")); + new VFS; new DebugLogDevice; @@ -114,8 +120,6 @@ extern "C" [[noreturn]] void init() RTC::initialize(); PIC::initialize(); - gdt_init(); - idt_init(); // call global constructors after gtd and itd init for (ctor_func_t* ctor = &start_ctors; ctor < &end_ctors; ctor++) @@ -136,9 +140,6 @@ extern "C" [[noreturn]] void init() new VirtualConsole(1); VirtualConsole::switch_to(0); - // Sample test to see if the ACPI parser is working... - kprintf("ACPI: HPET table @ P 0x%x\n", ACPIParser::the().find_table("HPET")); - PCI::Initializer::the().test_and_initialize(KParams::the().has("nopci_mmio")); PCI::Initializer::the().dismiss(); @@ -171,7 +172,6 @@ extern "C" [[noreturn]] void init() LoopbackAdapter::the(); auto e1000 = E1000NetworkAdapter::autodetect(); auto rtl8139 = RTL8139NetworkAdapter::autodetect(); - Process::initialize(); Thread::initialize(); @@ -231,7 +231,7 @@ void init_stage2() hang(); } - auto pata0 = PATAChannel::create(PATAChannel::ChannelType::Primary, force_pio); + auto pata0 = PATAChannel::autodetect(PATAChannel::ChannelType::Primary, force_pio); NonnullRefPtr root_dev = *pata0->master_device(); root = root.substring(strlen("/dev/hda"), root.length() - strlen("/dev/hda"));