Schützen digitaler Anforderungen, die direkte E/A verwenden
Im folgenden Codebeispiel wird veranschaulicht, wie ein Treiber eine Befehlsanforderung verwendet, um den Inhalt des Funktionsgrundregisters (Function Basic Register, FBR) eines Geräts abzurufen. Da die abgerufene Datenmenge gering ist, verwendet das Beispiel einen direkten E/A-Befehl (in der SD-Spezifikation als CMD52 bezeichnet), der den Bustreiber anweist, die Daten über die CMD-Leitung zu übertragen. Ein Codebeispiel, das die Verwendung von erweiterten E/A-Vorgängen (in der SD-Spezifikation als CMD53 bezeichnet) veranschaulicht, finden Sie unter Secure Digital Requests That Use Extended E/O.
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);
Um die FBR zu lesen, führt das Codebeispiel die folgenden Schritte aus:
Initialisieren des Deskriptors
Der erste Schritt beim Senden einer Gerätebefehlsanforderung besteht darin, einen SD-Befehlsdeskriptor zu definieren, SDCMD_DESCRIPTOR. In der Regel wird ein Deskriptor als konstante Datenstruktur definiert. Der Deskriptor im Codebeispiel definiert einen Lesevorgang mit den folgenden Elementen:
Element BESCHREIBUNG Der durch den Deskriptor definierte Vorgang liest ein einzelnes Byte von Daten aus der FBR, sodass im Codebeispiel ein direkter E/A-Befehl (CMD52) verwendet wird, der den Karte anweist, die angeforderten Daten über die CMD-Zeile und nicht über die DAT-Zeilen zu melden. Das Codebeispiel gibt einen direkten E/A-Befehl an, indem diesem Member der Wert SDCMD_IO_RW_DIRECT zugewiesen wird.
Lesevorgänge gehören zum Standardbefehlssatz (Befehlscodes 0 bis 63), sodass der diesem Member des Deskriptors zugewiesene Wert SDCC_STANDARD ist.
Lesevorgänge erfordern eine Übertragung vom Gerät auf den Host, sodass der diesem Member des Deskriptors zugewiesene Wert SDTD_READ ist.
Dieser Vorgang liest eine kleine Menge von Daten aus einem Register über die CMD-Zeile. Die Karte muss keine Daten über die DAT-Zeilen senden, daher wird diesem Member der Wert SDTT_CMD_ONLY zugewiesen.
Der Deskriptor gibt einen Antworttyp von SDRT_5 an. Dies bedeutet, dass der Karte den Host benachrichtigen muss, dass der Vorgang mit einer Interruptanforderung abgeschlossen wurde. Eine Erläuterung der R5-Antwort finden Sie in der MultiMedia Card Association-Spezifikation .
Initialisieren Sie das Anforderungspaket , indem Sie die folgenden Schritte ausführen:
Definieren Sie die Anforderungsfunktion:
Nach dem Erstellen eines SD-Deskriptors initialisiert das Codebeispiel das Anforderungspaket , SDBUS_REQUEST_PACKET. Der RequestFunction-Member des Anforderungspakets gibt an, ob die Anforderung einen Gerätebefehl (Wert von SDRF_DEVICE_COMMAND) oder einen Eigenschaftsvorgang (Wert von SDRF_GET_PROPERTY oder SDRF_SET_PROPERTY) enthält. Das Codebeispiel initiiert einen Gerätebefehl, sodass das RequestFunction-Element auf SDRF_DEVICE_COMMAND festgelegt wird.
Laden Sie den Befehlsdeskriptor: Als Nächstes speichert das Codebeispiel den neu initialisierten Deskriptor im Parameters.DeviceCommand.CmdDesc-Member des Anforderungspakets.
Initialisieren Sie das Lese-/Schreibargument:
Das Anforderungspaket enthält eine SD_RW_DIRECT_ARGUMENT Struktur, die den Speicherort der Vom Bustreiber abgerufenen Daten enthält. Diese Struktur speichert auch die Nummer der Funktion, deren E/A-Leerraum der Bustreiber liest. Der Beispielcode ruft die Funktionsnummer aus der Geräteerweiterung ab. Dies impliziert, dass der Treiber die Informationen zuvor aus dem Karte (wahrscheinlich beim Starten des Geräts) mit einer SDRF_GET_PROPERTY-Anforderung abgerufen und in der Geräteerweiterung gespeichert hat.
Übermitteln der Anforderung
Nach der Initialisierung des Deskriptors und des Anforderungspakets verwendet das Codebeispiel die synchrone Anforderungsroutine SdBusSubmitRequest, um die Anforderung zu übermitteln. Die Anforderungsroutine übergibt das Anforderungspaket und die Schnittstellenkontextinformationen, die das System dem Treiber beim Öffnen der SD-Schnittstelle bereitgestellt hat. Da es sich um eine synchrone Anforderung handelt, muss der Treiber bei IRQL ausgeführt werden, der kleiner als DISPATCH_LEVEL ist.
Ergebnisse des Befehls
Da im Codebeispiel direkte E/A verwendet wird, ist außer dem Feld ResponseData im SD-Anforderungspaket kein Datenpuffer erforderlich.