Share via


移除函式驅動程式中的裝置

移除裝置時,函式驅動程式必須復原它執行的任何作業,以新增和啟動裝置。 此討論包括周邊裝置的函式驅動程式,以及匯流排裝置的函式驅動程式。

函式驅動程式會使用 其 DispatchPnP 常式中的下列程式來移除裝置:

  1. 這是匯流排裝置的函式驅動程式嗎?

    如果是的話,可能會刪除匯流排上裝置的任何未處理子 PDO。

    如果匯流排驅動程式處理了先前 的子裝置IRP_MN_SURPRISE_REMOVAL 要求,但驅動程式尚未收到後續 的IRP_MN_REMOVE_DEVICE 要求,則匯流排驅動程式會保持不變的子 PDO。 稍後,關閉子裝置的所有控制碼時,PnP 管理員會傳送子裝置的移除 IRP,而匯流排驅動程式會刪除該時間的子 PDO。

    如果匯流排驅動程式已處理裝置的先前 IRP_MN_REMOVE_DEVICE 要求,而且後續沒有 IRP_MN_SURPRISE_REMOVAL 要求,則匯流排驅動程式會刪除子 PDO。 在此情況下,PnP 管理員可確保從子裝置中移除任何函式和篩選驅動程式, (FDO 和篩選 DO 已刪除) ,再將移除 IRP 傳送至父匯流排裝置。 子 PDO 可能仍然存在,因此匯流排驅動程式必須先刪除子 PDO,才能移除匯流排裝置。

  2. 驅動程式是否已處理此 FDO 的先前 IRP_MN_SURPRISE_REMOVAL 要求?

    如果是,請執行任何剩餘的清除,並跳至步驟 8 IoCallDriver

    驅動程式通常會維護裝置擴充功能中的旗標,指出驅動程式是否已處理裝置 的IRP_MN_SURPRISE_REMOVAL 要求。

  3. 如果驅動程式先前已啟用裝置進行喚醒,請取消 IRP_MN_WAIT_WAKE 要求。

  4. 確定裝置處於非作用中狀態。

    如果裝置尚未處於非作用中狀態,以回應先前 的IRP_MN_QUERY_REMOVE_DEVICE,驅動程式必須將裝置標示為不接受新要求,而且必須完成此驅動程式中已排入佇列的任何要求。 驅動程式必須失敗任何需要存取裝置的未處理要求。

    驅動程式可以使用IoXxxRemoveLockXxx常式來計算未處理的 I/O,並設定事件,指出移除處理可以繼續。

  5. 執行任何關閉電源作業。

    當裝置收到 IRP_MN_REMOVE_DEVICE 要求時,裝置的每個驅動程式都會執行其關閉電源作業。 裝置的電源原則擁有者通常是函式驅動程式,不會傳送個別 IRP_MN_SET_POWER 要求,將裝置電源狀態設定為 D3。 父匯流排驅動程式通常會關閉插槽,並在匯流排驅動程式取得移除 IRP 時,使用 PoSetPowerState 通知電源管理員。 如需詳細資訊,請參閱 電源管理

  6. 呼叫 IoSetDeviceInterfaceState來停用任何裝置介面。

  7. 釋放驅動程式使用中裝置的任何硬體資源。

    確切的作業取決於裝置和驅動程式,但可能包括中斷 與 IoDisconnectInterrupt中斷連線、使用 MmUnmapIoSpace釋放實體位址範圍,以及釋放 I/O 埠。

  8. IRP_MN_REMOVE_DEVICE 要求向下傳遞至下一個驅動程式。

    使用 IoSkipCurrentIrpStackLocation 設定下一個較低驅動程式的 IRP 堆疊位置,並使用 IoCallDriver將 IRP 傳遞至下一個驅動程式。

    驅動程式不需要等待基礎驅動程式完成移除作業,再繼續進行其移除活動。

  9. 使用 IoDetachDevice從裝置堆疊中移除裝置物件。

    將下一個較低裝置物件的指標指定為 TargetDevice 參數。 驅動程式會在驅動程式的AddDevice常式中,從呼叫 IoAttachDeviceToDeviceStack收到這類指標。

  10. 清除任何裝置特定的配置、記憶體、事件等等。

  11. 使用 IoDeleteDevice釋放 FDO。

  12. DispatchPnP 常式傳回,從 IoCallDriver傳播傳回狀態。

函式驅動程式不會指定移除 IRP 的 IoCompletion 常式,也不會完成 IRP。 父匯流排驅動程式已完成移除 IRP。