4.9 TRB Ring
TRB(Transfer Request Block) Ring是一个TRB数据结构的环状队列,TRB Ring用来在producer和consumer之间传送工作项(Work Item)。和其相关的有两个指针,出队指针(Dequeue)和入队指针(Enqueue)。一个工作项由一个或多个TRB数据结构组成。一个工作项定义了一个将要被执行的操作或是一个已经执行的操作的结果。
有三种基本TRB Rings:Transfer,Event和Command。每种Ring都有其专用的TRB数据结构。但他们都是使用底层的TRB Ring机制来组织工作项和基本TRB模版。
Transfer Rings提供来自或是到USB设备的数据传输。Transfer Rings和USB Pipes之间有个一对一的映射关系。这是通过设备上下文中的端口上下文数据结构(或者端口上下文指向的流上下文数组)定义的。
Event Rings为xHCI提供向系统软件报告的方式,报告的内容包括:数据传输和命令完成状态,root hub port状态改变,和其他xHCI相关的事件。一个Event Ring通过Runtime Registers中的Event Ring Segment Table Base Address,Segment Table Size和Dequeue Pointer Registers来定义。
Command Ring为系统软件提供发送命令来枚举USB设备,配置xHCI支持设备,以及协调虚拟化功能的能力。Command Ring由Operational register中的Command Ring Control Register来支持。
Enqueue pointer和Dequeue pointer是用来标志一个TRB Ring中的逻辑开始和结束的。TRB Ring的size由组成ring的segment的数量和大小决定的。Enqueue Pointer是R下一个Producer可用的Ring中的TRB地址,Producer从这位置创建一个新的工作项,然后将这个指针前移。Dequeue则是Consumer将要使用的TRB的地址。当Dequeue Pointer等于Enqueue pointer时,TRB Ring就是空的了。如果Enqueue pointer+1=Dequeue pointer,那么这个ring就是满的。在Enqueue Pointer-1和Dequeue Pointer之间的TRBs由Consumer拥有使用权。其他的TRBs就是Producer拥有使用权。每当这两个指针改变之后,那么TRB所有权就会发生转换。Consumer需要按序执行TRB。所有TRB都是16Bytes的大小。TRB Rings可能会比一个Page大,但是他们不能越过64K的界限(详见4.11.5.1)。
初始化,也就是当TRB ring在内存中创建或者如果它每次被重新初始化时,Ring中所有TRBs都需要被清“0”。这个状态表示一个空的队列。
注意:Transfer和Command Ring中的出入队指针并没有定义相应的物理xHCI寄存器,但是Event Ring定义了。
4.9.1 Transfer Descriptors
一个TD中包含一个或多个TRBs。TRB Chain (C) bit在所有TRB中都有设置,但是每个TD的最后一个TRB不会设置。xHCI可以为与一个TD相关的所有packets安排Max Packet Size USB 事务,可能除了最后一个packet(如果这个TD没有定义一个整数个的Max Packet Size data bytes)。
为生成一个0长度的USB事务,软件应该精确的定义一个只有一个TRB的TD,并且它的TRB Transfer Length字段应该等于0。注意这个TD可以包含non-Transfer TRBs,比如Event Data或者Link TRB。
在这个协议中有许多关于xHC应该“前移到下一个TD”的条件描述。但是,如果xHC在这些情况之一发生时正在处理一个TD的一个部分(a partially formed TD),则不可能前进到下一个TD,并且当到达Enqueue Pointer时xHC将停止前进。在这种情形下,xHC认为Transfer Ring是空的即两个指针相等,接着当下一次doorbell为端点Rung,xHC应该尝试去进入下一个TD的范围。注意xHC应该通过一个Set TR Dequeue Pointer Command来说明新的TR Dequeue Pointer。
“部分完成的TD”通过以下情况来标识:Dequeue pointer引用的TRB中的Chain bit(CH)设置为“1”,并推进Dequeue将其设置为等于Enqueue Pointer。
注意: Command和Event TRBs并不支持Chain bit(CH),因此所有的Command Descriptors (CDs)和Event Descriptor (EDs)只有单个TRB构成。(后面还有两个note)
4.9.2 Transfer Ring Management
这节描述Transfer Ring中Enqueue和Dequeue pointer的操作。如图所示,如表示一个Transfer Ring。Producer(host)在Enqueue Pointer将item放入Transfer Ring,Consummer(xHC)在Dequeue Pointer把item取出。TRB中的Cycle bit字段标识了Transfer Ring中的Enqueue Pointer中的位置。消除了使用寄存器来定义。
软件使用并且维持对于各个Transfer Ring的Enqueue和Dequeue pointer的副本。在Transfer ring初始setup时,Enqueue和Dequeue Pointers对于每个Transfer Ring都是设置为第一个TRB的地址,并且写入Endpoint/Stream Context TR Dequeue Pointer 字段。软件通过增加其大小每次增加一个TRB size或在遇到链接TRB时将其与环形段指针字段的值重新加载来推进其Enqueue pointer的副本。
xHC同样对每个Transfer Ring维持着自己对于这两个指针的副本。当一个Transfer Ring被启用或被重置,xHC使用Endpoint/Stream Context TR Dequeue Pointer Filed来更新这两个副本。xHC使用Dequeue Pointer来决定从Transfer Ring的哪儿拿取下一个work Item。xHC更新Dequeue Pointer的方式和软件的更新方式一样。
xHC使用Enqueue Pointer来确定什么时候Transfer Ring是空的。当它从一个Tansfer Ring取出TRBs时,它会检测是否有一个Cycle bit事务。如果一个事务被检测到,ring就是空的了。
而反过来,Software使用Dequeue pointer确定什么时候Transfer ring是满的。当他处理tansfer Events,它使用Transfer Event TRB Pointer 字段来更新它自身维持的Dequeue Pointer。如果当前移Enqueue Pointer时使得它等与Dequeue Pointer那么表明Transfer Ring就是满的。
Producer将要保持一个Producer Cycle State(PCS)flag用于标识它应该写入TRB Cycle bit的值。Consumer维持一个Consumer Cycle State(CCS)flag,它用此flag来和它取出的TRB中Cycle bit进行比较。如果CCS flag等于TRB Cycle bit的值,那么Consumer将获得此TRB(Dequeue Pointer指向的)的

本文详细解释了TRB Ring在USB设备通信、xHCI事件传递和命令处理中的角色,涉及Transfer、Event和Command Ring的工作原理、数据结构、指针操作及动态调整。讲解了Enqueue/Dequeue Pointer的管理,TRB状态转换,以及如何调整Ring大小以适应内存分配。
最低0.47元/天 解锁文章
8010

被折叠的 条评论
为什么被折叠?



