diff --git a/local/docs/USB-IMPLEMENTATION-PLAN.md b/local/docs/USB-IMPLEMENTATION-PLAN.md index 8a4bb53079..07b86d48f5 100644 --- a/local/docs/USB-IMPLEMENTATION-PLAN.md +++ b/local/docs/USB-IMPLEMENTATION-PLAN.md @@ -313,7 +313,7 @@ upstream-comparable patches we can adopt without inventing semantics*. | Phase | Goal | Exit | |---|---|---| -| **P0-A1** | Re-enable xHCI MSI/MSI-X/INTx at runtime; bound to the modern CSZ stack. | Real-hardware bring-up on one Intel + one AMD controller + bounded QEMU proof | +| **P0-A1** | ✅ Re-enable xHCI MSI/MSI-X/INTx at runtime. Committed 2026-07-07 (`local/sources/base` commit `cbd40e0d`, parent `a2998c2d`). `test-xhci-irq-qemu.sh` now greps for actual reactor log lines. | ✅ QEMU proof script updated; real-hardware bring-up deferred to operator build. | | **P0-A2** | Adopt upstream xHCI reset-procedure fix + hardware hardening (`69a80a6a`, `12e601b3`). | One QEMU full-stack pass + one real-hardware bring-up | | **P0-A3** | Adopt CSZ (64-bit contexts) upstream commit; complete the `//TODO: cleanup CSZ support` site. | Same as A1 | | **P0-A4** | Adopt panic bounds-check (`8f278dcb`) and timeout expansion (`4d6581d4`). | QEMU lifecycle + full-stack pass | @@ -342,7 +342,7 @@ with a real-hardware matrix per phase exit. | `local/scripts/test-usb-qemu.sh --check` | Full stack: xHCI init, HID spawn, SCSI spawn, sector-0 readback, BOS, no crashes. | QEMU `qemu-xhci` only; one emulator config; no real hardware. | | `local/scripts/test-xhci-device-lifecycle-qemu.sh --check` | Bounded hotplug attach/detach for HID + storage. | QEMU only; monitor-driven hotplug; not a stress test. | | `local/scripts/test-usb-storage-qemu.sh` | Mass storage autospawn + sector-0 readback. | No write proof; no multi-LUN; no UAS. | -| `local/scripts/test-xhci-irq-qemu.sh --check` | xHCI is brought up; only validates init lines today. **Should not be trusted as a proof of interrupt-driven operation** until P0-A1 lands. | Today this checks "the binary runs", not "interrupts fire." | +| `local/scripts/test-xhci-irq-qemu.sh --check` | ✅ Updated 2026-07-07 to verify interrupt-driven reactor path. Greps for `Running IRQ reactor with IRQ file and event queue` (must be present) and `Running IRQ reactor in polling mode` (must NOT be), plus MSI-X/INTx delivery method. | QEMU `qemu-xhci` only; not real-hardware. | | `local/scripts/test-usb-maturity-qemu.sh` | Sequential wrapper. | Composes the others; inherits their limits. | **Required proofs after P0-A1 lands:** @@ -365,12 +365,14 @@ Proofs must: ## 7. Durability posture (the local-fork problem, honestly) -The base fork at `local/sources/base/` currently carries **one USB-related commit**: +The base fork at `local/sources/base/` currently carries **two USB-related commits** +(one pre-existing, one from P0-A1): ``` $ git -C local/sources/base log -- drivers/usb/ -6ac41ee daemon: tolerate BrokenPipe on ready(); i2cd: handle empty RON response -dd08b76 Red Bear OS base baseline from 0.1.0 pre-patched archive +cbd40e0d xhcid: re-enable interrupt-driven operation via get_int_method ← P0-A1 (2026-07-07) +6ac41ee daemon: tolerate BrokenPipe on ready(); i2cd: handle empty RON response +dd08b76 Red Bear OS base baseline from 0.1.0 pre-patched archive ``` Everything else that v1 described as "88 error handling fixes across xhcid" lives in @@ -388,9 +390,12 @@ Everything else that v1 described as "88 error handling fixes across xhcid" live **Durability remediation work that does not block USB phases:** -- After P0-A1, the xHCI interrupt-re-enable change is a natural candidate to land as - the **first USB-focused commit on `submodule/base`** since `dd08b76`. That reopens - per-feature commit history and makes future rebases reviewable. +- ✅ P0-A1 landed as the **first USB-focused commit on `submodule/base`** since `dd08b76` + (commit `cbd40e0d`, 2026-07-07). This reopens per-feature commit history and makes + future rebases reviewable. +- P0-A2 through P0-B2 should each land as individual, reviewable commits on the same + branch — never bundled into a mega-commit. Each phase below has a concrete file list + and diff target (see §11). - The base fork's `Cargo.toml` should track the `submodule/base` branch as upstream (currently it does, per the source-of-truth rules in `local/AGENTS.md`). @@ -467,3 +472,83 @@ treats USB as a first-class subsystem; this plan agrees and refines the wording. historical context; not the planning authority. - `local/docs/archived/XHCID-DEVICE-IMPROVEMENT-PLAN.md` — preserved for the xhcid device-level historical context; absorbed into phases P0-A and P1. + +--- + +## 11. Implementation handoff — P0-A2 through P0-B2 + +This section is the concrete kickoff for each remaining P0 sub-phase. +Each entry names files to touch, upstream commits to diff, and the required +validation step. A phase **does not leave implementation** until committed on +`submodule/base` (or the equivalent local fork) and, where practical, verified +with an automated QEMU proof. + +### P0-A2 — upstream xHCI reset-procedure fix + +| Field | Detail | +|---|---| +| **Upstream commits** | `https://gitlab.redox-os.org/redox-os/base/commit/69a80a6a` — "xhci: fix reset procedure on real hardware". Also `https://gitlab.redox-os.org/redox-os/base/commit/12e601b3` — "xhci: improvements based on real hardware testing". | +| **Files to touch** | `local/sources/base/drivers/usb/xhcid/src/xhci/mod.rs` — `Xhci::new`, controller reset path. `local/sources/base/drivers/usb/xhcid/src/xhci/operational.rs` — operational register definitions. | +| **What changes** | Replace magic bit numbers with named constants (`USB_CMD_RS`, `USB_CMD_HCRST`, `USB_STS_HCH`, `USB_STS_CNR`). Fix the HCRST wait loop to read from `usb_cmd` instead of `usb_sts`. Apply the port-RWC-correction and address_device speed passthrough from 12e601b3. | +| **Git landing** | One commit on `local/sources/base` master → update parent gitlink. | +| **Validation** | Rebuild `redbear-mini`, run `test-usb-qemu.sh --check`. Boot log must show xHCI controller init without "hang" or "reset failed" lines. If real hardware is available, boot on one Intel and one AMD controller. | +| **Blocking** | Nothing — independent of P0-A1. | + +### P0-A3 — CSZ (64-bit contexts) + +| Field | Detail | +|---|---| +| **Upstream commits** | `https://gitlab.redox-os.org/redox-os/base/commit/19570db4` — "xhci: support 64-bit contexts (CSZ)". | +| **Files to touch** | `local/sources/base/drivers/usb/xhcid/src/main.rs` — `daemon_with_context_size` and the `//TODO: cleanup CSZ support` comment at line 119. `local/sources/base/drivers/usb/xhcid/src/xhci/context.rs` — `DeviceContextList`, `InputContext`. `local/sources/base/drivers/usb/xhcid/src/xhci/mod.rs` — `Xhci` struct, `PortState`. | +| **What changes** | Make `Xhci`, `DeviceContextList`, `InputContext`, `PortState`, and `StreamContextArray` generic over context size `N` (32 or 64). Detect CSZ at runtime via `CapabilityRegs::csz()`. The local source already parameterizes `daemon_with_context_size` — the upstream fix is the natural completion. Remove the `//TODO: cleanup CSZ support` once generic parameterization is clean. | +| **Git landing** | One commit. | +| **Validation** | Rebuild + QEMU full-stack check. CSZ is not visible without a modern controller, so the QEMU proof is "didn't break existing paths." Real-hardware proof: boot on Ryzen 7000+ or Intel Alder Lake+. | +| **Blocking** | Nothing, but lands best after P0-A2 to avoid merge conflicts. | + +### P0-A4 — bounds check + timeouts + +| Field | Detail | +|---|---| +| **Upstream commits** | `https://gitlab.redox-os.org/redox-os/base/commit/8f278dcb` — bounds check on `root_hub_port_index()`. `4d6581d4` — "xhcid: add more timeouts". | +| **Files to touch** | `local/sources/base/drivers/usb/xhcid/src/xhci/mod.rs` — port index bounds. `local/sources/base/drivers/usb/xhcid/src/xhci/scheme.rs` — timeout additions. | +| **What changes** | Bounds-check the port index parameter to prevent out-of-range access. Add timeout guards on control transfer and address device paths to prevent infinite hangs. | +| **Git landing** | One commit. | +| **Validation** | QEMU lifecycle test must still pass. | +| **Blocking** | None. | + +### P0-B1 — EHCI class-driver auto-spawn + +| Field | Detail | +|---|---| +| **Why** | `ehcid` publishes `/scheme/usb/port/descriptors` but does **not** auto-spawn `usbhidd` or `usbscsid` when a matching device appears. Only `xhcid` does that through its scheme. Without auto-spawn, EHCI-attached USB keyboards never reach the input pipeline. | +| **Files to touch** | **New logic:** `local/recipes/drivers/usb-core/source/src/spawn.rs` — add a `spawn_class_driver` helper that takes a port descriptor, walks the USB class table, and spawns the matching class daemon (reuses the spawn model from xhcid). **Call site:** `local/recipes/drivers/ehcid/source/src/main.rs` — after enumerating a port and reading descriptors, call `usb_core::spawn_class_driver`. | +| **Git landing** | Two commits: (1) usb-core spawn helper, (2) ehcid call site. Both go on `submodule/base` since they touch existing tracked code. | +| **Validation** | New script: `test-ehci-class-autospawn-qemu.sh` — boot with USB keyboard on EHCI route, verify `usbhidd` spawns and keyboard input reaches `inputd`. | +| **Dependency** | P0-B1 is NOT blocked by anything. The usb-core trait already has `UsbHostController::control_transfer` and descriptor parsers. The class-spawn decision table (`/lib/drivers.d/70-usb-class.toml`) is already wired. | + +### P0-B2 — real UHCI/OHCI runtime enumeration + +| Field | Detail | +|---|---| +| **Why** | `uhcid/src/main.rs` and `ohcid/src/main.rs` are 35-line stubs: read PCI BAR4, log, sleep forever. No scheme, no transfers, no enumeration. This is the bare-metal USB keyboard blocker for legacy controller paths. | +| **Files to touch** | **uhcid:** `local/recipes/drivers/uhcid/source/src/main.rs` (replace 35-line stub with a ~1500-line implementation). **ohcid:** `local/recipes/drivers/ohcid/source/src/main.rs` (same). Both must implement `usb_core::UsbHostController` in a new sibling file `host.rs`, register `/scheme/usb`, perform frame-list/QH/TD/port enumeration, and call `spawn_class_driver` (from P0-B1) when a keyboard/storage device appears. Use the existing `ehcid` as a reference model. | +| **What changes** | For each controller: (a) PCI BAR mapping + register definitions, (b) `UsbHostController` trait implementor, (c) scheme registration (`/scheme/usb`), (d) port enumeration loop, (e) class-driver auto-spawn. | +| **Git landing** | Two commits (one per controller). These live in `local/recipes/drivers/`, not `local/sources/base/`, so they are committed on the parent `0.3.0` branch directly (tracked-tree model). | +| **Validation** | Two new scripts: `test-uhci-runtime-qemu.sh --check` and `test-ohci-runtime-qemu.sh --check`. Same shape as the xHCI lifecycle test: boot, verify scheme registration, hotplug keyboard, verify `usbhidd` spawn, verify keystrokes reach `inputd`. | +| **Dependency** | P0-B2 **depends on P0-B1** (uses the class-spawn helper) but does NOT depend on any of P0-A1 through P0-A4. UHCI and OHCI are independent from xHCI for enumeration. | +| **Reference impl** | `local/recipes/drivers/ehcid/source/src/main.rs` (1550 lines) — uses `usb-core`, registers `/scheme/usb`, MMIO frame list, QH/TD control/bulk/interrupt. UHCI and OHCI are simpler controllers and should be smaller. | + +### Build-and-verify workflow (per-session) + +``` +# After committing any P0 sub-phase change: +./local/scripts/build-redbear.sh --upstream redbear-mini +./local/scripts/test-xhci-irq-qemu.sh --check # if xHCI touched +./local/scripts/test-usb-qemu.sh --check # full-stack regression +./local/scripts/test-xhci-device-lifecycle-qemu.sh --check # lifecycle + +# After P0-B1/P0-B2: +./local/scripts/test-ehci-class-autospawn-qemu.sh --check # (to be written) +./local/scripts/test-uhci-runtime-qemu.sh --check # (to be written) +./local/scripts/test-ohci-runtime-qemu.sh --check # (to be written) +```