基于UMDF2 获取DSDT硬件资源(Finding and Mapping Hardware Resources) Windows 驱动程序

1. 背景

作为一位标准的 WINDOWN 驱动开发人员最痛苦并快乐着就是如何获取DTDS的硬件资源,并操作GPIO。,
UMDF2 框架的特殊性,并不能直接获取硬件资源和操作GPIO(后期再详解),硬件资源文件DSDT在启动的时候被KERNEL获取和解析,然后通过API的方式UMDF2才能通过KMDF映射并获取资源。
因此,基于此基础上,就有了本文的撰写目的。

2. 概要

2.1 环境约定

运行环境:WIN10/WIN11
开发工具:VS2019
SDK版本:wdksetup.exe
驱动框架:UMDF2
LOG工具: traceview

2.2 参考文档

A.
https://docs.microsoft.com/en-us/windows-hardware/drivers/wdf/finding-and-mapping-hardware-resources

B.
https://docs.microsoft.com/en-us/windows-hardware/drivers/wdf/reading-and-writing-to-device-registers

3. 操作

3.1 DSDT 修改


 Device (TpDemo_I2C)
 {
     Name (_HID, EisaId ("SIL0333") /* PCI Express Bus */)  // _HID: Hardware ID
     Name (_DDN, "SIL03333_DDN")
     Name (_DEP, Package (0x03)  // _DEP: Dependencies
     {
         GPO4, 
         GPO2, 
         SPI2
     })
     Method (_STA, 0, NotSerialized)  // _STA: Status
     {
         Return (0x0F)
     }
     Method (_CRS, 0, NotSerialized)  // _CRS: Current Resource Settings
     {
         Name (FBUF, ResourceTemplate ()
         {
             SpiSerialBusV2 (0x0000, PolarityLow, FourWireMode, 0x08,
                 ControllerInitiated, 0x000f4240, ClockPolarityLow,
                 ClockPhaseFirst, "\\_SB.PCI0.SPI2",
                 0x00, ResourceConsumer, , Exclusive,
                 )
             //PinFunction(Exclusive, PullDefault, 0x5, "\\_SB.GPI22", 0, ResourceConsumer, ) {2, 3}
             //PinConfig(Exclusive, 0x01, 10000, "\\_SB.GPI22", 0, ResourceConsumer, ) {2, 3}
             /*
             Interrupt (ResourceConsumer, Edge, ActiveHigh, Exclusive, ,, )
             {
                 0x00000048,
             }
             */
             /*
             GpioIo (Exclusive, PullDefault, 0x0000, 0x0000, IoRestrictionOutputOnly,
                 "\\_SB.GPO2", 0x00, ResourceConsumer, ,
                 )
                 {   // Pin list
                     0x004E
                 }
             GpioInt (Level, ActiveHigh, ExclusiveAndWake, PullNone, 0x0000,//GpioInt (Edge, ActiveBoth, ExclusiveAndWake, PullNone, 0x0000,
                 "\\_SB.GPO4", 0x00, ResourceConsumer, ,
                 )
                 {   // Pin list
                     0x0005
                 } */
             GpioIo (Shared, PullNone, 0x0000, 0x0000, IoRestrictionNone,
                 "\\_SB.GPO2", 0x00, ResourceConsumer, ,
                 )
                 {   // Pin list
                     0x0018
                 }
             GpioInt (Edge, ActiveHigh, Shared, PullNone, 0x0000,//GpioInt (Edge, ActiveBoth, Shared, PullNone, 0x0000,
                 "\\_SB.GPO2", 0x00, ResourceConsumer, ,
                 )
                 {   // Pin list
                     0x0018
                 }
         })
         // from laptop
         /*
         CreateWordField (FBUF, 0x3B, RSTP)
         CreateWordField (FBUF, 0x5E, INTP)
         Store (GNUM (GFPS), RSTP)
         Store (GNUM (GFPI), INTP)
         */
         
         Return (FBUF) /* \_SB_.PCI0.SPI1.FP01._CRS.FBUF */
     }
 }

3.2项目 INF 文件(TpDemo_I2C.inf)

[MyDevice_Install.NT.Wdf]
UmdfService=TpDemo_I2C,TpDemo_I2C_Install
UmdfServiceOrder=TpDemo_I2C
++UmdfDirectHardwareAccess=AllowDirectHardwareAccess

