understanding linux usb ehci device driver(1) 1

 

轉自: http://www.diybl.com/course/6_system/linux/Linuxjs/2007917/71729.html

 

大概一年多前,曾經在linux下調試過VIA的一款ehci host controller,當時受項目進度以及知識積累所限,未能深入理解EHCI以及linux下的軟件層面實現. 隨着個人USB技術的不斷積累, 近期在工作之餘, 寫了一些對EHCI以及linux下實現的理解. 選擇EHCI作爲一個思考和研究的對象的出發點:
1),USB2.0以及 EHCI是非常成功的,這些成功背後必然有技術的因素,對這些導致成功的技術的思考有利於未來在所從事的工作給出成功的設計和實現;
2),EHCI 是usb 2.0 的PC架構下實現方式, 其實現從對處理器能力佔用,性能保證以及軟件架構都具有一定的通用性,對嵌入式下HC的設計和實現都有較強的參考價值,另外,PC架構下豐富的資源(開放 的EHCI規範, linux usb源碼開放,PC環境易於調試等)利於開發者掌握這些技術;
3), EHCI無疑是比較複雜的,對linux ehci的理解和思考有助於提高個人的設計能力.

主要包括以下三個部分 :ehci specification overview, linux ehci device driver 以及主要場景分析 . 由於 個人能力所限 , 錯誤在所難免 , 但歡迎提出意見 .

 

1.   ehci specification overview [1]

1.1. ehci architectual overview

ehci 規範定義了 usb2.0 host controller 寄存器層面的接口,同時包括了 host controller driver host controller 軟硬件之間的接口。 Fig1-1 中灰色部分是 ehci 規範的範圍 .

 

 

 

Fig1-1   Universal Serial Bus, Revision 2.0 System Block Diagram

USB 2.0 Host Controller 一般包含 1 個支持高速模式的 eHC 0 ~多個支持低速,全速模式的 companion HCs (參考 fig1-2 ),這樣可以同時支持三種速度 模式的 usb 設 備。 Port Routing Logic 根據軟件的配置以及所插入的 usb device speed mode ,將 port1~portN 映射到 cHCs 或者 eHC 的對應端口:

  .EHCD driver 沒有配 置 eHC port routing logic 將所 插入設備的 port 映 射到 cHCs 的對 應 port;

  .EHCD driver 配置 了 eHC 後, eHC 是所有 root ports 的默認 owner, 當所插入設備不是高速時, eHC 釋放 port owner cHCs, 否則 eHC 保持 port owner.

 

Fig1-2  USB 2.0 Host Controller

Fig1-3 給出了 EHCI general architecture, 包括了 pci configuration registers space, memory-based I/O registers space 以及 shared memory schedule space.

Fig1-3 General Architecture of Enhanced Host Controller Interface

EHCI 對兩類傳輸類型提供了支持: periodic transfer asynchronous transfer. Periodic 類型包括 isochronous and interrupt transfer,    asynchronous 類型包括 control bulk transfer.

 

 

The periodic schedule is based on a time-oriented frame list that represents a sliding window of time of host controller work items. The asynchronous schedule is a simple circular list of schedule work items that provides a round-robin service opportunity for all asynchronous transfers.

1.1.1.    ehci 定義的寄存器接口

主要包括了 pci configuration registers space 以及   register space, 具體參考 ehci specification ch2.   

Pci configureation registers space 包括 pci header  and device specific registers, USBLEGSUP register, USBLEGCTLSTS register.( 實際上 ehc 不一定非通過 pci device 來實現 , 當不使用 pci device 方式實現時候 , 此處對應的寄存器格式應該會有變化 )

Registers 被劃分爲兩類 : 只讀的 capability registers read/write 的操作寄存器 . 操作寄存器用於訪問 eHC 的狀態 , 控制 eHC , EHCD 訪問 eHC 的主要接口之一。

1.2. ehci 定義的 schedule interface

具體參考 ehci specification ch3

定義軟硬件間數據結構的接口,主要包含如下數據結構 :

Periodic Frame List

   定義了包含 1024,512 or 256( 如果 HC 允許 , 可以通過 USBCMD register 配置 ) element 的表格 , 每個 element 爲一個 4byte-aligned 的指針,可以指向 iTD/QH/siTD/FSTN 等結構 ; 一般需要將該結構對應的表格起始地址寫入 PERIODICLISTBASE 寄存器, eHC 結合 FRINDEX 寄存器即可找到當前 frame 所要調度的 periodic schedule 數據結構鏈表 .

 

