| /*************************************************************************/ /*! |
| @File |
| @Title Parameter dump macro target routines |
| @Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved |
| @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 (PDUMP) |
| |
| #include <asm/atomic.h> |
| #include <stdarg.h> |
| |
| #include "pvrversion.h" |
| #include "pvr_debug.h" |
| #include "pvrsrv.h" |
| #include "osfunc.h" |
| |
| #include "dbgdrvif_srv5.h" |
| #include "allocmem.h" |
| #include "pdump_km.h" |
| #include "pdump_osfunc.h" |
| #include "services_km.h" |
| |
| #include <linux/kernel.h> // sprintf |
| #include <linux/string.h> // strncpy, strlen |
| #include <linux/mutex.h> |
| |
| #define PDUMP_DATAMASTER_PIXEL (1) |
| #define PDUMP_DATAMASTER_EDM (3) |
| |
| static PDBGKM_SERVICE_TABLE gpfnDbgDrv = NULL; |
| |
| |
| typedef struct PDBG_PDUMP_STATE_TAG |
| { |
| PDBG_STREAM psStream[PDUMP_NUM_CHANNELS]; |
| |
| IMG_CHAR *pszMsg; |
| IMG_CHAR *pszScript; |
| IMG_CHAR *pszFile; |
| |
| } PDBG_PDUMP_STATE; |
| |
| static PDBG_PDUMP_STATE gsDBGPdumpState = {{NULL}, NULL, NULL, NULL}; |
| |
| #define SZ_MSG_SIZE_MAX PVRSRV_PDUMP_MAX_COMMENT_SIZE-1 |
| #define SZ_SCRIPT_SIZE_MAX PVRSRV_PDUMP_MAX_COMMENT_SIZE-1 |
| #define SZ_FILENAME_SIZE_MAX PVRSRV_PDUMP_MAX_COMMENT_SIZE-1 |
| |
| static struct mutex gsPDumpMutex; |
| |
| void DBGDrvGetServiceTable(void **fn_table); |
| |
| |
| /*! |
| * \name PDumpOSGetScriptString |
| */ |
| PVRSRV_ERROR PDumpOSGetScriptString(IMG_HANDLE *phScript, |
| IMG_UINT32 *pui32MaxLen) |
| { |
| *phScript = (IMG_HANDLE)gsDBGPdumpState.pszScript; |
| *pui32MaxLen = SZ_SCRIPT_SIZE_MAX; |
| if (!*phScript) |
| { |
| return PVRSRV_ERROR_PDUMP_NOT_ACTIVE; |
| } |
| return PVRSRV_OK; |
| } |
| |
| /*! |
| * \name PDumpOSGetMessageString |
| */ |
| PVRSRV_ERROR PDumpOSGetMessageString(IMG_CHAR **ppszMsg, |
| IMG_UINT32 *pui32MaxLen) |
| { |
| *ppszMsg = gsDBGPdumpState.pszMsg; |
| *pui32MaxLen = SZ_MSG_SIZE_MAX; |
| if (!*ppszMsg) |
| { |
| return PVRSRV_ERROR_PDUMP_NOT_ACTIVE; |
| } |
| return PVRSRV_OK; |
| } |
| |
| /*! |
| * \name PDumpOSGetFilenameString |
| */ |
| PVRSRV_ERROR PDumpOSGetFilenameString(IMG_CHAR **ppszFile, |
| IMG_UINT32 *pui32MaxLen) |
| { |
| *ppszFile = gsDBGPdumpState.pszFile; |
| *pui32MaxLen = SZ_FILENAME_SIZE_MAX; |
| if (!*ppszFile) |
| { |
| return PVRSRV_ERROR_PDUMP_NOT_ACTIVE; |
| } |
| return PVRSRV_OK; |
| } |
| |
| /*! |
| * \name PDumpOSBufprintf |
| */ |
| PVRSRV_ERROR PDumpOSBufprintf(IMG_HANDLE hBuf, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, ...) |
| { |
| IMG_CHAR* pszBuf = hBuf; |
| IMG_INT32 n; |
| va_list vaArgs; |
| |
| va_start(vaArgs, pszFormat); |
| |
| n = vsnprintf(pszBuf, ui32ScriptSizeMax, pszFormat, vaArgs); |
| |
| va_end(vaArgs); |
| |
| if (n>=(IMG_INT32)ui32ScriptSizeMax || n==-1) /* glibc >= 2.1 or glibc 2.0 */ |
| { |
| PVR_DPF((PVR_DBG_ERROR, "Buffer overflow detected, pdump output may be incomplete.")); |
| |
| return PVRSRV_ERROR_PDUMP_BUF_OVERFLOW; |
| } |
| |
| #if defined(PDUMP_DEBUG_OUTFILES) |
| g_ui32EveryLineCounter++; |
| #endif |
| |
| /* Put line ending sequence at the end if it isn't already there */ |
| PDumpOSVerifyLineEnding(pszBuf, ui32ScriptSizeMax); |
| |
| return PVRSRV_OK; |
| } |
| |
| /*! |
| * \name PDumpOSVSprintf |
| */ |
| PVRSRV_ERROR PDumpOSVSprintf(IMG_CHAR *pszComment, IMG_UINT32 ui32ScriptSizeMax, const IMG_CHAR* pszFormat, PDUMP_va_list vaArgs) |
| { |
| IMG_INT32 n; |
| |
| n = vsnprintf(pszComment, ui32ScriptSizeMax, pszFormat, vaArgs); |
| |
| if (n>=(IMG_INT32)ui32ScriptSizeMax || n==-1) /* glibc >= 2.1 or glibc 2.0 */ |
| { |
| PVR_DPF((PVR_DBG_ERROR, "Buffer overflow detected, pdump output may be incomplete.")); |
| |
| return PVRSRV_ERROR_PDUMP_BUF_OVERFLOW; |
| } |
| |
| return PVRSRV_OK; |
| } |
| |
| /*! |
| * \name PDumpOSDebugPrintf |
| */ |
| void PDumpOSDebugPrintf(IMG_CHAR* pszFormat, ...) |
| { |
| PVR_UNREFERENCED_PARAMETER(pszFormat); |
| |
| /* FIXME: Implement using services PVR_DBG or otherwise with kprintf */ |
| } |
| |
| /*! |
| * \name PDumpOSSprintf |
| */ |
| PVRSRV_ERROR PDumpOSSprintf(IMG_CHAR *pszComment, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR *pszFormat, ...) |
| { |
| IMG_INT32 n; |
| va_list vaArgs; |
| |
| va_start(vaArgs, pszFormat); |
| |
| n = vsnprintf(pszComment, ui32ScriptSizeMax, pszFormat, vaArgs); |
| |
| va_end(vaArgs); |
| |
| if (n>=(IMG_INT32)ui32ScriptSizeMax || n==-1) /* glibc >= 2.1 or glibc 2.0 */ |
| { |
| PVR_DPF((PVR_DBG_ERROR, "Buffer overflow detected, pdump output may be incomplete.")); |
| |
| return PVRSRV_ERROR_PDUMP_BUF_OVERFLOW; |
| } |
| |
| return PVRSRV_OK; |
| } |
| |
| /*! |
| * \name PDumpOSBuflen |
| */ |
| IMG_UINT32 PDumpOSBuflen(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax) |
| { |
| IMG_CHAR* pszBuf = hBuffer; |
| IMG_UINT32 ui32Count = 0; |
| |
| while ((pszBuf[ui32Count]!=0) && (ui32Count<ui32BufferSizeMax) ) |
| { |
| ui32Count++; |
| } |
| return(ui32Count); |
| } |
| |
| /*! |
| * \name PDumpOSVerifyLineEnding |
| */ |
| void PDumpOSVerifyLineEnding(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax) |
| { |
| IMG_UINT32 ui32Count; |
| IMG_CHAR* pszBuf = hBuffer; |
| |
| /* strlen */ |
| ui32Count = PDumpOSBuflen(hBuffer, ui32BufferSizeMax); |
| |
| /* Put \n sequence at the end if it isn't already there */ |
| if ((ui32Count >= 1) && (pszBuf[ui32Count-1] != '\n') && (ui32Count<ui32BufferSizeMax)) |
| { |
| pszBuf[ui32Count] = '\n'; |
| ui32Count++; |
| pszBuf[ui32Count] = '\0'; |
| } |
| } |
| |
| |
| |
| /*! |
| * \name PDumpOSGetStreamOffset |
| */ |
| IMG_BOOL PDumpOSSetSplitMarker(IMG_HANDLE hStream, IMG_UINT32 ui32Marker) |
| { |
| PDBG_STREAM psStream = (PDBG_STREAM) hStream; |
| |
| PVR_ASSERT(gpfnDbgDrv); |
| gpfnDbgDrv->pfnSetMarker(psStream, ui32Marker); |
| return IMG_TRUE; |
| } |
| |
| /*! |
| * \name PDumpOSDebugDriverWrite |
| */ |
| IMG_UINT32 PDumpOSDebugDriverWrite( IMG_HANDLE psStream, |
| IMG_UINT8 *pui8Data, |
| IMG_UINT32 ui32BCount) |
| { |
| PVR_ASSERT(gpfnDbgDrv != NULL); |
| |
| return gpfnDbgDrv->pfnDBGDrivWrite2(psStream, pui8Data, ui32BCount); |
| } |
| |
| /*! |
| * \name PDumpOSReleaseExecution |
| */ |
| void PDumpOSReleaseExecution(void) |
| { |
| OSReleaseThreadQuanta(); |
| } |
| |
| /************************************************************************** |
| * Function Name : PDumpOSInit |
| * Outputs : None |
| * Returns : |
| * Description : Reset connection to vldbgdrv |
| * Then try to connect to PDUMP streams |
| **************************************************************************/ |
| PVRSRV_ERROR PDumpOSInit(PDUMP_CHANNEL* psParam, PDUMP_CHANNEL* psScript, |
| IMG_UINT32* pui32InitCapMode, IMG_CHAR** ppszEnvComment) |
| { |
| PVRSRV_ERROR eError; |
| |
| *pui32InitCapMode = DEBUG_CAPMODE_FRAMED; |
| *ppszEnvComment = NULL; |
| |
| /* If we tried this earlier, then we might have connected to the driver |
| * But if pdump.exe was running then the stream connected would fail |
| */ |
| if (!gpfnDbgDrv) |
| { |
| DBGDrvGetServiceTable((void **)&gpfnDbgDrv); |
| |
| // If something failed then no point in trying to connect streams |
| if (gpfnDbgDrv == NULL) |
| { |
| return PVRSRV_ERROR_PDUMP_NOT_AVAILABLE; |
| } |
| |
| eError = PVRSRV_ERROR_OUT_OF_MEMORY; |
| if(!gsDBGPdumpState.pszFile) |
| { |
| gsDBGPdumpState.pszFile = OSAllocMem(SZ_FILENAME_SIZE_MAX); |
| if (gsDBGPdumpState.pszFile == NULL) |
| { |
| goto init_failed; |
| } |
| } |
| |
| if(!gsDBGPdumpState.pszMsg) |
| { |
| gsDBGPdumpState.pszMsg = OSAllocMem(SZ_MSG_SIZE_MAX); |
| if (gsDBGPdumpState.pszMsg == NULL) |
| { |
| goto init_failed; |
| } |
| } |
| |
| if(!gsDBGPdumpState.pszScript) |
| { |
| gsDBGPdumpState.pszScript = OSAllocMem(SZ_SCRIPT_SIZE_MAX); |
| if (gsDBGPdumpState.pszScript == NULL) |
| { |
| goto init_failed; |
| } |
| } |
| |
| eError = PVRSRV_ERROR_RESOURCE_UNAVAILABLE; |
| if (!gpfnDbgDrv->pfnCreateStream(PDUMP_PARAM_CHANNEL_NAME, 0, 10, &psParam->hInit, &psParam->hMain, &psParam->hDeinit)) |
| { |
| goto init_failed; |
| } |
| gsDBGPdumpState.psStream[PDUMP_CHANNEL_PARAM] = psParam->hMain; |
| |
| |
| if (!gpfnDbgDrv->pfnCreateStream(PDUMP_SCRIPT_CHANNEL_NAME, 0, 10, &psScript->hInit, &psScript->hMain, &psScript->hDeinit)) |
| { |
| goto init_failed; |
| } |
| gsDBGPdumpState.psStream[PDUMP_CHANNEL_SCRIPT] = psScript->hMain; |
| } |
| |
| return PVRSRV_OK; |
| |
| init_failed: |
| PDumpOSDeInit(psParam, psScript); |
| return eError; |
| } |
| |
| |
| void PDumpOSDeInit(PDUMP_CHANNEL* psParam, PDUMP_CHANNEL* psScript) |
| { |
| gpfnDbgDrv->pfnDestroyStream(psScript->hInit, psScript->hMain, psScript->hDeinit); |
| gpfnDbgDrv->pfnDestroyStream(psParam->hInit, psParam->hMain, psParam->hDeinit); |
| |
| if(gsDBGPdumpState.pszFile) |
| { |
| OSFreeMem(gsDBGPdumpState.pszFile); |
| gsDBGPdumpState.pszFile = NULL; |
| } |
| |
| if(gsDBGPdumpState.pszScript) |
| { |
| OSFreeMem(gsDBGPdumpState.pszScript); |
| gsDBGPdumpState.pszScript = NULL; |
| } |
| |
| if(gsDBGPdumpState.pszMsg) |
| { |
| OSFreeMem(gsDBGPdumpState.pszMsg); |
| gsDBGPdumpState.pszMsg = NULL; |
| } |
| |
| gpfnDbgDrv = NULL; |
| } |
| |
| PVRSRV_ERROR PDumpOSCreateLock(void) |
| { |
| mutex_init(&gsPDumpMutex); |
| return PVRSRV_OK; |
| } |
| |
| void PDumpOSDestroyLock(void) |
| { |
| /* no destruction work to be done, just assert |
| * the lock is not held */ |
| PVR_ASSERT(mutex_is_locked(&gsPDumpMutex) == 0); |
| } |
| |
| void PDumpOSLock(void) |
| { |
| mutex_lock(&gsPDumpMutex); |
| } |
| |
| void PDumpOSUnlock(void) |
| { |
| mutex_unlock(&gsPDumpMutex); |
| } |
| |
| IMG_UINT32 PDumpOSGetCtrlState(IMG_HANDLE hDbgStream, |
| IMG_UINT32 ui32StateID) |
| { |
| return (gpfnDbgDrv->pfnGetCtrlState((PDBG_STREAM)hDbgStream, ui32StateID)); |
| } |
| |
| void PDumpOSSetFrame(IMG_UINT32 ui32Frame) |
| { |
| gpfnDbgDrv->pfnSetFrame(ui32Frame); |
| return; |
| } |
| |
| IMG_BOOL PDumpOSAllowInitPhaseToComplete(IMG_BOOL bPDumpClient, IMG_BOOL bInitClient) |
| { |
| return (bInitClient); |
| } |
| |
| #if defined(PVR_TESTING_UTILS) |
| void PDumpOSDumpState(void); |
| |
| void PDumpOSDumpState(void) |
| { |
| PVR_LOG(("---- PDUMP LINUX: gpfnDbgDrv( %p ) gpfnDbgDrv.ui32Size( %d )", |
| gpfnDbgDrv, gpfnDbgDrv->ui32Size)); |
| |
| PVR_LOG(("---- PDUMP LINUX: gsDBGPdumpState( %p )", |
| &gsDBGPdumpState)); |
| |
| PVR_LOG(("---- PDUMP LINUX: gsDBGPdumpState.psStream[0]( %p )", |
| gsDBGPdumpState.psStream[0])); |
| |
| (void) gpfnDbgDrv->pfnGetCtrlState(gsDBGPdumpState.psStream[0], 0xFE); |
| |
| PVR_LOG(("---- PDUMP LINUX: gsDBGPdumpState.psStream[1]( %p )", |
| gsDBGPdumpState.psStream[1])); |
| |
| (void) gpfnDbgDrv->pfnGetCtrlState(gsDBGPdumpState.psStream[1], 0xFE); |
| |
| /* Now dump non-stream specific info */ |
| (void) gpfnDbgDrv->pfnGetCtrlState(gsDBGPdumpState.psStream[1], 0xFF); |
| } |
| #endif |
| |
| #endif /* #if defined (PDUMP) */ |
| /***************************************************************************** |
| End of file (PDUMP.C) |
| *****************************************************************************/ |