diff options
| author | Richard Qin <richard.qin.x@gmail.com> | 2026-04-21 23:20:56 +0800 |
|---|---|---|
| committer | Richard Qin <richard.qin.x@gmail.com> | 2026-04-21 23:20:56 +0800 |
| commit | 92ac3931ec7c2ee7746d38499edd9179c943c5ac (patch) | |
| tree | f524c59467df9317cbf0a480fd542601a3f1c981 | |
| parent | f5272c51b11ec06627d748901c7747154f3bbf04 (diff) | |
| download | lume-92ac3931ec7c2ee7746d38499edd9179c943c5ac.tar.gz lume-92ac3931ec7c2ee7746d38499edd9179c943c5ac.tar.xz | |
feat: add initial implementation of PLIC and UART drivers
| -rw-r--r-- | na/drivers/plic.cc | 24 | ||||
| -rw-r--r-- | na/drivers/uart.cc | 44 |
2 files changed, 68 insertions, 0 deletions
diff --git a/na/drivers/plic.cc b/na/drivers/plic.cc new file mode 100644 index 0000000..f640a2a --- /dev/null +++ b/na/drivers/plic.cc @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* Copyright (C) 2026 Richard Qin */ + +/* + * plic.cc — Platform-Level Interrupt Controller stub + */ + +#include <lume/fdt.h> +#include <lume/vmm.h> +#include <arch/config.h> + +void plic_init() { + /* + * In a fully implemented driver, we would discover the PLIC base + * and size via FDT. For now, we map the default QEMU virt PLIC. + */ + uint64 plic_pa = arch::kDefaultPlicPA; + /* QEMU virt PLIC is 0x4000000 in size */ + vmm_map_kernel_mmio(plic_pa, 0x4000000); +} + +void plic_init_ap() { + /* AP per-CPU init */ +} diff --git a/na/drivers/uart.cc b/na/drivers/uart.cc new file mode 100644 index 0000000..802e88d --- /dev/null +++ b/na/drivers/uart.cc @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* Copyright (C) 2026 Richard Qin */ + +/* + * uart.cc — 16550a UART driver (early console) + * + * Implements the early UART output mapping required by panic and kernel_main. + */ + +#include <lume/console.h> +#include <lume/fdt.h> +#include <lume/vmm.h> +#include <lume/addr.h> +#include <arch/config.h> + +static uint64 g_uart_pa = arch::kDefaultUartPA; + +extern "C" void early_putc(char c) { + if (!g_uart_pa) return; + volatile auto* uart = reinterpret_cast<volatile uint8*>(pa_to_va(g_uart_pa)); + *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; + FdtManager::early_scan_uart(fdt_paddr, &pa); + if (pa != 0) { + g_uart_pa = pa; + } +} + +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) { + vmm_map_kernel_mmio(g_uart_pa, 0x1000); + } +} |