3.3 EvtDevicePrepareHardware

NTSTATUS
SPBDevicePrepareHardware(
    _In_
    WDFDEVICE Device,
    _In_
    WDFCMRESLIST ResourcesRaw,
    _In_
    WDFCMRESLIST ResourcesTranslated
)
{
    ULONG resourceCount;
	ULONG ix;
	BOOLEAN I2ResourceFound = FALSE;
	BOOLEAN GPIOResourceFound = FALSE;
	PDEVICE_CONTEXT			  devContext = NULL;
	NTSTATUS status = STATUS_UNSUCCESSFUL;

	WDF_INTERRUPT_CONFIG interruptConfig;
	ULONG interruptIndex = 0;
	//(ResourcesRaw);
    LOG_MSG_DEBUG("Entry");

    /* 1. mapping resource. */

    /* 1.1 get the number of resource that the system has assigned to its device ; get it from kmdf ; dsdt --> kmdf --> umdf2 */
    resourceCount = WdfCmResourceListGetCount(ResourcesTranslated);

	/* 1.2 get resource from dsdt file ;dsdt --> kmdf --> umdf2 */
	devContext = DeviceGetContext(Device);
	devContext->InterruptCount = 0;
	for (ix = 0; ix < resourceCount; ix++)
	{
		//get details about a particular resource from the list.
		PCM_PARTIAL_RESOURCE_DESCRIPTOR pDescriptor;
		pDescriptor = WdfCmResourceListGetDescriptor(ResourcesTranslated, ix);
		if (pDescriptor == NULL)
		{
			break;
		}
		switch (pDescriptor->Type)
		{
		case CmResourceTypeConnection:
		{
			UCHAR Class = pDescriptor->u.Connection.Class;
			UCHAR Type = pDescriptor->u.Connection.Type;
			if (Class == CM_RESOURCE_CONNECTION_CLASS_SERIAL)
			{
				if (Type == CM_RESOURCE_CONNECTION_TYPE_SERIAL_I2C)//CM_RESOURCE_CONNECTION_TYPE_SERIAL_I2C
				{
					if (I2ResourceFound == FALSE)
					{
						// Save the SPB connection ID.
						devContext->ConnectionIds[SPB_RESOURCE_INDEX].LowPart =
							pDescriptor->u.Connection.IdLowPart;
						devContext->ConnectionIds[SPB_RESOURCE_INDEX].HighPart =
							pDescriptor->u.Connection.IdHighPart;
						LOG_MSG_DEBUG("I2Resource found.\n");
						I2ResourceFound = TRUE;
					}
				}
			}
			if (Class == CM_RESOURCE_CONNECTION_CLASS_GPIO)
			{
				// Check for GPIO pin resource.
				if (Type == CM_RESOURCE_CONNECTION_TYPE_GPIO_IO)// ±èè?£??òóD?à??gpio??£?
				{
					if (GPIOResourceFound == FALSE)
					{
						devContext->ConnectionIds[GPIO_RESOURCE_INDEX].LowPart =
							pDescriptor->u.Connection.IdLowPart;
						devContext->ConnectionIds[GPIO_RESOURCE_INDEX].HighPart =
							pDescriptor->u.Connection.IdHighPart;
						LOG_MSG_DEBUG("GPIOResource found.\n");
						GPIOResourceFound = TRUE;
					}
				}
			}
		}
		break;

		case CmResourceTypeInterrupt: // ?a??ê????′à′μ?£?
		{
			devContext->InterruptCount++;
			interruptIndex = ix;
			// Check for interrupt resource.
			//create interrupt object.
		}
		break;

		default:
			// Don't care about other resource descriptors.
			break;
		}//end switch
	}

	LOG_MSG_DEBUG("Resource values! SPB = %d, GPIO = %d, InterruptCount = %d\n",
		I2ResourceFound,
		GPIOResourceFound,
		devContext->InterruptCount);

	if ((devContext->InterruptCount != 1) || (I2ResourceFound != 1) || (GPIOResourceFound != 1))
	{
		LOG_MSG_DEBUG(" get hw resource failed :%d",status);
		return status;
	}
	else {
		status = STATUS_SUCCESS;
	}
    LOG_MSG_DEBUG("Exit");
    return status;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

人在路上……

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值