3. xHCI控制器硬件架构:寄存器布局与能力寄存器详解
xHCI(eXtensible Host Controller Interface)控制器的硬件寄存器布局遵循PCIe设备的标准BAR空间映射方式。在系统软件(如Linux内核驱动)对xHCI控制器进行初始化、设备枚举、中断处理等操作之前,必须首先理解其寄存器布局的基地址计算规则以及能力寄存器(Capability Registers)所暴露的硬件特性。本节将深入剖析xHCI寄存器布局的起始点——CAPLENGTH,以及三个核心能力寄存器:HCSPARAMS1、HCSPARAMS2和HCCPARAMS。
3.1 xHCI寄存器布局总览
xHCI控制器的寄存器空间被划分为两个主要区域:能力寄存器(Capability Registers)和操作寄存器(Operational Registers)。能力寄存器区域从PCIe BAR0的基地址开始,其布局是固定的,用于描述控制器的版本、结构参数和功能支持。操作寄存器区域则通过能力寄存器中的CAPLENGTH字段计算偏移量得到。
3.2 CAPLENGTH寄存器详解
CAPLENGTH寄存器位于能力寄存器区域的起始偏移0x00处,是一个8位寄存器。它定义了从能力寄存器基地址到操作寄存器基地址的字节偏移量。根据xHCI规范,这个值通常为0x20(32字节),但驱动必须动态读取,不能硬编码。
| 字段 | 位宽 | 偏移 | 描述 |
|---|---|---|---|
| CAPLENGTH | 8位 | 0x00 | 操作寄存器的起始偏移量(相对于BAR0基地址)。典型值为0x20。 |
| HCIVERSION | 16位 | 0x02 | xHCI控制器实现的接口版本号。例如,1.0版本为0x0100,1.1版本为0x0110。 |
drivers/usb/host/xhci.c 中,函数 xhci_gen_setup() 会首先读取CAPLENGTH和HCIVERSION,以验证控制器版本并计算操作寄存器基地址。代码片段如下:
/* 读取CAPLENGTH和HCIVERSION */
u8 cap_length = readb(hcd->regs + 0x00);
u16 hci_version = readw(hcd->regs + 0x02);
/* 计算操作寄存器基地址 */
xhci->op_regs = hcd->regs + cap_length;
/* 检查版本 */
if (hci_version < 0x0100) {
dev_err(&pdev->dev, "xHCI version %x not supported\n", hci_version);
return -ENODEV;
}
3.3 HCSPARAMS1寄存器详解
HCSPARAMS1(Host Controller Structural Parameters 1)寄存器位于偏移0x04处,是一个32位寄存器。它描述了控制器的基本结构参数,包括端口数量、中断线数量等。
| 位域 | 位范围 | 描述 |
|---|---|---|
| Max Ports | [31:24] | 控制器支持的USB端口总数(包括USB 2.0和USB 3.0端口)。 |
| Max Intrs | [23:8] | 控制器支持的中断器(Interrupter)数量。每个中断器对应一个中断向量。 |
| Max Slots | [7:0] | 控制器支持的设备槽位(Device Slot)数量。每个连接的USB设备占用一个槽位。 |
3.4 HCSPARAMS2寄存器详解
HCSPARAMS2(Host Controller Structural Parameters 2)寄存器位于偏移0x08处,也是一个32位寄存器。它提供了关于控制器内部结构更详细的参数,如事件环段大小、最大SCRatchpad缓冲区数量等。
| 位域 | 位范围 | 描述 |
|---|---|---|
| Max Scratchpad Buffers | [31:27] | 控制器支持的Scratchpad缓冲区数量。Scratchpad用于控制器内部管理,驱动必须为其分配内存。 |
| Max Event Ring Segment Count | [26:24] | 每个中断器支持的最大事件环段数量。值为0表示1个段,值为1表示2个段,以此类推。 |
| Max Primary Stream Array Size | [23:16] | 每个端点支持的最大主流数组大小。用于流式传输(Streaming)功能。 |
| Isochronous Scheduling Threshold | [7:4] | 等时调度阈值,表示控制器在调度等时传输时需要的提前量。 |
| Event Ring Segment Table Max | [3:0] | 事件环段表的最大索引值。 |
3.5 HCCPARAMS寄存器详解
HCCPARAMS(Host Controller Capability Parameters)寄存器位于偏移0x10处,是一个32位寄存器。它定义了控制器支持的高级功能特性,是驱动进行功能协商和初始化策略选择的关键依据。
| 位域 | 位范围 | 描述 |
|---|---|---|
| AC64 | [0] | 64位寻址能力。如果置1,控制器支持64位地址(使用高32位地址寄存器)。 |
| BNC | [1] | 带宽协商能力。如果置1,控制器支持带宽协商。 |
| CSZ | [2] | 上下文大小。如果置1,上下文结构大小为64字节;否则为32字节。 |
| PPC | [3] | 端口电源控制。如果置1,控制器支持端口电源独立控制。 |
| PIND | [4] | 端口指示器。如果置1,控制器支持端口LED指示。 |
| LHRC | [5] | Light Host Reset能力。如果置1,控制器支持轻量级主机复位。 |
| LTC | [6] | 延迟容忍度消息能力。如果置1,控制器支持延迟容忍度报告。 |
| NSS | [7] | 非标准速度能力。如果置1,控制器支持非标准USB速度。 |
| PAE | [8] | 每端口AER(Advanced Error Reporting)能力。 |
| SPR | [9] | Stall Prevention能力。 |
| SEC | [10] | 安全能力。 |
| CFC | [11] | 控制流控制能力。 |
| Max Primary Stream Array Size | [15:12] | 主流数组大小的最大值(与HCSPARAMS2中的字段配合使用)。 |
| XECP | [31:16] | 扩展能力指针(Extended Capabilities Pointer)。指向能力寄存器区域中扩展能力列表的起始偏移。 |
CTX_SIZE(xhci) 宏来动态获取上下文大小。另外,XECP字段用于遍历xHCI的扩展能力列表(如USB Legacy Support、Supported Protocol等),这是驱动识别USB 3.0端口和USB 2.0端口的关键。
3.6 能力寄存器在驱动初始化中的典型使用流程
在Linux xHCI驱动中,能力寄存器的读取是初始化流程的第一步。以下是一个典型的初始化序列:
- 读取CAPLENGTH和HCIVERSION:验证控制器版本,计算操作寄存器基地址。
- 读取HCSPARAMS1:获取Max Ports、Max Slots、Max Intrs,用于分配数据结构。
- 读取HCSPARAMS2:获取Max Scratchpad Buffers,决定是否需要分配Scratchpad缓冲区。
- 读取HCCPARAMS:检查AC64位决定是否启用64位DMA;检查CSZ位决定上下文结构体大小;读取XECP字段准备遍历扩展能力列表。
- 遍历扩展能力列表:通过XECP指针找到Supported Protocol能力,识别USB 2.0和USB 3.0端口映射。
drivers/usb/host/xhci-mem.c 中,函数 xhci_mem_init() 会基于HCSPARAMS1中的Max Slots值分配设备上下文数组,基于Max Intrs值分配中断器数组。而 xhci_gen_setup() 中会调用 xhci_readl() 读取HCCPARAMS并解析XECP。