Asynchronous List Queue Head Pointer

   該指針指向以 QH 爲元素的循環鏈表,所有 asynchronous transfer(control/bulk) QH 鏈接至此。

 

Isochronous (High-Speed) Transfer Descriptor (iTD)

    iTD 僅僅被 high speed Isochronous endpoints 所使用,代表該 endpoint usb 設備間一個 frame 內的 Isochronous 傳 輸 , iTD 只可以鏈接到 Periodic Frame List .

 

Split Transaction Isochronous Transfer Descriptor (siTD)

   通過 usb 2.0 hub(not root hub) 接入 usb bus fs usb Isochronous device ehci 使用 siTD 向設備對應 endpoint 傳輸數據。 siTD 只可以鏈接到 Periodic Frame List .

 

Queue Element Transfer Descriptor (qTD)

   qTD 需要鏈接到 QH 纔可以使用, qTD 用於實現 1 個或者多個 USB transaction.

 

Queue Head

   QH 用作實現 Interrupt, bulk 以及 control 傳輸 , 1 QH 包含 0~ 多個 qTD.

 

Periodic Frame Span Traversal Node (FSTN)

         FSTN 用於實現跨 Frame fs/ls split transaction.

1.3. ehci operational model

具體參考 ehci specification ch4

 

Ehci 中該部分主要從 host controller 以及 host controller driver 兩 個角度 , 描述了 各自的操作模型 . 從 該部分內容就可以看出 HC HCD 間複雜的接口 .

1.3.1.    Periodic schedule

Periodic schedule 用於管理所有 isochronous interrupt 傳 輸 . Periodic schedule 的基礎是 periodic frame list(Fig1-4), 軟件將各種 periodic schedule 的數據結構 (iTD,siTD, FSTN 以及 Interrupt QH) 鏈接到 periodic frame list 的某個 frame , 生成一個 poll rate 從低 到高的樹狀結構 , 葉子對應的 poll rate 最低 , 樹根對應的 poll rate 最高 . 

軟件設置 USBCMD 寄存器的 periodic schedule enable bit , HC 會從 PERIODICLISTBASE 寄存器

找到 periodic frame list, 結合 FRINDEX 寄存器即可找到當前 frame 所要調度的 transaction 鏈表 , 這個鏈表就是從一個樹葉到根的一個 path, 在該 frame 對應的 8 micro-frame,HC 都會遍歷一次該 path, iTD/siTD/interrupt QH 結構中都包含了 micro-frame 相關的 schedule 信息 , 使得 HC 在合 適的 micro-frame 完成對應的 transaction.

 

Fig1-4 Example Periodic Schedule

1.3.2.    Managing Isochronous Transfers Using iTDs

  iTD 主要包含 4 個部分內容 :

      . Next Link Pointer .

     . Transaction description array (8 uFrame array)

      . 7-element buffer page pointer( 最大可支持 7*4KB 傳輸 )

      .endpoint capabilities information(including endpoint addressing, transfer direction, maximum packet size and high-bandwidth multiplier.)

1.3.2.1.          from HC view

  HC 如何找到 iTD?

      HC 使用 FRINDEX[12:3] 去索引 periodic frame list, 得到對應的 periodic frame list element, element 對應的鏈表在當前幀包含的 8 uFrame 中各被掃描 1 ( 即當前幀會被連續掃描 8 ), HC 在掃描過程中可以將 iTD fetch HC chip . 每個 iTD 包含 8 transaction descriptor, HC 通過 FRINDEX[2:0] 來索引對應的 descriptor, 進而在 micro-frame 生成對應的 bus transaction.

    

