diff options
| author | salmonik <salmonik@tuta.io> | 2026-11-01 17:09:59 +0100 |
|---|---|---|
| committer | salmonik <salmonik@tuta.io> | 2026-11-01 17:09:59 +0100 |
| commit | d99906b48698c1bd722a1fa5f2270b76317ec661 (patch) | |
| tree | 780a2b7bcf09733b7f6fedde9cf802c6b6e3abfb /rsnix/src/usb.rs | |
| parent | ehci: diagnostics + hardening for the port-not-enabled case (diff) | |
| download | rs-dos-d99906b48698c1bd722a1fa5f2270b76317ec661.tar.gz rs-dos-d99906b48698c1bd722a1fa5f2270b76317ec661.zip | |
ehci: bound all init waits; stop auto-rescanning; wider boot watchdogqemu
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
Diffstat (limited to '')
| -rw-r--r-- | rsnix/src/usb.rs | 20 |
1 files changed, 19 insertions, 1 deletions
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 { | |||
| 699 | } | 699 | } |
| 700 | NXDEV.fetch_add(1, Ordering::Relaxed); | 700 | NXDEV.fetch_add(1, Ordering::Relaxed); |
| 701 | queue_report(idx); | 701 | queue_report(idx); |
| 702 | show_summary(); | ||
| 702 | crate::serial_println!( | 703 | crate::serial_println!( |
| 703 | "usb: HID {} armed (slot {} mps {} interval {})", | 704 | "usb: HID {} armed (slot {} mps {} interval {})", |
| 704 | if kind == Kind::Mouse { "mouse" } else { "keyboard" }, | 705 | if kind == Kind::Mouse { "mouse" } else { "keyboard" }, |
| @@ -968,10 +969,12 @@ pub fn init() -> bool { | |||
| 968 | } | 969 | } |
| 969 | } | 970 | } |
| 970 | INITOK.store(true, Ordering::Relaxed); | 971 | INITOK.store(true, Ordering::Relaxed); |
| 972 | let ports = unsafe { MAXPORTS }; | ||
| 971 | crate::serial_println!( | 973 | crate::serial_println!( |
| 972 | "usb: controller up ({} ports) — HID discovery deferred to polling", | 974 | "usb: controller up ({} ports) — HID discovery deferred to polling", |
| 973 | unsafe { MAXPORTS } | 975 | ports |
| 974 | ); | 976 | ); |
| 977 | show_summary(); | ||
| 975 | true | 978 | true |
| 976 | } | 979 | } |
| 977 | 980 | ||
| @@ -1008,6 +1011,21 @@ fn maybe_discover() { | |||
| 1008 | } | 1011 | } |
| 1009 | } | 1012 | } |
| 1010 | 1013 | ||
| 1014 | /// Persistent bottom-row summary for hardware runs without serial. | ||
| 1015 | fn show_summary() { | ||
| 1016 | let (np, nd) = unsafe { (MAXPORTS, NXDEV.load(Ordering::Relaxed)) }; | ||
| 1017 | let mut line = alloc::format!("xhci ports={} devs={}:", np, nd); | ||
| 1018 | unsafe { | ||
| 1019 | for p in 0..np.min(8) { | ||
| 1020 | let v = rd(op(OP_PORTSC) + (p as usize) * PORT_STRIDE); | ||
| 1021 | if v & PORT_CONNECT != 0 { | ||
| 1022 | line.push_str(&alloc::format!(" p{}={:04x}", p, v & 0xffff)); | ||
| 1023 | } | ||
| 1024 | } | ||
| 1025 | } | ||
| 1026 | crate::gop::boot_marker_at(&line, crate::gop::bottom_row(3)); | ||
| 1027 | } | ||
| 1028 | |||
| 1011 | fn has_kind(kind: Kind) -> bool { | 1029 | fn has_kind(kind: Kind) -> bool { |
| 1012 | let n = NXDEV.load(Ordering::Relaxed) as usize; | 1030 | let n = NXDEV.load(Ordering::Relaxed) as usize; |
| 1013 | for i in 0..n { | 1031 | for i in 0..n { |
