Sequenze di trasferimento di I/O

L'estensione spb framework (SpbCx) supporta le sequenze di trasferimento di I/O. Una sequenza di trasferimento di I/O è un set ordinato di trasferimenti di bus (operazioni di lettura e scrittura) eseguite come singola operazione atomica del bus. Tutti i trasferimenti in una sequenza di trasferimento di I/O accedono allo stesso dispositivo di destinazione sul bus. Durante l'esecuzione di una sequenza, non è possibile accedere ad altri dispositivi sul bus, anche se il driver del controller SPB potrebbe ricevere richieste di I/O per altri dispositivi prima del completamento della sequenza di trasferimento di I/O.

Un esempio di sequenza di trasferimento di I/O è un'operazione di lettura scrittura, che è un'operazione di scrittura del bus seguita da un'operazione di lettura del bus. Un driver di dispositivo periferica client può usare questo tipo di sequenza per scrivere in un registro di selezione funzione in un dispositivo periferico connesso a SPB e quindi leggere il valore della funzione del dispositivo selezionata. Questi due trasferimenti possono essere di lunghezza diversa. Ad esempio, l'operazione di scrittura potrebbe trasferire un byte di dati e l'operazione di lettura potrebbe trasferire molti byte di dati.

Tipi di sequenze di trasferimento I/O

Un client può avviare una sequenza di trasferimento di I/O in uno dei modi seguenti:

  1. Il client può specificare l'intera sequenza in una richiesta di controllo I/O IOCTL_SPB_EXECUTE_SEQUENCE . Questa richiesta consente al driver del controller SPB di usare le ottimizzazioni delle prestazioni specifiche dell'hardware disponibili per eseguire la sequenza di trasferimento. Per altre informazioni, vedere Sequenze di richieste singole.

  2. Il client può inviare una richiesta di controllo I/O IOCTL_SPB_LOCK_CONTROLLER per bloccare il controller all'inizio di una sequenza e inviare un IOCTL_SPB_UNLOCK_CONTROLLER al termine della sequenza. Mentre il controller è bloccato, il client invia una richiesta di I/O separata (IRP_MJ_READ o IRP_MJ_WRITE) per ogni operazione di lettura o scrittura nella sequenza. Per altre informazioni, vedere Sequenze implementate dal client.

Quando possibile, un client deve usare la richiesta di IOCTL_SPB_EXECUTE_SEQUENCE , che è più veloce, è meno soggetta a errori e riduce significativamente il tempo durante il quale altri client sono bloccati fuori dal bus. Tuttavia, un client può usare il IOCTL_SPB_LOCK_CONTROLLER e IOCTL_SPB_UNLOCK_CONTROLLER richieste se deve esaminare il valore letto durante uno dei trasferimenti nella sequenza prima di poter avviare un trasferimento successivo nella sequenza. In questo caso, è necessario un'attenta progettazione per evitare di bloccare altri client dall'autobus per più tempo di quanto necessario e un driver periferico progettato in modo errato può compromettere le prestazioni complessive del sistema.

sequenze Single-Request

Per migliorare le prestazioni, il driver del controller SPB deve implementare una funzione di callback EvtSpbControllerIoSequence per gestire le richieste IOCTL_SPB_EXECUTE_SEQUENCE . Questo approccio aggiunge una certa complessità al driver del controller SPB, ma evita di richiedere al client di eseguire una sequenza di trasferimento di I/O come una serie di singole operazioni di lettura e scrittura mentre altri client sono bloccati fuori dal bus.

Nota

L'implementazione di una funzione EvtSpbControllerIoSequence è fortemente consigliata e potrebbe diventare un requisito per Windows 8.

L'implementazione di una sequenza di trasferimento è simile a quella di una semplice operazione di lettura o scrittura, ma richiede inoltre aggiornamenti allo stato archiviato dell'operazione di sequenza tra i singoli trasferimenti nella sequenza. Al termine del primo trasferimento, il driver del controller SPB aggiorna lo stato della sequenza per selezionare il trasferimento successivo nella sequenza. Lo stato della sequenza viene archiviato nel contesto del dispositivo e include l'handle SPBREQUEST passato al callback EvtSpbControllerIoSequence . Il driver del controller SPB usa questo handle per ottenere i parametri buffer, length, direction e position per i singoli trasferimenti nella sequenza. Per altre informazioni su come ottenere questi parametri, vedere SpbRequestGetTransferParameters.

