锐英源软件
第一信赖

精通

英语

开源

擅长

开发

培训

胸怀四海 

第一信赖

当前位置:锐英源 / 驱动开发 / 访问物理内存、端口和PCI配置空间

服务方向

人工智能数据处理
人工智能培训
kaldi数据准备
小语种语音识别
语音识别标注
语音识别系统
语音识别转文字
kaldi开发技术服务
软件开发
运动控制卡上位机
机械加工软件
软件开发培训
Java 安卓移动开发
VC++
C#软件
汇编和破解
驱动开发

联系方式

固话:0371-63888850
手机:138-0381-0136
Q Q:396806883
微信:ryysoft

访问物理内存、端口和PCI配置空间


重点

MDL、IRP_MN_QUERY_INTERFACE、用接口的ReadConfig和WriteConfig读取。如果需要学习驱动开发培训,请联系QQ396806883,微信ryysoft。

Introduction 介绍

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配置空间的功能。


Background 背景

 

1. The Architecture 1.架构

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配置空间。


2. Access Physical Port 2.访问物理端口

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的函数读写端口。


3. Access Physical Memory 3.访问物理内存

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中可以找到更好的实现。只需要三个步骤:

  1. Use MmMapIoSpace to map physical address to kernel mode virtual address, driver can access this virtual address, but it’s not accessible in user mode. 使用MmMapIoSpace将物理地址映射到内核模式虚拟地址,驱动程序可以访问该虚拟地址,但是在用户模式下无法访问。
  2. Use IoAllocateMdl and MmBuildMdlForNonPagedPool to build an MDL for the mapped physical address. 使用IoAllocateMdl和MmBuildMdlForNonPagedPool为映射的物理地址构建MDL。
  3. Use MmMapLockedPages to map the physical pages described by MDL to user mode virtual address. Since our driver will always be the topmost driver, and run in the context of the current process, this user mode virtual address is valid to the caller. 使用MmMapLockedPages将MDL描述的物理页面映射到用户模式虚拟地址。由于我们的驱动程序将永远是最顶层的驱动程序,并且在当前进程的上下文中运行,因此该用户模式虚拟地址对调用方有效。

4. Access PCI Configuration Space 4.访问PCI配置空间

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总线上层滤波器驱动程序,该驱动程序将位于实际功能总线驱动程序之上。


Using the Code 使用代码

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),请执行以下两个步骤:

  1. Set environment variable $DDKROOT to DDK installation directory, such as "D:\WINDDK\2600”. 将环境变量$ DDKROOT设置到DDK安装目录,例如``D:\\ WINDDK \\ 2600''。
  2. In VC++ IDE, Tools->Options->Directories->Show directories for, choose “Executable files”, add DDK bin directory and move to the first line, such as “D:\WINDDK\2600\BIN\X86”. 在VC ++ IDE中,工具->选项->目录->显示目录,选择``可执行文件'',添加DDK bin目录并移至第一行,例如``D:\\ WINDDK \\ 2600 \\ BIN \\ X86''。

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设备驱动程序”一书。


Manual 手册

Copy pmdll.h, pmdll.lib to your source code directory, include and link with. 将pmdll.h,pmdll.lib复制到您的源代码目录中,包括并链接到该源代码目录。

  1. Copy pmdll.dll, phymem.sys to your application directory to run with. 将pmdll.dll,phymem.sys复制到要运行的应用程序目录中。
  2. Function Reference: 功能参考:
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 将物理内存映射到用户虚拟空间

    1. phyAddr = physical memory address
    2. memSize = memory size in bytes
VOID  UnmapPhyMem(PVOID pVirAddr, DWORD memSize)

Unmap mapped user virtual address 取消映射映射的用户虚拟地址

    1. pVirAddr = mapped user virtual address (return value of MapPhyMem)
    2. memSize = memory size in bytes
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配置空间

    1. busNum: Bus number (0-255)
    2. devNum: Device number (0-31)
    3. funcNum: Function number (0-7)
    4. regOff: Register offset (0-255)
    5. bytes: Bytes to read
    6. pValue: Buffer to receive returned value (must be allocated by the function caller)
BOOL  WritePCI(DWORD busNum, DWORD devNum, DWORD funcNum, 
                                           DWORD regOff, DWORD bytes, PVOID pValue)

Write PCI configuration space 写入PCI配置空间

    1. busNum: Bus number (0-255)
    2. devNum: Device number (0-31)
    3. funcNum: Function number (0-7)
    4. regOff: Register offset (0-255)
    5. bytes: Bytes to read
    6. pValue: New values to write

How to Install PCI Filter Driver 如何安装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筛选器驱动程序可能会完全崩溃您的计算机,使用该风险自负。

友情链接
版权所有 Copyright(c)2004-2015 锐英源软件
公司注册号:410105000449586 豫ICP备08007559号 最佳分辨率 1024*768
地址:郑州市文化路47号院1号楼4层(47-1楼位于文化路和红专路十字路口东北角,郑州大学工学院招待所南边,工学院科技报告厅西边。)