From 621b657f875b0a4c8778c0f33c45d75d7029df66 Mon Sep 17 00:00:00 2001 From: Tommy Hudson Date: Sun, 30 Jul 2017 15:46:34 +0100 Subject: [PATCH 1/2] Move x86_64-specific code to arch/x86_64 --- src/arch/mod.rs | 1 + src/{ => arch/x86_64}/device/cpu.rs | 0 src/{ => arch/x86_64}/device/hpet.rs | 0 src/{ => arch/x86_64}/device/local_apic.rs | 0 src/{ => arch/x86_64}/device/mod.rs | 0 src/{ => arch/x86_64}/device/pic.rs | 0 src/{ => arch/x86_64}/device/pit.rs | 0 src/{ => arch/x86_64}/device/rtc.rs | 0 src/{ => arch/x86_64}/device/serial.rs | 0 src/{ => arch/x86_64}/gdt.rs | 0 src/{ => arch/x86_64}/idt.rs | 0 src/{ => arch/x86_64}/interrupt/exception.rs | 0 src/{ => arch/x86_64}/interrupt/ipi.rs | 0 src/{ => arch/x86_64}/interrupt/irq.rs | 0 src/{ => arch/x86_64}/interrupt/mod.rs | 0 src/{ => arch/x86_64}/interrupt/syscall.rs | 0 src/{ => arch/x86_64}/interrupt/trace.rs | 0 src/arch/x86_64/macros.rs | 181 +++++++++++++++++ src/arch/x86_64/mod.rs | 23 +++ src/{ => arch/x86_64}/paging/entry.rs | 0 src/{ => arch/x86_64}/paging/mapper.rs | 0 src/{ => arch/x86_64}/paging/mod.rs | 0 src/{ => arch/x86_64}/paging/table.rs | 0 .../x86_64}/paging/temporary_page.rs | 0 src/{ => arch/x86_64}/start.rs | 0 src/{ => arch/x86_64}/stop.rs | 0 src/lib.rs | 26 +-- src/macros.rs | 182 ------------------ 28 files changed, 210 insertions(+), 203 deletions(-) create mode 100644 src/arch/mod.rs rename src/{ => arch/x86_64}/device/cpu.rs (100%) rename src/{ => arch/x86_64}/device/hpet.rs (100%) rename src/{ => arch/x86_64}/device/local_apic.rs (100%) rename src/{ => arch/x86_64}/device/mod.rs (100%) rename src/{ => arch/x86_64}/device/pic.rs (100%) rename src/{ => arch/x86_64}/device/pit.rs (100%) rename src/{ => arch/x86_64}/device/rtc.rs (100%) rename src/{ => arch/x86_64}/device/serial.rs (100%) rename src/{ => arch/x86_64}/gdt.rs (100%) rename src/{ => arch/x86_64}/idt.rs (100%) rename src/{ => arch/x86_64}/interrupt/exception.rs (100%) rename src/{ => arch/x86_64}/interrupt/ipi.rs (100%) rename src/{ => arch/x86_64}/interrupt/irq.rs (100%) rename src/{ => arch/x86_64}/interrupt/mod.rs (100%) rename src/{ => arch/x86_64}/interrupt/syscall.rs (100%) rename src/{ => arch/x86_64}/interrupt/trace.rs (100%) create mode 100644 src/arch/x86_64/macros.rs create mode 100644 src/arch/x86_64/mod.rs rename src/{ => arch/x86_64}/paging/entry.rs (100%) rename src/{ => arch/x86_64}/paging/mapper.rs (100%) rename src/{ => arch/x86_64}/paging/mod.rs (100%) rename src/{ => arch/x86_64}/paging/table.rs (100%) rename src/{ => arch/x86_64}/paging/temporary_page.rs (100%) rename src/{ => arch/x86_64}/start.rs (100%) rename src/{ => arch/x86_64}/stop.rs (100%) diff --git a/src/arch/mod.rs b/src/arch/mod.rs new file mode 100644 index 0000000..0bffdbe --- /dev/null +++ b/src/arch/mod.rs @@ -0,0 +1 @@ +pub mod x86_64; \ No newline at end of file diff --git a/src/device/cpu.rs b/src/arch/x86_64/device/cpu.rs similarity index 100% rename from src/device/cpu.rs rename to src/arch/x86_64/device/cpu.rs diff --git a/src/device/hpet.rs b/src/arch/x86_64/device/hpet.rs similarity index 100% rename from src/device/hpet.rs rename to src/arch/x86_64/device/hpet.rs diff --git a/src/device/local_apic.rs b/src/arch/x86_64/device/local_apic.rs similarity index 100% rename from src/device/local_apic.rs rename to src/arch/x86_64/device/local_apic.rs diff --git a/src/device/mod.rs b/src/arch/x86_64/device/mod.rs similarity index 100% rename from src/device/mod.rs rename to src/arch/x86_64/device/mod.rs diff --git a/src/device/pic.rs b/src/arch/x86_64/device/pic.rs similarity index 100% rename from src/device/pic.rs rename to src/arch/x86_64/device/pic.rs diff --git a/src/device/pit.rs b/src/arch/x86_64/device/pit.rs similarity index 100% rename from src/device/pit.rs rename to src/arch/x86_64/device/pit.rs diff --git a/src/device/rtc.rs b/src/arch/x86_64/device/rtc.rs similarity index 100% rename from src/device/rtc.rs rename to src/arch/x86_64/device/rtc.rs diff --git a/src/device/serial.rs b/src/arch/x86_64/device/serial.rs similarity index 100% rename from src/device/serial.rs rename to src/arch/x86_64/device/serial.rs diff --git a/src/gdt.rs b/src/arch/x86_64/gdt.rs similarity index 100% rename from src/gdt.rs rename to src/arch/x86_64/gdt.rs diff --git a/src/idt.rs b/src/arch/x86_64/idt.rs similarity index 100% rename from src/idt.rs rename to src/arch/x86_64/idt.rs diff --git a/src/interrupt/exception.rs b/src/arch/x86_64/interrupt/exception.rs similarity index 100% rename from src/interrupt/exception.rs rename to src/arch/x86_64/interrupt/exception.rs diff --git a/src/interrupt/ipi.rs b/src/arch/x86_64/interrupt/ipi.rs similarity index 100% rename from src/interrupt/ipi.rs rename to src/arch/x86_64/interrupt/ipi.rs diff --git a/src/interrupt/irq.rs b/src/arch/x86_64/interrupt/irq.rs similarity index 100% rename from src/interrupt/irq.rs rename to src/arch/x86_64/interrupt/irq.rs diff --git a/src/interrupt/mod.rs b/src/arch/x86_64/interrupt/mod.rs similarity index 100% rename from src/interrupt/mod.rs rename to src/arch/x86_64/interrupt/mod.rs diff --git a/src/interrupt/syscall.rs b/src/arch/x86_64/interrupt/syscall.rs similarity index 100% rename from src/interrupt/syscall.rs rename to src/arch/x86_64/interrupt/syscall.rs diff --git a/src/interrupt/trace.rs b/src/arch/x86_64/interrupt/trace.rs similarity index 100% rename from src/interrupt/trace.rs rename to src/arch/x86_64/interrupt/trace.rs diff --git a/src/arch/x86_64/macros.rs b/src/arch/x86_64/macros.rs new file mode 100644 index 0000000..ab75124 --- /dev/null +++ b/src/arch/x86_64/macros.rs @@ -0,0 +1,181 @@ +/// Create an interrupt function that can safely run rust code +#[macro_export] +macro_rules! interrupt { + ($name:ident, $func:block) => { + #[naked] + pub unsafe extern fn $name () { + #[inline(never)] + unsafe fn inner() { + $func + } + + // Push scratch registers + asm!("push rax + push rcx + push rdx + push rdi + push rsi + push r8 + push r9 + push r10 + push r11 + push fs + mov rax, 0x18 + mov fs, ax" + : : : : "intel", "volatile"); + + // Call inner rust function + inner(); + + // Pop scratch registers and return + asm!("pop fs + pop r11 + pop r10 + pop r9 + pop r8 + pop rsi + pop rdi + pop rdx + pop rcx + pop rax + iretq" + : : : : "intel", "volatile"); + } + }; +} + +#[allow(dead_code)] +#[repr(packed)] +pub struct InterruptStack { + pub fs: usize, + pub r11: usize, + pub r10: usize, + pub r9: usize, + pub r8: usize, + pub rsi: usize, + pub rdi: usize, + pub rdx: usize, + pub rcx: usize, + pub rax: usize, + pub rip: usize, + pub cs: usize, + pub rflags: usize, +} + +#[macro_export] +macro_rules! interrupt_stack { + ($name:ident, $stack: ident, $func:block) => { + #[naked] + pub unsafe extern fn $name () { + #[inline(never)] + unsafe fn inner($stack: &mut $crate::arch::x86_64::macros::InterruptStack) { + $func + } + + // Push scratch registers + asm!("push rax + push rcx + push rdx + push rdi + push rsi + push r8 + push r9 + push r10 + push r11 + push fs + mov rax, 0x18 + mov fs, ax" + : : : : "intel", "volatile"); + + // Get reference to stack variables + let rsp: usize; + asm!("" : "={rsp}"(rsp) : : : "intel", "volatile"); + + // Call inner rust function + inner(&mut *(rsp as *mut $crate::arch::x86_64::macros::InterruptStack)); + + // Pop scratch registers and return + asm!("pop fs + pop r11 + pop r10 + pop r9 + pop r8 + pop rsi + pop rdi + pop rdx + pop rcx + pop rax + iretq" + : : : : "intel", "volatile"); + } + }; +} + +#[allow(dead_code)] +#[repr(packed)] +pub struct InterruptErrorStack { + pub fs: usize, + pub r11: usize, + pub r10: usize, + pub r9: usize, + pub r8: usize, + pub rsi: usize, + pub rdi: usize, + pub rdx: usize, + pub rcx: usize, + pub rax: usize, + pub code: usize, + pub rip: usize, + pub cs: usize, + pub rflags: usize, +} + +#[macro_export] +macro_rules! interrupt_error { + ($name:ident, $stack:ident, $func:block) => { + #[naked] + pub unsafe extern fn $name () { + #[inline(never)] + unsafe fn inner($stack: &$crate::arch::x86_64::macros::InterruptErrorStack) { + $func + } + + // Push scratch registers + asm!("push rax + push rcx + push rdx + push rdi + push rsi + push r8 + push r9 + push r10 + push r11 + push fs + mov rax, 0x18 + mov fs, ax" + : : : : "intel", "volatile"); + + // Get reference to stack variables + let rsp: usize; + asm!("" : "={rsp}"(rsp) : : : "intel", "volatile"); + + // Call inner rust function + inner(&*(rsp as *const $crate::arch::x86_64::macros::InterruptErrorStack)); + + // Pop scratch registers, error code, and return + asm!("pop fs + pop r11 + pop r10 + pop r9 + pop r8 + pop rsi + pop rdi + pop rdx + pop rcx + pop rax + add rsp, 8 + iretq" + : : : : "intel", "volatile"); + } + }; +} diff --git a/src/arch/x86_64/mod.rs b/src/arch/x86_64/mod.rs new file mode 100644 index 0000000..7ae1a8e --- /dev/null +++ b/src/arch/x86_64/mod.rs @@ -0,0 +1,23 @@ +#[macro_use] +pub mod macros; + +/// Devices +pub mod device; + +/// Global descriptor table +pub mod gdt; + +/// Interrupt descriptor table +pub mod idt; + +/// Interrupt instructions +pub mod interrupt; + +/// Paging +pub mod paging; + +/// Initialization and start function +pub mod start; + +/// Stop function +pub mod stop; \ No newline at end of file diff --git a/src/paging/entry.rs b/src/arch/x86_64/paging/entry.rs similarity index 100% rename from src/paging/entry.rs rename to src/arch/x86_64/paging/entry.rs diff --git a/src/paging/mapper.rs b/src/arch/x86_64/paging/mapper.rs similarity index 100% rename from src/paging/mapper.rs rename to src/arch/x86_64/paging/mapper.rs diff --git a/src/paging/mod.rs b/src/arch/x86_64/paging/mod.rs similarity index 100% rename from src/paging/mod.rs rename to src/arch/x86_64/paging/mod.rs diff --git a/src/paging/table.rs b/src/arch/x86_64/paging/table.rs similarity index 100% rename from src/paging/table.rs rename to src/arch/x86_64/paging/table.rs diff --git a/src/paging/temporary_page.rs b/src/arch/x86_64/paging/temporary_page.rs similarity index 100% rename from src/paging/temporary_page.rs rename to src/arch/x86_64/paging/temporary_page.rs diff --git a/src/start.rs b/src/arch/x86_64/start.rs similarity index 100% rename from src/start.rs rename to src/arch/x86_64/start.rs diff --git a/src/stop.rs b/src/arch/x86_64/stop.rs similarity index 100% rename from src/stop.rs rename to src/arch/x86_64/stop.rs diff --git a/src/lib.rs b/src/lib.rs index 533b9e4..aaedb09 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -52,45 +52,29 @@ pub mod consts; /// ACPI table parsing mod acpi; +/// Architecture-dependent stuff +mod arch; +#[cfg(target_arch = "x86_64")] +pub use arch::x86_64::*; + /// Context management pub mod context; -/// Devices -pub mod device; - /// ELF file parsing pub mod elf; /// External functions pub mod externs; -/// Global descriptor table -pub mod gdt; - -/// Interrupt descriptor table -mod idt; - -/// Interrupt instructions -pub mod interrupt; - /// Memory management pub mod memory; -/// Paging -pub mod paging; - /// Panic pub mod panic; /// Schemes, filesystem handlers pub mod scheme; -/// Initialization and start function -pub mod start; - -/// Shutdown function -pub mod stop; - /// Synchronization primitives pub mod sync; diff --git a/src/macros.rs b/src/macros.rs index 2c8d133..beaef43 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -14,185 +14,3 @@ macro_rules! println { ($fmt:expr) => (print!(concat!($fmt, "\n"))); ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*)); } - -/// Create an interrupt function that can safely run rust code -#[macro_export] -macro_rules! interrupt { - ($name:ident, $func:block) => { - #[naked] - pub unsafe extern fn $name () { - #[inline(never)] - unsafe fn inner() { - $func - } - - // Push scratch registers - asm!("push rax - push rcx - push rdx - push rdi - push rsi - push r8 - push r9 - push r10 - push r11 - push fs - mov rax, 0x18 - mov fs, ax" - : : : : "intel", "volatile"); - - // Call inner rust function - inner(); - - // Pop scratch registers and return - asm!("pop fs - pop r11 - pop r10 - pop r9 - pop r8 - pop rsi - pop rdi - pop rdx - pop rcx - pop rax - iretq" - : : : : "intel", "volatile"); - } - }; -} - -#[allow(dead_code)] -#[repr(packed)] -pub struct InterruptStack { - pub fs: usize, - pub r11: usize, - pub r10: usize, - pub r9: usize, - pub r8: usize, - pub rsi: usize, - pub rdi: usize, - pub rdx: usize, - pub rcx: usize, - pub rax: usize, - pub rip: usize, - pub cs: usize, - pub rflags: usize, -} - -#[macro_export] -macro_rules! interrupt_stack { - ($name:ident, $stack: ident, $func:block) => { - #[naked] - pub unsafe extern fn $name () { - #[inline(never)] - unsafe fn inner($stack: &mut $crate::macros::InterruptStack) { - $func - } - - // Push scratch registers - asm!("push rax - push rcx - push rdx - push rdi - push rsi - push r8 - push r9 - push r10 - push r11 - push fs - mov rax, 0x18 - mov fs, ax" - : : : : "intel", "volatile"); - - // Get reference to stack variables - let rsp: usize; - asm!("" : "={rsp}"(rsp) : : : "intel", "volatile"); - - // Call inner rust function - inner(&mut *(rsp as *mut $crate::macros::InterruptStack)); - - // Pop scratch registers and return - asm!("pop fs - pop r11 - pop r10 - pop r9 - pop r8 - pop rsi - pop rdi - pop rdx - pop rcx - pop rax - iretq" - : : : : "intel", "volatile"); - } - }; -} - -#[allow(dead_code)] -#[repr(packed)] -pub struct InterruptErrorStack { - pub fs: usize, - pub r11: usize, - pub r10: usize, - pub r9: usize, - pub r8: usize, - pub rsi: usize, - pub rdi: usize, - pub rdx: usize, - pub rcx: usize, - pub rax: usize, - pub code: usize, - pub rip: usize, - pub cs: usize, - pub rflags: usize, -} - -#[macro_export] -macro_rules! interrupt_error { - ($name:ident, $stack:ident, $func:block) => { - #[naked] - pub unsafe extern fn $name () { - #[inline(never)] - unsafe fn inner($stack: &$crate::macros::InterruptErrorStack) { - $func - } - - // Push scratch registers - asm!("push rax - push rcx - push rdx - push rdi - push rsi - push r8 - push r9 - push r10 - push r11 - push fs - mov rax, 0x18 - mov fs, ax" - : : : : "intel", "volatile"); - - // Get reference to stack variables - let rsp: usize; - asm!("" : "={rsp}"(rsp) : : : "intel", "volatile"); - - // Call inner rust function - inner(&*(rsp as *const $crate::macros::InterruptErrorStack)); - - // Pop scratch registers, error code, and return - asm!("pop fs - pop r11 - pop r10 - pop r9 - pop r8 - pop rsi - pop rdi - pop rdx - pop rcx - pop rax - add rsp, 8 - iretq" - : : : : "intel", "volatile"); - } - }; -} From 0e1d664bf0ac733c043b31cb54be2833c65c1474 Mon Sep 17 00:00:00 2001 From: Tommy Hudson Date: Sun, 30 Jul 2017 20:54:36 +0100 Subject: [PATCH 2/2] Rearrange serial I/O code and make 16550 driver generic over T: Io --- src/arch/mod.rs | 6 +- src/arch/x86_64/device/serial.rs | 112 +--------------------------- src/arch/x86_64/macros.rs | 17 +++++ src/devices/mod.rs | 1 + src/devices/uart_16550.rs | 122 +++++++++++++++++++++++++++++++ src/lib.rs | 13 ++-- src/macros.rs | 16 ---- 7 files changed, 155 insertions(+), 132 deletions(-) create mode 100644 src/devices/mod.rs create mode 100644 src/devices/uart_16550.rs delete mode 100644 src/macros.rs diff --git a/src/arch/mod.rs b/src/arch/mod.rs index 0bffdbe..1abbd03 100644 --- a/src/arch/mod.rs +++ b/src/arch/mod.rs @@ -1 +1,5 @@ -pub mod x86_64; \ No newline at end of file +#[cfg(target_arch = "x86_64")] +#[macro_use] +pub mod x86_64; +#[cfg(target_arch = "x86_64")] +pub use self::x86_64::*; \ No newline at end of file diff --git a/src/arch/x86_64/device/serial.rs b/src/arch/x86_64/device/serial.rs index b29c8b0..05905a7 100644 --- a/src/arch/x86_64/device/serial.rs +++ b/src/arch/x86_64/device/serial.rs @@ -1,115 +1,11 @@ -use core::fmt::{self, Write}; +use devices::uart_16550::SerialPort; +use syscall::io::Pio; use spin::Mutex; -use scheme::debug::debug_input; -use syscall::io::{Io, Pio, ReadOnly}; - -pub static COM1: Mutex = Mutex::new(SerialPort::new(0x3F8)); -pub static COM2: Mutex = Mutex::new(SerialPort::new(0x2F8)); +pub static COM1: Mutex>> = Mutex::new(SerialPort::>::new(0x3F8)); +pub static COM2: Mutex>> = Mutex::new(SerialPort::>::new(0x2F8)); pub unsafe fn init() { COM1.lock().init(); COM2.lock().init(); } - -bitflags! { - /// Interrupt enable flags - flags IntEnFlags: u8 { - const RECEIVED = 1, - const SENT = 1 << 1, - const ERRORED = 1 << 2, - const STATUS_CHANGE = 1 << 3, - // 4 to 7 are unused - } -} - -bitflags! { - /// Line status flags - flags LineStsFlags: u8 { - const INPUT_FULL = 1, - // 1 to 4 unknown - const OUTPUT_EMPTY = 1 << 5, - // 6 and 7 unknown - } -} - -#[allow(dead_code)] -pub struct SerialPort { - /// Data register, read to receive, write to send - data: Pio, - /// Interrupt enable - int_en: Pio, - /// FIFO control - fifo_ctrl: Pio, - /// Line control - line_ctrl: Pio, - /// Modem control - modem_ctrl: Pio, - /// Line status - line_sts: ReadOnly>, - /// Modem status - modem_sts: ReadOnly>, -} - -impl SerialPort { - const fn new(base: u16) -> SerialPort { - SerialPort { - data: Pio::new(base), - int_en: Pio::new(base + 1), - fifo_ctrl: Pio::new(base + 2), - line_ctrl: Pio::new(base + 3), - modem_ctrl: Pio::new(base + 4), - line_sts: ReadOnly::new(Pio::new(base + 5)), - modem_sts: ReadOnly::new(Pio::new(base + 6)) - } - } - - fn init(&mut self) { - //TODO: Cleanup - self.int_en.write(0x00); - self.line_ctrl.write(0x80); - self.data.write(0x03); - self.int_en.write(0x00); - self.line_ctrl.write(0x03); - self.fifo_ctrl.write(0xC7); - self.modem_ctrl.write(0x0B); - self.int_en.write(0x01); - } - - fn line_sts(&self) -> LineStsFlags { - LineStsFlags::from_bits_truncate(self.line_sts.read()) - } - - pub fn receive(&mut self) { - while self.line_sts().contains(INPUT_FULL) { - debug_input(self.data.read()); - } - } - - pub fn send(&mut self, data: u8) { - match data { - 8 | 0x7F => { - while ! self.line_sts().contains(OUTPUT_EMPTY) {} - self.data.write(8); - while ! self.line_sts().contains(OUTPUT_EMPTY) {} - self.data.write(b' '); - while ! self.line_sts().contains(OUTPUT_EMPTY) {} - self.data.write(8); - }, - _ => { - while ! self.line_sts().contains(OUTPUT_EMPTY) {} - self.data.write(data); - } - } - } -} - -impl Write for SerialPort { - fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> { - for byte in s.bytes() { - self.send(byte); - } - - Ok(()) - } -} diff --git a/src/arch/x86_64/macros.rs b/src/arch/x86_64/macros.rs index ab75124..ff4f79c 100644 --- a/src/arch/x86_64/macros.rs +++ b/src/arch/x86_64/macros.rs @@ -1,3 +1,20 @@ +/// Print to console +#[macro_export] +macro_rules! print { + ($($arg:tt)*) => ({ + use core::fmt::Write; + let _ = write!($crate::arch::device::serial::COM1.lock(), $($arg)*); + }); +} + +/// Print with new line to console +#[macro_export] +macro_rules! println { + () => (print!("\n")); + ($fmt:expr) => (print!(concat!($fmt, "\n"))); + ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*)); +} + /// Create an interrupt function that can safely run rust code #[macro_export] macro_rules! interrupt { diff --git a/src/devices/mod.rs b/src/devices/mod.rs new file mode 100644 index 0000000..9dc8d5b --- /dev/null +++ b/src/devices/mod.rs @@ -0,0 +1 @@ +pub mod uart_16550; \ No newline at end of file diff --git a/src/devices/uart_16550.rs b/src/devices/uart_16550.rs new file mode 100644 index 0000000..8dfb356 --- /dev/null +++ b/src/devices/uart_16550.rs @@ -0,0 +1,122 @@ +use core::fmt::{self, Write}; + +use scheme::debug::debug_input; +use syscall::io::{Io, Pio, Mmio, ReadOnly}; + +bitflags! { + /// Interrupt enable flags + flags IntEnFlags: u8 { + const RECEIVED = 1, + const SENT = 1 << 1, + const ERRORED = 1 << 2, + const STATUS_CHANGE = 1 << 3, + // 4 to 7 are unused + } +} + +bitflags! { + /// Line status flags + flags LineStsFlags: u8 { + const INPUT_FULL = 1, + // 1 to 4 unknown + const OUTPUT_EMPTY = 1 << 5, + // 6 and 7 unknown + } +} + +#[allow(dead_code)] +pub struct SerialPort> { + /// Data register, read to receive, write to send + data: T, + /// Interrupt enable + int_en: T, + /// FIFO control + fifo_ctrl: T, + /// Line control + line_ctrl: T, + /// Modem control + modem_ctrl: T, + /// Line status + line_sts: ReadOnly, + /// Modem status + modem_sts: ReadOnly, +} + +impl SerialPort> { + pub const fn new(base: u16) -> SerialPort> { + SerialPort { + data: Pio::new(base), + int_en: Pio::new(base + 1), + fifo_ctrl: Pio::new(base + 2), + line_ctrl: Pio::new(base + 3), + modem_ctrl: Pio::new(base + 4), + line_sts: ReadOnly::new(Pio::new(base + 5)), + modem_sts: ReadOnly::new(Pio::new(base + 6)) + } + } +} + +impl SerialPort> { + pub fn new(base: usize) -> SerialPort> { + SerialPort { + data: Mmio::new(), + int_en: Mmio::new(), + fifo_ctrl: Mmio::new(), + line_ctrl: Mmio::new(), + modem_ctrl: Mmio::new(), + line_sts: ReadOnly::new(Mmio::new()), + modem_sts: ReadOnly::new(Mmio::new()) + } + } +} + +impl> SerialPort { + pub fn init(&mut self) { + //TODO: Cleanup + self.int_en.write(0x00); + self.line_ctrl.write(0x80); + self.data.write(0x03); + self.int_en.write(0x00); + self.line_ctrl.write(0x03); + self.fifo_ctrl.write(0xC7); + self.modem_ctrl.write(0x0B); + self.int_en.write(0x01); + } + + fn line_sts(&self) -> LineStsFlags { + LineStsFlags::from_bits_truncate(self.line_sts.read()) + } + + pub fn receive(&mut self) { + while self.line_sts().contains(INPUT_FULL) { + debug_input(self.data.read()); + } + } + + pub fn send(&mut self, data: u8) { + match data { + 8 | 0x7F => { + while ! self.line_sts().contains(OUTPUT_EMPTY) {} + self.data.write(8); + while ! self.line_sts().contains(OUTPUT_EMPTY) {} + self.data.write(b' '); + while ! self.line_sts().contains(OUTPUT_EMPTY) {} + self.data.write(8); + }, + _ => { + while ! self.line_sts().contains(OUTPUT_EMPTY) {} + self.data.write(data); + } + } + } +} + +impl> Write for SerialPort { + fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> { + for byte in s.bytes() { + self.send(byte); + } + + Ok(()) + } +} diff --git a/src/lib.rs b/src/lib.rs index aaedb09..33e746a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -42,9 +42,10 @@ pub use consts::*; /// Shared data structures pub mod common; -/// Macros like print, println, and interrupt +/// Architecture-dependent stuff #[macro_use] -pub mod macros; +pub mod arch; +pub use arch::*; /// Constants like memory locations pub mod consts; @@ -52,14 +53,12 @@ pub mod consts; /// ACPI table parsing mod acpi; -/// Architecture-dependent stuff -mod arch; -#[cfg(target_arch = "x86_64")] -pub use arch::x86_64::*; - /// Context management pub mod context; +/// Architecture-independent devices +pub mod devices; + /// ELF file parsing pub mod elf; diff --git a/src/macros.rs b/src/macros.rs deleted file mode 100644 index beaef43..0000000 --- a/src/macros.rs +++ /dev/null @@ -1,16 +0,0 @@ -/// Print to console -#[macro_export] -macro_rules! print { - ($($arg:tt)*) => ({ - use core::fmt::Write; - let _ = write!($crate::device::serial::COM1.lock(), $($arg)*); - }); -} - -/// Print with new line to console -#[macro_export] -macro_rules! println { - () => (print!("\n")); - ($fmt:expr) => (print!(concat!($fmt, "\n"))); - ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*)); -}