PS 咸鱼中有很多全新,性价比高的开发板,感兴趣的可以去瞧一瞧。
上一篇介绍了UHCI,这一篇继续来介绍OHCI, OHCI和UHCI都是针对USB1.x, 但是其实现思路侧重点不一样。两个标准并存导致了一些兼容问题,所以在USB2.0之后就统一了,后续只使用Intel的实现。
OHCI (Open Host Controller Interface)由Compaq,Microsoft,National Semiconductor开发,它将更多负担放在了硬件上,而软件更简单. 规格书见:http://www.o3one.org/hwdocs/usb/hcir1_0a.pdf
拓扑结构如下
OHCI驱动 <> OHCI标准 <> OHCI 控制器
内存映射寄存器
共享内存链表
OHCI控制器提供OHCi标准对应的内存映射寄存器,OHCI驱动配置对应的寄存器,并按照共享内存链表要求配置对应的链表,将链表的基地址配置到对应的寄存器中。
OHCI控制器就去遍历对应的链表根据描述符执行对应的动作,处理完后将链表放置到完成链表,驱动去判断完成链表状态即可。
从上可以看出软件的工作比较简单,只需要准备链表即可,硬件要完成链表遍历处理,处理完放置到完成链表等一系列工作,硬件的设计会更复杂。
整体框架如下
一共21个,通过PCI总线的BAR0暴露。
Offset (Hex) | Name |
00 | HcRevision |
04 | HcControl |
08 | HcCommandStatus |
0c | HcInterruptStatus |
10 | HcInterruptEnable |
14 | HcInterruptDisable |
18 | HcHCCA |
1c | HcPeriodCurrentED |
20 | HcControlHeadED |
24 | HcControlCurrentED |
28 | HcBulkHeadED |
2c | HcBulkCurrentED |
30 | HcDoneHead |
34 | HcFmInterval |
38 | HcFmRemaining |
3c | HcFmNumber |
40 | HcPeriodicStart |
44 | HcLSThreshold |
48 | HcRhDescriptorA |
4c | HcRhDescriptorB |
50 | HcRhStatus |
从偏移量54h开始,根集线器上的每个USB端口被分配一个HcRhPortStatus寄存器,该寄存器表示端口的当前状态。
上述寄存器在内存中的映射基地址不是固定的,可以位于任何32位地址,只需要按照上述排布即可。怎么找到基地址呢,PCI总线可以搜索特定的供应商/设备vendor/device id,或特定的Class ID来查找任何OHCI控制器,如下:
所有OHCI控制器的Class ID =0x0Ch, subclass = 0x03h, program interface=0x10h。PCI设备配置区域包含指向内存映射寄存器块的单个基址。
所有给控制器的命令和数据包,都通过包含表和链表的共享内存区域提供。
USB协议定义了4种不同的消息类型:中断、同步、控制和批量。
每种消息类型都有自己的传出消息链表。
当控制器处理这些消息时,它们被移动到相应的“完成”列表中,同时还有关于控制器在传递消息时遇到的错误信息。
控制消息用于初始化和配置HUB检测到的设备。未初始化的设备将不响应任何控制消息。要初始化设备,必须复位设备所连接的HUB端口。复位后,设备将默认为地址0,并将开始响应发送到该地址的任何控制消息。确保一次只能有一个设备被初始化,一旦设备的端口被复位,应该立即发送一个SetAddress命令来分配一个1到127之间未使用的地址给设备。一旦这个命令被发送,设备将开始响应它的新地址,不再响应地址0。
HcControlHead寄存器指向端点描述符链表中的第一个控制端点描述符(ED)。每个端点描述符描述USB总线上可以由操作系统通信的一个端点。为了从端点发送或接收数据,操作系统将传输描述符添加到端点描述符中。一旦数据传输完成,控制器将把传输描述符从端点描述符移动到完成队列。
每个端点描述符都有一个“头”传输描述符字段和一个“尾”传输描述符字段,以及一个“next”端点描述符字段。端点描述符链中的最后一个端点描述符的“next”端点描述符值将为零。当“头”传输描述符与“尾”传输描述符匹配时,端点描述符为空,不再发送数据。
HcControlHead列表中的端点描述符只能用于与控制端点通信。所有设备都有一个用于配置设备的控制端点0。
HcBulkHeadED寄存器指向批量端点描述符列表中的第一个批量端点描述符,用于发送和接收批量数据包。它在功能上与HcControlHead寄存器相同。
注意这里的端点描述符和传输描述符不是设备枚举过程中设备返回的描述符.
这里的描述符是内存中用于给控制器使用的信息。
端点描述符是一种内存结构,其中包含用于与特定设备地址上的特定端点通信的信息。
Offset (Hex) | Name |
00 | Control |
04 | Tail TD Address |
08 | Head TD Address |
0c | Next ED Address |
传输描述符,描述要发送到USB端点(非同步)要读出的缓冲区,或者从USB端点读到数据要存入的缓存区。
同步端点使用不同的描述符结构。
Offset (Hex) | Name |
00 | Control |
04 | First Byte Address |
08 | Next TD Address |
0c | Last Byte Address |
ED和TD的结构如下
ED组成链表,ED下可以挂多个TD
OHCI的特点是软件实现更简单,硬件更复杂,软件只需要准备ED,TD,大部分工作由硬件根据描述符自行去处理。