共用方式為


透過裝置樹狀結構瞭解等候/喚醒 IRP 的路徑

在單一裝置堆棧內,電源原則擁有者會傳送等候/喚醒 IRP,而所有驅動程式都會處理等候/喚醒 IRP,如 等候/喚醒 作業概觀中所述,並詳述於 分別傳送等候/喚醒 IRP接收等候/喚醒 IRP中所述。

裝置樹狀結構中 的某個分支(包括葉節點開發節點及其父節點、祖父節點等開發節點)中,驅動程式必須合作,確保等候/喚醒 IRP 會到達能啟動所有必要硬體以進行喚醒的驅動程式。

在ACPI電腦上,ACPI負責啟用與每個分葉裝置的喚醒信號相關聯的系統特定一般用途事件(GPE)暫存器。 因此,驅動程式必須要求並轉送等候/喚醒 IRP,直到到達 ACPI 篩選驅動程式(在啟動時插入裝置堆棧),或基礎 Windows ACPI 驅動程式,Acpi.sys。 作為回應,ACPI 會啟用暫存器,保留 IRP 擱置直到訊號送達,然後完成 IRP。 因為 ACPI 可以響應喚醒訊號,所以不會將 IRP 轉送至較低的驅動程式。

ACPI 篩選驅動程式,例如基礎 ACPI 驅動程式本身,對其他驅動程式而言是透明的。 為了在硬體設計中提供最大的彈性,任何裝置堆疊中 ACPI 篩選器驅動程式的確切位置都是裝置和系統特定的。 在設計驅動程式時,您無法對ACPI篩選器在裝置堆疊中是否存在或位置進行任何假設。

請記住,列舉子系的驅動程式會為每個子裝置建立 PDO,以及父裝置的 FDO。 因此,驅動程式會作為子裝置的總線驅動程式,以及父裝置的函式驅動程式/原則擁有者。 因此,每當總線驅動程式收到子 PDO 的等候/喚醒 IRP 時,應該要求另一個等候/喚醒 IRP 作為其父 PDO。

下圖顯示發生這類情況的範例組態。

圖表,說明範例 usb 組態。

在範例組態中,鍵盤和數據機是 USB 中樞的子系,而 USB 主機控制器的子系則由 PCI 總線列舉。 下圖顯示範例組態中鍵盤的裝置堆疊。

圖表,說明範例 usb 鍵盤組態的裝置堆疊。

如上圖所示,從下至上讀取:

  1. Windows ACPI 驅動程式Acpi.sys會建立適用於PCI的 PDO。

  2. PCI 驅動程式會建立PCI FDO和USB主機控制器 PDO,並擁有PCI裝置堆疊的原則。

  3. USB 主機控制器驅動程式(主機埠/迷你埠驅動程式組)會建立 USB 主機控制器 FDO 和 USB 中樞 PDO。 它擁有對USB主機控制器裝置堆疊的政策。 請注意,Acpi.sys 也會在此堆疊中建立篩選 DO。

  4. USB 集線器驅動程式會建立 USB 集線器 FDO 和鍵盤 PDO。 此驅動程式擁有 USB 集線器裝置堆疊的電源管理政策。

  5. 鍵盤的函式驅動程式是USB HID類別驅動程式/迷你驅動程式組。 此驅動程式會建立鍵盤的 FDO,並掌握其電源策略。 因為鍵盤沒有子裝置,因此此驅動程式不會建立 PDO。

請注意,每個裝置堆疊可能包含未顯示的其他可選擇的過濾器元件。

若要讓鍵盤輸入喚醒系統,鍵盤的策略管理者會要求其 PDO 的 IRP_MN_WAIT_WAKE。 該 IRP 會觸發其他等候/喚醒 IRP 的連鎖反應,如下圖所示。

範例 USB 組態的 IRP 等候/喚醒要求。

當總線驅動程式收到針對其創建的 PDO 的 IRP_MN_WAIT_WAKE 時,它必須為其擁有電源策略並創建 FDO 的裝置堆疊再請求另一個 IRP_MN_WAIT_WAKE

