Cara Mendapatkan Pengaturan Koneksi untuk Perangkat
Jika driver pengontrol SPB Anda mendaftarkan fungsi panggilan balik EvtSpbTargetConnect , ekstensi kerangka kerja SPB (SpbCx) memanggil fungsi ini ketika klien (driver periferal) pengontrol mengirim permintaan IRP_MJ_CREATE untuk membuka koneksi logis ke perangkat target di bus. Sebagai respons terhadap panggilan balik EvtSpbTargetConnect , driver pengontrol SPB harus memanggil metode SpbTargetGetConnectionParameters untuk mendapatkan pengaturan koneksi untuk perangkat target. Driver pengontrol SPB menyimpan pengaturan ini dan menggunakannya nanti untuk mengakses perangkat sebagai respons terhadap permintaan I/O dari klien.
Misalnya, pengaturan koneksi untuk perangkat target pada bus I2C mencakup alamat bus perangkat, lebar alamat (7 atau 10 bit), dan frekuensi jam bus yang akan digunakan selama akses perangkat. Driver pengontrol I2C menggunakan pengaturan ini untuk mengonfigurasi pengontrol untuk mengakses perangkat melalui bus I2C.
Driver pengontrol SPB memanggil SpbTargetGetConnectionParameters untuk mendapatkan penunjuk ke deskriptor koneksi bus serial yang menjelaskan koneksi perangkat target ke bus serial jenis I2C atau SPI. Deskriptor ini berisi informasi koneksi yang umum untuk kedua jenis bus serial, dan diikuti oleh informasi yang khusus untuk bus serial tempat perangkat terhubung. Untuk informasi selengkapnya tentang format untuk deskriptor ini, lihat spesifikasi ACPI 5.0.
Dalam contoh kode berikut, driver pengontrol I2C menentukan struktur PNP_I2C_SERIAL_BUS_DESCRIPTOR . Struktur ini mewakili pendeskripsi koneksi bus serial I2C, yang merupakan istilah yang digunakan spesifikasi ACPI 5.0 untuk menjelaskan pendeskripsi koneksi bus serial yang diikuti oleh pengaturan koneksi yang khusus untuk bus I2C. Anggota pertama dari struktur PNP_I2C_SERIAL_BUS_DESCRIPTOR , SerialBusDescriptor, adalah struktur PNP_SERIAL_BUS_DESCRIPTOR yang mewakili pendeskripsi koneksi bus serial. Anggota ConnectionSpeed dan SlaveAddress berisi pengaturan koneksi khusus 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>
File header reshub.h menentukan struktur PNP_SERIAL_BUS_DESCRIPTOR . File header pshpack1.h dan poppack.h mengontrol mode perataan struktur yang digunakan oleh pengkompilasi.
Deskriptor koneksi bus serial I2C adalah struktur data yang dikemas di mana bidang yang berdekatan selaras dengan batas byte terdekat, tanpa mengintervensi celah. Akibatnya, nilai bilangan bulat 16-bit dalam deskriptor ini mungkin dimulai pada batas byte ganjil. Dalam contoh kode sebelumnya, pshpack1.h disertakan untuk memberi tahu pengkompilasi untuk mengemas anggota struktur yang berdekatan, dan poppack.h memberi tahu pengkompilasi untuk melanjutkan perataan struktur default.
Anggota ConnectionSpeed dari struktur PNP_I2C_SERIAL_BUS_DESCRIPTOR menentukan frekuensi, di Hertz, untuk membuat jam bus I2C selama akses perangkat target. Anggota SlaveAddress adalah alamat bus perangkat target. Untuk beberapa driver pengontrol I2C, anggota SlaveAddress mungkin diikuti oleh data khusus vendor opsional, tetapi data ini tidak digunakan oleh driver dalam contoh kode ini dan, oleh karena itu, bukan bagian dari definisi struktur.
Dalam contoh kode berikut, driver pengontrol I2C dari contoh sebelumnya mengimplementasikan GetTargetSettings
rutinitas yang memanggil SpbTargetGetConnectionParameters untuk mendapatkan pengaturan koneksi untuk perangkat target pada bus I2C. Parameter input Target untuk rutinitas ini adalah handel ke perangkat target. Parameter output Pengaturan adalah penunjuk ke struktur SPB_CONNECTION_PARAMETERS yang dialokasikan driver tempat rutin menulis serangkaian parameter koneksi. Parameter ini mencakup penunjuk ke pengaturan koneksi yang diminta.
#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;
}
Dalam contoh kode sebelumnya, SpbTargetGetConnectionParameters menulis parameter koneksi ke struktur yang dialokasikan Params
driver. Anggota ConnectionParametersParams
menunjuk ke struktur RH_QUERY_CONNECTION_PROPERTIES_OUTPUT_BUFFER (didefinisikan dalam reshub.h), yang anggota ConnectionProperties-nya adalah byte pertama dari deskriptor koneksi bus serial; byte yang tersisa dari deskriptor ini segera mengikuti anggota ConnectionProperties . Buffer yang ditunjukkan oleh anggota Params
ConnectionParameters cukup besar untuk berisi struktur RH_QUERY_CONNECTION_PROPERTIES_OUTPUT_BUFFER ditambah byte deskriptor yang mengikuti struktur ini.
Rutinitas yang diimplementasikan GetTargetSettings
driver dalam contoh kode sebelumnya melakukan pemeriksaan parameter berikut pada parameter koneksi yang diterima dari SpbTargetGetConnectionParameters:
- Memverifikasi bahwa ukuran deskriptor koneksi bus serial yang terkandung dalam struktur RH_QUERY_CONNECTION_PROPERTIES_OUTPUT_BUFFER setidaknya ukuranof (PNP_SERIAL_BUS_DESCRIPTOR).
- Memverifikasi bahwa byte pertama dari pendeskripsi koneksi bus serial diatur ke SERIAL_BUS_DESCRIPTOR (nilai konstanta 0x8e), seperti yang diperlukan oleh spesifikasi ACPI 5.0.
- Memverifikasi bahwa jenis bus serial dalam deskriptor koneksi bus serial diatur ke I2C_SERIAL_BUS_TYPE (nilai konstanta 0x01), yang mengidentifikasi jenis bus serial sebagai I2C.
Di akhir contoh kode sebelumnya, struktur *Settings
berisi pengaturan koneksi (alamat bus, lebar alamat, dan frekuensi jam bus) untuk perangkat target. Driver pengontrol I2C menggunakan pengaturan koneksi ini untuk mengonfigurasi pengontrol untuk mengakses perangkat.