Condividi tramite


Uso delle routine del servizio interrupt a livello passivo

A partire da Windows 8, un driver può usare la routine Io Connessione InterruptEx per registrare una routine InterruptService (ISR) a livello passivo. Quando si verifica l'interrupt associato, il gestore di trap di interrupt del kernel pianifica l'esecuzione di questa routine in IRQL = PASSIVE_LEVEL. Un ISR potrebbe dover essere eseguito a livello passivo se può accedere ai registri hardware di un dispositivo solo tramite richieste di I/O. Un ISR a livello passivo può inviare in modo sincrono una richiesta di I/O a un dispositivo e bloccare fino al completamento della richiesta.

Registrazione di un ISR a livello passivo

Il parametro di input per Io Connessione InterruptEx è un puntatore a una struttura IO_CONNECT_INTERRUPT_PARAMETERS. Per registrare un ISR a livello passivo, impostare il membro Version di questa struttura su CONNECT_FULLY_SPECIFIED o CONNECT_LINE_BA edizione Standard D. Se Version = CONNECT_FULLY_SPECIFIED, impostare il membro Irql su PASSIVE_LEVEL, il membro SynchronizeIrql su PASSIVE_LEVEL e il membro SpinLock su NULL. Se Version = CONNECT_LINE_BA edizione Standard D, impostare SynchronizeIrql = PASSIVE_LEVEL e SpinLock = NULL.

Se l'oggetto interrupt specifica un ISR a livello passivo, la routine KeSynchronizeExecution usa un oggetto evento di sincronizzazione del kernel anziché un blocco di selezione per sincronizzare l'esecuzione della routine SynchCritSection con l'ISR.

Questo oggetto evento viene allocato dalla routine Io Connessione InterruptEx nella chiamata che registra l'ISR a livello passivo. Il chiamante non deve fornire un blocco di selezione in questa chiamata. (vale a dire, il chiamante deve impostare Membro SpinLock della struttura IO_CONNECT_INTERRUPT_PARAMETERS su NULL se l'ISR deve essere eseguito a livello passivo. In caso contrario, Io Connessione InterruptEx ha esito negativo e restituisce lo stato di errore STATUS_INVALID_PARAMETER.

Le routine KeAcquireInterruptSpinLock e KeReleaseInterruptSpinLock causano un controllo bug se l'ISR per l'oggetto interrupt fornito viene eseguito in IRQL = PASSIVE_LEVEL.

Dispositivi che richiedono la gestione degli interrupt a livello passivo

Per un dispositivo mappato alla memoria che segnala una richiesta di interrupt attivata a livello, l'ISR del dispositivo viene in genere chiamato in DIRQL dall'interno del gestore di trap di interrupt del kernel. L'ISR modifica i registri hardware nel dispositivo per disattivare l'interrupt.

Tuttavia, potrebbe essere necessario eseguire un ISR in IRQL = PASSIVE_LEVEL se il dispositivo associato segnala una richiesta di interrupt attivata dal livello, ma non è possibile accedere ai registri hardware del dispositivo direttamente da un ISR chiamato in DIRQL dall'interno del gestore di trap di interrupt del kernel. Ad esempio, i registri dei dispositivi potrebbero non essere mappati alla memoria o l'ISR potrebbe essere temporaneamente bloccato durante un accesso al registro.

A partire da Windows 8, un driver può registrare un ISR a livello passivo. Quando si verifica l'interrupt, il gestore di trap di interrupt del kernel pianifica l'esecuzione dell'ISR in IRQL = PASSIVE_LEVEL. Prima che il gestore venga restituito, deve disattivare l'interrupt nel controller di interrupt (o nel controller GPIO). Se un dispositivo segnala un interrupt attivato da edge, il gestore cancella l'interrupt nel controller di interrupt. Se il dispositivo segnala un interrupt attivato a livello, il gestore maschera temporaneamente l'interrupt nel controller interrupt; dopo l'esecuzione dell'ISR, il kernel annulla il mascherato dell'interrupt.

un esempio

Un esempio di dispositivo che potrebbe richiedere un ISR a livello passivo è un dispositivo sensore connesso a un bus seriale a basso consumo, ad esempio I²C. A partire da Windows 8, il supporto per I²C e per altri bus periferici semplici (SPB) è fornito dall'estensione del framework SPB (SpbCx).

Per accedere ai registri del dispositivo sensore connesso a I²C, il driver del sensore invia al dispositivo sensore una richiesta di I/O, gestita congiuntamente da SpbCx e dal driver controller per il bus. Per eseguire l'operazione richiesta, il controller SPB deve trasferire i dati in modo seriale sul bus. Questo trasferimento è relativamente lento e non può essere eseguito entro i vincoli temporali di un ISR eseguito in DIRQL. Tuttavia, un ISR a livello passivo può inviare la richiesta di I/O in modo sincrono e quindi bloccare fino al completamento della richiesta.

L'ISR a livello passivo in questo esempio potrebbe essere bloccato per un periodo di tempo più lungo se il controller bus I²C viene disattivato quando l'ISR invia la richiesta di I/O al dispositivo di interruzione. In questo caso, il controller deve completare la transizione allo stato di alimentazione D0 prima di poter trasferire i dati sul bus.

A differenza di un bus come PCI, il bus I²C in questo esempio non fornisce mezzi specifici del bus per trasmettere richieste di interruzione dai dispositivi periferici al processore. Al contrario, il dispositivo sensore potrebbe segnalare un interrupt a un pin in un dispositivo controller GPIO, che quindi inoltra la richiesta di interrupt al processore. Per altre informazioni, vedere Interrupt GPIO.

In genere, i registri hardware di un controller GPIO sono mappati alla memoria e possono essere accessibili in DIRQL dal gestore di trap interrupt del kernel. Quando il dispositivo sensore causa un interrupt, il gestore deve disattivare l'interrupt modificando i bit di interrupt nei registri del controller GPIO.

Per un interrupt attivato a livello di livello, il gestore di trap interrupt del kernel maschera la richiesta di interrupt al pin GPIO e quindi pianifica l'esecuzione dell'ISR del dispositivo sensore a livello passivo. L'ISR deve cancellare la richiesta di interrupt dal dispositivo sensore. Al termine dell'ISR, il kernel annulla il maschera della richiesta di interrupt al pin GPIO.

Per un interrupt attivato da edge, il gestore trap del kernel cancella la richiesta di interrupt al pin GPIO e quindi pianifica l'esecuzione dell'ISR del dispositivo sensore a livello passivo.

Routine di lavoro

Nella chiamata a Io Connessione InterruptEx, un driver ha la possibilità di suddividere l'elaborazione dell'interrupt tra un ISR a livello passivo e una routine di lavoro. Come regola generale, l'ISR deve eseguire l'elaborazione iniziale dell'interrupt (ad esempio, disattivare un interrupt attivato dal livello) e rinviare l'elaborazione aggiuntiva al ruolo di lavoro. Anche se sia l'ISR che il ruolo di lavoro vengono eseguiti a livello passivo, l'ISR viene eseguito con priorità relativamente alta e potrebbe ritardare altre attività con priorità alta. Queste attività possono includere isr a livello passivo per i nuovi interrupt.

In rari casi, un interrupt potrebbe richiedere un'elaborazione così piccola che l'ISR a livello passivo possa eseguire tutta l'elaborazione per l'interrupt e non è necessaria alcuna routine di lavoro.

Per informazioni sull'uso di ISR a livello passivo nei driver KMDF, vedere Supporto di interrupt a livello passivo.