From d99906b48698c1bd722a1fa5f2270b76317ec661 Mon Sep 17 00:00:00 2001 From: salmonik Date: Sun, 1 Nov 2026 17:09:59 +0100 Subject: ehci: bound all init waits; stop auto-rescanning; wider boot watchdog Hardware run 3 showed the same PED=0 SETUP halt and then never reached the prompt. Two boot-time hazards explain the death: - reset_port polled PED with a 2,000,000-iteration MMIO loop (seconds on real silicon) and the reset retry ran it twice per port, so the port scan alone exceeded the boot watchdog window (task 0 in one frame for 7.5 s panics). - while no HID was found the cursor task re-ran the whole EHCI scan, port resets included, every second -- a rate-matching hub never settles. Changes: - every EHCI wait is wall-clock bounded: halt/reset/run 500 ms, PED 200 ms - control-transfer timeout 5 s -> 500 ms - per-controller 3 s port-scan budget; no automatic re-scan (explicit `usb rescan` only) - 300 ms power-up settle before the reset walk (RMH bring-up) - boot-phase watchdog 750 -> 2000 ticks (20 s), room for hub bring-up - xHCI gets the same persistent bottom-row port/device summary --- rsnix/src/usb.rs | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'rsnix/src/usb.rs') diff --git a/rsnix/src/usb.rs b/rsnix/src/usb.rs index 5a4136f..aa41b0e 100644 --- a/rsnix/src/usb.rs +++ b/rsnix/src/usb.rs @@ -699,6 +699,7 @@ fn enumerate(port: u32, speed: u32) -> bool { } NXDEV.fetch_add(1, Ordering::Relaxed); queue_report(idx); + show_summary(); crate::serial_println!( "usb: HID {} armed (slot {} mps {} interval {})", if kind == Kind::Mouse { "mouse" } else { "keyboard" }, @@ -968,10 +969,12 @@ pub fn init() -> bool { } } INITOK.store(true, Ordering::Relaxed); + let ports = unsafe { MAXPORTS }; crate::serial_println!( "usb: controller up ({} ports) — HID discovery deferred to polling", - unsafe { MAXPORTS } + ports ); + show_summary(); true } @@ -1008,6 +1011,21 @@ fn maybe_discover() { } } +/// Persistent bottom-row summary for hardware runs without serial. +fn show_summary() { + let (np, nd) = unsafe { (MAXPORTS, NXDEV.load(Ordering::Relaxed)) }; + let mut line = alloc::format!("xhci ports={} devs={}:", np, nd); + unsafe { + for p in 0..np.min(8) { + let v = rd(op(OP_PORTSC) + (p as usize) * PORT_STRIDE); + if v & PORT_CONNECT != 0 { + line.push_str(&alloc::format!(" p{}={:04x}", p, v & 0xffff)); + } + } + } + crate::gop::boot_marker_at(&line, crate::gop::bottom_row(3)); +} + fn has_kind(kind: Kind) -> bool { let n = NXDEV.load(Ordering::Relaxed) as usize; for i in 0..n { -- cgit v1.2.3