共用方式為


協調元件電源狀態與 I/O 要求

[僅適用於 KMDF]

多元件裝置的 KMDF 驅動程式只能將要求傳送至處於作用中狀態的元件。 一般而言,驅動程式會將I/O 佇列指派給元件或元件集。

首先考慮指派給單一元件的佇列。 當元件變成作用中時,驅動程式會啟動佇列,並在元件閑置時停止佇列。 因此,當 KMDF 呼叫佇列的要求處理程式時,裝置會處於完全開啟 (D0) 狀態,且所需的元件為作用中。 要求處理程式可以安全地存取元件硬體。

相同的概念適用於指派給一組元件的佇列。 在此情況下,驅動程式會在集合中的所有元件都處於使用中狀態時啟動佇列。 驅動程式會在任一元件閑置時停止佇列。

本主題描述多元件裝置的 KMDF 驅動程式在涉及需要不同元件組合的多個要求類型的情況下,如何實作這類支援。

範例

針對驅動程式所支援的每個要求類型,請識別必要的元件。 例如,假設裝置有三個元件:0、1 和 2,驅動程式會收到三種類型的要求:A、B 和 C。要求的元件需求如下:

要求類型 所需的元件
A 0,2
B 1
C 0,1,2

在此範例中,有三組不同的元件,每個要求類型各一組。 驅動程式會為裝置提供一個預設的電源受控 I/O 佇列,以及一個對應至每個元件集的額外電源受控佇列。 在上述範例中,驅動程式會建立一個主要佇列和三個次要佇列,一個對應至每個元件集。 下圖顯示此佇列組態:

圖表,顯示具有要求類型 A、B 和 C 的多個元件裝置的佇列實作

驅動程式會維護每個元件集的位掩碼。 位掩碼中的每個位都代表其中一個元件的使用中/閑置狀態。 如果已設定位元,則元件處於使用中。 如果該位元已被清除,元件就會處於空閒狀態。

當要求到達時,最上層佇列 要求處理程式會決定要求需要哪些元件,並針對每個元件呼叫 PoFxActivateComponent。 然後,要求處理程式會將要求轉送至對應至該元件集合的次要 I/O 佇列。

當元件變成使用中時,電源管理架構 (PoFx) 會呼叫驅動程式的 ComponentActiveConditionCallback 例程。 在此回呼中,驅動程式會在每個代表指定元件的位掩碼中,設定對應於該元件的位。 如果已設定指定位掩碼中的所有位,對應集合中的所有元件都會作用中。 針對完全作用中的每個元件集,驅動程式會呼叫 WdfIoQueueStart 來啟動對應的次要 I/O 佇列。

例如,請考慮上述假設裝置。 假設元件 0 為使用中,而元件 1 和 2 則處於閑置狀態。 當元件 2 啟動時,PoFx 會呼叫該元件的 ComponentActiveConditionCallback 例程。 要求類型 A 和 C 使用元件 2,因此驅動程式會控制這兩個要求類型的位掩碼。 由於現在已設定要求類型 A 位掩碼中的所有位,因此驅動程式會啟動要求類型 A 的佇列。不過,並非所有位都設定為要求類型 C (元件 1 仍然閑置)。 驅動程式不會啟動要求類型 C 的佇列。

啟動次要 I/O 佇列時,架構會開始傳遞儲存在佇列中的要求。 在次要 I/O 佇列的 要求處理程式 中,由於元件處於作用中狀態,且已為每個請求在元件上取得電力引用,驅動程式可以安全地處理這些請求。

當驅動程式完成處理要求時,它會針對要求所使用的每個元件呼叫 PoFxIdleComponent,然後完成要求。 當不再使用元件要求時,Power Framework 會呼叫驅動程式的 ComponentIdleConditionCallback 例程。

在此回呼中,驅動程式會在每個表示該元件的位元掩碼中,清除對應至指定元件的位元。 如果指定的位掩碼指出元件是對應集合中第一個轉換成閑置條件的元件,驅動程式會呼叫 WdfIoQueueStop 來停止對應的次要 I/O 佇列。 如此一來,驅動程式可確保除非對應集合中的所有元件都處於作用中狀態,否則佇列不會分派要求。

再次考慮上述範例。 假設所有元件都在作用中,因此會啟動所有佇列。 元件 1 閑置時,PoFx 會呼叫元件 1 的 ComponentIdleConditionCallback 例程。 在此回呼中,驅動程式會操作要求類型 B 和 C 的位掩碼,因為這些類型使用了元件 1。 因為元件 1 是這兩個要求類型的第一個閒置元件,因此驅動程式會停止要求類型 B 和 C 的佇列。

假設此時元件 0 變成閑置。 在元件 0 的 ComponentIdleConditionCallback 中,驅動程式會操作要求類型 A 和 C 的位掩碼。因為元件 0 是要求類型 A 的第一個空閒元件(元件 2 仍在運作中),因此驅動程式會停止要求類型 A 的佇列。 不過,對於要求類型 C,元件 0 不是第一個變成空閒的元件。 驅動程式不會停止要求類型 C 的佇列(先前已這麼做)。

若要使用此範例中所述的技術,驅動程式也必須為其每個次要佇列註冊 EvtIoCanceledOnQueue 回呼函式。 如果在次要佇列中取消要求,驅動程式可以使用此回呼函數以便呼叫每個對應元件的 PoFxIdleComponent。 這樣做會釋放要求處理程式在將要求轉送至次要佇列之前呼叫 PoFxActivateComponent 時所取得的電源參考。