From: Tulio A M Mendes Date: Thu, 5 Feb 2026 19:40:15 +0000 (-0300) Subject: hal: add UART HAL and refactor uart_console to use it X-Git-Url: https://projects.tadryanom.me/sitemap.xml?a=commitdiff_plain;h=a507e756beb74962a221e36abb597299b5502691;p=AdrOS.git hal: add UART HAL and refactor uart_console to use it --- diff --git a/include/hal/uart.h b/include/hal/uart.h new file mode 100644 index 0000000..3fa3078 --- /dev/null +++ b/include/hal/uart.h @@ -0,0 +1,7 @@ +#ifndef HAL_UART_H +#define HAL_UART_H + +void hal_uart_init(void); +void hal_uart_putc(char c); + +#endif diff --git a/src/drivers/uart_console.c b/src/drivers/uart_console.c index bc0146a..10e73dd 100644 --- a/src/drivers/uart_console.c +++ b/src/drivers/uart_console.c @@ -1,68 +1,14 @@ #include #include "uart_console.h" -#include "io.h" -/* - * Hardware Constants - * These should ideally be in a platform-specific config or Device Tree. - * For now, we hardcode for QEMU 'virt' and x86 standard PC. - */ - -#if defined(__i386__) || defined(__x86_64__) - #define UART_IS_PORT_IO 1 - #define UART_BASE 0x3F8 // COM1 -#elif defined(__aarch64__) - #define UART_IS_PORT_IO 0 - #define UART_BASE 0x09000000 // PL011 on QEMU virt -#elif defined(__riscv) - #define UART_IS_PORT_IO 0 - #define UART_BASE 0x10000000 // NS16550A on QEMU virt -#else - #define UART_IS_PORT_IO 0 - #define UART_BASE 0 // Unknown -#endif +#include "hal/uart.h" void uart_init(void) { -#if defined(__i386__) || defined(__x86_64__) - outb(UART_BASE + 1, 0x00); // Disable all interrupts - outb(UART_BASE + 3, 0x80); // Enable DLAB (set baud rate divisor) - outb(UART_BASE + 0, 0x03); // Set divisor to 3 (lo byte) 38400 baud - outb(UART_BASE + 1, 0x00); // (hi byte) - outb(UART_BASE + 3, 0x03); // 8 bits, no parity, one stop bit - outb(UART_BASE + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold - outb(UART_BASE + 4, 0x0B); // IRQs enabled, RTS/DSR set -#elif defined(__riscv) - // NS16550A setup (minimal) - mmio_write8(UART_BASE + 3, 0x03); // LCR: 8-bit, no parity - mmio_write8(UART_BASE + 2, 0x01); // FCR: Enable FIFO - mmio_write8(UART_BASE + 1, 0x01); // IER: Enable TX interrupts (optional) -#elif defined(__aarch64__) - // PL011 setup (simplified, assumes firmware initialized clocks) - // Actually PL011 is different register map than 16550. - // Base registers are 32-bit aligned usually. - // For now, relies on QEMU default state or minimal write. - // (Real implementation requires full PL011 driver logic) -#endif + hal_uart_init(); } void uart_put_char(char c) { -#if defined(__aarch64__) - // PL011 Register map - // DR (Data Register) is at offset 0x00 - // FR (Flag Register) is at offset 0x18. Bit 5 is TXFF (Transmit FIFO Full). - volatile uint32_t* uart = (volatile uint32_t*)UART_BASE; - while (uart[6] & (1 << 5)) { ; } // Wait while TXFF is set - uart[0] = c; -#else - // 16550 / x86 logic - if (UART_IS_PORT_IO) { - while ((inb(UART_BASE + 5) & 0x20) == 0); // Wait for empty transmit holding register - outb(UART_BASE, c); - } else { - while ((mmio_read8(UART_BASE + 5) & 0x20) == 0); - mmio_write8(UART_BASE, c); - } -#endif + hal_uart_putc(c); } void uart_print(const char* str) { diff --git a/src/hal/arm/uart.c b/src/hal/arm/uart.c new file mode 100644 index 0000000..dc9e74a --- /dev/null +++ b/src/hal/arm/uart.c @@ -0,0 +1,13 @@ +#include "hal/uart.h" +#include + +#define UART_BASE 0x09000000 + +void hal_uart_init(void) { +} + +void hal_uart_putc(char c) { + volatile uint32_t* uart = (volatile uint32_t*)UART_BASE; + while (uart[6] & (1 << 5)) { } + uart[0] = (uint32_t)c; +} diff --git a/src/hal/mips/uart.c b/src/hal/mips/uart.c new file mode 100644 index 0000000..4b76f62 --- /dev/null +++ b/src/hal/mips/uart.c @@ -0,0 +1,17 @@ +#include "hal/uart.h" +#include "io.h" +#include + +/* + * QEMU MIPS Malta exposes a 16550-compatible UART at 0xBFD003F8. + */ +#define UART_BASE 0xBFD003F8 + +void hal_uart_init(void) { + /* Minimal init: assume firmware/QEMU defaults are usable */ +} + +void hal_uart_putc(char c) { + while ((mmio_read8(UART_BASE + 5) & 0x20) == 0) { } + mmio_write8(UART_BASE, (uint8_t)c); +} diff --git a/src/hal/riscv/uart.c b/src/hal/riscv/uart.c new file mode 100644 index 0000000..3da0906 --- /dev/null +++ b/src/hal/riscv/uart.c @@ -0,0 +1,15 @@ +#include "hal/uart.h" +#include "io.h" + +#define UART_BASE 0x10000000 + +void hal_uart_init(void) { + mmio_write8(UART_BASE + 3, 0x03); + mmio_write8(UART_BASE + 2, 0x01); + mmio_write8(UART_BASE + 1, 0x01); +} + +void hal_uart_putc(char c) { + while ((mmio_read8(UART_BASE + 5) & 0x20) == 0) { } + mmio_write8(UART_BASE, (uint8_t)c); +} diff --git a/src/hal/x86/uart.c b/src/hal/x86/uart.c new file mode 100644 index 0000000..05458a5 --- /dev/null +++ b/src/hal/x86/uart.c @@ -0,0 +1,21 @@ +#include "hal/uart.h" +#include "io.h" + +#include + +#define UART_BASE 0x3F8 + +void hal_uart_init(void) { + outb(UART_BASE + 1, 0x00); + outb(UART_BASE + 3, 0x80); + outb(UART_BASE + 0, 0x03); + outb(UART_BASE + 1, 0x00); + outb(UART_BASE + 3, 0x03); + outb(UART_BASE + 2, 0xC7); + outb(UART_BASE + 4, 0x0B); +} + +void hal_uart_putc(char c) { + while ((inb(UART_BASE + 5) & 0x20) == 0) { } + outb(UART_BASE, (uint8_t)c); +}