📄 queue.c
字号:
/*!****************************************************************************
@File services/common/queue.c
@Title Kernel side command queue functions
@Author Imagination Technologies
@date 02/09/2003
@Copyright Copyright 2003-2004 by Imagination Technologies Limited.
All rights reserved. No part of this software, either
material or conceptual may be copied or distributed,
transmitted, transcribed, stored in a retrieval system
or translated into any human or computer language in any
form by any means, electronic, mechanical, manual or
other-wise, or disclosed to third parties without the
express written permission of Imagination Technologies
Limited, Unit 8, HomePark Industrial Estate,
King's Langley, Hertfordshire, WD4 8LZ, U.K.
@Platform generic
@Description Kernel side command queue functions
@DoxygenVer
******************************************************************************/
/******************************************************************************
Modifications :-
$Log: queue.c $
*****************************************************************************/
#ifndef QUEUE_C
#define QUEUE_C
#include "services_headers.h"
#if defined(__linux__) && defined(__KERNEL__)
#include "proc.h"
/*****************************************************************************
Return the name of a command as a string
*/
static const char *
CommandName (IMG_UINT32 ui32CommandID)
{
switch (ui32CommandID)
{
case PVRSRV_CMD_ID_BLT: return "blt"; break;
case PVRSRV_CMD_ID_FLIP: return "flip"; break;
case PVRSRV_CMD_ID_RENDER: return "render"; break;
case PVRSRV_CMD_ID_LOCK: return "lock"; break;
case PVRSRV_CMD_ID_UPDATE: return "update"; break;
default: return "unknown"; break;
}
} /*CommandName*/
/*****************************************************************************
FUNCTION : QueuePrintCommands
PURPOSE : Walks a command queue and prints each command into the supplied
buffer
PARAMETERS : psQueue - the queue
buf - buffer to print into
size - total size of buffer
off - the offset into the buffer to start at
*****************************************************************************/
static int
QueuePrintCommands (PVRSRV_QUEUE_INFO * psQueue, char * buffer, size_t size)
{
off_t off = 0;
IMG_UINT32 ui32ReadOffset = psQueue->ui32ReadOffset;
IMG_UINT32 ui32WriteOffset = psQueue->ui32WriteOffset;
PVRSRV_CMD_HEADER * psCmdHeader;
off = printAppend (buffer, size, off, " queue at %p\n ", psQueue);
while (ui32ReadOffset != ui32WriteOffset)
{
psCmdHeader = (PVRSRV_CMD_HEADER *)
((IMG_UINT32)psQueue->pvLinQueueKM + ui32ReadOffset);
off = printAppend (buffer, size, off, "%s ",
CommandName (psCmdHeader->ui32CommandID));
/* taken from UPDATE_QUEUE_ROFF in queue.h */
ui32ReadOffset += psCmdHeader->ui32Size;
ui32ReadOffset &= psQueue->ui32QueueSize - 1;
}
return printAppend (buffer, size, off, " <end>\n");
} /*QueuePrintCommands*/
/*****************************************************************************
FUNCTION : QueuePrintQueues
PURPOSE : Print the commands in each existing command queue
PARAMETERS : buf - buffer to print into
size - total size of buffer
off - the offset into the buffer to start at
*****************************************************************************/
off_t
QueuePrintQueues (char * buffer, size_t size, off_t off)
{
off_t n;
SYS_DATA * psSysData;
PVRSRV_QUEUE_INFO * psQueue;
if (SysAcquireData(&psSysData) != PVRSRV_OK)
return END_OF_FILE;
if (!off)
return printAppend (buffer, size, 0, "Command Queues\n");
/* Find the allocation according to the index. We do want the first entry
* and, as 'off' is non-zero here, we must use off-1 */
for (n=0, psQueue = psSysData->psQueueList; psQueue && n<off-1; n++)
psQueue = psQueue->psNextKM;
return psQueue ? QueuePrintCommands (psQueue, buffer, size) : END_OF_FILE;
} /*QueuePrintQueues*/
#endif // __linux__ && __KERNEL__
/*****************************************************************************
Kernel-side functions of User->Kernel transitions
******************************************************************************/
IMG_UINT32 NearestPower2(IMG_UINT32 ui32Value)
{
IMG_UINT32 ui32Temp, ui32Result = 1;
if(!ui32Value)
return 0;
ui32Temp = ui32Value - 1;
while(ui32Temp)
{
ui32Result <<= 1;
ui32Temp >>= 1;
}
return ui32Result;
}
/*!
******************************************************************************
@Function PVRSRVDestroyCommandQueueCallback
@Description
Destroys a command queue
@Input ui32ProcessID : process id
@Input pvParam - data packet
@Input ui32Param - packet size
@Return PVRSRV_ERROR :
******************************************************************************/
static PVRSRV_ERROR IMG_CALLCONV DestroyCommandQueueCallBack(IMG_UINT32 ui32ProcessID, IMG_PVOID pvParam, IMG_UINT32 ui32Param)
{
PVRSRV_QUEUE_INFO *psQueueInfo = (PVRSRV_QUEUE_INFO *)pvParam;
PVRSRV_QUEUE_INFO *psQueue;
SYS_DATA *psSysData;
PVRSRV_ERROR eError;
IMG_UINT32 i;
eError = SysAcquireData(&psSysData);
if (eError != PVRSRV_OK)
{
return eError;
}
psQueue = psSysData->psQueueList;
for(i=0; i<WAIT_TRY_COUNT; i++)
{
if(psQueueInfo->ui32ReadOffset == psQueueInfo->ui32WriteOffset)
{
break;
}
SysKickCmdProc (psSysData->pui32KickerAddr);
HostWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
//FIXME: not required in kernel? HostReleaseThreadQuanta();
}
if(i==WAIT_TRY_COUNT)
{
PVR_DPF((PVR_DBG_ERROR,"DestroyCommandQueueCallBack : Failed to empty queue"));
return PVRSRV_ERROR_GENERIC;
}
/* Ensure we don't corrupt queue list, by blocking access */
eError = HostLockResource(&psSysData->hQProcessResource, IMG_TRUE);
if (eError != PVRSRV_OK)
{
return eError;
}
if(psQueue == psQueueInfo)
{
psSysData->psQueueList = psQueueInfo->psNextKM;
HostFreeMem(PVRSRV_HOST_NON_PAGEABLE_HEAP, psQueueInfo->pvLinQueueKM);
HostFreeMem(PVRSRV_HOST_NON_PAGEABLE_HEAP, psQueueInfo);
eError = HostDestroyResource(&psQueueInfo->hAccess);
if (eError != PVRSRV_OK)
{
return eError;
}
}
else
{
while(psQueue)
{
if(psQueue->psNextKM == psQueueInfo)
{
psQueue->psNextKM = psQueueInfo->psNextKM;
HostFreeMem(PVRSRV_HOST_NON_PAGEABLE_HEAP, psQueueInfo->pvLinQueueKM);
HostFreeMem(PVRSRV_HOST_NON_PAGEABLE_HEAP, psQueueInfo);
eError = HostDestroyResource(&psQueueInfo->hAccess);
if (eError != PVRSRV_OK)
{
return eError;
}
break;
}
psQueue = psQueue->psNextKM;
}
if(!psQueue)
{
eError = HostUnlockResource(&psSysData->hQProcessResource);
if (eError != PVRSRV_OK)
{
return eError;
}
return PVRSRV_ERROR_INVALID_PARAMS;
}
}
return HostUnlockResource(&psSysData->hQProcessResource);
}
/*!
******************************************************************************
@Function PVRSRVCreateCommandQueue
@Description
Creates a new command queue into which render/blt commands etc can be
inserted.
@Input psDevData :
@Input ui32QueueSize :
@Output ppsQueueInfo :
@Return PVRSRV_ERROR :
******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateCommandQueue( PVRSRV_DEV_DATA *psDevData,
IMG_UINT32 ui32QueueSize,
PVRSRV_QUEUE_INFO **ppsQueueInfo)
{
PVRSRV_QUEUE_INFO *psQueueInfo;
IMG_UINT32 ui32Power2QueueSize = NearestPower2(ui32QueueSize);
SYS_DATA *psSysData;
PVRSRV_ERROR eError;
eError = SysAcquireData(&psSysData);
if (eError != PVRSRV_OK)
{
return eError;
}
/* allocate an internal queue info structure */
if(HostAllocMem( PVRSRV_HOST_NON_PAGEABLE_HEAP,
sizeof(PVRSRV_QUEUE_INFO),
(IMG_VOID **)&psQueueInfo, 0) != PVRSRV_OK)
{
goto ErrorExit;
}
HostMemSet(psQueueInfo, 0, sizeof(PVRSRV_QUEUE_INFO));
/* allocate the command queue buffer - allow for overrun */
if(HostAllocMem( PVRSRV_HOST_NON_PAGEABLE_HEAP,
ui32Power2QueueSize + PVRSRV_MAX_CMD_SIZE,
&psQueueInfo->pvLinQueueKM, 0) != PVRSRV_OK)
{
goto ErrorExit;
}
psQueueInfo->pvLinQueueUM = psQueueInfo->pvLinQueueKM;
psQueueInfo->ui32ReadOffset = 0;
psQueueInfo->ui32WriteOffset = 0;
if (HostCreateResource(&psQueueInfo->hAccess) != PVRSRV_OK)
{
goto ErrorExit;
}
psQueueInfo->ui32QueueSize = ui32Power2QueueSize;
/* Ensure we don't corrupt queue list, by blocking access */
if (HostLockResource(&psSysData->hQProcessResource, IMG_TRUE) != PVRSRV_OK)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -