2. UHCI 主控制器寄存器模型详解
UHCI(Universal Host Controller Interface)主控制器通过一组 PCI 基地址寄存器(Base Address Register, BAR) 映射到系统内存或 I/O 空间。驱动开发者必须精确理解每个寄存器的位定义、访问时序和复位状态,才能正确初始化控制器、调度传输帧和处理中断。本节将逐一剖析 UHCI 寄存器布局中的关键寄存器。
2.1 寄存器整体布局与基地址
UHCI 主控制器占用 32 字节连续的 I/O 空间(或内存映射空间),起始地址由 PCI 配置空间中的 BAR0 提供。驱动在枚举 PCI 设备时读取 BAR0,获取基地址后即可通过 inl/outl(I/O 空间)或 ioread32/iowrite32(内存映射)访问所有寄存器。
| 偏移地址 | 寄存器名称 | 缩写 | 复位值 | 主要功能 |
|---|---|---|---|---|
| 0x00 | USB 命令寄存器 | USBCMD | 0x0000 0020 | 启动/停止主机控制器、全局复位、帧列表大小配置 |
| 0x02 | USB 状态寄存器 | USBSTS | 0x0000 0000 | 主机控制器当前状态、中断挂起、错误指示 |
| 0x04 | USB 中断使能寄存器 | USBINTR | 0x0000 0000 | 使能/屏蔽各类中断源 |
| 0x06 | 帧号寄存器 | FRNUM | 0x0000 0000 | 当前帧号(0~1023),每 1 ms 递增 |
| 0x08 | 帧列表基地址寄存器 | FLBASEADD | 0x0000 0000 | 帧列表在系统内存中的 4 KB 对齐基地址 |
| 0x0C | 起始帧修正寄存器 | SOF | 0x0000 0040 | 调整 SOF 包发送时机,微调帧起始位置 |
| 0x10–0x1F | 端口状态与控制寄存器 | PORTSC[0..1] | 0x0000 0080 | 每个端口一个,控制连接检测、复位、使能、挂起 |
lspci -vvv -s <bus:dev.func> 查看 UHCI 控制器的 BAR0 地址,然后通过 cat /proc/ioports 确认 I/O 空间是否已被 uhci_hcd 驱动占用。
2.2 USBCMD — USB 命令寄存器(偏移 0x00)
USBCMD 是驱动控制主机控制器的核心寄存器。驱动通过写入该寄存器启动/停止控制器、触发全局复位、配置帧列表大小。
| 位域 | 名称 | 描述 |
|---|---|---|
| Bit 0 | RS (Run/Stop) | 1 = 运行;0 = 停止。停止后控制器不再处理帧列表。 |
| Bit 1 | HCRESET (Host Controller Reset) | 写 1 触发软件复位,复位后自动清零。复位所有寄存器(除 FLBASEADD 和 SOF 外)到默认值。 |
| Bit 2 | GRESET (Global Reset) | 写 1 触发 USB 总线全局复位(至少 10 ms),复位后自动清零。 |
| Bit 3 | EGSM (Enter Global Suspend Mode) | 1 = 进入全局挂起模式;0 = 正常。用于电源管理。 |
| Bit 4 | FGR (Force Global Resume) | 写 1 强制全局恢复,用于从挂起中唤醒。 |
| Bit 5 | SWDBG (Software Debug) | 1 = 使能软件调试模式(保留位,建议写 0)。 |
| Bit 6 | CF (Configure Flag) | 驱动配置完成后置 1,表示端口路由逻辑已配置。主机控制器据此开始处理端口事件。 |
| Bit 7 | MAXP (Max Packet) | 0 = 64 字节;1 = 32 字节。控制批量/中断传输的最大包长。 |
2.3 USBSTS — USB 状态寄存器(偏移 0x02)
USBSTS 反映主机控制器的实时状态和中断事件。驱动在中断服务例程(ISR)中读取该寄存器判断中断原因,并在处理完成后写 1 清除对应位。
| 位域 | 名称 | 描述 |
|---|---|---|
| Bit 0 | UI (USB Interrupt) | 1 = 有中断挂起。由 USBINTR 使能的中断源触发。 |
| Bit 1 | UEI (USB Error Interrupt) | 1 = 发生传输错误(如 CRC、超时、Babble)。 |
| Bit 2 | PCI (Port Change Interrupt) | 1 = 端口状态发生变化(连接/断开/使能/挂起改变)。 |
| Bit 3 | RI (Resume Interrupt) | 1 = 检测到远程唤醒信号。 |
| Bit 4 | HCH (Host Controller Halted) | 1 = 控制器已停止(RS=0 且内部状态机空闲)。 |
| Bit 5 | HCPE (Host Controller Process Error) | 1 = 主机控制器内部处理错误(通常不可恢复)。 |
| Bit 6–15 | Reserved | 保留位,读返回 0。 |
uhci_irq() 函数正是采用此模式。
2.4 USBINTR — 中断使能寄存器(偏移 0x04)
USBINTR 控制哪些 USBSTS 状态位能够产生中断信号。驱动在初始化阶段根据需求使能对应中断源。
| 位域 | 名称 | 对应 USBSTS 位 | 描述 |
|---|---|---|---|
| Bit 0 | IUE (Interrupt Enable) | UI | 使能传输完成中断 |
| Bit 1 | IE (Error Interrupt Enable) | UEI | 使能传输错误中断 |
| Bit 2 | IPC (Port Change Interrupt Enable) | PCI | 使能端口变化中断 |
| Bit 3 | IR (Resume Interrupt Enable) | RI | 使能远程唤醒中断 |
| Bit 4–15 | Reserved | — | 保留位,写 0 |
2.5 FRNUM — 帧号寄存器(偏移 0x06)
FRNUM 是一个 10 位计数器(Bit 0–9),每 1 ms 递增一次,值范围 0–1023。主机控制器使用帧号索引帧列表,决定当前帧要处理的传输描述符链表。
- 只读属性: 驱动只能读取 FRNUM,不能写入。写入操作被硬件忽略。
- 与帧列表的关系: 帧列表包含 1024 个表项,FRNUM 的低 10 位作为索引,选择当前帧对应的帧列表项。
- 调试用途: 驱动可通过轮询 FRNUM 判断帧是否推进,验证控制器是否正常运行。如果 FRNUM 长时间不变,说明控制器可能挂起或未启动。
2.6 FLBASEADD — 帧列表基地址寄存器(偏移 0x08)
FLBASEADD 存储帧列表在系统物理内存中的起始地址。帧列表必须 4 KB 对齐(即地址低 12 位为 0),因为帧列表包含 1024 个 4 字节的表项,正好占用 4 KB。
| 位域 | 描述 |
|---|---|
| Bit 31:12 | 帧列表基地址(高 20 位),对应物理地址的 [31:12] |
| Bit 11:0 | 保留位,必须写 0。硬件忽略低 12 位,强制 4 KB 对齐。 |
dma_alloc_coherent() 分配,确保物理地址连续且不被 CPU 缓存干扰。在 32 位系统上,地址可能超过 4 GB,需确认 DMA 掩码设置正确。
2.7 SOF — 起始帧修正寄存器(偏移 0x0C)
SOF 寄存器用于微调 SOF(Start of Frame)包的发送时机。UHCI 规范要求每帧开始时发送 SOF 包,但不同 USB 总线拓扑可能导致传播延迟差异。SOF 寄存器允许驱动调整 SOF 包的发送偏移量。
| 位域 | 描述 |
|---|---|
| Bit 7:0 | SOF 修正值(SOF Timing Value),单位是位时间(bit time)。默认值 0x40(64 位时间)。 |
| Bit 15:8 | 保留位,写 0。 |
- 默认值: 0x40(64 位时间)对应约 2.67 µs(USB 全速 12 Mbps,每位 83.3 ns)。
- 调整场景: 当 USB 总线过长或级联集线器过多时,可适当增大 SOF 修正值,确保下游设备有足够时间准备接收数据。
- 调试建议: 在批量传输出现间歇性超时时,尝试调整 SOF 值(如 0x50 或 0x60)可能改善时序裕量。
2.8 PORTSC — 端口状态与控制寄存器(偏移 0x10–0x1F)
每个 UHCI 控制器最多支持 2 个端口,每个端口对应一个 PORTSC 寄存器,偏移地址分别为 0x10 和 0x12。PORTSC 是驱动与物理 USB 端口交互的主要接口。
| 位域 | 名称 | 描述 |
|---|---|---|
| Bit 0 | CCS (Current Connect Status) | 1 = 设备已连接;0 = 未连接。只读。 |
| Bit 1 | CSC (Connect Status Change) | 1 = 连接状态发生变化。写 1 清除。 |
| Bit 2 | PE (Port Enable) | 1 = 端口使能;0 = 端口禁用。驱动写 1 使能,写 0 禁用。 |
| Bit 3 | PEC (Port Enable Change) | 1 = 端口使能状态发生变化。写 1 清除。 |
| Bit 4 | OC (Over Current) | 1 = 过流事件发生。只读。 |
| Bit 5 | OCC (Over Current Change) | 1 = 过流状态变化。写 1 清除。 |
| Bit 6 | PR (Port Reset) | 写 1 触发端口复位,至少保持 10 ms 后写 0 结束复位。 |
| Bit 7 | SUSP (Suspend) | 1 = 端口挂起;0 = 正常。驱动写 1 进入挂起,写 0 恢复。 |
| Bit 8 | RD (Resume Detect) | 1 = 检测到远程唤醒信号。写 1 清除。 |
| Bit 9–15 | Reserved | 保留位,读返回 0。 |
- 检测 CCS 位,确认设备连接。
- 写 PR=1 触发端口复位,等待 10 ms 后写 PR=0。
- 写 PE=1 使能端口。
- 读取 PE 确认使能成功,然后开始地址分配和配置。