HC如何解析 iTD 並生成 bus transaction?

      如果 (iTD.transaction_descriptor[N] .status & ACTIVE ) == 0, 那麼 HC 會忽略該 iTD, 並沿着 NEXT pointer 到達下一個同步 schedule data structure.(N = FRINDEX[2:0] )

     如果 (iTD.transaction_descriptor[N] .status & ACTIVE ) == 1, 那麼開始解析該 iTD:

        . 使用 iTD.transaction_descriptor[N].PG 以及 iTD.transaction_descriptor[N] .Transaction_offset 得到傳輸數據 buffer 的物理地址

        . 使用 endpoint addressing information 以及 I/O bit( 均包含在 iTD endpoint capabilities information ) 向對應的 endpoint 執行 transaction. 完成後 , HC clear iTD.transaction_descriptor[N].status ACTIVE , 並 且回寫其他一些狀態信息到 iTD.transaction_descriptor[N].status .

 

  HC 怎樣在 uFrame 中執行多個 iso transaction:

      Mult field(iTD endpoint capabilities information ) 表示在 一個 uFrame HC 可以向該 endpoint 連續執行幾個 transaction, 取值範圍爲 1~3. 事實上只有 device endpoint 具有這種能力的話 , HCD 纔會 iTD.Multi 設置對應的值 , device endpoint descriptor 中有對應的 Multi 能力描述信息 .

1.3.2.2.          from HCD view

上層軟件一般會請求 HCD 做一個 HS ISO transfer, 提供如下信息 :

     .buffer address 以及 transfer length;

     .endpoint 信息 .

HCD 需要將這種請求轉化成 HC 可以識別的 iTD, 並將其鏈接到 periodic frame list . HCD 需要依據如下完成這種轉化 :

     .endpoint interval 能力 ;

      .endpoint MAXPACKETSIZE 能力 ;

     .endpoint Multi 能力 ;

     .HCD 需要保證同步傳輸 在每個 uFrame 中 所佔據帶寬不能超過 80%(USB 2.0 spec 規定 ).

1.3.3.    Asynchronous schedule

Asynchronous schedule 用於管理 control bulk 傳輸 , 這兩種傳輸都使用 QH 數據結構來實現調度 . Asynchronous schedule ASYNCLISTADDR register 得到 control/bulk 傳輸的 QH 鏈表 head 地址 , HC 即可遍歷 / 解析 asynchronous schedule 的所有 QH 結構 , 生成 bus transaction. HC 完成 asynchronous schedule processing 時候 , 就將上次訪問的 QH’s horizontal pointer 保持在

ASYNCLISTADDR register, 以便下次 asynchronous schedule 可以繼續上次的遍歷 . HC 在如下情況下 , 完成一 次 asynchronous schedule 的處理 :

        . The end of a micro-frame occurs.

.T he host controller detects an empty list condition.

. The schedule has been disabled via the Asynchronous Schedule Enable bit in the USBCMD

register.

     實際上 ,HC control/bulk asynchronous 傳輸的調度採取 round-robin 的方式 (Fig 1-5).

   

Fig 1-5 General Format of Asynchronous Schedule List

1.3.3.1.          Adding Queue Heads to Asynchronous Schedule

HCD 角度 , 就是將一個 QH 結構添加到 Asynchronous Schedule list , 算法如下 :

InsertQueueHead (pQHeadCurrent, pQueueHeadNew)

--

-- Requirement: all inputs must be properly initialized.

--

-- pQHeadCurrent is a pointer to a queue head that is already in the active list


-- pQHeadNew is a pointer to the queue head to be added

--

-- This algorithm links a new queue head into a existing list

--

pQueueHeadNew.HorizontalPointer = pQueueHeadCurrent.HorizontalPointer

pQueueHeadCurrent.HorizontalPointer = physicalAddressOf(pQueueHeadNew)

End InsertQueueHead

 

需要注意的是 , 軟件需要保證添加 QH 過程中從 HC 角度保持 schedule 的一致性 : 所有 QH 結構的 pointer field 必須是有效的 .

1.3.3.2.          Removing Queue Heads from Asynchronous Schedule

該部分從 HCD 角度說明如何從 asynchronous schedule list 中刪除 QH.

HCD unlink QH 的算法如下 :

 

 

UnlinkQueueHead (pQHeadPrevious, pQueueHeadToUnlink, pQHeadNext)

--

-- Requirement: all inputs must be properly initialized.

--

-- pQHeadPrevious is a pointer to a queue head that references the

-- queue head to remove

-- pQHeadToUnlink is a pointer to the queue head to be removed

-- pQheadNext is a pointer to a queue head still in the schedule. Software

-- provides this pointer with the following strict rules:

-- if the host software is one queue head, then pQHeadNext must be the

-- same as pQueueheadToUnlink.HorizontalPointer. If the host software is

