diff --git a/arch/x86_64/Cargo.toml b/arch/x86_64/Cargo.toml index 65a644a3d0f1b1944857c183d29d7a7623102e47..567b412ce781d6b0ce379af82657c726bd703d60 100644 --- a/arch/x86_64/Cargo.toml +++ b/arch/x86_64/Cargo.toml @@ -4,7 +4,8 @@ version = "0.1.0" [dependencies] bitflags = "*" -hole_list_allocator = { path = "../../alloc/hole_list_allocator"} +hole_list_allocator = { path = "../../alloc/hole_list_allocator" } +io = { path = "../../drivers/io" } ransid = { git = "https://github.com/redox-os/ransid.git", branch = "new_api" } spin = "*" diff --git a/arch/x86_64/src/device/mod.rs b/arch/x86_64/src/device/mod.rs index 02fe70dd11e69d00b70628e0b56fd8c866a2aec9..c8032646e51d355f792a25b3b5f4da2b6f1ccc63 100644 --- a/arch/x86_64/src/device/mod.rs +++ b/arch/x86_64/src/device/mod.rs @@ -1,11 +1,9 @@ use paging::ActivePageTable; pub mod display; -pub mod ps2; pub mod serial; pub unsafe fn init(active_table: &mut ActivePageTable){ serial::init(); display::init(active_table); - ps2::init(); } diff --git a/arch/x86_64/src/io/mod.rs b/arch/x86_64/src/io/mod.rs deleted file mode 100644 index 86a1c34f42c2c4e612000fbbd6adfdc830887efb..0000000000000000000000000000000000000000 --- a/arch/x86_64/src/io/mod.rs +++ /dev/null @@ -1,9 +0,0 @@ -/// I/O functions - -pub use self::io::*; -pub use self::mmio::*; -pub use self::pio::*; - -mod io; -mod mmio; -mod pio; diff --git a/arch/x86_64/src/lib.rs b/arch/x86_64/src/lib.rs index 21d4ceb353343f9b9bd3dd3b95fb2f35d9860d4b..c7e5f877df0f841b6aa9b656c7cb81cd10299a89 100644 --- a/arch/x86_64/src/lib.rs +++ b/arch/x86_64/src/lib.rs @@ -15,6 +15,7 @@ extern crate hole_list_allocator as allocator; #[macro_use] extern crate bitflags; +extern crate io; extern crate ransid; extern crate spin; pub extern crate x86; @@ -198,9 +199,6 @@ pub mod gdt; /// Interrupt descriptor table pub mod idt; -/// IO Handling -pub mod io; - /// Interrupt instructions pub mod interrupt; diff --git a/drivers/io/Cargo.toml b/drivers/io/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..b0ee40b297428b67e55088d62657e3efc2e6123e --- /dev/null +++ b/drivers/io/Cargo.toml @@ -0,0 +1,3 @@ +[package] +name = "io" +version = "0.1.0" diff --git a/arch/x86_64/src/io/io.rs b/drivers/io/src/io.rs similarity index 100% rename from arch/x86_64/src/io/io.rs rename to drivers/io/src/io.rs diff --git a/drivers/io/src/lib.rs b/drivers/io/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..22f8eb72c0ba52ae3bd36795116a98f1fc1cee31 --- /dev/null +++ b/drivers/io/src/lib.rs @@ -0,0 +1,14 @@ +//! I/O functions + +#![feature(asm)] +#![feature(const_fn)] +#![feature(core_intrinsics)] +#![no_std] + +pub use self::io::*; +pub use self::mmio::*; +pub use self::pio::*; + +mod io; +mod mmio; +mod pio; diff --git a/arch/x86_64/src/io/mmio.rs b/drivers/io/src/mmio.rs similarity index 100% rename from arch/x86_64/src/io/mmio.rs rename to drivers/io/src/mmio.rs diff --git a/arch/x86_64/src/io/pio.rs b/drivers/io/src/pio.rs similarity index 53% rename from arch/x86_64/src/io/pio.rs rename to drivers/io/src/pio.rs index 562c1c1e13e3000d9f5a9adb648f36b67d49b5c1..91ae310b624a06029cd872905ea2f97abdc42e9a 100644 --- a/arch/x86_64/src/io/pio.rs +++ b/drivers/io/src/pio.rs @@ -1,5 +1,4 @@ use core::marker::PhantomData; -use x86::io; use super::io::Io; @@ -27,13 +26,19 @@ impl Io for Pio<u8> { /// Read #[inline(always)] fn read(&self) -> u8 { - unsafe { io::inb(self.port) } + let value: u8; + unsafe { + asm!("in $0, $1" : "={al}"(value) : "{dx}"(self.port) : "memory" : "intel", "volatile"); + } + value } /// Write #[inline(always)] fn write(&mut self, value: u8) { - unsafe { io::outb(self.port, value) } + unsafe { + asm!("out $1, $0" : : "{al}"(value), "{dx}"(self.port) : "memory" : "intel", "volatile"); + } } } @@ -44,13 +49,19 @@ impl Io for Pio<u16> { /// Read #[inline(always)] fn read(&self) -> u16 { - unsafe { io::inw(self.port) } + let value: u16; + unsafe { + asm!("in $0, $1" : "={ax}"(value) : "{dx}"(self.port) : "memory" : "intel", "volatile"); + } + value } /// Write #[inline(always)] fn write(&mut self, value: u16) { - unsafe { io::outw(self.port, value) } + unsafe { + asm!("out $1, $0" : : "{ax}"(value), "{dx}"(self.port) : "memory" : "intel", "volatile"); + } } } @@ -61,12 +72,18 @@ impl Io for Pio<u32> { /// Read #[inline(always)] fn read(&self) -> u32 { - unsafe { io::inl(self.port) } + let value: u32; + unsafe { + asm!("in $0, $1" : "={eax}"(value) : "{dx}"(self.port) : "memory" : "intel", "volatile"); + } + value } /// Write #[inline(always)] fn write(&mut self, value: u32) { - unsafe { io::outl(self.port, value) } + unsafe { + asm!("out $1, $0" : : "{eax}"(value), "{dx}"(self.port) : "memory" : "intel", "volatile"); + } } } diff --git a/drivers/ps2d/Cargo.toml b/drivers/ps2d/Cargo.toml index f49dee131349c9f1e94ec6fc3bf6a4c0eb253b61..665e3c19c89c0898c0fd97330cf3843b86519453 100644 --- a/drivers/ps2d/Cargo.toml +++ b/drivers/ps2d/Cargo.toml @@ -2,5 +2,8 @@ name = "ps2d" version = "0.1.0" -[dependencies.syscall] -path = "../../syscall/" +[dependencies] +bitflags = "*" +io = { path = "../io/" } +spin = "*" +syscall = { path = "../../syscall/" } diff --git a/arch/x86_64/src/device/ps2.rs b/drivers/ps2d/src/controller.rs similarity index 66% rename from arch/x86_64/src/device/ps2.rs rename to drivers/ps2d/src/controller.rs index 8b29f0310c2d5b2aa7bda404d295381a745f7632..8355dba7bc8e59de22c22298b2f8e56e6986c0e8 100644 --- a/arch/x86_64/src/device/ps2.rs +++ b/drivers/ps2d/src/controller.rs @@ -1,5 +1,3 @@ -use core::cmp; - use io::{Io, Pio, ReadOnly, WriteOnly}; pub unsafe fn init() { @@ -79,86 +77,6 @@ enum MouseCommandData { SetSampleRate = 0xF3, } -bitflags! { - flags MousePacketFlags: u8 { - const LEFT_BUTTON = 1, - const RIGHT_BUTTON = 1 << 1, - const MIDDLE_BUTTON = 1 << 2, - const ALWAYS_ON = 1 << 3, - const X_SIGN = 1 << 4, - const Y_SIGN = 1 << 5, - const X_OVERFLOW = 1 << 6, - const Y_OVERFLOW = 1 << 7 - } -} - -pub struct Ps2Mouse { - data: ReadOnly<Pio<u8>>, - mouse: [u8; 4], - mouse_i: usize, - mouse_extra: bool, - mouse_x: usize, - mouse_y: usize -} - -impl Ps2Mouse { - fn new(mouse_extra: bool) -> Self { - Ps2Mouse { - data: ReadOnly::new(Pio::new(0x60)), - mouse: [0; 4], - mouse_i: 0, - mouse_extra: mouse_extra, - mouse_x: 0, - mouse_y: 0 - } - } - - pub fn on_irq(&mut self) { - self.mouse[self.mouse_i] = self.data.read(); - self.mouse_i += 1; - - let flags = MousePacketFlags::from_bits_truncate(self.mouse[0]); - if ! flags.contains(ALWAYS_ON) { - println!("MOUSE MISALIGN {:X}", self.mouse[0]); - - self.mouse = [0; 4]; - self.mouse_i = 0; - } else if self.mouse_i >= self.mouse.len() || (!self.mouse_extra && self.mouse_i >= 3) { - if ! flags.contains(X_OVERFLOW) && ! flags.contains(Y_OVERFLOW) { - let mut dx = self.mouse[1] as isize; - if flags.contains(X_SIGN) { - dx -= 0x100; - } - - let mut dy = self.mouse[2] as isize; - if flags.contains(Y_SIGN) { - dy -= 0x100; - } - - let _extra = if self.mouse_extra { - self.mouse[3] - } else { - 0 - }; - - //print!("MOUSE {:?}, {}, {}, {}\n", flags, dx, dy, extra); - - if let Some(ref mut display) = *super::display::DISPLAY.lock() { - self.mouse_x = cmp::max(0, cmp::min(display.width as isize - 1, self.mouse_x as isize + dx)) as usize; - self.mouse_y = cmp::max(0, cmp::min(display.height as isize - 1, self.mouse_y as isize - dy)) as usize; - let offset = self.mouse_y * display.width + self.mouse_x; - display.onscreen[offset as usize] = 0xFF0000; - } - } else { - println!("MOUSE OVERFLOW {:X} {:X} {:X} {:X}", self.mouse[0], self.mouse[1], self.mouse[2], self.mouse[3]); - } - - self.mouse = [0; 4]; - self.mouse_i = 0; - } - } -} - pub struct Ps2 { data: Pio<u8>, status: ReadOnly<Pio<u8>>, @@ -166,7 +84,7 @@ pub struct Ps2 { } impl Ps2 { - const fn new() -> Self { + pub fn new() -> Self { Ps2 { data: Pio::new(0x60), status: ReadOnly::new(Pio::new(0x64)), @@ -244,7 +162,7 @@ impl Ps2 { self.read() } - fn init(&mut self) { + pub fn init(&mut self) -> bool { // Disable devices self.command(Command::DisableFirst); self.command(Command::DisableSecond); @@ -294,18 +212,6 @@ impl Ps2 { let mouse_id = self.read(); let mouse_extra = mouse_id == 3; - // Enable extra buttons, TODO - /* - if self.mouse_extra { - print!("SAMPLE 200 {:X}\n", self.mouse_command_data(MouseCommandData::SetSampleRate, 200)); - print!("SAMPLE 200 {:X}\n", self.mouse_command_data(MouseCommandData::SetSampleRate, 200)); - print!("SAMPLE 80 {:X}\n", self.mouse_command_data(MouseCommandData::SetSampleRate, 80)); - print!("GET ID {:X}\n", self.mouse_command(MouseCommand::GetDeviceId)); - let mouse_id = self.read(); - print!("MOUSE ID: {:X} == 0x04\n", mouse_id); - } - */ - // Set sample rate to maximum assert_eq!(self.mouse_command_data(MouseCommandData::SetSampleRate, 200), 0xFA); @@ -325,5 +231,7 @@ impl Ps2 { } self.flush_read(); + + mouse_extra } } diff --git a/drivers/ps2d/src/keyboard.rs b/drivers/ps2d/src/keyboard.rs new file mode 100644 index 0000000000000000000000000000000000000000..109819a7256343587c0e7df0ab21c6c308098cdb --- /dev/null +++ b/drivers/ps2d/src/keyboard.rs @@ -0,0 +1,34 @@ +use std::fs::File; +use std::io::{Read, Write}; +use std::mem; +use std::thread; + +use keymap; + +pub fn keyboard() { + let mut file = File::open("irq:1").expect("ps2d: failed to open irq:1"); + + loop { + let mut irqs = [0; 8]; + if file.read(&mut irqs).expect("ps2d: failed to read irq:1") >= mem::size_of::<usize>() { + let data: u8; + unsafe { + asm!("in al, dx" : "={al}"(data) : "{dx}"(0x60) : : "intel", "volatile"); + } + + let (scancode, pressed) = if data >= 0x80 { + (data - 0x80, false) + } else { + (data, true) + }; + + if pressed { + print!("{}", keymap::get_char(scancode)); + } + + file.write(&irqs).expect("ps2d: failed to write irq:1"); + } else { + thread::yield_now(); + } + } +} diff --git a/drivers/ps2d/src/main.rs b/drivers/ps2d/src/main.rs index f5818a6b7ae9e84ae5e637d6061c9a60884e7340..4a3888eab85c5b1c96d952598079a9a4b29c19ad 100644 --- a/drivers/ps2d/src/main.rs +++ b/drivers/ps2d/src/main.rs @@ -1,77 +1,42 @@ #![feature(asm)] +#[macro_use] +extern crate bitflags; +extern crate io; extern crate syscall; -use std::fs::File; -use std::io::{Read, Write}; -use std::mem; use std::thread; use syscall::iopl; +mod controller; +mod keyboard; mod keymap; +mod mouse; -fn keyboard() { - let mut file = File::open("irq:1").expect("pskbd: failed to open irq:1"); - - loop { - let mut irqs = [0; 8]; - if file.read(&mut irqs).expect("pskbd: failed to read irq:1") >= mem::size_of::<usize>() { - let data: u8; - unsafe { - asm!("in al, dx" : "={al}"(data) : "{dx}"(0x60) : : "intel", "volatile"); - } - - let (scancode, pressed) = if data >= 0x80 { - (data - 0x80, false) - } else { - (data, true) - }; - println!("pskbd: IRQ {}: {:X}: {:X}: {}: {}", unsafe { *(irqs.as_ptr() as *const usize) }, data, scancode, keymap::get_char(scancode), pressed); - - file.write(&irqs).expect("pskbd: failed to write irq:1"); - } else { - thread::yield_now(); - } +fn main() { + unsafe { + iopl(3).expect("ps2d: failed to get I/O permission"); + asm!("cli" :::: "intel", "volatile"); } -} - -fn mouse() { - let mut file = File::open("irq:12").expect("psmsd: failed to open irq:12"); - loop { - let mut irqs = [0; 8]; - if file.read(&mut irqs).expect("psmsd: failed to read irq:12") >= mem::size_of::<usize>() { - let data: u8; - unsafe { - asm!("in al, dx" : "={al}"(data) : "{dx}"(0x60) : : "intel", "volatile"); - } + let extra_packet = controller::Ps2::new().init(); - println!("psmsd: IRQ {}: {:X}", unsafe { *(irqs.as_ptr() as *const usize) }, data); - - file.write(&irqs).expect("psmsd: failed to write irq:12"); - } else { - thread::yield_now(); - } - } -} - -fn main() { thread::spawn(|| { unsafe { - iopl(3).expect("pskbd: failed to get I/O permission"); + iopl(3).expect("ps2d: failed to get I/O permission"); asm!("cli" :::: "intel", "volatile"); } - keyboard(); + keyboard::keyboard(); }); - thread::spawn(|| { + thread::spawn(move || { unsafe { - iopl(3).expect("psmsd: failed to get I/O permission"); + iopl(3).expect("ps2d: failed to get I/O permission"); asm!("cli" :::: "intel", "volatile"); } - mouse(); + mouse::mouse(extra_packet); }); } diff --git a/drivers/ps2d/src/mouse.rs b/drivers/ps2d/src/mouse.rs new file mode 100644 index 0000000000000000000000000000000000000000..f273de9670ce2612284141ca0d9f32638c9188cd --- /dev/null +++ b/drivers/ps2d/src/mouse.rs @@ -0,0 +1,73 @@ +use std::fs::File; +use std::io::{Read, Write}; +use std::mem; +use std::thread; + +bitflags! { + flags MousePacketFlags: u8 { + const LEFT_BUTTON = 1, + const RIGHT_BUTTON = 1 << 1, + const MIDDLE_BUTTON = 1 << 2, + const ALWAYS_ON = 1 << 3, + const X_SIGN = 1 << 4, + const Y_SIGN = 1 << 5, + const X_OVERFLOW = 1 << 6, + const Y_OVERFLOW = 1 << 7 + } +} + +pub fn mouse(extra_packet: bool) { + let mut file = File::open("irq:12").expect("ps2d: failed to open irq:12"); + + let mut packets = [0; 4]; + let mut packet_i = 0; + loop { + let mut irqs = [0; 8]; + if file.read(&mut irqs).expect("ps2d: failed to read irq:12") >= mem::size_of::<usize>() { + let data: u8; + unsafe { + asm!("in al, dx" : "={al}"(data) : "{dx}"(0x60) : : "intel", "volatile"); + } + + packets[packet_i] = data; + packet_i += 1; + + let flags = MousePacketFlags::from_bits_truncate(packets[0]); + if ! flags.contains(ALWAYS_ON) { + println!("MOUSE MISALIGN {:X}", packets[0]); + + packets = [0; 4]; + packet_i = 0; + } else if packet_i >= packets.len() || (!extra_packet && packet_i >= 3) { + if ! flags.contains(X_OVERFLOW) && ! flags.contains(Y_OVERFLOW) { + let mut dx = packets[1] as isize; + if flags.contains(X_SIGN) { + dx -= 0x100; + } + + let mut dy = packets[2] as isize; + if flags.contains(Y_SIGN) { + dy -= 0x100; + } + + let extra = if extra_packet { + packets[3] + } else { + 0 + }; + + print!("ps2d: IRQ {:?}, {}, {}, {}\n", flags, dx, dy, extra); + } else { + println!("ps2d: overflow {:X} {:X} {:X} {:X}", packets[0], packets[1], packets[2], packets[3]); + } + + packets = [0; 4]; + packet_i = 0; + } + + file.write(&irqs).expect("ps2d: failed to write irq:12"); + } else { + thread::yield_now(); + } + } +}