From bd0b2c54a1340440611bc42c4506289630327eb8 Mon Sep 17 00:00:00 2001 From: Tulio A M Mendes Date: Thu, 5 Feb 2026 17:46:17 -0300 Subject: [PATCH] hal: add timer/keyboard/video HAL and refactor drivers --- include/hal/keyboard.h | 8 +++++ include/hal/timer.h | 10 ++++++ include/hal/video.h | 8 +++++ src/drivers/keyboard.c | 68 ++++-------------------------------- src/drivers/timer.c | 26 +++----------- src/drivers/vga_console.c | 15 ++++++-- src/hal/arm/keyboard.c | 5 +++ src/hal/arm/timer.c | 6 ++++ src/hal/arm/video.c | 5 +++ src/hal/mips/keyboard.c | 5 +++ src/hal/mips/timer.c | 6 ++++ src/hal/mips/video.c | 5 +++ src/hal/riscv/keyboard.c | 5 +++ src/hal/riscv/timer.c | 6 ++++ src/hal/riscv/video.c | 5 +++ src/hal/x86/keyboard.c | 73 +++++++++++++++++++++++++++++++++++++++ src/hal/x86/timer.c | 31 +++++++++++++++++ src/hal/x86/video.c | 16 +++++++++ src/kernel/main.c | 9 ++--- 19 files changed, 223 insertions(+), 89 deletions(-) create mode 100644 include/hal/keyboard.h create mode 100644 include/hal/timer.h create mode 100644 include/hal/video.h create mode 100644 src/hal/arm/keyboard.c create mode 100644 src/hal/arm/timer.c create mode 100644 src/hal/arm/video.c create mode 100644 src/hal/mips/keyboard.c create mode 100644 src/hal/mips/timer.c create mode 100644 src/hal/mips/video.c create mode 100644 src/hal/riscv/keyboard.c create mode 100644 src/hal/riscv/timer.c create mode 100644 src/hal/riscv/video.c create mode 100644 src/hal/x86/keyboard.c create mode 100644 src/hal/x86/timer.c create mode 100644 src/hal/x86/video.c diff --git a/include/hal/keyboard.h b/include/hal/keyboard.h new file mode 100644 index 0000000..a2cc84c --- /dev/null +++ b/include/hal/keyboard.h @@ -0,0 +1,8 @@ +#ifndef HAL_KEYBOARD_H +#define HAL_KEYBOARD_H + +typedef void (*hal_keyboard_char_cb_t)(char c); + +void hal_keyboard_init(hal_keyboard_char_cb_t cb); + +#endif diff --git a/include/hal/timer.h b/include/hal/timer.h new file mode 100644 index 0000000..12096f1 --- /dev/null +++ b/include/hal/timer.h @@ -0,0 +1,10 @@ +#ifndef HAL_TIMER_H +#define HAL_TIMER_H + +#include + +typedef void (*hal_timer_tick_cb_t)(void); + +void hal_timer_init(uint32_t frequency_hz, hal_timer_tick_cb_t tick_cb); + +#endif diff --git a/include/hal/video.h b/include/hal/video.h new file mode 100644 index 0000000..5d45446 --- /dev/null +++ b/include/hal/video.h @@ -0,0 +1,8 @@ +#ifndef HAL_VIDEO_H +#define HAL_VIDEO_H + +#include + +uint16_t* hal_video_text_buffer(void); + +#endif diff --git a/src/drivers/keyboard.c b/src/drivers/keyboard.c index dbb5227..5d544ef 100644 --- a/src/drivers/keyboard.c +++ b/src/drivers/keyboard.c @@ -1,76 +1,20 @@ #include "keyboard.h" -#include "idt.h" -#include "io.h" #include "uart_console.h" #include -static keyboard_callback_t active_callback = NULL; +#include "hal/keyboard.h" -// US QWERTY Map (Scancodes 0x00 - 0x39) -// 0 means unmapped or special key -static char scancode_map[128] = { - 0, 27, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b', /* Backspace */ - '\t', /* Tab */ - 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', /* Enter key */ - 0, /* 29 - Control */ - 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', 0, /* Left shift */ - '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 0, /* Right shift */ - '*', - 0, /* Alt */ - ' ', /* Space bar */ - 0, /* Caps lock */ - 0, /* 59 - F1 key ... > */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, /* < ... F10 */ - 0, /* 69 - Num lock*/ - 0, /* Scroll Lock */ - 0, /* Home key */ - 0, /* Up Arrow */ - 0, /* Page Up */ - -1, /* Minus */ - 0, /* Left Arrow */ - 0, - 0, /* Right Arrow */ - '+', - 0, /* 79 - End key*/ - 0, /* Down Arrow */ - 0, /* Page Down */ - 0, /* Insert Key */ - 0, /* Delete Key */ - 0, 0, 0, - 0, /* F11 Key */ - 0, /* F12 Key */ - 0, /* All other keys are undefined */ -}; +static keyboard_callback_t active_callback = NULL; -void keyboard_handler_impl(struct registers* regs) { - (void)regs; - - // Read status - uint8_t status = inb(0x64); - - // Check if buffer is full - if (status & 0x01) { - uint8_t scancode = inb(0x60); - - // If highest bit set, it's a key release - if (scancode & 0x80) { - // TODO: Handle shift release - } else { - // Key Press - if (scancode < 128) { - char c = scancode_map[scancode]; - if (c != 0 && active_callback) { - active_callback(c); - } - } - } +static void hal_kbd_bridge(char c) { + if (active_callback) { + active_callback(c); } } void keyboard_init(void) { uart_print("[KBD] Initializing Keyboard Driver...\n"); - register_interrupt_handler(33, keyboard_handler_impl); + hal_keyboard_init(hal_kbd_bridge); } void keyboard_set_callback(keyboard_callback_t callback) { diff --git a/src/drivers/timer.c b/src/drivers/timer.c index 293cc4f..be453eb 100644 --- a/src/drivers/timer.c +++ b/src/drivers/timer.c @@ -1,38 +1,22 @@ #include "timer.h" -#include "idt.h" -#include "io.h" #include "uart_console.h" #include "process.h" +#include "hal/timer.h" + static uint32_t tick = 0; uint32_t get_tick_count(void) { return tick; } -void timer_callback(struct registers* regs) { - (void)regs; +static void hal_tick_bridge(void) { tick++; - - // Check if anyone needs to wake up process_wake_check(tick); - - // Every 100 ticks (approx 2 sec at 50Hz), print dot - if (tick % 100 == 0) { - // uart_print("."); - } - schedule(); } void timer_init(uint32_t frequency) { - uart_print("[TIMER] Initializing PIT...\n"); - register_interrupt_handler(32, timer_callback); - - uint32_t divisor = 1193180 / frequency; - outb(0x43, 0x36); - uint8_t l = (uint8_t)(divisor & 0xFF); - uint8_t h = (uint8_t)( (divisor>>8) & 0xFF ); - outb(0x40, l); - outb(0x40, h); + uart_print("[TIMER] Initializing...\n"); + hal_timer_init(frequency, hal_tick_bridge); } diff --git a/src/drivers/vga_console.c b/src/drivers/vga_console.c index 812dd4c..b3d71a1 100644 --- a/src/drivers/vga_console.c +++ b/src/drivers/vga_console.c @@ -1,6 +1,8 @@ #include "vga_console.h" -static volatile uint16_t* const VGA_BUFFER = (uint16_t*) 0xB8000; +#include "hal/video.h" + +static volatile uint16_t* VGA_BUFFER = 0; static const int VGA_WIDTH = 80; static const int VGA_HEIGHT = 25; @@ -9,9 +11,14 @@ static int term_row = 0; static uint8_t term_color = 0x0F; // White on Black void vga_init(void) { + VGA_BUFFER = (volatile uint16_t*)hal_video_text_buffer(); term_col = 0; term_row = 0; term_color = 0x07; // Light Grey on Black + + if (!VGA_BUFFER) { + return; + } for (int y = 0; y < VGA_HEIGHT; y++) { for (int x = 0; x < VGA_WIDTH; x++) { @@ -19,7 +26,11 @@ void vga_init(void) { VGA_BUFFER[index] = (uint16_t) ' ' | (uint16_t) term_color << 8; } } -} +}!VGA_BUFFER) { + return; + } + + if ( void vga_set_color(uint8_t fg, uint8_t bg) { term_color = fg | (bg << 4); diff --git a/src/hal/arm/keyboard.c b/src/hal/arm/keyboard.c new file mode 100644 index 0000000..6ed8bf5 --- /dev/null +++ b/src/hal/arm/keyboard.c @@ -0,0 +1,5 @@ +#include "hal/keyboard.h" + +void hal_keyboard_init(hal_keyboard_char_cb_t cb) { + (void)cb; +} diff --git a/src/hal/arm/timer.c b/src/hal/arm/timer.c new file mode 100644 index 0000000..0ea54a0 --- /dev/null +++ b/src/hal/arm/timer.c @@ -0,0 +1,6 @@ +#include "hal/timer.h" + +void hal_timer_init(uint32_t frequency_hz, hal_timer_tick_cb_t tick_cb) { + (void)frequency_hz; + (void)tick_cb; +} diff --git a/src/hal/arm/video.c b/src/hal/arm/video.c new file mode 100644 index 0000000..474c9ff --- /dev/null +++ b/src/hal/arm/video.c @@ -0,0 +1,5 @@ +#include "hal/video.h" + +uint16_t* hal_video_text_buffer(void) { + return (uint16_t*)0; +} diff --git a/src/hal/mips/keyboard.c b/src/hal/mips/keyboard.c new file mode 100644 index 0000000..6ed8bf5 --- /dev/null +++ b/src/hal/mips/keyboard.c @@ -0,0 +1,5 @@ +#include "hal/keyboard.h" + +void hal_keyboard_init(hal_keyboard_char_cb_t cb) { + (void)cb; +} diff --git a/src/hal/mips/timer.c b/src/hal/mips/timer.c new file mode 100644 index 0000000..0ea54a0 --- /dev/null +++ b/src/hal/mips/timer.c @@ -0,0 +1,6 @@ +#include "hal/timer.h" + +void hal_timer_init(uint32_t frequency_hz, hal_timer_tick_cb_t tick_cb) { + (void)frequency_hz; + (void)tick_cb; +} diff --git a/src/hal/mips/video.c b/src/hal/mips/video.c new file mode 100644 index 0000000..474c9ff --- /dev/null +++ b/src/hal/mips/video.c @@ -0,0 +1,5 @@ +#include "hal/video.h" + +uint16_t* hal_video_text_buffer(void) { + return (uint16_t*)0; +} diff --git a/src/hal/riscv/keyboard.c b/src/hal/riscv/keyboard.c new file mode 100644 index 0000000..6ed8bf5 --- /dev/null +++ b/src/hal/riscv/keyboard.c @@ -0,0 +1,5 @@ +#include "hal/keyboard.h" + +void hal_keyboard_init(hal_keyboard_char_cb_t cb) { + (void)cb; +} diff --git a/src/hal/riscv/timer.c b/src/hal/riscv/timer.c new file mode 100644 index 0000000..0ea54a0 --- /dev/null +++ b/src/hal/riscv/timer.c @@ -0,0 +1,6 @@ +#include "hal/timer.h" + +void hal_timer_init(uint32_t frequency_hz, hal_timer_tick_cb_t tick_cb) { + (void)frequency_hz; + (void)tick_cb; +} diff --git a/src/hal/riscv/video.c b/src/hal/riscv/video.c new file mode 100644 index 0000000..474c9ff --- /dev/null +++ b/src/hal/riscv/video.c @@ -0,0 +1,5 @@ +#include "hal/video.h" + +uint16_t* hal_video_text_buffer(void) { + return (uint16_t*)0; +} diff --git a/src/hal/x86/keyboard.c b/src/hal/x86/keyboard.c new file mode 100644 index 0000000..aefa2ce --- /dev/null +++ b/src/hal/x86/keyboard.c @@ -0,0 +1,73 @@ +#include "hal/keyboard.h" + +#if defined(__i386__) +#include "idt.h" +#include "io.h" + +static hal_keyboard_char_cb_t g_cb = 0; + +static char scancode_map[128] = { + 0, 27, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b', + '\t', + 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', + 0, + 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', 0, + '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 0, + '*', + 0, + ' ', + 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + -1, + 0, + 0, + 0, + '+', + 0, + 0, + 0, + 0, + 0, + 0, 0, 0, + 0, + 0, + 0, +}; + +static void kbd_irq(struct registers* regs) { + (void)regs; + + uint8_t status = inb(0x64); + if (status & 0x01) { + uint8_t scancode = inb(0x60); + + if (!(scancode & 0x80)) { + if (scancode < 128) { + char c = scancode_map[scancode]; + if (c != 0 && g_cb) { + g_cb(c); + } + } + } + } +} + +void hal_keyboard_init(hal_keyboard_char_cb_t cb) { + g_cb = cb; + register_interrupt_handler(33, kbd_irq); +} +#else +void hal_keyboard_init(hal_keyboard_char_cb_t cb) { + (void)cb; +} +#endif diff --git a/src/hal/x86/timer.c b/src/hal/x86/timer.c new file mode 100644 index 0000000..710abb9 --- /dev/null +++ b/src/hal/x86/timer.c @@ -0,0 +1,31 @@ +#include "hal/timer.h" + +#if defined(__i386__) +#include "idt.h" +#include "io.h" + +static hal_timer_tick_cb_t g_tick_cb = 0; + +static void timer_irq(struct registers* regs) { + (void)regs; + if (g_tick_cb) g_tick_cb(); +} + +void hal_timer_init(uint32_t frequency_hz, hal_timer_tick_cb_t tick_cb) { + g_tick_cb = tick_cb; + + register_interrupt_handler(32, timer_irq); + + uint32_t divisor = 1193180 / frequency_hz; + outb(0x43, 0x36); + uint8_t l = (uint8_t)(divisor & 0xFF); + uint8_t h = (uint8_t)((divisor >> 8) & 0xFF); + outb(0x40, l); + outb(0x40, h); +} +#else +void hal_timer_init(uint32_t frequency_hz, hal_timer_tick_cb_t tick_cb) { + (void)frequency_hz; + (void)tick_cb; +} +#endif diff --git a/src/hal/x86/video.c b/src/hal/x86/video.c new file mode 100644 index 0000000..210af46 --- /dev/null +++ b/src/hal/x86/video.c @@ -0,0 +1,16 @@ +#include "hal/video.h" + +#if defined(__i386__) || defined(__x86_64__) + +// This address must be mapped by VMM in higher half (see vmm_init mapping) +#define VGA_TEXT_BUFFER_VIRT ((uint16_t*)0xC00B8000) + +uint16_t* hal_video_text_buffer(void) { + return (uint16_t*)VGA_TEXT_BUFFER_VIRT; +} + +#else +uint16_t* hal_video_text_buffer(void) { + return (uint16_t*)0; +} +#endif diff --git a/src/kernel/main.c b/src/kernel/main.c index d418bac..5578fca 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -32,10 +32,6 @@ void kernel_main(unsigned long magic, unsigned long addr) { uart_print("\n[AdrOS] Booting...\n"); #if defined(__i386__) || defined(__x86_64__) - vga_init(); - vga_set_color(0x0A, 0x00); - vga_print("[AdrOS] Kernel Initialized (VGA).\n"); - // Check Multiboot2 Magic if (magic != 0x36d76289) { uart_print("[ERR] Invalid Multiboot2 Magic!\n"); @@ -53,6 +49,11 @@ void kernel_main(unsigned long magic, unsigned long addr) { uart_print("[AdrOS] Initializing VMM...\n"); #if defined(__i386__) vmm_init(); + + // VGA console depends on higher-half mapping (VMM) + vga_init(); + vga_set_color(0x0A, 0x00); + vga_print("[AdrOS] Kernel Initialized (VGA).\n"); // 4. Initialize Kernel Heap kheap_init(); -- 2.43.0