/*************************************************************************/ /*!
|
@File
|
@Title Debug Driver
|
@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
|
@Description 32 Bit kernel mode debug driver
|
@License Dual MIT/GPLv2
|
|
The contents of this file are subject to the MIT license as set out below.
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
of this software and associated documentation files (the "Software"), to deal
|
in the Software without restriction, including without limitation the rights
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
copies of the Software, and to permit persons to whom the Software is
|
furnished to do so, subject to the following conditions:
|
|
The above copyright notice and this permission notice shall be included in
|
all copies or substantial portions of the Software.
|
|
Alternatively, the contents of this file may be used under the terms of
|
the GNU General Public License Version 2 ("GPL") in which case the provisions
|
of GPL are applicable instead of those above.
|
|
If you wish to allow use of your version of this file only under the terms of
|
GPL, and not to allow others to use your version of this file under the terms
|
of the MIT license, indicate your decision by deleting the provisions above
|
and replace them with the notice and other provisions required by GPL as set
|
out in the file called "GPL-COPYING" included in this distribution. If you do
|
not delete the provisions above, a recipient may use your version of this file
|
under the terms of either the MIT license or GPL.
|
|
This License is also included in this distribution in the file called
|
"MIT-COPYING".
|
|
EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
|
PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
*/ /**************************************************************************/
|
|
#if defined(_WIN32)
|
#pragma warning(disable:4201)
|
#pragma warning(disable:4214)
|
#pragma warning(disable:4115)
|
#pragma warning(disable:4514)
|
|
|
#include <ntddk.h>
|
#include <windef.h>
|
#include <winerror.h>
|
#endif /* _WIN32 */
|
|
#ifdef LINUX
|
#include <linux/string.h>
|
#endif
|
|
#if defined (__QNXNTO__) || defined (INTEGRITY_OS)
|
#include <string.h>
|
#endif
|
|
#include "img_types.h"
|
#include "img_defs.h"
|
#include "pvr_debug.h"
|
#include "dbgdrvif_srv5.h"
|
#include "dbgdriv.h"
|
#include "hostfunc.h"
|
|
#ifdef _WIN32
|
#pragma warning(default:4214)
|
#pragma warning(default:4115)
|
#endif /* _WIN32 */
|
|
|
/******************************************************************************
|
Types
|
******************************************************************************/
|
|
/*
|
Per-buffer control structure.
|
*/
|
typedef struct _DBG_STREAM_
|
{
|
struct _DBG_STREAM_* psNext;
|
struct _DBG_STREAM_* psInitStream;
|
struct _DBG_STREAM_* psDeinitStream;
|
IMG_UINT32 ui32Flags; /*!< flags (see DEBUG_FLAGS) */
|
void *pvBase;
|
IMG_UINT32 ui32Size;
|
IMG_UINT32 ui32RPtr;
|
IMG_UINT32 ui32WPtr;
|
|
IMG_UINT32 ui32Marker; /*!< Size marker for file splitting */
|
|
IMG_UINT32 ui32InitPhaseWOff; /*!< snapshot offset for init phase end for follow-on pdump */
|
|
IMG_CHAR szName[DEBUG_STREAM_NAME_MAX]; /* Give this a size, some compilers don't like [] */
|
} DBG_STREAM;
|
|
/* Check 4xDBG_STREAM will fit in one page */
|
static_assert((sizeof(DBG_STREAM) * 4) < HOST_PAGESIZE, "DBG_STREAM is too large");
|
|
/******************************************************************************
|
Global variables
|
******************************************************************************/
|
|
static PDBG_STREAM g_psStreamList = 0;
|
|
/* Mutex used to prevent UM threads (via the dbgdrv ioctl interface) and KM
|
* threads (from pvrsrvkm via the ExtDBG API) entering the debug driver core
|
* and changing the state of share data at the same time.
|
*/
|
void * g_pvAPIMutex=NULL;
|
|
static IMG_UINT32 g_PDumpCurrentFrameNo = 0;
|
|
DBGKM_SERVICE_TABLE g_sDBGKMServices =
|
{
|
sizeof (DBGKM_SERVICE_TABLE),
|
ExtDBGDrivCreateStream,
|
ExtDBGDrivDestroyStream,
|
ExtDBGDrivWrite2,
|
ExtDBGDrivSetMarker,
|
ExtDBGDrivWaitForEvent,
|
ExtDBGDrivGetCtrlState,
|
ExtDBGDrivSetFrame
|
};
|
|
|
/***************************************************************************
|
Forward declarations
|
***************************************************************************/
|
|
IMG_BOOL IMG_CALLCONV DBGDrivCreateStream(IMG_CHAR *pszName, IMG_UINT32 ui32Flags, IMG_UINT32 ui32Pages, IMG_HANDLE* phInit, IMG_HANDLE* phMain, IMG_HANDLE* phDeinit);
|
void IMG_CALLCONV DBGDrivDestroyStream(IMG_HANDLE hInit,IMG_HANDLE hMain, IMG_HANDLE hDeinit);
|
void * IMG_CALLCONV DBGDrivFindStream(IMG_CHAR * pszName, IMG_BOOL bResetStream);
|
IMG_UINT32 IMG_CALLCONV DBGDrivRead(PDBG_STREAM psStream, IMG_UINT32 ui32BufID, IMG_UINT32 ui32OutBufferSize,IMG_UINT8 *pui8OutBuf);
|
void IMG_CALLCONV DBGDrivSetCaptureMode(PDBG_STREAM psStream,IMG_UINT32 ui32Mode,IMG_UINT32 ui32Start,IMG_UINT32 ui32Stop,IMG_UINT32 ui32SampleRate);
|
IMG_UINT32 IMG_CALLCONV DBGDrivWrite2(PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize);
|
void IMG_CALLCONV DBGDrivSetMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker);
|
IMG_UINT32 IMG_CALLCONV DBGDrivGetMarker(PDBG_STREAM psStream);
|
void IMG_CALLCONV DBGDrivWaitForEvent(DBG_EVENT eEvent);
|
IMG_UINT32 IMG_CALLCONV DBGDrivGetCtrlState(PDBG_STREAM psStream, IMG_UINT32 ui32StateID);
|
IMG_UINT32 IMG_CALLCONV DBGDrivGetFrame(void);
|
void IMG_CALLCONV DBGDrivSetFrame(IMG_UINT32 ui32Frame);
|
void DestroyAllStreams(void);
|
|
/* Static function declarations */
|
static IMG_UINT32 SpaceInStream(PDBG_STREAM psStream);
|
static IMG_BOOL ExpandStreamBuffer(PDBG_STREAM psStream, IMG_UINT32 ui32NewSize);
|
static void InvalidateAllStreams(void);
|
|
|
/*****************************************************************************
|
Code
|
*****************************************************************************/
|
|
/*!
|
@name ExtDBGDrivCreateStream
|
*/
|
IMG_BOOL IMG_CALLCONV ExtDBGDrivCreateStream(IMG_CHAR *pszName, IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size, IMG_HANDLE* phInit, IMG_HANDLE* phMain, IMG_HANDLE* phDeinit)
|
{
|
IMG_BOOL pvRet;
|
|
/* Acquire API Mutex */
|
HostAquireMutex(g_pvAPIMutex);
|
|
pvRet=DBGDrivCreateStream(pszName, ui32Flags, ui32Size, phInit, phMain, phDeinit);
|
|
/* Release API Mutex */
|
HostReleaseMutex(g_pvAPIMutex);
|
|
return pvRet;
|
}
|
|
/*!
|
@name ExtDBGDrivDestroyStream
|
*/
|
void IMG_CALLCONV ExtDBGDrivDestroyStream(IMG_HANDLE hInit,IMG_HANDLE hMain, IMG_HANDLE hDeinit)
|
{
|
/* Acquire API Mutex */
|
HostAquireMutex(g_pvAPIMutex);
|
|
DBGDrivDestroyStream(hInit, hMain, hDeinit);
|
|
/* Release API Mutex */
|
HostReleaseMutex(g_pvAPIMutex);
|
|
return;
|
}
|
|
/*!
|
@name ExtDBGDrivFindStream
|
*/
|
void * IMG_CALLCONV ExtDBGDrivFindStream(IMG_CHAR * pszName, IMG_BOOL bResetStream)
|
{
|
void * pvRet;
|
|
/* Acquire API Mutex */
|
HostAquireMutex(g_pvAPIMutex);
|
|
pvRet=DBGDrivFindStream(pszName, bResetStream);
|
if (pvRet == NULL)
|
{
|
PVR_DPF((PVR_DBG_ERROR, "ExtDBGDrivFindStream: Stream not found"));
|
}
|
|
|
/* Release API Mutex */
|
HostReleaseMutex(g_pvAPIMutex);
|
|
return pvRet;
|
}
|
|
/*!
|
@name ExtDBGDrivRead
|
*/
|
IMG_UINT32 IMG_CALLCONV ExtDBGDrivRead(PDBG_STREAM psStream, IMG_UINT32 ui32BufID, IMG_UINT32 ui32OutBuffSize,IMG_UINT8 * pui8OutBuf)
|
{
|
IMG_UINT32 ui32Ret;
|
|
/* Acquire API Mutex */
|
HostAquireMutex(g_pvAPIMutex);
|
|
ui32Ret=DBGDrivRead(psStream, ui32BufID, ui32OutBuffSize, pui8OutBuf);
|
|
/* Release API Mutex */
|
HostReleaseMutex(g_pvAPIMutex);
|
|
return ui32Ret;
|
}
|
|
/*!
|
@name ExtDBGDrivWrite2
|
*/
|
IMG_UINT32 IMG_CALLCONV ExtDBGDrivWrite2(PDBG_STREAM psStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize)
|
{
|
IMG_UINT32 ui32Ret;
|
|
/* Acquire API Mutex */
|
HostAquireMutex(g_pvAPIMutex);
|
|
ui32Ret=DBGDrivWrite2(psStream, pui8InBuf, ui32InBuffSize);
|
|
/* Release API Mutex */
|
HostReleaseMutex(g_pvAPIMutex);
|
|
return ui32Ret;
|
}
|
|
/*!
|
@name ExtDBGDrivSetMarker
|
*/
|
void IMG_CALLCONV ExtDBGDrivSetMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker)
|
{
|
/* Acquire API Mutex */
|
HostAquireMutex(g_pvAPIMutex);
|
|
DBGDrivSetMarker(psStream, ui32Marker);
|
|
/* Release API Mutex */
|
HostReleaseMutex(g_pvAPIMutex);
|
|
return;
|
}
|
|
/*!
|
@name ExtDBGDrivGetMarker
|
*/
|
IMG_UINT32 IMG_CALLCONV ExtDBGDrivGetMarker(PDBG_STREAM psStream)
|
{
|
IMG_UINT32 ui32Marker;
|
|
/* Acquire API Mutex */
|
HostAquireMutex(g_pvAPIMutex);
|
|
ui32Marker = DBGDrivGetMarker(psStream);
|
|
/* Release API Mutex */
|
HostReleaseMutex(g_pvAPIMutex);
|
|
return ui32Marker;
|
}
|
|
/*!
|
@name ExtDBGDrivWaitForEvent
|
*/
|
void IMG_CALLCONV ExtDBGDrivWaitForEvent(DBG_EVENT eEvent)
|
{
|
#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
|
DBGDrivWaitForEvent(eEvent);
|
#else /* defined(SUPPORT_DBGDRV_EVENT_OBJECTS) */
|
PVR_UNREFERENCED_PARAMETER(eEvent); /* PRQA S 3358 */
|
#endif /* defined(SUPPORT_DBGDRV_EVENT_OBJECTS) */
|
}
|
|
|
/*!
|
@name ExtDBGDrivGetCtrlState
|
*/
|
IMG_UINT32 IMG_CALLCONV ExtDBGDrivGetCtrlState(PDBG_STREAM psStream, IMG_UINT32 ui32StateID)
|
{
|
IMG_UINT32 ui32State = 0;
|
|
/* Acquire API Mutex */
|
HostAquireMutex(g_pvAPIMutex);
|
|
ui32State = DBGDrivGetCtrlState(psStream, ui32StateID);
|
|
/* Release API Mutex */
|
HostReleaseMutex(g_pvAPIMutex);
|
|
return ui32State;
|
}
|
|
/*!
|
@name ExtDBGDrivGetFrame
|
*/
|
IMG_UINT32 IMG_CALLCONV ExtDBGDrivGetFrame(void)
|
{
|
IMG_UINT32 ui32Frame = 0;
|
|
/* Acquire API Mutex */
|
HostAquireMutex(g_pvAPIMutex);
|
|
ui32Frame = DBGDrivGetFrame();
|
|
/* Release API Mutex */
|
HostReleaseMutex(g_pvAPIMutex);
|
|
return ui32Frame;
|
}
|
|
/*!
|
@name ExtDBGDrivGetCtrlState
|
*/
|
void IMG_CALLCONV ExtDBGDrivSetFrame(IMG_UINT32 ui32Frame)
|
{
|
/* Acquire API Mutex */
|
HostAquireMutex(g_pvAPIMutex);
|
|
DBGDrivSetFrame(ui32Frame);
|
|
/* Release API Mutex */
|
HostReleaseMutex(g_pvAPIMutex);
|
|
return;
|
}
|
|
|
|
/*!****************************************************************************
|
@name AtoI
|
@brief Returns the integer value of a decimal string
|
@param szIn - String with hexadecimal value
|
@return IMG_UINT32 integer value, 0 if string is null or not valid
|
Based on Max`s one, now copes with (only) hex ui32ords, upper or lower case a-f.
|
*****************************************************************************/
|
IMG_UINT32 AtoI(IMG_CHAR *szIn)
|
{
|
IMG_INT iLen = 0;
|
IMG_UINT32 ui32Value = 0;
|
IMG_UINT32 ui32Digit=1;
|
IMG_UINT32 ui32Base=10;
|
IMG_INT iPos;
|
IMG_CHAR bc;
|
|
//get len of string
|
while (szIn[iLen] > 0)
|
{
|
iLen ++;
|
}
|
|
//nothing to do
|
if (iLen == 0)
|
{
|
return (0);
|
}
|
|
/* See if we have an 'x' or 'X' before the number to make it a hex number */
|
iPos=0;
|
while (szIn[iPos] == '0')
|
{
|
iPos++;
|
}
|
if (szIn[iPos] == '\0')
|
{
|
return 0;
|
}
|
if (szIn[iPos] == 'x' || szIn[iPos] == 'X')
|
{
|
ui32Base=16;
|
szIn[iPos]='0';
|
}
|
|
//go through string from right (least significant) to left
|
for (iPos = iLen - 1; iPos >= 0; iPos --)
|
{
|
bc = szIn[iPos];
|
|
if ( (bc >= 'a') && (bc <= 'f') && ui32Base == 16) //handle lower case a-f
|
{
|
bc -= 'a' - 0xa;
|
}
|
else
|
if ( (bc >= 'A') && (bc <= 'F') && ui32Base == 16) //handle upper case A-F
|
{
|
bc -= 'A' - 0xa;
|
}
|
else
|
if ((bc >= '0') && (bc <= '9')) //if char out of range, return 0
|
{
|
bc -= '0';
|
}
|
else
|
return (0);
|
|
ui32Value += (IMG_UINT32)bc * ui32Digit;
|
|
ui32Digit = ui32Digit * ui32Base;
|
}
|
return (ui32Value);
|
}
|
|
|
/*!****************************************************************************
|
@name StreamValid
|
@brief Validates supplied debug buffer.
|
@param psStream - debug stream
|
@return true if valid
|
*****************************************************************************/
|
static IMG_BOOL StreamValid(PDBG_STREAM psStream)
|
{
|
PDBG_STREAM psThis;
|
|
psThis = g_psStreamList;
|
|
while (psThis)
|
{
|
if (psStream && ((psThis == psStream) ||
|
(psThis->psInitStream == psStream) ||
|
(psThis->psDeinitStream == psStream)) )
|
{
|
return(IMG_TRUE);
|
}
|
else
|
{
|
psThis = psThis->psNext;
|
}
|
}
|
|
return(IMG_FALSE);
|
}
|
|
|
/*!****************************************************************************
|
@name StreamValidForRead
|
@brief Validates supplied debug buffer for read op.
|
@param psStream - debug stream
|
@return true if readable
|
*****************************************************************************/
|
static IMG_BOOL StreamValidForRead(PDBG_STREAM psStream)
|
{
|
if( StreamValid(psStream) &&
|
((psStream->ui32Flags & DEBUG_FLAGS_WRITEONLY) == 0) )
|
{
|
return(IMG_TRUE);
|
}
|
|
return(IMG_FALSE);
|
}
|
|
/*!****************************************************************************
|
@name StreamValidForWrite
|
@brief Validates supplied debug buffer for write op.
|
@param psStream - debug stream
|
@return true if writable
|
*****************************************************************************/
|
static IMG_BOOL StreamValidForWrite(PDBG_STREAM psStream)
|
{
|
if( StreamValid(psStream) &&
|
((psStream->ui32Flags & DEBUG_FLAGS_READONLY) == 0) )
|
{
|
return(IMG_TRUE);
|
}
|
|
return(IMG_FALSE);
|
}
|
|
/*!****************************************************************************
|
@name Write
|
@brief Copies data from a buffer into selected stream. Stream size is fixed.
|
@param psStream - stream for output
|
@param pui8Data - input buffer
|
@param ui32InBuffSize - size of input
|
@return none
|
*****************************************************************************/
|
static void Write(PDBG_STREAM psStream,IMG_PUINT8 pui8Data,IMG_UINT32 ui32InBuffSize)
|
{
|
/*
|
Split copy into two bits as necessary (if we're allowed to wrap).
|
*/
|
if ((psStream->ui32Flags & DEBUG_FLAGS_CIRCULAR) == 0)
|
{
|
PVR_ASSERT( (psStream->ui32WPtr + ui32InBuffSize) < psStream->ui32Size );
|
}
|
|
if ((psStream->ui32WPtr + ui32InBuffSize) > psStream->ui32Size)
|
{
|
/* Yes we need two bits, calculate their sizes */
|
IMG_UINT32 ui32B1 = psStream->ui32Size - psStream->ui32WPtr;
|
IMG_UINT32 ui32B2 = ui32InBuffSize - ui32B1;
|
|
/* Copy first block to current location */
|
HostMemCopy((void *)((uintptr_t)psStream->pvBase + psStream->ui32WPtr),
|
(void *) pui8Data,
|
ui32B1);
|
|
/* Copy second block to start of buffer */
|
HostMemCopy(psStream->pvBase,
|
(void *)(pui8Data + ui32B1),
|
ui32B2);
|
|
/* Set pointer to be the new end point */
|
psStream->ui32WPtr = ui32B2;
|
}
|
else
|
{ /* Can fit block in single chunk */
|
HostMemCopy((void *)((uintptr_t)psStream->pvBase + psStream->ui32WPtr),
|
(void *) pui8Data,
|
ui32InBuffSize);
|
|
psStream->ui32WPtr += ui32InBuffSize;
|
|
if (psStream->ui32WPtr == psStream->ui32Size)
|
{
|
psStream->ui32WPtr = 0;
|
}
|
}
|
}
|
|
|
/*!****************************************************************************
|
@name WriteExpandingBuffer
|
@brief Copies data from a buffer into selected stream. Stream size may be expandable.
|
@param psStream - stream for output
|
@param pui8InBuf - input buffer
|
@param ui32InBuffSize - size of input
|
@return bytes copied
|
*****************************************************************************/
|
static IMG_UINT32 WriteExpandingBuffer(PDBG_STREAM psStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize)
|
{
|
IMG_UINT ui32Space;
|
|
/*
|
How much space have we got in the buffer ?
|
*/
|
ui32Space = SpaceInStream(psStream);
|
|
/*
|
Check if we can expand the buffer
|
*/
|
if (psStream->ui32Flags & DEBUG_FLAGS_NO_BUF_EXPANDSION)
|
{
|
/*
|
Don't do anything if we've got less that 32 ui8tes of space and
|
we're not allowing expansion of buffer space...
|
*/
|
if (ui32Space < 32)
|
{
|
PVR_DPF((PVR_DBG_ERROR, "WriteExpandingBuffer: buffer %p is full and isn't expandable", psStream));
|
return(0);
|
}
|
}
|
else
|
{
|
if ((ui32Space < 32) || (ui32Space <= (ui32InBuffSize + 4)))
|
{
|
IMG_UINT32 ui32NewBufSize;
|
|
/*
|
Find new buffer size, double the current size or increase by 1MB
|
*/
|
ui32NewBufSize = MIN(psStream->ui32Size<<1,psStream->ui32Size+(1<<20));
|
ui32NewBufSize = MIN(ui32NewBufSize, PDUMP_STREAMBUF_MAX_SIZE_MB<<20);
|
PVR_DPF((PVR_DBGDRIV_MESSAGE, "Expanding buffer size = %x, new size = %x",
|
psStream->ui32Size, ui32NewBufSize));
|
|
if (ui32InBuffSize > psStream->ui32Size)
|
{
|
ui32NewBufSize += ui32InBuffSize;
|
PVR_DPF((PVR_DBG_ERROR, "WriteExpandingBuffer: buffer %p is expanding by size of input buffer %u", psStream, ui32NewBufSize));
|
}
|
|
/*
|
Attempt to expand the buffer
|
*/
|
if ((ui32NewBufSize < psStream->ui32Size) ||
|
!ExpandStreamBuffer(psStream,ui32NewBufSize))
|
{
|
if (ui32Space < 32)
|
{
|
if((psStream->ui32Flags & DEBUG_FLAGS_CIRCULAR) != 0)
|
{
|
return(0);
|
}
|
else
|
{
|
/* out of memory */
|
PVR_DPF((PVR_DBG_ERROR, "WriteExpandingBuffer: Unable to expand %p. Out of memory.", psStream));
|
InvalidateAllStreams();
|
return (0xFFFFFFFFUL);
|
}
|
}
|
}
|
|
/*
|
Recalc the space in the buffer
|
*/
|
ui32Space = SpaceInStream(psStream);
|
PVR_DPF((PVR_DBGDRIV_MESSAGE, "Expanded buffer, free space = %x",
|
ui32Space));
|
}
|
}
|
|
/*
|
Only copy what we can..
|
*/
|
if (ui32Space <= (ui32InBuffSize + 4))
|
{
|
ui32InBuffSize = ui32Space - 4;
|
}
|
|
/*
|
Write the stuff...
|
*/
|
Write(psStream,pui8InBuf,ui32InBuffSize);
|
|
#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
|
if (ui32InBuffSize)
|
{
|
HostSignalEvent(DBG_EVENT_STREAM_DATA);
|
}
|
#endif
|
return(ui32InBuffSize);
|
}
|
|
/*****************************************************************************
|
******************************************************************************
|
******************************************************************************
|
THE ACTUAL FUNCTIONS
|
******************************************************************************
|
******************************************************************************
|
*****************************************************************************/
|
|
static void DBGDrivSetStreamName(PDBG_STREAM psStream,
|
IMG_CHAR* pszBase,
|
IMG_CHAR* pszExt)
|
{
|
IMG_CHAR* pCh = psStream->szName;
|
IMG_CHAR* pChEnd = psStream->szName+DEBUG_STREAM_NAME_MAX-8;
|
IMG_CHAR* pSrcCh;
|
IMG_CHAR* pSrcChEnd;
|
|
for (pSrcCh = pszBase, pSrcChEnd = pszBase+strlen(pszBase);
|
(pSrcCh < pSrcChEnd) && (pCh < pChEnd) ;
|
pSrcCh++, pCh++)
|
{
|
*pCh = *pSrcCh;
|
}
|
|
for (pSrcCh = pszExt, pSrcChEnd = pszExt+strlen(pszExt);
|
(pSrcCh < pSrcChEnd) && (pCh < pChEnd) ;
|
pSrcCh++, pCh++)
|
{
|
*pCh = *pSrcCh;
|
}
|
|
*pCh = '\0';
|
}
|
|
/*!****************************************************************************
|
@name DBGDrivCreateStream
|
@brief Creates a pdump/debug stream
|
@param pszName - stream name
|
@param ui32Flags - output flags, text stream bit is set for pdumping
|
@param ui32Size - size of stream buffer in pages
|
@return none
|
*****************************************************************************/
|
IMG_BOOL IMG_CALLCONV DBGDrivCreateStream(IMG_CHAR *pszName,
|
IMG_UINT32 ui32Flags,
|
IMG_UINT32 ui32Size,
|
IMG_HANDLE* phInit,
|
IMG_HANDLE* phMain,
|
IMG_HANDLE* phDeinit)
|
{
|
IMG_BOOL bUseNonPagedMem4Buffers = ((ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0);
|
PDBG_STREAM psStream = NULL;
|
PDBG_STREAM psInitStream = NULL;
|
PDBG_STREAM psStreamDeinit = NULL;
|
void* pvBase = NULL;
|
|
/*
|
If we already have a buffer using this name just return
|
its handle.
|
*/
|
psStream = (PDBG_STREAM) DBGDrivFindStream(pszName, IMG_FALSE);
|
if (psStream)
|
{
|
*phInit = psStream->psInitStream;
|
*phMain = psStream;
|
*phDeinit = psStream->psDeinitStream;
|
return IMG_TRUE;
|
}
|
|
/*
|
Allocate memory for control structures
|
*/
|
psStream = HostNonPageablePageAlloc(1);
|
if (!psStream)
|
{
|
PVR_DPF((PVR_DBG_ERROR,"DBGDriv: Couldn't alloc control structs\n\r"));
|
goto errCleanup;
|
}
|
psInitStream = psStream+1;
|
psStreamDeinit = psStream+2;
|
|
|
/* Allocate memory for Main buffer */
|
psStream->pvBase = NULL;
|
if (bUseNonPagedMem4Buffers)
|
{
|
pvBase = HostNonPageablePageAlloc(ui32Size);
|
}
|
else
|
{
|
pvBase = HostPageablePageAlloc(ui32Size);
|
}
|
|
if (!pvBase)
|
{
|
PVR_DPF((PVR_DBG_ERROR,"DBGDriv: Couldn't alloc Stream buffer\n\r"));
|
goto errCleanup;
|
}
|
|
/*
|
Setup debug buffer state.
|
*/
|
psStream->psNext = 0;
|
psStream->pvBase = pvBase;
|
psStream->ui32Flags = ui32Flags | DEBUG_FLAGS_CIRCULAR;
|
psStream->ui32Size = ui32Size * HOST_PAGESIZE;
|
psStream->ui32RPtr = 0;
|
psStream->ui32WPtr = 0;
|
psStream->ui32Marker = 0;
|
psStream->ui32InitPhaseWOff = 0;
|
DBGDrivSetStreamName(psStream, pszName, "");
|
PVR_DPF((PVR_DBG_MESSAGE,"DBGDriv: Created stream with deinit name (%s)\n\r", psStream->szName));
|
|
/* Allocate memory for Init buffer */
|
psInitStream->pvBase = NULL;
|
if (bUseNonPagedMem4Buffers)
|
{
|
pvBase = HostNonPageablePageAlloc(ui32Size);
|
}
|
else
|
{
|
pvBase = HostPageablePageAlloc(ui32Size);
|
}
|
|
if (!pvBase)
|
{
|
PVR_DPF((PVR_DBG_ERROR,"DBGDriv: Couldn't alloc InitStream buffer\n\r"));
|
goto errCleanup;
|
}
|
|
/* Initialise the stream for the Init phase */
|
psInitStream->psNext = psInitStream->psInitStream = psInitStream->psDeinitStream = NULL;
|
psInitStream->ui32Flags = ui32Flags;
|
psInitStream->pvBase = pvBase;
|
psInitStream->ui32Size = ui32Size * HOST_PAGESIZE;
|
psInitStream->ui32RPtr = 0;
|
psInitStream->ui32WPtr = 0;
|
psInitStream->ui32Marker = 0;
|
psInitStream->ui32InitPhaseWOff = 0;
|
DBGDrivSetStreamName(psInitStream, pszName, "_Init");
|
PVR_DPF((PVR_DBG_MESSAGE,"DBGDriv: Created stream with init name (%s)\n\r", psInitStream->szName));
|
psStream->psInitStream = psInitStream;
|
|
/* Allocate memory for Deinit buffer */
|
psStreamDeinit->pvBase = NULL;
|
if (bUseNonPagedMem4Buffers)
|
{
|
pvBase = HostNonPageablePageAlloc(1);
|
}
|
else
|
{
|
pvBase = HostPageablePageAlloc(1);
|
}
|
|
if (!pvBase)
|
{
|
PVR_DPF((PVR_DBG_ERROR,"DBGDriv: Couldn't alloc DeinitStream buffer\n\r"));
|
goto errCleanup;
|
}
|
|
/* Initialise the stream for the Deinit phase */
|
psStreamDeinit->psNext = psStreamDeinit->psInitStream = psStreamDeinit->psDeinitStream = NULL;
|
psStreamDeinit->pvBase = pvBase;
|
psStreamDeinit->ui32Flags = ui32Flags;
|
psStreamDeinit->ui32Size = HOST_PAGESIZE;
|
psStreamDeinit->ui32RPtr = 0;
|
psStreamDeinit->ui32WPtr = 0;
|
psStreamDeinit->ui32Marker = 0;
|
psStreamDeinit->ui32InitPhaseWOff = 0;
|
DBGDrivSetStreamName(psStreamDeinit, pszName, "_Deinit");
|
PVR_DPF((PVR_DBG_MESSAGE,"DBGDriv: Created stream with deinit name (%s)\n\r", psStreamDeinit->szName));
|
|
psStream->psDeinitStream = psStreamDeinit;
|
|
/*
|
Insert into list.
|
*/
|
psStream->psNext = g_psStreamList;
|
g_psStreamList = psStream;
|
|
AddSIDEntry(psStream);
|
|
*phInit = psStream->psInitStream;
|
*phMain = psStream;
|
*phDeinit = psStream->psDeinitStream;
|
|
return IMG_TRUE;
|
|
errCleanup:
|
if (bUseNonPagedMem4Buffers)
|
{
|
if (psStream) HostNonPageablePageFree(psStream->pvBase);
|
if (psInitStream) HostNonPageablePageFree(psInitStream->pvBase);
|
if (psStreamDeinit) HostNonPageablePageFree(psStreamDeinit->pvBase);
|
}
|
else
|
{
|
if (psStream) HostPageablePageFree(psStream->pvBase);
|
if (psInitStream) HostPageablePageFree(psInitStream->pvBase);
|
if (psStreamDeinit) HostPageablePageFree(psStreamDeinit->pvBase);
|
}
|
HostNonPageablePageFree(psStream);
|
psStream = psInitStream = psStreamDeinit = NULL;
|
return IMG_FALSE;
|
}
|
|
/*!****************************************************************************
|
@name DBGDrivDestroyStream
|
@brief Delete a stream and free its memory
|
@param psStream - stream to be removed
|
@return none
|
*****************************************************************************/
|
void IMG_CALLCONV DBGDrivDestroyStream(IMG_HANDLE hInit,IMG_HANDLE hMain, IMG_HANDLE hDeinit)
|
{
|
PDBG_STREAM psStreamInit = (PDBG_STREAM) hInit;
|
PDBG_STREAM psStream = (PDBG_STREAM) hMain;
|
PDBG_STREAM psStreamDeinit = (PDBG_STREAM) hDeinit;
|
PDBG_STREAM psStreamThis;
|
PDBG_STREAM psStreamPrev;
|
|
PVR_DPF((PVR_DBG_MESSAGE, "DBGDriv: Destroying stream %s\r\n", psStream->szName ));
|
|
/*
|
Validate buffer.
|
*/
|
if (!StreamValid(psStream))
|
{
|
return;
|
}
|
|
RemoveSIDEntry(psStream);
|
|
/*
|
Remove from linked list.
|
*/
|
psStreamThis = g_psStreamList;
|
psStreamPrev = 0;
|
|
while (psStreamThis)
|
{
|
if (psStreamThis == psStream)
|
{
|
if (psStreamPrev)
|
{
|
psStreamPrev->psNext = psStreamThis->psNext;
|
}
|
else
|
{
|
g_psStreamList = psStreamThis->psNext;
|
}
|
|
psStreamThis = 0;
|
}
|
else
|
{
|
psStreamPrev = psStreamThis;
|
psStreamThis = psStreamThis->psNext;
|
}
|
}
|
|
/*
|
And free its memory.
|
*/
|
if ((psStream->ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
|
{
|
HostNonPageablePageFree(psStream->pvBase);
|
HostNonPageablePageFree(psStreamInit->pvBase);
|
HostNonPageablePageFree(psStreamDeinit->pvBase);
|
}
|
else
|
{
|
HostPageablePageFree(psStream->pvBase);
|
HostPageablePageFree(psStreamInit->pvBase);
|
HostPageablePageFree(psStreamDeinit->pvBase);
|
}
|
|
/* Free the shared page used for the three stream tuple */
|
HostNonPageablePageFree(psStream);
|
psStream = psStreamInit = psStreamDeinit = NULL;
|
|
if (g_psStreamList == 0)
|
{
|
PVR_DPF((PVR_DBG_MESSAGE,"DBGDriv: Stream list now empty" ));
|
}
|
|
return;
|
}
|
|
/*!****************************************************************************
|
@name DBGDrivFindStream
|
@brief Finds/resets a named stream
|
@param pszName - stream name
|
@param bResetStream - whether to reset the stream, e.g. to end pdump init phase
|
@return none
|
*****************************************************************************/
|
void * IMG_CALLCONV DBGDrivFindStream(IMG_CHAR * pszName, IMG_BOOL bResetStream)
|
{
|
PDBG_STREAM psStream;
|
PDBG_STREAM psThis;
|
IMG_UINT32 ui32Off;
|
IMG_BOOL bAreSame;
|
|
psStream = 0;
|
|
PVR_DPF((PVR_DBGDRIV_MESSAGE, "PDump client connecting to %s %s",
|
pszName,
|
(bResetStream == IMG_TRUE) ? "with reset" : "no reset"));
|
|
/*
|
Scan buffer names for supplied one.
|
*/
|
for (psThis = g_psStreamList; psThis != NULL; psThis = psThis->psNext)
|
{
|
bAreSame = IMG_TRUE;
|
ui32Off = 0;
|
|
if (strlen(psThis->szName) == strlen(pszName))
|
{
|
while ((ui32Off < DEBUG_STREAM_NAME_MAX) && (psThis->szName[ui32Off] != 0) && (pszName[ui32Off] != 0) && bAreSame)
|
{
|
if (psThis->szName[ui32Off] != pszName[ui32Off])
|
{
|
bAreSame = IMG_FALSE;
|
}
|
|
ui32Off++;
|
}
|
}
|
else
|
{
|
bAreSame = IMG_FALSE;
|
}
|
|
if (bAreSame)
|
{
|
psStream = psThis;
|
break;
|
}
|
}
|
|
if(psStream)
|
{
|
psStream->psInitStream->ui32RPtr = 0;
|
psStream->psDeinitStream->ui32RPtr = 0;
|
psStream->ui32RPtr = 0;
|
if (bResetStream)
|
{
|
/* This will erase any data written to the main stream
|
* before the client starts. */
|
psStream->ui32WPtr = 0;
|
}
|
psStream->ui32Marker = psStream->psInitStream->ui32Marker = 0;
|
|
|
/* mark init stream to prevent further reading by pdump client */
|
/* Check for possible race condition */
|
psStream->psInitStream->ui32InitPhaseWOff = psStream->psInitStream->ui32WPtr;
|
|
PVR_DPF((PVR_DBGDRIV_MESSAGE, "Set %s client marker bo %x",
|
psStream->szName,
|
psStream->psInitStream->ui32InitPhaseWOff));
|
}
|
|
return((void *) psStream);
|
}
|
|
static void IMG_CALLCONV DBGDrivInvalidateStream(PDBG_STREAM psStream)
|
{
|
IMG_CHAR pszErrorMsg[] = "**OUTOFMEM\n";
|
IMG_UINT32 ui32Space;
|
IMG_UINT32 ui32Off = 0;
|
IMG_UINT32 ui32WPtr = psStream->ui32WPtr;
|
IMG_PUINT8 pui8Buffer = (IMG_UINT8 *) psStream->pvBase;
|
|
PVR_DPF((PVR_DBG_ERROR, "DBGDrivInvalidateStream: An error occurred for stream %s", psStream->szName ));
|
|
/*
|
Validate buffer.
|
*/
|
/*
|
if (!StreamValid(psStream))
|
{
|
return;
|
}
|
*/
|
/* Write what we can of the error message */
|
ui32Space = SpaceInStream(psStream);
|
|
/* Make sure there's space for termination character */
|
if(ui32Space > 0)
|
{
|
ui32Space--;
|
}
|
else
|
{
|
PVR_DPF((PVR_DBG_ERROR, "DBGDrivInvalidateStream: Buffer full."));
|
}
|
|
while((pszErrorMsg[ui32Off] != 0) && (ui32Off < ui32Space))
|
{
|
pui8Buffer[ui32WPtr] = (IMG_UINT8)pszErrorMsg[ui32Off];
|
ui32Off++;
|
ui32WPtr++;
|
}
|
pui8Buffer[ui32WPtr++] = '\0';
|
psStream->ui32WPtr = ui32WPtr;
|
|
/* Buffer will accept no more params from Services/client driver */
|
psStream->ui32Flags |= DEBUG_FLAGS_READONLY;
|
}
|
|
/*!****************************************************************************
|
@name InvalidateAllStreams
|
@brief invalidate all streams in list
|
@return none
|
*****************************************************************************/
|
static void InvalidateAllStreams(void)
|
{
|
PDBG_STREAM psStream = g_psStreamList;
|
while (psStream != NULL)
|
{
|
DBGDrivInvalidateStream(psStream);
|
DBGDrivInvalidateStream(psStream->psInitStream);
|
DBGDrivInvalidateStream(psStream->psDeinitStream);
|
psStream = psStream->psNext;
|
}
|
return;
|
}
|
|
/*!****************************************************************************
|
@name DBGDrivWrite2
|
@brief Copies data from a buffer into selected (expandable) stream.
|
@param psStream - stream for output
|
@param pui8InBuf - input buffer
|
@param ui32InBuffSize - size of input
|
@return bytes copied, 0 if recoverable error, -1 if unrecoverable error
|
*****************************************************************************/
|
IMG_UINT32 IMG_CALLCONV DBGDrivWrite2(PDBG_STREAM psStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize)
|
{
|
|
/*
|
Validate buffer.
|
*/
|
if (!StreamValidForWrite(psStream))
|
{
|
PVR_DPF((PVR_DBG_ERROR, "DBGDrivWrite2: stream not valid"));
|
return(0xFFFFFFFFUL);
|
}
|
|
PVR_DPF((PVR_DBGDRIV_MESSAGE, "Recv(exp) %d b for %s: Roff = %x, WOff = %x",
|
ui32InBuffSize,
|
psStream->szName,
|
psStream->ui32RPtr,
|
psStream->ui32WPtr));
|
|
return( WriteExpandingBuffer(psStream, pui8InBuf, ui32InBuffSize) );
|
}
|
|
/*!****************************************************************************
|
@name DBGDrivRead
|
@brief Read from debug driver buffers
|
@param psMainStream - stream
|
@param ui32BufID - on of the DEBUG_READ_BUFID flags to indicate which buffer
|
@param ui32OutBuffSize - available space in client buffer
|
@param pui8OutBuf - output buffer
|
@return bytes read, 0 if failure occurred
|
*****************************************************************************/
|
IMG_UINT32 IMG_CALLCONV DBGDrivRead(PDBG_STREAM psMainStream, IMG_UINT32 ui32BufID, IMG_UINT32 ui32OutBuffSize,IMG_UINT8 * pui8OutBuf)
|
{
|
IMG_UINT32 ui32Data;
|
DBG_STREAM *psStream;
|
|
/*
|
Validate buffer.
|
*/
|
if (!StreamValidForRead(psMainStream))
|
{
|
PVR_DPF((PVR_DBG_ERROR, "DBGDrivRead: buffer %p is invalid", psMainStream));
|
return(0);
|
}
|
|
if(ui32BufID == DEBUG_READ_BUFID_INIT)
|
{
|
psStream = psMainStream->psInitStream;
|
}
|
else if (ui32BufID == DEBUG_READ_BUFID_DEINIT)
|
{
|
psStream = psMainStream->psDeinitStream;
|
}
|
else
|
{
|
psStream = psMainStream;
|
}
|
|
/* Don't read beyond the init phase marker point */
|
if (psStream->ui32RPtr == psStream->ui32WPtr ||
|
((psStream->ui32InitPhaseWOff > 0) &&
|
(psStream->ui32RPtr >= psStream->ui32InitPhaseWOff)) )
|
{
|
return(0);
|
}
|
|
/*
|
Get amount of data in buffer.
|
*/
|
if (psStream->ui32RPtr <= psStream->ui32WPtr)
|
{
|
ui32Data = psStream->ui32WPtr - psStream->ui32RPtr;
|
}
|
else
|
{
|
ui32Data = psStream->ui32WPtr + (psStream->ui32Size - psStream->ui32RPtr);
|
}
|
|
/*
|
Don't read beyond the init phase marker point
|
*/
|
if ((psStream->ui32InitPhaseWOff > 0) &&
|
(psStream->ui32InitPhaseWOff < psStream->ui32WPtr))
|
{
|
ui32Data = psStream->ui32InitPhaseWOff - psStream->ui32RPtr;
|
}
|
|
/*
|
Only transfer what target buffer can handle.
|
*/
|
if (ui32Data > ui32OutBuffSize)
|
{
|
ui32Data = ui32OutBuffSize;
|
}
|
|
PVR_DPF((PVR_DBGDRIV_MESSAGE, "Send %x b from %s: Roff = %x, WOff = %x",
|
ui32Data,
|
psStream->szName,
|
psStream->ui32RPtr,
|
psStream->ui32WPtr));
|
|
/*
|
Split copy into two bits or one depending on W/R position.
|
*/
|
if ((psStream->ui32RPtr + ui32Data) > psStream->ui32Size)
|
{ /* Calc block 1 and block 2 sizes */
|
IMG_UINT32 ui32B1 = psStream->ui32Size - psStream->ui32RPtr;
|
IMG_UINT32 ui32B2 = ui32Data - ui32B1;
|
|
/* Copy up to end of circular buffer */
|
HostMemCopy((void *) pui8OutBuf,
|
(void *)((uintptr_t)psStream->pvBase + psStream->ui32RPtr),
|
ui32B1);
|
|
/* Copy from start of circular buffer */
|
HostMemCopy((void *)(pui8OutBuf + ui32B1),
|
psStream->pvBase,
|
ui32B2);
|
|
/* Update read pointer now that we've copied the data out */
|
psStream->ui32RPtr = ui32B2;
|
}
|
else
|
{ /* Copy data from wherever */
|
HostMemCopy((void *) pui8OutBuf,
|
(void *)((uintptr_t)psStream->pvBase + psStream->ui32RPtr),
|
ui32Data);
|
|
/* Update read pointer now that we've copied the data out */
|
psStream->ui32RPtr += ui32Data;
|
|
/* Check for wrapping */
|
if ((psStream->ui32RPtr != psStream->ui32WPtr) &&
|
(psStream->ui32RPtr >= psStream->ui32Size))
|
{
|
psStream->ui32RPtr = 0;
|
}
|
}
|
|
return(ui32Data);
|
}
|
|
/*!****************************************************************************
|
@name DBGDrivSetMarker
|
@brief Sets the marker in the stream to split output files
|
@param psStream, ui32Marker
|
@return nothing
|
*****************************************************************************/
|
void IMG_CALLCONV DBGDrivSetMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker)
|
{
|
/*
|
Validate buffer
|
*/
|
if (!StreamValid(psStream))
|
{
|
return;
|
}
|
|
/* Called by PDump client to reset the marker to zero after a file split */
|
if ((ui32Marker == 0) && (psStream->ui32Marker == 0))
|
{
|
PVR_DPF((PVR_DBG_ERROR, "DBGDrivSetMarker: Client resetting marker that is already zero!"));
|
}
|
/* Called by pvrsrvkm to set the marker to signal a file split is required */
|
if ((ui32Marker != 0) && (psStream->ui32Marker != 0))
|
{
|
/* In this case a previous split request is still outstanding. The
|
* client has not yet actioned and acknowledged the previous
|
* marker. This may be an error if the client does not catch-up and
|
* the stream's written data is allowed to pass the max file
|
* size again. If this happens the PDump is invalid as the offsets
|
* from the script file will be incorrect.
|
*/
|
PVR_DPF((PVR_DBG_ERROR, "DBGDrivSetMarker: Server setting marker that is already set!"));
|
}
|
else
|
{
|
PVR_DPF((PVR_DBG_MESSAGE, "DBGDrivSetMarker: Setting stream split marker to %d (was %d)", ui32Marker, psStream->ui32Marker));
|
}
|
|
psStream->ui32Marker = ui32Marker;
|
}
|
|
/*!****************************************************************************
|
@name DBGDrivGetMarker
|
@brief Gets the marker in the stream to split output files
|
@param psStream - stream
|
@return marker offset
|
*****************************************************************************/
|
IMG_UINT32 IMG_CALLCONV DBGDrivGetMarker(PDBG_STREAM psStream)
|
{
|
/*
|
Validate buffer
|
*/
|
if (!StreamValid(psStream))
|
{
|
return 0;
|
}
|
|
return psStream->ui32Marker;
|
}
|
|
/*!****************************************************************************
|
@name DBGDrivGetServiceTable
|
@brief get jump table for Services driver
|
@return pointer to jump table
|
*****************************************************************************/
|
void * IMG_CALLCONV DBGDrivGetServiceTable(void)
|
{
|
return &g_sDBGKMServices;
|
}
|
|
|
#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
|
/*!****************************************************************************
|
@name DBGDrivWaitForEvent
|
@brief waits for an event
|
@param eEvent - debug driver event
|
@return void
|
*****************************************************************************/
|
void IMG_CALLCONV DBGDrivWaitForEvent(DBG_EVENT eEvent)
|
{
|
HostWaitForEvent(eEvent);
|
}
|
#endif
|
|
/*!****************************************************************************
|
@name DBGDrivGetCtrlState
|
@brief Gets a state value from the debug driver or stream
|
@param psStream - stream
|
@param ui32StateID - state ID
|
@return Nothing
|
*****************************************************************************/
|
IMG_UINT32 IMG_CALLCONV DBGDrivGetCtrlState(PDBG_STREAM psStream, IMG_UINT32 ui32StateID)
|
{
|
/* Validate buffer */
|
if (!StreamValid(psStream))
|
{
|
return (0xFFFFFFFF);
|
}
|
|
/* Retrieve the state asked for */
|
switch (ui32StateID)
|
{
|
case DBG_GET_STATE_FLAG_IS_READONLY:
|
return ((psStream->ui32Flags & DEBUG_FLAGS_READONLY) != 0);
|
|
case 0xFE: /* Dump the current stream state */
|
PVR_DPF((PVR_DBG_CALLTRACE,
|
"------ PDUMP DBGDriv: psStream( %p ) ( -- %s -- ) ui32Flags( %x )",
|
psStream, psStream->szName, psStream->ui32Flags));
|
PVR_DPF((PVR_DBG_CALLTRACE,
|
"------ PDUMP DBGDriv: psStream->pvBase( %p ) psStream->ui32Size( %u )",
|
psStream->pvBase, psStream->ui32Size));
|
PVR_DPF((PVR_DBG_CALLTRACE,
|
"------ PDUMP DBGDriv: psStream->ui32RPtr( %u ) psStream->ui32WPtr( %u )",
|
psStream->ui32RPtr, psStream->ui32WPtr));
|
PVR_DPF((PVR_DBG_CALLTRACE,
|
"------ PDUMP DBGDriv: psStream->ui32Marker( %u ) psStream->ui32InitPhaseWOff( %u )",
|
psStream->ui32Marker, psStream->ui32InitPhaseWOff));
|
if (psStream->psInitStream)
|
{
|
PVR_DPF((PVR_DBG_CALLTRACE,
|
"-------- PDUMP DBGDriv: psInitStream( %p ) ( -- %s -- ) ui32Flags( %x )",
|
psStream->psInitStream, psStream->psInitStream->szName, psStream->ui32Flags));
|
PVR_DPF((PVR_DBG_CALLTRACE,
|
"-------- PDUMP DBGDriv: psInitStream->pvBase( %p ) psInitStream->ui32Size( %u )",
|
psStream->psInitStream->pvBase, psStream->psInitStream->ui32Size));
|
PVR_DPF((PVR_DBG_CALLTRACE,
|
"-------- PDUMP DBGDriv: psInitStream->ui32RPtr( %u ) psInitStream->ui32WPtr( %u )",
|
psStream->psInitStream->ui32RPtr, psStream->psInitStream->ui32WPtr));
|
PVR_DPF((PVR_DBG_CALLTRACE,
|
"-------- PDUMP DBGDriv: psInitStream->ui32Marker( %u ) psInitStream->ui32InitPhaseWOff( %u ) ",
|
psStream->psInitStream->ui32Marker, psStream->psInitStream->ui32InitPhaseWOff));
|
}
|
|
break;
|
|
case 0xFF: /* Dump driver state not in a stream */
|
{
|
PVR_DPF((PVR_DBG_CALLTRACE,
|
"------ PDUMP DBGDriv: g_psStreamList( head %p ) g_pvAPIMutex( %p ) g_PDumpCurrentFrameNo( %u )",
|
g_psStreamList, g_pvAPIMutex, g_PDumpCurrentFrameNo));
|
}
|
break;
|
|
default:
|
PVR_ASSERT(0);
|
}
|
|
return (0xFFFFFFFF);
|
}
|
|
IMG_UINT32 IMG_CALLCONV DBGDrivGetFrame(void)
|
{
|
return g_PDumpCurrentFrameNo;
|
}
|
|
void IMG_CALLCONV DBGDrivSetFrame(IMG_UINT32 ui32Frame)
|
{
|
g_PDumpCurrentFrameNo = ui32Frame;
|
}
|
|
|
/*!****************************************************************************
|
@name ExpandStreamBuffer
|
@brief allocates a new buffer when the current one is full
|
@param psStream - stream
|
@param ui32NewSize - new size
|
@return IMG_TRUE - if allocation succeeded, IMG_FALSE - if not
|
*****************************************************************************/
|
static IMG_BOOL ExpandStreamBuffer(PDBG_STREAM psStream, IMG_UINT32 ui32NewSize)
|
{
|
void * pvNewBuf;
|
IMG_UINT32 ui32NewSizeInPages;
|
IMG_UINT32 ui32NewWOffset;
|
IMG_UINT32 ui32NewROffset;
|
IMG_UINT32 ui32SpaceInOldBuf;
|
|
/*
|
First check new size is bigger than existing size
|
*/
|
if (psStream->ui32Size >= ui32NewSize)
|
{
|
return IMG_FALSE;
|
}
|
|
/*
|
Calc space in old buffer
|
*/
|
ui32SpaceInOldBuf = SpaceInStream(psStream);
|
|
/*
|
Allocate new buffer
|
*/
|
ui32NewSizeInPages = ((ui32NewSize + 0xfffUL) & ~0xfffUL) / 4096UL;
|
|
if ((psStream->ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
|
{
|
pvNewBuf = HostNonPageablePageAlloc(ui32NewSizeInPages);
|
}
|
else
|
{
|
pvNewBuf = HostPageablePageAlloc(ui32NewSizeInPages);
|
}
|
|
if (pvNewBuf == NULL)
|
{
|
return IMG_FALSE;
|
}
|
|
if ((psStream->ui32Flags & DEBUG_FLAGS_CIRCULAR) != 0)
|
{
|
/*
|
Copy over old buffer to new one, we place data at start of buffer
|
even if Read offset is not at start of buffer
|
*/
|
if (psStream->ui32RPtr <= psStream->ui32WPtr)
|
{
|
/*
|
No wrapping of data so copy data to start of new buffer
|
*/
|
HostMemCopy(pvNewBuf,
|
(void *)((uintptr_t)psStream->pvBase + psStream->ui32RPtr),
|
psStream->ui32WPtr - psStream->ui32RPtr);
|
}
|
else
|
{
|
IMG_UINT32 ui32FirstCopySize;
|
|
/*
|
The data has wrapped around the buffer, copy beginning of buffer first
|
*/
|
ui32FirstCopySize = psStream->ui32Size - psStream->ui32RPtr;
|
|
HostMemCopy(pvNewBuf,
|
(void *)((uintptr_t)psStream->pvBase + psStream->ui32RPtr),
|
ui32FirstCopySize);
|
|
/*
|
Now second half
|
*/
|
HostMemCopy((void *)((uintptr_t)pvNewBuf + ui32FirstCopySize),
|
(void *)(IMG_PBYTE)psStream->pvBase,
|
psStream->ui32WPtr);
|
}
|
ui32NewROffset = 0;
|
}
|
else
|
{
|
/* Copy everything in the old buffer to the new one */
|
HostMemCopy(pvNewBuf, psStream->pvBase, psStream->ui32WPtr);
|
ui32NewROffset = psStream->ui32RPtr;
|
}
|
|
/*
|
New Write offset is at end of data
|
*/
|
ui32NewWOffset = psStream->ui32Size - ui32SpaceInOldBuf;
|
|
/*
|
Free old buffer
|
*/
|
if ((psStream->ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
|
{
|
HostNonPageablePageFree(psStream->pvBase);
|
}
|
else
|
{
|
HostPageablePageFree(psStream->pvBase);
|
}
|
|
/*
|
Now set new params up
|
*/
|
psStream->pvBase = pvNewBuf;
|
psStream->ui32RPtr = ui32NewROffset;
|
psStream->ui32WPtr = ui32NewWOffset;
|
psStream->ui32Size = ui32NewSizeInPages * 4096;
|
|
return IMG_TRUE;
|
}
|
|
/*!****************************************************************************
|
@name SpaceInStream
|
@brief remaining space in stream
|
@param psStream - stream
|
@return bytes remaining
|
*****************************************************************************/
|
static IMG_UINT32 SpaceInStream(PDBG_STREAM psStream)
|
{
|
IMG_UINT32 ui32Space;
|
|
if ((psStream->ui32Flags & DEBUG_FLAGS_CIRCULAR) != 0)
|
{
|
/* Allow overwriting the buffer which was already read */
|
if (psStream->ui32RPtr > psStream->ui32WPtr)
|
{
|
ui32Space = psStream->ui32RPtr - psStream->ui32WPtr;
|
}
|
else
|
{
|
ui32Space = psStream->ui32RPtr + (psStream->ui32Size - psStream->ui32WPtr);
|
}
|
}
|
else
|
{
|
/* Don't overwrite anything */
|
ui32Space = psStream->ui32Size - psStream->ui32WPtr;
|
}
|
|
return ui32Space;
|
}
|
|
|
/*!****************************************************************************
|
@name DestroyAllStreams
|
@brief delete all streams in list
|
@return none
|
*****************************************************************************/
|
void DestroyAllStreams(void)
|
{
|
PDBG_STREAM psStream = g_psStreamList;
|
PDBG_STREAM psStreamToFree;
|
|
while (psStream != NULL)
|
{
|
psStreamToFree = psStream;
|
psStream = psStream->psNext;
|
DBGDrivDestroyStream(psStreamToFree->psInitStream, psStreamToFree, psStreamToFree->psDeinitStream);
|
}
|
g_psStreamList = NULL;
|
return;
|
}
|
|
/******************************************************************************
|
End of file (DBGDRIV.C)
|
******************************************************************************/
|