Partilhar via


Encaminhamento de IRPs de energia

Os IRPs de energia devem ser passados pela pilha de dispositivos até ao DOP para garantir que as transições de energia sejam geridas de forma limpa. Os drivers lidam com um IRP que reduz a energia do dispositivo à medida que o IRP percorre a pilha de dispositivos. Os drivers lidam com um IRP que aplica a potência do dispositivo nas rotinas do IoCompletion enquanto o IRP sobe de volta na pilha de dispositivos.

A figura a seguir mostra os passos que os drivers precisam seguir para passar um IRP de energia por uma pilha de dispositivos no Windows 7 e Windows Vista.

Diagrama que ilustra a transmissão de um 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 estiver definindo uma rotina IoCompletion.

    Essas duas rotinas definem a localização da pilha de IRP para o driver de nível inferior seguinte. Copiar o local da pilha atual garante que o ponteiro da pilha IRP seja ajustado para o local correto quando a rotina IoCompletion for executada.

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

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

  3. Chame IoCallDriver para passar o IRP para o próximo driver inferior na pilha.

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

Transferindo um Power IRP (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, pode ser necessário chamar PoStartNextPowerIrp. Para obter mais informações, consulte Invocar PoStartNextPowerIrp.

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

    Essas duas rotinas definem o local da pilha de IRP para o próximo driver inferior. Copiar a posição atual da pilha assegura que o ponteiro da pilha IRP seja ajustado para a posição correta quando a rotina IoCompletion é executada.

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

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

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

Lembre-se que as rotinas IoCompletion podem ser chamadas em IRQL = DISPATCH_LEVEL. Portanto, se um driver precisar de processamento adicional no IRQL = PASSIVE_LEVEL após os drivers de nível inferior concluírem com o IRP, a rotina de conclusão do driver deve 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 pedidos de IRP de energia em nível IRQL igual a PASSIVE_LEVEL.

Não altere os códigos de função em um IRP de energia

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 gerenciador de energia ou por drivers de nível superior. O gerenciador de energia depende que esses códigos de função permaneçam inalterados até que o IRP seja concluído. As violações desta regra podem causar problemas difíceis de depurar. Por exemplo, o sistema operativo pode parar de responder ou "bloquear".

Não bloqueie ao manusear um IRP de energia

Os motoristas não devem causar grandes atrasos durante o manuseio 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 do kernel ou atrasar-se de qualquer outra forma antes de retornar. Se um driver não puder processar um IRP de energia rapidamente, deverá retornar STATUS_PENDING e enfileirar todos os IRPs de entrada até que o IRP de energia seja concluído. (Observe que este comportamento é diferente em relação ao de IRPs de PnP e rotinas DispatchPnP, que têm permissão para bloquear.)

Se o driver precisar aguardar uma ação de energia de outro driver mais abaixo na pilha de dispositivos, ele deverá retornar STATUS_PENDING de sua rotina DispatchPower e definir uma rotina IoCompletion para o IRP de energia. O driver pode executar quaisquer tarefas necessárias na rotina IoCompletion e, em seguida, chamar PoStartNextPowerIrp (Windows Server 2003, Windows XP e Windows 2000 apenas) 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 inferior seguinte e retornar STATUS_PENDING na 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.

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

Em uma situação semelhante, quando o sistema está a dormir, um responsável pela política de energia pode precisar concluir algumas operações de entrada/saída pendentes antes de enviar o IRP do dispositivo para encerrar o dispositivo. Em vez de sinalizar um evento quando a E/S é concluída e aguardando na sua rotina DispatchPower, o driver deve enfileirar um item de trabalho e retornar STATUS_PENDING na rotina DispatchPower. No thread de trabalho, ele aguarda a conclusão da E/S e, em seguida, envia o IRP de energia do dispositivo. Para obter mais informações, consulte IoAllocateWorkItem.