Skip to content

xHCI

struct xhci_cap_regs {
uint8_t cap_length;
uint8_t reserved;
uint16_t hci_version;
uint32_t hcs_params1;
uint32_t hcs_params2;
uint32_t hcs_params3;
uint32_t hcc_params1;
uint32_t dboff;
uint32_t rtsoff;
uint32_t hcc_params2;
};
struct xhci_port_regs {
uint32_t portsc;
uint32_t portpmsc;
uint32_t portli;
uint32_t portct;
};
struct xhci_usbcmd {
union {
uint32_t raw;
struct {
uint32_t run_stop;
uint32_t host_controller_reset;
uint32_t interrupter_enable;
uint32_t host_system_error_en;
uint32_t reserved0;
uint32_t light_host_controller_reset;
uint32_t controller_save_state;
uint32_t controller_restore_state;
uint32_t enable_wrap_event;
uint32_t enable_u3_mf_index;
uint32_t reserved1;
uint32_t cem_enable;
uint32_t extended_tbc_enable;
uint32_t extended_tbc_trb_status_enable;
uint32_t vtio_enable;
uint32_t reserved2;
};
};
};
struct xhci_slot_ctx {
uint32_t route_string;
uint32_t speed;
uint32_t reserved0;
uint32_t mtt;
uint32_t hub;
uint32_t context_entries;
uint32_t max_exit_latency;
uint32_t root_hub_port;
uint32_t num_ports;
uint32_t parent_hub_slot_id;
uint32_t parent_port_number;
uint32_t parent_think_time;
uint32_t reserved1;
uint32_t interrupter_target;
uint32_t usb_device_address;
uint32_t reserved2;
uint32_t slot_state;
uint32_t reserved3[4];
};
struct xhci_ep_ctx {
uint32_t ep_state;
uint32_t reserved1;
uint32_t mult;
uint32_t max_pstreams;
uint32_t lsa;
uint32_t interval;
uint32_t max_esit_payload_hi;
uint32_t reserved2;
uint32_t error_count;
uint32_t ep_type;
uint32_t reserved3;
uint32_t host_initiate_disable;
uint32_t max_burst_size;
uint32_t max_packet_size;
union {
uint64_t dequeue_ptr_raw;
struct {
uint32_t dcs;
uint32_t reserved4;
uint64_t dequeue_ptr;
};
};
uint32_t average_trb_length;
uint32_t max_esit_payload_lo;
uint32_t reserved5[3];
};
struct xhci_input_ctrl_ctx {
uint32_t drop_flags;
uint32_t add_flags;
uint32_t reserved[5];
uint32_t config;
uint32_t interface_num;
uint32_t alternate_setting;
uint32_t reserved1;
};
struct xhci_input_ctx {
struct xhci_input_ctrl_ctx ctrl_ctx;
struct xhci_slot_ctx slot_ctx;
struct xhci_ep_ctx ep_ctx[31];
};

struct xhci_input_ctx referenced types:

struct xhci_device_ctx {
struct xhci_slot_ctx slot_ctx;
struct xhci_ep_ctx ep_ctx[32];
};

struct xhci_device_ctx referenced types:

struct xhci_op_regs {
struct xhci_usbcmd usbcmd;
uint32_t usbsts;
uint32_t pagesize;
uint32_t reserved[2];
uint32_t dnctrl;
uint64_t crcr;
uint32_t reserved2[4];
uint64_t dcbaap;
uint32_t config;
uint32_t reserved3[241];
struct xhci_port_regs regs[];
};

struct xhci_op_regs referenced types:

struct xhci_trb {
uint64_t parameter;
uint32_t status;
uint32_t control;
};
struct xhci_ring {
struct xhci_trb *trbs;
uint64_t phys;
uint32_t enqueue_index;
uint32_t dequeue_index;
uint8_t cycle;
uint32_t size;
size_t outgoing;
};

struct xhci_ring referenced types:

struct xhci_erst_entry {
uint64_t ring_segment_base;
uint32_t ring_segment_size;
uint32_t reserved;
};
struct xhci_interrupter_regs {
uint32_t iman;
uint32_t imod;
uint32_t erstsz;
uint32_t reserved;
uint64_t erstba;
uint64_t erdp;
};
struct xhci_dcbaa {
uint64_t ptrs[256];
};
struct xhci_ext_cap {
uint8_t cap_id;
uint8_t next;
uint16_t cap_specific;
};
struct xhci_slot {
enum xhci_slot_state state;
struct xhci_device *dev;
struct xhci_ring *ep_rings[32];
uint8_t slot_id;
refcount_t refcount;
struct xhci_port *port;
struct usb_device *udev;
};

