diff --git a/kernel/src/arch/aarch64/driver/mod.rs b/kernel/src/arch/aarch64/driver/mod.rs index 9c29662..a100c2b 100644 --- a/kernel/src/arch/aarch64/driver/mod.rs +++ b/kernel/src/arch/aarch64/driver/mod.rs @@ -5,6 +5,7 @@ use once::*; pub use self::board::fb; pub use self::board::serial; +#[path = "../../../drivers/console/mod.rs"] pub mod console; /// Initialize ARM64 common drivers diff --git a/kernel/src/arch/mipsel/board/malta/fb.rs b/kernel/src/arch/mipsel/board/malta/fb.rs new file mode 100644 index 0000000..89c4321 --- /dev/null +++ b/kernel/src/arch/mipsel/board/malta/fb.rs @@ -0,0 +1,7 @@ +lazy_static! { + pub static ref FRAME_BUFFER: Mutex> = Mutex::new(None); +} + +pub struct FramebufferInfo {} + +pub enum ColorDepth {} \ No newline at end of file diff --git a/kernel/src/arch/mipsel/board/malta/mod.rs b/kernel/src/arch/mipsel/board/malta/mod.rs new file mode 100644 index 0000000..ae61c69 --- /dev/null +++ b/kernel/src/arch/mipsel/board/malta/mod.rs @@ -0,0 +1,19 @@ +use once::*; + +pub mod serial; +pub mod fb; +#[path = "../../../../drivers/console/mod.rs"] +pub mod console; + +/// Initialize serial port first +pub fn init_serial_early() { + assert_has_not_been_called!("board::init must be called only once"); + serial::init(); + println!("Hello QEMU Malta!"); +} + +/// Initialize other board drivers +pub fn init_driver() { + // TODO: add possibly more drivers + // timer::init(); +} \ No newline at end of file diff --git a/kernel/src/arch/mipsel/board/malta/serial.rs b/kernel/src/arch/mipsel/board/malta/serial.rs new file mode 100644 index 0000000..4a20383 --- /dev/null +++ b/kernel/src/arch/mipsel/board/malta/serial.rs @@ -0,0 +1,114 @@ +use core::fmt::{Write, Result, Arguments}; +use core::ptr::{read_volatile, write_volatile}; + +struct SerialPort {}; + +impl SerialPort { + fn new() -> SerialPort { + SerialPort { } + } +} + +impl Write for SerialPort { + fn write_str(&mut self, s: &str) -> Result { + for c in s.bytes() { + if c == 127 { + putchar(8); + putchar(b' '); + putchar(8); + } else { + putchar(c); + } + } + Ok(()) + } +} + +fn write(addr: usize, content: T) { + let cell = (addr) as *mut T; + write_volatile(cell, content); +} + +fn read(addr: usize) -> T { + let cell = (addr) as *const T; + read_volatile(cell); +} + +/// non-blocking version of putchar() +fn putchar(c: u8) { + write(COM1 + COM_TX, c); +} + +/// blocking version of getchar() +pub fn getchar() -> char { + loop { + if (read::(COM1 + COM_LSR) & COM_LSR_DATA) == 0 { + break; + } + } + let c = read::(COM1 + COM_RX); + match c { + 255 => '\0', // null + c => c as char, + } +} + +/// non-blocking version of getchar() +pub fn getchar_option() -> Option { + match read::(COM1 + COM_LSR) & COM_LSR_DATA { + 0 => None, + else => Some(read::(COM1 + COM_RX) as u8 as char), + } +} + +pub fn putfmt(fmt: Arguments) { + SerialPort.write_fmt(fmt).unwrap(); +} + +pub fn init() { + // Turn off the FIFO + write(COM1 + COM_FCR, 0 as u8); + // Set speed; requires DLAB latch + write(COM1 + COM_LCR, COM_LCR_DLAB); + write(COM1 + COM_DLL, (115200 / 9600) as u8); + write(COM1 + COM_DLM, 0 as u8); + + // 8 data bits, 1 stop bit, parity off; turn off DLAB latch + write(COM1 + COM_LCR, COM_LCR_WLEN8 & !COM_LCR_DLAB); + + // No modem controls + write(COM1 + COM_MCR, 0 as u8); + // Enable rcv interrupts + write(COM1 + COM_IER, COM_IER_RDI); +} + +const COM1 :usize = 0xbf000900; // 16550 Base Address + +const COM_RX :usize = 0; // In: Receive buffer (DLAB=0) +const COM_TX :usize = 0; // Out: Transmit buffer (DLAB=0) +const COM_DLL :usize = 0; // Out: Divisor Latch Low (DLAB=1) +const COM_DLM :usize = 1; // Out: Divisor Latch High (DLAB=1) +const COM_IER :usize = 1; // Out: Interrupt Enable Register +const COM_IER_RDI :u8 = 0x01; // Enable receiver data interrupt +const COM_IIR :usize = 2; // In: Interrupt ID Register +const COM_FCR :usize = 2; // Out: FIFO Control Register +const COM_LCR :usize = 3; // Out: Line Control Register +const COM_LCR_DLAB :u8 = 0x80; // Divisor latch access bit +const COM_LCR_WLEN8 :u8 = 0x03; // Wordlength: 8 bits +const COM_MCR :usize = 4; // Out: Modem Control Register +const COM_MCR_RTS :u8 = 0x02; // RTS complement +const COM_MCR_DTR :u8 = 0x01; // DTR complement +const COM_MCR_OUT2 :u8 = 0x08; // Out2 complement +const COM_LSR :usize = 5; // In: Line Status Register +const COM_LSR_DATA :u8 = 0x01; // Data available +const COM_LSR_TXRDY :u8 = 0x20; // Transmit buffer avail +const COM_LSR_TSRE :u8 = 0x40; // Transmitter off + + +lazy_static! { + pub static ref SERIAL_PORT: Mutex = Mutex::new(SerialPort::new()); +} + +pub fn init() { + SERIAL_PORT.lock().init(); +} \ No newline at end of file diff --git a/kernel/src/arch/mipsel/board/thinpad/mod.rs b/kernel/src/arch/mipsel/board/thinpad/mod.rs new file mode 100644 index 0000000..1277ed7 --- /dev/null +++ b/kernel/src/arch/mipsel/board/thinpad/mod.rs @@ -0,0 +1,20 @@ +use once::*; + +pub mod serial; +pub mod fb; +#[path = "../../../../drivers/console/mod.rs"] +pub mod console; + +/// Initialize serial port first +pub fn init_serial_early() { + assert_has_not_been_called!("board::init must be called only once"); + serial::init(); + println!("Hello ThinPad!"); +} + +/// Initialize other board drivers +pub fn init_driver() { + // TODO: add possibly more drivers + // timer::init(); + console::init(); +} \ No newline at end of file diff --git a/kernel/src/arch/mipsel/driver/mod.rs b/kernel/src/arch/mipsel/driver/mod.rs new file mode 100644 index 0000000..67c4009 --- /dev/null +++ b/kernel/src/arch/mipsel/driver/mod.rs @@ -0,0 +1,16 @@ +//! mipsel drivers + +use super::board; +use once::*; + +pub use self::board::serial; +pub use self::board::fb; +#[path = "../../../drivers/console/mod.rs"] +pub mod console; + +/// Initialize common drivers +pub fn init() { + assert_has_not_been_called!("driver::init must be called only once"); + board::init_driver(); + console::init(); +} diff --git a/kernel/src/arch/mipsel/io.rs b/kernel/src/arch/mipsel/io.rs index 50c224d..b184a57 100644 --- a/kernel/src/arch/mipsel/io.rs +++ b/kernel/src/arch/mipsel/io.rs @@ -1,100 +1,30 @@ -use core::fmt::{Write, Result, Arguments}; -use core::ptr::{read_volatile, write_volatile}; +//! Input/output for mipsel. -struct SerialPort {}; +use super::driver::console::CONSOLE; +use super::driver::serial::*; +use core::fmt::{Arguments, Write}; -impl Write for SerialPort { - fn write_str(&mut self, s: &str) -> Result { - for c in s.bytes() { - if c == 127 { - putchar(8); - putchar(b' '); - putchar(8); - } else { - putchar(c); - } - } - Ok(()) - } -} - -fn write(addr: usize, content: T) { - let cell = (addr) as *mut T; - write_volatile(cell, content); -} - -fn read(addr: usize) -> T { - let cell = (addr) as *const T; - read_volatile(cell); -} - -/// non-blocking version of putchar() -fn putchar(c: u8) { - write(COM1 + COM_TX, c); -} - -/// blocking version of getchar() pub fn getchar() -> char { - loop { - if (read::(COM1 + COM_LSR) & COM_LSR_DATA) == 0 { - break; - } - } - let c = read::(COM1 + COM_RX); - match c { - 255 => '\0', // null - c => c as char, - } + unsafe { SERIAL_PORT.force_unlock() } + SERIAL_PORT.lock().getchar() } -/// non-blocking version of getchar() -pub fn getchar_option() -> Option { - match read::(COM1 + COM_LSR) & COM_LSR_DATA { - 0 => None, - else => Some(read::(COM1 + COM_RX) as u8 as char), - } +pub fn getchar_option() -> Option { + unsafe { SERIAL_PORT.force_unlock() } + SERIAL_PORT.lock().getchar_option() } pub fn putfmt(fmt: Arguments) { - SerialPort.write_fmt(fmt).unwrap(); -} - -pub fn init() { - // Turn off the FIFO - write(COM1 + COM_FCR, 0 as u8); - // Set speed; requires DLAB latch - write(COM1 + COM_LCR, COM_LCR_DLAB); - write(COM1 + COM_DLL, (115200 / 9600) as u8); - write(COM1 + COM_DLM, 0 as u8); + unsafe { SERIAL_PORT.force_unlock() } + SERIAL_PORT.lock().write_fmt(fmt).unwrap(); - // 8 data bits, 1 stop bit, parity off; turn off DLAB latch - write(COM1 + COM_LCR, COM_LCR_WLEN8 & !COM_LCR_DLAB); - - // No modem controls - write(COM1 + COM_MCR, 0 as u8); - // Enable rcv interrupts - write(COM1 + COM_IER, COM_IER_RDI); + unsafe { CONSOLE.force_unlock() } + if let Some(console) = CONSOLE.lock().as_mut() { + console.write_fmt(fmt).unwrap(); + } } -#[cfg(feature = "board_malta")] -const COM1 :usize = 0xbf000900; // 16550 Base Address - -const COM_RX :usize = 0; // In: Receive buffer (DLAB=0) -const COM_TX :usize = 0; // Out: Transmit buffer (DLAB=0) -const COM_DLL :usize = 0; // Out: Divisor Latch Low (DLAB=1) -const COM_DLM :usize = 1; // Out: Divisor Latch High (DLAB=1) -const COM_IER :usize = 1; // Out: Interrupt Enable Register -const COM_IER_RDI :u8 = 0x01; // Enable receiver data interrupt -const COM_IIR :usize = 2; // In: Interrupt ID Register -const COM_FCR :usize = 2; // Out: FIFO Control Register -const COM_LCR :usize = 3; // Out: Line Control Register -const COM_LCR_DLAB :u8 = 0x80; // Divisor latch access bit -const COM_LCR_WLEN8 :u8 = 0x03; // Wordlength: 8 bits -const COM_MCR :usize = 4; // Out: Modem Control Register -const COM_MCR_RTS :u8 = 0x02; // RTS complement -const COM_MCR_DTR :u8 = 0x01; // DTR complement -const COM_MCR_OUT2 :u8 = 0x08; // Out2 complement -const COM_LSR :usize = 5; // In: Line Status Register -const COM_LSR_DATA :u8 = 0x01; // Data available -const COM_LSR_TXRDY :u8 = 0x20; // Transmit buffer avail -const COM_LSR_TSRE :u8 = 0x40; // Transmitter off +pub fn putchar(c: u8) { + unsafe { SERIAL_PORT.force_unlock() } + SERIAL_PORT.lock().putchar(c); +} diff --git a/kernel/src/arch/mipsel/mod.rs b/kernel/src/arch/mipsel/mod.rs index 9681b06..ca51a72 100644 --- a/kernel/src/arch/mipsel/mod.rs +++ b/kernel/src/arch/mipsel/mod.rs @@ -8,11 +8,20 @@ pub mod consts; pub mod cpu; pub mod syscall; pub mod rand; +pub mod driver; use log::*; use mips::registers; use mips::instructions; +#[cfg(feature = "board_malta")] +#[path = "board/malta/mod.rs"] +pub mod board; + +#[cfg(feature = "board_thinpad")] +#[path = "board/thinpad/mod.rs"] +pub mod board; + extern "C" { fn _dtb_start(); fn _dtb_end(); @@ -38,14 +47,16 @@ pub extern fn rust_main() -> ! { unsafe { memory::clear_bss(); } - crate::io::init(); + board::init_serial_early(); + driver::init(); println!("Hello MIPS 32 from CPU {}, dtb @ {:#x}", cpu_id, dtb_start); - crate::logging::init(); interrupt::init(); memory::init(); timer::init(); + + crate::logging::init(); crate::drivers::init(dtb_start); crate::process::init(); diff --git a/kernel/src/arch/aarch64/driver/console/color.rs b/kernel/src/drivers/console/color.rs similarity index 100% rename from kernel/src/arch/aarch64/driver/console/color.rs rename to kernel/src/drivers/console/color.rs diff --git a/kernel/src/arch/aarch64/driver/console/fonts/font8x16.rs b/kernel/src/drivers/console/fonts/font8x16.rs similarity index 100% rename from kernel/src/arch/aarch64/driver/console/fonts/font8x16.rs rename to kernel/src/drivers/console/fonts/font8x16.rs diff --git a/kernel/src/arch/aarch64/driver/console/fonts/mod.rs b/kernel/src/drivers/console/fonts/mod.rs similarity index 100% rename from kernel/src/arch/aarch64/driver/console/fonts/mod.rs rename to kernel/src/drivers/console/fonts/mod.rs diff --git a/kernel/src/arch/aarch64/driver/console/mod.rs b/kernel/src/drivers/console/mod.rs similarity index 100% rename from kernel/src/arch/aarch64/driver/console/mod.rs rename to kernel/src/drivers/console/mod.rs