os/device/serial/
uart16550.rs1use 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
18pub 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 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}