summaryrefslogtreecommitdiff
path: root/drivers/uart.cc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/uart.cc')
-rw-r--r--drivers/uart.cc181
1 files changed, 0 insertions, 181 deletions
diff --git a/drivers/uart.cc b/drivers/uart.cc
deleted file mode 100644
index 467b496..0000000
--- a/drivers/uart.cc
+++ /dev/null
@@ -1,181 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/* Copyright (C) 2026 Richard Qin */
-
-/*
- * uart.cc — 16550a UART driver + console registry
- *
- * Two roles:
- * 1. Early console: early_putc() for pre-init output (panic, kprintf)
- * 2. Runtime console: struct console registered with register_console().
- * klog/printk route through console_write_all() → uart_console_write().
- *
- * The console registry is a simple linked list of struct console.
- * console_write_all() iterates the list and calls each console's write().
- * If no console is registered, it falls back to early_putc().
- *
- * Reference: Linux kernel/printk/printk.c, drivers/tty/serial/8250/
- */
-
-#include <lume/console.h>
-#include <lume/fdt.h>
-#include <lume/vmm.h>
-#include <lume/addr.h>
-#include <arch/config.h>
-
-/* ================================================================== */
-/* UART state */
-/* ================================================================== */
-
-static uint64 g_uart_pa = 0;
-static uint64 g_uart_size = 0;
-static bool g_runtime_mapping_ready = false;
-static bool g_mmu_enabled = false;
-
-/* ================================================================== */
-/* Early console (Phase 1) */
-/* ================================================================== */
-
-extern "C" void console_set_mmu_enabled() {
- g_mmu_enabled = true;
-}
-
-extern "C" void early_putc(char c) {
- if (!g_uart_pa) return;
-
- /*
- * Before vmm_init() activates the final page table, UART MMIO is only
- * reachable via the bootstrap fixed direct map from entry.S.
- * After activation, switch to the runtime (possibly KASLR-slid) base.
- */
- uint64 uart_va = 0;
- if (g_runtime_mapping_ready) {
- uart_va = pa_to_va(phys_addr(g_uart_pa)).raw;
- } else if (!g_mmu_enabled) {
- uart_va = g_uart_pa;
- } else {
- uart_va = boot_pa_to_va(phys_addr(g_uart_pa)).raw;
- }
-
- volatile auto* uart = reinterpret_cast<volatile uint8*>(uart_va);
- *uart = static_cast<uint8>(c);
-}
-
-extern "C" void early_puts(const char* s) {
- while (*s) early_putc(*s++);
-}
-
-void console_early_init(uint64 fdt_paddr) {
- uint64 pa = 0;
- uint64 size = 0;
- FdtManager::early_scan_uart(fdt_paddr, &pa, &size);
- if (pa != 0) {
- g_uart_pa = pa;
- if (size != 0) g_uart_size = size;
- }
-}
-
-void console_init() {
- /*
- * Once vmm_init() activates the new page table, the 1GB identity map is dropped.
- * The UART must be explicitly registered into the active page table.
- */
- if (g_uart_pa != 0 && g_uart_size != 0) {
- vmm_map_kernel_mmio(g_uart_pa, g_uart_size);
- }
-}
-
-void console_use_runtime_mapping() {
- g_runtime_mapping_ready = true;
-}
-
-/* ================================================================== */
-/* Console registry (Phase 2) — linked list of struct console */
-/* ================================================================== */
-
-static list_node g_console_list;
-static bool g_console_list_init = false;
-
-void register_console(console* con)
-{
- if (!con) return;
-
- if (!g_console_list_init) {
- g_console_list.init();
- g_console_list_init = true;
- }
-
- con->flags |= CON_ENABLED;
- con->list.init();
-
- /* Insert at tail */
- list_add_tail(&con->list, &g_console_list);
-}
-
-void unregister_console(console* con)
-{
- if (!con) return;
-
- list_del_init(&con->list);
- con->flags &= ~CON_ENABLED;
-}
-
-bool console_drivers_registered()
-{
- if (!g_console_list_init) return false;
- return !list_empty(&g_console_list);
-}
-
-void console_write_all(const char* s, int count)
-{
- if (g_console_list_init && !list_empty(&g_console_list)) {
- list_node* pos;
- list_for_each(pos, &g_console_list) {
- auto* con = container_of(pos, console, list);
- if ((con->flags & CON_ENABLED) && con->write) {
- con->write(con, s, static_cast<unsigned int>(count));
- }
- }
- } else {
- /* Fallback: direct early_putc (pre-registration) */
- for (int i = 0; i < count; i++) {
- early_putc(s[i]);
- }
- }
-}
-
-/* ================================================================== */
-/* UART console driver */
-/* ================================================================== */
-
-static void uart_console_write(console* /*con*/, const char* s, unsigned int count)
-{
- for (unsigned int i = 0; i < count; i++) {
- if (s[i] == '\n') {
- early_putc('\r');
- }
- early_putc(s[i]);
- }
-}
-
-/*
- * uart_console must be initialized at RUNTIME, not with static
- * aggregate initializers. Reason: KASLR self-relocation processes
- * .rela.dyn entries for simple pointer variables, but may not cover
- * function pointer fields inside static aggregate initializers.
- * A static `{ .write = uart_console_write }` would store the
- * pre-relocation address, causing a crash when called.
- */
-static console uart_console;
-
-void uart_register_console()
-{
- uart_console.name = "ttyS";
- uart_console.write = uart_console_write;
- uart_console.setup = nullptr;
- uart_console.flags = CON_ENABLED | CON_BOOT;
- uart_console.index = 0;
- uart_console.data = nullptr;
- uart_console.list.init();
- register_console(&uart_console);
-}
-