[Zion] Add a keyboard interrupt handler and a driver manager.
This commit is contained in:
parent
d9a936db09
commit
838ef01a2a
|
@ -183,7 +183,22 @@ glcr::ErrorCode AhciDriver::RegisterIrq() {
|
||||||
if (pci_device_header_->interrupt_pin == 0) {
|
if (pci_device_header_->interrupt_pin == 0) {
|
||||||
crash("Can't register IRQ without a pin num", glcr::INVALID_ARGUMENT);
|
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_));
|
RET_ERR(ZIrqRegister(irq_num, &irq_port_cap_));
|
||||||
irq_thread_ = Thread(interrupt_thread, this);
|
irq_thread_ = Thread(interrupt_thread, this);
|
||||||
ahci_hba_->global_host_control |= kGhc_InteruptEnable;
|
ahci_hba_->global_host_control |= kGhc_InteruptEnable;
|
||||||
|
|
|
@ -10,6 +10,7 @@ add_executable(zion
|
||||||
debug/debug.cpp
|
debug/debug.cpp
|
||||||
interrupt/apic.cpp
|
interrupt/apic.cpp
|
||||||
interrupt/apic_timer.cpp
|
interrupt/apic_timer.cpp
|
||||||
|
interrupt/driver_manager.cpp
|
||||||
interrupt/interrupt.cpp
|
interrupt/interrupt.cpp
|
||||||
interrupt/interrupt_enter.s
|
interrupt/interrupt_enter.s
|
||||||
interrupt/timer.cpp
|
interrupt/timer.cpp
|
||||||
|
|
|
@ -146,8 +146,8 @@ void ParseMadt(SdtHeader* rsdt) {
|
||||||
MadtHeader* header = reinterpret_cast<MadtHeader*>(rsdt);
|
MadtHeader* header = reinterpret_cast<MadtHeader*>(rsdt);
|
||||||
|
|
||||||
#if K_ACPI_DEBUG
|
#if K_ACPI_DEBUG
|
||||||
dbgln("Local APIC {x}", header->local_apic_address);
|
dbgln("Local APIC {x}", +header->local_apic_address);
|
||||||
dbgln("Flags: {x}", header->flags);
|
dbgln("Flags: {x}", +header->flags);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
gLApicBase = header->local_apic_address;
|
gLApicBase = header->local_apic_address;
|
||||||
|
@ -160,7 +160,7 @@ void ParseMadt(SdtHeader* rsdt) {
|
||||||
MadtLocalApic* local = reinterpret_cast<MadtLocalApic*>(entry);
|
MadtLocalApic* local = reinterpret_cast<MadtLocalApic*>(entry);
|
||||||
#if K_ACPI_DEBUG
|
#if K_ACPI_DEBUG
|
||||||
dbgln("Local APIC (Proc id, id, flags): {x}, {x}, {x}",
|
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
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -168,7 +168,7 @@ void ParseMadt(SdtHeader* rsdt) {
|
||||||
MadtIoApic* io = reinterpret_cast<MadtIoApic*>(entry);
|
MadtIoApic* io = reinterpret_cast<MadtIoApic*>(entry);
|
||||||
#if K_ACPI_DEBUG
|
#if K_ACPI_DEBUG
|
||||||
dbgln("IO Apic (id, addr, gsi base): {x}, {x}, {x}", io->io_apic_id,
|
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
|
#endif
|
||||||
if (gIOApicBase != 0) {
|
if (gIOApicBase != 0) {
|
||||||
dbgln("More than one IOApic, unhandled");
|
dbgln("More than one IOApic, unhandled");
|
||||||
|
@ -181,8 +181,8 @@ void ParseMadt(SdtHeader* rsdt) {
|
||||||
reinterpret_cast<MadtIoApicInterruptSource*>(entry);
|
reinterpret_cast<MadtIoApicInterruptSource*>(entry);
|
||||||
#if K_ACPI_DEBUG
|
#if K_ACPI_DEBUG
|
||||||
dbgln("IO Source (Bus, IRQ, GSI, flags): {x}, {x}, {x}, {x}",
|
dbgln("IO Source (Bus, IRQ, GSI, flags): {x}, {x}, {x}, {x}",
|
||||||
src->bus_source, src->irq_source, src->global_system_interrupt,
|
src->bus_source, src->irq_source, +src->global_system_interrupt,
|
||||||
src->flags);
|
+src->flags);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -191,7 +191,7 @@ void ParseMadt(SdtHeader* rsdt) {
|
||||||
reinterpret_cast<MadtLocalApicNonMaskable*>(entry);
|
reinterpret_cast<MadtLocalApicNonMaskable*>(entry);
|
||||||
#if K_ACPI_DEBUG
|
#if K_ACPI_DEBUG
|
||||||
dbgln("Local NMI (proc id, flags, lint#): {x}, {x}, {x}",
|
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
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -254,7 +254,7 @@ void ProbeRsdp() {
|
||||||
|
|
||||||
#if K_ACPI_DEBUG
|
#if K_ACPI_DEBUG
|
||||||
dbgln("ACPI Ver {}", rsdp->revision);
|
dbgln("ACPI Ver {}", rsdp->revision);
|
||||||
dbgln("RSDT Addr: {x}", rsdp->rsdt_addr);
|
dbgln("RSDT Addr: {x}", +rsdp->rsdt_addr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ProbeRsdt(reinterpret_cast<SdtHeader*>(rsdp->rsdt_addr));
|
ProbeRsdt(reinterpret_cast<SdtHeader*>(rsdp->rsdt_addr));
|
||||||
|
@ -270,7 +270,7 @@ void ProbeRsdp() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#if K_ACPI_DEBUG
|
#if K_ACPI_DEBUG
|
||||||
dbgln("XSDT Addr: {x}", rsdp->xsdt_addr);
|
dbgln("XSDT Addr: {x}", +rsdp->xsdt_addr);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,8 +50,6 @@ const uint64_t kZionReplyPortSend = 0x63;
|
||||||
const uint64_t kZionReplyPortRecv = 0x64;
|
const uint64_t kZionReplyPortRecv = 0x64;
|
||||||
const uint64_t kZionEndpointCall = 0x65;
|
const uint64_t kZionEndpointCall = 0x65;
|
||||||
|
|
||||||
#define Z_IRQ_PCI_BASE 0x30
|
|
||||||
|
|
||||||
// Capability Calls
|
// Capability Calls
|
||||||
const uint64_t kZionCapDuplicate = 0x70;
|
const uint64_t kZionCapDuplicate = 0x70;
|
||||||
const uint64_t kZionCapRelease = 0x71;
|
const uint64_t kZionCapRelease = 0x71;
|
||||||
|
@ -67,6 +65,13 @@ const uint64_t kZionSemaphoreSignal = 0x85;
|
||||||
// Debugging Calls.
|
// Debugging Calls.
|
||||||
const uint64_t kZionDebug = 0x1'0000;
|
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
|
* Capability Types
|
||||||
* ------------------------------*/
|
* ------------------------------*/
|
||||||
|
|
|
@ -136,6 +136,9 @@ Apic::Apic(const ApicConfiguration& config)
|
||||||
// FIXME: Get this offset from ACPI.
|
// FIXME: Get this offset from ACPI.
|
||||||
SetIoDoubleReg(0x14, 0x20 | APIC_MASK);
|
SetIoDoubleReg(0x14, 0x20 | APIC_MASK);
|
||||||
|
|
||||||
|
// Map Keyboard
|
||||||
|
SetIoDoubleReg(0x12, 0x22);
|
||||||
|
|
||||||
// For now set these based on the presets in the following spec.
|
// 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
|
// 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
|
// FIXME: However in the future we should likely use the MADT for legacy
|
||||||
|
|
|
@ -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> port) {
|
||||||
|
if (driver_map_.Contains(irq_num)) {
|
||||||
|
return glcr::ALREADY_EXISTS;
|
||||||
|
}
|
||||||
|
return driver_map_.Insert(irq_num, port);
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <glacier/container/hash_map.h>
|
||||||
|
#include <glacier/memory/ref_ptr.h>
|
||||||
|
|
||||||
|
#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> port);
|
||||||
|
|
||||||
|
private:
|
||||||
|
glcr::HashMap<uint64_t, glcr::RefPtr<Port>> driver_map_;
|
||||||
|
};
|
|
@ -7,6 +7,7 @@
|
||||||
#include "debug/debug.h"
|
#include "debug/debug.h"
|
||||||
#include "interrupt/apic.h"
|
#include "interrupt/apic.h"
|
||||||
#include "interrupt/apic_timer.h"
|
#include "interrupt/apic_timer.h"
|
||||||
|
#include "interrupt/driver_manager.h"
|
||||||
#include "memory/kernel_heap.h"
|
#include "memory/kernel_heap.h"
|
||||||
#include "memory/physical_memory.h"
|
#include "memory/physical_memory.h"
|
||||||
#include "scheduler/scheduler.h"
|
#include "scheduler/scheduler.h"
|
||||||
|
@ -196,27 +197,39 @@ extern "C" void interrupt_apic_timer(InterruptFrame*) {
|
||||||
gScheduler->Preempt();
|
gScheduler->Preempt();
|
||||||
}
|
}
|
||||||
|
|
||||||
glcr::RefPtr<Port> pci1_port;
|
extern "C" void isr_keyboard();
|
||||||
|
extern "C" void interrupt_keyboard(InterruptFrame*) {
|
||||||
|
glcr::Array<uint8_t> 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 isr_pci1();
|
||||||
extern "C" void interrupt_pci1(InterruptFrame*) {
|
extern "C" void interrupt_pci1(InterruptFrame*) {
|
||||||
pci1_port->Send({});
|
DriverManager::Get().WriteMessage(kZIrqPci1, {});
|
||||||
gApic->SignalEOI();
|
gApic->SignalEOI();
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void isr_pci2();
|
extern "C" void isr_pci2();
|
||||||
extern "C" void interrupt_pci2(InterruptFrame*) {
|
extern "C" void interrupt_pci2(InterruptFrame*) {
|
||||||
|
DriverManager::Get().WriteMessage(kZIrqPci2, {});
|
||||||
dbgln("Interrupt PCI line 2");
|
dbgln("Interrupt PCI line 2");
|
||||||
gApic->SignalEOI();
|
gApic->SignalEOI();
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void isr_pci3();
|
extern "C" void isr_pci3();
|
||||||
extern "C" void interrupt_pci3(InterruptFrame*) {
|
extern "C" void interrupt_pci3(InterruptFrame*) {
|
||||||
|
DriverManager::Get().WriteMessage(kZIrqPci3, {});
|
||||||
dbgln("Interrupt PCI line 3");
|
dbgln("Interrupt PCI line 3");
|
||||||
gApic->SignalEOI();
|
gApic->SignalEOI();
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void isr_pci4();
|
extern "C" void isr_pci4();
|
||||||
extern "C" void interrupt_pci4(InterruptFrame*) {
|
extern "C" void interrupt_pci4(InterruptFrame*) {
|
||||||
|
DriverManager::Get().WriteMessage(kZIrqPci4, {});
|
||||||
dbgln("Interrupt PCI line 4");
|
dbgln("Interrupt PCI line 4");
|
||||||
gApic->SignalEOI();
|
gApic->SignalEOI();
|
||||||
}
|
}
|
||||||
|
@ -230,6 +243,7 @@ void InitIdt() {
|
||||||
|
|
||||||
gIdt[0x20] = CreateDescriptor(isr_timer);
|
gIdt[0x20] = CreateDescriptor(isr_timer);
|
||||||
gIdt[0x21] = CreateDescriptor(isr_apic_timer);
|
gIdt[0x21] = CreateDescriptor(isr_apic_timer);
|
||||||
|
gIdt[0x22] = CreateDescriptor(isr_keyboard);
|
||||||
|
|
||||||
gIdt[0x30] = CreateDescriptor(isr_pci1);
|
gIdt[0x30] = CreateDescriptor(isr_pci1);
|
||||||
gIdt[0x31] = CreateDescriptor(isr_pci2);
|
gIdt[0x31] = CreateDescriptor(isr_pci2);
|
||||||
|
@ -253,5 +267,3 @@ void UpdateFaultHandlersToIst1() {
|
||||||
};
|
};
|
||||||
asm volatile("lidt %0" ::"m"(idtp));
|
asm volatile("lidt %0" ::"m"(idtp));
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegisterPciPort(const glcr::RefPtr<Port>& port) { pci1_port = port; }
|
|
||||||
|
|
|
@ -7,5 +7,3 @@
|
||||||
void InitIdt();
|
void InitIdt();
|
||||||
|
|
||||||
void UpdateFaultHandlersToIst1();
|
void UpdateFaultHandlersToIst1();
|
||||||
|
|
||||||
void RegisterPciPort(const glcr::RefPtr<Port>& port);
|
|
||||||
|
|
|
@ -63,6 +63,7 @@ isr_handler fpe_fault
|
||||||
|
|
||||||
isr_handler timer
|
isr_handler timer
|
||||||
isr_handler apic_timer
|
isr_handler apic_timer
|
||||||
|
isr_handler keyboard
|
||||||
|
|
||||||
isr_handler pci1
|
isr_handler pci1
|
||||||
isr_handler pci2
|
isr_handler pci2
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include "capability/capability.h"
|
#include "capability/capability.h"
|
||||||
#include "debug/debug.h"
|
#include "debug/debug.h"
|
||||||
|
#include "interrupt/driver_manager.h"
|
||||||
#include "interrupt/interrupt.h"
|
#include "interrupt/interrupt.h"
|
||||||
#include "object/endpoint.h"
|
#include "object/endpoint.h"
|
||||||
#include "object/reply_port.h"
|
#include "object/reply_port.h"
|
||||||
|
@ -157,13 +158,10 @@ glcr::ErrorCode PortPoll(ZPortPollReq* req) {
|
||||||
|
|
||||||
glcr::ErrorCode IrqRegister(ZIrqRegisterReq* req) {
|
glcr::ErrorCode IrqRegister(ZIrqRegisterReq* req) {
|
||||||
auto& proc = gScheduler->CurrentProcess();
|
auto& proc = gScheduler->CurrentProcess();
|
||||||
if (req->irq_num != Z_IRQ_PCI_BASE) {
|
|
||||||
// FIXME: Don't hardcode this nonsense.
|
|
||||||
return glcr::UNIMPLEMENTED;
|
|
||||||
}
|
|
||||||
glcr::RefPtr<Port> port = glcr::MakeRefCounted<Port>();
|
glcr::RefPtr<Port> port = glcr::MakeRefCounted<Port>();
|
||||||
*req->port_cap = proc.AddNewCapability(port);
|
*req->port_cap = proc.AddNewCapability(port);
|
||||||
RegisterPciPort(port);
|
DriverManager::Get().RegisterListener(req->irq_num, port);
|
||||||
return glcr::OK;
|
return glcr::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "debug/debug.h"
|
#include "debug/debug.h"
|
||||||
#include "interrupt/apic.h"
|
#include "interrupt/apic.h"
|
||||||
#include "interrupt/apic_timer.h"
|
#include "interrupt/apic_timer.h"
|
||||||
|
#include "interrupt/driver_manager.h"
|
||||||
#include "interrupt/interrupt.h"
|
#include "interrupt/interrupt.h"
|
||||||
#include "interrupt/timer.h"
|
#include "interrupt/timer.h"
|
||||||
#include "loader/init_loader.h"
|
#include "loader/init_loader.h"
|
||||||
|
@ -46,6 +47,7 @@ extern "C" void zion() {
|
||||||
// These two need to occur after memory allocation is available.
|
// These two need to occur after memory allocation is available.
|
||||||
Apic::Init();
|
Apic::Init();
|
||||||
ApicTimer::Init();
|
ApicTimer::Init();
|
||||||
|
DriverManager driver_manager;
|
||||||
|
|
||||||
dbgln("[boot] Init syscalls.");
|
dbgln("[boot] Init syscalls.");
|
||||||
InitSyscall();
|
InitSyscall();
|
||||||
|
|
Loading…
Reference in New Issue