From be868a43185826b02bf6d091019bb779678525bb Mon Sep 17 00:00:00 2001 From: salmonik Date: Mon, 17 Aug 2026 14:53:52 +0200 Subject: USB2/1.1 (EHCI/UHCI) drivers + real-hardware bring-up hardening - Add polled EHCI (USB2) and UHCI (USB1.1) host-controller drivers with HID boot mouse support, wired into cursor polling and the 'usb' shell cmd - Add USB Legacy ownership handoff (claim_usb_legacy) plus config_write_byte - Harden boot: verify the PIT/timer ticks before shell entry, EOI stray interrupts in the LAPIC to stop interrupt storms, bound PS/2 controller waits, and INTx-disable AHCI (polled driver) - Add boot stage markers, klog screen echo, and QR lock; scheduler mark_shell_running; NO_USB stopgap to keep BIOS USB-Legacy input alive - alloc_pages_above for DMA buffers that must avoid low conventional memory - Expand DEBUG_NOTES with EHCI/QEMU bring-up findings --- rsnix/src/tty.rs | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) (limited to 'rsnix/src/tty.rs') diff --git a/rsnix/src/tty.rs b/rsnix/src/tty.rs index 7304925..0783521 100644 --- a/rsnix/src/tty.rs +++ b/rsnix/src/tty.rs @@ -1,4 +1,8 @@ -//! Line discipline over the PS/2 keyboard — the kernel's tty layer. +//! Line discipline over the keyboard — the kernel's tty layer. +//! +//! Keys come from either the PS/2 controller (IRQ-fed scancode ring) or the +//! USB HID boot keyboard (polled UHCI driver). Both are translated to the +//! same `KeyEvent` space, so the shell is input-source agnostic. //! //! Two modes, like a real UNIX terminal: //! - **canonical** (`read_line`): input is echoed, buffered until Enter, @@ -34,6 +38,20 @@ pub enum LineInput { static mut RAW_QUEUE: [u8; 8] = [0; 8]; static mut RAW_LEN: usize = 0; +/// Combined blocking key poll: USB HID keyboard first (polled UHCI), then +/// the PS/2 path (which parks via `hlt` until an IRQ-fed scancode lands). +fn poll_key() -> KeyEvent { + if let Some(ev) = crate::uhci::try_poll_key() { + return ev; + } + ps2::poll_key() +} + +/// Combined non-blocking key poll (USB first, then PS/2). +fn try_poll_key() -> Option { + crate::uhci::try_poll_key().or_else(ps2::try_poll_key) +} + // --------------------------------------------------------------------------- // canonical mode // --------------------------------------------------------------------------- @@ -46,7 +64,7 @@ pub fn read_line() -> LineInput { crate::vt::sync_scroll(); let mut buf = strbuf::String::::new(); loop { - match ps2::poll_key() { + match poll_key() { KeyEvent::Enter => { gop::put_char('\n'); serial::write_str("\r\n"); @@ -104,7 +122,7 @@ pub fn read_line() -> LineInput { /// streaming commands (cat/hexdump) so a long dump can be interrupted. pub fn interrupt_pressed() -> bool { let mut pressed = false; - while let Some(ev) = ps2::try_poll_key() { + while let Some(ev) = try_poll_key() { if matches!(ev, KeyEvent::Ctrl('c')) { pressed = true; } @@ -126,7 +144,7 @@ pub fn read_byte() -> u8 { if let Some(b) = pop_raw() { return b; } - let ev = ps2::poll_key(); + let ev = poll_key(); enqueue_key(ev); } } @@ -136,7 +154,7 @@ pub fn try_read_byte() -> Option { if let Some(b) = pop_raw() { return Some(b); } - match ps2::try_poll_key() { + match try_poll_key() { Some(ev) => { enqueue_key(ev); pop_raw() -- cgit v1.2.3