1 /**********************************************************************
2 Copyright (c) Imagination Technologies Ltd.
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 ******************************************************************************/
23 #if defined (SUPPORT_SGX)
26 #include <asm/atomic.h>
29 #include "services_headers.h"
31 #include "pvrversion.h"
32 #include "pvr_debug.h"
39 #include <linux/tty.h>
41 static IMG_BOOL PDumpWriteString2 (IMG_CHAR * pszString, IMG_UINT32 ui32Flags);
42 static IMG_BOOL PDumpWriteILock (PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_UINT32 ui32Count, IMG_UINT32 ui32Flags);
43 static IMG_VOID DbgSetFrame (PDBG_STREAM psStream, IMG_UINT32 ui32Frame);
44 static IMG_UINT32 DbgGetFrame (PDBG_STREAM psStream);
45 static IMG_VOID DbgSetMarker (PDBG_STREAM psStream, IMG_UINT32 ui32Marker);
46 static IMG_UINT32 DbgWrite (PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_UINT32 ui32BCount, IMG_UINT32 ui32Flags);
48 #define PDUMP_DATAMASTER_PIXEL (1)
49 #define PDUMP_DATAMASTER_EDM (3)
51 #define MIN(a,b) (a > b ? b : a)
53 #define MAX_FILE_SIZE 0x40000000
55 static atomic_t gsPDumpSuspended = ATOMIC_INIT(0);
57 static PDBGKM_SERVICE_TABLE gpfnDbgDrv = IMG_NULL;
61 IMG_CHAR *pszStreamName[PDUMP_NUM_STREAMS] = { "ParamStream2",
64 typedef struct PDBG_PDUMP_STATE_TAG
66 PDBG_STREAM psStream[PDUMP_NUM_STREAMS];
67 IMG_UINT32 ui32ParamFileNum;
75 static PDBG_PDUMP_STATE gsDBGPdumpState = {{IMG_NULL}, 0, IMG_NULL, IMG_NULL, IMG_NULL};
77 #define SZ_MSG_SIZE_MAX PVRSRV_PDUMP_MAX_COMMENT_SIZE-1
78 #define SZ_SCRIPT_SIZE_MAX PVRSRV_PDUMP_MAX_COMMENT_SIZE-1
79 #define SZ_FILENAME_SIZE_MAX PVRSRV_PDUMP_MAX_COMMENT_SIZE-1
84 IMG_VOID DBGDrvGetServiceTable(IMG_VOID **fn_table);
86 static inline IMG_BOOL PDumpSuspended(IMG_VOID)
88 return atomic_read(&gsPDumpSuspended) != 0;
91 PVRSRV_ERROR PDumpOSGetScriptString(IMG_HANDLE *phScript,
92 IMG_UINT32 *pui32MaxLen)
94 *phScript = (IMG_HANDLE)gsDBGPdumpState.pszScript;
95 *pui32MaxLen = SZ_SCRIPT_SIZE_MAX;
96 if ((!*phScript) || PDumpSuspended())
98 return PVRSRV_ERROR_GENERIC;
103 PVRSRV_ERROR PDumpOSGetMessageString(IMG_HANDLE *phMsg,
104 IMG_UINT32 *pui32MaxLen)
106 *phMsg = (IMG_HANDLE)gsDBGPdumpState.pszMsg;
107 *pui32MaxLen = SZ_MSG_SIZE_MAX;
108 if ((!*phMsg) || PDumpSuspended())
110 return PVRSRV_ERROR_GENERIC;
115 PVRSRV_ERROR PDumpOSGetFilenameString(IMG_CHAR **ppszFile,
116 IMG_UINT32 *pui32MaxLen)
118 *ppszFile = gsDBGPdumpState.pszFile;
119 *pui32MaxLen = SZ_FILENAME_SIZE_MAX;
120 if ((!*ppszFile) || PDumpSuspended())
122 return PVRSRV_ERROR_GENERIC;
127 IMG_BOOL PDumpOSWriteString2(IMG_HANDLE hScript, IMG_UINT32 ui32Flags)
129 return PDumpWriteString2(hScript, ui32Flags);
132 PVRSRV_ERROR PDumpOSBufprintf(IMG_HANDLE hBuf, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, ...)
134 IMG_CHAR* pszBuf = hBuf;
138 va_start(vaArgs, pszFormat);
140 n = vsnprintf(pszBuf, ui32ScriptSizeMax, pszFormat, vaArgs);
144 if (n>=ui32ScriptSizeMax || n==-1)
146 PVR_DPF((PVR_DBG_ERROR, "Buffer overflow detected, pdump output may be incomplete."));
148 return PVRSRV_ERROR_PDUMP_BUF_OVERFLOW;
154 PVRSRV_ERROR PDumpOSVSprintf(IMG_CHAR *pszComment, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, PDUMP_va_list vaArgs)
158 n = vsnprintf(pszComment, ui32ScriptSizeMax, pszFormat, vaArgs);
160 if (n>=ui32ScriptSizeMax || n==-1)
162 PVR_DPF((PVR_DBG_ERROR, "Buffer overflow detected, pdump output may be incomplete."));
164 return PVRSRV_ERROR_PDUMP_BUF_OVERFLOW;
170 IMG_VOID PDumpOSDebugPrintf(IMG_CHAR* pszFormat, ...)
175 PVRSRV_ERROR PDumpOSSprintf(IMG_CHAR *pszComment, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR *pszFormat, ...)
180 va_start(vaArgs, pszFormat);
182 n = vsnprintf(pszComment, ui32ScriptSizeMax, pszFormat, vaArgs);
186 if (n>=ui32ScriptSizeMax || n==-1)
188 PVR_DPF((PVR_DBG_ERROR, "Buffer overflow detected, pdump output may be incomplete."));
190 return PVRSRV_ERROR_PDUMP_BUF_OVERFLOW;
196 IMG_UINT32 PDumpOSBuflen(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax)
198 IMG_CHAR* pszBuf = hBuffer;
199 IMG_UINT32 ui32Count = 0;
201 while ((pszBuf[ui32Count]!=0) && (ui32Count<ui32BufferSizeMax) )
208 IMG_VOID PDumpOSVerifyLineEnding(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax)
210 IMG_UINT32 ui32Count = 0;
211 IMG_CHAR* pszBuf = hBuffer;
214 ui32Count = PDumpOSBuflen(hBuffer, ui32BufferSizeMax);
217 if ((ui32Count >= 1) && (pszBuf[ui32Count-1] != '\n') && (ui32Count<ui32BufferSizeMax))
219 pszBuf[ui32Count] = '\n';
221 pszBuf[ui32Count] = '\0';
223 if ((ui32Count >= 2) && (pszBuf[ui32Count-2] != '\r') && (ui32Count<ui32BufferSizeMax))
225 pszBuf[ui32Count-1] = '\r';
226 pszBuf[ui32Count] = '\n';
228 pszBuf[ui32Count] = '\0';
232 IMG_HANDLE PDumpOSGetStream(IMG_UINT32 ePDumpStream)
234 return (IMG_HANDLE)gsDBGPdumpState.psStream[ePDumpStream];
237 IMG_UINT32 PDumpOSGetStreamOffset(IMG_UINT32 ePDumpStream)
239 PDBG_STREAM psStream = gsDBGPdumpState.psStream[ePDumpStream];
240 return gpfnDbgDrv->pfnGetStreamOffset(psStream);
243 IMG_UINT32 PDumpOSGetParamFileNum(IMG_VOID)
245 return gsDBGPdumpState.ui32ParamFileNum;
248 IMG_BOOL PDumpOSWriteString(IMG_HANDLE hStream,
249 IMG_UINT8 *psui8Data,
251 IMG_UINT32 ui32Flags)
253 PDBG_STREAM psStream = (PDBG_STREAM)hStream;
254 return PDumpWriteILock(psStream,
260 IMG_VOID PDumpOSCheckForSplitting(IMG_HANDLE hStream, IMG_UINT32 ui32Size, IMG_UINT32 ui32Flags)
263 PVR_UNREFERENCED_PARAMETER(hStream);
264 PVR_UNREFERENCED_PARAMETER(ui32Size);
265 PVR_UNREFERENCED_PARAMETER(ui32Size);
268 IMG_BOOL PDumpOSJTInitialised(IMG_VOID)
277 inline IMG_BOOL PDumpOSIsSuspended(IMG_VOID)
279 return atomic_read(&gsPDumpSuspended) != 0;
282 IMG_VOID PDumpOSCPUVAddrToDevPAddr(PVRSRV_DEVICE_TYPE eDeviceType,
283 IMG_HANDLE hOSMemHandle,
284 IMG_UINT32 ui32Offset,
285 IMG_UINT8 *pui8LinAddr,
286 IMG_UINT32 ui32PageSize,
287 IMG_DEV_PHYADDR *psDevPAddr)
292 IMG_CPU_PHYADDR sCpuPAddr;
294 PVR_UNREFERENCED_PARAMETER(pui8LinAddr);
296 sCpuPAddr = OSMemHandleToCpuPAddr(hOSMemHandle, ui32Offset);
297 PVR_ASSERT((sCpuPAddr.uiAddr & (ui32PageSize - 1)) == 0);
300 *psDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr);
304 IMG_CPU_PHYADDR sCpuPAddr;
306 PVR_UNREFERENCED_PARAMETER(ui32Offset);
308 sCpuPAddr = OSMapLinToCPUPhys(pui8LinAddr);
309 *psDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr);
313 IMG_VOID PDumpOSCPUVAddrToPhysPages(IMG_HANDLE hOSMemHandle,
314 IMG_UINT32 ui32Offset,
315 IMG_PUINT8 pui8LinAddr,
316 IMG_UINT32 *pui32PageOffset)
321 IMG_CPU_PHYADDR sCpuPAddr;
323 PVR_UNREFERENCED_PARAMETER(pui8LinAddr);
325 sCpuPAddr = OSMemHandleToCpuPAddr(hOSMemHandle, ui32Offset);
326 *pui32PageOffset = sCpuPAddr.uiAddr & (HOST_PAGESIZE() -1);
330 PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
331 PVR_UNREFERENCED_PARAMETER(ui32Offset);
333 *pui32PageOffset = (IMG_UINT32)pui8LinAddr & (HOST_PAGESIZE() - 1);
339 IMG_VOID PDumpInit(IMG_VOID)
346 DBGDrvGetServiceTable((IMG_VOID **)&gpfnDbgDrv);
351 if (gpfnDbgDrv == IMG_NULL)
356 if(!gsDBGPdumpState.pszFile)
358 if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_FILENAME_SIZE_MAX, (IMG_PVOID *)&gsDBGPdumpState.pszFile, 0,
359 "Filename string") != PVRSRV_OK)
365 if(!gsDBGPdumpState.pszMsg)
367 if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_MSG_SIZE_MAX, (IMG_PVOID *)&gsDBGPdumpState.pszMsg, 0,
368 "Message string") != PVRSRV_OK)
374 if(!gsDBGPdumpState.pszScript)
376 if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_SCRIPT_SIZE_MAX, (IMG_PVOID *)&gsDBGPdumpState.pszScript, 0,
377 "Script string") != PVRSRV_OK)
383 for(i=0; i < PDUMP_NUM_STREAMS; i++)
385 gsDBGPdumpState.psStream[i] = gpfnDbgDrv->pfnCreateStream(pszStreamName[i],
386 DEBUG_CAPMODE_FRAMED,
387 DEBUG_OUTMODE_STREAMENABLE,
391 gpfnDbgDrv->pfnSetCaptureMode(gsDBGPdumpState.psStream[i],DEBUG_CAPMODE_FRAMED,0xFFFFFFFF, 0xFFFFFFFF, 1);
392 gpfnDbgDrv->pfnSetFrame(gsDBGPdumpState.psStream[i],0);
395 PDUMPCOMMENT("Driver Product Name: %s", VS_PRODUCT_NAME);
396 PDUMPCOMMENT("Driver Product Version: %s (%s)", PVRVERSION_STRING, PVRVERSION_FILE);
397 PDUMPCOMMENT("Start of Init Phase");
404 if(gsDBGPdumpState.pszFile)
406 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_FILENAME_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszFile, 0);
407 gsDBGPdumpState.pszFile = IMG_NULL;
410 if(gsDBGPdumpState.pszScript)
412 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_SCRIPT_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszScript, 0);
413 gsDBGPdumpState.pszScript = IMG_NULL;
416 if(gsDBGPdumpState.pszMsg)
418 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_MSG_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszMsg, 0);
419 gsDBGPdumpState.pszMsg = IMG_NULL;
422 gpfnDbgDrv = IMG_NULL;
426 IMG_VOID PDumpDeInit(IMG_VOID)
430 for(i=0; i < PDUMP_NUM_STREAMS; i++)
432 gpfnDbgDrv->pfnDestroyStream(gsDBGPdumpState.psStream[i]);
435 if(gsDBGPdumpState.pszFile)
437 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_FILENAME_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszFile, 0);
438 gsDBGPdumpState.pszFile = IMG_NULL;
441 if(gsDBGPdumpState.pszScript)
443 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_SCRIPT_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszScript, 0);
444 gsDBGPdumpState.pszScript = IMG_NULL;
447 if(gsDBGPdumpState.pszMsg)
449 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_MSG_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszMsg, 0);
450 gsDBGPdumpState.pszMsg = IMG_NULL;
453 gpfnDbgDrv = IMG_NULL;
456 PVRSRV_ERROR PDumpStartInitPhaseKM(IMG_VOID)
462 PDUMPCOMMENT("Start Init Phase");
463 for(i=0; i < PDUMP_NUM_STREAMS; i++)
465 gpfnDbgDrv->pfnStartInitPhase(gsDBGPdumpState.psStream[i]);
471 PVRSRV_ERROR PDumpStopInitPhaseKM(IMG_VOID)
477 PDUMPCOMMENT("Stop Init Phase");
479 for(i=0; i < PDUMP_NUM_STREAMS; i++)
481 gpfnDbgDrv->pfnStopInitPhase(gsDBGPdumpState.psStream[i]);
487 IMG_BOOL PDumpIsLastCaptureFrameKM(IMG_VOID)
489 return gpfnDbgDrv->pfnIsLastCaptureFrame(gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2]);
493 IMG_BOOL PDumpIsCaptureFrameKM(IMG_VOID)
495 if (PDumpSuspended())
499 return gpfnDbgDrv->pfnIsCaptureFrame(gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2], IMG_FALSE);
502 PVRSRV_ERROR PDumpSetFrameKM(IMG_UINT32 ui32Frame)
504 IMG_UINT32 ui32Stream;
506 for (ui32Stream = 0; ui32Stream < PDUMP_NUM_STREAMS; ui32Stream++)
508 if (gsDBGPdumpState.psStream[ui32Stream])
510 DbgSetFrame(gsDBGPdumpState.psStream[ui32Stream], ui32Frame);
517 PVRSRV_ERROR PDumpGetFrameKM(IMG_PUINT32 pui32Frame)
519 *pui32Frame = DbgGetFrame(gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2]);
526 static IMG_BOOL PDumpWriteString2(IMG_CHAR * pszString, IMG_UINT32 ui32Flags)
528 return PDumpWriteILock(gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2], (IMG_UINT8 *) pszString, strlen(pszString), ui32Flags);
532 static IMG_BOOL PDumpWriteILock(PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_UINT32 ui32Count, IMG_UINT32 ui32Flags)
534 IMG_UINT32 ui32Written = 0;
535 IMG_UINT32 ui32Off = 0;
537 if ((psStream == IMG_NULL) || PDumpSuspended() || ((ui32Flags & PDUMP_FLAGS_NEVER) != 0))
545 if (psStream == gsDBGPdumpState.psStream[PDUMP_STREAM_PARAM2])
547 IMG_UINT32 ui32ParamOutPos = gpfnDbgDrv->pfnGetStreamOffset(gsDBGPdumpState.psStream[PDUMP_STREAM_PARAM2]);
549 if (ui32ParamOutPos + ui32Count > MAX_FILE_SIZE)
551 if ((gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2] && PDumpWriteString2("\r\n-- Splitting pdump output file\r\n\r\n", ui32Flags)))
553 DbgSetMarker(gsDBGPdumpState.psStream[PDUMP_STREAM_PARAM2], ui32ParamOutPos);
554 gsDBGPdumpState.ui32ParamFileNum++;
560 while (((IMG_UINT32) ui32Count > 0) && (ui32Written != 0xFFFFFFFF))
562 ui32Written = DbgWrite(psStream, &pui8Data[ui32Off], ui32Count, ui32Flags);
567 if (ui32Written == 0)
569 OSReleaseThreadQuanta();
572 if (ui32Written != 0xFFFFFFFF)
574 ui32Off += ui32Written;
575 ui32Count -= ui32Written;
579 if (ui32Written == 0xFFFFFFFF)
587 static IMG_VOID DbgSetFrame(PDBG_STREAM psStream, IMG_UINT32 ui32Frame)
589 gpfnDbgDrv->pfnSetFrame(psStream, ui32Frame);
593 static IMG_UINT32 DbgGetFrame(PDBG_STREAM psStream)
595 return gpfnDbgDrv->pfnGetFrame(psStream);
598 static IMG_VOID DbgSetMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker)
600 gpfnDbgDrv->pfnSetMarker(psStream, ui32Marker);
603 static IMG_UINT32 DbgWrite(PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_UINT32 ui32BCount, IMG_UINT32 ui32Flags)
605 IMG_UINT32 ui32BytesWritten;
607 if ((ui32Flags & PDUMP_FLAGS_CONTINUOUS) != 0)
611 if (((psStream->ui32CapMode & DEBUG_CAPMODE_FRAMED) != 0) &&
612 (psStream->ui32Start == 0xFFFFFFFFUL) &&
613 (psStream->ui32End == 0xFFFFFFFFUL) &&
614 psStream->bInitPhaseComplete)
616 ui32BytesWritten = ui32BCount;
620 ui32BytesWritten = gpfnDbgDrv->pfnDBGDrivWrite2(psStream, pui8Data, ui32BCount, 1);
625 if (ui32Flags & PDUMP_FLAGS_LASTFRAME)
627 IMG_UINT32 ui32DbgFlags;
630 if (ui32Flags & PDUMP_FLAGS_RESETLFBUFFER)
632 ui32DbgFlags |= WRITELF_FLAGS_RESETBUF;
635 ui32BytesWritten = gpfnDbgDrv->pfnWriteLF(psStream, pui8Data, ui32BCount, 1, ui32DbgFlags);
639 ui32BytesWritten = gpfnDbgDrv->pfnWriteBINCM(psStream, pui8Data, ui32BCount, 1);
643 return ui32BytesWritten;
647 IMG_VOID PDumpSuspendKM(IMG_VOID)
649 atomic_inc(&gsPDumpSuspended);
652 IMG_VOID PDumpResumeKM(IMG_VOID)
654 atomic_dec(&gsPDumpSuspended);