디바이스 전원 상태에 대한 IRP_MN_QUERY_POWER 또는 IRP_MN_SET_POWER 보내기

디바이스 전원 정책 소유자는 디바이스 전원 상태 변경을 수용할 수 있는지 여부를 확인하기 위해 디바이스 쿼리 전원 IRP(IRP_MN_QUERY_POWER)와 디바이스 전원 상태를 변경하는 디바이스 세트 전원 IRP(IRP_MN_SET_POWER)를 보냅니다. (이 드라이버는 대기/절전 모드 해제 IRP를 보내 외부 신호에 대한 응답으로 디바이스가 각성되도록 할 수도 있습니다. 자세한 내용은 Wake-Up 기능이 있는 지원 디바이스 를 참조하세요.)

다음 중 하나가 true인 경우 드라이버는 IRP_MN_QUERY_POWER 요청을 보내야 합니다.

  • 드라이버는 시스템 쿼리 전원 IRP를 받습니다.

  • 드라이버는 유휴 디바이스를 절전 모드 상태로 전환할 준비를 하고 있으므로 낮은 드라이버를 쿼리하여 가능한지 확인해야 합니다.

드라이버는 다음 중 하나라도 true인 경우 IRP_MN_SET_POWER 요청을 보내야 합니다.

  • 드라이버가 디바이스가 유휴 상태이며 절전 모드로 전환할 수 있음을 확인했습니다.

  • 디바이스가 절전 모드이고 대기 중인 I/O를 처리하기 위해 작업 상태를 다시 입력해야 합니다.

  • 드라이버는 시스템 설정 전원 IRP를 받습니다.

드라이버는 자체 전원 IRP를 할당해서는 안 되며, Power Manager는 이 목적을 위해 PoRequestPowerIrp 루틴을 제공합니다. Power IRP 처리 규칙에서 설명한 대로 PoRequestPowerIrp는 IRP를 할당하고 전송하며, IoCallDriver(Windows 7 및 Windows Vista의 경우) 또는 PoCallDriver(Windows Server 2003, Windows XP 및 Windows 2000)와 함께 모든 전원 요청이 제대로 동기화되도록 합니다. PoRequestPowerIrp의 호출자는 IRQL <= DISPATCH_LEVEL 실행되어야 합니다.

다음은 이 루틴의 프로토타입입니다.

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
    );

IRP를 보내기 위해 드라이버는 PoRequestPowerIrp를 호출하여 DeviceObject의 대상 디바이스 개체에 대한 포인터를 지정하고, 부 IRP 코드는 PowerStateDevicePowerState 값인 MinorFunction에서 IRP_MN_SET_POWER 또는 IRP_MN_QUERY_POWER 지정합니다. PowerState의 유형 및 디바이스 전원 상태입니다. 상태. Windows 98/Me에서 DeviceObject 는 기본 디바이스의 PDO를 지정해야 합니다. Windows 2000 이상 버전의 Windows에서 이 값은 동일한 디바이스 스택에 있는 드라이버의 PDO 또는 FDO를 가리킬 수 있습니다.

다른 모든 드라이버가 IRP를 완료한 후 드라이버가 추가 작업을 수행해야 하는 경우 CompletionFunction의 전원 완성 함수에 대한 포인터를 전달해야 합니다. I/O 관리자는 드라이버가 IRP를 스택 아래로 전달할 때 설정한 모든 IoCompletion 루틴을 호출한 후 CompletionFunction을 호출합니다.

디바이스 전원 정책 소유자가 디바이스 파워 쿼리 IRP를 보낼 때마다 이후에 PoRequestPowerIrp 호출에서 지정한 콜백 루틴(CompletionFunction)에서 디바이스 집합 전원 IRP를 보내야 합니다. 쿼리가 성공하면 set-power IRP는 쿼리된 전원 상태를 지정합니다. 쿼리가 실패하면 설정 전원 IRP가 현재 디바이스 전원 상태를 다시 어설션합니다. 드라이버가 쿼리에 대한 응답으로 I/O를 큐에 넣기 때문에 현재 상태를 다시 어설션하는 것이 중요합니다. 정책 소유자는 디바이스 스택의 드라이버에 큐에 대기 중인 I/O 요청 처리를 시작하도록 알리기 위해 설정 전원 IRP를 보내야 합니다.

디바이스의 정책 소유자는 디바이스 전원 IRP를 보낼 뿐만 아니라 디바이스 스택 아래로 전달될 때 IRP를 처리합니다. 따라서 이러한 드라이버는 IRP 처리 코드의 일부로 IoCompletion 루틴( IoSetCompletionRoutine 포함)을 설정하는 경우가 많습니다. 특히 디바이스 전원이 켜지는 경우 IoCompletion 루틴은 다른 드라이버에서 설정한 IoCompletion 루틴과 CompletionFunction 이전에 순서대로 호출됩니다. 자세한 내용은 디바이스 전원 IRP에 대한 IoCompletion 루틴을 참조하세요.

CompletionFunction이 호출될 때 모든 드라이버에서 IRP가 완료되었으므로 CompletionFunction은 IRP를 사용하여 IoCallDriver, PoCallDriver 또는 PoStartNextPowerIrp을 호출해서는 안 됩니다. (그러나 다른 전원 IRP에 대해 이러한 루틴을 호출할 수 있습니다.) 대신 이 루틴은 IRP를 시작한 드라이버에 필요한 추가 작업을 수행합니다. 드라이버가 시스템 IRP에 대한 응답으로 디바이스 IRP를 보낸 경우 CompletionFunction 에서 시스템 IRP를 완료할 수 있습니다. 자세한 내용은 디바이스 전원 정책 소유자에서 시스템 Set-Power IRP 처리를 참조하세요.

PoRequestPowerIrp 호출에 대한 응답으로 전원 관리자는 전원 IRP를 할당하고 디바이스에 대한 디바이스 스택의 맨 위로 보냅니다. Power Manager는 할당된 IRP에 대한 포인터를 반환합니다.

오류가 발생하지 않으면 PoRequestPowerIrp은 STATUS_PENDING 반환합니다. 이 상태 IRP가 성공적으로 전송되었으며 완료 보류 중임을 의미합니다. 전원 관리자가 IRP를 할당할 수 없거나 호출자가 잘못된 부 전원 IRP 코드를 지정한 경우 호출이 실패합니다.

디바이스 전원을 켜는 요청은 먼저 디바이스의 기본 버스 드라이버에 의해 처리된 다음 스택의 각 연속적으로 더 높은 드라이버에 의해 처리되어야 합니다. 따라서 PowerDeviceD0 요청을 보낼 때 드라이버는 IRP가 완료되고 디바이스 전원이 켜진 후 CompletionFunction 이 필요한 작업을 수행하는지 확인해야 합니다.

디바이스 전원을 끄면(PowerDeviceD3) 디바이스 스택의 각 드라이버는 필요한 컨텍스트를 모두 저장하고 IRP를 다음 하위 드라이버로 보내기 전에 필요한 모든 클린 수행해야 합니다. 컨텍스트 정보 및 클린 범위는 드라이버 유형에 따라 달라집니다. 함수 드라이버는 하드웨어 컨텍스트를 저장해야 합니다. 필터 드라이버는 자체 소프트웨어 컨텍스트를 저장해야 할 수 있습니다. 이 상황에서 CompleteFunction 집합은 완료된 전원 IRP와 관련된 작업을 수행할 수 있지만 드라이버는 디바이스에 액세스할 수 없습니다.