diff --git a/sys/denali/ahci/ahci_driver.cpp b/sys/denali/ahci/ahci_driver.cpp index 28d0de5..64b340d 100644 --- a/sys/denali/ahci/ahci_driver.cpp +++ b/sys/denali/ahci/ahci_driver.cpp @@ -183,7 +183,22 @@ glcr::ErrorCode AhciDriver::RegisterIrq() { if (pci_device_header_->interrupt_pin == 0) { crash("Can't register IRQ without a pin num", glcr::INVALID_ARGUMENT); } - uint64_t irq_num = Z_IRQ_PCI_BASE + pci_device_header_->interrupt_pin - 1; + uint64_t irq_num = 0; + switch (pci_device_header_->interrupt_pin) { + case 1: + irq_num = kZIrqPci1; + break; + case 2: + irq_num = kZIrqPci2; + break; + case 3: + irq_num = kZIrqPci3; + break; + case 4: + irq_num = kZIrqPci4; + break; + } + RET_ERR(ZIrqRegister(irq_num, &irq_port_cap_)); irq_thread_ = Thread(interrupt_thread, this); ahci_hba_->global_host_control |= kGhc_InteruptEnable; diff --git a/zion/CMakeLists.txt b/zion/CMakeLists.txt index 9adc404..409e237 100644 --- a/zion/CMakeLists.txt +++ b/zion/CMakeLists.txt @@ -10,6 +10,7 @@ add_executable(zion debug/debug.cpp interrupt/apic.cpp interrupt/apic_timer.cpp + interrupt/driver_manager.cpp interrupt/interrupt.cpp interrupt/interrupt_enter.s interrupt/timer.cpp diff --git a/zion/boot/acpi.cpp b/zion/boot/acpi.cpp index 1639676..7bc1d51 100644 --- a/zion/boot/acpi.cpp +++ b/zion/boot/acpi.cpp @@ -146,8 +146,8 @@ void ParseMadt(SdtHeader* rsdt) { MadtHeader* header = reinterpret_cast(rsdt); #if K_ACPI_DEBUG - dbgln("Local APIC {x}", header->local_apic_address); - dbgln("Flags: {x}", header->flags); + dbgln("Local APIC {x}", +header->local_apic_address); + dbgln("Flags: {x}", +header->flags); #endif gLApicBase = header->local_apic_address; @@ -160,7 +160,7 @@ void ParseMadt(SdtHeader* rsdt) { MadtLocalApic* local = reinterpret_cast(entry); #if K_ACPI_DEBUG dbgln("Local APIC (Proc id, id, flags): {x}, {x}, {x}", - local->processor_id, local->apic_id, local->flags); + local->processor_id, local->apic_id, +local->flags); #endif break; } @@ -168,7 +168,7 @@ void ParseMadt(SdtHeader* rsdt) { MadtIoApic* io = reinterpret_cast(entry); #if K_ACPI_DEBUG dbgln("IO Apic (id, addr, gsi base): {x}, {x}, {x}", io->io_apic_id, - io->io_apic_address, io->global_system_interrupt_base); + +io->io_apic_address, +io->global_system_interrupt_base); #endif if (gIOApicBase != 0) { dbgln("More than one IOApic, unhandled"); @@ -181,8 +181,8 @@ void ParseMadt(SdtHeader* rsdt) { reinterpret_cast(entry); #if K_ACPI_DEBUG dbgln("IO Source (Bus, IRQ, GSI, flags): {x}, {x}, {x}, {x}", - src->bus_source, src->irq_source, src->global_system_interrupt, - src->flags); + src->bus_source, src->irq_source, +src->global_system_interrupt, + +src->flags); #endif break; } @@ -191,7 +191,7 @@ void ParseMadt(SdtHeader* rsdt) { reinterpret_cast(entry); #if K_ACPI_DEBUG dbgln("Local NMI (proc id, flags, lint#): {x}, {x}, {x}", - lnmi->apic_processor_id, lnmi->flags, lnmi->lint_num); + lnmi->apic_processor_id, +lnmi->flags, lnmi->lint_num); #endif break; } @@ -254,7 +254,7 @@ void ProbeRsdp() { #if K_ACPI_DEBUG dbgln("ACPI Ver {}", rsdp->revision); - dbgln("RSDT Addr: {x}", rsdp->rsdt_addr); + dbgln("RSDT Addr: {x}", +rsdp->rsdt_addr); #endif ProbeRsdt(reinterpret_cast(rsdp->rsdt_addr)); @@ -270,7 +270,7 @@ void ProbeRsdp() { } #if K_ACPI_DEBUG - dbgln("XSDT Addr: {x}", rsdp->xsdt_addr); + dbgln("XSDT Addr: {x}", +rsdp->xsdt_addr); #endif } diff --git a/zion/include/ztypes.h b/zion/include/ztypes.h index 6dd9535..0798688 100644 --- a/zion/include/ztypes.h +++ b/zion/include/ztypes.h @@ -50,8 +50,6 @@ const uint64_t kZionReplyPortSend = 0x63; const uint64_t kZionReplyPortRecv = 0x64; const uint64_t kZionEndpointCall = 0x65; -#define Z_IRQ_PCI_BASE 0x30 - // Capability Calls const uint64_t kZionCapDuplicate = 0x70; const uint64_t kZionCapRelease = 0x71; @@ -67,6 +65,13 @@ const uint64_t kZionSemaphoreSignal = 0x85; // Debugging Calls. const uint64_t kZionDebug = 0x1'0000; +// Irq Types +const uint64_t kZIrqKbd = 0x22; +const uint64_t kZIrqPci1 = 0x30; +const uint64_t kZIrqPci2 = 0x31; +const uint64_t kZIrqPci3 = 0x32; +const uint64_t kZIrqPci4 = 0x33; + /* ------------------------------ * Capability Types * ------------------------------*/ diff --git a/zion/interrupt/apic.cpp b/zion/interrupt/apic.cpp index 2e1641d..927edfd 100644 --- a/zion/interrupt/apic.cpp +++ b/zion/interrupt/apic.cpp @@ -136,6 +136,9 @@ Apic::Apic(const ApicConfiguration& config) // FIXME: Get this offset from ACPI. SetIoDoubleReg(0x14, 0x20 | APIC_MASK); + // Map Keyboard + SetIoDoubleReg(0x12, 0x22); + // For now set these based on the presets in the following spec. // http://web.archive.org/web/20161130153145/http://download.intel.com/design/chipsets/datashts/29056601.pdf // FIXME: However in the future we should likely use the MADT for legacy diff --git a/zion/interrupt/driver_manager.cpp b/zion/interrupt/driver_manager.cpp new file mode 100644 index 0000000..67e78fc --- /dev/null +++ b/zion/interrupt/driver_manager.cpp @@ -0,0 +1,26 @@ +#include "interrupt/driver_manager.h" + +#include "debug/debug.h" + +DriverManager* gDriverManager = nullptr; + +DriverManager& DriverManager::Get() { return *gDriverManager; } + +DriverManager::DriverManager() { gDriverManager = this; } + +void DriverManager::WriteMessage(uint64_t irq_num, IpcMessage&& message) { + if (!driver_map_.Contains(irq_num)) { + dbgln("WARN IRQ for {x} with no registered driver", irq_num); + return; + } + + driver_map_.at(irq_num)->Send(glcr::Move(message)); +} + +glcr::ErrorCode DriverManager::RegisterListener(uint64_t irq_num, + glcr::RefPtr port) { + if (driver_map_.Contains(irq_num)) { + return glcr::ALREADY_EXISTS; + } + return driver_map_.Insert(irq_num, port); +} diff --git a/zion/interrupt/driver_manager.h b/zion/interrupt/driver_manager.h new file mode 100644 index 0000000..c2ad11b --- /dev/null +++ b/zion/interrupt/driver_manager.h @@ -0,0 +1,22 @@ +#pragma once + +#include +#include + +#include "object/port.h" + +class DriverManager { + public: + static DriverManager& Get(); + + DriverManager(); + DriverManager(const DriverManager&) = delete; + DriverManager(DriverManager&&) = delete; + + void WriteMessage(uint64_t irq_num, IpcMessage&& message); + + glcr::ErrorCode RegisterListener(uint64_t irq_num, glcr::RefPtr port); + + private: + glcr::HashMap> driver_map_; +}; diff --git a/zion/interrupt/interrupt.cpp b/zion/interrupt/interrupt.cpp index 527d37b..2d9e8f5 100644 --- a/zion/interrupt/interrupt.cpp +++ b/zion/interrupt/interrupt.cpp @@ -7,6 +7,7 @@ #include "debug/debug.h" #include "interrupt/apic.h" #include "interrupt/apic_timer.h" +#include "interrupt/driver_manager.h" #include "memory/kernel_heap.h" #include "memory/physical_memory.h" #include "scheduler/scheduler.h" @@ -196,27 +197,39 @@ extern "C" void interrupt_apic_timer(InterruptFrame*) { gScheduler->Preempt(); } -glcr::RefPtr pci1_port; +extern "C" void isr_keyboard(); +extern "C" void interrupt_keyboard(InterruptFrame*) { + glcr::Array data(1); + data[0] = inb(0x60); + IpcMessage msg{.data = glcr::Move(data)}; + DriverManager::Get().WriteMessage(kZIrqKbd, glcr::Move(msg)); + + gApic->SignalEOI(); +} + extern "C" void isr_pci1(); extern "C" void interrupt_pci1(InterruptFrame*) { - pci1_port->Send({}); + DriverManager::Get().WriteMessage(kZIrqPci1, {}); gApic->SignalEOI(); } extern "C" void isr_pci2(); extern "C" void interrupt_pci2(InterruptFrame*) { + DriverManager::Get().WriteMessage(kZIrqPci2, {}); dbgln("Interrupt PCI line 2"); gApic->SignalEOI(); } extern "C" void isr_pci3(); extern "C" void interrupt_pci3(InterruptFrame*) { + DriverManager::Get().WriteMessage(kZIrqPci3, {}); dbgln("Interrupt PCI line 3"); gApic->SignalEOI(); } extern "C" void isr_pci4(); extern "C" void interrupt_pci4(InterruptFrame*) { + DriverManager::Get().WriteMessage(kZIrqPci4, {}); dbgln("Interrupt PCI line 4"); gApic->SignalEOI(); } @@ -230,6 +243,7 @@ void InitIdt() { gIdt[0x20] = CreateDescriptor(isr_timer); gIdt[0x21] = CreateDescriptor(isr_apic_timer); + gIdt[0x22] = CreateDescriptor(isr_keyboard); gIdt[0x30] = CreateDescriptor(isr_pci1); gIdt[0x31] = CreateDescriptor(isr_pci2); @@ -253,5 +267,3 @@ void UpdateFaultHandlersToIst1() { }; asm volatile("lidt %0" ::"m"(idtp)); } - -void RegisterPciPort(const glcr::RefPtr& port) { pci1_port = port; } diff --git a/zion/interrupt/interrupt.h b/zion/interrupt/interrupt.h index e1b5114..23b12ce 100644 --- a/zion/interrupt/interrupt.h +++ b/zion/interrupt/interrupt.h @@ -7,5 +7,3 @@ void InitIdt(); void UpdateFaultHandlersToIst1(); - -void RegisterPciPort(const glcr::RefPtr& port); diff --git a/zion/interrupt/interrupt_enter.s b/zion/interrupt/interrupt_enter.s index 0da6b16..db02a22 100644 --- a/zion/interrupt/interrupt_enter.s +++ b/zion/interrupt/interrupt_enter.s @@ -63,6 +63,7 @@ isr_handler fpe_fault isr_handler timer isr_handler apic_timer +isr_handler keyboard isr_handler pci1 isr_handler pci2 diff --git a/zion/syscall/ipc.cpp b/zion/syscall/ipc.cpp index 5011418..e18f84a 100644 --- a/zion/syscall/ipc.cpp +++ b/zion/syscall/ipc.cpp @@ -2,6 +2,7 @@ #include "capability/capability.h" #include "debug/debug.h" +#include "interrupt/driver_manager.h" #include "interrupt/interrupt.h" #include "object/endpoint.h" #include "object/reply_port.h" @@ -157,13 +158,10 @@ glcr::ErrorCode PortPoll(ZPortPollReq* req) { glcr::ErrorCode IrqRegister(ZIrqRegisterReq* req) { auto& proc = gScheduler->CurrentProcess(); - if (req->irq_num != Z_IRQ_PCI_BASE) { - // FIXME: Don't hardcode this nonsense. - return glcr::UNIMPLEMENTED; - } + glcr::RefPtr port = glcr::MakeRefCounted(); *req->port_cap = proc.AddNewCapability(port); - RegisterPciPort(port); + DriverManager::Get().RegisterListener(req->irq_num, port); return glcr::OK; } diff --git a/zion/zion.cpp b/zion/zion.cpp index 43aff22..fe9e497 100644 --- a/zion/zion.cpp +++ b/zion/zion.cpp @@ -6,6 +6,7 @@ #include "debug/debug.h" #include "interrupt/apic.h" #include "interrupt/apic_timer.h" +#include "interrupt/driver_manager.h" #include "interrupt/interrupt.h" #include "interrupt/timer.h" #include "loader/init_loader.h" @@ -46,6 +47,7 @@ extern "C" void zion() { // These two need to occur after memory allocation is available. Apic::Init(); ApicTimer::Init(); + DriverManager driver_manager; dbgln("[boot] Init syscalls."); InitSyscall();