阅读:1484回复:3
怎样将硬件地址映射到用户程序中?
能不能将硬件的物理地址映射到当前用户进程中,使用用户程序直接使用CopyMemory函数读写硬件内存?
在DDK中该使用什么函数? |
|
最新喜欢:mapofl
|
沙发#
发布于:2003-12-07 17:34
MapPhysicalMemoryToLinearSpace
|
|
板凳#
发布于:2003-12-07 17:37
//copy from WINIO source code:
NTSTATUS MapPhysicalMemoryToLinearSpace(PVOID pPhysAddress, ULONG PhysMemSizeInBytes, PVOID *ppPhysMemLin, HANDLE *pPhysicalMemoryHandle) { UNICODE_STRING PhysicalMemoryUnicodeString; PVOID PhysicalMemorySection = NULL; OBJECT_ATTRIBUTES ObjectAttributes; PHYSICAL_ADDRESS ViewBase; NTSTATUS ntStatus; PHYSICAL_ADDRESS pStartPhysAddress; PHYSICAL_ADDRESS pEndPhysAddress; PHYSICAL_ADDRESS MappingLength; BOOLEAN Result1, Result2; ULONG IsIOSpace; unsigned char *pbPhysMemLin = NULL; OutputDebugString (\"Entering MapPhysicalMemoryToLinearSpace\"); RtlInitUnicodeString (&PhysicalMemoryUnicodeString, L\"\\\\Device\\\\PhysicalMemory\"); InitializeObjectAttributes (&ObjectAttributes, &PhysicalMemoryUnicodeString, OBJ_CASE_INSENSITIVE, (HANDLE) NULL, (PSECURITY_DESCRIPTOR) NULL); *pPhysicalMemoryHandle = NULL; ntStatus = ZwOpenSection (pPhysicalMemoryHandle, SECTION_ALL_ACCESS, &ObjectAttributes); if (NT_SUCCESS(ntStatus)) { ntStatus = ObReferenceObjectByHandle (*pPhysicalMemoryHandle, SECTION_ALL_ACCESS, (POBJECT_TYPE) NULL, KernelMode, &PhysicalMemorySection, (POBJECT_HANDLE_INFORMATION) NULL); if (NT_SUCCESS(ntStatus)) { pStartPhysAddress.QuadPart = (ULONGLONG)pPhysAddress; pEndPhysAddress = RtlLargeIntegerAdd (pStartPhysAddress, RtlConvertUlongToLargeInteger(PhysMemSizeInBytes)); IsIOSpace = 0; Result1 = HalTranslateBusAddress (1, 0, pStartPhysAddress, &IsIOSpace, &pStartPhysAddress); IsIOSpace = 0; Result2 = HalTranslateBusAddress (1, 0, pEndPhysAddress, &IsIOSpace, &pEndPhysAddress); if (Result1 && Result2) { MappingLength = RtlLargeIntegerSubtract (pEndPhysAddress, pStartPhysAddress); if (MappingLength.LowPart) { // Let ZwMapViewOfSection pick a linear address PhysMemSizeInBytes = MappingLength.LowPart; ViewBase = pStartPhysAddress; ntStatus = ZwMapViewOfSection (*pPhysicalMemoryHandle, (HANDLE) -1, &pbPhysMemLin, 0L, PhysMemSizeInBytes, &ViewBase, &PhysMemSizeInBytes, ViewShare, 0, PAGE_READWRITE | PAGE_NOCACHE); if (!NT_SUCCESS(ntStatus)) OutputDebugString (\"ERROR: ZwMapViewOfSection failed\"); else { pbPhysMemLin += (ULONG)pStartPhysAddress.LowPart - (ULONG)ViewBase.LowPart; *ppPhysMemLin = pbPhysMemLin; } } else OutputDebugString (\"ERROR: RtlLargeIntegerSubtract failed\"); } else OutputDebugString (\"ERROR: MappingLength = 0\"); } else OutputDebugString (\"ERROR: ObReferenceObjectByHandle failed\"); } else OutputDebugString (\"ERROR: ZwOpenSection failed\"); if (!NT_SUCCESS(ntStatus)) ZwClose(*pPhysicalMemoryHandle); OutputDebugString (\"Leaving MapPhysicalMemoryToLinearSpace\"); return ntStatus; } |
|
地板#
发布于:2003-12-07 19:06
非常感谢.
我在DDK中也找到了其它方法,非常适用于KernelDriver中. 使用KernelDriver6.11,假设一块PCI卡,有1024字节缓存,想要映射到用户程序中,使用户程序可以直接读写,方法如下: 驱动程序中的TEST_STRUCT结构体中增加两中定义 PMDL pMdl; PVOID pUserVirtualAddress; 在TEST_Open例程中,WD_CardRegister函数调用成功后,在hTEST结构体中已经有PCI卡内存的物理地址和ring0虚拟地址,想要得到ring3虚拟地址,过程如下: 在return TRUE;前面加入 hTEST->pMdl = IoAllocateMdl((PVOID)hTEST->cardReg.Card.Item[hTEST->addrDesc[AD_PCI_BAR1].index].I.Mem.dwTransAddr),1024, FALSE, FALSE, NULL); if(hTEST->pMdl != NULL) { MmBuildMdlForNonPagedPool(hhTEST->pMdl); hTEST->pUserVirtualAddress = MmMapLockedPages(hTEST->pMdl,UserMode);//得到ring3虚拟地址! } 这样就把PCI卡上的内存映射到了用户程序中,通过DeviceIoControl,把映射指针pUserVirtualAddress传给用户程序,用户程序就可以直接读写PCI卡的内存了。 最后在驱动程序关闭时的操作: 在TEST_Close例程中的开头加入 if (hTEST->pMdl != NULL) { MmUnmapLockedPages(hTEST->pUserVirtualAddress, hTEST->pMdl); IoFreeMdl(hTEST->pMdl); } 有不正确处,请高手指正. |
|
|