os/device/serial/
uart16550.rs

1//! 16550 UART 串行端口驱动程序模块
2
3use alloc::{format, sync::Arc};
4use fdt::node::FdtNode;
5use uart_16550::MmioSerialPort;
6
7use crate::{
8    device::{
9        DRIVERS, DeviceType, Driver, SERIAL_DRIVERS, console::uart_console,
10        device_tree::DEVICE_TREE_REGISTRY, serial::SerialDriver,
11    },
12    kernel::current_memory_space,
13    mm::address::{Paddr, UsizeConvert},
14    pr_info, pr_warn,
15    sync::SpinLock,
16};
17
18/// 16550 UART 串行端口驱动程序结构体
19pub struct Uart16550 {
20    serial_port: SpinLock<MmioSerialPort>,
21}
22
23impl Driver for Uart16550 {
24    fn try_handle_interrupt(&self, irq: Option<usize>) -> bool {
25        todo!()
26    }
27
28    fn device_type(&self) -> crate::device::DeviceType {
29        DeviceType::Serial
30    }
31
32    fn get_id(&self) -> alloc::string::String {
33        format!("ns16550a")
34    }
35
36    fn as_serial(&self) -> Option<&dyn SerialDriver> {
37        Some(self)
38    }
39}
40
41impl SerialDriver for Uart16550 {
42    fn read(&self) -> u8 {
43        // Now the serial port is ready to be used. To send a byte:
44        self.serial_port.lock().receive()
45    }
46
47    fn write(&self, data: &[u8]) {
48        for &byte in data {
49            self.serial_port.lock().send(byte);
50        }
51    }
52
53    fn try_read(&self) -> Option<u8> {
54        match self.serial_port.lock().try_receive() {
55            Ok(byte) => Some(byte),
56            Err(_) => None,
57        }
58    }
59}
60
61pub fn init(node: &FdtNode) {
62    let reg = node
63        .reg()
64        .and_then(|mut reg| reg.next())
65        .expect("No reg property found for ns16550a");
66    let paddr = reg.starting_address as usize;
67    let size = reg.size.unwrap_or(0);
68    if size == 0 {
69        pr_warn!(
70            "[Device] ns16550a device tree node {} has no size",
71            node.name
72        );
73        return;
74    }
75    let vaddr = current_memory_space()
76        .lock()
77        .map_mmio(Paddr::from_usize(paddr), size)
78        .ok()
79        .expect("Failed to map MMIO region");
80    let mut serial_port = unsafe { MmioSerialPort::new(vaddr.as_usize()) };
81    serial_port.init();
82    let driver = Arc::new(Uart16550 {
83        serial_port: SpinLock::new(serial_port),
84    });
85    DRIVERS.write().push(driver.clone());
86    SERIAL_DRIVERS.write().push(driver.clone());
87    uart_console::init(driver);
88    pr_info!("[Device] Serial driver (uart16550) is initialized");
89}
90
91pub fn driver_init() {
92    DEVICE_TREE_REGISTRY.write().insert("ns16550a", init);
93}