📄 commonapi.c
字号:
&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 unmap\n"
));
return ApiInvalidAddress;
}
}
// Find the map object to unmap
KeAcquireSpinLock(
&(pMemObject->Lock_MappingsList),
&IrqL_Original
);
pEntry = pMemObject->List_Mappings.Flink;
bFound = FALSE;
// Traverse list to find the desired list object
while (!bFound && (pEntry != &(pMemObject->List_Mappings)))
{
// Get the object
pMapObject =
CONTAINING_RECORD(
pEntry,
PLX_USER_MAPPING,
ListEntry
);
// Compare owner & virtual address
if ((pOwner == pMapObject->pOwner) &&
((PLX_UINT_PTR)pMapObject->pUserVa[0] == pPciMem->UserAddr))
{
// Remove entry from the list
RemoveEntryList(
pEntry
);
bFound = TRUE;
}
else
{
// Jump to next item in the list
pEntry = pEntry->Flink;
}
}
KeReleaseSpinLock(
&(pMemObject->Lock_MappingsList),
IrqL_Original
);
if (!bFound)
{
DebugPrintf((
"ERROR - Mapping object not found in list, unable to unmap\n"
));
return ApiInvalidAddress;
}
// Unmap the memory
if (pMapObject->pUserVa[0] != NULL)
{
DebugPrintf((
"Unmapping Virtual address (0x%p) from User Space (owner=%p)...\n",
pMapObject->pUserVa[0], pOwner
));
MmUnmapLockedPages(
pMapObject->pUserVa[0],
pMemObject->pMdl
);
// Clear virtual address
pPciMem->UserAddr = 0;
}
else
{
DebugPrintf((
"ERROR - Invalid virtual address (0x%p), cannot unmap\n",
pMapObject->pUserVa[0]
));
return ApiInvalidAddress;
}
// Release memory for map object
ExFreePool(
pMapObject
);
return ApiSuccess;
}
/******************************************************************************
*
* Function : PlxPciBarMap
*
* Description: Map a PCI BAR Space into User virtual space
*
******************************************************************************/
RETURN_CODE
PlxPciBarMap(
DEVICE_EXTENSION *pdx,
U8 BarIndex,
VOID *pUserVa,
VOID *pOwner
)
{
U8 i;
PMDL pMdl[MAX_VIRTUAL_ADDR];
VOID *Va[MAX_VIRTUAL_ADDR];
VOID *VaBase;
BOOLEAN bMapError;
PLX_USER_MAPPING *pMapObject;
// Set default address
*(PLX_UINT_PTR*)pUserVa = 0;
// Verify BAR is of type memory
if (pdx->PciBar[BarIndex].bIsIoSpace)
{
DebugPrintf((
"ERROR - BAR %d is an I/O space, cannot map to user space\n",
BarIndex
));
return ApiInvalidPciSpace;
}
// Check if the space is valid
if (pdx->PciBar[BarIndex].Physical.QuadPart == 0)
{
DebugPrintf((
"ERROR - BAR %d address (0x%08lx) is invalid\n",
BarIndex, pdx->PciBar[BarIndex].Physical
));
return ApiInvalidAddress;
}
// Verify Kernel virtual address
if (pdx->PciBar[BarIndex].pVa == NULL)
{
DebugPrintf((
"ERROR - Kernel Virtual address for BAR %d is not valid\n",
BarIndex
));
return ApiInvalidAddress;
}
// Make sure memory size is valid
if (pdx->PciBar[BarIndex].Size == 0)
{
DebugPrintf((
"ERROR - Size of BAR %d is 0\n",
BarIndex
));
return ApiInvalidSize;
}
// Verify the MDL
if (pdx->PciBar[BarIndex].pMdl == NULL)
{
DebugPrintf((
"ERROR - MDL does not exist for BAR %d\n",
BarIndex
));
return ApiInsufficientResources;
}
// Make sure there is enough space to store all virtual addresses
if (pdx->PciBar[BarIndex].Size > (MAX_VIRTUAL_ADDR * MAX_MDL_SIZE))
{
DebugPrintf((
"ERROR - Not enough virtual addresses for space of size %dMB\n",
(pdx->PciBar[BarIndex].Size >> 20)
));
return ApiInsufficientResources;
}
// Set initial values
i = 0;
pMdl[0] = pdx->PciBar[BarIndex].pMdl;
VaBase = NULL;
bMapError = FALSE;
// Clear the virtual addresses
RtlZeroMemory(
Va,
MAX_VIRTUAL_ADDR * sizeof(VOID*)
);
// Attempt to map the BAR into user space
while ((i < MAX_VIRTUAL_ADDR) && (pMdl[i] != NULL))
{
Va[i] =
MmMapLockedPagesSpecifyCache(
pMdl[i],
UserMode,
MmNonCached, // Do not cache PCI BAR space
VaBase, // User address to use
FALSE,
LowPagePriority
);
// Check if the mapping succeeded
if (Va[i] == NULL)
{
DebugPrintf((
"ERROR - Unable to map PCI BAR %d (0x%08lx) ==> User space\n",
BarIndex, pdx->PciBar[BarIndex].Physical
));
bMapError = TRUE;
}
else if (VaBase != NULL)
{
// Make sure VA address is consecutive
if (VaBase != Va[i])
{
DebugPrintf((
"ERROR - Unable to assign contiguous virtual addresses for PCI BAR %d (0x%08lx) ==> User space\n",
BarIndex, pdx->PciBar[BarIndex].Physical
));
bMapError = TRUE;
}
}
if (bMapError)
{
// Release any previous mappings
while (i != 0)
{
i--;
MmUnmapLockedPages(
Va[i],
pMdl[i]
);
}
return ApiInsufficientResources;
}
// Adjust to next consecutive base address
VaBase = ((U8*)Va[i]) + MmGetMdlByteCount(pMdl[i]);
// Go to next entry
i++;
pMdl[i] = pMdl[i-1]->Next;
}
// Return initial base address
*(PLX_UINT_PTR*)pUserVa = (PLX_UINT_PTR)Va[0];
DebugPrintf((
"Mapped PCI BAR %d (0x%08lx) ==> User VA (0x%08lx) (owner=%p)\n",
BarIndex, pdx->PciBar[BarIndex].Physical, *(PLX_UINT_PTR*)pUserVa, pOwner
));
// Add mapping to list for later unmapping
pMapObject =
ExAllocatePool(
NonPagedPool,
sizeof(PLX_USER_MAPPING)
);
if (pMapObject == NULL)
{
DebugPrintf(("ERROR: Unable to save mapping, insufficient memory\n"));
}
else
{
// Record mapping properties
pMapObject->pOwner = pOwner;
pMapObject->BarIndex = BarIndex;
RtlCopyMemory(
pMapObject->pUserVa,
Va,
MAX_VIRTUAL_ADDR * sizeof(VOID*)
);
// Save the mapping for later cleanup
ExInterlockedInsertTailList(
&(pdx->List_BarMappings),
&(pMapObject->ListEntry),
&(pdx->Lock_BarMappingsList)
);
}
return ApiSuccess;
}
/******************************************************************************
*
* Function : PlxPciBarUnmap
*
* Description: Unmap a previously mapped PCI BAR Space from User virtual space
*
******************************************************************************/
RETURN_CODE
PlxPciBarUnmap(
DEVICE_EXTENSION *pdx,
VOID *UserVa,
VOID *pOwner
)
{
U8 i;
PMDL pMdl;
KIRQL IrqL_Original;
PLIST_ENTRY pEntry;
PLX_USER_MAPPING *pMapObject;
// Find the previous mapping object
KeAcquireSpinLock(
&(pdx->Lock_BarMappingsList),
&IrqL_Original
);
pEntry = pdx->List_BarMappings.Flink;
while (pEntry != &(pdx->List_BarMappings))
{
pMapObject =
CONTAINING_RECORD(
pEntry,
PLX_USER_MAPPING,
ListEntry
);
if ((pMapObject->pOwner == pOwner) &&
(pMapObject->pUserVa[0] == UserVa))
{
// Remove map object from list
RemoveEntryList(
pEntry
);
KeReleaseSpinLock(
&(pdx->Lock_BarMappingsList),
IrqL_Original
);
DebugPrintf((
"Unmapping Virtual address (0x%p) for BAR %d from User Space (owner=%p)...\n",
pMapObject->pUserVa[0], pMapObject->BarIndex, pOwner
));
// Unmap the space
i = 0;
pMdl = pdx->PciBar[pMapObject->BarIndex].pMdl;
while ((i < MAX_VIRTUAL_ADDR) && (pMapObject->pUserVa[i] != NULL))
{
MmUnmapLockedPages(
pMapObject->pUserVa[i],
pMdl
);
i++;
pMdl = pMdl->Next;
}
// Release the list object
ExFreePool(
pMapObject
);
return ApiSuccess;
}
// Jump to next item
pEntry = pEntry->Flink;
}
DebugPrintf((
"ERROR - Map object not found in list...\n"
));
KeReleaseSpinLock(
&(pdx->Lock_BarMappingsList),
IrqL_Original
);
return ApiInvalidAddress;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -