diff options
| author | Richard Qin <richard.qin.x@gmail.com> | 2026-10-16 02:39:56 +0800 |
|---|---|---|
| committer | Richard Qin <richard.qin.x@gmail.com> | 2026-10-16 02:39:56 +0800 |
| commit | 8cace3f05003c6cb4d38c36890055f03151c2ad4 (patch) | |
| tree | aa739deaac0266f17c4e91b333957501cb1ea2e9 /drivers/tty/tty_uart.cc | |
| parent | 3ad39e9878310e5317ee73c9b353c1e2c1c5c4ee (diff) | |
| download | lume-8cace3f05003c6cb4d38c36890055f03151c2ad4.tar.gz lume-8cace3f05003c6cb4d38c36890055f03151c2ad4.tar.xz | |
Remove old code
Signed-off-by: Richard Qin <richard.qin.x@gmail.com>
Diffstat (limited to 'drivers/tty/tty_uart.cc')
| -rw-r--r-- | drivers/tty/tty_uart.cc | 251 |
1 files changed, 0 insertions, 251 deletions
diff --git a/drivers/tty/tty_uart.cc b/drivers/tty/tty_uart.cc deleted file mode 100644 index 973a6e9..0000000 --- a/drivers/tty/tty_uart.cc +++ /dev/null @@ -1,251 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -/* - * tty_uart.cc — UART → tty_driver adapter - * - * Bridges the 16550A UART hardware to the TTY subsystem. - * - * TX: Calls early_putc() for each character (same as before). - * RX: Registers a PLIC IRQ handler. On UART RX interrupt, - * reads available bytes and feeds them to the line discipline - * via tty_receive_buf(). - * - * QEMU virt UART: - * - IRQ 10 on the PLIC - * - 16550A register layout at the base address discovered from FDT - */ - -#include <lume/tty.h> -#include <lume/irq.h> -#include <lume/addr.h> -#include <lume/fdt.h> -#include <lume/vmm.h> -#include <lume/errno.h> -#include <lume/klog.h> - -#ifndef ENOIOCTLCMD -#define ENOIOCTLCMD 515 -#endif - -extern "C" void early_putc(char c); - -/* 16550A register offsets */ -static constexpr int UART_RBR = 0; /* Receive Buffer Register */ -static constexpr int UART_THR = 0; /* Transmit Holding Register */ -static constexpr int UART_IER = 1; /* Interrupt Enable Register */ -static constexpr int UART_IIR = 2; /* Interrupt Identification Register */ -static constexpr int UART_FCR = 2; /* FIFO Control Register */ -static constexpr int UART_LCR = 3; /* Line Control Register */ -static constexpr int UART_MCR = 4; /* Modem Control Register */ -static constexpr int UART_LSR = 5; /* Line Status Register */ - -/* LSR bits */ -static constexpr uint8 UART_LSR_DR = 0x01; /* Data Ready */ -static constexpr uint8 UART_LSR_THRE = 0x20; /* TX Holding Register Empty */ - -/* IER bits */ -static constexpr uint8 UART_IER_RDI = 0x01; /* Received Data Available */ - -/* MCR bits */ -static constexpr uint8 UART_MCR_DTR = 0x01; /* Data Terminal Ready */ -static constexpr uint8 UART_MCR_RTS = 0x02; /* Request To Send */ -static constexpr uint8 UART_MCR_OUT2 = 0x08; /* Auxiliary output 2 — gates the - IRQ pin on PC-style 16550A. - Without this the UART - internally asserts but does - NOT propagate to the PLIC. */ - -/* QEMU virt default UART IRQ */ -static constexpr uint32 UART_IRQ = 10; - -/* UART MMIO base (virtual address) */ -static volatile uint8* g_uart_base; -static tty_struct* g_uart_tty; - -/* ================================================================== */ -/* UART MMIO helpers */ -/* ================================================================== */ - -static inline uint8 uart_read(int reg) -{ - return g_uart_base[reg]; -} - -static inline void uart_write(int reg, uint8 val) -{ - g_uart_base[reg] = val; -} - -static inline bool uart_rx_ready() -{ - return (uart_read(UART_LSR) & UART_LSR_DR) != 0; -} - -static inline char uart_rx_char() -{ - return static_cast<char>(uart_read(UART_RBR)); -} - -/* ================================================================== */ -/* UART RX interrupt handler */ -/* ================================================================== */ - -static void uart_irq_handler(uint32 /*irq*/, void* arg) -{ - auto* tty = static_cast<tty_struct*>(arg); - - /* Read all available bytes from the FIFO */ - char buf[16]; - int count = 0; - - while (uart_rx_ready() && count < 16) { - buf[count++] = uart_rx_char(); - } - - if (count > 0) { - tty_receive_buf(tty, buf, count); - } -} - -/* ================================================================== */ -/* tty_driver_ops for UART */ -/* ================================================================== */ - -static int uart_tty_open_op(tty_struct* /*tty*/) -{ - return 0; -} - -static void uart_tty_close_op(tty_struct* /*tty*/) -{ - /* Nothing to do */ -} - -static int uart_tty_write_op(tty_struct* /*tty*/, const char* buf, int count) -{ - for (int i = 0; i < count; i++) { - early_putc(buf[i]); - } - return count; -} - -static int uart_tty_write_room_op(tty_struct* /*tty*/) -{ - return TTY_BUF_SIZE; /* Always room (blocking putc) */ -} - -static void uart_tty_put_char_op(tty_struct* /*tty*/, char ch) -{ - early_putc(ch); -} - -static void uart_tty_flush_chars_op(tty_struct* /*tty*/) -{ - /* No buffering in early_putc, nothing to flush */ -} - -static int uart_tty_chars_in_buffer_op(tty_struct* /*tty*/) -{ - return 0; /* No TX buffer */ -} - -static void uart_tty_flush_buffer_op(tty_struct* /*tty*/) -{ - /* No TX buffer to flush */ -} - -static int uart_tty_ioctl_op(tty_struct* /*tty*/, unsigned int /*cmd*/, uint64 /*arg*/) -{ - return -ENOIOCTLCMD; -} - -static void uart_tty_hangup_op(tty_struct* /*tty*/) -{ - /* Disable UART RX interrupts */ - if (g_uart_base) { - uart_write(UART_IER, 0); - } -} - -static const tty_driver_ops uart_ops = { - .open = uart_tty_open_op, - .close = uart_tty_close_op, - .write = uart_tty_write_op, - .write_room = uart_tty_write_room_op, - .put_char = uart_tty_put_char_op, - .flush_chars = uart_tty_flush_chars_op, - .chars_in_buffer = uart_tty_chars_in_buffer_op, - .flush_buffer = uart_tty_flush_buffer_op, - .ioctl = uart_tty_ioctl_op, - .throttle = nullptr, - .unthrottle = nullptr, - .hangup = uart_tty_hangup_op, -}; - -const tty_driver uart_tty_driver = { - .name = "ttyS", - .major = 4, - .minor_start = 64, - .num = 1, - .ops = &uart_ops, -}; - -/* ================================================================== */ -/* UART TTY init — discover base address, enable RX IRQ */ -/* ================================================================== */ - -void uart_tty_init(tty_struct* tty) -{ - g_uart_tty = tty; - - /* Discover UART base from FDT */ - DeviceNode* node = fdt_find_compatible("ns16550a"); - if (!node) { - /* Try alternative compatible string */ - node = fdt_find_compatible("snps,dw-apb-uart"); - } - - uint64 uart_pa = 0; - if (node) { - uart_pa = node->get_prop_u64("reg", 0); - } - - if (uart_pa == 0) { - /* Fallback: QEMU virt default */ - uart_pa = 0x10000000; - } - - g_uart_base = reinterpret_cast<volatile uint8*>( - pa_to_va(phys_addr(uart_pa)).raw); - - /* Set FIFO control: enable FIFOs, clear RX/TX FIFOs, 1-byte trigger */ - uart_write(UART_FCR, 0x07); - - /* MCR: assert OUT2 (gates the IRQ pin on PC-style 16550A), plus - * DTR/RTS for completeness. Mirrors Linux drivers/tty/serial/8250/ - * 8250_port.c: serial8250_do_startup() does the same. */ - uart_write(UART_MCR, UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2); - - /* Enable UART receive-data-available interrupt */ - uart_write(UART_IER, UART_IER_RDI); - - /* Register IRQ handler with PLIC */ - uint32 irq = UART_IRQ; - if (node) { - /* Try to get IRQ number from FDT */ - const FdtProperty* irq_prop = node->get_prop("interrupts"); - if (irq_prop && irq_prop->len >= 4) { - const uint8* val = static_cast<const uint8*>(irq_prop->value); - irq = (uint32(val[0]) << 24) | (uint32(val[1]) << 16) | - (uint32(val[2]) << 8) | val[3]; - } - } - - g_irq_manager.register_handler(irq, uart_irq_handler, tty); - g_irq_manager.enable(irq); - - printk(KERN_INFO "uart_tty_init: base=0x%llx irq=%u IER=0x%x LSR=0x%x\n", - (unsigned long long)uart_pa, irq, - uart_read(UART_IER), uart_read(UART_LSR)); -} |
