精通
英语
和
开源
,
擅长
开发
与
培训
,
胸怀四海
第一信赖
服务方向
联系方式
MDL、IRP_MN_QUERY_INTERFACE、用接口的ReadConfig和WriteConfig读取。如果需要学习驱动开发培训,请联系QQ396806883,微信ryysoft。
I recently developed a lot of interest in ACPI programming. By Googling, I found Intel’s ACPICA open source library. Of course, to make it work (such as read ACPI tables, evaluate ACPI methods), I must implement some functions to access physical memory, port and PCI configuration space, even install ISR. 我最近对ACPI编程产生了很多兴趣。通过Googling,我找到了英特尔的ACPICA开源库。当然,要使其正常工作(例如读取ACPI表,评估ACPI方法),我必须实现一些功能来访问物理内存,端口和PCI配置空间,甚至安装ISR。
It’s quite easy to implement these functions in kernel mode. But I don't want to put the whole ACPICA library in a “.sys” which will make it very hard to debug. Debugging is important for me because I always want to find out what really happens. So the only solution is to access these resources in user mode. 在内核模式下实现这些功能非常容易。但是我不想将整个ACPICA库放在“ .sys”中,这将使调试变得非常困难。调试对我来说很重要,因为我一直想找出实际发生的情况。因此,唯一的解决方案是在用户模式下访问这些资源。
At first I used WinIO and it works. Yet after reading the source code, I found it used too many “undocumented” and “obsolete” functions. I decided to make a more elegant solution, and add the function of accessing PCI configuration space. 起初我使用了WinIO,它可以正常工作。但是,在阅读源代码之后,我发现它使用了太多的“未记录”和“过时”的功能。我决定做出一个更优雅的解决方案,并添加访问PCI配置空间的功能。
I borrow the software architecture from WinIO: a kernel mode driver “phymem.sys” and a user mode DLL “pmdll.dll”. Applications can easily access physical memory using the functions exported by pmdll.dll, which will talk to the phymem.sys by standard “DeviceIoControl”. 我从WinIO借用了软件体系结构:内核模式驱动程序“ phymem.sys”和用户模式DLL“ pmdll.dll”。应用程序可以使用pmdll.dll导出的功能轻松访问物理内存,该功能将通过标准“ DeviceIoControl”与phymem.sys进行通信。
To access PCI configuration space in a DDK recommended method, I wrote a PCI bus upper filter driver “PCIFlt.sys”. With this filter driver, we can find the unnamed PCI bus driver which lies under our named filter driver. Then we use “Driver Interface” to directly read and write PCI configuration space. 为了以DDK推荐的方法访问PCI配置空间,我编写了PCI总线上层过滤器驱动程序“ PCIFlt.sys”。使用此筛选器驱动程序,我们可以找到未命名的PCI总线驱动程序,该驱动程序位于我们命名的筛选器驱动程序下面。然后,我们使用“驱动程序接口”直接读取和写入PCI配置空间。
IA based PC uses separated port and memory address spaces. In kernel mode, we can read and write port with functions named like WRITE_PORT_UCHAR, READ_PORT_UCHAR. 基于IA的PC使用分开的端口和内存地址空间。在内核模式下,我们可以使用名为WRITE_PORT_UCHAR,READ_PORT_UCHAR的函数读写端口。
To access physical memory in user mode, we must map this memory region to the user process’ address space. One implementation is through the \Device\PhysicalMemory section object. This is first introduced in the old NT DDK samples. It uses obsolete functions which are not recommended; also the code is really hard to understand. 要以用户模式访问物理内存,我们必须将此内存区域映射到用户进程的地址空间。一种实现是通过\\ Device \\ PhysicalMemory部分对象。这是在旧的NT DDK示例中首次引入的。它使用了不推荐使用的过时功能;代码也很难理解。
A better implementation can be found in MSDN. Only three steps are required: 在MSDN中可以找到更好的实现。只需要三个步骤:
Windows XP bus drivers must implement “Driver Interface” which can be acquired by sending it an IRP with major code IRP_MN_QUERY_INTERFACE. After acquiring “Driver Interface”, we can access the bus address space by calling the interface provided ReadConfig and WriteConfig routines. Windows XP总线驱动程序必须实现“驱动程序接口”,可以通过向其发送包含主要代码IRP_MN_QUERY_INTERFACE的IRP来获取。获取“驱动程序接口”后,我们可以通过调用提供的接口ReadConfig和WriteConfig例程来访问总线地址空间。
The trouble is that the PCI bus driver has no name, that is, we can't find its device object. Without the PCI bus driver’s device object, we have no way to query its “Driver Interface”. The solution is providing a PCI bus upper filter driver, which will be layered above the actual function bus driver. 问题在于PCI总线驱动程序没有名称,也就是说,我们找不到其设备对象。没有PCI总线驱动程序的设备对象,我们将无法查询其“驱动程序接口”。该解决方案提供了PCI总线上层滤波器驱动程序,该驱动程序将位于实际功能总线驱动程序之上。
All source code is built under Visual C++ 6.0, XP DDK 2600, and Windows XP SP3. To build driver (.sys) in Visual C++ IDE, follow the next two steps: 所有源代码均在Visual C ++ 6.0,XP DDK 2600和Windows XP SP3下构建。要在Visual C ++ IDE中生成驱动程序(.sys),请执行以下两个步骤:
The driver source code uses PHDDebugPrint for debugging purposes. Reference the book “Writing Windows WDM Device Drivers” by Chris Cant. 驱动程序源代码使用PHDDebugPrint进行调试。请参考Chris Cant撰写的“编写Windows WDM设备驱动程序”一书。
Copy pmdll.h, pmdll.lib to your source code directory, include and link with. 将pmdll.h,pmdll.lib复制到您的源代码目录中,包括并链接到该源代码目录。
BOOL LoadPhyMemDriver()
Dynamically load phymem.sys into memory; Return TRUE if succeeded, otherwise FALSE. 动态将phymem.sys加载到内存中;如果成功返回TRUE,否则返回FALSE。
VOID UnloadPhyMemDriver()
Unload phymem.sys from memory. 从内存中卸载phymem.sys。
PVOID MapPhyMem(DWORD phyAddr, DWORD memSize)
Map physical memory to user virtual space 将物理内存映射到用户虚拟空间
VOID UnmapPhyMem(PVOID pVirAddr, DWORD memSize)
Unmap mapped user virtual address 取消映射映射的用户虚拟地址
BYTE ReadPortByte(WORD portAddr)
WORD ReadPortWord(WORD portAddr)
DWORD ReadPortLong(WORD portAddr)
Read one byte, two bytes and four bytes from Port address portAddr. 从端口地址portAddr读取一个字节,两个字节和四个字节。
VOID WritePortByte(WORD portAddr, BYTE portValue)
VOID WritePortWord(WORD portAddr, WORD portValue)
VOID WritePortLong(WORD portAddr, DWORD portValue)
Write one byte, two bytes and four bytes to Port address portAddr. 将一个字节,两个字节和四个字节写入端口地址portAddr。
BOOL ReadPCI(DWORD busNum, DWORD devNum, DWORD funcNum, DWORD regOff, DWORD bytes, PVOID pValue)
Read PCI configuration space 读取PCI配置空间
BOOL WritePCI(DWORD busNum, DWORD devNum, DWORD funcNum, DWORD regOff, DWORD bytes, PVOID pValue)
Write PCI configuration space 写入PCI配置空间
If you want to access PCI configuration space, the PCI filter driver “PCIFlt.sys” must be installed. In “Device Manager”, find “PCI Bus” and choose “Update Driver”, select the PCIFilter.inf. Don't automatically search the INF file, choose selecting driver by yourself. 如果要访问PCI配置空间,则必须安装PCI筛选器驱动程序“ PCIFlt.sys”。在“设备管理器”中,找到“ PCI总线”并选择“更新驱动程序”,然后选择PCIFilter.inf。不要自动搜索INF文件,而是选择自己选择驱动程序。
The PCI filter driver may totally crash your computer, use it at your own risk. PCI筛选器驱动程序可能会完全崩溃您的计算机,使用该风险自负。