]> Projects (at) Tadryanom (dot) Me - AdrOS.git/commitdiff
hal: add UART HAL and refactor uart_console to use it
authorTulio A M Mendes <[email protected]>
Thu, 5 Feb 2026 19:40:15 +0000 (16:40 -0300)
committerTulio A M Mendes <[email protected]>
Thu, 5 Feb 2026 19:40:15 +0000 (16:40 -0300)
include/hal/uart.h [new file with mode: 0644]
src/drivers/uart_console.c
src/hal/arm/uart.c [new file with mode: 0644]
src/hal/mips/uart.c [new file with mode: 0644]
src/hal/riscv/uart.c [new file with mode: 0644]
src/hal/x86/uart.c [new file with mode: 0644]

diff --git a/include/hal/uart.h b/include/hal/uart.h
new file mode 100644 (file)
index 0000000..3fa3078
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef HAL_UART_H
+#define HAL_UART_H
+
+void hal_uart_init(void);
+void hal_uart_putc(char c);
+
+#endif
index bc0146a800efe5f67e01096fdf07597516a720a4..10e73dd2afdc5da42b8be918f7c7442e5f684df6 100644 (file)
@@ -1,68 +1,14 @@
 #include <stdint.h>
 #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 (file)
index 0000000..dc9e74a
--- /dev/null
@@ -0,0 +1,13 @@
+#include "hal/uart.h"
+#include <stdint.h>
+
+#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 (file)
index 0000000..4b76f62
--- /dev/null
@@ -0,0 +1,17 @@
+#include "hal/uart.h"
+#include "io.h"
+#include <stdint.h>
+
+/*
+ * 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 (file)
index 0000000..3da0906
--- /dev/null
@@ -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 (file)
index 0000000..05458a5
--- /dev/null
@@ -0,0 +1,21 @@
+#include "hal/uart.h"
+#include "io.h"
+
+#include <stdint.h>
+
+#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);
+}