-- unlinking a consecutive series of queue heads, pQHeadNext must be

-- set by software to the queue head remaining in the schedule.

-- This algorithm unlinks a queue head from a circular list

--

pQueueHeadPrevious.HorizontalPointer = pQueueHeadToUnlink.HorizontalPointer

pQueueHeadToUnlink.HorizontalPointer = pQHeadNext

End UnlinkQueueHead

 

從算法來看 , 軟件操作非常簡單 , 但需要注意到 : HC 可以看作和主 CPU 並行運行的的處理器 ,

HC 正在運行過程中刪除某個 QH 的話 , 如何使得 HC 內部的狀態 ( 比如 cache QH pointer 信息 ) 和內存中實際的鏈表狀態一致呢 ? EHCI 提供瞭如下方法 :

        軟件 UnlinkQueueHead ; // 刪除了內存中 asynchronous schedule list 中某個 QH

        Set IAAD to USBCMD register; // 通知 HC 內存中的某個 asynchronous QH 被刪除

        使能 IAA 中斷 ;

       

        IAA   IRQ comes  //IAA 中斷到來, 表示 HC 已經更新其內部狀態 , 和內存保持一致

       

:

     IAAD: Interrupt on Async Advance Doorbell

     IAA  : Interrupt on Async Advance

1.3.3.3.          Empty Asynchronous Schedule Detection

該部分從 HC 角度說明 .

HC 使用如下信息來發現何時 Asynchronous Schedule 爲空 :

  .H bit in QH data structure // HC 設置 ,asynchronous schedule 中最多有 1 QH 設置了 H bit

                        // 設置 H 1 QH head of reclaim list.

  . Reclamation bit in USBSTS register //HC 遍歷 asynchronous schedule 過程中發現了 H 1 QH   // 即將該位 clear, 在開始執行一個 transaction 時候 set to 1

HC 發現 H bit 1 並且 Reclamation bit 0 時候 , 認爲發現了 empty asynchronous schedule, 即停止遍歷 asynchronous schedule.

1.3.3.4.          Restarting Asynchronous Schedule Before EOF

該部分從 HC 角度說明 .

Fig1-6 Example State Machine for Managing Asynchronous Schedule Traversal

檢測到 Empty List 時候 ,HC 會停止 traversal 進入 idle. 那麼爲什麼要停止呢 , 畢竟還沒有到達 end of micro-frame, 還可以執行儘可能多的 transaction. 這是因爲導致 empty list 的很多情況都是由於來 自 endpoint Nak/Nyet responses, 如果不停下來那麼勢必不必要的佔用太多 memory 總線帶寬 . 那麼停下來後 , 是不是 在 current uFrame 就不再 asynchronous schedule ? 其實不是 , Fig1-6 可以看出 , 發現 Empty List , HC 會進入 Async Sched Sleeping 狀態 , 一般設置該狀態的超時時間是 10us, 超時後又會進入 Async Sched Active 狀態 , 繼續開始 asynchronous schedule.

1.3.3.5.          Reclamation Status Bit (USBSTS Register)

該部分從 HCD 角度說明 .

參考 Empty Asynchronous Schedule Detection

1.3.4.    Managing Control/Bulk/Interrupt Transfers via Queue Heads

一個 QH 用來管理到一個 endpoint 的數據流 . QH 包含了 endpoint 的能力特性信息 , 包含了執行 bus transaction 的工作區 . QH 使用 qTD 來運行 transaction, 每個 qTD 代表了一個或者多個 Bus transaction.  HC 會將執行 qTD bus transaction 時候的狀態信息記錄在 QH.status field , 當完成一個 qTD 傳輸後 , 會把 QH.status 回寫到 qTD.status , 同時不需要軟件干預就可前進到下一個 qTD.

 

HC QH 的通用處理模型 (Fig 1-7) 如下 :

      . read a queue head,

. execute a transaction from the overlay area,

. write back the results of the transaction to the overlay area

. move to the next queue head.

Fig1-7 Host Controller Queue Head Traversal State Machine

Fig 1-7 HC QH traversal State Machine 適 用於各種類型的 QH(control, bulk and Interrupt type), 以及 highspeed transaction , split transaction.

1.3.4.1.          Fetch Queue Head

HC QH 結構讀入芯片內部後 , 標誌該狀態結束 .

1.3.4.2.          Advance Queue

