Artemis Milestone 2g: Configure Endpoint command

Adds the xHCI Configure Endpoint command for the two bulk endpoints
identified by the previous increment, and fixes control-transfer
sequencing to match the spec: xHCI 1.2 section 4.3.5 requires Configure
Endpoint before SET_CONFIGURATION is sent to the device, the reverse of
the order this driver used through 2f (which happened to work against
QEMU's lenient qemu-xhci emulation but wasn't spec-correct).

New XHCI_TRB_TYPE_CONFIGURE_ENDPOINT_CMD, EP Context type constants for
Bulk IN/OUT, and an XHCI_EP_ADDR_TO_DCI() macro (DCI = 2*EndpointNumber
+ Direction) in xhci.h. xhci_cmd_configure_endpoint() builds the Input
Context (Slot + one EP Context per DCI up to the highest bulk endpoint
in use) and submits the command via the existing next_action deferral
mechanism, correlated on completion via a new
XHCI_CONN_AWAIT_CONFIGURE_ENDPOINT connect_state, then chains into the
existing SET_CONFIGURATION path.

Two allocations had to grow beyond what Address Device sized them for:
the Input Context (previously room for one EP Context only) and, less
obviously, the Device Context that DCBAA[slot_id] itself points at --
the controller only touches DCIs named in a command's own Add/Drop
flags, so growing that buffer required copying its existing Slot+EP0
content forward rather than zeroing it, to avoid handing the controller
a blank EP0 out from under an endpoint this command isn't touching.
Bulk Transfer Rings (bulk_in_ring/bulk_out_ring) are allocated and
wired into the new EP Contexts but not yet exercised by an actual
transfer -- CBW/CSW submission is next.

Verified live via QMP hotplug, all three architectures, byte-identical:
bulk endpoint identification -> configure endpoint command submitted ->
configure endpoint succeeded -> the existing set configuration ->
device configured chain, then a clean disconnect/disable-slot teardown
afterward with the larger Device Context installed.

