EHCI r1.0
3.5 Queue Element Transfer Descriptor (qTD)
3.6 Queue Head
Transfer Overlay
a transaction working space, an execution cache for the transfer.
4.10 Managing Control/BulkInterrupt Transfers via Quque Heads
Host Controller Queue Head Traversal State Machine
- One QH for one endpoint
- Each qTD represents on or more bus transactions
- Software simply link qTDs to the QH and activate them
- Host controller will always find them if/when they are reachable
Fetch QH
QH can be referenced by ASYNCLISTADDR, or Next Link Pointer field of an iTD, siTD, FSTN, or another QH.
- empty schedule detection
- The QH is not an interrupt QH
- QH.[H] is a one
- USBSTS.[Reclamation] is a zero
- Nak Counter reloads
- find next qTD
- if [Bytes to Transfer] is not zero and [Alternate Next qTD Pointer].[T] is set to zero, => use [Alternate Next qTD Pointer]
- else if [Next qTD Pointer].[T] is set to zero => use [Next qTD Pointer]
- else exit this state and follow [QH Horizontal Pointer]
- adjust pointers
- if the qTD.[Status].[Active] is a one => move the pointer to [Current qTD Pointer]
- else exit this state and follow [QH Horizontal Pointer]
- if the qTD.[Status].[Active] is a one => move the pointer to [Current qTD Pointer]
- perform the overlay
- QH.[dt] = (QH.[dtc]) ? (new qTD.[dtc]) : (QH.[dt])
- if QH.[EPS] indicate high-speed(10b) => QH.[Status].[Ping] preserved
- QH.[C-prog-mask] is set to zero
- QH.[Frame Tag] is set to zero
- QH.[NakCnt] = QH.[RL]
- All other areas of the overlay are set by the incoming qTD
- write back the result to QH
Write Back qTD (aka qTD Retirement)
write (transfer results area) of the (QH overlay area) to qTD pointed by QH.[Current qTD Pointer]
Follow QH Horizontal Pointer
4.10.6 Buffer Pointer List Use fro Data Streaming with qTD
virtually contiguous
The buffer is actually a continuous buffer, maximum 20KB(only when the buffer start on 4K boundary), but there are 5 buffer pointer to assign.
- the 1st buffer pointer could begin with a offset in a page
- the rest buffer pointers should be the next 4K boundary following the 1st buffer pointer
我的理解
一個endpoint一個QH,QH裡有一個Overlay,基本上就是個cache,是一個目前正在處理的qTD的複製(又不完全是, ref Advance Queue step3 perform the overlay),會把外部的qTD抓進來,處理完後再寫回去
一個in/out/setup一個qTD。host controller會視情況把data分作好幾個transaction。每個qTD只能帶一個連續的buffer(pointer+size),最大到20K(only if 這個buffer是4KB-aligned)
QH處理流程
- Fetch QH
- 只要遇到任何Halted qTD,這個QH就會被跳過,換下一個QH
- (只在Periodic Schedule與EPS是full/low-speed才成立) 如果[Current qTD]不是[Active]而且[QH].[I]是1 ==> 跳過這個QH
- 如果[Current qTD]不是[Active] ==> Advance Queue
- 如果[Current qTD]還沒傳完 則優先用 [Alternate Next qTD Pointer] 其次 [Next qTD Pointer]當作[Current qTD]
- 如果[Current qTD]傳完了 ==> 用 [Next qTD Pointer]當作[Current qTD]
- 到這裡如果[Current qTD]的qTD還是沒Active,就跳下一個QH
- Execute qTD (到這裡[Current qTD]一定是[Active])
- 每個QH最多只執行一個qTD,不管有沒有執行完,就換下一個QH
- 如果執行完,則把Overlay的status寫回[Current qTD],然後跳下一個QH
- 如果沒執行完,則直接跳下一個QH
沒有留言:
張貼留言