Se il driver del controller SPB non riesce a eseguire l'operazione di IOCTL_SPB_EXECUTE_SEQUENCE richiesta, completa la richiesta con un codice di errore. Se si verifica un errore di questo tipo, il client può, come opzione, bloccare il bus, eseguire in modo esplicito la sequenza di trasferimento di I/O come una serie di semplici richieste di I/O e quindi sbloccare il bus. Per altre informazioni, vedere Sequenze implementate dal client.

SpbCx esegue il controllo dei parametri sulle richieste IOCTL_SPB_XXX ricevute dai driver di dispositivo periferici. Per le richieste di IOCTL_SPB_EXECUTE_SEQUENCE , SpbCx rifiuta sia sequenze vuote che sequenze contenenti puntatori a buffer NULL o buffer di lunghezza zero.

Il driver del controller SPB deve verificare che la lunghezza di ogni trasferimento in una sequenza non superi il limite specificato dal driver. Ad esempio, il driver di esempio SkeletonI2C in Windows Driver Kit (WDK) non riesce una richiesta di IOCTL_SPB_EXECUTE_SEQUENCE che specifica un trasferimento superiore a 4 KB di byte e imposta il codice di stato per questa richiesta su STATUS_INVALID_PARAMETER. Prima di avviare un'operazione di sequenza per una richiesta di IOCTL_SPB_EXECUTE_SEQUENCE , il driver deve convalidare i parametri per tutti i trasferimenti nella sequenza per verificare che l'operazione possa essere completata correttamente.

SpbCx non precede mai un callback EvtSpbControllerIoSequence con un callback EvtSpbControllerLock e non segue mai un callback EvtSpbControllerIoSequence con un callback EvtSpbControllerUnlock .

sequenze Client-Implemented

Un client di un driver controller SPB può eseguire in modo esplicito una sequenza di trasferimento di I/O come una serie di letture e scritture semplici. Il client può essere un driver in modalità kernel o un driver in modalità utente che controlla un dispositivo periferico collegato al bus. Prima del primo trasferimento nella sequenza, il client invia una richiesta di IOCTL_SPB_LOCK_CONTROLLER al dispositivo di destinazione per impedire l'accesso di altri bus non correlati tra i trasferimenti nella sequenza. Successivamente, il client invia IRP_MJ_READ e IRP_MJ_WRITE richieste per eseguire i trasferimenti nella sequenza. Infine, il client invia una richiesta di IOCTL_SPB_UNLOCK_CONTROLLER per rilasciare il blocco.

Un client potrebbe dover implementare questo tipo di sequenza di trasferimento di I/O se un trasferimento successivo nella sequenza ha una dipendenza da un trasferimento precedente. Ad esempio, la prima lettura potrebbe indicare il numero di byte da leggere o scrivere successivamente. Se non esiste alcuna dipendenza di questo tipo, tuttavia, il client deve inviare una richiesta di IOCTL_SPB_EXECUTE_SEQUENCE al driver del controller SPB, che può eseguire la sequenza in modo più efficiente.

Tra la richiesta IOCTL_SPB_LOCK_CONTROLLER che avvia una sequenza implementata dal client e la richiesta IOCTL_SPB_UNLOCK_CONTROLLER che termina la sequenza, le uniche richieste di I/O che il client può inviare al dispositivo di destinazione sono IRP_MJ_READ e IRP_MJ_WRITE richieste. Qualsiasi violazione di questa regola è un errore.

I blocchi SPB vengono usati solo per garantire che una sequenza di letture e scritture venga eseguita come operazione atomica del bus e deve essere usata esclusivamente a tale scopo.

Per altre informazioni, vedere Gestione delle sequenze di Client-Implemented.