Artemis Milestone 2g: Configure Endpoint command
Adds the xHCI Configure Endpoint command for the two bulk endpoints identified by the previous increment, and fixes control-transfer sequencing to match the spec: xHCI 1.2 section 4.3.5 requires Configure Endpoint before SET_CONFIGURATION is sent to the device, the reverse of the order this driver used through 2f (which happened to work against QEMU's lenient qemu-xhci emulation but wasn't spec-correct). New XHCI_TRB_TYPE_CONFIGURE_ENDPOINT_CMD, EP Context type constants for Bulk IN/OUT, and an XHCI_EP_ADDR_TO_DCI() macro (DCI = 2*EndpointNumber + Direction) in xhci.h. xhci_cmd_configure_endpoint() builds the Input Context (Slot + one EP Context per DCI up to the highest bulk endpoint in use) and submits the command via the existing next_action deferral mechanism, correlated on completion via a new XHCI_CONN_AWAIT_CONFIGURE_ENDPOINT connect_state, then chains into the existing SET_CONFIGURATION path. Two allocations had to grow beyond what Address Device sized them for: the Input Context (previously room for one EP Context only) and, less obviously, the Device Context that DCBAA[slot_id] itself points at -- the controller only touches DCIs named in a command's own Add/Drop flags, so growing that buffer required copying its existing Slot+EP0 content forward rather than zeroing it, to avoid handing the controller a blank EP0 out from under an endpoint this command isn't touching. Bulk Transfer Rings (bulk_in_ring/bulk_out_ring) are allocated and wired into the new EP Contexts but not yet exercised by an actual transfer -- CBW/CSW submission is next. Verified live via QMP hotplug, all three architectures, byte-identical: bulk endpoint identification -> configure endpoint command submitted -> configure endpoint succeeded -> the existing set configuration -> device configured chain, then a clean disconnect/disable-slot teardown afterward with the larger Device Context installed. FABRIC-2.md Section X Milestone 2g's endpoint identify+configure checklist item marked fully done. 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
96d55fcd87
commit
92ce1f85dd
@@ -194,6 +194,7 @@ typedef struct {
|
||||
#define XHCI_TRB_TYPE_ENABLE_SLOT_CMD 9
|
||||
#define XHCI_TRB_TYPE_DISABLE_SLOT_CMD 10
|
||||
#define XHCI_TRB_TYPE_ADDRESS_DEVICE_CMD 11
|
||||
#define XHCI_TRB_TYPE_CONFIGURE_ENDPOINT_CMD 12
|
||||
#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
|
||||
@@ -319,10 +320,23 @@ typedef struct {
|
||||
} xhci_ep_ctx32_t;
|
||||
|
||||
#define XHCI_EP_CTX_TYPE_SHIFT 3
|
||||
#define XHCI_EP_CTX_TYPE_CONTROL_BIDI 4u /* the only EP type this driver uses so far (EP0) */
|
||||
#define XHCI_EP_CTX_TYPE_CONTROL_BIDI 4u /* EP0 */
|
||||
#define XHCI_EP_CTX_TYPE_BULK_OUT 2u /* xHCI 1.2 spec table 6-9 */
|
||||
#define XHCI_EP_CTX_TYPE_BULK_IN 6u
|
||||
#define XHCI_EP_CTX_CERR_SHIFT 1
|
||||
#define XHCI_EP_CTX_MAX_PACKET_SHIFT 16
|
||||
|
||||
/* Device Context Index (DCI) for a given endpoint, xHCI 1.2 spec section
|
||||
* 4.5.1: DCI = 2*EndpointNumber + Direction (Direction=1 for IN, 0 for
|
||||
* OUT/control) -- EP0 is always DCI 1 regardless of direction, a special
|
||||
* case this macro does not need to handle since EP0's DCI is hardcoded
|
||||
* (XHCI_INPUT_CTRL_ADD_EP0's bit position) everywhere it's used. Takes a
|
||||
* full bEndpointAddress (bit 7 = direction, bits 3:0 = number), matching
|
||||
* how bulk_in_ep_addr/bulk_out_ep_addr are stored. */
|
||||
#define XHCI_EP_ADDR_TO_DCI(addr) \
|
||||
((2u * ((uint32_t)(addr) & USB_EP_ADDR_NUM_MASK)) + \
|
||||
(((uint32_t)(addr) & USB_EP_ADDR_DIR_MASK) ? 1u : 0u))
|
||||
|
||||
typedef struct {
|
||||
volatile uint32_t drop_flags; /* D0..D31 -- unused for Address Device (nothing to drop) */
|
||||
volatile uint32_t add_flags; /* A0..A31 -- bit0=Slot, bit1=EP0 for Address Device */
|
||||
|
||||
@@ -71,7 +71,8 @@ typedef struct {
|
||||
XHCI_CONN_IDLE = 0,
|
||||
XHCI_CONN_AWAIT_ENABLE_SLOT,
|
||||
XHCI_CONN_AWAIT_ADDRESS_DEVICE,
|
||||
XHCI_CONN_AWAIT_DISABLE_SLOT
|
||||
XHCI_CONN_AWAIT_DISABLE_SLOT,
|
||||
XHCI_CONN_AWAIT_CONFIGURE_ENDPOINT
|
||||
} connect_state;
|
||||
uint32_t pending_connect_slot_id;
|
||||
/* Milestone 2e/2g: disconnect teardown. Same single-outstanding-
|
||||
@@ -132,6 +133,21 @@ typedef struct {
|
||||
uint8_t bulk_out_ep_addr;
|
||||
uint16_t bulk_out_max_packet;
|
||||
|
||||
/* Milestone 2g: bulk endpoint Transfer Rings, one per direction --
|
||||
* same fixed-ring-plus-Link-TRB pattern as ep0_ring, lazily allocated
|
||||
* once and reused across every connect (single-device scope, matching
|
||||
* every other ring in this driver). Not usable for actual transfers
|
||||
* until xhci_cmd_configure_endpoint() succeeds -- allocating them
|
||||
* early (rather than only after success) keeps the allocation site in
|
||||
* one place and lets the Input Context's EP Contexts point at real,
|
||||
* already-initialised rings before the command is even submitted. */
|
||||
xhci_trb_t *bulk_in_ring;
|
||||
uint32_t bulk_in_ring_cycle;
|
||||
uint32_t bulk_in_ring_enq;
|
||||
xhci_trb_t *bulk_out_ring;
|
||||
uint32_t bulk_out_ring_cycle;
|
||||
uint32_t bulk_out_ring_enq;
|
||||
|
||||
/* 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
|
||||
@@ -147,6 +163,7 @@ typedef struct {
|
||||
XHCI_NEXT_ACTION_NONE = 0,
|
||||
XHCI_NEXT_ACTION_GET_DEVICE_DESC,
|
||||
XHCI_NEXT_ACTION_GET_CONFIG_DESC,
|
||||
XHCI_NEXT_ACTION_CONFIGURE_ENDPOINT,
|
||||
XHCI_NEXT_ACTION_SET_CONFIG
|
||||
} next_action;
|
||||
uint32_t next_action_slot_id;
|
||||
@@ -273,6 +290,39 @@ int xhci_cmd_disable_slot(xhci_dev_t *dev, uint32_t slot_id);
|
||||
int xhci_cmd_address_device(xhci_dev_t *dev, uint32_t slot_id,
|
||||
uint32_t port_id, uint32_t speed);
|
||||
|
||||
/*
|
||||
* xhci_cmd_configure_endpoint — build the Input Context (Slot + the two
|
||||
* bulk EP Contexts, add-only), allocate the
|
||||
* bulk Transfer Rings, and submit a
|
||||
* Configure Endpoint command TRB for
|
||||
* slot_id.
|
||||
*
|
||||
* Per xHCI 1.2 spec section 4.3.5, this must be issued after enumeration
|
||||
* has identified the endpoints a device's chosen configuration/interface
|
||||
* actually uses, and before the USB SET_CONFIGURATION request is sent to
|
||||
* the device -- the reverse of that order (which this driver used before
|
||||
* this increment) works against QEMU's lenient emulation but is not
|
||||
* spec-correct. Requires dev->bulk_in_ep_addr/bulk_out_ep_addr to already
|
||||
* be populated (2f's config descriptor walk) -- refuses if either is
|
||||
* still 0 (not found).
|
||||
*
|
||||
* The Slot Context's Route String/Speed/Root Hub Port/Interrupter Target
|
||||
* fields are copied from the already-addressed device's own Device
|
||||
* Context (populated by a prior successful Address Device) rather than
|
||||
* reconstructed from scratch -- those values aren't retained anywhere
|
||||
* else by the time enumeration reaches this point (pending_connect_port_id
|
||||
* is cleared as soon as Address Device completes). Only Context Entries is
|
||||
* changed, to the highest DCI now in use.
|
||||
*
|
||||
* Called from xhci_poll_events()'s deferred next_action dispatch once the
|
||||
* full Configuration descriptor has confirmed a Mass Storage/BOT interface
|
||||
* and identified both bulk endpoints -- not called directly by other code.
|
||||
*
|
||||
* Returns 0 if the command was posted, -1 on allocation failure or missing
|
||||
* prerequisite state, -2 if 64-byte contexts are required.
|
||||
*/
|
||||
int xhci_cmd_configure_endpoint(xhci_dev_t *dev, uint32_t slot_id);
|
||||
|
||||
/*
|
||||
* xhci_ep0_get_device_descriptor — issue a standard GET_DESCRIPTOR
|
||||
* (Device) control transfer (Setup +
|
||||
|
||||
Reference in New Issue
Block a user