FABRIC-2.md Section X Milestone 2g's endpoint identify+configure
checklist item marked fully done.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R4VMX6VSKCten8nGgaMkq4
This commit is contained in:
Robert Allan James
2026-08-25 08:40:35 -04:00
co-authored by Claude Sonnet 5
parent 96d55fcd87
commit 92ce1f85dd
12 changed files with 27511 additions and 17 deletions
+50 -8
View File
@@ -3451,11 +3451,8 @@ arch afterward, no wedge. `logs/20260825-073235/amd64/`, `logs/20260825-073417/a
`logs/20260825-073728/riscv64/`.
**2g. Bulk-Only Transport (BOT) — the actual read/write path**
- [~] Identify the device's bulk IN and bulk OUT endpoints — **identification done
2026-08-25**, see writeup below; *configuring* them (a Configure Endpoint command,
wiring their EP Contexts/DCIs so the controller will actually run transfers on them)
is still open — this increment only reads the addresses out of the descriptor, it
doesn't yet act on them
- [x] Identify and configure the device's bulk IN and bulk OUT endpoints — **identification
done 2026-08-25, configuration done 2026-08-25**, see writeups below
- [ ] Implement CBW (Command Block Wrapper) construction and send, for a SCSI READ(10)
- [ ] Implement CSW (Command Status Wrapper) receive and status check
- [ ] Get one real SCSI READ(10) working end to end — first proof the whole stack works,
@@ -3489,9 +3486,54 @@ individually-tracked instance — see the disconnect-teardown writeup above for
matters), all three architectures, byte-identical results everywhere: `bulk IN
endpoint=0x81`, `bulk OUT endpoint=0x02`, immediately followed by the existing `set
configuration submitted` → `device configured` chain, unaffected. `logs/20260825-081058/amd64/`,
`logs/20260825-081300/aarch64/`, `logs/20260825-081517/riscv64/`. *Configuring* these
endpoints (a Configure Endpoint command, EP Context setup) is the next open item in this
milestone — this increment only identifies them.
`logs/20260825-081300/aarch64/`, `logs/20260825-081517/riscv64/`.
**Configure Endpoint command, done 2026-08-25.** Per xHCI 1.2 spec section 4.3.5, a Configure
Endpoint command must be issued once enumeration has identified the endpoints a device's
configuration actually uses, and *before* the USB SET_CONFIGURATION request is sent to the
device — the reverse of the order this driver used through 2f (SET_CONFIGURATION issued with
no endpoints ever configured). That earlier order happened to work against QEMU's lenient
`qemu-xhci` emulation, but wasn't spec-correct; this increment fixes the sequencing as part of
adding the command, chaining Configure Endpoint in between the bulk-endpoint-identification
step and SET_CONFIGURATION via the same `next_action` deferral mechanism as every other
control transfer/command in this driver (a new `XHCI_NEXT_ACTION_CONFIGURE_ENDPOINT` value,
and a new `XHCI_CONN_AWAIT_CONFIGURE_ENDPOINT` connect-state to correlate the command's own
Command Completion Event, same pattern as Enable Slot/Address Device/Disable Slot above).
Two things had to grow beyond what Address Device allocated, both realised only while writing
this: the **Input Context** (Address Device's 96-byte allocation only ever held one EP
Context; Configure Endpoint needs one EP Context per Device Context Index up to the highest
DCI now in use — DCI = `2*EndpointNumber + Direction`, `XHCI_EP_ADDR_TO_DCI()`, new in
`xhci.h` — so it's reallocated at a size covering the Slot Context plus every DCI from 1
through the bulk endpoints' own, unused intermediate DCIs left zeroed since their Add flags
are 0), and the **Device Context** that `DCBAA[slot_id]` itself points at (same reasoning,
but with a sharper constraint: xHCI 1.2 spec section 4.6.6 has the controller touch only the
DCIs actually named in a command's Add/Drop flags, so the *existing* Slot+EP0 content has to
be copied into the newly, larger buffer rather than left zeroed — a freshly zeroed Device
Context would hand the controller a blank EP0 out from under an endpoint this command isn't
touching, corrupting live control-transfer state). The Slot Context written into the Input
Context is itself copied from the live Device Context (Route String/Speed/Root Hub
Port/Interrupter Target aren't retained anywhere else by this point in enumeration —
`pending_connect_port_id` is cleared as soon as Address Device completes), with only Context
Entries changed to the new highest DCI.
Max Burst Size is left at 0 (single-burst) in both bulk EP Contexts — SuperSpeed Endpoint
Companion descriptor parsing isn't implemented, so this driver doesn't yet know a real
device's burst capability; matches every device tested against so far under QEMU's emulation,
flagged as a revisit point if a real high-throughput SS device needs it. Average TRB Length is
a placeholder (1024, a scheduling hint per spec, not a correctness constraint) until real
CBW/data/CSW transfer sizes are known — 2g's next items.
Verified live via QMP hotplug, all three architectures, byte-identical results: `xhci: bulk IN
endpoint=0x81` / `bulk OUT endpoint=0x02` → `configure endpoint command submitted` →
`configure endpoint succeeded` → the existing `set configuration submitted` → `device
configured` chain, unaffected. Disconnect confirmed clean afterward on every arch, no wedge —
`disable slot succeeded` still fires normally with the larger Device Context now installed.
`logs/20260825-083142/amd64/`, `logs/20260825-083425/aarch64/`, `logs/20260825-083744/riscv64/`.
Bulk Transfer Rings (`bulk_in_ring`/`bulk_out_ring`, same fixed-ring-plus-Link-TRB pattern as
every other ring in this driver) are allocated and wired into the EP Contexts by this
increment but not yet used for an actual transfer — CBW/CSW submission (2g's next items) is
what exercises them for the first time.
**2h. Integration with the existing block subsystem**
- [ ] Wire a working USB MSC device into `blk_subsys_attach_device()` (or