-
-
Notifications
You must be signed in to change notification settings - Fork 779
x86_q35: add ps/2 controller to connect mouse and keyboard peripherals for VGA #4594
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would suggest adding a _timeout
to all wait_
functions.
step1: PS/2 controller self-test (clock & IRQ still disabled) step2: enable keyboard clock (IRQ 1 still masked) step3: full PS/2 driver – self-test, clock on, IRQ1 unmasked, single-byte buffering step4: drain-loop IRQ handler; full ring-buffer active step5: add send_with_ack() with RESEND retry; enable keyboard scanning (0xF4) step7: implemented some unit tests to debug buffers fix: readded comments from previous controller, moved ps2.init() to enable debug macro feature: added IRQ1 self-test when init.
workflow: rebased with upstream
…for init, reworked ISR to handle drop parity/timeout => make/break logs + prefixes
…lf to keep ISR tny, minor polish
…spin number, removed helper functions
1392160
to
0d862a9
Compare
chips/x86_q35/src/ps2.rs
Outdated
/// Client hook (future: keyboard capsule) | ||
pub trait Ps2Client { | ||
fn receive_scancode(&self, code: u8); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We do have a keyboard HIL now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed the old P2Client and added the keyboard HIL. Will take a look to see how should I implement it in the keyboard driver.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Edit regarding my previous message (prepare for a loong message :D )
We split the PS/2 stack into two layers:
Controller (transport): ps2.rs
-
Owns the i8042 hardware: port I/O, status polling, bring-up (self-test, config, Set-2, enable IRQ1).
-
IRQ top-half enqueues raw bytes; deferred call (bottom-half) drains a ring buffer and forwards bytes to a small, local hook:
Keyboard (device): keyboard.rs
-
Implements the new
kernel::hil::keyboard::Keyboard<'a>
and calls the HIL client via:c.keys_pressed(&[(linux_keycode, pressed)], Ok(()));
-
Implements Ps2Client so the controller can feed it raw bytes.
-
Provides a Set-2 decoder (E0/F0/E1) and emits MAKE/BREAK logs after prefix resolution.
-
Maps Set-2 - Linux keycodes (initial coverage: letters, digits, common modifiers, arrows).
-
Contains a small command engine (ACK/RESEND FIFO) for device commands (to move full init here later and to send commands).
(i wrote this in x86_q35: add keyboard driver over i8042 controller #4595)
Now the big question :
Why keep Ps2Client if we have a keyboard HIL now ?
Ps2Client is not another HIL; it’s a tiny internal hook for the controller to deliver raw scancodes to some consumer (the keyboard device here, but could be a mouse/AUX later). The actual HIL interface is implemented in keyboard.rs (emitting Linux keycodes + press/release), which matches the new kernel/src/hil/keyboard.rs
. We removed the old ASCII path and byte emission. We now rely solely on the HIL interface for key events.
This separation keeps responsibilities clean:
-
Controller = reusable i8042 transport (also future-proof for AUX/mouse).
-
Keyboard = device semantics (decode, mapping, HIL emission).
// PS/2 inside the component | ||
let ps2 = | ||
unsafe { static_init!(crate::ps2::Ps2Controller, crate::ps2::Ps2Controller::new()) }; | ||
kernel::deferred_call::DeferredCallClient::register(ps2); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now is not that time, but at some point we need to stop adding new static_init
here, which shouldn't have ever been here.
Once we have #4595 ready and the PR which uses this stack we can start merging these. |
Pull Request Overview
This pull request adds an i8042 PS/2 controller for the x86_q35 platform and wires it into the board/chip (all was done according to https://wiki.osdev.org/I8042_PS/2_Controller)
Implements controller bring-up (init_early): disable ports, flush OB, self-test, typed config byte updates (translation OFF, clocks/IRQs as needed), keyboard port test/enable, and device init (F5, FF => AA, F0 02, F4).
Interrupt/top-half: reads OB, drops bytes with parity/timeout errors, enqueues scan codes, and schedules a deferred call.
Deferred/bottom-half: drains a ring buffer and currently logs Set-2 MAKE/BREAK lines; also exposes a client hook:
pub trait Ps2Client { fn receive_scancode(&self, code: u8); }
pub fn set_client(&self, client: &'static dyn Ps2Client)
Observability: adds
Ps2Health { bytes_rx, overruns, parity_err, timeout_err, timeouts, resends }
andhealth_snapshot()
, with periodic debug logging.Uses
LocalRegisterCopy<u8, CONFIG::Register>
for typed, safe CONFIG-byte manipulation.Integrates with PcComponent: registers as a DeferredCallClient, dispatches IRQ1 to the controller, and runs bring-up during finalize.
Testing Strategy
This pull request was tested by running on QEMU
Verified IRQ1 fires, ISR queues bytes, and deferred call drains/logs MAKE/BREAK for key presses.
Observed bytes_rx increasing in health logs; no parity/timeout drops seen during normal typing.
Confirmed no regressions in PIT and serial console paths; kernel boots and services interrupts normally.
TODO or Help Wanted
Documentation Updated
/docs
, or no updates are required.Formatting
make prepush
.