保护使用直接 I/O 的数字请求
下面的代码示例演示驱动程序如何使用命令请求来检索设备函数基本寄存器的内容 (FBR) 。 由于检索的数据量较小,本示例在 SD 规范) 中使用名为 CMD52 的直接 I/O 命令 (,该命令指示总线驱动程序跨 CMD 线路传输数据。 若要查看演示如何在 SD 规范) 中使用名为 CMD53 的扩展 I/O (的代码示例,请参阅 使用扩展 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 读取单个字节的数据,因此代码示例使用直接 I/O 命令 (CMD52) ,该命令指示卡跨 CMD 行而不是 DAT 行报告请求的数据。 代码示例通过将值 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 字段外,不需要其他数据缓冲区。