kernel/drivers/uart/
virt.rs

1// UART driver for QEMU virt machine
2
3use core::{fmt, any::Any, ptr::{read_volatile, write_volatile}};
4use core::fmt::Write;
5use alloc::boxed::Box;
6
7use crate::{early_initcall, traits::serial::Serial, device::{Device, DeviceType, char::CharDevice}};
8
9
10#[derive(Clone)]
11pub struct Uart {
12    base: usize,
13}
14
15pub const RHR_OFFSET: usize = 0x00;
16pub const THR_OFFSET: usize = 0x00;
17pub const LSR_OFFSET: usize = 0x05;
18
19pub const LSR_THRE: u8 = 0x20;
20pub const LSR_DR: u8 = 0x01;
21
22impl Uart {
23    pub fn new(base: usize) -> Self {
24        Uart { base }
25    }
26
27    fn reg_write(&self, offset: usize, value: u8) {
28        let addr = self.base + offset;
29        unsafe { write_volatile(addr as *mut u8, value) }
30    }
31
32    fn reg_read(&self, offset: usize) -> u8 {
33        let addr = self.base + offset;
34        unsafe { read_volatile(addr as *const u8) }
35    }
36
37    fn write_byte_internal(&self, c: u8) {
38        while self.reg_read(LSR_OFFSET) & LSR_THRE == 0 {}
39        self.reg_write(THR_OFFSET, c);
40    }
41
42    fn read_byte_internal(&self) -> u8 {
43        if self.reg_read(LSR_OFFSET) & LSR_DR == 0 {
44            return 0;
45        }
46        self.reg_read(RHR_OFFSET)
47    }
48}
49
50impl Serial for Uart {
51    fn init(&mut self) {
52        // Initialization code for the UART can be added here if needed.
53        // For now, we assume the UART is already initialized by the QEMU virt machine.
54    }
55
56    /// Writes a character to the UART. (blocking)
57    /// 
58    /// This function will block until the UART is ready to accept the character.
59    /// 
60    /// # Arguments
61    /// * `c` - The character to write to the UART
62    /// 
63    /// # Returns
64    /// A `fmt::Result` indicating success or failure.
65    /// 
66    fn put(&mut self, c: char) -> fmt::Result {
67        self.write_byte_internal(c as u8); // Block until ready
68        Ok(())
69    }
70
71    /// Reads a character from the UART. (non-blocking)
72    /// 
73    /// Returns `Some(char)` if a character is available, or `None` if not.
74    /// 
75    fn get(&mut self) -> Option<char> {
76        if self.can_read() {
77            Some(self.read_byte_internal() as char)
78        } else {
79            None
80        }
81    }
82}
83
84impl Device for Uart {
85    fn device_type(&self) -> DeviceType {
86        DeviceType::Char
87    }
88
89    fn name(&self) -> &'static str {
90        "virt-uart"
91    }
92
93    fn id(&self) -> usize {
94        0
95    }
96
97    fn as_any(&self) -> &dyn Any {
98        self
99    }
100    
101    fn as_any_mut(&mut self) -> &mut dyn Any {
102        self
103    }
104    
105    fn as_char_device(&mut self) -> Option<&mut dyn CharDevice> {
106        Some(self)
107    }
108}
109
110impl CharDevice for Uart {
111    fn read_byte(&mut self) -> Option<u8> {
112        if self.can_read() {
113            Some(self.read_byte_internal())
114        } else {
115            None
116        }
117    }
118
119    fn write_byte(&mut self, byte: u8) -> Result<(), &'static str> {
120        self.write_byte_internal(byte); // Block until ready
121        Ok(())
122    }
123
124    fn can_read(&self) -> bool {
125        self.reg_read(LSR_OFFSET) & LSR_DR != 0
126    }
127
128    fn can_write(&self) -> bool {
129        self.reg_read(LSR_OFFSET) & LSR_THRE != 0
130    }
131    
132}
133
134impl Write for Uart {
135    fn write_str(&mut self, s: &str) -> fmt::Result {
136        for c in s.chars() {
137            if c == '\n' {
138                self.put('\r')?; // Convert newline to carriage return + newline
139            }
140            self.put(c)?;
141        }
142        Ok(())
143    }
144}
145
146fn register_uart() {
147    let uart = Uart::new(0x1000_0000);
148    crate::device::manager::register_serial(Box::new(uart));
149}
150
151early_initcall!(register_uart);