xuexi 居然不能發???
電源管理是WDM驅動的一個重點和難點,需要處理好,否則在測試、使用過程中很容易出現各種異常。最嚴重的就是 bug check 0x9F 相關的各種BSOD。
這裏簡單介紹下,power Irp包括兩類,一類是系統狀態相關power Irp(system-irp),另一類是設備狀態相關power Irp(device-irp)。我們在Driver Entry中註冊的dispatch可以接受上述system-irp和device-irp。本文下面提到的system-irp/device-irp都是指system power irp/device power irp。
本節只介紹下面四種power相關Irp,包括 IRP_MN_QUERY_POWER System-Irp,IRP_MN_QUERY_POWER Device-Irp,IRP_MN_SET_POWER System-Irp,IRP_MN_SET_POWER Device-Irp。
上述四種power相關Irp,系統在轉換power state時會首先下發system-Irp,設備的 function driver收到後,會產生一個與之對應的device-Irp,並通過系統下發到power dispatch。處理的流程是首先將system-Irp設置爲pending,在device-Irp處理完畢後,依據返回狀態設置system-Irp的status,再complete此 system-Irp。具體的處理流程可以參考後面的詳細介紹。
上述四種power相關Irp可以依據不同的標準劃分,可以劃分爲system、device相關,還可以劃分爲 query、se、wakeup相關。本節只討論query、set相關的power Irp。這裏簡單描述下query和set的區別。Query通常是用於系統詢問設備,是否可以進入某種power狀態。Set通常在query之後發送,是系統明確要求設備進入某種power狀態。
下面依據query、set的分類來描述下上述Irp的處理過程。
IRP_MN_QUERY_POWER :
1) 系統會下發IRP_MN_QUERY_POWER system-irp
2a) Function Driver收到 IRP_MN_QUERY_POWER system-irp
-function driver設置I/O completion call back,以便在底層bus driver返回時做一些必要的處理
-function driver將此Irp繼續向底層driver發送
-function driver返回STATUS_PENDING
在底層bus driver處理完畢,complete此system-irp後,會call到上述的I/O completion call back A函數
2b) 2a)中提到的I/O completion call back A中需要請求Power Manager依據上述IRP_MN_QUERY_POWER system-irp的內容,發送一個IRP_MN_QUERY_POWER device-irp。在請求PM下發IRP_MN_QUERY_POWER device-irp的同時,設置completion call back B函數,同時返回STATUS_MORE_PROCESSING_REQUIRED。
2c) function driver收到IRP_MN_QUERY_POWER device-irp,可以complete with Success(可以允許device進入要求的狀態) or fail(禁止device進入要求的狀態)。
在這之後,系統會call到2b)中提到的completion call back B。
2d) 在completion call back B中將IRP_MN_QUERY_POWER system-irp的status設置爲IRP_MN_QUERY_POWER device-irp的status。同時complete IRP_MN_QUERY_POWER system-irp。
2c)中提到的允許/禁止系統進入想要進入的狀態並非always生效,在某些情況下系統可以不care這些result直接通過IRP_MN_SET_POWER來要求device進入相應的狀態。
IRP_MN_SET_POWER :
3) 系統會下發IRP_MN_SET_POWER system-irp
4a) Function Driver收到 IRP_MN_SET_POWER system-irp
-function driver設置I/O completion call back,以便在底層bus driver返回時做一些必要的處理
-function driver將此Irp繼續向底層driver發送
-function driver返回STATUS_PENDING
在底層bus driver處理完畢,complete此system-irp後,會call到上述的I/O completion call back C函數
4b) 4a)中提到的I/O completion call back A中需要請求Power Manager依據上述IRP_MN_SET_POWER system-irp的內容,發送一個IRP_MN_QUERY_POWER device-irp。在請求PM下發IRP_MN_SET_POWER device-irp的同時,設置completion call back D函數,同時返回STATUS_MORE_PROCESSING_REQUIRED。
4c) function driver收到IRP_MN_SET_POWER device-irp,需要明確Set power的state,確認是power-up還是power-down。
4c1) 如果是power-up irp,首先需要將此irp下發至底層bus driver,因爲device首先需要底層bus供電。除此之外,function driver還需要等待所有pending irp結束後方可開始操作。當然function driver不可以直接阻塞等待,因爲會影響到系統的運行。通常的做法是:
-function driver將此device-irp設置爲pending,並設置I/O completion call back E,在底層bus driver處理完畢後會call到此call back。之後將此irp下發至底層driver,並返回STATUS_PENDING,此時system-irp、device-irp都處於pending狀態
-在bus driver complete上述device-irp後,會call上述I/O completion call back E,此時function driver仍然需要等待之前處於pending的irp結束。由於在completion call back中無法死等,因此需要透過system work thread在PASSIVE_LEVEL來處理。可以設置一個workitem A,並返回STATUS_MORE_PROCESSING_REQUIRED。
-system worker thread會在PASSIVE_LEVEL調用上述workitem A,可以等待所有處於pending的irp結束後在返回。最終會complete上述device-irp。
4c2) 如果是power-down irp,function driver需要在下發此device-irp之前做一些必要的處理,因爲一旦bus driver斷電後,resume時所需的一些必要操作將變得不可訪問。
-function driver可以通過設置workitem B,並返回SSTATUS_PENDING。而在system worker thread PASSIVE_LEVEL中做一些必要的backup操作。
-system worker thread會在PASSIVE_LEVEL調用上述workitem B,在backup動作完成後,將此device-irp下發至底層driver。
4d) 在completion call back D中將IRP_MN_QUERY_POWER system-irp的status設置爲IRP_MN_QUERY_POWER device-irp的status。同時complete IRP_MN_QUERY_POWER system-irp。