Artemis Milestone 2e: Address Device implemented, worked first try, 3-arch
Adds Slot/Endpoint/Input Control Context structs (32-byte layout only -- HCCPARAMS1.CSZ checked live and confirmed 0 against this driver's QEMU target; 64-byte contexts refuse rather than silently mis-laying-out), xhci_cmd_address_device(), and a new dev->connect_state (idle/await-enable-slot/await-address-device) sequencing Enable Slot and Address Device per connect. Input Context (what the command TRB's parameter points at) and Device Context (what DCBAA[slot_id] points at) are separate 64-byte-aligned allocations, lazily created once and reused across every connect -- single-device driver scope, no free path needed. A new EP0 Transfer Ring uses the same fixed-ring-plus-Link-TRB pattern as the Command Ring. Two facts checked live before writing any context code, not assumed: HCCPARAMS1.CSZ (32-byte, confirmed) and PORTSC.PED at connect time (already set -- PORTSC=0x00021203, SuperSpeed -- the test device self-enables via USB3 link training, so no port-reset state machine was needed this increment; USB2 would need one, untested). Both diagnostics also added console_puts/println-based hex logging (xhci_log_hex32()) -- console_println() only takes string literals, no formatted print existed on this driver's console path before now. Verified live via QMP hotplug, all three architectures, succeeded on the first attempt with no debugging needed: "enable slot succeeded" -> "address device command submitted" -> "address device succeeded" on every boot. Also fixes a FABRIC-2.md dependency-direction error from the previous commit (Address Device is 2f's prerequisite, not the reverse). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HZ8kNoTuP63pbQtro4qvrm
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
6d330efdd8
commit
2b7743027c
+42
-7
@@ -3207,9 +3207,10 @@ Final three-arch acceptance (probe-free, `clean qemu`): all three boot to `ok>`
|
||||
**2e. Hotplug detection (the actual trigger for everything in Section U)**
|
||||
- [x] On a Port Status Change event, read the corresponding Port Register to determine
|
||||
connect vs. disconnect — **done 2026-08-22**, see writeup below
|
||||
- [x] On connect: allocate a Device Slot (Enable Slot command via the Command Ring) — **Enable
|
||||
Slot done 2026-08-22**, see writeup below; Address Device + device descriptor read still
|
||||
open (needs enumeration groundwork from 2f)
|
||||
- [x] On connect: allocate a Device Slot (Enable Slot command via the Command Ring), address
|
||||
the device (Address Device command) — **both done 2026-08-22**, see writeup below.
|
||||
Device descriptor read is 2f's job and depends on this (not the reverse — an earlier
|
||||
version of this note had the dependency backwards)
|
||||
- [ ] On disconnect: tear down the corresponding device slot and signal to whatever higher-
|
||||
level code (Section U's identity/VM logic) that the device is gone — **this is the
|
||||
first point where Section U/V's design actually gets a real trigger to hang off**
|
||||
@@ -3282,10 +3283,44 @@ disconnect/reconnect cycle repeats cleanly with no wedge. Full cycle on amd64
|
||||
(`logs/20260822-102849/amd64/`); single connect confirmed on aarch64
|
||||
(`logs/20260822-103005/aarch64/`) and riscv64 (`logs/20260822-103137/riscv64/`).
|
||||
|
||||
Still open: correlating the Command Completion Event back to its issuing command via the real
|
||||
Command TRB Pointer (not needed yet, see above), Address Device + device descriptor read
|
||||
(needs 2f's enumeration groundwork), and the callback surface into Section U's higher-level
|
||||
code.
|
||||
**Address Device, done 2026-08-22.** Sequenced after Enable Slot succeeds, via a new
|
||||
`dev->connect_state` (`XHCI_CONN_IDLE` / `_AWAIT_ENABLE_SLOT` / `_AWAIT_ADDRESS_DEVICE`) —
|
||||
Enable Slot and Address Device are issued sequentially for a given connect, never concurrently,
|
||||
so `connect_state` alone identifies which command a Command Completion Event answers; real
|
||||
Command TRB Pointer matching is still deferred until commands from different connects can
|
||||
overlap in flight.
|
||||
|
||||
Two things checked live before writing any context code, per the same "verify, don't assume"
|
||||
discipline used for the amd64 PIRQ formula in 2d: **`HCCPARAMS1.CSZ`** (32- vs 64-byte Slot/
|
||||
Endpoint/Input Context layout — confirmed `CSZ=0`, 32-byte, on this driver's target QEMU
|
||||
`qemu-xhci`; only 32-byte contexts are implemented, `xhci_cmd_address_device()` refuses rather
|
||||
than mis-laying-out a 64-byte controller) and **`PORTSC.PED`** at connect time (whether the
|
||||
port already reached Default state, or needs a software-driven `PORTSC.PR` reset first —
|
||||
confirmed `PED` already set, `PORTSC=0x00021203`, SuperSpeed, on this test device: the USB3
|
||||
link trains and enables itself, so no port-reset state machine was needed for this increment;
|
||||
a USB2 device may still need one, untested here).
|
||||
|
||||
Layout: **Input Context** (Input Control Context + Slot Context + EP0 Context, 96 bytes) is
|
||||
what the command TRB's `parameter` points at; **Device Context** (Slot Context + EP0 Context,
|
||||
64 bytes, no Input Control Context) is what `DCBAA[slot_id]` points at — two separate
|
||||
allocations, conflating them is the standard mistake here. Both, plus a new EP0 Transfer Ring
|
||||
(same fixed-ring-plus-Link-TRB pattern as the Command Ring), are lazily allocated once and
|
||||
reused across every connect — single-device scope, no free path exists or is needed. Slot
|
||||
Context: Route String 0 (directly on root hub), Speed from the live `PORTSC.Port Speed` read
|
||||
at connect time, Context Entries=1, Root Hub Port Number=the connecting port. EP0 Context:
|
||||
Control Bidirectional, CErr=3, Max Packet Size defaulted by speed (SuperSpeed 512/High 64/
|
||||
Full 64/Low 8 — spec's own recommended pre-descriptor-read defaults, corrected once 2f reads
|
||||
the real `bMaxPacketSize0`), Average TRB Length=8.
|
||||
|
||||
Verified live via QMP hotplug, all three architectures, first attempt: `enable slot
|
||||
succeeded` -> `address device command submitted` -> `address device succeeded` on every boot,
|
||||
no debugging needed. `logs/20260822-113852/amd64/`, `logs/20260822-114043/aarch64/`,
|
||||
`logs/20260822-114214/riscv64/`.
|
||||
|
||||
Still open: correlating Command Completion Events via the real Command TRB Pointer (not needed
|
||||
yet, see above), device descriptor read (2f), USB2 port-reset handling (untested — this
|
||||
increment's test device was SuperSpeed and self-enabled), disconnect teardown (Disable Slot
|
||||
command, DCBAA entry clear), and the callback surface into Section U's higher-level code.
|
||||
|
||||
**2f. USB device enumeration (post-connect, before it's usable as storage)**
|
||||
- [ ] Request and parse the device descriptor (confirm vendor/product IDs are even needed,
|
||||
|
||||
Reference in New Issue
Block a user