📄 commonapi.c
字号:
// Set buffer request size
pBufferObj->Size = pPciMem->Size;
// Set Cacheability of the buffer
pBufferObj->bCacheable = Gbl_PhysicalMemoryCacheable;
// Setup amount to reduce on failure
DecrementAmount = (pPciMem->Size / 10);
DebugPrintf((
"Attempting to allocate physical memory (%d Kb)...\n",
(pPciMem->Size >> 10)
));
do
{
// Attempt to allocate the buffer
pBufferObj->pKernelVa =
Plx_dma_buffer_alloc(
pdx,
pBufferObj
);
if (pBufferObj->pKernelVa == NULL)
{
// Reduce memory request size if requested
if (bSmallerOk && (pBufferObj->Size > PAGE_SIZE))
{
pBufferObj->Size -= DecrementAmount;
}
else
{
// Release the list object
ExFreePool(
pBufferObj
);
DebugPrintf((
"ERROR - Physical memory allocation failed\n"
));
pPciMem->Size = 0;
return ApiInsufficientResources;
}
}
}
while (pBufferObj->pKernelVa == NULL);
// Record buffer owner
pBufferObj->pOwner = pOwner;
// Allocate MDL for buffer for later mapping into user space
pBufferObj->pMdl =
IoAllocateMdl(
pBufferObj->pKernelVa,
pBufferObj->Size,
FALSE, // Is this a secondary buffer?
FALSE, // Charge quota?
NULL // No IRP associated with MDL
);
// Check if the MDL allocation succeeded
if (pBufferObj->pMdl == NULL)
DebugPrintf(("ERROR - failed to allocate an MDL for buffer\n"));
else
{
// Build the MDL
MmBuildMdlForNonPagedPool(
pBufferObj->pMdl
);
}
// Initialize mappings list
InitializeListHead(
&(pBufferObj->List_Mappings)
);
KeInitializeSpinLock(
&(pBufferObj->Lock_MappingsList)
);
// Return buffer information
pPciMem->Size = pBufferObj->Size;
pPciMem->PhysicalAddr = pBufferObj->BusPhysical;
pPciMem->CpuPhysical = pBufferObj->CpuPhysical;
// Add buffer object to list
ExInterlockedInsertTailList(
&(pdx->List_PhysicalMem),
&(pBufferObj->ListEntry),
&(pdx->Lock_PhysicalMemList)
);
// Check if this is the common buffer allocation
if (pdx == pOwner)
{
// Store common buffer information
pGbl_CommonBuffer = pBufferObj;
}
return ApiSuccess;
}
/******************************************************************************
*
* Function : PlxPciPhysicalMemoryFree
*
* Description: Free previously allocated physically contiguous page-locked memory
*
******************************************************************************/
RETURN_CODE
PlxPciPhysicalMemoryFree(
DEVICE_EXTENSION *pdx,
PLX_PHYSICAL_MEM *pPciMem
)
{
KIRQL IrqL_Original;
PLIST_ENTRY pEntry;
PLX_PHYS_MEM_OBJECT *pBufferObj;
KeAcquireSpinLock(
&(pdx->Lock_PhysicalMemList),
&IrqL_Original
);
pEntry = pdx->List_PhysicalMem.Flink;
// Traverse list to find the desired list object
while (pEntry != &(pdx->List_PhysicalMem))
{
// Get the object
pBufferObj =
CONTAINING_RECORD(
pEntry,
PLX_PHYS_MEM_OBJECT,
ListEntry
);
// Check if the physical addresses matches
if (pBufferObj->BusPhysical == pPciMem->PhysicalAddr)
{
// Release lock until mappings are removed
KeReleaseSpinLock(
&(pdx->Lock_PhysicalMemList),
IrqL_Original
);
// Make sure all mappings to this memory are unmapped
PlxPciPhysicalMemoryUnmapAll_ByOwner(
pdx,
pBufferObj,
NULL // Ignore owner to remove all mappings
);
// Remove the object from the list
KeAcquireSpinLock(
&(pdx->Lock_PhysicalMemList),
&IrqL_Original
);
RemoveEntryList(
pEntry
);
KeReleaseSpinLock(
&(pdx->Lock_PhysicalMemList),
IrqL_Original
);
// Free the MDL
if (pBufferObj->pMdl != NULL)
{
IoFreeMdl(
pBufferObj->pMdl
);
}
Plx_dma_buffer_free(
pdx,
pBufferObj
);
// Release the list object
ExFreePool(
pBufferObj
);
// Check if this is the common buffer release
if (pGbl_CommonBuffer == pBufferObj)
{
// Clear common buffer information
pGbl_CommonBuffer = NULL;
}
return ApiSuccess;
}
// Jump to next item in the list
pEntry = pEntry->Flink;
}
KeReleaseSpinLock(
&(pdx->Lock_PhysicalMemList),
IrqL_Original
);
DebugPrintf((
"ERROR - buffer object not found in list\n"
));
return ApiInvalidData;
}
/******************************************************************************
*
* Function : PlxPciPhysicalMemoryMap
*
* Description: Maps physical memory to User virtual address space
*
******************************************************************************/
RETURN_CODE
PlxPciPhysicalMemoryMap(
DEVICE_EXTENSION *pdx,
PLX_PHYSICAL_MEM *pPciMem,
BOOLEAN bDeviceMem,
VOID *pOwner
)
{
VOID *pUserVa;
KIRQL IrqL_Original;
BOOLEAN bFound;
PLIST_ENTRY pEntry;
PHYSICAL_ADDRESS AddrPhysical;
PLX_USER_MAPPING *pMapObject;
PLX_PHYS_MEM_OBJECT *pMemObject;
MEMORY_CACHING_TYPE CacheMode;
// Set default return value
pPciMem->UserAddr = 0;
pMemObject = NULL;
// Check if memory object is common buffer
if (pGbl_CommonBuffer != NULL)
{
if (pPciMem->PhysicalAddr == pGbl_CommonBuffer->BusPhysical)
{
pMemObject = pGbl_CommonBuffer;
}
}
// Find the memory object to map
if (pMemObject == NULL)
{
// Find the object in the list
KeAcquireSpinLock(
&(pdx->Lock_PhysicalMemList),
&IrqL_Original
);
pEntry = pdx->List_PhysicalMem.Flink;
bFound = FALSE;
// Traverse list to find the desired list object
while (!bFound && (pEntry != &(pdx->List_PhysicalMem)))
{
// Get the object
pMemObject =
CONTAINING_RECORD(
pEntry,
PLX_PHYS_MEM_OBJECT,
ListEntry
);
// Check if the physical addresses matches
if (pMemObject->BusPhysical == pPciMem->PhysicalAddr)
{
bFound = TRUE;
}
else
{
// Jump to next item in the list
pEntry = pEntry->Flink;
}
}
KeReleaseSpinLock(
&(pdx->Lock_PhysicalMemList),
IrqL_Original
);
if (!bFound)
{
DebugPrintf((
"ERROR - Physical memory object not found in list, unable to map\n"
));
return ApiInvalidAddress;
}
}
// Verify an MDL for the memory
if (pMemObject->pMdl == NULL)
{
DebugPrintf((
"ERROR - MDL does not exist for this memory, cannot map to user space\n"
));
return ApiInsufficientResources;
}
// Set cache mode
if (Gbl_PhysicalMemoryCacheable)
{
CacheMode = MmCached;
}
else
{
CacheMode = MmNonCached;
}
// Attempt to map the region
pUserVa =
MmMapLockedPagesSpecifyCache(
pMemObject->pMdl,
UserMode,
CacheMode,
NULL,
FALSE,
NormalPagePriority
);
if (pUserVa == NULL)
{
DebugPrintf((
"ERROR - Unable to map Physical address (0x%08lx) ==> User Space\n",
pMemObject->CpuPhysical
));
return ApiInsufficientResources;
}
DebugPrintf((
"Mapped Physical address (0x%08lx) ==> Virtual address (0x%p) (owner=%p)\n",
pMemObject->CpuPhysical, pUserVa, pOwner
));
// Return virtual address
pPciMem->UserAddr = (PLX_UINT_PTR)pUserVa;
// Save mapping to list for this physical memory
pMapObject =
ExAllocatePool(
NonPagedPool,
sizeof(PLX_USER_MAPPING)
);
if (pMapObject == NULL)
{
DebugPrintf((
"ERROR: Unable to save mapping, insufficient memory\n"
));
}
else
{
// Clear the virtual addresses
RtlZeroMemory(
pMapObject->pUserVa,
MAX_VIRTUAL_ADDR * sizeof(VOID*)
);
// Record the IRP owner
pMapObject->pOwner = pOwner;
// Record the virtual address
pMapObject->pUserVa[0] = pUserVa;
// Save the mapping for later cleanup
ExInterlockedInsertTailList(
&(pMemObject->List_Mappings),
&(pMapObject->ListEntry),
&(pMemObject->Lock_MappingsList)
);
}
return ApiSuccess;
}
/******************************************************************************
*
* Function : PlxPciPhysicalMemoryUnmap
*
* Description: Unmap physical memory from User virtual address space
*
******************************************************************************/
RETURN_CODE
PlxPciPhysicalMemoryUnmap(
DEVICE_EXTENSION *pdx,
PLX_PHYSICAL_MEM *pPciMem,
VOID *pOwner
)
{
VOID *pUserVa;
KIRQL IrqL_Original;
BOOLEAN bFound;
PLIST_ENTRY pEntry;
PHYSICAL_ADDRESS AddrPhysical;
PLX_USER_MAPPING *pMapObject;
PLX_PHYS_MEM_OBJECT *pMemObject;
pMemObject = NULL;
// Check if memory object is common buffer
if (pGbl_CommonBuffer != NULL)
{
if (pPciMem->PhysicalAddr == pGbl_CommonBuffer->BusPhysical)
{
pMemObject = pGbl_CommonBuffer;
}
}
// Find the memory object to unmap
if (pMemObject == NULL)
{
// Find the object in the list
KeAcquireSpinLock(
&(pdx->Lock_PhysicalMemList),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -