Condividi tramite


Proteggere le richieste digitali che usano l'I/O diretto

Nell'esempio di codice seguente viene illustrato come un driver usa una richiesta di comando per recuperare il contenuto del registro di base della funzione di un dispositivo. Poiché la quantità di dati recuperata è ridotta, nell'esempio viene usato un comando di I/O diretto (denominato CMD52 nella specifica SD), che indica al driver del bus di trasmettere i dati nella riga CMD. Per visualizzare un esempio di codice che illustra come usare l'I/O esteso (denominato CMD53 nella specifica SD), vedere Richieste digitali sicure che usano I/O estese.

    const SDCMD_DESCRIPTOR ReadIoDirectDesc =
    {SDCMD_IO_RW_DIRECT, SDCC_STANDARD, SDTD_READ,
    SDTT_CMD_ONLY, SDRT_5};
    
    PSDBUS_REQUEST_PACKET sdrp = NULL;
    SD_RW_DIRECT_ARGUMENT sdIoArgument;
    
    sdrp = ExAllocatePool(NonPagedPool, 
        sizeof(SDBUS_REQUEST_PACKET));
    if (!sdrp) {
        return STATUS_INSUFFICIENT_RESOURCES;
    }
    RtlZeroMemory(sdrp, sizeof(SDBUS_REQUEST_PACKET));
    sdrp->RequestFunction = SDRF_DEVICE_COMMAND;
    sdrp->Parameters.DeviceCommand.CmdDesc = ReadIoDirectDesc;
    
    // Set up the argument and command descriptor
    
    sdIoArgument.u.AsULONG = 0;
    sdIoArgument.u.bits.Address = Offset;
    
    // Function # must be initialized by SdBus GetProperty call
    
    sdIoArgument.u.bits.Function = pDevExt->FunctionNumber;
    sdrp->Parameters.DeviceCommand.Argument = sdIoArgument.u.AsULONG;
    
    // Submit the request
    
    status = SdBusSubmitRequest(pDevExt->BusInterface.Context, sdrp);
    
    if (NT_SUCCESS(status)) {
        // for direct I/O, the data comes in the response
        *Data = sdrp->ResponseData.AsUCHAR[0];
    }
    ExFreePool(sdrp);

Per leggere FBR, nell'esempio di codice vengono eseguiti i passaggi seguenti:

  1. Inizializzare il descrittore

    Il primo passaggio nell'invio di una richiesta di comando del dispositivo consiste nel definire un descrittore di comando SD, SDCMD_DESCRIPTOR. In genere, un descrittore viene definito come una struttura di dati costante. Il descrittore nell'esempio di codice definisce un'operazione di lettura con gli elementi seguenti:

    Elemento Descrizione

    SD_COMMAND_CODE

    L'operazione definita dal descrittore legge un singolo byte di dati dalla FBR, quindi l'esempio di codice usa un comando di I/O diretto (CMD52), che indica alla scheda di segnalare i dati richiesti nella riga CMD e non nelle righe DAT. L'esempio di codice indica un comando di I/O diretto assegnando un valore di SDCMD_IO_RW_DIRECT a questo membro.

    SD_COMMAND_CLASS

    Le operazioni di lettura appartengono al set di comandi standard (codici di comando da 0 a 63), quindi il valore assegnato a questo membro del descrittore è SDCC_STANDARD.

    SD_TRANSFER_DIRECTION

    Le operazioni di lettura richiedono un trasferimento dal dispositivo all'host, quindi il valore assegnato a questo membro del descrittore è SDTD_READ.

    SD_TRANSFER_TYPE

    Questa operazione legge una piccola quantità di dati da un registro sulla riga CMD. La scheda non deve inviare dati sulle righe DAT, pertanto questo membro viene assegnato un valore di SDTT_CMD_ONLY.

    SD_RESPONSE_TYPE

    Il descrittore specifica un tipo di risposta di SDRT_5, il che significa che la scheda deve notificare all'host che l'operazione è stata completata con una richiesta di interruzione. Per una spiegazione della risposta R5, vedere la specifica MultiMedia Card Association .

  2. Inizializzare il pacchetto richiesta completando i passaggi seguenti:

    1. Definire la funzione request:

      Dopo aver creato un descrittore SD, l'esempio di codice inizializza il pacchetto di richiesta, SDBUS_REQUEST_PACKET. Il membro RequestFunction del pacchetto di richiesta specifica se la richiesta contiene un comando del dispositivo (valore di SDRF_DEVICE_COMMAND) o un'operazione di proprietà (valore di SDRF_GET_PROPERTY o SDRF_SET_PROPERTY). L'esempio di codice avvia un comando del dispositivo, quindi imposta il membro RequestFunction su SDRF_DEVICE_COMMAND.

    2. Caricare il descrittore di comando: successivamente, l'esempio di codice archivia il descrittore appena inizializzato nel membro Parameters.DeviceCommand.CmdDesc del pacchetto di richiesta.

    3. Inizializzare l'argomento Di lettura/scrittura:

      Il pacchetto di richiesta contiene una struttura SD_RW_DIRECT_ARGUMENT che contiene la posizione dei dati recuperati dal driver del bus. Questa struttura archivia anche il numero della funzione di cui viene letto lo spazio di I/O dal quale il driver del bus legge. Il codice di esempio recupera il numero di funzione dall'estensione del dispositivo, che implica che il driver ha recuperato in precedenza le informazioni dalla scheda (probabilmente all'avvio del dispositivo) con una richiesta SDRF_GET_PROPERTY e archiviata nell'estensione del dispositivo.

  3. Inviare la richiesta

    Dopo aver inizializzato il descrittore e il pacchetto di richiesta, nell'esempio di codice viene usata la routine di richiesta sincrona SdBusSubmitRequest per inviare la richiesta. La routine di richiesta passa il pacchetto di richiesta e le informazioni sul contesto dell'interfaccia fornite al driver quando apre l'interfaccia SD. Poiché si tratta di una richiesta sincrona, il driver deve essere in esecuzione in IRQL minore di DISPATCH_LEVEL.

  4. Risultati del comando

    Poiché l'esempio di codice usa l'I/O diretto, non è necessario alcun buffer di dati diverso dal campo ResponseData nel pacchetto di richiesta SD.