ダイレクト I/O を使用する安全なデジタル要求
次のコード例は、ドライバーがコマンド要求を使用して、デバイスの関数基本レジスタ (FBR) の内容を取得する方法を示しています。 取得されるデータの量が少ないため、この例ではダイレクト I/O コマンド (SD 仕様では CMD52 と呼ばれます) を使用します。このコマンドは、CMD ラインにかけてデータを送信するようにバス ドライバーに指示します。 拡張 I/O (SD 仕様では CMD53 と呼ばれます) の使用方法を示すコード例については、「 拡張 I/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);
FBR を読み取るために、このコード例では次の手順を実行します。
記述子の初期化
device-command 要求を送信する最初の手順は、SD コマンド記述子 "SDCMD_DESCRIPTOR" を定義することです。 通常、記述子は定数のデータ構造として定義されます。 このコード例の記述子は、次の要素を使用して読み取り操作を定義します。
要素 説明 記述子が定義した操作は FBR から 1 バイトのデータを読み取るため、このコード例ではダイレクト I/O コマンド (CMD52) を使用します。このコマンドは、DAT ラインではなく CMD ラインにかけて要求されたデータを報告するよう、カードに指示します。 これは、"SDCMD_IO_RW_DIRECT" の値をこのメンバーに割り当てることによって、ダイレクト I/O コマンドであることを示すコード例です。
読み取り操作は標準コマンド セット (コマンド コード 0 から 63) に属しているため、記述子のこのメンバーに割り当てられる値は "SDCC_STANDARD" です。
読み取り操作ではデバイスからホストへの転送が必要であるため、記述子のこのメンバーに割り当てられる値は "SDTD_READ" です。
この操作は、CMD ラインを介してレジスタから少量のデータを読み取ります。 カードは DAT ラインを介してデータを送信する必要がないため、このメンバーには "SDTT_CMD_ONLY" の値が割り当てられます。
記述子は SDRT_5 の応答の種類を指定します。つまり、操作が割り込み要求で完了したことをカードがホストに通知する必要があります。 R5 応答の説明については、マルチメディア・カード・アソシエーションの仕様を参照してください。
次の手順を実行して、要求パケットを初期化します。
要求関数の定義:
このコード例では、SD 記述子を作成した後、要求パケット "SDBUS_REQUEST_PACKET" を初期化します。 要求パケットの RequestFunction メンバーは、要求にデバイス コマンド (SDRF_DEVICE_COMMAND の値) またはプロパティ操作 (SDRF_GET_PROPERTY または SDRF_SET_PROPERTY の値) が含まれているかどうかを指定します。 このコード例では、デバイス コマンドを開始するため、RequestFunction メンバーを "SDRF_DEVICE_COMMAND" に設定します。
コマンド記述子を読み込む: 次に、新しく初期化された記述子を要求パケットの Parameters.DeviceCommand.CmdDesc メンバーに格納します。
読み取り/書き込み引数を初期化する:
要求パケットには、バス ドライバーが取得するデータの場所を保持する SD_RW_DIRECT_ARGUMENT 構造体が含まれています。 この構造体には、バス ドライバーの読み取り先となる I/O 空間を持つファンクション番号も格納されます。 このコード例では、デバイス拡張機能からファンクション番号を取得します。これは、ドライバーが以前に (おそらくデバイスを起動したときに) SDRF_GET_PROPERTY 要求を使用してカードから情報を取得し、デバイス拡張機能に格納したことを意味します。
要求の送信
このコード例では、記述子と要求パケットを初期化した後、同期要求ルーチン "SdBusSubmitRequest" を使用して要求を送信します。 要求ルーチンは、システムが SD インターフェイスを開いたときにドライバーに提供した要求パケットとインターフェイス コンテキスト情報を渡します。 これは同期要求であるため、ドライバーが DISPATCH_LEVEL 未満の IRQL で実行されている必要があります。
コマンドの結果
このコード例ではダイレクト I/O を使用するため、SD 要求パケットの ResponseData フィールド以外にデータ バッファーは必要ありません。