这一篇文章说明了在device.c文件里,驱动程序怎样枚举设备,然后获得设备资源,并将其显示出来供开发者使用。
device.c
/*++
Module Name: device.c - Device handling events for example driver.
Abstract: This file contains the device entry points and callbacks, sucn as EvtDevicePrepareHardware and EvtDeviceReleaseHardware function.
Environment: Kernel-mode Driver Framework
Time: 20181015
--*/
#include "driver.h"
//#pragma warning(disable:4013)
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, PCIe_EvtDevicePrepareHardware)
#pragma alloc_text(PAGE, PCIe_EvtDeviceReleaseHardware)
#endif
NTSTATUS
PCIe_EvtDevicePrepareHardware(
IN WDFDEVICE Device,
IN WDFCMRESLIST ResourceList,
IN WDFCMRESLIST ResourceListTranslated
)
{
ULONG i;
PDEVICE_CONTEXT pDeviceContext; //设备上下文结构体的句柄
PCM_PARTIAL_RESOURCE_DESCRIPTOR descriptor; //设备资源描述符
PINTERRUPT_CONTEXT pInterruptContext; //中断上下文结构体的句柄
NTSTATUS status;
PAGED_CODE();
KdPrintEx((DPFLTR_IHVAUDIO_ID, DPFLTR_ERROR_LEVEL, "Function 'PCIe_EvtDevicePrepareHardware' begins\n"));
pDeviceContext = GetDeviceContext(Device);
pDeviceContext->MemBaseAddress0 = NULL;
pDeviceContext->MemBaseAddress1 = NULL;
pDeviceContext->MemBaseAddress2 = NULL;
pDeviceContext->Counter_i = 0;
for (i = 0; i < WdfCmResourceListGetCount(ResourceListTranslated); i++) {
KdPrintEx((DPFLTR_IHVAUDIO_ID, DPFLTR_ERROR_LEVEL, "i is %0d\n", i));
//获取到设备资源描述符
descriptor = WdfCmResourceListGetDescriptor(ResourceListTranslated, i);
if (!descriptor) {
return STATUS_DEVICE_CONFIGURATION_ERROR;
}
//根据不同类型,将设备资源描述符转化为开发者可用的类型,这里主要用到了memory和interrupt两种资源
switch (descriptor->Type)
{
case CmResourceTypeMemory:
if (i == 0) {
//获取到设备存储资源的物理地址
pDeviceContext->PhysicalAddressRegister0 = descriptor->u.Memory.Start.LowPart;
//获取到设备存储资源在系统内核模式下的虚拟地址(后续对于寄存器的访问也将用到这个地址)
pDeviceContext->MemBaseAddress0 = MmMapIoSpace(
descriptor->u.Memory.Start,
descriptor->u.Memory.Length,
MmNonCached);
if (!pDeviceContext->MemBaseAddress0) {
return STATUS_INSUF