写一个能访问pcie配置空间的wdf驱动程序
时间: 2024-05-13 10:20:02 浏览: 15
以下是一个简单的WDF驱动程序,可以访问PCIe配置空间:
```cpp
#include <ntddk.h>
#include <wdf.h>
#define DEVICE_NAME L"\\Device\\MyPCIDevice"
#define SYMBOLIC_LINK_NAME L"\\DosDevices\\MyPCIDevice"
#define BAR_INDEX 0
// Device context
typedef struct _DEVICE_CONTEXT
{
ULONG BusNumber;
ULONG DeviceNumber;
ULONG FunctionNumber;
} DEVICE_CONTEXT, *PDEVICE_CONTEXT;
WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DEVICE_CONTEXT, GetDeviceContext)
// Forward declarations
DRIVER_INITIALIZE DriverEntry;
EVT_WDF_DRIVER_UNLOAD MyDriverUnload;
EVT_WDF_DEVICE_CONTEXT_CLEANUP MyDeviceContextCleanup;
EVT_WDF_DEVICE_PREPARE_HARDWARE MyDevicePrepareHardware;
NTSTATUS WriteConfigSpace(PDEVICE_CONTEXT pDevCtx, ULONG dwOffset, ULONG dwValue)
{
ULONG ulBytesReturned;
ULONG ulLength = sizeof(ULONG);
ULONG ulAddress = (pDevCtx->BusNumber << 16) | (pDevCtx->DeviceNumber << 11) | (pDevCtx->FunctionNumber << 8) | (dwOffset & 0xfc);
return WdfDeviceQueryProperty(WdfDeviceWdmGetDeviceObject(pDevCtx->Device), DevicePropertyAddress, ulLength, &ulAddress, &ulBytesReturned, &dwValue);
}
NTSTATUS ReadConfigSpace(PDEVICE_CONTEXT pDevCtx, ULONG dwOffset, PULONG pdwValue)
{
ULONG ulBytesReturned;
ULONG ulLength = sizeof(ULONG);
ULONG ulAddress = (pDevCtx->BusNumber << 16) | (pDevCtx->DeviceNumber << 11) | (pDevCtx->FunctionNumber << 8) | (dwOffset & 0xfc);
return WdfDeviceQueryProperty(WdfDeviceWdmGetDeviceObject(pDevCtx->Device), DevicePropertyAddress, ulLength, &ulAddress, &ulBytesReturned, pdwValue);
}
// DriverEntry routine
NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath)
{
NTSTATUS status;
WDF_DRIVER_CONFIG config;
KdPrint(("DriverEntry\n"));
// Initialize WDF driver configuration
WDF_DRIVER_CONFIG_INIT(&config, WDF_NO_EVENT_CALLBACK);
// Register driver unload callback
config.DriverUnload = MyDriverUnload;
// Create WDF driver object
status = WdfDriverCreate(DriverObject, RegistryPath, WDF_NO_OBJECT_ATTRIBUTES, &config, WDF_NO_HANDLE);
if (!NT_SUCCESS(status))
{
KdPrint(("WdfDriverCreate failed: 0x%x\n", status));
}
return status;
}
// Driver unload callback
VOID MyDriverUnload(_In_ WDFDRIVER Driver)
{
KdPrint(("MyDriverUnload\n"));
}
// Device context cleanup callback
VOID MyDeviceContextCleanup(_In_ WDFOBJECT Device)
{
PDEVICE_CONTEXT pDevCtx = GetDeviceContext(Device);
KdPrint(("MyDeviceContextCleanup\n"));
WdfObjectDelete(pDevCtx->Device);
}
// Device prepare hardware callback
NTSTATUS MyDevicePrepareHardware(_In_ WDFDEVICE Device, _In_ WDFCMRESLIST Resources, _In_ WDFCMRESLIST ResourcesTranslated)
{
NTSTATUS status;
PDEVICE_CONTEXT pDevCtx = GetDeviceContext(Device);
ULONG ulValue = 0;
KdPrint(("MyDevicePrepareHardware\n"));
// Get PCI configuration space values
status = ReadConfigSpace(pDevCtx, 0x00, &ulValue);
if (!NT_SUCCESS(status))
{
KdPrint(("ReadConfigSpace failed: 0x%x\n", status));
return status;
}
// Log vendor ID and device ID
KdPrint(("Vendor ID: 0x%x\n", ulValue & 0xffff));
KdPrint(("Device ID: 0x%x\n", (ulValue >> 16) & 0xffff));
// Get BAR value
status = ReadConfigSpace(pDevCtx, 0x10 + BAR_INDEX * 4, &ulValue);
if (!NT_SUCCESS(status))
{
KdPrint(("ReadConfigSpace failed: 0x%x\n", status));
return status;
}
// Log BAR value
KdPrint(("BAR[%d]: 0x%x\n", BAR_INDEX, ulValue));
return STATUS_SUCCESS;
}
// DriverEntry routine
NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath)
{
NTSTATUS status;
WDF_DRIVER_CONFIG config;
WDF_OBJECT_ATTRIBUTES attributes;
WDFDEVICE device;
PDEVICE_CONTEXT pDevCtx;
KdPrint(("DriverEntry\n"));
// Initialize WDF driver configuration
WDF_DRIVER_CONFIG_INIT(&config, WDF_NO_EVENT_CALLBACK);
// Register driver unload callback
config.DriverUnload = MyDriverUnload;
// Create WDF driver object
status = WdfDriverCreate(DriverObject, RegistryPath, WDF_NO_OBJECT_ATTRIBUTES, &config, WDF_NO_HANDLE);
if (!NT_SUCCESS(status))
{
KdPrint(("WdfDriverCreate failed: 0x%x\n", status));
return status;
}
// Create WDF device object
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT);
status = WdfDeviceCreate(&attributes, WDF_NO_OBJECT_ATTRIBUTES, &device);
if (!NT_SUCCESS(status))
{
KdPrint(("WdfDeviceCreate failed: 0x%x\n", status));
return status;
}
// Set device context
pDevCtx = GetDeviceContext(device);
pDevCtx->BusNumber = 0;
pDevCtx->DeviceNumber = 1;
pDevCtx->FunctionNumber = 0;
pDevCtx->Device = device;
// Set device name and symbolic link
status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_MY_DEVICE, NULL);
if (!NT_SUCCESS(status))
{
KdPrint(("WdfDeviceCreateDeviceInterface failed: 0x%x\n", status));
return status;
}
status = WdfDeviceCreateSymbolicLink(device, &SYMBOLIC_LINK_NAME);
if (!NT_SUCCESS(status))
{
KdPrint(("WdfDeviceCreateSymbolicLink failed: 0x%x\n", status));
return status;
}
// Register cleanup callback
WdfDeviceSetContextCleanupCallback(device, MyDeviceContextCleanup);
// Register prepare hardware callback
WdfDeviceInitSetPnpPowerEventCallbacks(WdfDeviceWdmGetDeviceInit(device), MyDevicePrepareHardware, NULL, NULL);
return STATUS_SUCCESS;
}
```
此驱动程序创建了一个名为“\\DosDevices\\MyPCIDevice”的符号链接,该符号链接指向一个PCIe设备。在“EVT_WDF_DEVICE_PREPARE_HARDWARE”回调中,它使用“ReadConfigSpace”函数读取PCI配置空间,并使用“WriteConfigSpace”函数写入PCI配置空间。将“BAR_INDEX”设置为要读取或写入的基址寄存器(BAR)的索引。