Artemis Milestone 2f: Configuration descriptor read + Mass Storage/BOT class confirmation

Chains off the device descriptor request via a new deferred-action mechanism
on xhci_dev_t (next_action/next_action_slot_id/next_action_length): a short
9-byte Configuration descriptor read learns wTotalLength, then a full read
retrieves Config+Interface+Endpoint descriptors, walked for the Interface
descriptor to confirm bInterfaceClass/SubClass/Protocol == Mass Storage/
SCSI/Bulk-Only Transport.

The deferral exists because ringing the next doorbell synchronously inside
xhci_poll_events()'s event-processing loop -- before the current event's
ERDP write -- hung the guest outright (confirmed live via checkpoint
logging, amd64). Fixed by moving the actual control-transfer submission to
a small dispatch at the end of xhci_poll_events(), after ERDP is updated.

A debug hack that shipped mid-session (forcing a repeated 9-byte read
instead of chaining into the real 44-byte length, to isolate whether the
hang was doorbell-ordering or length-specific) has been reverted: restored
the real length and re-verified live. The doorbell-ordering fix was the
whole story -- the 44-byte read completes cleanly.

Verified live via QMP hotplug, all three architectures, byte-identical
results: wTotalLength=0x2c, bInterfaceClass=0x08, bInterfaceSubClass=0x06,
bInterfaceProtocol=0x50 -- confirmed Mass Storage/SCSI/BOT. Disconnect
confirmed clean on every arch, no wedge. FABRIC-2.md Section X Milestone 2f
updated with the full writeup.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QPfdtaXs9ay1nbwuMnrscu
This commit is contained in:
Robert Allan James
2026-08-25 07:27:07 -04:00
co-authored by Claude Sonnet 5
parent 2c34e45d05
commit b9c540a78b
22 changed files with 101974 additions and 52 deletions
+24
View File
@@ -231,8 +231,32 @@ typedef struct {
#define USB_REQ_GET_DESCRIPTOR 6u
#define USB_DESC_TYPE_DEVICE 1u
#define USB_DESC_TYPE_CONFIG 2u
#define USB_DIR_DEVICE_TO_HOST 0x80u
/* Standard USB Interface descriptor field offsets (9 bytes, USB 2.0 spec
* table 9-12) -- Mass Storage class detection reads these three fields.
* Not decoded via a struct like usb_setup_packet_t: the Interface
* descriptor's exact position within a Configuration descriptor's byte
* stream isn't fixed (depends on the device's actual interface/endpoint
* layout), so it's found by walking the byte stream looking for
* bDescriptorType == USB_DESC_TYPE_INTERFACE, not by a fixed struct
* offset into the whole buffer. */
/* Every standard USB descriptor starts with these two bytes (bLength,
* bDescriptorType) -- used to walk the concatenated descriptor stream a
* full Configuration descriptor read returns (Config + Interface +
* Endpoint descriptors back to back), not just the Interface one. */
#define USB_DESC_OFF_LENGTH 0u
#define USB_DESC_OFF_TYPE 1u
#define USB_CONFIG_OFF_TOTAL_LENGTH 2u /* wTotalLength, 2 bytes, Configuration descriptor only */
#define USB_DESC_TYPE_INTERFACE 4u
#define USB_IFACE_OFF_CLASS 5u
#define USB_IFACE_OFF_SUBCLASS 6u
#define USB_IFACE_OFF_PROTOCOL 7u
#define USB_CLASS_MASS_STORAGE 0x08u
#define USB_SUBCLASS_SCSI 0x06u /* SCSI transparent command set */
#define USB_PROTOCOL_BOT 0x50u /* Bulk-Only Transport */
/* Command Completion Event TRB layout (xHCI 1.2 spec table 6-32):
* parameter[63:4] = Command TRB Pointer, status[31:24] = Completion Code,
* status[23:0] = unused here, control[31:24] = Slot ID (Enable Slot's