struct xhci_slot referenced types:

struct xhci_port {
struct spinlock update_lock;
uint8_t port_id;
struct xhci_slot *slot;
uint8_t speed;
bool usb3;
uint64_t generation;
enum xhci_port_state state;
struct xhci_device *dev;
};

struct xhci_port referenced types:

struct xhci_device {
uint8_t irq;
struct pci_device *pci;
struct xhci_input_ctx *input_ctx;
struct xhci_cap_regs *cap_regs;
struct xhci_op_regs *op_regs;
struct xhci_interrupter_regs *intr_regs;
struct xhci_dcbaa *dcbaa;
struct xhci_ring *event_ring;
struct xhci_ring *cmd_ring;
struct xhci_erst_entry *erst;
struct xhci_port_regs *port_regs;
uint64_t ports;
struct xhci_slot slots[XHCI_SLOT_COUNT];
struct xhci_port port_info[XHCI_PORT_COUNT];
struct list_head requests[XHCI_REQ_LIST_MAX];
size_t num_devices;
struct list_head devices;
struct spinlock lock;
struct semaphore sem;
struct semaphore port_disconnect;
struct semaphore port_connect;
struct usb_controller *controller;
atomic_bool worker_waiting;
};

struct xhci_device referenced types:

struct xhci_command {
struct xhci_ring *ring;
struct xhci_slot *slot;
uint32_t ep_id;
size_t num_trbs;
void (*emit)(struct xhci_command *cmd, struct xhci_ring *ring);
struct xhci_request *request;
void *private;
};

struct xhci_command referenced types:

struct xhci_request {
enum xhci_request_list list_owner;
struct usb_request *urb;
struct xhci_command *command;
bool slot_reset;
struct xhci_trb *last_trb;
uint64_t trb_phys;
uint8_t port;
uint8_t completion_code;
uint64_t return_parameter;
uint32_t return_status;
uint32_t return_control;
uint64_t generation;
enum xhci_request_status status;
struct list_head list;
void (*callback)(struct xhci_device *, struct xhci_request *);
void *private;
};

struct xhci_request referenced types:

struct xhci_return {
uint32_t control;
uint32_t status;
};
enum xhci_slot_state {
XHCI_SLOT_STATE_UNDEF,
XHCI_SLOT_STATE_ENABLED,
XHCI_SLOT_STATE_DISCONNECTING,
XHCI_SLOT_STATE_DISCONNECTED,
};
enum xhci_port_state {
XHCI_PORT_STATE_UNDEF,
XHCI_PORT_STATE_CONNECTING,
XHCI_PORT_STATE_CONNECTED,
XHCI_PORT_STATE_DISCONNECTING,
XHCI_PORT_STATE_DISCONNECTED,
};
enum xhci_request_status {
XHCI_REQUEST_SENDING,
XHCI_REQUEST_OK,
XHCI_REQUEST_CANCELLED,
XHCI_REQUEST_DISCONNECT,
XHCI_REQUEST_ERR,
};
enum xhci_request_list {
XHCI_REQ_LIST_NONE,
XHCI_REQ_LIST_OUTGOING,
XHCI_REQ_LIST_WAITING,
XHCI_REQ_LIST_PROCESSED,
XHCI_REQ_LIST_MAX,
};
char xhci_slot_state_str(enum xhci_slot_state s);

xhci_slot_state_str referenced types:

char xhci_port_state_str(enum xhci_port_state s);

xhci_port_state_str referenced types:

