Artemis Milestone 2g: CBW construction and send for SCSI READ(10)
First real use of the bulk Transfer Rings Configure Endpoint wired up. xhci_bot_send_read10() builds a 31-byte Command Block Wrapper (USB Mass Storage Class Bulk-Only Transport spec section 5.1) and submits it as a single Normal TRB on the bulk OUT ring via a new xhci_bulk_out_enqueue_and_ring() helper -- a CBW is always exactly one TRB, so unlike the EP0 helper this one rings its own doorbell rather than leaving that to a caller assembling a group. usb_bot_cbw_t is a real struct (every field up to the CDB array is naturally aligned, and this driver's targets are all little-endian already assumed everywhere else), but its DMA length is the explicit USB_BOT_CBW_LENGTH (31) constant, never sizeof(*cbw), since the compiler may pad the struct to 32 bytes. The SCSI READ(10) CDB itself is written byte-by-byte since its LBA/Transfer Length fields are big-endian on the wire, unlike everything else in this driver -- the one place two byte orders are both live in the same function. Completion is correlated via the existing pending_transfer_slot_id/ transfer_purpose gate (new XHCI_XFER_CBW_SENT purpose) -- no ring-specific dispatch needed, since this driver's single-outstanding- transfer scope already implies which ring produced an event. This covers construction and send only (one third of a full READ(10): CBW -> Data-In stage -> CSW) -- reading the Data-In stage and CSW receive/validation are separate, explicitly not-yet-implemented items. Verified live via a temporary probe (written, run once, log captured, reverted per this project's own probe convention) -- all three architectures, byte-identical: CBW submitted -> CBW send completed, then a clean disconnect even with the Data-In stage never drained (confirms no wedge on a dangling BOT transaction). Probe-free re-verification afterward on all three architectures. FABRIC-2.md Section X Milestone 2g's CBW checklist item marked done. Also records a monitoring gotcha hit three times this session: `ls -t` over the logs/ tree can return a stale leftover log from an earlier run in the same session -- fixed going forward by reading the log path off the actual running QEMU process's own command line instead, and a memory note added so it doesn't recur next session. 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
92ce1f85dd
commit
a88c004ecb
@@ -113,7 +113,8 @@ typedef struct {
|
||||
XHCI_XFER_DEVICE_DESC,
|
||||
XHCI_XFER_CONFIG_DESC_SHORT,
|
||||
XHCI_XFER_CONFIG_DESC_FULL,
|
||||
XHCI_XFER_SET_CONFIG
|
||||
XHCI_XFER_SET_CONFIG,
|
||||
XHCI_XFER_CBW_SENT
|
||||
} transfer_purpose;
|
||||
uint32_t pending_transfer_slot_id;
|
||||
uint8_t device_descriptor[18];
|
||||
@@ -148,6 +149,18 @@ typedef struct {
|
||||
uint32_t bulk_out_ring_cycle;
|
||||
uint32_t bulk_out_ring_enq;
|
||||
|
||||
/* Milestone 2g: Bulk-Only Transport CBW. bot_cbw is reused across every
|
||||
* command (single-outstanding-transfer scope, matching every other
|
||||
* buffer in this driver) -- built fresh by xhci_bot_send_read10() each
|
||||
* call, not preserved between calls. bot_next_tag is a free-running
|
||||
* counter for dCBWTag; the BOT spec requires the host verify a CSW's
|
||||
* dCSWTag matches the CBW that produced it, so this is forward-looking
|
||||
* plumbing for that check (CSW receive is 2g's next item, not
|
||||
* implemented yet) rather than something this increment reads back
|
||||
* itself. */
|
||||
usb_bot_cbw_t bot_cbw;
|
||||
uint32_t bot_next_tag;
|
||||
|
||||
/* Deferred chaining: a doorbell ring (new control transfer) must
|
||||
* never happen synchronously from inside xhci_poll_events()'s event-
|
||||
* processing loop, before ERDP has been updated for the event
|
||||
@@ -323,6 +336,34 @@ int xhci_cmd_address_device(xhci_dev_t *dev, uint32_t slot_id,
|
||||
*/
|
||||
int xhci_cmd_configure_endpoint(xhci_dev_t *dev, uint32_t slot_id);
|
||||
|
||||
/*
|
||||
* xhci_bot_send_read10 — build a Command Block Wrapper for a SCSI
|
||||
* READ(10) and submit it on the bulk OUT Transfer
|
||||
* Ring.
|
||||
*
|
||||
* lba is the starting Logical Block Address, num_blocks the SCSI transfer
|
||||
* length (blocks, not bytes -- READ(10)'s own field), block_size the
|
||||
* device's actual bytes-per-block, used only to compute
|
||||
* dCBWDataTransferLength (the data stage's total byte length CBW
|
||||
* declares up front, not carried in the CDB itself).
|
||||
*
|
||||
* This covers CBW construction and send only, one third of a full
|
||||
* READ(10) (CBW -> Data-In stage -> CSW) -- reading the Data-In stage and
|
||||
* validating/receiving the CSW are separate, not-yet-implemented steps
|
||||
* (2g's own punch list). Does not wait for or read the resulting Transfer
|
||||
* Event -- it arrives asynchronously via xhci_poll_events(), correlated
|
||||
* via dev->transfer_purpose == XHCI_XFER_CBW_SENT, same pattern as every
|
||||
* other transfer in this driver.
|
||||
*
|
||||
* Requires bulk_out_ep_addr/bulk_out_ring to already be populated (2f/2g's
|
||||
* config descriptor walk and Configure Endpoint command) -- refuses if
|
||||
* either prerequisite is missing.
|
||||
*
|
||||
* Returns 0 if the CBW was posted, -1 if a prerequisite is missing.
|
||||
*/
|
||||
int xhci_bot_send_read10(xhci_dev_t *dev, uint32_t slot_id, uint32_t lba,
|
||||
uint16_t num_blocks, uint32_t block_size);
|
||||
|
||||
/*
|
||||
* xhci_ep0_get_device_descriptor — issue a standard GET_DESCRIPTOR
|
||||
* (Device) control transfer (Setup +
|
||||
|
||||
Reference in New Issue
Block a user