WDM Power IRP 学习 (一)

    电源管理是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。


sample可以参考WDK
WinDDK\7600.16385.1\src\general\toaster\wdm\func\featured1


你可能感兴趣的:(WDM Power IRP 学习 (一))