Artemis Milestone 2f: EP0 control transfer, device descriptor request
Adds Setup/Data/Status stage TRB types and control bits (IDT, TRT, DIR) to xhci.h, and xhci_ep0_enqueue_trb()/xhci_ep0_get_device_descriptor() to xhci.c -- the first real control transfer this driver has issued. Follows the same enqueue-then-doorbell-once pattern as the Command Ring, operating on the EP0 Transfer Ring built during 2e's Address Device work. Setup Stage uses Immediate Data (parameter IS the 8-byte setup packet); Data Stage reads into a reused 18-byte device_descriptor buffer; Status Stage alone carries IOC, so exactly one Transfer Event signals transfer completion, correlated via a new pending_transfer_slot_id (same single-outstanding-operation pattern as connect/Enable Slot/Address Device). Automatically triggered once Address Device succeeds. Verified live via QMP hotplug, all three architectures, worked first try with identical results everywhere: idVendor=0x46f4, idProduct=0x0001, bDeviceClass=0x00 -- the class=0 confirms Mass Storage class detection needs the Configuration/Interface descriptor (2f's next item), not the device descriptor. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HZ8kNoTuP63pbQtro4qvrm
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
2e7e957680
commit
2c34e45d05
@@ -193,6 +193,9 @@ typedef struct {
|
||||
#define XHCI_TRB_TYPE_LINK 6 /* ring-wraparound marker, Command/Transfer Rings only */
|
||||
#define XHCI_TRB_TYPE_ENABLE_SLOT_CMD 9
|
||||
#define XHCI_TRB_TYPE_ADDRESS_DEVICE_CMD 11
|
||||
#define XHCI_TRB_TYPE_SETUP_STAGE 2 /* Transfer Ring, control transfers only */
|
||||
#define XHCI_TRB_TYPE_DATA_STAGE 3
|
||||
#define XHCI_TRB_TYPE_STATUS_STAGE 4
|
||||
#define XHCI_TRB_TYPE_TRANSFER_EVENT 32
|
||||
#define XHCI_TRB_TYPE_COMMAND_COMPLETION_EVT 33
|
||||
#define XHCI_TRB_TYPE_PORT_STATUS_CHANGE_EVT 34
|
||||
@@ -200,6 +203,36 @@ typedef struct {
|
||||
/* Control bits used only by Link TRBs */
|
||||
#define XHCI_TRB_CONTROL_TC (1u << 1) /* Toggle Cycle */
|
||||
|
||||
/* Control bits for control-transfer TRBs (xHCI 1.2 spec section 4.11.2.2 /
|
||||
* table 6-23..6-25). IDT (Immediate Data) tells the controller the Setup
|
||||
* Stage TRB's parameter field IS the 8-byte setup packet, not a pointer
|
||||
* to one -- required for every Setup Stage TRB. TRT/DIR select data
|
||||
* direction: TRT=3 (IN Data Stage) for the standard "read a descriptor"
|
||||
* case this driver needs first; DIR must match TRT's direction on the
|
||||
* Data Stage TRB, and the Status Stage TRB's DIR is the OPPOSITE
|
||||
* direction of the Data Stage (status is always the reverse handshake). */
|
||||
#define XHCI_TRB_CONTROL_IDT (1u << 6)
|
||||
#define XHCI_TRB_CONTROL_IOC (1u << 5) /* Interrupt On Completion */
|
||||
#define XHCI_TRB_CONTROL_DIR_IN (1u << 16) /* Data/Status Stage: 1=IN, 0=OUT */
|
||||
#define XHCI_SETUP_TRT_NO_DATA 0u
|
||||
#define XHCI_SETUP_TRT_OUT_DATA 2u
|
||||
#define XHCI_SETUP_TRT_IN_DATA 3u
|
||||
#define XHCI_TRB_CONTROL_TRT_SHIFT 16 /* Setup Stage TRB only; Data/Status Stage overlays DIR at the same bit */
|
||||
|
||||
/* Standard USB Setup packet (8 bytes) -- the exact bytes placed in a
|
||||
* Setup Stage TRB's parameter field via IDT. */
|
||||
typedef struct {
|
||||
uint8_t bmRequestType;
|
||||
uint8_t bRequest;
|
||||
uint16_t wValue;
|
||||
uint16_t wIndex;
|
||||
uint16_t wLength;
|
||||
} usb_setup_packet_t;
|
||||
|
||||
#define USB_REQ_GET_DESCRIPTOR 6u
|
||||
#define USB_DESC_TYPE_DEVICE 1u
|
||||
#define USB_DIR_DEVICE_TO_HOST 0x80u
|
||||
|
||||
/* 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
|
||||
|
||||
@@ -78,6 +78,16 @@ typedef struct {
|
||||
xhci_trb_t *ep0_ring; /* EP0 Transfer Ring, XHCI_RING_TRB_COUNT TRBs */
|
||||
uint32_t ep0_ring_cycle;
|
||||
uint32_t ep0_ring_enq;
|
||||
|
||||
/* Milestone 2f: EP0 control transfers. Like connect_state, this
|
||||
* driver only ever has one control transfer outstanding at a time --
|
||||
* pending_transfer_slot_id is 0 when idle, else the slot ID whose
|
||||
* Transfer Event (posted only by the Status Stage TRB, which alone
|
||||
* has IOC set) is still outstanding. device_descriptor is the
|
||||
* (reused, not per-slot) buffer control transfers read into; 18
|
||||
* bytes is the full standard USB device descriptor size. */
|
||||
uint32_t pending_transfer_slot_id;
|
||||
uint8_t device_descriptor[18];
|
||||
} xhci_dev_t;
|
||||
|
||||
/*
|
||||
@@ -181,4 +191,25 @@ int xhci_cmd_enable_slot(xhci_dev_t *dev);
|
||||
int xhci_cmd_address_device(xhci_dev_t *dev, uint32_t slot_id,
|
||||
uint32_t port_id, uint32_t speed);
|
||||
|
||||
/*
|
||||
* xhci_ep0_get_device_descriptor — issue a standard GET_DESCRIPTOR
|
||||
* (Device) control transfer (Setup +
|
||||
* Data-IN + Status-OUT stages) on
|
||||
* slot_id's EP0, reading the 18-byte
|
||||
* result into dev->device_descriptor.
|
||||
* Does not wait for completion -- the
|
||||
* result arrives asynchronously via
|
||||
* xhci_poll_events()'s Transfer Event
|
||||
* handling, which currently only logs
|
||||
* success/failure (parsing the fields
|
||||
* is the next increment).
|
||||
*
|
||||
* Called once Address Device succeeds -- not called directly by other
|
||||
* code yet (Milestone 2f is still in progress).
|
||||
*
|
||||
* Returns 0 if the transfer was posted, -1 if dev/dev->ep0_ring is not
|
||||
* set up.
|
||||
*/
|
||||
int xhci_ep0_get_device_descriptor(xhci_dev_t *dev, uint32_t slot_id);
|
||||
|
||||
#endif /* STARKERNEL_XHCI_DRIVER_H */
|
||||
|
||||
Reference in New Issue
Block a user