共用方式為


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

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

裝置樹 狀結構 (的分支內,由分葉開發節點及其父代、父代等的 devnode 組成) ,驅動程式必須合作,以確保等候/喚醒 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 中樞的子系,接著是 PCI 總線所列舉的 USB 主機控制器子系。 下圖顯示範例組態中鍵盤的裝置堆疊。

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

如上圖所示,從底部向上讀取:

  1. Windows ACPI 驅動程式 Acpi.sys 會建立 PDO for PCI。

  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。

請注意,每個裝置堆疊可能包含未顯示的其他選擇性篩選 DO。

若要允許鍵盤輸入喚醒系統,鍵盤的原則擁有者會要求其 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中樞驅動程式無法在喚醒訊號送達時喚醒系統,所以USB中樞驅動程序必須呼叫 PoRequestPowerIrp ,以要求等候/喚醒 IRP (IRP2) USB 中樞裝置堆疊。

    電源管理員會將此 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,設定 Cancel 例程可讓驅動程式有機會取消新的 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,以在剛到達喚醒訊號的相同裝置上重新啟用等候/喚醒。 只有裝置電源原則管理員才能這麼做。 重新啟用等候/喚醒不是自動的。