Compartilhar via


Passando IRPs de energia

Os IRPs de energia devem ser passados até a pilha do dispositivo para o PDO para garantir que as transições de energia sejam gerenciadas corretamente. Os drivers lidam com um IRP que reduz a energia do dispositivo à medida que o IRP percorre a pilha do dispositivo. Os drivers lidam com um IRP que aplica a energia do dispositivo em rotinas IoCompletion à medida que o IRP faz backup da pilha de dispositivos.

A figura a seguir mostra as etapas que os drivers precisam executar para passar um IRP de energia para baixo em uma pilha de dispositivos no Windows 7 e no Windows Vista.

diagrama ilustrando a passagem de uma irp de energia no Windows Vista.

Como mostra a figura anterior, no Windows 7 e no Windows Vista, um driver deve fazer o seguinte:

  1. Chame IoCopyCurrentIrpStackLocationToNext se estiver definindo uma rotina IoCompletion ou IoSkipCurrentIrpStackLocation se não definir uma rotina IoCompletion .

    Essas duas rotinas definem o local da pilha IRP para o driver inferior seguinte. Copiar o local da pilha atual garante que o ponteiro da pilha IRP esteja definido como o local correto quando a rotina IoCompletion for executada.

    Se um driver mal escrito cometer o erro de chamar IoSkipCurrentIrpStackLocation e, em seguida, definir uma rotina de conclusão, esse driver poderá substituir uma rotina de conclusão definida pelo driver abaixo dele.

  2. Chame IoSetCompletionRoutine para definir uma rotina IoCompletion , se uma rotina completa for necessária.

  3. Chame IoCallDriver para passar o IRP para o driver inferior seguinte na pilha.

A figura a seguir mostra as etapas que os drivers precisam executar para passar um IRP de energia para baixo em uma pilha de dispositivos no Windows Server 2003, Windows XP e Windows 2000.

passando um irp de energia (windows server 2003, windows xp e windows 2000).

Como mostra a figura anterior, um driver deve fazer o seguinte:

  1. Dependendo do tipo de driver, possivelmente chame PoStartNextPowerIrp. Para obter mais informações, consulte Chamando PoStartNextPowerIrp.

  2. Chame IoCopyCurrentIrpStackLocationToNext se estiver definindo uma rotina IoCompletion ou IoSkipCurrentIrpStackLocation se não definir uma rotina IoCompletion .

    Essas duas rotinas definem o local da pilha IRP para o driver inferior seguinte. Copiar o local da pilha atual garante que o ponteiro da pilha IRP esteja definido como o local correto quando a rotina IoCompletion for executada.

  3. Chame IoSetCompletionRoutine para definir uma rotina IoCompletion . Na rotina IoCompletion , a maioria dos drivers chama PoStartNextPowerIrp para indicar que ele está pronto para lidar com o próximo IRP de energia.

  4. Chame PoCallDriver para passar o IRP para o driver inferior na pilha.

    Os drivers devem usar PoCallDriver, em vez de IoCallDriver (como para outros IRPs) para garantir que o sistema sincronize os IRPs de energia corretamente. Para obter mais informações, consulte Chamando IoCallDriver vs. Chamando PoCallDriver.

Lembre-se de que as rotinas IoCompletion podem ser chamadas em IRQL = DISPATCH_LEVEL. Portanto, se um driver exigir processamento adicional em IRQL = PASSIVE_LEVEL após a conclusão dos drivers de nível inferior com o IRP, a rotina de conclusão do driver deverá enfileirar um item de trabalho e, em seguida, retornar STATUS_MORE_PROCESSING_REQUIRED. O thread de trabalho deve concluir o IRP.

No Windows 98/Me, os drivers devem concluir os IRPs de energia em IRQL = PASSIVE_LEVEL.

Não alterar os códigos de função em um POWER IRP

Além das regras usuais que regem o processamento de IRPs, IRP_MJ_POWER IRPs têm o seguinte requisito especial: um driver que recebe um IRP de energia não deve alterar os códigos de função principal e secundária em nenhum local de pilha de E/S no IRP que tenha sido definido pelo power manager ou por drivers de nível superior. O power manager depende desses códigos de função permanecerem inalterados até que o IRP seja concluído. Violações dessa regra podem causar problemas difíceis de depurar. Por exemplo, o sistema operacional pode parar de responder ou "travar".

Não bloquear durante o tratamento de um IRP de energia

Os drivers não devem causar longos atrasos durante o tratamento de IRPs de energia.

Ao passar um IRP de energia, um driver deve retornar de sua rotina DispatchPower o mais rápido possível depois de chamar IoCallDriver (no Windows 7 e Windows Vista) ou PoCallDriver (no Windows Server 2003, Windows XP e Windows 2000). Um driver não deve esperar por um evento de kernel ou, caso contrário, atrasar antes de retornar. Se um driver não puder manipular um IRP de energia em breve, ele deverá retornar STATUS_PENDING e enfileirar todos os IRPs de entrada até que o IRP de energia seja concluído. (Observe que esse comportamento é diferente do das rotinas PnP IRPs e DispatchPnP , que têm permissão para bloquear.)

Se o driver precisar aguardar uma ação de energia por outro driver mais abaixo na pilha do dispositivo, ele deverá retornar STATUS_PENDING de sua rotina DispatchPower e definir uma rotina IoCompletion para o IRP de energia. O driver pode executar todas as tarefas necessárias na rotina IoCompletion e chamar PoStartNextPowerIrp (somente Windows Server 2003, Windows XP e Windows 2000) e IoCompleteRequest.

Por exemplo, o proprietário da política de energia de um dispositivo normalmente envia um IRP de energia do dispositivo enquanto mantém um IRP de energia do sistema para definir o estado de energia do dispositivo apropriado para o estado de energia do sistema solicitado.

Nessa situação, o proprietário da política de energia deve definir uma rotina IoCompletion no IRP de energia do sistema, passar o IRP de energia do sistema para o driver mais baixo e retornar STATUS_PENDING de sua rotina DispatchPower .

Na rotina IoCompletion , ele chama PoRequestPowerIrp para enviar o IRP de energia do dispositivo, passando um ponteiro para uma rotina de retorno de chamada na solicitação. A rotina IoCompletion deve retornar STATUS_MORE_PROCESSING_REQUIRED.

Por fim, o driver passa o IRP do sistema da rotina de retorno de chamada. O driver não deve esperar por um evento de kernel em sua rotina DispatchPower e sinalizar com a rotina IoCompletion para o IRP que está tratando no momento; um deadlock do sistema pode ocorrer. Para obter mais informações, consulte Manipulando um sistema Set-Power IRP em um proprietário de política de energia do dispositivo.

Em uma situação semelhante, quando o sistema vai entrar em suspensão, um proprietário de política de energia pode precisar concluir algumas E/S pendentes antes de enviar o IRP do dispositivo para desligar seu dispositivo. Em vez de sinalizar um evento quando a E/S for concluída e aguardar em sua rotina DispatchPower , o driver deve enfileirar um item de trabalho e retornar STATUS_PENDING da rotina DispatchPower . No thread de trabalho, ele aguarda a conclusão da E/S e envia o IRP de energia do dispositivo. Para obter mais informações, consulte IoAllocateWorkItem.