4. USB主机控制器硬件
USB主机控制器(Host Controller)是USB系统中连接软件栈与物理总线的硬件引擎。从USB 1.x到USB 3.x,先后出现了OHCI、UHCI、EHCI和xHCI四种规范。理解它们的硬件架构、寄存器模型、DMA机制和调度策略,是编写稳定、高性能USB主机驱动的基石。
学习提示:本章重点不是死记寄存器偏移地址,而是掌握四种控制器的设计哲学差异——OHCI/UHCI面向USB 1.x全/低速,EHCI面向USB 2.0高速,xHCI统一所有速度并引入可扩展事件环。这些差异直接决定了驱动中初始化、传输管理和中断处理的代码结构。
4.1 四种主机控制器规范概览
USB主机控制器规范由Intel、Microsoft、NEC等公司共同制定,按出现时间和支持速率可分为四代:
| 规范 | 全称 | 主导方 | 支持速率 | 首次发布 | 典型硬件 |
|---|---|---|---|---|---|
| OHCI | Open Host Controller Interface | Compaq/Microsoft/NEC | USB 1.x Full/Low Speed (1.5/12 Mbps) | 1996 | 非Intel芯片组(如VIA、SiS) |
| UHCI | Universal Host Controller Interface | Intel | USB 1.x Full/Low Speed (1.5/12 Mbps) | 1996 | Intel PIIX4及之后南桥 |
| EHCI | Enhanced Host Controller Interface | Intel | USB 2.0 High Speed (480 Mbps) | 2000 | ICH5/ICH6/ICH7等南桥 |
| xHCI | eXtensible Host Controller Interface | Intel | USB 3.x SuperSpeed (5/10/20 Gbps) + 向下兼容 | 2008 | Intel 7系列及之后、AMD、ASMedia |
关键差异:OHCI与UHCI虽然都支持USB 1.x,但OHCI将更多调度逻辑固化在硬件中(硬件管理帧列表和中断列表),驱动负担较轻;UHCI则将调度决策交给软件(驱动维护帧列表和队列头),硬件只做简单的帧起始(SOF)触发。EHCI在USB 2.0时代引入高速模式,但必须搭配一个“companion controller”(OHCI或UHCI)来兼容全/低速设备。xHCI彻底统一了所有速度等级,不再需要companion控制器。
4.2 寄存器接口对比
每种控制器规范都定义了一套标准的MMIO(Memory-Mapped I/O)寄存器接口。驱动通过操作这些寄存器完成初始化、中断控制、传输触发和状态查询。
4.2.1 寄存器空间布局
四种控制器的寄存器布局均以能力寄存器(Capability Registers)开头,后接操作寄存器(Operational Registers)。但具体偏移和字段含义差异很大:
| 寄存器类别 | OHCI | UHCI | EHCI | xHCI |
|---|---|---|---|---|
| 基地址获取 | PCI BAR 0 | PCI BAR 0/1 | PCI BAR 0 | PCI BAR 0/1 |
| 能力寄存器起始 | 偏移0x00 | 无独立能力区 | 偏移0x00 | 偏移0x00 |
| 操作寄存器起始 | 偏移0x40 | 偏移0x00 | 由CAPLENGTH决定 | 由CAPLENGTH决定 |
| 帧列表基址 | HcFmNumber + HcFmInterval | SOF定时器寄存器 | FLISTBASE(Frame List Base Address) | 无帧列表(使用事件环) |
| 端口状态控制 | HcRhPortStatus[1..n] | 端口SC1/SC2 | PORTSC[1..n] | PORTSC[1..n] |
| 中断寄存器 | HcInterruptStatus/Enable | USBSTS/USBINTR | USBSTS/USBINTR | ERSTSZ + ERDP + IMAN |
驱动开发注意:UHCI的寄存器是8/16位混合访问,且端口寄存器与帧定时器紧密耦合;OHCI的寄存器全部32位对齐;EHCI和xHCI的寄存器以32位为主,但xHCI引入了64位地址支持(寄存器对)。在Linux内核中,这些差异通过不同的
hc_driver结构体封装,驱动开发者通常不需要直接操作原始寄存器,但理解映射关系对调试DMA错误至关重要。
4.2.2 关键寄存器功能对比
以下列出每种控制器中驱动最常访问的寄存器及其作用:
- OHCI:
HcControl(0x04): 控制HCFS(主机控制器功能状态)、PLE(周期列表启用)、CLE(控制列表启用)、BLE(批量列表启用)。HcCommandStatus(0x08): 写HCR(主机控制器复位)、SOC(调度超时计数)。HcInterruptStatus(0x0C): 读清除中断源,写屏蔽位。HcHCCA(0x10): 主机控制器通信区(Host Controller Communication Area)物理地址,用于硬件写回完成状态。
- UHCI:
USBCMD(0x00): 运行/停止位(RS)、主机控制器复位(HCRESET)、全局复位(GRESET)、帧列表大小(FREG)。USBSTS(0x02): 主机控制器挂起(HCHalted)、中断标志(INT)、错误标志(ERR)。USBINTR(0x04): 中断使能位。SOFMOD(0x0C): 帧起始调节值。
- EHCI:
USBCMD(0x00): 运行/停止(RS)、异步列表使能(ASE)、周期列表使能(PSE)、帧列表大小(FS[1:0])。USBSTS(0x04): 异步调度状态(AS)、周期调度状态(PS)、端口改变检测(PCD)。FLISTBASE(0x18): 帧列表基地址(4K对齐)。ASYNCLISTADDR(0x1C): 异步列表(批量/控制)链表头物理地址。
- xHCI:
CAAP(0x14): 上下文数组基地址指针(64位)。DCBAAP(0x30): 设备上下文基地址数组指针。CRCR(0x38): 命令环控制寄存器(64位)。ERSTSZ(0x48): 事件环段表大小。ERSTBA(0x50): 事件环段表基地址。ERDP(0x58): 事件环去队列指针。
4.3 DMA与数据传输机制
所有USB主机控制器都使用DMA(Direct Memory Access)在主机内存与USB设备之间搬运数据,无需CPU逐字节干预。但不同规范在DMA描述符的组织方式上存在根本差异。
4.3.1 描述符结构对比
| 规范 | 基本DMA单元 | 描述符链组织 | 硬件遍历方式 | 完成通知 |
|---|---|---|---|---|
| OHCI | ED(Endpoint Descriptor)+ TD(Transfer Descriptor) | ED通过NextED指针形成链表;TD挂在ED的TD队列上 | 硬件遍历HCCA中的HccaFrameNumber,找到对应帧的ED列表 | TD完成后,硬件写回TD状态并产生中断 |
| UHCI | TD(Transfer Descriptor)+ QH(Queue Head) | 帧列表指向TD/QH链表;QH用于批量/控制,TD用于中断/等时 | 硬件每帧从帧列表基址开始遍历链表 | TD完成后,硬件设置TD状态位,软件轮询或中断 |
| EHCI | qTD(Queue Element Transfer Descriptor)+ QH(Queue Head) | QH组织成异步列表(批量/控制)和周期列表(中断/等时) | 硬件从ASYNCLISTADDR或周期列表开始遍历QH链 | qTD完成后,硬件写回状态并产生中断 |
| xHCI | TRB(Transfer Request Block) | TRB组织成环(Ring):命令环、传输环、事件环 | 硬件通过CRCR(命令环)和DCBAAP(设备上下文)找到传输环 | TRB完成后,硬件在事件环上产生事件TRB,驱动读取事件环 |
4.3.2 xHCI的环(Ring)结构详解
xHCI引入了革命性的“环”概念,取代了传统链表。每个端点(Endpoint)拥有一个独立的传输环(Transfer Ring),主机控制器通过一个命令环(Command Ring)接收驱动指令,通过事件环(Event Ring)向驱动报告完成状态。
4.4 周期调度(Periodic Scheduling)
USB总线是轮询式总线,主机控制器负责在每帧(或微帧)内为所有端点分配总线时间。等时(Isochronous)和中断(Interrupt)传输需要周期性的总线访问保证,而批量(Bulk)和控制(Control)传输在剩余时间中尽力而为。
4.4.1 帧与微帧结构
| 规范 | 帧周期 | 微帧数 | 帧列表大小 | 调度粒度 |
|---|---|---|---|---|
| OHCI | 1 ms | 1(无微帧) | 32 个帧条目 | 1 ms |
| UHCI | 1 ms | 1(无微帧) | 1024 个帧条目 | 1 ms |
| EHCI | 1 ms | 8(每125 µs一个微帧) | 1024 个帧条目(每个指向微帧列表) | 125 µs |
| xHCI | 1 ms(高速/全速/低速)或 125 µs(超高速) | 8(高速模式) | 无帧列表,使用中断端点上下文中的Interval字段 | 125 µs 或更细 |
4.4.2 调度算法对比
- OHCI 调度:硬件维护一个32条目的帧列表(Frame List),每帧硬件根据帧号索引到对应条目,然后遍历该条目指向的ED链表。ED链表分为周期列表(中断/等时)和控制/批量列表。硬件在每帧开始时先服务周期列表,剩余时间服务控制/批量列表。
- UHCI 调度:软件维护一个1024条目的帧列表,每帧硬件从帧列表基址读取一个指针,然后遍历该指针指向的TD/QH链表。软件负责在帧列表中安排不同端点的TD,实现带宽分配。UHCI的调度完全由软件控制,灵活性高但驱动复杂度大。
- EHCI 调度:硬件维护两个独立的调度列表:异步列表(Asynchronous List,用于批量/控制)和周期列表(Periodic List,用于中断/等时)。周期列表是一个1024条目的帧列表,每个条目指向一个微帧的QH链表。硬件在每微帧(125 µs)开始时先遍历周期列表,剩余时间遍历异步列表。
- xHCI 调度:不再使用帧列表。每个中断/等时端点在设备上下文中指定
bInterval字段(超高速为指数,高速/全速/低速为帧数)。硬件内部维护一个调度器,根据端点的Interval值计算下次服务时间,并在事件环上产生事件通知驱动。xHCI的调度是事件驱动的,而非轮询驱动。