From 0b3be623fc9e9e9e319da38f694d64f146f005ab Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 19 Sep 2016 17:19:49 -0600 Subject: [PATCH] Move PS/2 driver to userspace --- arch/x86_64/Cargo.toml | 3 +- arch/x86_64/src/device/mod.rs | 2 - arch/x86_64/src/io/mod.rs | 9 -- arch/x86_64/src/lib.rs | 4 +- drivers/io/Cargo.toml | 3 + {arch/x86_64/src/io => drivers/io/src}/io.rs | 0 drivers/io/src/lib.rs | 14 +++ .../x86_64/src/io => drivers/io/src}/mmio.rs | 0 {arch/x86_64/src/io => drivers/io/src}/pio.rs | 31 ++++-- drivers/ps2d/Cargo.toml | 7 +- .../ps2.rs => drivers/ps2d/src/controller.rs | 100 +----------------- drivers/ps2d/src/keyboard.rs | 34 ++++++ drivers/ps2d/src/main.rs | 71 ++++--------- drivers/ps2d/src/mouse.rs | 73 +++++++++++++ 14 files changed, 178 insertions(+), 173 deletions(-) delete mode 100644 arch/x86_64/src/io/mod.rs create mode 100644 drivers/io/Cargo.toml rename {arch/x86_64/src/io => drivers/io/src}/io.rs (100%) create mode 100644 drivers/io/src/lib.rs rename {arch/x86_64/src/io => drivers/io/src}/mmio.rs (100%) rename {arch/x86_64/src/io => drivers/io/src}/pio.rs (53%) rename arch/x86_64/src/device/ps2.rs => drivers/ps2d/src/controller.rs (66%) create mode 100644 drivers/ps2d/src/keyboard.rs create mode 100644 drivers/ps2d/src/mouse.rs diff --git a/arch/x86_64/Cargo.toml b/arch/x86_64/Cargo.toml index 65a644a..567b412 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 02fe70d..c803264 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 86a1c34..0000000 --- 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 21d4ceb..c7e5f87 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 0000000..b0ee40b --- /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 0000000..22f8eb7 --- /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 562c1c1..91ae310 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 { /// 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 { /// 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 { /// 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 f49dee1..665e3c1 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 8b29f03..8355dba 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>, - 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, status: ReadOnly>, @@ -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 0000000..109819a --- /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::() { + 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 f5818a6..4a3888e 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; - -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::() { - 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 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::() { - let data: u8; - unsafe { - asm!("in al, dx" : "={al}"(data) : "{dx}"(0x60) : : "intel", "volatile"); - } - - 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(); - } - } -} +mod mouse; fn main() { + unsafe { + iopl(3).expect("ps2d: failed to get I/O permission"); + asm!("cli" :::: "intel", "volatile"); + } + + let extra_packet = controller::Ps2::new().init(); + 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 0000000..f273de9 --- /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::() { + 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(); + } + } +}