移除函式驅動程式中的裝置
移除裝置時,函式驅動程式必須復原它執行的任何作業,以新增和啟動裝置。 此討論包括周邊裝置的函式驅動程式,以及匯流排裝置的函式驅動程式。
函式驅動程式會使用 其 DispatchPnP 常式中的下列程式來移除裝置:
這是匯流排裝置的函式驅動程式嗎?
如果是的話,可能會刪除匯流排上裝置的任何未處理子 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,才能移除匯流排裝置。
驅動程式是否已處理此 FDO 的先前 IRP_MN_SURPRISE_REMOVAL 要求?
如果是,請執行任何剩餘的清除,並跳至步驟 8 IoCallDriver。
驅動程式通常會維護裝置擴充功能中的旗標,指出驅動程式是否已處理裝置 的IRP_MN_SURPRISE_REMOVAL 要求。
如果驅動程式先前已啟用裝置進行喚醒,請取消 IRP_MN_WAIT_WAKE 要求。
確定裝置處於非作用中狀態。
如果裝置尚未處於非作用中狀態,以回應先前 的IRP_MN_QUERY_REMOVE_DEVICE,驅動程式必須將裝置標示為不接受新要求,而且必須完成此驅動程式中已排入佇列的任何要求。 驅動程式必須失敗任何需要存取裝置的未處理要求。
驅動程式可以使用IoXxxRemoveLockXxx常式來計算未處理的 I/O,並設定事件,指出移除處理可以繼續。
執行任何關閉電源作業。
當裝置收到 IRP_MN_REMOVE_DEVICE 要求時,裝置的每個驅動程式都會執行其關閉電源作業。 裝置的電源原則擁有者通常是函式驅動程式,不會傳送個別 IRP_MN_SET_POWER 要求,將裝置電源狀態設定為 D3。 父匯流排驅動程式通常會關閉插槽,並在匯流排驅動程式取得移除 IRP 時,使用 PoSetPowerState 通知電源管理員。 如需詳細資訊,請參閱 電源管理。
呼叫 IoSetDeviceInterfaceState來停用任何裝置介面。
釋放驅動程式使用中裝置的任何硬體資源。
確切的作業取決於裝置和驅動程式,但可能包括中斷 與 IoDisconnectInterrupt中斷連線、使用 MmUnmapIoSpace釋放實體位址範圍,以及釋放 I/O 埠。
將 IRP_MN_REMOVE_DEVICE 要求向下傳遞至下一個驅動程式。
使用 IoSkipCurrentIrpStackLocation 設定下一個較低驅動程式的 IRP 堆疊位置,並使用 IoCallDriver將 IRP 傳遞至下一個驅動程式。
驅動程式不需要等待基礎驅動程式完成移除作業,再繼續進行其移除活動。
使用 IoDetachDevice從裝置堆疊中移除裝置物件。
將下一個較低裝置物件的指標指定為 TargetDevice 參數。 驅動程式會在驅動程式的AddDevice常式中,從呼叫 IoAttachDeviceToDeviceStack收到這類指標。
清除任何裝置特定的配置、記憶體、事件等等。
使用 IoDeleteDevice釋放 FDO。
從 DispatchPnP 常式傳回,從 IoCallDriver傳播傳回狀態。
函式驅動程式不會指定移除 IRP 的 IoCompletion 常式,也不會完成 IRP。 父匯流排驅動程式已完成移除 IRP。