Passaggio di runtime di integrazione di Power

I runtime di integrazione di alimentazione devono essere passati fino allo stack di dispositivi al PDO per garantire che le transizioni di alimentazione vengano gestite correttamente. I driver gestiscono un IRP che riduce la potenza del dispositivo man mano che l'IRP si sposta verso il basso nello stack di dispositivi. I driver gestiscono un IRP che applica la potenza del dispositivo nelle routine IoCompletion durante il backup dello stack di dispositivi.

La figura seguente illustra i passaggi che i driver devono eseguire per passare un'alimentazione IRP in uno stack di dispositivi in Windows 7 e Windows Vista.

diagramma che illustra il passaggio di una potenza irp in Windows Vista.

Come illustrato nella figura precedente, in Windows 7 e Windows Vista, un driver deve eseguire le operazioni seguenti:

  1. Chiamare IoCopyCurrentIrpStackLocationToNext se si imposta una routine IoCompletion o IoSkipCurrentIrpStackLocation se non si imposta una routine IoCompletion .

    Queste due routine impostano la posizione dello stack IRP per il driver inferiore successivo. La copia del percorso dello stack corrente garantisce che il puntatore allo stack IRP sia impostato sulla posizione corretta quando viene eseguita la routine IoCompletion .

    Se un driver scritto male commette l'errore di chiamare IoSkipCurrentIrpStackLocation e quindi di impostare una routine di completamento, questo driver potrebbe sovrascrivere una routine di completamento impostata dal driver sottostante.

  2. Chiamare IoSetCompletionRoutine per impostare una routine IoCompletion , se è necessaria una routine completa.

  3. Chiamare IoCallDriver per passare l'IRP al driver inferiore successivo nello stack.

La figura seguente illustra i passaggi che i driver devono eseguire per passare un IRP di alimentazione in uno stack di dispositivi in Windows Server 2003, Windows XP e Windows 2000.

passando un irp di alimentazione (windows server 2003, windows xp e windows 2000).

Come illustrato nella figura precedente, un driver deve eseguire le operazioni seguenti:

  1. A seconda del tipo di driver, eventualmente chiamare PoStartNextPowerIrp. Per altre informazioni, vedere Chiamata di PoStartNextPowerIrp.

  2. Chiamare IoCopyCurrentIrpStackLocationToNext se si imposta una routine IoCompletion o IoSkipCurrentIrpStackLocation se non si imposta una routine IoCompletion .

    Queste due routine impostano la posizione dello stack IRP per il driver inferiore successivo. La copia del percorso dello stack corrente garantisce che il puntatore allo stack IRP sia impostato sulla posizione corretta quando viene eseguita la routine IoCompletion .

  3. Chiamare IoSetCompletionRoutine per impostare una routine IoCompletion . Nella routine IoCompletion la maggior parte dei driver chiama PoStartNextPowerIrp per indicare che è pronta per gestire l'IRP di alimentazione successiva.

  4. Chiamare PoCallDriver per passare l'IRP al driver inferiore successivo nello stack.

    I driver devono usare PoCallDriver, anziché IoCallDriver (come per altri IRP) per garantire che il sistema sincronizzi correttamente i runtime di integrazione di alimentazione. Per altre informazioni, vedere Chiamata di IoCallDriver e Chiamata di PoCallDriver.

Tenere presente che le routine IoCompletion possono essere chiamate in IRQL = DISPATCH_LEVEL. Pertanto, se un driver richiede un'elaborazione aggiuntiva in IRQL = PASSIVE_LEVEL dopo il completamento dei driver di livello inferiore, la routine di completamento del driver deve accodamento di un elemento di lavoro e quindi restituire STATUS_MORE_PROCESSING_REQUIRED. Il thread di lavoro deve completare l'IRP.

In Windows 98/Me i driver devono completare i runtime di integrazione di alimentazione in IRQL = PASSIVE_LEVEL.

Non modificare i codici di funzione in power IRP

Oltre alle consuete regole che regolano l'elaborazione dei provider di integrazione, IRP_MJ_POWER i provider di integrazione hanno il requisito speciale seguente: un driver che riceve un IRP di alimentazione non deve modificare i codici di funzione principali e secondari in qualsiasi posizione dello stack di I/O in IRP che sono stati impostati dal risparmio energia o da driver di livello superiore. Il risparmio energia si basa su questi codici di funzione che rimangono invariati fino al completamento dell'IRP. Le violazioni di questa regola possono causare problemi di cui è difficile eseguire il debug. Ad esempio, il sistema operativo potrebbe smettere di rispondere o "blocca".

Non bloccare durante la gestione di power IRP

I driver non devono causare ritardi lunghi durante la gestione dei runtime di integrazione di alimentazione.

Quando si passa un IRP di alimentazione, un driver deve tornare dalla routine DispatchPower appena possibile dopo aver chiamato IoCallDriver (in Windows 7 e Windows Vista) o PoCallDriver (in Windows Server 2003, Windows XP e Windows 2000). Un driver non deve attendere un evento del kernel o ritardare altrimenti prima di restituire . Se un driver non è in grado di gestire un IRP di alimentazione in breve tempo, deve restituire STATUS_PENDING e accodare tutti gli IRP in ingresso fino al completamento dell'IRP di alimentazione. Si noti che questo comportamento è diverso da quello delle routine PnP IRP e DispatchPnP , che possono essere bloccate.

Se il driver deve attendere un'azione di alimentazione da un altro driver verso il basso nello stack di dispositivi, deve restituire STATUS_PENDING dalla routine DispatchPower e impostare una routine IoCompletion per l'alimentazione IRP. Il driver può eseguire qualsiasi attività richiesta nella routine IoCompletion e quindi chiamare PoStartNextPowerIrp (Solo Windows Server 2003, Windows XP e Windows 2000) e IoCompleteRequest.

Ad esempio, il proprietario dei criteri di risparmio energia per un dispositivo invia in genere un IRP di alimentazione del dispositivo mantenendo un IRP di alimentazione del sistema per impostare lo stato di alimentazione del dispositivo appropriato per lo stato di alimentazione del sistema richiesto.

In questo caso, il proprietario dei criteri di alimentazione deve impostare una routine IoCompletion nell'IRP di alimentazione del sistema, passare l'IRP di alimentazione di sistema al driver inferiore successivo e restituire STATUS_PENDING dalla routine DispatchPower .

Nella routine IoCompletion chiama PoRequestPowerIrp per inviare l'IRP di alimentazione del dispositivo, passando un puntatore a una routine di callback nella richiesta. La routine IoCompletion deve restituire STATUS_MORE_PROCESSING_REQUIRED.

Infine, il driver passa l'IRP di sistema dalla routine di callback. Il driver non deve attendere un evento kernel nella routine DispatchPower e segnalare con la routine IoCompletion per il protocollo IRP attualmente gestito ; potrebbe verificarsi un deadlock di sistema. Per altre informazioni, vedere Gestione di un Set-Power IRP di sistema in un proprietario di Criteri di risparmio energia del dispositivo.

In una situazione simile, quando il sistema sta per dormire, un proprietario dei criteri di alimentazione potrebbe dover completare alcune operazioni di I/O in sospeso prima di inviare l'IRP del dispositivo per spegnere il dispositivo. Invece di segnalare un evento quando l'I/O viene completato e in attesa nella routine DispatchPower , il driver deve accodare un elemento di lavoro e restituire STATUS_PENDING dalla routine DispatchPower . Nel thread di lavoro attende il completamento dell'I/O e quindi invia l'IRP di alimentazione del dispositivo. Per altre informazioni, vedere IoAllocateWorkItem.