📄 pvrsrv.c
字号:
if(eError != PVRSRV_OK)
{
return(eError);
}
bFindByType = IMG_FALSE;
if (eDeviceType != PVRSRV_DEVICE_TYPE_UNKNOWN)
{
bFindByType = IMG_TRUE;
}
/*
* First have a look to see if we all ready have this device...
*/
psDevInfo = (PPVRSRV_DEV_INFO) 0;
psThis = psSysData->psDevInfoList;
while (psThis)
{
bFound = IMG_FALSE;
if (bFindByType)
{
if (psThis->sDevId.eDeviceType == eDeviceType)
{
bFound = IMG_TRUE;
}
}
else
{
if (psThis->sDevId.ui32DeviceIndex == uiDevIndex)
{
bFound = IMG_TRUE;
}
}
if (bFound)
{
psDevInfo = psThis;
psThis = 0;
}
else
{
psThis = psThis->psNext;
}
}
/*
* Found it ? then return it..
*/
if(psDevInfo)
{
/*
* Increment instance count first !
*/
psDevInfo->ui32NumConnected++;
/*
* Setup KM Ptr
*/
psDevData->psDevInfoKM = psDevInfo;
/*
Fill in UM Ptr with KM Ptr.
This ptr must be overwritten by the IOCTL glue if a user/kernel divide exists
*/
psDevData->psDevInfoUM = psDevInfo;
psDevData->hServices = IMG_NULL;
psDevData->psResItem = ResManRegisterRes((PRESMAN_ITEM)IMG_NULL,
RESMAN_TYPE_ACQUIRE_DEVICE_DATA,
psDevData->psDevInfoKM,
0,
ReleaseDeviceDataCallBack,
RESMAN_AUTOFREE_LEV5);
return(PVRSRV_OK);
}
for(i=0; i < psSysData->ui32NumDevices; i++)
{
psDevID = &psSysData->asDevIdList[i];
bFound = IMG_FALSE;
if (bFindByType)
{
if (psDevID->eDeviceType == eDeviceType)
{
bFound = IMG_TRUE;
}
}
else
{
if (psDevID->ui32DeviceIndex == uiDevIndex)
{
bFound = IMG_TRUE;
}
}
if (bFound)
{
break;
}
else
{
psDevID = IMG_NULL;
}
}
if(!psDevID)
{
return PVRSRV_ERROR_INVALID_PARAMS;
}
if(!psSysData->bBMInitialised && !psDevID->bIsMemoryMaster)
{
return PVRSRV_ERROR_INVALID_PARAMS;
}
eError = InitDeviceInfo(&psDevInfo, psDevID);
if (eError != PVRSRV_OK)
{
return eError;
}
/*
* Insert device info structure into linked list..
*/
psDevInfo->psNext = psSysData->psDevInfoList;
psSysData->psDevInfoList = psDevInfo;
psDevData->psDevInfoKM = psDevInfo;
/* initialise connection count */
psDevInfo->ui32NumConnected = 1;
/* install ISR for the device */
eError = SysInstallISR(psDevInfo);
if (eError != PVRSRV_OK)
{
return eError;
}
/* initialise the device */
if(psDevInfo->pfnInitDevice != IMG_NULL)
{
eError = psDevInfo->pfnInitDevice (psDevInfo);
if (eError != PVRSRV_OK)
{
return eError;
}
}
if(!psSysData->bBMInitialised)
{
/* Initialise the memory manager */
if(BM_Initialise ( psDevInfo->sDevLocation.pvRegsBaseKM,
psDevInfo->sDevLocation.sDeviceSpecific.sMBX.s2DSlavePort.pvData,
psDevInfo->sDevId.ui32CoreConfig) != IMG_TRUE)
{
return PVRSRV_ERROR_INIT_FAILURE;
}
psSysData->bBMInitialised = IMG_TRUE;
}
/*
* Fill in user mode ptr.
* This ptr must be overwritten by the IOCTL glue if a user/kernel divide exists
*/
psDevData->psDevInfoUM = psDevInfo;
/* Require resource manager track resource */
psDevData->psResItem = ResManRegisterRes((PRESMAN_ITEM)IMG_NULL,
RESMAN_TYPE_ACQUIRE_DEVICE_DATA,
psDevData->psDevInfoKM,
0,
ReleaseDeviceDataCallBack,
RESMAN_AUTOFREE_LEV5);
return(PVRSRV_OK);
}
/*!
******************************************************************************
@Function ReleaseDeviceDataCallBack
@Description
This function is used to release device data it can either be called via the
resource manager or directly for PVRSRVReleaseDeviceData
@Input psDevData :
@Return PVRSRV_ERROR IMG_CALLCONV :
******************************************************************************/
static PVRSRV_ERROR ReleaseDeviceDataCallBack(IMG_UINT32 ui32ProcessID,
IMG_PVOID pvParam,
IMG_UINT32 ui32Param)
{
PPVRSRV_DEV_INFO psDevInfo = (PPVRSRV_DEV_INFO) pvParam;
PPVRSRV_DEV_INFO psThis, psPrev;
SYS_DATA *psSysData;
PVRSRV_ERROR eError = PVRSRV_OK;
IMG_BOOL bDoMemorySlavesExist = IMG_FALSE;
PVR_ASSERT(pvParam != IMG_NULL);
eError = SysAcquireData(&psSysData);
if (eError != PVRSRV_OK)
{
return eError;
}
psThis = psSysData->psDevInfoList;
while (psThis)
{
if(!psThis->sDevId.bIsMemoryMaster)
{
bDoMemorySlavesExist = IMG_TRUE;
}
psThis = psThis->psNext;
}
psDevInfo->ui32NumConnected--;
/* Time to go away ? */
if (psDevInfo->ui32NumConnected == 0)
{
if(psDevInfo->sDevId.bIsMemoryMaster && bDoMemorySlavesExist)
{
PVR_DPF((PVR_DBG_ERROR,"Cannot release master device until slave devices have gone"));
return PVRSRV_ERROR_INIT_FAILURE;
}
if(psSysData->psDevInfoList->psNext == IMG_NULL)
{
/* close down the buffer manager, eventually this call should
take a device handle */
BM_Finalise ();
psSysData->bBMInitialised = IMG_FALSE;
}
/* uninstall ISR for the device */
eError = SysUnInstallISR(psDevInfo);
if (eError != PVRSRV_OK)
{
return eError;
}
/*
de-init device
*/
if(psDevInfo->pfnDeInitDevice != IMG_NULL)
{
eError = psDevInfo->pfnDeInitDevice (psDevInfo);
if (eError != PVRSRV_OK)
{
return eError;
}
}
/*
Find list entry...
*/
psThis = psSysData->psDevInfoList;
psPrev = 0;
while (psThis)
{
if (psThis == psDevInfo)
{
/*
Found it, so remove it...
*/
if (psPrev)
{
psPrev->psNext = psThis->psNext;
}
else
{
/* update head of the list */
psSysData->psDevInfoList = psThis->psNext;
}
psThis = 0;
}
else
{
psPrev = psThis;
psThis = psThis->psNext;
}
}
/* free up heap allocations */
eError = DeInitDeviceInfo(psDevInfo);
if (eError != PVRSRV_OK)
{
return eError;
}
}
return(eError);
}
/*!
******************************************************************************
@Function PVRSRVReleaseDeviceData
@Description
This decrements the reference count to the device info structure and when the
reference count reaches zero causes the device to be de-initialised
@Input psDevData :
@Return PVRSRV_ERROR :
******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVReleaseDeviceData (PPVRSRV_DEV_DATA psDevData)
{
PVRSRV_ERROR eRtn;
if (psDevData == IMG_NULL)
{
return PVRSRV_ERROR_INVALID_PARAMS;
}
if(psDevData->psResItem)
{
eRtn = ResManFreeResByPtr(psDevData->psResItem);
}
else
{
/* Resource not managed call the free callback directly */
eRtn = ReleaseDeviceDataCallBack(0,(IMG_PVOID) psDevData->psDevInfoKM, 0);
}
return(eRtn);
}
/*!
******************************************************************************
@Function PVRSRVAllocDeviceMem
@Description
Allocates device memory
@Input psDevData : DevData for the device this memory will primarily be used with
@Input ui32Flags : Some combination of PVRSRV_MEMFLG_ flags
@Input ui32Size : Number of bytes to allocate
@Input ui32Alignment :
@Output **ppsMemInfo : On success, receives a pointer to the created MEM_INFO structure
@Return PVRSRV_ERROR :
******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVAllocDeviceMem (PVRSRV_DEV_DATA *psDevData,
IMG_UINT32 ui32Flags,
IMG_UINT32 ui32Size,
IMG_UINT32 ui32Alignment,
PVRSRV_MEM_INFO **ppsMemInfo)
{
PVRSRV_MEM_INFO* psMemInfo = (PVRSRV_MEM_INFO*)IMG_NULL;
PVRSRV_DEV_DATA *psNewDevData;
BM_HANDLE hBuffer;
/* Pointer to implementation details within the mem_info */
PVRSRV_MEMBLK *psMemBlock;
IMG_UINT32 ui3BM2Flags;
IMG_BOOL bBMError;
PPVRSRV_DEV_INFO psDevInfo;
if ((psDevData == IMG_NULL) || (ppsMemInfo == IMG_NULL))
{
return PVRSRV_ERROR_INVALID_PARAMS;
}
psDevInfo = psDevData->psDevInfoKM;
/* Start with an invalid pointer for the output value */
*ppsMemInfo = IMG_NULL;
if(HostAllocMem( PVRSRV_HOST_NON_PAGEABLE_HEAP,
sizeof(PVRSRV_MEM_INFO ),
(IMG_VOID **)&psMemInfo, 0) != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR,"PVRSRVAllocDeviceMem : Failed to alloc memory for block"));
return (PVRSRV_ERROR_OUT_OF_MEMORY);
}
if(HostAllocMem( PVRSRV_HOST_NON_PAGEABLE_HEAP,
sizeof(IMG_UINT32),
(IMG_VOID **)&psMemInfo->pui32Flags, 0) != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR,"PVRSRVAllocDeviceMem : Failed to alloc memory for flag word"));
HostFreeMem(PVRSRV_HOST_NON_PAGEABLE_HEAP, psMemInfo);
return PVRSRV_ERROR_OUT_OF_MEMORY;
}
psMemBlock = &(psMemInfo->sMemBlk);
/* Translate to BM flags....*/
ui3BM2Flags = ((ui32Flags&PVRSRV_MEMFLG_CONTIGIOUS) ? BP_CONTIGUOUS : 0 );
/* If requesting memory from alternate heap, request memory from secondary pool */
if(ui32Flags & PVRSRV_MEMFLG_ALTERNATE_HEAP)
{
ui3BM2Flags |= 1;
}
bBMError = BM_Alloc (ui32Size,
ui3BM2Flags,
ui32Alignment,
&hBuffer);
if (!bBMError)
{
PVR_DPF((PVR_DBG_ERROR,"PVRSRVWrapDeviceMem : BM_Alloc Failed"));
HostFreeMem(PVRSRV_HOST_NON_PAGEABLE_HEAP, psMemInfo->pui32Flags);
HostFreeMem(PVRSRV_HOST_NON_PAGEABLE_HEAP, psMemInfo);
return PVRSRV_ERROR_OUT_OF_MEMORY;
}
/* Fill in "Implementation dependant" section of mem info */
psMemBlock->sSysPhysAddr = BM_HandleToSysPaddr(hBuffer);
psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer);
/* Convert from BM_HANDLE to external IMG_HANDLE */
psMemBlock->hBuffer = (IMG_HANDLE)hBuffer.h;
/* Fill in the public fields of the MEM_INFO structure */
psMemInfo->pvLinAddr = BM_HandleToCpuVaddr(hBuffer);
psMemInfo->uiDevAddr = psMemBlock->sDevVirtAddr;
// Set to a known value to start with.
HostMemSet((void *)psMemInfo->pvLinAddr, 0x00, ui32Size);
*psMemInfo->pui32Flags = ui32Flags;
/* set the fact that the memory is valid */
*psMemInfo->pui32Flags &= ~PVRSRV_MEMFLG_MEMORY_NOT_AVAILABLE;
psMemInfo->ui32AllocSize = ui32Size;
psMemInfo->psSyncInfo = AllocSyncInfo(psDevInfo);
/* Clear the Backup buffer pointer as we do not have one at this point. We only allocate this as we are going up/down */
psMemInfo->pvSysBackupBuffer = IMG_NULL;
psMemInfo->psMemInfoKM = psMemInfo;
/*
* Setup the output.
*/
*ppsMemInfo = psMemInfo;
/* Register Resource */
if(ui32Flags & PVRSRV_MEMFLG_NO_RESMAN)
{
psMemInfo->sMemBlk.psResItem = IMG_NULL;
}
else
{
if(ui32Flags & PVRSRV_MEMFLG_FLIPPABLE)
{
IMG_UINT32 i, ui32NumDevices;
PVRSRV_DEVICE_IDENTIFIER asDeviceID[PVRSRV_MAX_DEVICES];
HostAllocMem( PVRSRV_HOST_NON_PAGEABLE_HEAP,sizeof(PVRSRV_DEV_DATA), (IMG_VOID **)&psNewDevData, 0);
/* FIXME: this really is ugly and might not work on a system with more than one display device */
PVRSRVEnumerateDevices(psDevData->hServices, &ui32NumDevices, asDeviceID);
for(i=0; i < ui32NumDevices; i++)
{
if(asDeviceID[i].eDeviceClass == PVRSRV_DEVICE_CLASS_DISPLAY)
{
PVRSRVAcquireDeviceData( psDevData->hServices,
asDeviceID[i].ui32DeviceIndex,
psNewDevData,
PVRSRV_DEVICE_TYPE_UNKNOWN);
break;
}
}
psMemInfo->sMemBlk.psResItem = ResManRegisterRes((PRESMAN_ITEM)IMG_NULL,
RESMAN_TYPE_FRAMBUFMEM,
psMemInfo,
(IMG_UINT32)psNewDevData,
FreeDeviceMemCallBack,
RESMAN_AUTOFREE_LEV4);
}
else
{
psMemInfo->sMemBlk.psResItem = ResManRegisterRes((PRESMAN_ITEM)IMG_NULL,
RESMAN_TYPE_FRAMBUFMEM,
psMemInfo,
0,
FreeDeviceMemCallBack,
RESMAN_AUTOFREE_LEV4);
}
}
/*
* And I think we're done for now....
*/
return (PVRSRV_OK);
}
/*!
******************************************************************************
@Function PVRSRVWrapDeviceMem
@Description
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -