Use uart_16550 crate

master
WangRunji 7 years ago
parent da4db141d0
commit 0e2cccef9e

@ -32,6 +32,7 @@ linked_list_allocator = "0.6"
redox_syscall = "0.1" redox_syscall = "0.1"
xmas-elf = "0.6" xmas-elf = "0.6"
log = "0.4" log = "0.4"
uart_16550 = "0.1"
lazy_static = { version = "1.0.0", features = ["spin_no_std"] } lazy_static = { version = "1.0.0", features = ["spin_no_std"] }
simple-filesystem = { git = "https://github.com/wangrunji0408/SimpleFileSystem-Rust" } simple-filesystem = { git = "https://github.com/wangrunji0408/SimpleFileSystem-Rust" }
bit-allocator = { path = "crate/bit-allocator" } bit-allocator = { path = "crate/bit-allocator" }

@ -1,11 +1,12 @@
// Copy from Redox // Copy from Redox
use core::fmt::{self, Write}; use core::fmt::{self, Write};
use redox_syscall::io::{Io, Mmio, Pio, ReadOnly}; use redox_syscall::io::{Io, Pio};
use spin::Mutex; use spin::Mutex;
use uart_16550::SerialPort;
pub static COM1: Mutex<Serial> = Mutex::new(Serial::new(0x3F8)); pub static COM1: Mutex<SerialPort> = Mutex::new(SerialPort::new(0x3F8));
pub static COM2: Mutex<Serial> = Mutex::new(Serial::new(0x2F8)); pub static COM2: Mutex<SerialPort> = Mutex::new(SerialPort::new(0x2F8));
pub fn init() { pub fn init() {
assert_has_not_been_called!("serial::init must be called only once"); assert_has_not_been_called!("serial::init must be called only once");
@ -17,127 +18,21 @@ pub fn init() {
enable_irq(IRQ_COM2); enable_irq(IRQ_COM2);
} }
#[allow(dead_code)] pub trait SerialRead {
pub struct SerialPort<T: Io<Value = u8>> { fn receive(&mut self);
/// 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<T>,
/// Modem status
modem_sts: ReadOnly<T>,
} }
type Serial = SerialPort<Pio<u8>>; impl SerialRead for SerialPort {
fn receive(&mut self) {
impl SerialPort<Pio<u8>> { unsafe {
pub const fn new(base: u16) -> SerialPort<Pio<u8>> { let ports = self as *mut _ as *mut [Pio<u8>; 6];
SerialPort { let line_sts = &(*ports)[5];
data: Pio::new(base), let data = &(*ports)[0];
int_en: Pio::new(base + 1), while line_sts.read() & 1 == 1 {
fifo_ctrl: Pio::new(base + 2), let data = data.read();
line_ctrl: Pio::new(base + 3), writeln!(self, "serial receive {}", data).unwrap();
modem_ctrl: Pio::new(base + 4), // TODO handle received data
line_sts: ReadOnly::new(Pio::new(base + 5)),
modem_sts: ReadOnly::new(Pio::new(base + 6))
}
}
}
impl SerialPort<Mmio<u8>> {
pub fn new(_base: usize) -> SerialPort<Mmio<u8>> {
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<T: Io<Value = u8>> SerialPort<T> {
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<T: Io<Value = u8>> Write for SerialPort<T> {
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
}
}

@ -132,13 +132,13 @@ fn keyboard() {
} }
fn com1() { fn com1() {
use arch::driver::serial::COM1; use arch::driver::serial::*;
info!("\nInterupt: COM1"); info!("\nInterupt: COM1");
COM1.lock().receive(); COM1.lock().receive();
} }
fn com2() { fn com2() {
use arch::driver::serial::COM2; use arch::driver::serial::*;
info!("\nInterupt: COM2"); info!("\nInterupt: COM2");
COM2.lock().receive(); COM2.lock().receive();
} }

@ -35,6 +35,7 @@ extern crate rlibc;
extern crate simple_filesystem; extern crate simple_filesystem;
extern crate spin; extern crate spin;
extern crate syscall as redox_syscall; extern crate syscall as redox_syscall;
extern crate uart_16550;
extern crate volatile; extern crate volatile;
#[macro_use] #[macro_use]
extern crate x86_64; extern crate x86_64;

Loading…
Cancel
Save