To advance the queue, the host controller must find the next qTD, adjust pointers, perform the overlay and write back the results to the queue head.

當在 FetchQHD 狀態 , HC 發現 QH overlay Active HALT bits 0, 即進入 Advance Queue 狀態 . 進入該狀態後 ,HC 確定 使用哪個指 針來 fetch a qTD, 然後 fetches a qTD 並決定是否做 overlay 操作 ( I-bit == 1 並且 Active-bit is 0, HC 跳過對該 QH 的處理 , 退出該狀態 , 並且使用當前 QH horizontal pointer 到達下一個 schedule data structure).

    如果 Bytes to Transfer !=0 並且 Alternate Next qTD Pointer.T ==0, HC 使用 Alternate Next qTD Pointer fetches a qTD, 否則 HC 使用 Next qTD Pointer. 如果 Next qTD Pointer.T==1, HC 退出該狀態並使用 QH horizontal pointer 到達下一個 schedule data structure.

HC 使用確定好的 pointer fetches the referenced qTD, 如果 the qTD.Active==1, HC 設置 current qTD Pointer 值爲所確定的取出 qTD 的指針 , 然後 performs the overlay; 如 果 the qTD.Active ==0, HC 退出該狀態並使用 QH horizontal pointer 到達下一個 schedule data structure.

HC 按照一系列原則 perform  overlay, 寫入 QH 結構後 , 退出該狀態 .

1.3.4.3.          Execute Transaction

進入該狀態後, HC 會執行一些 pre-operations, 並在執行 QH 所代表的 transaction 之前做一些

Pre-condition criteria 的測試 這些 pre-operations pre-condition criteria 對於 interrupt QH control/bulk QH 是不同的 .

 

Interrupt Transfer Pre-condition Criteria

  QH.S-mask & ( 1<< FRINDEX[2:0] ) != 0 ,HC 纔會執行該 QH transactions.

 

Asynchronous Transfer Pre-operations

  HC 判斷是否需要 reload the NAK Counter field, 如果需要的話 ,reload the NAK Count.

 

Asynchronous Transfer Pre-condition Criteria

  如果 QH. NakCnt !=0 || Reload Nak Counter ==0, HC 纔會執行該 QH transactions.

 

Transfer Type Independent Pre-operations

  Load the QH.Multi to HC 內部變量 qHTransactionCounter , HC 該實現對 asynchronous QH 是可選的 , Interrupt QH 是必須實現的 .

 

Transfer Type Independent Pre-condition Criteria

  .HC 是否可以在當 前 micro-frame 內完成 QH 的一個 transaction, 如果不可以 , 那麼退 出該狀態

  . 如果 qHTransactionCounter for an interrupt endpoint 等於 0, 那麼 HC 退出該狀態 .

 

當所有的 Pre-operations 完成並且滿足所有的 Pre-condition Criteria , HC 設置 USBCMD. Reclamation 1, 開始使用 QH 中的 endpoint 信息執行一個或者多個 transaction, HC 會循環 qHTransactionCounter , 每執行一個 transaction, qHTransactionCounter--. 當如下條件之一發生時 ,

HC 結束該狀態 :

     . qHTransactionCounter == 0

    . The endpoint responds to the transaction with any handshake other than an ACK

. The transaction experiences a transaction error, or

. The Active bit in the queue head goes to a zero, or

. There is not enough time in the micro-frame left to execute the next transaction

 

每次 transaction 的執行結果會記錄在 on-chip overlay area, 如果 transaction 的數據成功傳輸 ,overlay area 的傳輸狀態更新如下 :

        Total Bytes to Transfer -= the number of bytes moved in the transaction

        Data toggle bit toggled

        Current page offset += the number of bytes moved in the transaction

        the C_Page field is updated to the appropriate value (if necessary)

當前 transaction 結束後 , HC transaction 的結果回寫到 QH’s overlay area in main memory.

 

如果 transaction 執行出錯 , 傳輸狀態不會更新 , QH.CErr--, QH.status 會記錄錯誤信息 . 如下 事件會導致 HC clear QH.status ACTIVE bit, When the Active bit transitions from a one to a zero, the transfer in the overlay is considered complete.

    .CErr field decrements to zero.

   . The device responds to the transaction with a STALL PID.

   . The Total Bytes to Transfer field is zero after the transaction completes.

   . The PID code is an IN, and the number of bytes moved during the transaction is less than the MaximumPacket Length.

   . The PID Code field indicates an IN and the device sends more than the expected number of bytes

 

   HC 收到 NAK ( 並且 RL==0),HC 將傳輸結果回寫到 QH overlay area. 對於 high speed endpoint, QH 的下述 field 需要被更新 :

