diff --git a/Cargo.toml b/Cargo.toml index 3918d80..a4d9d16 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,6 +32,7 @@ linked_list_allocator = "0.6" redox_syscall = "0.1" xmas-elf = "0.6" log = "0.4" +uart_16550 = "0.1" lazy_static = { version = "1.0.0", features = ["spin_no_std"] } simple-filesystem = { git = "https://github.com/wangrunji0408/SimpleFileSystem-Rust" } bit-allocator = { path = "crate/bit-allocator" } diff --git a/src/arch/x86_64/driver/serial.rs b/src/arch/x86_64/driver/serial.rs index bee8ad2..bfe9b24 100644 --- a/src/arch/x86_64/driver/serial.rs +++ b/src/arch/x86_64/driver/serial.rs @@ -1,11 +1,12 @@ // Copy from Redox use core::fmt::{self, Write}; -use redox_syscall::io::{Io, Mmio, Pio, ReadOnly}; +use redox_syscall::io::{Io, Pio}; use spin::Mutex; +use uart_16550::SerialPort; -pub static COM1: Mutex = Mutex::new(Serial::new(0x3F8)); -pub static COM2: Mutex = Mutex::new(Serial::new(0x2F8)); +pub static COM1: Mutex = Mutex::new(SerialPort::new(0x3F8)); +pub static COM2: Mutex = Mutex::new(SerialPort::new(0x2F8)); pub fn init() { assert_has_not_been_called!("serial::init must be called only once"); @@ -17,127 +18,21 @@ pub fn init() { enable_irq(IRQ_COM2); } -#[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, +pub trait SerialRead { + fn receive(&mut self); } -type Serial = SerialPort>; - -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(LineStsFlags::INPUT_FULL) { - let data = self.data.read(); - write!(self, "serial receive {}", data).unwrap(); - // TODO handle received data - } - } - - fn wait(&self) { - while ! self.line_sts().contains(LineStsFlags::OUTPUT_EMPTY) {} - } - - pub fn send(&mut self, data: u8) { - match data { - 8 | 0x7F => { - self.wait(); - self.data.write(8); - self.wait(); - self.data.write(b' '); - self.wait(); - self.data.write(8); - }, - _ => { - self.wait(); - self.data.write(data); +impl SerialRead for SerialPort { + fn receive(&mut self) { + unsafe { + let ports = self as *mut _ as *mut [Pio; 6]; + let line_sts = &(*ports)[5]; + let data = &(*ports)[0]; + while line_sts.read() & 1 == 1 { + let data = data.read(); + writeln!(self, "serial receive {}", data).unwrap(); + // TODO handle received data } } } } - -impl> Write for SerialPort { - fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> { - for byte in s.bytes() { - self.send(byte); - } - Ok(()) - } -} - -bitflags! { - /// Interrupt enable flags - struct IntEnFlags: u8 { - const RECEIVED = 1 << 0; - const SENT = 1 << 1; - const ERRORED = 1 << 2; - const STATUS_CHANGE = 1 << 3; - // 4 to 7 are unused - } -} - -bitflags! { - /// Line status flags - struct LineStsFlags: u8 { - const INPUT_FULL = 1 << 0; - // 1 to 4 unknown - const OUTPUT_EMPTY = 1 << 5; - // 6 and 7 unknown - } -} \ No newline at end of file diff --git a/src/arch/x86_64/interrupt/handler.rs b/src/arch/x86_64/interrupt/handler.rs index 2e0dc07..4d9ade3 100644 --- a/src/arch/x86_64/interrupt/handler.rs +++ b/src/arch/x86_64/interrupt/handler.rs @@ -132,13 +132,13 @@ fn keyboard() { } fn com1() { - use arch::driver::serial::COM1; + use arch::driver::serial::*; info!("\nInterupt: COM1"); COM1.lock().receive(); } fn com2() { - use arch::driver::serial::COM2; + use arch::driver::serial::*; info!("\nInterupt: COM2"); COM2.lock().receive(); } diff --git a/src/lib.rs b/src/lib.rs index 89587a2..595cc2e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -35,6 +35,7 @@ extern crate rlibc; extern crate simple_filesystem; extern crate spin; extern crate syscall as redox_syscall; +extern crate uart_16550; extern crate volatile; #[macro_use] extern crate x86_64;