#pragma once // eXtensible Host Controller Interface -- the register and data-structure // definitions from the xHCI 1.2 specification. // // Why xHCI and not UHCI/OHCI/EHCI: xHCI is the only host controller interface // that speaks every USB speed, so one driver covers USB 1.1 through 3.x. The // older controllers would each need their own, and a machine with all of them // needs the companion-controller handover dance on top. There is no hardware // worth supporting that has no xHCI. // --------------------------------------------------------------------------- // Capability registers -- at the start of BAR0, read-only // --------------------------------------------------------------------------- #define XHCI_CAPLENGTH 0x00 // byte: where the operational regs begin #define XHCI_HCIVERSION 0x02 // word #define XHCI_HCSPARAMS1 0x04 #define XHCI_HCSPARAMS2 0x08 #define XHCI_HCSPARAMS3 0x0C #define XHCI_HCCPARAMS1 0x10 #define XHCI_DBOFF 0x14 // doorbell array offset from BAR0 #define XHCI_RTSOFF 0x18 // runtime register offset from BAR0 #define HCS1_MAXSLOTS(x) ((x) & 0xFF) #define HCS1_MAXINTRS(x) (((x) >> 8) & 0x7FF) #define HCS1_MAXPORTS(x) (((x) >> 24) & 0xFF) // Scratchpad buffer count is split across two fields, high part first. #define HCS2_SPB_HI(x) (((x) >> 21) & 0x1F) #define HCS2_SPB_LO(x) (((x) >> 27) & 0x1F) #define HCC1_AC64 (1 << 0) // 64-bit addressing #define HCC1_CSZ (1 << 2) // contexts are 64 bytes, not 32 #define HCC1_XECP(x) (((x) >> 16) & 0xFFFF) // extended caps, in dwords // Extended capabilities: a chain of dwords, each with an ID in bits 7:0 and // the distance to the next, in dwords, in bits 15:8. #define XECP_ID(v) ((v) & 0xFF) #define XECP_NEXT(v) (((v) >> 8) & 0xFF) #define XECP_LEGACY 1 // USB Legacy Support #define LEGSUP_BIOS_OWNED (1u << 16) #define LEGSUP_OS_OWNED (1u << 24) // USBLEGCTLSTS, the dword after it: the SMI enables to clear and the // write-one-to-clear SMI events, as xHCI 1.2 section 7.1.2 lays them out. #define LEGCTL_KEEP ((0x7u << 1) | (0xFFu << 5) | (0x7u << 17)) #define LEGCTL_EVENTS (0x7u << 29) // --------------------------------------------------------------------------- // Operational registers -- at BAR0 + CAPLENGTH // --------------------------------------------------------------------------- #define XHCI_USBCMD 0x00 #define XHCI_USBSTS 0x04 #define XHCI_PAGESIZE 0x08 #define XHCI_DNCTRL 0x14 #define XHCI_CRCR 0x18 // 64-bit #define XHCI_DCBAAP 0x30 // 64-bit #define XHCI_CONFIG 0x38 #define XHCI_PORTSC(p) (0x400 + 0x10 * ((p) - 1)) // ports are 1-based #define CMD_RS (1 << 0) // run/stop #define CMD_HCRST (1 << 1) // host controller reset #define CMD_INTE (1 << 2) // interrupter enable #define CMD_HSEE (1 << 3) #define STS_HCH (1 << 0) // halted #define STS_HSE (1 << 2) // host system error #define STS_EINT (1 << 3) // event interrupt (write 1 to clear) #define STS_PCD (1 << 4) // port change detect (write 1 to clear) #define STS_CNR (1 << 11) // controller not ready #define CRCR_RCS (1 << 0) // ring cycle state // PORTSC. The change bits are write-1-to-clear, and so is PED -- writing back // a value read from this register clears whatever happened to be set. Every // write has to mask them off first. #define PORT_CCS (1 << 0) // current connect status #define PORT_PED (1 << 1) // port enabled (RW1C!) #define PORT_OCA (1 << 3) #define PORT_PR (1 << 4) // port reset #define PORT_PLS(x) (((x) >> 5) & 0xF) #define PORT_PP (1 << 9) // port power #define PORT_SPEED(x) (((x) >> 10) & 0xF) #define PORT_CSC (1 << 17) #define PORT_PEC (1 << 18) #define PORT_PRC (1 << 21) #define PORT_CHANGES 0x00FE0000u // every change bit, 17..23 #define PORT_RW1C 0x00FE0002u // change bits 17..23, plus PED // PORTSC speed encoding. These are the same numbers as USB_SPEED_* in usb.h, // which is not a coincidence -- the core uses this encoding directly so that // nothing has to be translated on its way to a slot context. #define XSPEED_FULL USB_SPEED_FULL #define XSPEED_LOW USB_SPEED_LOW #define XSPEED_HIGH USB_SPEED_HIGH #define XSPEED_SUPER USB_SPEED_SUPER // --------------------------------------------------------------------------- // Runtime registers -- at BAR0 + RTSOFF. Interrupter n is at 0x20 + 32*n. // --------------------------------------------------------------------------- #define XHCI_MFINDEX 0x00 #define XHCI_IR0 0x20 #define IR_IMAN 0x00 #define IR_IMOD 0x04 #define IR_ERSTSZ 0x08 #define IR_ERSTBA 0x10 // 64-bit #define IR_ERDP 0x18 // 64-bit #define IMAN_IP (1 << 0) // interrupt pending (RW1C) #define IMAN_IE (1 << 1) // interrupt enable #define ERDP_EHB (1 << 3) // event handler busy (RW1C) // --------------------------------------------------------------------------- // Transfer Request Blocks // --------------------------------------------------------------------------- struct trb { uint64 param; uint32 status; uint32 control; } __attribute__((packed)); #define TRB_TYPE(t) (((t) & 0x3F) << 10) #define TRB_GET_TYPE(c) (((c) >> 10) & 0x3F) #define TRB_C (1 << 0) // cycle bit #define TRB_TC (1 << 1) // toggle cycle (link TRBs) #define TRB_ISP (1 << 2) #define TRB_CH (1 << 4) // chain #define TRB_IOC (1 << 5) // interrupt on completion #define TRB_IDT (1 << 6) // immediate data #define TRB_SLOT(s) ((uint32)(s) << 24) #define TRB_GET_SLOT(c) (((c) >> 24) & 0xFF) #define TRB_GET_EPID(c) (((c) >> 16) & 0x1F) // transfer events // Transfer TRBs #define TRB_NORMAL 1 #define TRB_SETUP 2 #define TRB_DATA 3 #define TRB_STATUS 4 #define TRB_LINK 6 // Command TRBs #define TRB_ENABLE_SLOT 9 #define TRB_DISABLE_SLOT 10 #define TRB_ADDRESS_DEV 11 #define TRB_CONFIG_EP 12 #define TRB_EVAL_CTX 13 #define TRB_RESET_EP 14 #define TRB_NOOP_CMD 23 // Event TRBs #define TRB_XFER_EVENT 32 #define TRB_CMD_COMPLETE 33 #define TRB_PORT_STATUS 34 #define TRB_CC(status) (((status) >> 24) & 0xFF) #define CC_SUCCESS 1 #define CC_SHORT_PACKET 13 // Setup Stage transfer type, and Data Stage direction. #define TRT_NONE 0 #define TRT_OUT 2 #define TRT_IN 3 #define DIR_IN (1 << 16) // Endpoint types in an endpoint context. Direction is part of the type, and // the numbering is not arbitrary: OUT types are 1-3, control is 4, and the IN // types are the OUT ones plus four. #define EPTYPE_ISOCH_OUT 1 #define EPTYPE_BULK_OUT 2 #define EPTYPE_INT_OUT 3 #define EPTYPE_CONTROL 4 #define EPTYPE_ISOCH_IN 5 #define EPTYPE_BULK_IN 6 #define EPTYPE_INT_IN 7 // Doorbell targets: 0 is the command ring; for a device slot, DCI 1 is EP0. #define DCI_EP0 1