Поделиться через


Получение параметров подключения для устройства

Если драйвер контроллера SPB регистрирует функцию обратного вызова EvtSpbTargetConnect , расширение платформы SPB (SpbCx) вызывает эту функцию, когда клиент (драйвер периферийных устройств) контроллера отправляет IRP_MJ_CREATE запрос на открытие логического подключения к целевому устройству в шине. В ответ на обратный вызов EvtSpbTargetConnect драйвер контроллера SPB должен вызвать метод SpbTargetConnectionParameters , чтобы получить параметры подключения для целевого устройства. Драйвер контроллера 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 указывает частоту в Hertz, с которой будет выполняться синхронизация шины I2C во время доступа к целевому устройству. Элемент SlaveAddress — это адрес шины целевого устройства. Для некоторых драйверов контроллера I2C за элементом SlaveAddress могут следовать необязательные данные поставщика, но эти данные не используются драйвером в этом примере кода и, следовательно, не являются частью определения структуры.

В следующем примере кода драйвер контроллера I2C из предыдущего примера реализует подпрограмму GetTargetSettings , которая вызывает SpbTargetConnectionParameters для получения параметров подключения для целевого устройства на шине I2C. Входной параметр Target для этой подпрограммы является дескриптором для целевого устройства. Выходной параметр Settings является указателем на структуру, выделенную драйвером 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 драйвером. Элемент ParamsConnectionParameters указывает на структуру 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 , не ниже sizeof(PNP_SERIAL_BUS_DESCRIPTOR).
  • Проверяет, задан ли первый байт дескриптора подключения последовательной шины SERIAL_BUS_DESCRIPTOR (значение константы 0x8e) в соответствии со спецификацией ACPI 5.0.
  • Проверяет, задан ли тип последовательной шины в дескрипторе подключения последовательной шины I2C_SERIAL_BUS_TYPE (значение константы 0x01), который определяет тип последовательной шины как I2C.

В конце предыдущего примера кода структура *Settings содержит параметры подключения (адрес шины, ширина адреса и частота шины) для целевого устройства. Драйвер контроллера I2C использует эти параметры подключения для настройки контроллера для доступа к устройству.