Защита цифровых запросов, использующих прямой ввод-вывод
В следующем примере кода показано, как драйвер использует командный запрос для получения содержимого базового регистра функции устройства (FBR). Так как объем полученных данных невелик, в примере используется команда прямого ввода-вывода (которая называется CMD52 в спецификации SD), которая предписывает водителю шины передавать данные через линию CMD. Пример кода, демонстрирующий использование расширенных операций ввода-вывода (cmd53 в спецификации SD), см. в статье Защита цифровых запросов, использующих расширенный ввод-вывод.
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, поэтому в примере кода используется команда прямого ввода-вывода (CMD52), которая предписывает карта передавать запрошенные данные через строку CMD, а не строки DAT. В примере кода указывается прямая команда ввода-вывода путем присвоения этому элементу значения SDCMD_IO_RW_DIRECT.
Операции чтения относятся к стандартному набору команд (коды команд от 0 до 63), поэтому значение, присвоенное этому члену дескриптора, SDCC_STANDARD.
Операции чтения требуют передачи с устройства на узел, поэтому значение, присвоенное этому члену дескриптора, равно SDTD_READ.
Эта операция считывает небольшой объем данных из регистра через строку CMD. Карта не нужно отправлять данные по строкам DAT, поэтому этому члену присваивается значение SDTT_CMD_ONLY.
Дескриптор задает тип ответа SDRT_5, что означает, что карта должен уведомить узел о завершении операции с помощью запроса прерывания. Описание ответа R5 см. в спецификации Сопоставления карт MultiMedia .
Инициализируйте пакет запроса , выполнив следующие действия.
Определите функцию запроса:
После создания дескриптора 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 , содержащую расположение данных, извлекаемых драйвером шины. В этой структуре также хранится количество функции, пространство ввода-вывода которой считывает водитель автобуса. Пример кода извлекает номер функции из расширения устройства, что означает, что драйвер ранее извлек сведения из карта (вероятно, при запуске устройства) с помощью запроса SDRF_GET_PROPERTY и сохранил их в расширении устройства.
Отправка запроса
После инициализации дескриптора и пакета запроса для отправки запроса в примере кода используется синхронная подпрограмма запроса SdBusSubmitRequest. Подпрограмма запроса передает пакет запроса и сведения о контексте интерфейса, которые система предоставила драйверу при открытии интерфейса SD. Так как это синхронный запрос, драйвер должен работать в IRQL менее DISPATCH_LEVEL.
Результаты выполнения команды
Так как в примере кода используется прямой ввод-вывод, буфер данных не требуется, кроме поля ResponseData в пакете запроса SD.