|
|
|
@ -2,26 +2,26 @@
|
|
|
|
|
|
|
|
|
|
use core::fmt;
|
|
|
|
|
|
|
|
|
|
use crate::traits::console::{Console, Write};
|
|
|
|
|
|
|
|
|
|
use crate::traits::console::{Console, Read, Write};
|
|
|
|
|
use crate::traits::synchronization::{DummyMutex, Mutex};
|
|
|
|
|
|
|
|
|
|
/// The address for the magic qemu output
|
|
|
|
|
const QEMU_MAGIC_OUTPUT_ADDR: *mut u8 = 0x3F20_1000 as *mut u8;
|
|
|
|
|
/// The address for the magic qemu uart
|
|
|
|
|
const QEMU_MAGIC_UART_ADDR: *mut u8 = 0x3F20_1000 as *mut u8;
|
|
|
|
|
const QEMU_MAGIC_UART_ADDR_FR: *mut u8 = 0x3F20_1018 as *mut u8;
|
|
|
|
|
|
|
|
|
|
/// The unique qemu output allowing access to the qemu output.
|
|
|
|
|
static QEMU_OUTPUT: QemuOutput = QemuOutput::new();
|
|
|
|
|
/// The unique QemuUart allowing access to the qemu uart.
|
|
|
|
|
static QEMU_UART: QemuUart = QemuUart::new();
|
|
|
|
|
|
|
|
|
|
/// A structure allowing access to the qemu magic output.
|
|
|
|
|
struct QemuOutput {
|
|
|
|
|
inner: DummyMutex<QemuOutputInner>,
|
|
|
|
|
/// A structure allowing access to the qemu magic uart.
|
|
|
|
|
struct QemuUart {
|
|
|
|
|
inner: DummyMutex<QemuUartInner>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Inner Qemu output.
|
|
|
|
|
struct QemuOutputInner;
|
|
|
|
|
/// Inner Qemu Uart.
|
|
|
|
|
struct QemuUartInner;
|
|
|
|
|
|
|
|
|
|
impl QemuOutputInner {
|
|
|
|
|
/// Constructor for [`QemuOutputInner`].
|
|
|
|
|
impl QemuUartInner {
|
|
|
|
|
/// Constructor for [`QemuUartInner`].
|
|
|
|
|
const fn new() -> Self {
|
|
|
|
|
Self {}
|
|
|
|
|
}
|
|
|
|
@ -29,26 +29,39 @@ impl QemuOutputInner {
|
|
|
|
|
/// Write a character to the output.
|
|
|
|
|
fn write_char(&mut self, c: char) {
|
|
|
|
|
unsafe {
|
|
|
|
|
core::ptr::write_volatile(QEMU_MAGIC_OUTPUT_ADDR, c as u8);
|
|
|
|
|
core::ptr::write_volatile(QEMU_MAGIC_UART_ADDR, c as u8);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Read a character from the uart.
|
|
|
|
|
fn read_char(&mut self) -> char {
|
|
|
|
|
loop {
|
|
|
|
|
let fr = unsafe { core::ptr::read_volatile(QEMU_MAGIC_UART_ADDR_FR) };
|
|
|
|
|
if fr & 0b1_0000 == 0 {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
unsafe {
|
|
|
|
|
core::ptr::read_volatile(QEMU_MAGIC_UART_ADDR) as u8 as char
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl QemuOutput {
|
|
|
|
|
/// Constructor for [`QemuOutput`].
|
|
|
|
|
impl QemuUart {
|
|
|
|
|
/// Constructor for [`QemuUart`].
|
|
|
|
|
pub const fn new() -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
inner: DummyMutex::new(QemuOutputInner::new()),
|
|
|
|
|
inner: DummyMutex::new(QemuUartInner::new()),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Allow to use QemuOutputInner for print! and formating macros.
|
|
|
|
|
/// Allow to use QemuUartInner for print! and formating macros.
|
|
|
|
|
/// `write_str` needs `&mut self` (mutable ref), so we can implement
|
|
|
|
|
/// it only on the inner type, the `QemuOutput` need to be manipulable
|
|
|
|
|
/// it only on the inner type, the `QemuUart` need to be manipulable
|
|
|
|
|
/// using unmutable references (`&self`), so we will use a custom
|
|
|
|
|
/// interface for it.
|
|
|
|
|
impl fmt::Write for QemuOutputInner {
|
|
|
|
|
impl fmt::Write for QemuUartInner {
|
|
|
|
|
fn write_str(&mut self, s: &str) -> fmt::Result {
|
|
|
|
|
for c in s.chars() {
|
|
|
|
|
// \n -> \r\n
|
|
|
|
@ -61,7 +74,7 @@ impl fmt::Write for QemuOutputInner {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Write for QemuOutput {
|
|
|
|
|
impl Write for QemuUart {
|
|
|
|
|
fn write_char(&self, c: char) {
|
|
|
|
|
self.inner.lock(|q_out| q_out.write_char(c))
|
|
|
|
|
}
|
|
|
|
@ -76,10 +89,18 @@ impl Write for QemuOutput {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Console for QemuOutput {}
|
|
|
|
|
impl Read for QemuUart {
|
|
|
|
|
fn read_char(&self) -> char {
|
|
|
|
|
self.inner.lock(|q_in| q_in.read_char())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn flush_input(&self) {}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Console for QemuUart {}
|
|
|
|
|
|
|
|
|
|
// TODO: move?
|
|
|
|
|
/// Return a reference to the Qemu Output.
|
|
|
|
|
/// Return a reference to the Qemu Uart.
|
|
|
|
|
pub fn console() -> &'static dyn Console {
|
|
|
|
|
&QEMU_OUTPUT
|
|
|
|
|
&QEMU_UART
|
|
|
|
|
}
|
|
|
|
|