x86_64: Add basic keyboard support with an ASYNC DRIVER
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
ed34009b50
commit
7952d1d8a0
@ -187,3 +187,4 @@ ISR 20 ; virtualization exception (#VE)
|
||||
ISR_ERROR 21 ; control-protection exception (#CP)
|
||||
; ISR 22-31 reserved
|
||||
IRQ 32, 0 ; timer interrupt
|
||||
IRQ 33, 0 ; keyboard interrupt
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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));
|
||||
|
||||
|
57
luna/include/luna/CircularQueue.h
Normal file
57
luna/include/luna/CircularQueue.h
Normal 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;
|
||||
};
|
Loading…
Reference in New Issue
Block a user