summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Qin <richard.qin.x@gmail.com>2026-04-21 23:20:56 +0800
committerRichard Qin <richard.qin.x@gmail.com>2026-04-21 23:20:56 +0800
commit92ac3931ec7c2ee7746d38499edd9179c943c5ac (patch)
treef524c59467df9317cbf0a480fd542601a3f1c981
parentf5272c51b11ec06627d748901c7747154f3bbf04 (diff)
downloadlume-92ac3931ec7c2ee7746d38499edd9179c943c5ac.tar.gz
lume-92ac3931ec7c2ee7746d38499edd9179c943c5ac.tar.xz
feat: add initial implementation of PLIC and UART drivers
-rw-r--r--na/drivers/plic.cc24
-rw-r--r--na/drivers/uart.cc44
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);
+ }
+}