📄 supportfunc.c
字号:
IoAllocateMdl(
pVa,
SizeToMap,
FALSE,
FALSE,
NULL
);
// Check if the MDL allocation succeeded
if (pMdl == NULL)
{
DebugPrintf(("ERROR - MDL allocation for space failed\n"));
// Release any created MDLs
while (pdx->PciBar[BarIndex].pMdl != NULL)
{
pMdl = pdx->PciBar[BarIndex].pMdl;
pdx->PciBar[BarIndex].pMdl = pMdl->Next;
IoFreeMdl(
pMdl
);
}
return STATUS_SUCCESS;
}
else
{
// Build the MDL
MmBuildMdlForNonPagedPool(
pMdl
);
}
// Clear next MDL pointer
pMdl->Next = NULL;
// Store MDL
if (pdx->PciBar[BarIndex].pMdl == NULL)
{
// Insert first MDL
pdx->PciBar[BarIndex].pMdl = pMdl;
pMdl_Previous = pMdl;
}
else
{
// Add new MDL to list
pMdl_Previous->Next = pMdl;
// Update previous pointer
pMdl_Previous = pMdl;
}
// Adjust for next virtual address
(U8*)pVa += SizeToMap;
// Adjust remaining count
SizeRemain -= SizeToMap;
}
return STATUS_SUCCESS;
}
/******************************************************************************
*
* Function : PlxPciBarResourcesUnmap
*
* Description: Unmap all mapped PCI BAR memory for a device
*
******************************************************************************/
VOID
PlxPciBarResourcesUnmap(
DEVICE_EXTENSION *pdx
)
{
U8 i;
PMDL pMdl;
// Go through all the BARS
for (i = 0; i < PCI_NUM_BARS_TYPE_00; i++)
{
// Unmap the space from Kernel space if previously mapped
if ((pdx->PciBar[i].bIsIoSpace == FALSE) &&
(pdx->PciBar[i].Physical.QuadPart != 0))
{
DebugPrintf(("Unmapping BAR %d...\n", i));
// Release the MDLs describing the BAR space
while (pdx->PciBar[i].pMdl != NULL)
{
pMdl = pdx->PciBar[i].pMdl;
pdx->PciBar[i].pMdl = pMdl->Next;
IoFreeMdl(
pMdl
);
}
// Unmap from kernel space
if (pdx->PciBar[i].pVa != NULL)
{
MmUnmapIoSpace(
pdx->PciBar[i].pVa,
pdx->PciBar[i].Size
);
pdx->PciBar[i].pVa = NULL;
}
}
}
}
/******************************************************************************
*
* Function : PlxPciBarSpaceUnmapAll_ByOwner
*
* Description: Unmap any PCI BAR spaces assigned to the specified owner
*
******************************************************************************/
VOID
PlxPciBarSpaceUnmapAll_ByOwner(
DEVICE_EXTENSION *pdx,
VOID *pOwner
)
{
VOID *UserVa;
KIRQL IrqL_Original;
PLIST_ENTRY pEntry;
PLX_USER_MAPPING *pMapObject;
KeAcquireSpinLock(
&(pdx->Lock_BarMappingsList),
&IrqL_Original
);
pEntry = pdx->List_BarMappings.Flink;
// Traverse list to find the desired list objects
while (pEntry != &(pdx->List_BarMappings))
{
// Get the object
pMapObject =
CONTAINING_RECORD(
pEntry,
PLX_USER_MAPPING,
ListEntry
);
// Check if owner matches
if (pMapObject->pOwner == pOwner)
{
// Copy address
UserVa = pMapObject->pUserVa[0];
// Release list lock
KeReleaseSpinLock(
&(pdx->Lock_BarMappingsList),
IrqL_Original
);
// Unmap BAR space
PlxPciBarUnmap(
pdx,
UserVa,
pOwner
);
KeAcquireSpinLock(
&(pdx->Lock_BarMappingsList),
&IrqL_Original
);
// Restart parsing the list from the beginning
pEntry = pdx->List_BarMappings.Flink;
}
else
{
// Jump to next item
pEntry = pEntry->Flink;
}
}
KeReleaseSpinLock(
&(pdx->Lock_BarMappingsList),
IrqL_Original
);
}
/******************************************************************************
*
* Function : PlxPciPhysicalMemoryFreeAll_ByOwner
*
* Description: Unmap & release all physical memory assigned to the specified owner
*
******************************************************************************/
VOID
PlxPciPhysicalMemoryFreeAll_ByOwner(
DEVICE_EXTENSION *pdx,
VOID *pOwner
)
{
KIRQL IrqL_Original;
PLIST_ENTRY pEntry;
PLX_PHYSICAL_MEM PciMem;
PLX_PHYS_MEM_OBJECT *pMemObject;
KeAcquireSpinLock(
&(pdx->Lock_PhysicalMemList),
&IrqL_Original
);
pEntry = pdx->List_PhysicalMem.Flink;
// Traverse list to find the desired list objects
while (pEntry != &(pdx->List_PhysicalMem))
{
// Get the object
pMemObject =
CONTAINING_RECORD(
pEntry,
PLX_PHYS_MEM_OBJECT,
ListEntry
);
// Check if owner matches
if (pMemObject->pOwner == pOwner)
{
// Copy memory information
PciMem.PhysicalAddr = pMemObject->BusPhysical;
PciMem.Size = pMemObject->Size;
// Release list lock
KeReleaseSpinLock(
&(pdx->Lock_PhysicalMemList),
IrqL_Original
);
// Release the memory & remove from list
PlxPciPhysicalMemoryFree(
pdx,
&PciMem
);
KeAcquireSpinLock(
&(pdx->Lock_PhysicalMemList),
&IrqL_Original
);
// Restart parsing the list from the beginning
pEntry = pdx->List_PhysicalMem.Flink;
}
else
{
// Jump to next item
pEntry = pEntry->Flink;
}
}
KeReleaseSpinLock(
&(pdx->Lock_PhysicalMemList),
IrqL_Original
);
}
/******************************************************************************
*
* Function : PlxPciPhysicalMemoryUnmapAll_ByOwner
*
* Description: Unmap any physical memory assigned to the specified owner
*
******************************************************************************/
VOID
PlxPciPhysicalMemoryUnmapAll_ByOwner(
DEVICE_EXTENSION *pdx,
PLX_PHYS_MEM_OBJECT *pMemObject,
VOID *pOwner
)
{
VOID *pUserVa;
KIRQL IrqL_Original;
PLIST_ENTRY pEntry;
PLX_PHYSICAL_MEM PciMem;
PHYSICAL_ADDRESS AddrPhysical;
PLX_USER_MAPPING *pMapObject;
// Verify Memory Object
if (pMemObject == NULL)
{
return;
}
// Verify size
if (pMemObject->Size == 0)
{
return;
}
// Setup memory properties
PciMem.PhysicalAddr = pMemObject->BusPhysical;
PciMem.Size = pMemObject->Size;
// Find the map object to unmap
KeAcquireSpinLock(
&(pMemObject->Lock_MappingsList),
&IrqL_Original
);
pEntry = pMemObject->List_Mappings.Flink;
// Traverse list to find the desired list object
while (pEntry != &(pMemObject->List_Mappings))
{
// Get the object
pMapObject =
CONTAINING_RECORD(
pEntry,
PLX_USER_MAPPING,
ListEntry
);
// Check if the owner matches
if ((pOwner == NULL) || (pMapObject->pOwner == pOwner))
{
// Copy virtual address
PciMem.UserAddr = (PLX_UINT_PTR)pMapObject->pUserVa[0];
// Release list lock
KeReleaseSpinLock(
&(pMemObject->Lock_MappingsList),
IrqL_Original
);
// Unmap the memory & remove from list
PlxPciPhysicalMemoryUnmap(
pdx,
&PciMem,
pMapObject->pOwner
);
KeAcquireSpinLock(
&(pMemObject->Lock_MappingsList),
&IrqL_Original
);
// Restart parsing the list from the beginning
pEntry = pMemObject->List_Mappings.Flink;
}
else
{
// Jump to next item
pEntry = pEntry->Flink;
}
}
KeReleaseSpinLock(
&(pMemObject->Lock_MappingsList),
IrqL_Original
);
}
/******************************************************************************
*
* Function : PlxDmaChannelCleanup
*
* Description: Called by the Cleanup routine to close any open channels
*
******************************************************************************/
VOID
PlxDmaChannelCleanup(
DEVICE_EXTENSION *pdx,
VOID *pOwner
)
{
#if defined(DMA_SUPPORT)
U8 i;
DMA_CHANNEL channel;
// Added to avoid compiler warning
channel = PrimaryPciChannel0;
for (i = 0; i < NUMBER_OF_DMA_CHANNELS; i++)
{
// Check if terminating application is the owner
if (pdx->DmaInfo[i].pOwner == pOwner)
{
DebugPrintf(("Closing DMA channel %d\n", i));
switch (i)
{
case 0:
channel = PrimaryPciChannel0;
break;
case 1:
channel = PrimaryPciChannel1;
break;
case 2:
channel = IopChannel2;
break;
}
switch (pdx->DmaInfo[i].state)
{
case DmaStateClosed:
// DMA closed already, do nothing
break;
case DmaStateBlock:
PlxDmaBlockChannelClose(
pdx,
channel,
FALSE
);
break;
case DmaStateSgl:
PlxDmaSglChannelClose(
pdx,
channel,
FALSE
);
break;
default:
// Unknown or unsupported state
break;
}
}
}
#endif // DMA_SUPPORT
}
#if defined(DMA_SUPPORT)
/******************************************************************************
*
* Function : PlxSglDmaTransferComplete
*
* Description: Perform any necessary cleanup after an SGL DMA transfer
*
******************************************************************************/
VOID
PlxSglDmaTransferComplete(
DEVICE_EXTENSION *pdx,
U8 DmaIndex
)
{
KIRQL IrqL_Original;
if (pdx->DmaInfo[DmaIndex].bPending == FALSE)
{
DebugPrintf(("No pending SGL DMA to complete\n"));
return;
}
DebugPrintf((
"Unlocking user-mode buffer used for SGL DMA transfer...\n"
));
KeAcquireSpinLock(
&(pdx->Lock_DmaChannel),
&IrqL_Original
);
// Unlock the data buffer and free the MDL
if (pdx->DmaInfo[DmaIndex].pMdl != NULL)
{
MmUnlockPages(
pdx->DmaInfo[DmaIndex].pMdl
);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -