📄 pcifuction_haero.c
字号:
}
}
return ApiInvalidDeviceInfo;
}
DEVICE_NODE * DeviceListAdd(HANDLE hDevice)
{
DEVICE_NODE *pCurrentDevice;
DEVICE_NODE *pPreviousDevice;
LockGlobals();
pPreviousDevice = pDeviceList;
if (pDeviceList != NULL)
{
while (pPreviousDevice->pNext != NULL)
{
pPreviousDevice = pPreviousDevice->pNext;
}
}
// Allocate a new node
pCurrentDevice = (DEVICE_NODE *)malloc(sizeof(DEVICE_NODE));
if (pCurrentDevice == NULL)
{
UnlockGlobals();
return NULL;
}
// Fill in new data
pCurrentDevice->Handle = hDevice;
pCurrentDevice->pEventList = NULL;
pCurrentDevice->pDmaList = NULL;
pCurrentDevice->pNext = NULL;
FillMemory(
&pCurrentDevice->VirtualAddrs,
sizeof(VIRTUAL_ADDRESSES),
0xff
);
FillMemory(
&pCurrentDevice->PciMemory,
sizeof(PCI_MEMORY),
0xff
);
// Adjust the pointers
if (pDeviceList == NULL)
{
pDeviceList = pCurrentDevice;
}
else
{
pPreviousDevice->pNext = pCurrentDevice;
}
// Release access to globals
UnlockGlobals();
return pCurrentDevice;
}
/******************************************************************************
*
* Function : IoPoolGetNode
*
* Description: Returns an I/O Node from a pool. New structures are
* allocated on an as-needed basis. An event handle is
* also allocated and inserted into the overlapped strucure.
*
* Returns : Pointer - to an IO_NODE structure
* NULL - if error
*
*****************************************************************************/
IO_NODE *IoPoolGetNode(void)
{
IO_NODE *pIoNode;
IO_NODE *pIoNodePrevious;
LockGlobals();
pIoNode = pIoPoolList;
// Search for an unused already allocated node
while (pIoNode != NULL)
{
if (pIoNode->InUse == FALSE)
{
pIoNode->InUse = TRUE;
UnlockGlobals();
pIoNode->Overlapped.Internal = 0;
pIoNode->Overlapped.InternalHigh = 0;
pIoNode->Overlapped.Offset = 0;
pIoNode->Overlapped.OffsetHigh = 0;
return pIoNode;
}
pIoNodePrevious = pIoNode;
pIoNode = pIoNode->pNext;
}
// Allocate a new node
pIoNode = (IO_NODE *)malloc(sizeof(IO_NODE));
if (pIoNode == NULL)
{
UnlockGlobals();
return NULL;
}
// Mark as In Use
pIoNode->InUse = TRUE;
// End the list
pIoNode->pNext = NULL;
// Add the node to the list
if (pIoPoolList == NULL)
pIoPoolList = pIoNode;
else
pIoNodePrevious->pNext = pIoNode;
UnlockGlobals();
// Allocate the event
pIoNode->Overlapped.hEvent =
CreateEvent(
NULL, // Not inheritable to child processes
TRUE, // Manual reset?
FALSE, // Intial state
NULL
);
pIoNode->Overlapped.Internal = 0;
pIoNode->Overlapped.InternalHigh = 0;
pIoNode->Overlapped.Offset = 0;
pIoNode->Overlapped.OffsetHigh = 0;
return pIoNode;
}
void IoPoolReleaseNode(IO_NODE *pIoNode)
{
pIoNode->InUse = FALSE;
}
RETURN_CODE PlxPciDeviceClose(HANDLE hDevice)
{
BOOLEAN removed;
removed = DeviceListRemove(hDevice);
if (removed == FALSE)
{
return ApiInvalidDeviceInfo;
}
return ApiSuccess;
}
BOOLEAN DeviceListRemove(HANDLE hDevice)
{
BOOLEAN DeviceFound;
IO_NODE *pIoNode;
DEVICE_NODE *pCurrentDevice;
DEVICE_NODE *pPreviousDevice;
if (pDeviceList == NULL)
return FALSE;
LockGlobals();
pCurrentDevice = pDeviceList;
// Search for the node in the Device List
DeviceFound = FALSE;
do
{
if (pCurrentDevice->Handle == hDevice)
DeviceFound = TRUE;
else
{
// Check for end of list
if (pCurrentDevice->pNext == NULL)
{
UnlockGlobals();
return FALSE;
}
pPreviousDevice = pCurrentDevice;
pCurrentDevice = pCurrentDevice->pNext;
}
}
while (DeviceFound == FALSE);
// Remove device from the list
if (pDeviceList == pCurrentDevice)
{
pDeviceList = pCurrentDevice->pNext;
}
else
{
pPreviousDevice->pNext = pCurrentDevice->pNext;
}
// Release access to globals
UnlockGlobals();
// Clear the Event List
if (pCurrentDevice->pEventList != NULL)
{
IoListDestroy(&(pCurrentDevice->pEventList));
}
// Clear the DMA List
if (pCurrentDevice->pDmaList != NULL)
{
IoListDestroy(
&(pCurrentDevice->pDmaList)
);
}
pIoNode = IoPoolGetNode();
// Send message to the driver to unmap the virtual addresses
if ( pCurrentDevice->VirtualAddrs.Va0 != (unsigned long)-1 ||
pCurrentDevice->VirtualAddrs.Va1 != (unsigned long)-1 ||
pCurrentDevice->VirtualAddrs.Va2 != (unsigned long)-1 ||
pCurrentDevice->VirtualAddrs.Va3 != (unsigned long)-1 ||
pCurrentDevice->VirtualAddrs.Va4 != (unsigned long)-1 ||
pCurrentDevice->VirtualAddrs.Va5 != (unsigned long)-1 ||
pCurrentDevice->VirtualAddrs.VaRom != (unsigned long)-1 )
{
pIoNode->IoBuffer.MgmtData.VirtAddr = pCurrentDevice->VirtualAddrs;
DeviceIoControl(
pCurrentDevice->Handle,
PLX_IOCTL_BASE_ADDRESSES_FREE,
&(pIoNode->IoBuffer),
sizeof(IOCTLDATA),
NULL,
0,
NULL,
&(pIoNode->Overlapped)
);
}
// Send message to the driver to unmap the common buffer
if ( pCurrentDevice->PciMemory.UserAddr != (unsigned long)-1 ||
pCurrentDevice->PciMemory.PhysicalAddr != (unsigned long)-1 ||
pCurrentDevice->PciMemory.Size != (unsigned long)-1 )
{
pIoNode->IoBuffer.MgmtData.PciMemory.UserAddr = pCurrentDevice->PciMemory.UserAddr;
DeviceIoControl(
pCurrentDevice->Handle,
PLX_IOCTL_COMMON_BUFFER_FREE,
&(pIoNode->IoBuffer),
sizeof(IOCTLDATA),
NULL,
0,
NULL,
&(pIoNode->Overlapped)
);
}
IoPoolReleaseNode(
pIoNode
);
// Close the handle
CloseHandle(
pCurrentDevice->Handle
);
// Release memory
free(
pCurrentDevice
);
return TRUE;
}
void IoListDestroy(IO_NODE **pIoList)
{
while (*pIoList != NULL)
{
IoListRemove(pIoList,*pIoList);
}
}
BOOLEAN IoListRemove(IO_NODE **pIoList,IO_NODE *pIoNodeToRemove)
{
BOOLEAN bFlag;
DWORD BytesTransferred;
IO_NODE *pCurrentNode;
IO_NODE *pPreviousNode;
if (*pIoList == NULL)
return FALSE;
LockGlobals();
pCurrentNode = *pIoList;
// Search for the node in the Event List
bFlag = FALSE;
do
{
if (pCurrentNode == pIoNodeToRemove)
bFlag = TRUE;
else
{
// Check for end of list
if (pCurrentNode->pNext == NULL)
{
UnlockGlobals();
return FALSE;
}
pPreviousNode = pCurrentNode;
pCurrentNode = pCurrentNode->pNext;
}
}
while (bFlag == FALSE);
// Adjust the pointers
if (*pIoList == pCurrentNode)
{
*pIoList = pCurrentNode->pNext;
}
else
{
pPreviousNode->pNext = pCurrentNode->pNext;
}
// Release access to globals
UnlockGlobals();
// Check the status of the Overlapped operation
bFlag = GetOverlappedResult(
pCurrentNode->Overlapped.hEvent,
&(pCurrentNode->Overlapped),
&BytesTransferred,
FALSE // Don't wait for completion
);
if (bFlag == FALSE)
{
if (GetLastError() == ERROR_IO_INCOMPLETE)
return FALSE;
}
// Cleanup the Event Node if the operation has completed
// Release the event handle
CloseHandle(
pCurrentNode->Overlapped.hEvent
);
// Release I/O node memory
free(
pCurrentNode
);
return TRUE;
}
RETURN_CODE PlxChipTypeGet(HANDLE hDevice,unsigned long *pChipType,unsigned char *pRevision)
{
IO_NODE *pIoNode;
if ((pChipType == NULL) ||
(pRevision == NULL))
{
return ApiNullParam;
}
// Verify the handle
if (DeviceListFind(hDevice) == NULL)
{
return ApiInvalidHandle;
}
pIoNode = IoPoolGetNode();
DeviceIoControl(
hDevice,
PLX_IOCTL_CHIP_TYPE_GET,
NULL,
0,
&(pIoNode->IoBuffer),
sizeof(IOCTLDATA),
NULL,
&(pIoNode->Overlapped)
);
*pChipType = pIoNode->IoBuffer.MiscData.Value;
*pRevision = (unsigned char)pIoNode->IoBuffer.MiscData.Value1;
IoPoolReleaseNode(
pIoNode
);
return ApiSuccess;
}
RETURN_CODE PlxDmaSglChannelOpen(HANDLE hDevice,DMA_CHANNEL dmaChannel,DMA_CHANNEL_DESC *pDmaChannelDesc)
{
IO_NODE *pIoNode;
DEVICE_NODE *pDevice;
RETURN_CODE rc;
// Verify the handle
pDevice = DeviceListFind(
hDevice
);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -