eXtensible Host Controller Interface
eXtensible Host Controller Interface (xHCI) defines a register-level description of a Host Controller for Universal Serial bus (USB), which is capable of interfacing to USB 1.x, 2.0, and 3.0 compatible devices without the use of companion controllers.
The xHCI controller communicates with the operating system using memory mapped registers that can be located by searching the PCI configuration space for a device with a specific Class ID, Subclass ID, and Interface number. All xHCI controllers will have a Class ID of 0x0C, a Sublcass ID of 0x03, and an Interface value of 0x30. The configuration space for this device will contain two Base Address Registers: BAR0 and BAR1. These two 32-bit address fields combine to create a single 64-bit address that points to the base address of the memory mapped registers for the controller.
The capability registers are located at the address specified by the PCI configuration space.
|00||CAPLENGTH||Capability Register Length|
|02||HCIVERSION||Interface Version Number|
|04||HCSPARAMS1||Structural Parameters 1|
|08||HCSPARAMS2||Structural Parameters 2|
|0C||HCSPARAMS3||Structural Parameters 3|
|18||RTSOFF||Runtime Registers Space Offset|
|1C||HCCPARMS2||Capability Parameters 2|
The operational registers are located after the capability registers in memory, and can be found by adding the CAPLENGTH field to the base address specified in the PCI configuration space.
|14||DNCTRL||Device Notification Control|
|18||CRCR||Command Ring Control|
|30||DCBAAP||Device Context Base Address Array Pointer|
Reading CRCR (or bits of it) provides '0'. Therefore, keep your own track of this address. Bit 0 of CRCR is the Consumer Cycle State (CCS) flag.
At the end of the operational registers (at offset 0x400!), each port on the root hub is assigned a set of registers. The number of entries in the port registers table is determined by the MaxPorts value in the HCSPARAMS1 register.
|00||PORTSC||Port Status and Control|
|04||PORTPMSC||Port Power Management Status and Control|
|08||PORTLI||Port Link Info|
The runtime registers are located after the operational registers in memory, and can be found by adding the RTSOFF field to the base address specified in the PCI configuration space.
|20||IR0-1023||Interrupter Register Sets|
Starting at offset 0x20, each interrupter register set defines the event ring memory addresses needed to send and receive events and data to the USB bus.
|08||ERSTSZ||Event Ring Segment Table Size|
|10||ERSTBA||Event Ring Segment Table Base Address|
|18||ERDP||Event Ring Dequeue Pointer|
The doorbell registers are located after the runtime registers in memory, and can be found by adding the DBOFF field to the base address specified in the PCI configuration space. The length of the doorbell register table is based on the number of ports specified in the MaxSlots field in the HCSPARAMS1 register above. Each doorbell register is 32-bits long, and is used to notify the controller that there are pending operations to be performed on a specific device slot.
The xHCI specifications support "virtual" controllers that can be used to support multiple virtual machines running on a single physical machine. These registers must be configured and managed by the VM host, and effectively duplicate the registers above for use by the guest VMs.
Chipsets with both EHC and xHC
Some chipsets such as the Intel Panther Point (
8086:1e31) feature both an EHC and xHC. Both controllers share the same set of ports and access to each port is determined by a hardware toggle (0 = EHC, 1 = xHC).
To switch a port to either the EHC or the xHC registers
0xd8) must be written.
For example, to switch all available ports to the xHC (make sure the registers are actually present!):
#define USB3_PSSEN 0xd0 #define XUSB2PR 0xd8 char *pci_header = ...; (u32 *)(pci_header + USB3_PSSEN) = 0xffff_ffff; // Enable SuperSpeed on USB3 ports (u32 *)(pci_header + XUSB2PR) = 0xffff_ffff; // Switch over USB2 ports
- eXtensible Host Controller Interface Specification 1.2
69e848c2090aebba5698a1620604c7dccb448684in the Linux source tree
- Haiku's XHCI implementation