Artemis Milestone 2g: Data-In stage read and CSW receive/validation
Completes the CBW -> Data-In -> CSW chain for READ(10) started last commit. xhci_bot_read_data_in() and xhci_bot_receive_csw(), each a single Normal TRB on the bulk IN Transfer Ring via a new xhci_bulk_in_enqueue_and_ring() helper (mirrors the OUT-side helper from CBW send). All three stages now chain automatically via the existing deferred next_action pattern: CBW completion defers into Data-In, Data-In completion defers into CSW receive, CSW completion is where signature/tag/status validation happens. Data-In reads into a new fixed 512-byte bot_data_buf -- single-block scope for this increment, matches QEMU's usb-storage reported block size; xhci_bot_send_read10() now refuses rather than overflow/truncate if a request exceeds it. CSW validation (BOT spec section 5.2) checks dCSWSignature and dCSWTag (a new bot_last_tag field, latched from the CBW) before trusting bCSWStatus at all, so a garbled/misaligned CSW read can't be misread as a clean pass. usb_bot_csw_t follows the same struct-with-explicit-length-not-sizeof discipline as usb_bot_cbw_t. Verified live via a temporary probe (written, run once, log captured, reverted per this project's own probe convention), all three architectures, byte-identical: the full CBW -> Data-In -> CSW exchange completes cleanly, well-formed CSW with correct signature and echoed tag, no wedge, clean disconnect immediately after. The SCSI command itself reports CSW status FAILED against the current test fixture -- expected at this stage (no TEST UNIT READY / UNIT ATTENTION handling implemented yet, consistent with a fresh-attach unit-attention condition, not a transport-layer defect) and not root-caused further here; the BOT mechanism itself is confirmed correct end to end. Probe-free re-verification afterward on all three architectures. FABRIC-2.md Section X Milestone 2g's CSW checklist item marked done; "get one real READ(10) working end to end" stays explicitly open, distinguishing "the mechanism works" from "the SCSI command succeeds." Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R4VMX6VSKCten8nGgaMkq4
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
a88c004ecb
commit
c54ea24aaf
+54
-2
@@ -3455,9 +3455,16 @@ arch afterward, no wedge. `logs/20260825-073235/amd64/`, `logs/20260825-073417/a
|
||||
done 2026-08-25, configuration done 2026-08-25**, see writeups below
|
||||
- [x] Implement CBW (Command Block Wrapper) construction and send, for a SCSI READ(10) —
|
||||
**done 2026-08-25**, see writeup below
|
||||
- [ ] Implement CSW (Command Status Wrapper) receive and status check
|
||||
- [x] Implement CSW (Command Status Wrapper) receive and status check — **done 2026-08-25**,
|
||||
see writeup below. Also reads the Data-In stage, not just CSW (the checklist's own
|
||||
split between this item and "identify/configure endpoints" above didn't leave a
|
||||
separate line for it, but it's new work, not folded silently into either neighbor —
|
||||
see writeup)
|
||||
- [ ] Get one real SCSI READ(10) working end to end — first proof the whole stack works,
|
||||
before write
|
||||
before write. **Partially exercised, not satisfied**: the CBW→Data-In→CSW mechanism
|
||||
itself is confirmed working (see writeup below), but the SCSI command itself returns
|
||||
CSW status FAILED against the current test fixture -- this item stays open until a
|
||||
READ(10) actually returns PASS with real data, not just a well-formed CSW
|
||||
- [ ] Implement CBW/data/CSW for SCSI WRITE(10) — this is where the earlier "read/write,
|
||||
unquestionable" requirement actually gets satisfied
|
||||
- [ ] Implement basic error/stall recovery (CSW failure status, endpoint stall clear) — at
|
||||
@@ -3598,6 +3605,51 @@ directly on the command line) before trusting the result. `ls -t` on this log tr
|
||||
known-unreliable pattern for "find the log for the process I just launched" — the PID's own
|
||||
command line is the ground truth, not directory mtime ordering.
|
||||
|
||||
**Data-In stage read and CSW receive/validation, done 2026-08-25.** Completes the CBW→Data-In→
|
||||
CSW chain for READ(10): `xhci_bot_read_data_in()` and `xhci_bot_receive_csw()`, each a single
|
||||
Normal TRB on the bulk IN Transfer Ring via a new `xhci_bulk_in_enqueue_and_ring()` helper
|
||||
(mirrors `xhci_bulk_out_enqueue_and_ring()` from the CBW-send increment, targeting
|
||||
`bulk_in_ring`/`bulk_in_ep_addr` instead). All three stages now chain automatically, same
|
||||
deferred `next_action` pattern as every earlier control-transfer/command sequence in this
|
||||
driver: CBW send completion (`XHCI_XFER_CBW_SENT`) defers into the Data-In read, whose own
|
||||
completion (`XHCI_XFER_BOT_DATA_IN`) defers into the CSW receive, whose completion
|
||||
(`XHCI_XFER_CSW_RECEIVED`) is where signature/tag/status validation actually happens.
|
||||
|
||||
Data-In reads into a new fixed 512-byte `bot_data_buf` -- this increment's whole scope is a
|
||||
single 512-byte block (matches the block size QEMU's `usb-storage` reports), not a real
|
||||
variable-size/multi-block transfer; that's 2h's problem once the block subsystem calls this
|
||||
path with real sizes. `xhci_bot_send_read10()` now refuses (`-1`) if the requested
|
||||
`num_blocks*block_size` exceeds this buffer, rather than silently truncating or overflowing.
|
||||
|
||||
CSW validation (USB Mass Storage Class BOT spec section 5.2) checks, in order: `dCSWSignature`
|
||||
against `USB_BOT_CSW_SIGNATURE` ("USBS"), then `dCSWTag` against a new `bot_last_tag` field
|
||||
(latched from the CBW that started this transaction) -- both checked *before* trusting
|
||||
`bCSWStatus` at all, since a garbled or misaligned CSW read could otherwise be misread as a
|
||||
clean pass. `usb_bot_csw_t` follows the same discipline as `usb_bot_cbw_t`: a real struct
|
||||
(every field naturally aligned, little-endian throughout), but its DMA length is the explicit
|
||||
`USB_BOT_CSW_LENGTH` (13) constant, never `sizeof()`, since the compiler may pad the struct to
|
||||
16 bytes.
|
||||
|
||||
Verified live via a temporary probe (written, run once, log captured, then reverted per this
|
||||
project's own probe convention), all three architectures, byte-identical: `CBW (READ10)
|
||||
submitted` → `CBW send completed` → `BOT Data-In read submitted` → `BOT Data-In read completed`
|
||||
→ `CSW receive submitted` → `CSW status = FAILED`, `CSW data residue=0x00000200`. The BOT
|
||||
transport mechanism itself is confirmed correct end to end -- CBW sent, Data-In stage run, a
|
||||
well-formed CSW received with the right signature and the right tag echoed back, no wedge, and
|
||||
a clean disconnect afterward even immediately following the exchange. The SCSI command itself
|
||||
failing is a separate, expected-at-this-stage condition: no SCSI unit-initialization sequence
|
||||
(TEST UNIT READY / clearing a UNIT ATTENTION condition, standard behavior for the first command
|
||||
issued to a freshly attached SCSI target) is implemented yet, and this probe issues a bare
|
||||
READ(10) with no retry -- consistent with a UNIT ATTENTION rather than a driver defect, though
|
||||
not root-caused further this increment (that root-causing, plus whatever else it takes to get
|
||||
an actual PASS, is squarely the still-open "get one real READ(10) working end to end" item
|
||||
above). `logs/20260825-091727/amd64/`, `logs/20260825-092121/aarch64/`,
|
||||
`logs/20260825-092401/riscv64/`. The probe (`XHCI_NEXT_ACTION_BOT_TEST_READ` and its trigger in
|
||||
the SET_CONFIGURATION completion handler) was removed after capture; only
|
||||
`xhci_bot_read_data_in()`/`xhci_bot_receive_csw()` and their Transfer Event handling remain.
|
||||
Re-verified probe-free afterward, all three architectures, clean boots with no BOT activity:
|
||||
`logs/20260825-092701/amd64/`, `logs/20260825-092842/aarch64/`, `logs/20260825-093048/riscv64/`.
|
||||
|
||||
**2h. Integration with the existing block subsystem**
|
||||
- [ ] Wire a working USB MSC device into `blk_subsys_attach_device()` (or
|
||||
`blk_subsys_add_raw_device()`, whichever fits — confirm which, since USB is
|
||||
|
||||
Reference in New Issue
Block a user