x86_64: Add basic keyboard support with an ASYNC DRIVER
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
apio 2022-12-26 19:59:18 +01:00
parent ed34009b50
commit 7952d1d8a0
Signed by: apio
GPG Key ID: B8A7D06E42258954
6 changed files with 87 additions and 18 deletions

View File

@ -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
IRQ 32, 0 ; timer interrupt
IRQ 33, 0 ; keyboard interrupt

View File

@ -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 <cpuid.h>
#include <luna/CString.h>
#include <luna/CircularQueue.h>
#include <luna/Result.h>
#include <luna/SystemError.h>
#include <luna/Types.h>
@ -76,16 +78,35 @@ extern "C" void handle_x86_exception(Registers* regs)
}
}
CircularQueue<u8, 60> 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();
}

View File

@ -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;

View File

@ -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);
}

View File

@ -12,25 +12,12 @@
#include "memory/MemoryManager.h"
#include "thread/Scheduler.h"
#include <luna/CString.h>
#include <luna/CircularQueue.h>
#include <luna/Result.h>
#include <luna/Units.h>
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<void> 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));

View File

@ -0,0 +1,57 @@
#pragma once
#include <luna/Atomic.h>
#include <luna/Types.h>
template <typename T, usize Size> 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<usize> m_head = 0;
Atomic<usize> m_tail = 0;
};