如上圖所示:

  1. 鍵盤驅動程式會呼叫 PoRequestPowerIrp,以將等候/喚醒 IRP (IRP1) 傳送至其 PDO。

    電源管理員會配置 IRP,並透過 I/O 管理員將它傳送到鍵盤的裝置堆疊頂端。 驅動程式設定 IoCompletion 例程,並向下傳遞 IRP 直到抵達鍵盤 PDO。 作為鍵盤總線驅動程式的USB中樞驅動程式會將IRP1保持在等待狀態。

  2. 由於 USB 集線器驅動程式無法在喚醒信號到達時喚醒系統,因此必須呼叫 PoRequestPowerIrp,以要求 USB 集線器裝置堆疊的等待/喚醒 IRP(IRP2)。

    電源管理員會將此 IRP 傳送至 USB 中樞裝置堆疊的頂端。 此堆疊中的驅動程式會設置 IoCompletion 例程,並將 IRP 傳送至 USB 主機控制器驅動程式(即 USB 中樞的總線驅動程式)。 USB 主機控制器驅動程式會暫止 IRP2,直到鍵盤發出喚醒事件訊號為止。

  3. 同樣地,USB 主機控制器驅動程式無法喚醒系統,因此 USB 主機控制器驅動程式會呼叫 PoRequestPowerIrp,以將等候/喚醒 IRP (IRP3) 傳送至 USB 主機控制器裝置堆疊。

    電源管理員會將此 IRP 傳送至 USB 主機控制器裝置堆疊的頂端,其中驅動程式會設定 IoCompletion 例程,並將 IRP 向下傳遞至 PCI 驅動程式(這可作為 USB 中樞的總線驅動程式)。 PCI 驅動程式會暫止 IRP3,直到鍵盤發出喚醒事件訊號為止。

  4. PCI 驅動程式無法喚醒系統,因此PCI驅動程式會呼叫 PoRequestPowerIrp,以將等候/喚醒 IRP (IRP4) 傳送至PCI裝置堆疊。 其父系是根裝置,ACPI 是總線驅動程式。

    電源管理員會將 IRP 傳送至 PCI 總線裝置堆疊的頂端;其驅動程式會設定完成例程,並將 IRP 向下傳遞至 Windows ACPI 驅動程式,Acpi.sys。

  5. Acpi.sys 可以喚醒系統,因此不會將等候/喚醒 IRP 傳送給任何其他 PDO。 Acpi.sys 會保持 IRP4 暫止狀態,直到喚醒訊號送達為止。

當鍵盤發出喚醒訊號時,Acpi.sys攔截它。 不過,ACPI 無法判斷訊號是否由鍵盤發出,只能得知訊號是透過根裝置傳來的。 Acpi.sys 然後完成 IRP4,I/O 管理器會呼叫 IoCompletion 例程,回到 PCI 裝置堆疊的上一層。 當 IRP4 完成且所有 IoCompletion 例程都已執行時,就會叫用 PCI 驅動程式的回呼例程。 在回呼例程中,PCI 驅動程式會判斷訊號是透過USB主機控制器傳來的。 PCI 驅動程序接著會完成 IRP3。 相同的順序會透過USB主機控制器堆疊和USB中樞堆疊發生,直到鍵盤驅動程式收到IRP1為止。 此時,鍵盤驅動程式可以視需要服務喚醒事件。

每次驅動程式將等候/喚醒 IRP 傳送至父 PDO 時,它都必須為自己的 IRP 設定 Cancel 常式。 設定 取消 例程,讓驅動程式有機會在觸發它的 IRP 被取消時,同時取消新的 IRP。 在USB範例中,如果鍵盤驅動程式取消了其等待/喚醒IRP(因此停用了鍵盤喚醒功能),那麼USB集線器、USB主機控制器和PCI驅動程式必須取消因應鍵盤IRP而傳送的那些IRP。 如需詳細資訊,請參閱 等候/喚醒 IRP 的取消例程

雖然父驅動程式可能會列舉多個可以啟用等候/喚醒的子系,但 PDO 只能有一個等候/喚醒 IRP 擱置中。 在這種情況下,父系驅動程式應確保每當其任何裝置被啟用喚醒功能時,都保持等候/喚醒 IRP 處於擱置狀態。 若要這樣做,驅動程式會在每次收到等候/喚醒 IRP 時遞增內部計數器。 每次驅動程式完成等候/喚醒 IRP 時,都會遞減計數,如果產生的值為非零,則會將另一個等候/喚醒 IRP 傳送至其裝置堆棧。

例如,在先前顯示在 範例 USB 組態 圖所示的 USB 組態中,USB 中樞會列舉兩個裝置:鍵盤和數據機。 當 USB 中樞驅動程式收到鍵盤 PDO 的等候/喚醒 IRP 時,它會先遞增等候/喚醒 IRP 的計數,再向自己的 PDO 要求 IRP。 如果數據機的原則擁有者稍後啟用數據機喚醒,USB 中樞驅動程式會為數據機 PDO 掛上新的 IRP,並遞增其等候/喚醒參考計數。 不過,由於USB集線器PDO不能有兩個同時擱置等候/喚醒IRP,所以USB集線器驅動程式不會要求USB集線器PDO的新等候/喚醒IRP。

當喚醒訊號從鍵盤或數據機送達時,USB 中樞驅動程式會決定哪個裝置發出訊號、完成對應的 IRP,並遞減其參考計數。 由於這兩個裝置都已啟用喚醒(因此其參考計數為非零),因此它必須傳送自身裝置堆疊另一個等候/喚醒 IRP,以「重新啟用」其自己的 PDO 來喚醒。 (USB 主機控制器和PCI驅動程式也是如此。

不過,驅動程式不會自行傳送 IRP,來在剛收到喚醒訊號的同一裝置上重新啟用等待/喚醒功能。 只有裝置電源原則管理員可以這麼做。 重新啟用等候/喚醒不是自動的。