#define PAGE_SIZE 				0x1000 	// 1 page:4KB
#define PAGE_ALIGN(Vaddr) 		((PVOID)((ULONG)(Vaddr) & ~(PAGE_SIZE - 1)))
#define ROUND_TO_PAGES(Size)  	(((ULONG)(Size) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))

extern "C"
{
   __declspec(dllimport) BOOL   VirtualCopy(LPVOID lpvDest, LPVOID lpvSrc, DWORD cbSize, DWORD fdwProtect);
}

PVOID MapPhysicalAddr(PVOID dwPhysicalAddress, DWORD dwSize)
{
	LPVOID pVirtualAddr;
	PVOID PageAlinedPhysicalAddress;
	ULONG Offset;
	DWORD PageAlignedSize;
	BOOL bCopyReturn;

	// Get Page Aligned Address
	PageAlinedPhysicalAddress = PAGE_ALIGN (dwPhysicalAddress);
	Offset = (ULONG)dwPhysicalAddress - (ULONG)PageAlinedPhysicalAddress;

	// Get page Aligned Size
	PageAlignedSize = ROUND_TO_PAGES(dwSize + Offset);

	// Create reserved block of virtual memory
	pVirtualAddr = VirtualAlloc(0, PageAlignedSize, MEM_RESERVE, PAGE_NOACCESS);

    if(pVirtualAddr == NULL) 
	{
		RETAILMSG(1,(L"	MapPhysicalAddr : Error Return. \r\n"));
        return NULL;
    }

	// Map physical memory to virtual memory
 	// then /256 and use the PAGE_PHYSICAL flag
	//----------------------------------------------
    bCopyReturn = VirtualCopy (	pVirtualAddr, 
								(LPVOID)((ULONG)PageAlinedPhysicalAddress >> 8),
								PageAlignedSize, 
								PAGE_READWRITE | PAGE_NOCACHE | PAGE_PHYSICAL);

    if(bCopyReturn == FALSE) 
	{
		RETAILMSG(1,(L"	MapPhysicalAddr : return false from VirtualCopy(). \r\n"));      
        VirtualFree( pVirtualAddr, 0, MEM_RELEASE  );
        return NULL;
    }

	pVirtualAddr = (PVOID)((PUCHAR)pVirtualAddr + Offset);

	return pVirtualAddr;

}