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:
Robert Allan James
2026-08-25 08:40:35 -04:00
co-authored by Claude Sonnet 5
parent 96d55fcd87
commit 92ce1f85dd
12 changed files with 27511 additions and 17 deletions
+15 -1
View File
@@ -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 */