axplat_aarch64_peripherals/
pl011.rs1use arm_pl011::Pl011Uart;
4use axplat::mem::VirtAddr;
5use kspin::SpinNoIrq;
6use lazyinit::LazyInit;
7
8static UART: LazyInit<SpinNoIrq<Pl011Uart>> = LazyInit::new();
9
10fn do_putchar(uart: &mut Pl011Uart, c: u8) {
11 match c {
12 b'\n' => {
13 uart.putchar(b'\r');
14 uart.putchar(b'\n');
15 }
16 c => uart.putchar(c),
17 }
18}
19
20pub fn putchar(c: u8) {
22 do_putchar(&mut UART.lock(), c);
23}
24
25pub fn getchar() -> Option<u8> {
27 UART.lock().getchar()
28}
29
30pub fn write_bytes(bytes: &[u8]) {
32 let mut uart = UART.lock();
33 for c in bytes {
34 do_putchar(&mut uart, *c);
35 }
36}
37
38pub fn read_bytes(bytes: &mut [u8]) -> usize {
41 let mut read_len = 0;
42 while read_len < bytes.len() {
43 if let Some(c) = getchar() {
44 bytes[read_len] = c;
45 } else {
46 break;
47 }
48 read_len += 1;
49 }
50 read_len
51}
52
53pub fn init_early(uart_base: VirtAddr) {
55 UART.init_once(SpinNoIrq::new(Pl011Uart::new(uart_base.as_mut_ptr())));
56 UART.lock().init();
57}
58
59pub fn irq_handler() {
61 let is_receive_interrupt = UART.lock().is_receive_interrupt();
62 UART.lock().ack_interrupts();
63 if is_receive_interrupt {
64 while let Some(c) = getchar() {
65 putchar(c);
66 }
67 }
68}
69
70#[macro_export]
73macro_rules! console_if_impl {
74 ($name:ident) => {
75 struct $name;
76
77 #[axplat::impl_plat_interface]
78 impl axplat::console::ConsoleIf for $name {
79 fn write_bytes(bytes: &[u8]) {
81 $crate::pl011::write_bytes(bytes);
82 }
83
84 fn read_bytes(bytes: &mut [u8]) -> usize {
88 $crate::pl011::read_bytes(bytes)
89 }
90 }
91 };
92}