summaryrefslogtreecommitdiffstats
path: root/src/drivers/usb/xhci.h
diff options
context:
space:
mode:
authorMichael Brown2015-02-02 15:40:06 +0100
committerMichael Brown2015-02-03 13:33:28 +0100
commitfd53ada87cc3b715738e01d5470829b9948c1e09 (patch)
tree9d61593756103fff88b190647dbdae5416491f71 /src/drivers/usb/xhci.h
parent[usb] Add basic support for USB hubs (diff)
downloadipxe-fd53ada87cc3b715738e01d5470829b9948c1e09.tar.gz
ipxe-fd53ada87cc3b715738e01d5470829b9948c1e09.tar.xz
ipxe-fd53ada87cc3b715738e01d5470829b9948c1e09.zip
[usb] Add support for xHCI host controllers
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/drivers/usb/xhci.h')
-rw-r--r--src/drivers/usb/xhci.h1066
1 files changed, 1066 insertions, 0 deletions
diff --git a/src/drivers/usb/xhci.h b/src/drivers/usb/xhci.h
new file mode 100644
index 00000000..b9f6d9fe
--- /dev/null
+++ b/src/drivers/usb/xhci.h
@@ -0,0 +1,1066 @@
+#ifndef _IPXE_XHCI_H
+#define _IPXE_XHCI_H
+
+/** @file
+ *
+ * USB eXtensible Host Controller Interface (xHCI) driver
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <assert.h>
+#include <ipxe/pci.h>
+#include <ipxe/uaccess.h>
+#include <ipxe/usb.h>
+
+/** Minimum alignment required for data structures
+ *
+ * With the exception of the scratchpad buffer pages (which are
+ * page-aligned), data structures used by xHCI generally require from
+ * 16 to 64 byte alignment and must not cross an (xHCI) page boundary.
+ * We simplify this requirement by aligning each structure on its own
+ * size, with a minimum of a 64 byte alignment.
+ */
+#define XHCI_MIN_ALIGN 64
+
+/** xHCI PCI BAR */
+#define XHCI_BAR PCI_BASE_ADDRESS_0
+
+/** Capability register length */
+#define XHCI_CAP_CAPLENGTH 0x00
+
+/** Host controller interface version number */
+#define XHCI_CAP_HCIVERSION 0x02
+
+/** Structural parameters 1 */
+#define XHCI_CAP_HCSPARAMS1 0x04
+
+/** Number of device slots */
+#define XHCI_HCSPARAMS1_SLOTS(params) ( ( (params) >> 0 ) & 0xff )
+
+/** Number of interrupters */
+#define XHCI_HCSPARAMS1_INTRS(params) ( ( (params) >> 8 ) & 0x3ff )
+
+/** Number of ports */
+#define XHCI_HCSPARAMS1_PORTS(params) ( ( (params) >> 24 ) & 0xff )
+
+/** Structural parameters 2 */
+#define XHCI_CAP_HCSPARAMS2 0x08
+
+/** Number of page-sized scratchpad buffers */
+#define XHCI_HCSPARAMS2_SCRATCHPADS(params) \
+ ( ( ( (params) >> 16 ) & 0x3e0 ) | ( ( (params) >> 27 ) & 0x1f ) )
+
+/** Capability parameters */
+#define XHCI_CAP_HCCPARAMS1 0x10
+
+/** 64-bit addressing capability */
+#define XHCI_HCCPARAMS1_ADDR64(params) ( ( (params) >> 0 ) & 0x1 )
+
+/** Context size shift */
+#define XHCI_HCCPARAMS1_CSZ_SHIFT(params) ( 5 + ( ( (params) >> 2 ) & 0x1 ) )
+
+/** xHCI extended capabilities pointer */
+#define XHCI_HCCPARAMS1_XECP(params) ( ( ( (params) >> 16 ) & 0xffff ) << 2 )
+
+/** Doorbell offset */
+#define XHCI_CAP_DBOFF 0x14
+
+/** Runtime register space offset */
+#define XHCI_CAP_RTSOFF 0x18
+
+/** xHCI extended capability ID */
+#define XHCI_XECP_ID(xecp) ( ( (xecp) >> 0 ) & 0xff )
+
+/** Next xHCI extended capability pointer */
+#define XHCI_XECP_NEXT(xecp) ( ( ( (xecp) >> 8 ) & 0xff ) << 2 )
+
+/** USB legacy support extended capability */
+#define XHCI_XECP_ID_LEGACY 1
+
+/** USB legacy support BIOS owned semaphore */
+#define XHCI_USBLEGSUP_BIOS 0x02
+
+/** USB legacy support BIOS ownership flag */
+#define XHCI_USBLEGSUP_BIOS_OWNED 0x01
+
+/** USB legacy support OS owned semaphore */
+#define XHCI_USBLEGSUP_OS 0x03
+
+/** USB legacy support OS ownership flag */
+#define XHCI_USBLEGSUP_OS_OWNED 0x01
+
+/** USB legacy support control/status */
+#define XHCI_USBLEGSUP_CTLSTS 0x04
+
+/** Supported protocol extended capability */
+#define XHCI_XECP_ID_SUPPORTED 2
+
+/** Supported protocol revision */
+#define XHCI_SUPPORTED_REVISION 0x00
+
+/** Supported protocol minor revision */
+#define XHCI_SUPPORTED_REVISION_VER(revision) ( ( (revision) >> 16 ) & 0xffff )
+
+/** Supported protocol name */
+#define XHCI_SUPPORTED_NAME 0x04
+
+/** Supported protocol ports */
+#define XHCI_SUPPORTED_PORTS 0x08
+
+/** Supported protocol port offset */
+#define XHCI_SUPPORTED_PORTS_OFFSET(ports) ( ( (ports) >> 0 ) & 0xff )
+
+/** Supported protocol port count */
+#define XHCI_SUPPORTED_PORTS_COUNT(ports) ( ( (ports) >> 8 ) & 0xff )
+
+/** Supported protocol PSI count */
+#define XHCI_SUPPORTED_PORTS_PSIC(ports) ( ( (ports) >> 28 ) & 0x0f )
+
+/** Supported protocol slot */
+#define XHCI_SUPPORTED_SLOT 0x0c
+
+/** Supported protocol slot type */
+#define XHCI_SUPPORTED_SLOT_TYPE(slot) ( ( (slot) >> 0 ) & 0x1f )
+
+/** Supported protocol PSI */
+#define XHCI_SUPPORTED_PSI(index) ( 0x10 + ( (index) * 4 ) )
+
+/** Supported protocol PSI value */
+#define XHCI_SUPPORTED_PSI_VALUE(psi) ( ( (psi) >> 0 ) & 0x0f )
+
+/** Supported protocol PSI mantissa */
+#define XHCI_SUPPORTED_PSI_MANTISSA(psi) ( ( (psi) >> 16 ) & 0xffff )
+
+/** Supported protocol PSI exponent */
+#define XHCI_SUPPORTED_PSI_EXPONENT(psi) ( ( (psi) >> 4 ) & 0x03 )
+
+/** Default PSI values */
+enum xhci_default_psi_value {
+ /** Full speed (12Mbps) */
+ XHCI_SPEED_FULL = 1,
+ /** Low speed (1.5Mbps) */
+ XHCI_SPEED_LOW = 2,
+ /** High speed (480Mbps) */
+ XHCI_SPEED_HIGH = 3,
+ /** Super speed */
+ XHCI_SPEED_SUPER = 4,
+};
+
+/** USB command register */
+#define XHCI_OP_USBCMD 0x00
+
+/** Run/stop */
+#define XHCI_USBCMD_RUN 0x00000001UL
+
+/** Host controller reset */
+#define XHCI_USBCMD_HCRST 0x00000002UL
+
+/** USB status register */
+#define XHCI_OP_USBSTS 0x04
+
+/** Host controller halted */
+#define XHCI_USBSTS_HCH 0x00000001UL
+
+/** Page size register */
+#define XHCI_OP_PAGESIZE 0x08
+
+/** Page size */
+#define XHCI_PAGESIZE(pagesize) ( (pagesize) << 12 )
+
+/** Device notifcation control register */
+#define XHCI_OP_DNCTRL 0x14
+
+/** Command ring control register */
+#define XHCI_OP_CRCR 0x18
+
+/** Command ring cycle state */
+#define XHCI_CRCR_RCS 0x00000001UL
+
+/** Command ring running */
+#define XHCI_CRCR_CRR 0x00000008UL
+
+/** Device context base address array pointer */
+#define XHCI_OP_DCBAAP 0x30
+
+/** Configure register */
+#define XHCI_OP_CONFIG 0x38
+
+/** Maximum device slots enabled */
+#define XHCI_CONFIG_MAX_SLOTS_EN(slots) ( (slots) << 0 )
+
+/** Maximum device slots enabled mask */
+#define XHCI_CONFIG_MAX_SLOTS_EN_MASK \
+ XHCI_CONFIG_MAX_SLOTS_EN ( 0xff )
+
+/** Port status and control register */
+#define XHCI_OP_PORTSC(port) ( 0x400 - 0x10 + ( (port) << 4 ) )
+
+/** Current connect status */
+#define XHCI_PORTSC_CCS 0x00000001UL
+
+/** Port enabled */
+#define XHCI_PORTSC_PED 0x00000002UL
+
+/** Port reset */
+#define XHCI_PORTSC_PR 0x00000010UL
+
+/** Port link state */
+#define XHCI_PORTSC_PLS(pls) ( (pls) << 5 )
+
+/** Disabled port link state */
+#define XHCI_PORTSC_PLS_DISABLED XHCI_PORTSC_PLS ( 4 )
+
+/** RxDetect port link state */
+#define XHCI_PORTSC_PLS_RXDETECT XHCI_PORTSC_PLS ( 5 )
+
+/** Port link state mask */
+#define XHCI_PORTSC_PLS_MASK XHCI_PORTSC_PLS ( 0xf )
+
+/** Port power */
+#define XHCI_PORTSC_PP 0x00000200UL
+
+/** Time to delay after enabling power to a port */
+#define XHCI_PORT_POWER_DELAY_MS 20
+
+/** Port speed ID value */
+#define XHCI_PORTSC_PSIV(portsc) ( ( (portsc) >> 10 ) & 0xf )
+
+/** Port indicator control */
+#define XHCI_PORTSC_PIC(indicators) ( (indicators) << 14 )
+
+/** Port indicator control mask */
+#define XHCI_PORTSC_PIC_MASK XHCI_PORTSC_PIC ( 3 )
+
+/** Port link state write strobe */
+#define XHCI_PORTSC_LWS 0x00010000UL
+
+/** Connect status change */
+#define XHCI_PORTSC_CSC 0x00020000UL
+
+/** Port enabled/disabled change */
+#define XHCI_PORTSC_PEC 0x00040000UL
+
+/** Warm port reset change */
+#define XHCI_PORTSC_WRC 0x00080000UL
+
+/** Over-current change */
+#define XHCI_PORTSC_OCC 0x00100000UL
+
+/** Port reset change */
+#define XHCI_PORTSC_PRC 0x00200000UL
+
+/** Port link state change */
+#define XHCI_PORTSC_PLC 0x00400000UL
+
+/** Port config error change */
+#define XHCI_PORTSC_CEC 0x00800000UL
+
+/** Port status change mask */
+#define XHCI_PORTSC_CHANGE \
+ ( XHCI_PORTSC_CSC | XHCI_PORTSC_PEC | XHCI_PORTSC_WRC | \
+ XHCI_PORTSC_OCC | XHCI_PORTSC_PRC | XHCI_PORTSC_PLC | \
+ XHCI_PORTSC_CEC )
+
+/** Port status and control bits which should be preserved
+ *
+ * The port status and control register is a horrendous mix of
+ * differing semantics. Some bits are written to only when a separate
+ * write strobe bit is set. Some bits should be preserved when
+ * modifying other bits. Some bits will be cleared if written back as
+ * a one. Most excitingly, the "port enabled" bit has the semantics
+ * that 1=enabled, 0=disabled, yet writing a 1 will disable the port.
+ */
+#define XHCI_PORTSC_PRESERVE ( XHCI_PORTSC_PP | XHCI_PORTSC_PIC_MASK )
+
+/** Port power management status and control register */
+#define XHCI_OP_PORTPMSC(port) ( 0x404 - 0x10 + ( (port) << 4 ) )
+
+/** Port link info register */
+#define XHCI_OP_PORTLI(port) ( 0x408 - 0x10 + ( (port) << 4 ) )
+
+/** Port hardware link power management control register */
+#define XHCI_OP_PORTHLPMC(port) ( 0x40c - 0x10 + ( (port) << 4 ) )
+
+/** Event ring segment table size register */
+#define XHCI_RUN_ERSTSZ(intr) ( 0x28 + ( (intr) << 5 ) )
+
+/** Event ring segment table base address register */
+#define XHCI_RUN_ERSTBA(intr) ( 0x30 + ( (intr) << 5 ) )
+
+/** Event ring dequeue pointer register */
+#define XHCI_RUN_ERDP(intr) ( 0x38 + ( (intr) << 5 ) )
+
+/** A transfer request block template */
+struct xhci_trb_template {
+ /** Parameter */
+ uint64_t parameter;
+ /** Status */
+ uint32_t status;
+ /** Control */
+ uint32_t control;
+};
+
+/** A transfer request block */
+struct xhci_trb_common {
+ /** Reserved */
+ uint64_t reserved_a;
+ /** Reserved */
+ uint32_t reserved_b;
+ /** Flags */
+ uint8_t flags;
+ /** Type */
+ uint8_t type;
+ /** Reserved */
+ uint16_t reserved_c;
+} __attribute__ (( packed ));
+
+/** Transfer request block cycle bit flag */
+#define XHCI_TRB_C 0x01
+
+/** Transfer request block toggle cycle bit flag */
+#define XHCI_TRB_TC 0x02
+
+/** Transfer request block chain flag */
+#define XHCI_TRB_CH 0x10
+
+/** Transfer request block interrupt on completion flag */
+#define XHCI_TRB_IOC 0x20
+
+/** Transfer request block immediate data flag */
+#define XHCI_TRB_IDT 0x40
+
+/** Transfer request block type */
+#define XHCI_TRB_TYPE(type) ( (type) << 2 )
+
+/** Transfer request block type mask */
+#define XHCI_TRB_TYPE_MASK XHCI_TRB_TYPE ( 0x3f )
+
+/** A normal transfer request block */
+struct xhci_trb_normal {
+ /** Data buffer */
+ uint64_t data;
+ /** Length */
+ uint32_t len;
+ /** Flags */
+ uint8_t flags;
+ /** Type */
+ uint8_t type;
+ /** Reserved */
+ uint16_t reserved;
+} __attribute__ (( packed ));
+
+/** A normal transfer request block */
+#define XHCI_TRB_NORMAL XHCI_TRB_TYPE ( 1 )
+
+/** Construct TD size field */
+#define XHCI_TD_SIZE(remaining) \
+ ( ( ( (remaining) <= 0xf ) ? remaining : 0xf ) << 17 )
+
+/** A setup stage transfer request block */
+struct xhci_trb_setup {
+ /** Setup packet */
+ struct usb_setup_packet packet;
+ /** Length */
+ uint32_t len;
+ /** Flags */
+ uint8_t flags;
+ /** Type */
+ uint8_t type;
+ /** Transfer direction */
+ uint8_t direction;
+ /** Reserved */
+ uint8_t reserved;
+} __attribute__ (( packed ));
+
+/** A setup stage transfer request block */
+#define XHCI_TRB_SETUP XHCI_TRB_TYPE ( 2 )
+
+/** Setup stage input data direction */
+#define XHCI_SETUP_IN 3
+
+/** Setup stage output data direction */
+#define XHCI_SETUP_OUT 2
+
+/** A data stage transfer request block */
+struct xhci_trb_data {
+ /** Data buffer */
+ uint64_t data;
+ /** Length */
+ uint32_t len;
+ /** Flags */
+ uint8_t flags;
+ /** Type */
+ uint8_t type;
+ /** Transfer direction */
+ uint8_t direction;
+ /** Reserved */
+ uint8_t reserved;
+} __attribute__ (( packed ));
+
+/** A data stage transfer request block */
+#define XHCI_TRB_DATA XHCI_TRB_TYPE ( 3 )
+
+/** Input data direction */
+#define XHCI_DATA_IN 0x01
+
+/** Output data direction */
+#define XHCI_DATA_OUT 0x00
+
+/** A status stage transfer request block */
+struct xhci_trb_status {
+ /** Reserved */
+ uint64_t reserved_a;
+ /** Reserved */
+ uint32_t reserved_b;
+ /** Flags */
+ uint8_t flags;
+ /** Type */
+ uint8_t type;
+ /** Direction */
+ uint8_t direction;
+ /** Reserved */
+ uint8_t reserved_c;
+} __attribute__ (( packed ));
+
+/** A status stage transfer request block */
+#define XHCI_TRB_STATUS XHCI_TRB_TYPE ( 4 )
+
+/** Input status direction */
+#define XHCI_STATUS_IN 0x01
+
+/** Output status direction */
+#define XHCI_STATUS_OUT 0x00
+
+/** A link transfer request block */
+struct xhci_trb_link {
+ /** Next ring segment */
+ uint64_t next;
+ /** Reserved */
+ uint32_t reserved_a;
+ /** Flags */
+ uint8_t flags;
+ /** Type */
+ uint8_t type;
+ /** Reserved */
+ uint16_t reserved_c;
+} __attribute__ (( packed ));
+
+/** A link transfer request block */
+#define XHCI_TRB_LINK XHCI_TRB_TYPE ( 6 )
+
+/** A no-op transfer request block */
+#define XHCI_TRB_NOP XHCI_TRB_TYPE ( 8 )
+
+/** An enable slot transfer request block */
+struct xhci_trb_enable_slot {
+ /** Reserved */
+ uint64_t reserved_a;
+ /** Reserved */
+ uint32_t reserved_b;
+ /** Flags */
+ uint8_t flags;
+ /** Type */
+ uint8_t type;
+ /** Slot type */
+ uint8_t slot;
+ /** Reserved */
+ uint8_t reserved_c;
+} __attribute__ (( packed ));
+
+/** An enable slot transfer request block */
+#define XHCI_TRB_ENABLE_SLOT XHCI_TRB_TYPE ( 9 )
+
+/** A disable slot transfer request block */
+struct xhci_trb_disable_slot {
+ /** Reserved */
+ uint64_t reserved_a;
+ /** Reserved */
+ uint32_t reserved_b;
+ /** Flags */
+ uint8_t flags;
+ /** Type */
+ uint8_t type;
+ /** Reserved */
+ uint8_t reserved_c;
+ /** Slot ID */
+ uint8_t slot;
+} __attribute__ (( packed ));
+
+/** A disable slot transfer request block */
+#define XHCI_TRB_DISABLE_SLOT XHCI_TRB_TYPE ( 10 )
+
+/** A context transfer request block */
+struct xhci_trb_context {
+ /** Input context */
+ uint64_t input;
+ /** Reserved */
+ uint32_t reserved_a;
+ /** Flags */
+ uint8_t flags;
+ /** Type */
+ uint8_t type;
+ /** Reserved */
+ uint8_t reserved_b;
+ /** Slot ID */
+ uint8_t slot;
+} __attribute__ (( packed ));
+
+/** An address device transfer request block */
+#define XHCI_TRB_ADDRESS_DEVICE XHCI_TRB_TYPE ( 11 )
+
+/** A configure endpoint transfer request block */
+#define XHCI_TRB_CONFIGURE_ENDPOINT XHCI_TRB_TYPE ( 12 )
+
+/** An evaluate context transfer request block */
+#define XHCI_TRB_EVALUATE_CONTEXT XHCI_TRB_TYPE ( 13 )
+
+/** A reset endpoint transfer request block */
+struct xhci_trb_reset_endpoint {
+ /** Reserved */
+ uint64_t reserved_a;
+ /** Reserved */
+ uint32_t reserved_b;
+ /** Flags */
+ uint8_t flags;
+ /** Type */
+ uint8_t type;
+ /** Endpoint ID */
+ uint8_t endpoint;
+ /** Slot ID */
+ uint8_t slot;
+} __attribute__ (( packed ));
+
+/** A reset endpoint transfer request block */
+#define XHCI_TRB_RESET_ENDPOINT XHCI_TRB_TYPE ( 14 )
+
+/** A stop endpoint transfer request block */
+struct xhci_trb_stop_endpoint {
+ /** Reserved */
+ uint64_t reserved_a;
+ /** Reserved */
+ uint32_t reserved_b;
+ /** Flags */
+ uint8_t flags;
+ /** Type */
+ uint8_t type;
+ /** Endpoint ID */
+ uint8_t endpoint;
+ /** Slot ID */
+ uint8_t slot;
+} __attribute__ (( packed ));
+
+/** A stop endpoint transfer request block */
+#define XHCI_TRB_STOP_ENDPOINT XHCI_TRB_TYPE ( 15 )
+
+/** A set transfer ring dequeue pointer transfer request block */
+struct xhci_trb_set_tr_dequeue_pointer {
+ /** Dequeue pointer */
+ uint64_t dequeue;
+ /** Reserved */
+ uint32_t reserved;
+ /** Flags */
+ uint8_t flags;
+ /** Type */
+ uint8_t type;
+ /** Endpoint ID */
+ uint8_t endpoint;
+ /** Slot ID */
+ uint8_t slot;
+} __attribute__ (( packed ));
+
+/** A set transfer ring dequeue pointer transfer request block */
+#define XHCI_TRB_SET_TR_DEQUEUE_POINTER XHCI_TRB_TYPE ( 16 )
+
+/** A no-op command transfer request block */
+#define XHCI_TRB_NOP_CMD XHCI_TRB_TYPE ( 23 )
+
+/** A transfer event transfer request block */
+struct xhci_trb_transfer {
+ /** Transfer TRB pointer */
+ uint64_t transfer;
+ /** Residual transfer length */
+ uint16_t residual;
+ /** Reserved */
+ uint8_t reserved;
+ /** Completion code */
+ uint8_t code;
+ /** Flags */
+ uint8_t flags;
+ /** Type */
+ uint8_t type;
+ /** Endpoint ID */
+ uint8_t endpoint;
+ /** Slot ID */
+ uint8_t slot;
+} __attribute__ (( packed ));
+
+/** A transfer event transfer request block */
+#define XHCI_TRB_TRANSFER XHCI_TRB_TYPE ( 32 )
+
+/** A command completion event transfer request block */
+struct xhci_trb_complete {
+ /** Command TRB pointer */
+ uint64_t command;
+ /** Parameter */
+ uint8_t parameter[3];
+ /** Completion code */
+ uint8_t code;
+ /** Flags */
+ uint8_t flags;
+ /** Type */
+ uint8_t type;
+ /** Virtual function ID */
+ uint8_t vf;
+ /** Slot ID */
+ uint8_t slot;
+} __attribute__ (( packed ));
+
+/** A command completion event transfer request block */
+#define XHCI_TRB_COMPLETE XHCI_TRB_TYPE ( 33 )
+
+/** xHCI completion codes */
+enum xhci_completion_code {
+ /** Success */
+ XHCI_CMPLT_SUCCESS = 1,
+ /** Short packet */
+ XHCI_CMPLT_SHORT = 13,
+};
+
+/** A port status change transfer request block */
+struct xhci_trb_port_status {
+ /** Reserved */
+ uint8_t reserved_a[3];
+ /** Port ID */
+ uint8_t port;
+ /** Reserved */
+ uint8_t reserved_b[7];
+ /** Completion code */
+ uint8_t code;
+ /** Flags */
+ uint8_t flags;
+ /** Type */
+ uint8_t type;
+ /** Reserved */
+ uint16_t reserved_c;
+} __attribute__ (( packed ));
+
+/** A port status change transfer request block */
+#define XHCI_TRB_PORT_STATUS XHCI_TRB_TYPE ( 34 )
+
+/** A transfer request block */
+union xhci_trb {
+ /** Template */
+ struct xhci_trb_template template;
+ /** Common fields */
+ struct xhci_trb_common common;
+ /** Normal TRB */
+ struct xhci_trb_normal normal;
+ /** Setup stage TRB */
+ struct xhci_trb_setup setup;
+ /** Data stage TRB */
+ struct xhci_trb_data data;
+ /** Status stage TRB */
+ struct xhci_trb_status status;
+ /** Link TRB */
+ struct xhci_trb_link link;
+ /** Enable slot TRB */
+ struct xhci_trb_enable_slot enable;
+ /** Disable slot TRB */
+ struct xhci_trb_disable_slot disable;
+ /** Input context TRB */
+ struct xhci_trb_context context;
+ /** Reset endpoint TRB */
+ struct xhci_trb_reset_endpoint reset;
+ /** Stop endpoint TRB */
+ struct xhci_trb_stop_endpoint stop;
+ /** Set transfer ring dequeue pointer TRB */
+ struct xhci_trb_set_tr_dequeue_pointer dequeue;
+ /** Transfer event */
+ struct xhci_trb_transfer transfer;
+ /** Command completion event */
+ struct xhci_trb_complete complete;
+ /** Port status changed event */
+ struct xhci_trb_port_status port;
+} __attribute__ (( packed ));
+
+/** An input control context */
+struct xhci_control_context {
+ /** Drop context flags */
+ uint32_t drop;
+ /** Add context flags */
+ uint32_t add;
+ /** Reserved */
+ uint32_t reserved_a[5];
+ /** Configuration value */
+ uint8_t config;
+ /** Interface number */
+ uint8_t intf;
+ /** Alternate setting */
+ uint8_t alt;
+ /** Reserved */
+ uint8_t reserved_b;
+} __attribute__ (( packed ));
+
+/** A slot context */
+struct xhci_slot_context {
+ /** Device info */
+ uint32_t info;
+ /** Maximum exit latency */
+ uint16_t latency;
+ /** Root hub port number */
+ uint8_t port;
+ /** Number of downstream ports */
+ uint8_t ports;
+ /** TT hub slot ID */
+ uint8_t tt_id;
+ /** TT port number */
+ uint8_t tt_port;
+ /** Interrupter target */
+ uint16_t intr;
+ /** USB address */
+ uint8_t address;
+ /** Reserved */
+ uint16_t reserved_a;
+ /** Slot state */
+ uint8_t state;
+ /** Reserved */
+ uint32_t reserved_b[4];
+} __attribute__ (( packed ));
+
+/** Construct slot context device info */
+#define XHCI_SLOT_INFO( entries, hub, speed, route ) \
+ ( ( (entries) << 27 ) | ( (hub) << 26 ) | ( (speed) << 20 ) | (route) )
+
+/** An endpoint context */
+struct xhci_endpoint_context {
+ /** Endpoint state */
+ uint8_t state;
+ /** Stream configuration */
+ uint8_t stream;
+ /** Polling interval */
+ uint8_t interval;
+ /** Max ESIT payload high */
+ uint8_t esit_high;
+ /** Endpoint type */
+ uint8_t type;
+ /** Maximum burst size */
+ uint8_t burst;
+ /** Maximum packet size */
+ uint16_t mtu;
+ /** Transfer ring dequeue pointer */
+ uint64_t dequeue;
+ /** Average TRB length */
+ uint16_t trb_len;
+ /** Max ESIT payload low */
+ uint16_t esit_low;
+ /** Reserved */
+ uint32_t reserved[3];
+} __attribute__ (( packed ));
+
+/** Endpoint states */
+enum xhci_endpoint_state {
+ /** Endpoint is disabled */
+ XHCI_ENDPOINT_DISABLED = 0,
+ /** Endpoint is running */
+ XHCI_ENDPOINT_RUNNING = 1,
+ /** Endpoint is halted due to a USB Halt condition */
+ XHCI_ENDPOINT_HALTED = 2,
+ /** Endpoint is stopped */
+ XHCI_ENDPOINT_STOPPED = 3,
+ /** Endpoint is halted due to a TRB error */
+ XHCI_ENDPOINT_ERROR = 4,
+};
+
+/** Endpoint state mask */
+#define XHCI_ENDPOINT_STATE_MASK 0x07
+
+/** Endpoint type */
+#define XHCI_EP_TYPE(type) ( (type) << 3 )
+
+/** Control endpoint type */
+#define XHCI_EP_TYPE_CONTROL XHCI_EP_TYPE ( 4 )
+
+/** Input endpoint type */
+#define XHCI_EP_TYPE_IN XHCI_EP_TYPE ( 4 )
+
+/** Endpoint dequeue cycle state */
+#define XHCI_EP_DCS 0x00000001UL
+
+/** Control endpoint average TRB length */
+#define XHCI_EP0_TRB_LEN 8
+
+/** An event ring segment */
+struct xhci_event_ring_segment {
+ /** Base address */
+ uint64_t base;
+ /** Number of TRBs */
+ uint32_t count;
+ /** Reserved */
+ uint32_t reserved;
+} __attribute__ (( packed ));
+
+/** A transfer request block command/transfer ring */
+struct xhci_trb_ring {
+ /** Producer counter */
+ unsigned int prod;
+ /** Consumer counter */
+ unsigned int cons;
+ /** Ring size (log2) */
+ unsigned int shift;
+ /** Ring counter mask */
+ unsigned int mask;
+
+ /** I/O buffers */
+ struct io_buffer **iobuf;
+
+ /** Transfer request blocks */
+ union xhci_trb *trb;
+ /** Length of transfer request blocks */
+ size_t len;
+ /** Link TRB (if applicable) */
+ struct xhci_trb_link *link;
+
+ /** Doorbell register */
+ void *db;
+ /** Doorbell register value */
+ uint32_t dbval;
+};
+
+/** An event ring */
+struct xhci_event_ring {
+ /** Consumer counter */
+ unsigned int cons;
+ /** Event ring segment table */
+ struct xhci_event_ring_segment *segment;
+ /** Transfer request blocks */
+ union xhci_trb *trb;
+};
+
+/**
+ * Calculate doorbell register value
+ *
+ * @v target Doorbell target
+ * @v stream Doorbell stream ID
+ * @ret dbval Doorbell register value
+ */
+#define XHCI_DBVAL( target, stream ) ( (target) | ( (stream) << 16 ) )
+
+/**
+ * Calculate space used in TRB ring
+ *
+ * @v ring TRB ring
+ * @ret fill Number of entries used
+ */
+static inline __attribute__ (( always_inline )) unsigned int
+xhci_ring_fill ( struct xhci_trb_ring *ring ) {
+
+ return ( ring->prod - ring->cons );
+}
+
+/**
+ * Calculate space remaining in TRB ring
+ *
+ * @v ring TRB ring
+ * @ret remaining Number of entries remaining
+ *
+ * xHCI does not allow us to completely fill a ring; there must be at
+ * least one free entry (excluding the Link TRB).
+ */
+static inline __attribute__ (( always_inline )) unsigned int
+xhci_ring_remaining ( struct xhci_trb_ring *ring ) {
+ unsigned int fill = xhci_ring_fill ( ring );
+
+ /* We choose to utilise rings with ( 2^n + 1 ) entries, with
+ * the final entry being a Link TRB. The maximum fill level
+ * is therefore
+ *
+ * ( ( 2^n + 1 ) - 1 (Link TRB) - 1 (one slot always empty)
+ * == ( 2^n - 1 )
+ *
+ * which is therefore equal to the ring mask.
+ */
+ assert ( fill <= ring->mask );
+ return ( ring->mask - fill );
+}
+
+/**
+ * Calculate physical address of most recently consumed TRB
+ *
+ * @v ring TRB ring
+ * @ret trb TRB physical address
+ */
+static inline __attribute__ (( always_inline )) physaddr_t
+xhci_ring_consumed ( struct xhci_trb_ring *ring ) {
+ unsigned int index = ( ( ring->cons - 1 ) & ring->mask );
+
+ return virt_to_phys ( &ring->trb[index] );
+}
+
+/** Slot context index */
+#define XHCI_CTX_SLOT 0
+
+/** Calculate context index from USB endpoint address */
+#define XHCI_CTX(address) \
+ ( (address) ? ( ( ( (address) & 0x0f ) << 1 ) | \
+ ( ( (address) & 0x80 ) >> 7 ) ) : 1 )
+
+/** Endpoint zero context index */
+#define XHCI_CTX_EP0 XHCI_CTX ( 0x00 )
+
+/** End of contexts */
+#define XHCI_CTX_END 32
+
+/** Device context index */
+#define XHCI_DCI(ctx) ( (ctx) + 0 )
+
+/** Input context index */
+#define XHCI_ICI(ctx) ( (ctx) + 1 )
+
+/** Number of TRBs (excluding Link TRB) in the command ring
+ *
+ * This is a policy decision.
+ */
+#define XHCI_CMD_TRBS_LOG2 2
+
+/** Number of TRBs in the event ring
+ *
+ * This is a policy decision.
+ */
+#define XHCI_EVENT_TRBS_LOG2 6
+
+/** Number of TRBs in a transfer ring
+ *
+ * This is a policy decision.
+ */
+#define XHCI_TRANSFER_TRBS_LOG2 6
+
+/** Maximum time to wait for BIOS to release ownership
+ *
+ * This is a policy decision.
+ */
+#define XHCI_USBLEGSUP_MAX_WAIT_MS 100
+
+/** Maximum time to wait for host controller to stop
+ *
+ * This is a policy decision.
+ */
+#define XHCI_STOP_MAX_WAIT_MS 100
+
+/** Maximum time to wait for reset to complete
+ *
+ * This is a policy decision.
+ */
+#define XHCI_RESET_MAX_WAIT_MS 500
+
+/** Maximum time to wait for a command to complete
+ *
+ * This is a policy decision.
+ */
+#define XHCI_COMMAND_MAX_WAIT_MS 500
+
+/** Maximum time to wait for a port reset to complete
+ *
+ * This is a policy decision.
+ */
+#define XHCI_PORT_RESET_MAX_WAIT_MS 500
+
+/** An xHCI device */
+struct xhci_device {
+ /** Registers */
+ void *regs;
+
+ /** Capability registers */
+ void *cap;
+ /** Operational registers */
+ void *op;
+ /** Runtime registers */
+ void *run;
+ /** Doorbell registers */
+ void *db;
+
+ /** Number of device slots */
+ unsigned int slots;
+ /** Number of interrupters */
+ unsigned int intrs;
+ /** Number of ports */
+ unsigned int ports;
+
+ /** Number of page-sized scratchpad buffers */
+ unsigned int scratchpads;
+
+ /** 64-bit addressing capability */
+ int addr64;
+ /** Context size shift */
+ unsigned int csz_shift;
+ /** xHCI extended capabilities offset */
+ unsigned int xecp;
+
+ /** Page size */
+ size_t pagesize;
+
+ /** USB legacy support capability (if present and enabled) */
+ unsigned int legacy;
+
+ /** Device context base address array */
+ uint64_t *dcbaa;
+
+ /** Scratchpad buffer area */
+ userptr_t scratchpad;
+ /** Scratchpad buffer array */
+ uint64_t *scratchpad_array;
+
+ /** Command ring */
+ struct xhci_trb_ring command;
+ /** Event ring */
+ struct xhci_event_ring event;
+ /** Current command completion buffer (if any) */
+ union xhci_trb *completion;
+
+ /** Device slots, indexed by slot ID */
+ struct xhci_slot **slot;
+
+ /** USB bus */
+ struct usb_bus *bus;
+};
+
+/** An xHCI device slot */
+struct xhci_slot {
+ /** xHCI device */
+ struct xhci_device *xhci;
+ /** USB device */
+ struct usb_device *usb;
+ /** Slot ID */
+ unsigned int id;
+ /** Slot context */
+ struct xhci_slot_context *context;
+ /** Route string */
+ unsigned int route;
+ /** Root hub port number */
+ unsigned int port;
+ /** Protocol speed ID */
+ unsigned int psiv;
+ /** Endpoints, indexed by context ID */
+ struct xhci_endpoint *endpoint[XHCI_CTX_END];
+};
+
+/** An xHCI endpoint */
+struct xhci_endpoint {
+ /** xHCI device */
+ struct xhci_device *xhci;
+ /** xHCI slot */
+ struct xhci_slot *slot;
+ /** USB endpoint */
+ struct usb_endpoint *ep;
+ /** Context index */
+ unsigned int ctx;
+ /** Endpoint type */
+ unsigned int type;
+ /** Endpoint context */
+ struct xhci_endpoint_context *context;
+ /** Transfer ring */
+ struct xhci_trb_ring ring;
+};
+
+#endif /* _IPXE_XHCI_H */