4. USB主机控制器硬件:OHCI/UHCI/EHCI/xHCI规范对比、寄存器接口、DMA与周期调度

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): 事件环去队列指针。
四种USB主机控制器寄存器空间布局对比 OHCI 寄存器空间 偏移 0x00: HcRevision 偏移 0x04: HcControl 偏移 0x08: HcCommandStatus 偏移 0x0C: HcInterruptStatus 偏移 0x10: HcHCCA 偏移 0x18: HcPeriodCurrentED 偏移 0x40: HcRhDescriptorA ... 端口状态寄存器 UHCI 寄存器空间 偏移 0x00: USBCMD (16-bit) 偏移 0x02: USBSTS (16-bit) 偏移 0x04: USBINTR (16-bit) 偏移 0x06: FRNUM (16-bit) 偏移 0x08: FLBASEADD (32-bit) 偏移 0x0C: SOFMOD (8-bit) 偏移 0x10: PORTSC1 (16-bit) 偏移 0x12: PORTSC2 (16-bit) EHCI 寄存器空间 偏移 0x00: CAPLENGTH/HCIVERSION 偏移 0x10: HCSPARAMS 偏移 0x18: HCCPARAMS 操作寄存器起始: USBCMD, USBSTS, USBINTR FLISTBASE, ASYNCLISTADDR PORTSC[1..n] ... 64位扩展寄存器 xHCI 寄存器空间 偏移 0x00: CAPLENGTH/HCIVERSION 偏移 0x04: HCSPARAMS1 偏移 0x08: HCSPARAMS2 偏移 0x10: HCSPARAMS3 偏移 0x14: CAPSPARAMS 偏移 0x30: DCBAAP (64-bit) 偏移 0x38: CRCR (64-bit) 偏移 0x48: ERSTSZ/ERSTBA/ERDP 寄存器布局设计差异总结 1. OHCI:所有寄存器32位,HcHCCA指向主存中的通信区,硬件写回完成状态。 2. UHCI:寄存器以16位为主,帧列表基址寄存器(FLBASEADD)指向软件维护的帧列表。 3. EHCI:引入能力寄存器结构,操作寄存器起始偏移由CAPLENGTH决定,支持64位寻址。 4. xHCI:完全基于上下文和环(Ring)结构,寄存器数量最少,但每个寄存器功能高度抽象。 5. 驱动初始化时,必须首先读取CAPLENGTH/HCIVERSION,然后计算操作寄存器基址。 6. xHCI的DCBAAP和CRCR是64位指针,需要两个32位寄存器组合读取。

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)向驱动报告完成状态。

xHCI 环(Ring)结构示意图 命令环 (Command Ring) CRCR (Command Ring Control Register) 包含: 命令TRB (CMD_TRB) 驱动写入: 地址设备、配置端点等 硬件消费: 从环头取出TRB执行 传输环 (Transfer Ring) 每个端点一个传输环 包含: 普通TRB, 数据TRB, 状态TRB 驱动写入: 要发送/接收的数据描述 硬件消费: DMA传输数据 事件环 (Event Ring) ERST (Event Ring Segment Table) 包含: 事件TRB (EVT_TRB) 硬件写入: 传输完成、错误、端口事件 驱动消费: 从环尾读取事件TRB 环结构关键特性 1. 环是循环缓冲区:TRB按顺序排列,硬件通过“生产者-消费者”模型推进环指针。 2. 每个环有一个“环段表”(Ring Segment Table),支持跨物理页的环扩展。 3. 命令环和传输环由驱动写入TRB,硬件消费;事件环由硬件写入TRB,驱动消费。 4. TRB类型包括:普通TRB(Normal)、设置TRB(Setup)、数据TRB(Data)、状态TRB(Status)、 链接TRB(Link,用于环段跳转)、事件TRB(Transfer Event、Command Completion Event等)。 5. 驱动通过写DOORBELL寄存器通知硬件有新的TRB需要处理,硬件自动从环中取出TRB执行。

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的调度是事件驱动的,而非轮询驱动。
EHCI 周期调度与异步调度流程图 帧列表 Frame 0 Frame 1 ... Frame 1023 每帧1ms 每个帧条目 指向一个 微帧列表 (8个微帧) 微帧列表 uFrame 0 uFrame 1 ... uFrame 7 每微帧125µs 每个微帧条目 指向一个QH链表 周期QH链表 QH (中断端点1) QH (中断端点2) QH (等时端点1) ... 每个QH包含 一个qTD链表 ← 上一章 📖 返回目录 下一章 →