From 7952d1d8a085a229977e43b958a317de6ea57b19 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 26 Dec 2022 19:59:18 +0100 Subject: [PATCH] x86_64: Add basic keyboard support with an ASYNC DRIVER --- kernel/src/arch/x86_64/CPU.asm | 3 +- kernel/src/arch/x86_64/CPU.cpp | 25 ++++++++++++- kernel/src/arch/x86_64/init/IDT.cpp | 2 + kernel/src/arch/x86_64/init/PIC.cpp | 2 +- kernel/src/main.cpp | 16 +------- luna/include/luna/CircularQueue.h | 57 +++++++++++++++++++++++++++++ 6 files changed, 87 insertions(+), 18 deletions(-) create mode 100644 luna/include/luna/CircularQueue.h diff --git a/kernel/src/arch/x86_64/CPU.asm b/kernel/src/arch/x86_64/CPU.asm index f3e2d2fc..f5a2c98a 100644 --- a/kernel/src/arch/x86_64/CPU.asm +++ b/kernel/src/arch/x86_64/CPU.asm @@ -186,4 +186,5 @@ ISR 19 ; SIMD floating-point exception (#XM) ISR 20 ; virtualization exception (#VE) ISR_ERROR 21 ; control-protection exception (#CP) ; ISR 22-31 reserved -IRQ 32, 0 ; timer interrupt \ No newline at end of file +IRQ 32, 0 ; timer interrupt +IRQ 33, 0 ; keyboard interrupt \ No newline at end of file diff --git a/kernel/src/arch/x86_64/CPU.cpp b/kernel/src/arch/x86_64/CPU.cpp index e58c4fa8..44c5a932 100644 --- a/kernel/src/arch/x86_64/CPU.cpp +++ b/kernel/src/arch/x86_64/CPU.cpp @@ -2,10 +2,12 @@ #include "Log.h" #include "arch/Timer.h" #include "arch/x86_64/CPU.h" +#include "arch/x86_64/IO.h" #include "memory/MemoryManager.h" #include "thread/Scheduler.h" #include #include +#include #include #include #include @@ -76,16 +78,35 @@ extern "C" void handle_x86_exception(Registers* regs) } } +CircularQueue scancode_queue; + +void io_thread() +{ + while (true) + { + u8 scancode; + while (!scancode_queue.try_pop(scancode)) { kernel_sleep(10); } + + kinfoln("Read scancode: %#hhx", scancode); + } +} + // Called from _asm_interrupt_entry extern "C" void arch_interrupt_entry(Registers* regs) { if (regs->isr < 32) handle_x86_exception(regs); - else if (regs->isr == 32) + else if (regs->isr == 32) // Timer interrupt { Timer::tick(); if (should_invoke_scheduler()) Scheduler::invoke(regs); pic_eoi(regs); } + else if (regs->isr == 33) // Keyboard interrupt + { + u8 scancode = IO::inb(0x60); + scancode_queue.try_push(scancode); + pic_eoi(regs); + } else { kwarnln("IRQ catched! Halting."); @@ -151,6 +172,8 @@ namespace CPU void platform_finish_init() { + Scheduler::new_kernel_thread(io_thread).expect_value("Could not create the IO background thread!"); + remap_pic(); } diff --git a/kernel/src/arch/x86_64/init/IDT.cpp b/kernel/src/arch/x86_64/init/IDT.cpp index eb1d01e6..00ad454b 100644 --- a/kernel/src/arch/x86_64/init/IDT.cpp +++ b/kernel/src/arch/x86_64/init/IDT.cpp @@ -82,6 +82,7 @@ INT(19); INT(20); INT(21); INT(32); +INT(33); void setup_idt() { @@ -108,6 +109,7 @@ void setup_idt() TRAP(20); TRAP(21); IRQ(32); + IRQ(33); static IDTR idtr; idtr.limit = 0x0FFF; diff --git a/kernel/src/arch/x86_64/init/PIC.cpp b/kernel/src/arch/x86_64/init/PIC.cpp index a3af5be2..632c94a0 100644 --- a/kernel/src/arch/x86_64/init/PIC.cpp +++ b/kernel/src/arch/x86_64/init/PIC.cpp @@ -36,7 +36,7 @@ void remap_pic() IO::outb(PIC2_DATA, ICW4_8086); io_delay(); - IO::outb(PIC1_DATA, 0b11111110); + IO::outb(PIC1_DATA, 0b11111100); io_delay(); IO::outb(PIC2_DATA, 0b11111111); } diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 83519890..7237c191 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -12,25 +12,12 @@ #include "memory/MemoryManager.h" #include "thread/Scheduler.h" #include +#include #include #include extern const BOOTBOOT bootboot; -void async_thread() -{ - while (true) - { - Thread* current = Scheduler::current(); - kinfoln("Ticks: %lu, %lu user, %lu kernel, %lu idle", current->ticks, current->ticks_in_user, - current->ticks_in_kernel, Scheduler::idle()->ticks); - - CPU::wait_for_interrupt(); - - kernel_sleep(1000); - } -} - void heap_thread() { CPU::disable_interrupts(); @@ -90,7 +77,6 @@ Result init() Thread::init(); Scheduler::init(); - TRY(Scheduler::new_kernel_thread(async_thread)); TRY(Scheduler::new_kernel_thread(heap_thread)); TRY(Scheduler::new_kernel_thread(reap_thread)); diff --git a/luna/include/luna/CircularQueue.h b/luna/include/luna/CircularQueue.h new file mode 100644 index 00000000..3960854e --- /dev/null +++ b/luna/include/luna/CircularQueue.h @@ -0,0 +1,57 @@ +#pragma once +#include +#include + +template class CircularQueue +{ + enum + { + Capacity = Size + 1 + }; + + public: + CircularQueue() + { + } + + bool try_push(const T& value) + { + usize current_tail = m_tail.load(MemoryOrder::Relaxed); + const usize new_tail = (current_tail + 1) % Capacity; + if (new_tail == m_head.load(MemoryOrder::Acquire)) + { + // Queue is full + return false; + } + m_data[current_tail] = value; + if (!m_tail.compare_exchange_strong(current_tail, new_tail, MemoryOrder::Release, MemoryOrder::Relaxed)) + { + // Someone else updated the tail + return false; + } + return true; + } + + bool try_pop(T& value) + { + usize current_head = m_head.load(MemoryOrder::Relaxed); + if (current_head == m_tail.load(MemoryOrder::Acquire)) + { + // Queue is empty + return false; + } + value = m_data[current_head]; + const usize new_head = (current_head + 1) % Capacity; + if (!m_head.compare_exchange_strong(current_head, new_head, MemoryOrder::Release, MemoryOrder::Relaxed)) + { + // Someone else updated the head + return false; + } + return true; + } + + private: + T m_data[Capacity]; + Atomic m_head = 0; + Atomic m_tail = 0; +};