Envío de IRP_MN_QUERY_POWER o IRP_MN_SET_POWER para estados de energía del dispositivo

El propietario de una directiva de alimentación de dispositivo envía un IRP de consulta de dispositivo (IRP_MN_QUERY_POWER) para determinar si los controladores inferiores pueden dar cabida a un cambio en el estado de alimentación del dispositivo y un IRP (IRP_MN_SET_POWER) del conjunto de dispositivos para cambiar el estado de alimentación del dispositivo. (Este controlador también puede enviar un IRP de espera/reactivación para permitir que su dispositivo se despierte en respuesta a una señal externa; consulte Compatibilidad con dispositivos que tienen Wake-Up funcionalidades para obtener más información).

El controlador debe enviar una solicitud de IRP_MN_QUERY_POWER cuando se cumple alguna de las siguientes condiciones:

  • El controlador recibe un IRP de alimentación de consulta del sistema.

  • El controlador se prepara para poner un dispositivo inactivo en un estado de suspensión, por lo que debe consultar controladores inferiores para averiguar si hacerlo es factible.

El controlador debe enviar una solicitud de IRP_MN_SET_POWER cuando se cumple cualquiera de las siguientes condiciones:

  • El controlador ha determinado que el dispositivo está inactivo y se puede poner en suspensión.

  • El dispositivo está en suspensión y debe volver a entrar en el estado de trabajo para controlar la E/S en espera.

  • El controlador recibe un IRP de configuración del sistema.

Un controlador no debe asignar su propio IRP de energía; el administrador de energía proporciona la rutina PoRequestPowerIrp para este propósito. Como explica Reglas para controlar los IRP de Power , PoRequestPowerIrp asigna y envía el IRP, y en combinación con IoCallDriver (en Windows 7 y Windows Vista) o PoCallDriver (en Windows Server 2003, Windows XP y Windows 2000), garantiza que todas las solicitudes de energía estén sincronizadas correctamente. Los autores de llamadas de PoRequestPowerIrp deben ejecutarse en IRQL <= DISPATCH_LEVEL.

A continuación se muestra el prototipo de esta rutina:

NTSTATUS
PoRequestPowerIrp (
    IN PDEVICE_OBJECT DeviceObject,
    IN UCHAR MinorFunction,
    IN POWER_STATE PowerState,
    IN PREQUEST_POWER_COMPLETE CompletionFunction,
    IN PVOID Context,
    OUT PIRP *Irp OPTIONAL
    );

Para enviar el IRP, el controlador llama a PoRequestPowerIrp, especificando un puntero al objeto de dispositivo de destino en DeviceObject, el código IRP secundario IRP_MN_SET_POWER o IRP_MN_QUERY_POWER en MinorFunction, el valor DevicePowerState en PowerState. Escriba y un estado de alimentación del dispositivo en PowerState. Estado. En Windows 98/Me, DeviceObject debe especificar el PDO del dispositivo subyacente; en Windows 2000 y versiones posteriores de Windows, este valor puede apuntar a PDO o A FDO de un controlador en la misma pila de dispositivos.

Si el controlador debe realizar tareas adicionales después de que todos los demás controladores hayan completado el IRP, debe pasar un puntero a una función de finalización de energía en CompletionFunction. El administrador de E/S llama a CompletionFunction después de llamar a todas las rutinas de IoCompletion establecidas por los controladores a medida que pasaron el IRP a la pila.

Cada vez que el propietario de una directiva de energía de dispositivo envía un IRP de consulta de energía del dispositivo, debe enviar posteriormente un IRP de configuración de dispositivo desde la rutina de devolución de llamada (CompletionFunction) que especificó en la llamada a PoRequestPowerIrp. Si la consulta se realizó correctamente, el IRP set-power especifica el estado de energía consultado. Si se produjo un error en la consulta, el IRP set-power vuelve a validar el estado de alimentación del dispositivo actual. Volver a afirmar el estado actual es importante porque los controladores ponen en cola la E/S en respuesta a la consulta; El propietario de la directiva debe enviar el IRP de set-power para notificar a los controladores de su pila de dispositivos para comenzar a procesar las solicitudes de E/S en cola.

Tenga en cuenta que el propietario de la directiva de un dispositivo no solo envía el IRP de alimentación del dispositivo, sino que también controla el IRP a medida que se pasa a la pila de dispositivos. Por lo tanto, este controlador suele establecer una rutina de IoCompletion (con IoSetCompletionRoutine) como parte de su código de control IRP, especialmente cuando el dispositivo está encendido. Se llama a la rutina IoCompletion en secuencia con rutinas de IoCompletion establecidas por otros controladores y antes de CompletionFunction. Para más información, consulte Rutinas de IoCompletion para IRP de power del dispositivo.

Dado que todos los controladores han completado el IRP cuando se llama a CompletionFunction, CompletionFunction no debe llamar a IoCallDriver, PoCallDriver o PoStartNextPowerIrp con el IRP que se originó. (Sin embargo, podría llamar a estas rutinas para un IRP de potencia diferente). En su lugar, esta rutina realiza cualquier acción adicional requerida por el controlador que originó el IRP. Si el controlador envió el IRP del dispositivo en respuesta a un IRP del sistema, completionFunction podría completar el IRP del sistema. Para obtener más información, consulte Control de un IRP del sistema Set-Power en un propietario de la directiva de energía del dispositivo.

En respuesta a la llamada a PoRequestPowerIrp, el administrador de energía asigna un IRP de energía y lo envía a la parte superior de la pila de dispositivos para el dispositivo. El administrador de energía devuelve un puntero al IRP asignado.

Si no se produce ningún error, PoRequestPowerIrp devuelve STATUS_PENDING. Este estado significa que el IRP se ha enviado correctamente y está pendiente de finalización. Se produce un error en la llamada si el administrador de energía no puede asignar el IRP o si el autor de la llamada ha especificado un código IRP de energía secundaria no válido.

Las solicitudes para encender un dispositivo deben controlarse primero por el controlador de bus subyacente para el dispositivo y, a continuación, por cada controlador sucesivamente superior en la pila. Por lo tanto, al enviar una solicitud PowerDeviceD0 , el controlador debe asegurarse de que completionFunction realiza las tareas necesarias una vez completado el IRP y el dispositivo está encendido.

Al apagar un dispositivo (PowerDeviceD3), cada controlador de la pila de dispositivos debe guardar todo su contexto necesario y realizar cualquier limpieza necesaria antes de enviar el IRP al controlador inferior siguiente. La extensión de la información del contexto y la limpieza depende del tipo de controlador. Un controlador de función debe guardar el contexto de hardware; Es posible que un controlador de filtro tenga que guardar su propio contexto de software. Un elemento CompletionFunction establecido en esta situación puede realizar acciones asociadas a un IRP de alimentación completado, pero el controlador no puede acceder al dispositivo.