. NakCnt , dt, Total Bytes to Transfer, C_Page, Status, CERR, and Current Offset

對於 full speed/low speed endpoint, 需要更新 QH 如下的 field:

. C-prog-mask , FrameTag and S-bytes.

1.3.4.4.          Write Back qTD

該狀態又名 qTD retirement. 在該狀態 , HC QH overlay area 回寫到 QH. Current qTD Pointer 指向的目標 qTD. 回寫的 field 至少包括 :

        Total Bytes to Transfer , Cerr, and Status

1.3.4.5.          Follow Queue Head Horizontal Pointer

當如下事件發生時 , HC 使用 QH. horizontal pointer 到達下一個 schedule data structure:

    . If the Active bit is a one on exit from the Execute Transaction state, or

. When the host controller exits the Write Back qTD state, or

. If the Advance Queue state fails to advance the queue because the target qTD is not active, or

. If the Halted bit is a one on exit from the Fetch QH stat

 

 

:

   HC 不需要等待當前 transaction 完成後 , 使用 QH. horizontal pointer 讀 出下一個 schedule data structure, 但是必須完成當 前 transaction , 纔可以執行下一個數據結構中的 transaction.

1.3.4.6.          Adding Interrupt Queue Heads to the Periodic Schedule

類似與添加 iTD periodic schedule.

1.3.4.7.          Managing Transfer Complete Interrupts from Queue Heads

如果設置了 qTD.IOC, 那麼該 qTD 完成後 ,HC 會向 CPU 發出中斷請求 .

1.3.5.    Ping Control

Ping 協議是 USB2.0 新加的內容 , 主要用於 HS control/bulk endpoint, hs control bulk 傳輸的 out transaction 服務 . Fig 1-8 ping control 的狀態轉換表 .

Fig 1-8 Ping Control State Transition Table

1 Transaction Error (XactErr) is any time the host misses the handshake.

2 No transition change required for the Ping State bit. The Stall handshake results in the endpoint being halted (e.g.

Active set to zero and Halt set to a one). Software intervention is required to restart queue.

3 A Nyet response to an OUT means that the device has accepted the data, but cannot receive any more at this time. Host must advance the transfer state and additionally, transition the Ping State bit to Do Ping .

 

1.3.6.    Split Transactions

爲了支持通過 usb 2.0 hub 接入總線的 fs/ls 設備 , ehci 引入了 split transaction. Usb2.0 規範在 hs hub 中集成了 transaction translator(tt) 來支持接入的 fs/ls 設備 , tt 充當了 fs/ls host controller 的角色 , 負責執行到 fs/ls 設備的 transaction. Split transaction HC 發到 TT transaction, 包括 start-split transaction (ss) complete-split transaction(cs), ss 用於 HC 請求 TT 發起一個 fs/ls 傳輸 transaction, cs 用於 HC TT 查詢 ss 發起的 transaction 是否完成 , 如果完成 , 會向 cs 響應並返回完成結果 .

Ehci 通過 hs hub device address 以及所包含 TT port number 來標識 TT

 

Ehci 規範中 ,Asynchronous schedule , Interrupt schedule Isochronous schedule split transaction 的實現方 法是不同的 . Asynchronous schedule 通過 QH 支持 split transaction; Interrupt schedule 也是 通過 QH 支持 split transaction, 同時 QH.uFrame S-mask 用於設置 HC 在哪個 micro-frame 發 起 ss, QH.uFrame C-mask 用於設置 HC 在哪些 micro-frame 發起 cs, 爲了解決跨 frame 問題 ( 即有些 CS 事務需要安排到下一 frame 調度 ), 還引入了 FSTN 數據結構 ; Isochronous schedule 單獨引入了 siTD 數據結構來支持 fs/ls isochronous split transaction, siTD 需要像 iTD 一樣被鏈接到 periodic schedule list .

  Split transaction ehci operational model 章節中佔據了不少篇幅來說明 , 同時也是 ehci 中的一個難點 .

(未完)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章