Simplify ps2 interrupts to reduce latency to reading bytes

This commit is contained in:
Jeremy Soller
2022-09-08 10:33:31 -06:00
parent f5bdae2d0c
commit 3bef7d7bad
2 changed files with 22 additions and 76 deletions

View File

@@ -8,48 +8,13 @@ use crate::device::{local_apic, ioapic, pic};
use crate::device::serial::{COM1, COM2};
use crate::ipi::{ipi, IpiKind, IpiTarget};
use crate::scheme::debug::{debug_input, debug_notify};
use crate::scheme::serio::serio_input;
use crate::{context, time};
//resets to 0 in context::switch()
#[thread_local]
pub static PIT_TICKS: AtomicUsize = AtomicUsize::new(0);
// The only way to read PS2 data without race conditions is to allow a keyboard interrupt to happen
// and then read data while reading mouse data, since keyboard data overrides mouse data and
// reading the status register is not done atomically with reading the data. This is not possible
// from userspace, so we do this minimal part of the PS2 driver in the kernel.
#[inline(always)]
unsafe fn ps2_interrupt(_index: usize) {
use crate::scheme::serio::serio_input;
let data: u8;
let status: u8;
core::arch::asm!("
sti
nop
cli
in al, 0x64
mov ah, al
in al, 0x60
mov {}, al
mov {}, ah
",
out(reg_byte) data,
out(reg_byte) status,
);
if status & 1 != 0 {
let status_index = if status & (1 << 5) == 0 {
// Keyboard, according to status
0
} else {
// Mouse, according to status
1
};
serio_input(status_index, data);
}
}
#[repr(u8)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum IrqMethod {
@@ -196,8 +161,12 @@ interrupt_stack!(pit_stack, |_stack| {
});
interrupt!(keyboard, || {
ps2_interrupt(0);
let data: u8;
core::arch::asm!("in al, 0x60", out("al") data);
eoi(1);
serio_input(0, data);
});
interrupt!(cascade, || {
@@ -262,8 +231,12 @@ interrupt!(pci3, || {
});
interrupt!(mouse, || {
ps2_interrupt(1);
let data: u8;
core::arch::asm!("in al, 0x60", out("al") data);
eoi(12);
serio_input(1, data);
});
interrupt!(fpu, || {

View File

@@ -8,48 +8,13 @@ use crate::device::{local_apic, ioapic, pic};
use crate::device::serial::{COM1, COM2};
use crate::ipi::{ipi, IpiKind, IpiTarget};
use crate::scheme::debug::{debug_input, debug_notify};
use crate::scheme::serio::serio_input;
use crate::{context, time};
//resets to 0 in context::switch()
#[thread_local]
pub static PIT_TICKS: AtomicUsize = AtomicUsize::new(0);
// The only way to read PS2 data without race conditions is to allow a keyboard interrupt to happen
// and then read data while reading mouse data, since keyboard data overrides mouse data and
// reading the status register is not done atomically with reading the data. This is not possible
// from userspace, so we do this minimal part of the PS2 driver in the kernel.
#[inline(always)]
unsafe fn ps2_interrupt(_index: usize) {
use crate::scheme::serio::serio_input;
let data: u8;
let status: u8;
core::arch::asm!("
sti
nop
cli
in al, 0x64
mov ah, al
in al, 0x60
mov {}, al
mov {}, ah
",
out(reg_byte) data,
out(reg_byte) status,
);
if status & 1 != 0 {
let status_index = if status & (1 << 5) == 0 {
// Keyboard, according to status
0
} else {
// Mouse, according to status
1
};
serio_input(status_index, data);
}
}
#[repr(u8)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum IrqMethod {
@@ -196,8 +161,12 @@ interrupt_stack!(pit_stack, |_stack| {
});
interrupt!(keyboard, || {
ps2_interrupt(0);
let data: u8;
core::arch::asm!("in al, 0x60", out("al") data);
eoi(1);
serio_input(0, data);
});
interrupt!(cascade, || {
@@ -262,8 +231,12 @@ interrupt!(pci3, || {
});
interrupt!(mouse, || {
ps2_interrupt(1);
let data: u8;
core::arch::asm!("in al, 0x60", out("al") data);
eoi(12);
serio_input(1, data);
});
interrupt!(fpu, || {