#define XHCI_DEVICE_TIMEOUT 1000
#define TRB_RING_SIZE 256
#define XHCI_PORT_COUNT 64
#define XHCI_SLOT_COUNT 255
#define XHCI_INPUT_CTX_ADD_FLAGS ((1 << 0) | (1 << 1))
#define XHCI_SETUP_TRANSFER_TYPE_NONE 0
#define XHCI_SETUP_TRANSFER_TYPE_OUT 2
#define XHCI_SETUP_TRANSFER_TYPE_IN 3
#define XHCI_USBSTS_HCH 1 /* HC halted */
#define XHCI_USBSTS_HSE (1 << 2) /* host system error */
#define XHCI_USBSTS_EI (1 << 3) /* event interrupt */
#define XHCI_USBSTS_PCD (1 << 4) /* port change detect */
#define XHCI_IMAN_MASK 0x2
#define XHCI_IMAN_INT_PENDING 0x1
#define XHCI_IMAN_INT_ENABLE 0x2
#define XHCI_ENDPOINT_TYPE_INVAL 0
#define XHCI_ENDPOINT_TYPE_ISOCH_OUT 1
#define XHCI_ENDPOINT_TYPE_BULK_OUT 2
#define XHCI_ENDPOINT_TYPE_INTERRUPT_OUT 3
#define XHCI_ENDPOINT_TYPE_CONTROL_BI 4
#define XHCI_ENDPOINT_TYPE_ISOCH_IN 5
#define XHCI_ENDPOINT_TYPE_BULK_IN 6
#define XHCI_ENDPOINT_TYPE_INTERRUPT_IN 7
#define XHCI_EXT_CAP_ID_LEGACY_SUPPORT 1
#define XHCI_EXT_CAP_ID_USB 2
#define TRB_TYPE_RESERVED 0x00
#define TRB_TYPE_NORMAL 0x01
#define TRB_TYPE_SETUP_STAGE 0x02
#define TRB_TYPE_DATA_STAGE 0x03
#define TRB_TYPE_STATUS_STAGE 0x04
#define TRB_TYPE_ISOCH 0x05
#define TRB_TYPE_LINK 0x06
#define TRB_TYPE_EVENT_DATA 0x07
#define TRB_TYPE_NO_OP 0x08
#define TRB_TYPE_NO_OP_COMMAND 0x8
#define TRB_TYPE_ENABLE_SLOT 0x09
#define TRB_TYPE_DISABLE_SLOT 0x0A
#define TRB_TYPE_ADDRESS_DEVICE 0x0B
#define TRB_TYPE_CONFIGURE_ENDPOINT 0x0C
#define TRB_TYPE_EVALUATE_CONTEXT 0x0D
#define TRB_TYPE_RESET_ENDPOINT 0x0E
#define TRB_TYPE_STOP_ENDPOINT 0x0F
#define TRB_TYPE_SET_TR_DEQUEUE_POINTER 0x10
#define TRB_TYPE_RESET_DEVICE 0x11
#define TRB_TYPE_FORCE_EVENT 0x12
#define TRB_TYPE_NEGOTIATE_BW 0x13
#define TRB_TYPE_SET_LATENCY_TOLERANCE 0x14
#define TRB_TYPE_GET_PORT_BANDWIDTH 0x15
#define TRB_TYPE_FORCE_HEADER 0x16
#define TRB_TYPE_NO_OP_2_COMMAND 0x17
#define TRB_TYPE_TRANSFER_EVENT 0x20
#define TRB_TYPE_COMMAND_COMPLETION 0x21
#define TRB_TYPE_PORT_STATUS_CHANGE 0x22
#define TRB_TYPE_BANDWIDTH_REQUEST 0x23
#define TRB_TYPE_DOORBELL_EVENT 0x24
#define TRB_TYPE_HOST_CONTROLLER_EVENT 0x25
#define TRB_TYPE_DEVICE_NOTIFICATION 0x26
#define TRB_TYPE_MFINDEX_WRAP 0x27
#define TRB_FIELD(val, lo, hi) BIT_RANGE(val, lo, hi)
#define TRB_TYPE(ctrl) TRB_FIELD(ctrl, 10, 15)
#define TRB_SLOT(ctrl) TRB_FIELD(ctrl, 24, 31)
#define TRB_EP(ctrl) TRB_FIELD(ctrl, 16, 23)
#define TRB_CC(status) TRB_FIELD(status, 24, 31)
#define TRB_PORT(parameter) TRB_FIELD(parameter, 24, 31)
#define TRB_SET_TYPE(val) (((val) & 0x3F) << 10)
#define TRB_SET_CYCLE(val) (((val) & 1))
#define TRB_SET_INTERRUPTER_TARGET(target) ((target) >> 21)
#define TRB_CYCLE_BIT (1 << 0)
#define TRB_ENT_BIT (1 << 1) // Evaluate Next TRB
#define TRB_ISP_BIT (1 << 2) // Interrupt on Short Packet
#define TRB_NS_BIT (1 << 3) // No Snoop
#define TRB_CH_BIT (1 << 4) // Chain
#define TRB_IOC_BIT (1 << 5) // Interrupt On Completion
#define TRB_IDT_BIT (1 << 6) // Immediate Data
#define TRB_BEI_BIT (1 << 9) // Block Event Interrupt (ISO)
#define TRB_TOGGLE_CYCLE_BIT (1 << 1)
#define TRB_TYPE_SHIFT 10
#define TRB_SET_SLOT_ID(id) (((id) & 0xFF) << 24)
#define PORTSC_CCS (1 << 0) // Current Connect Status
#define PORTSC_PED (1 << 1) // Port Enabled/Disabled
#define PORTSC_OCA (1 << 3) // Over-Current Active
#define PORTSC_RESET (1 << 4) // Port Reset
#define PORTSC_PR (1 << 4) // Port Reset
#define PORTSC_PLSE (1 << 5) // Port Link State Enable
#define PORTSC_PRES (1 << 6) // Port Resume
#define PORTSC_PP (1 << 9) // Port Power
#define PORTSC_SPEED_MASK (0xF << 10) // Bits 10–13: Port Speed
#define PORTSC_SPEED_SHIFT 10
#define PORTSC_PLS_SHIFT 5
#define PORTSC_PLS_MASK (0xF << 5)
#define PORTSC_LWS (1 << 16) // Link Write Strobe
#define PORTSC_CSC (1 << 17) // Connect Status Change
#define PORTSC_PEC (1 << 18) // Port Enable/Disable Change
#define PORTSC_WRC (1 << 19) // Warm Port Reset Change
#define PORTSC_OCC (1 << 20) // Over-current Change
#define PORTSC_PRC (1 << 21) // Port Reset Change
#define PORTSC_PLC (1 << 22) // Port Link State Change
#define PORTSC_CEC (1 << 23) // Port Config Error Change
#define PORTSC_PLS_POLLING 7
#define PORTSC_PLS_U0 0
#define PORTSC_PLS_U2 2
#define PORTSC_PLS_U3 3
#define PORTSC_PLS_RXDETECT 5
#define PORTSC_IND (1 << 24) // Port Indicator Control
#define PORTSC_LWS_BIT (1 << 16) // Link Write Strobe
#define PORTSC_DR (1 << 30) // Device Removable
#define PORTSC_WPR (1u << 31) // Warm Port Reset
#define PORT_SPEED_FULL 1 // USB 1.1 Full Speed
#define PORT_SPEED_LOW 2 // USB 1.1 Low Speed
#define PORT_SPEED_HIGH 3 // USB 2.0 High Speed
#define PORT_SPEED_SUPER 4 // USB 3.0 SuperSpeed
#define PORT_SPEED_SUPER_PLUS 5 // USB 3.1 Gen2 (SuperSpeed+)
#define CC_SUCCESS 1
#define CC_DATA_BUFFER_ERROR 2
#define CC_BABBLE_DETECTED 3
#define CC_USB_TRANSACTION_ERROR 4
#define CC_TRB_ERROR 5
#define CC_STALL_ERROR 6
#define CC_RESOURCE_ERROR 7
#define CC_BANDWIDTH_ERROR 8
#define CC_NO_SLOTS_AVAILABLE 9
#define CC_INVALID_STREAM_TYPE 10
#define CC_SLOT_NOT_ENABLED_ERROR 11
#define CC_ENDPOINT_NOT_ENABLED 12
#define CC_SHORT_PACKET 13
#define CC_RING_UNDERRUN 14
#define CC_RING_OVERRUN 15
#define CC_VF_EVENT_RING_FULL_ERROR 16
#define CC_PARAMETER_ERROR 17
#define CC_BANDWIDTH_OVERRUN_ERROR 18
#define CC_CONTEXT_STATE_ERROR 19
#define CC_NO_PING_RESPONSE_ERROR 20
#define CC_EVENT_RING_FULL 21
#define CC_INCOMPATIBLE_DEVICE 22
#define CC_MISSED_SERVICE 23
#define CC_COMMAND_RING_STOPPED 24
#define CC_COMMAND_ABORTED 25
#define CC_STOPPED 26
#define CC_STOPPED_LEN_INVALID 27
#define CC_STOPPED_SHORT_PACKET 28
#define CC_MAX_EXIT_LATENCY_TOO_LARGE 29
#define xhci_log(log_level, fmt, ...) \ log(LOG_SITE(xhci), LOG_HANDLE(xhci), log_level, fmt, ##__VA_ARGS__)
#define xhci_warn(fmt, ...) xhci_log(LOG_WARN, fmt, ##__VA_ARGS__)
#define xhci_error(fmt, ...) xhci_log(LOG_ERROR, fmt, ##__VA_ARGS__)
#define xhci_info(fmt, ...) xhci_log(LOG_INFO, fmt, ##__VA_ARGS__)
#define xhci_debug(fmt, ...) xhci_log(LOG_DEBUG, fmt, ##__VA_ARGS__)
#define xhci_trace(fmt, ...) xhci_log(LOG_TRACE, fmt, ##__VA_ARGS__)
#define XHCI_ERDP_EHB_BIT (1 << 3)