IntroductionI 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. 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. 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. Background1. The ArchitectureI 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 “ 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. 2. Access Physical PortIA based PC uses separated port and memory address spaces. In kernel mode, we can read and write port with functions named like 3. Access Physical MemoryTo 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. A better implementation can be found in MSDN. Only three steps are required:
4. Access PCI Configuration SpaceWindows XP bus drivers must implement “Driver Interface” which can be acquired by sending it an IRP with major code 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. Using the CodeAll 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:
The driver source code uses Manual
![]() BYTE ReadPortByte(WORD portAddr)
Read one byte, two bytes and four bytes from Port address ![]() VOID WritePortByte(WORD portAddr, BYTE portValue)
Write one byte, two bytes and four bytes to Port address ![]() BOOL ReadPCI(DWORD busNum, DWORD devNum, DWORD funcNum,
Read PCI configuration space ![]() BOOL WritePCI(DWORD busNum, DWORD devNum, DWORD funcNum,
Write PCI configuration space How to Install PCI Filter DriverIf 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. The PCI filter driver may totally crash your computer, use it at your own risk. |
|