Flush TLB correctly when remapping
Seperate mouse and keyboard structs in PS/2 driver
This commit is contained in:
parent
44e8b99b46
commit
8563961f28
8 changed files with 169 additions and 112 deletions
|
@ -3,10 +3,13 @@ use spin::Mutex;
|
|||
|
||||
use io::{Io, Pio, ReadOnly, WriteOnly};
|
||||
|
||||
pub static PS2: Mutex<Ps2> = Mutex::new(Ps2::new());
|
||||
pub static PS2_KEYBOARD: Mutex<Option<Ps2Keyboard>> = Mutex::new(None);
|
||||
pub static PS2_MOUSE: Mutex<Option<Ps2Mouse>> = Mutex::new(None);
|
||||
|
||||
pub unsafe fn init() {
|
||||
PS2.lock().init();
|
||||
let (keyboard, mouse) = Ps2::new().init();
|
||||
*PS2_KEYBOARD.lock() = keyboard;
|
||||
*PS2_MOUSE.lock() = mouse;
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
|
@ -95,12 +98,36 @@ bitflags! {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct Ps2 {
|
||||
data: Pio<u8>,
|
||||
status: ReadOnly<Pio<u8>>,
|
||||
command: WriteOnly<Pio<u8>>,
|
||||
pub struct Ps2Keyboard {
|
||||
data: ReadOnly<Pio<u8>>,
|
||||
key: [u8; 3],
|
||||
key_i: usize,
|
||||
}
|
||||
|
||||
impl Ps2Keyboard {
|
||||
fn new() -> Self {
|
||||
Ps2Keyboard {
|
||||
data: ReadOnly::new(Pio::new(0x60)),
|
||||
key: [0; 3],
|
||||
key_i: 0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn on_irq(&mut self) {
|
||||
let scancode = self.data.read();
|
||||
self.key[self.key_i] = scancode;
|
||||
self.key_i += 1;
|
||||
if self.key_i >= self.key.len() || scancode < 0xE0 {
|
||||
println!("KEY: {:X} {:X} {:X}", self.key[0], self.key[1], self.key[2]);
|
||||
|
||||
self.key = [0; 3];
|
||||
self.key_i = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Ps2Mouse {
|
||||
data: ReadOnly<Pio<u8>>,
|
||||
mouse: [u8; 4],
|
||||
mouse_i: usize,
|
||||
mouse_extra: bool,
|
||||
|
@ -108,19 +135,76 @@ pub struct Ps2 {
|
|||
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>>,
|
||||
command: WriteOnly<Pio<u8>>
|
||||
}
|
||||
|
||||
impl Ps2 {
|
||||
const fn new() -> Ps2 {
|
||||
const fn new() -> Self {
|
||||
Ps2 {
|
||||
data: Pio::new(0x60),
|
||||
status: ReadOnly::new(Pio::new(0x64)),
|
||||
command: WriteOnly::new(Pio::new(0x64)),
|
||||
key: [0; 3],
|
||||
key_i: 0,
|
||||
mouse: [0; 4],
|
||||
mouse_i: 0,
|
||||
mouse_extra: false,
|
||||
mouse_x: 0,
|
||||
mouse_y: 0
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -194,7 +278,7 @@ impl Ps2 {
|
|||
self.read()
|
||||
}
|
||||
|
||||
fn init(&mut self) {
|
||||
fn init(&mut self) -> (Option<Ps2Keyboard>, Option<Ps2Mouse>) {
|
||||
// Disable devices
|
||||
self.command(Command::DisableFirst);
|
||||
self.command(Command::DisableSecond);
|
||||
|
@ -242,7 +326,7 @@ impl Ps2 {
|
|||
assert_eq!(self.mouse_command_data(MouseCommandData::SetSampleRate, 80), 0xFA);
|
||||
assert_eq!(self.mouse_command(MouseCommand::GetDeviceId), 0xFA);
|
||||
let mouse_id = self.read();
|
||||
self.mouse_extra = mouse_id == 3;
|
||||
let mouse_extra = mouse_id == 3;
|
||||
|
||||
// Enable extra buttons, TODO
|
||||
/*
|
||||
|
@ -272,57 +356,9 @@ impl Ps2 {
|
|||
config.insert(SECOND_INTERRUPT);
|
||||
self.set_config(config);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn on_keyboard(&mut self) {
|
||||
let scancode = self.data.read();
|
||||
self.key[self.key_i] = scancode;
|
||||
self.key_i += 1;
|
||||
if self.key_i >= self.key.len() || scancode < 0xE0 {
|
||||
//println!("KEY: {:X} {:X} {:X}", self.key[0], self.key[1], self.key[2]);
|
||||
self.flush_read();
|
||||
|
||||
self.key = [0; 3];
|
||||
self.key_i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn on_mouse(&mut self) {
|
||||
self.mouse[self.mouse_i] = self.data.read();
|
||||
self.mouse_i += 1;
|
||||
if self.mouse_i >= self.mouse.len() || (!self.mouse_extra && self.mouse_i >= 3) {
|
||||
let flags = MousePacketFlags::from_bits_truncate(self.mouse[0]);
|
||||
|
||||
if flags.contains(ALWAYS_ON) && ! 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!("BAD MOUSE {:?}", self.mouse);
|
||||
}
|
||||
|
||||
self.mouse = [0; 4];
|
||||
self.mouse_i = 0;
|
||||
}
|
||||
(Some(Ps2Keyboard::new()), Some(Ps2Mouse::new(mouse_extra)))
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue