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


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

Если драйвер контроллера 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 использует эти параметры подключения для настройки контроллера для доступа к устройству.