Получение параметров подключения для устройства
Если драйвер контроллера SPB регистрирует функцию обратного вызова EvtSpbTargetConnect, расширение платформы SPB (SpbCx) вызывает эту функцию, когда клиент (периферийный драйвер) контроллера отправляет запрос IRP_MJ_CREATE на открытие логического подключения к целевому устройству на шине. В ответ на обратный вызов EvtSpbTargetConnect драйвер контроллера SPB должен вызвать метод SpbTargetGetConnectionParameters, чтобы получить параметры подключения для целевого устройства. Драйвер контроллера SPB сохраняет эти параметры и использует их позже для доступа к устройству в ответ на запросы ввода-вывода от клиента.
Например, параметры подключения для целевого устройства на шине I2C включают адрес шины устройства, ширину адреса (7 или 10 битов) и частоту часов шины для использования во время доступа к устройству. Драйвер контроллера I2C использует эти параметры для настройки контроллера для доступа к устройству через шину I2C.
Драйвер контроллера SPB вызывает spbTargetGetConnectionParameters, чтобы получить указатель на дескриптор подключения последовательной шины , описывающий подключение целевого устройства к последовательной шине типа I2C или SPI. Этот дескриптор содержит сведения о подключении, которые являются общими для типов последовательной шины, и за ним следует информация, относящуюся к последовательной шине, к которой подключено устройство. Дополнительные сведения о формате дескриптора см. в спецификации ACPI 5.0.
В следующем примере кода драйвер контроллера I2C определяет структуру PNP_I2C_SERIAL_BUS_DESCRIPTOR. Эта структура представляет дескриптор дескриптора подключения последовательной шины I2C, который является термином спецификации ACPI 5.0 для описания дескриптора подключения последовательной шины, за которым следует параметры подключения, относящиеся к шине I2C. Первый элемент структуры PNP_I2C_SERIAL_BUS_DESCRIPTOR, SerialBusDescriptorявляется структурой PNP_SERIAL_BUS_DESCRIPTOR, представляющей дескриптор подключения последовательной шины. ConnectionSpeed и SlaveAddress содержат параметры подключения, специфичные для I2C.
#include <reshub.h>
#include <pshpack1.h>
//
// See the ACPI 5.0 spec, section 6.4.3.8.2.1 (I2C Serial Bus Connection Descriptor).
//
typedef struct _PNP_I2C_SERIAL_BUS_DESCRIPTOR {
PNP_SERIAL_BUS_DESCRIPTOR SerialBusDescriptor;
ULONG ConnectionSpeed;
USHORT SlaveAddress;
// Followed by optional vendor-specific data.
// Followed by name of serial bus controller.
} PNP_I2C_SERIAL_BUS_DESCRIPTOR, *PPNP_I2C_SERIAL_BUS_DESCRIPTOR;
#include <poppack.h>
Файл заголовка reshub.h определяет структуру PNP_SERIAL_BUS_DESCRIPTOR. Файлы заголовков pshpack1.h и poppack.h управляют режимом выравнивания структуры, используемым компилятором.
Дескриптор подключения последовательной шины I2C — это упакованная структура данных, в которой смежные поля выровнены по ближайшим границам байт без промежуточных пробелов. В результате 16-разрядное целое значение в этом дескрипторе может начинаться с нечетной границы байтов. В приведенном выше примере кода pshpack1.h включается, чтобы сообщить компилятору упаковать смежные элементы структуры, а poppack.h сообщает компилятору возобновить выравнивание структуры по умолчанию.
Элемент ConnectionSpeed структуры PNP_I2C_SERIAL_BUS_DESCRIPTOR указывает частоту в Герцах, с которой выполняется тактирование шины I2C при обращениях к целевому устройству. Элемент SlaveAddress является адресом шины целевого устройства. Для некоторых драйверов контроллера I2C за элементом SlaveAddress могут следовать необязательные данные конкретного поставщика, но эти данные не используются драйвером в этом примере кода и поэтому не являются частью определения структуры.
В следующем примере кода драйвер контроллера I2C из предыдущего примера реализует подпрограмму GetTargetSettings
, которая вызывает SpbTargetGetConnectionParameters, чтобы получить параметры подключения для целевого устройства на шине I2C. Входной параметр Target для этой подпрограммы является дескриптором целевого устройства. Параметр настроек выходной процедуры — это указатель на выделенную драйвером структуру SPB_CONNECTION_PARAMETERS, в которую процедура записывает набор параметров подключения. Эти параметры включают указатель на запрошенные параметры подключения.
#define I2C_SERIAL_BUS_TYPE 0x01
#define I2C_SERIAL_BUS_SPECIFIC_FLAG_10BIT_ADDRESS 0x0001
typedef enum _I2C_ADDRESS_MODE
{
AddressMode7Bit,
AddressMode10Bit
} I2C_ADDRESS_MODE, *PI2C_ADDRESS_MODE;
typedef struct _I2C_TARGET_SETTINGS
{
ULONG ClockFrequency;
ULONG Address;
I2C_ADDRESS_MODE AddressMode;
} I2C_TARGET_SETTINGS, *PI2C_TARGET_SETTINGS;
NTSTATUS
GetTargetSettings(_In_ SPBTARGET Target, _Out_ PI2C_TARGET_SETTINGS Settings)
{
PRH_QUERY_CONNECTION_PROPERTIES_OUTPUT_BUFFER Connection = NULL;
SPB_CONNECTION_PARAMETERS Params;
SPB_CONNECTION_PARAMETERS_INIT(&Params);
SpbTargetGetConnectionParameters(Target, &Params);
Connection = (PRH_QUERY_CONNECTION_PROPERTIES_OUTPUT_BUFFER)Params.ConnectionParameters;
if (Connection->PropertiesLength < sizeof(PNP_SERIAL_BUS_DESCRIPTOR))
{
return STATUS_INVALID_PARAMETER;
}
PPNP_SERIAL_BUS_DESCRIPTOR Descriptor;
Descriptor = (PPNP_SERIAL_BUS_DESCRIPTOR)Connection->ConnectionProperties;
if (Descriptor->Tag != SERIAL_BUS_DESCRIPTOR ||
Descriptor->SerialBusType != I2C_SERIAL_BUS_TYPE)
{
return STATUS_INVALID_PARAMETER;
}
PPNP_I2C_SERIAL_BUS_DESCRIPTOR I2CDescriptor;
USHORT I2CFlags;
I2CDescriptor = (PPNP_I2C_SERIAL_BUS_DESCRIPTOR)Connection->ConnectionProperties;
Settings->Address = (ULONG)I2CDescriptor->SlaveAddress;
I2CFlags = I2CDescriptor->SerialBusDescriptor.TypeSpecificFlags;
Settings->AddressMode =
((I2CFlags & I2C_SERIAL_BUS_SPECIFIC_FLAG_10BIT_ADDRESS) == 0) ? AddressMode7Bit : AddressMode10Bit;
Settings->ClockFrequency = I2CDescriptor->ConnectionSpeed;
return STATUS_SUCCESS;
}
В предыдущем примере кода SpbTargetGetConnectionParameters записывает параметры подключения в структуру, выделенную драйвером Params
. Элемент ConnectionParameters элемента Params
указывает на структуру RH_QUERY_CONNECTION_PROPERTIES_OUTPUT_BUFFER (определенную в reshub.h), член ConnectionProperties является первым байтом дескриптора подключения последовательной шины; оставшиеся байты этого дескриптора немедленно следуют за членом ConnectionProperties. Буфер, на который указывает элемент ConnectionParameters структуры Params
, достаточно велик, чтобы содержать структуру RH_QUERY_CONNECTION_PROPERTIES_OUTPUT_BUFFER, плюс байты дескриптора, следующие за этой структурой.
Подпрограмма, реализованная драйвером GetTargetSettings
в предыдущем примере кода, выполняет следующие проверки параметров подключения, полученных от SpbTargetGetConnectionParameters:
- Проверяет, что размер дескриптора подключения последовательной шины, содержащегося в структуре RH_QUERY_CONNECTION_PROPERTIES_OUTPUT_BUFFER, не менее размер(PNP_SERIAL_BUS_DESCRIPTOR).
- Проверяет, что для первого байта дескриптора подключения последовательной шины задано значение SERIAL_BUS_DESCRIPTOR (константное значение 0x8e), как требуется спецификация ACPI 5.0.
- Проверяет, установлен ли тип последовательной шины в дескрипторе подключения последовательной шины I2C_SERIAL_BUS_TYPE (константное значение 0x01), идентифицирующий тип последовательной шины как I2C.
В конце предыдущего примера кода структура *Settings
содержит параметры подключения (адрес шины, ширина адреса и частота часов шины) для целевого устройства. Драйвер контроллера I2C использует эти параметры подключения для настройки контроллера для доступа к устройству.