FABRIC-3.md: scope WRITE(10), the graph's highest-leverage node

First pass of the iterative Q&A planning loop over §E's dependency graph:
traced the existing READ(10) implementation in xhci.c to establish that
WRITE(10) is a direct mirror (data direction, new SCSI opcode, new BOT
state) rather than new protocol work, then recorded the three scoping
decisions made (read_only flip timing, QEMU disposable-image validation
target, scope boundary excluding MINT/DETACH) in new §F.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U14ET9CWAtbQMbYqomKgXd
This commit is contained in:
Robert Allan James
2026-08-27 10:14:15 -04:00
co-authored by Claude Sonnet 5
parent ee2018179f
commit 4c7a39b5c3
+45
View File
@@ -1483,3 +1483,48 @@ finished). Dashed arrows = softer "gates/informs" relationships.
**Not yet done:** an ordered plan (which node to attack first, given the graph). Per Captain
Bob's own framing, that's the next pass — "start asking and answering questions iteratively
until we've planned as much as possible."
## F. Scoped plans (iterative Q&A pass, started 2026-08-27)
One node at a time: surface the concrete decisions the node's own doc comments/code don't
already answer, get a ruling, record it here. This section grows as the pass continues — it's
the output of "the punch list of punch lists," not a duplicate of §E.
### F.1 — `WRITE(10)` (the graph's highest-leverage node)
Traced against the live READ(10) implementation in `src/starkernel/usb/xhci.c`
(`xhci_bot_read_block()` / `xhci_bot_send_read10()` / the `XHCI_XFER_*`/`BOT_CMD_*`/
`XHCI_NEXT_ACTION_*` deferred-dispatch state machine) before asking anything — the mechanism
already exists for READ10 and WRITE10 is a direct mirror of it, not new protocol work:
- **Data direction flips.** READ10's Data-In stage rides `bulk_in_ring`; WRITE10's Data-Out
stage must ride `bulk_out_ring` instead (new `XHCI_XFER_BOT_DATA_OUT` /
`XHCI_NEXT_ACTION_BOT_DATA_OUT`, reusing the existing `xhci_bulk_out_enqueue_and_ring()`
against `bot_data_buf` rather than the CBW). CBW's `bmCBWFlags` clears the DATA_IN bit
(host→device) instead of setting it.
- **New SCSI opcode** — `SCSI_CMD_WRITE10` (0x2A) — plus `BOT_CMD_WRITE10` /
`BOT_TUR_CHAIN_WRITE10`, mirroring READ10's TUR-preflight chain exactly (same first-command
UNIT ATTENTION handling on a fresh target).
- **`blkio_usb.c`'s `usb_blk_write()`** stops being the `BLKIO_ENOSUP` stub: `memcpy` the
caller's `src` into `xdev->bot_data_buf`, then call the new `xhci_bot_write_block()` — same
shape as `usb_blk_read()`.
**Decisions made 2026-08-27 (iterative Q&A pass):**
1. **`read_only` flag in `blkio_info()`** — flips to 0 immediately once `xhci_bot_write_block()`
is proven in QEMU. No separate "bring-up mode" gate to design or later retire.
2. **Validation target** — a new disposable QEMU-only test image (e.g.
`disk/usbwrite-test.img`, following the same disposable-clone convention as
`disk/artemis-metafence-*.img`), attached via `-drive` + `-device usb-storage,drive=...`.
Never `disk/artemis.img` itself, matching [[project_disk_images_in_repo]]'s standing rule
and how Phase 8's block-fence work was validated
([[project_metadata_fence_design]]'s verification method).
3. **Scope boundary** — `WRITE(10)` alone is the unit of work. `MINT`'s write-the-identity step
and `DETACH`'s flush-back-to-thumb step are separate graph nodes; each gets its own scoping
pass once `WRITE(10)` lands, rather than being pulled into this one preemptively.
**Not yet scoped (deferred within this node):** exact CSW failure/residue handling for a
partial write (READ10's PASS/FAILED logic likely transfers unchanged, not independently
verified); whether a write needs a follow-up `TEST UNIT READY` or cache-flush SCSI command
before the transfer is considered durable on real media (QEMU's `usb-storage` backend may mask
this — a real-hardware-only question, revisit at Milestone 8).