1 /*************************************************************************/ /*!
4 @Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
5 @Description 32 Bit kernel mode debug driver
6 @License Dual MIT/GPLv2
8 The contents of this file are subject to the MIT license as set out below.
10 Permission is hereby granted, free of charge, to any person obtaining a copy
11 of this software and associated documentation files (the "Software"), to deal
12 in the Software without restriction, including without limitation the rights
13 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 copies of the Software, and to permit persons to whom the Software is
15 furnished to do so, subject to the following conditions:
17 The above copyright notice and this permission notice shall be included in
18 all copies or substantial portions of the Software.
20 Alternatively, the contents of this file may be used under the terms of
21 the GNU General Public License Version 2 ("GPL") in which case the provisions
22 of GPL are applicable instead of those above.
24 If you wish to allow use of your version of this file only under the terms of
25 GPL, and not to allow others to use your version of this file under the terms
26 of the MIT license, indicate your decision by deleting the provisions above
27 and replace them with the notice and other provisions required by GPL as set
28 out in the file called "GPL-COPYING" included in this distribution. If you do
29 not delete the provisions above, a recipient may use your version of this file
30 under the terms of either the MIT license or GPL.
32 This License is also included in this distribution in the file called
35 EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
36 PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
37 BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
38 PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
39 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
40 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
41 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
42 */ /**************************************************************************/
45 #pragma warning(disable:4201)
46 #pragma warning(disable:4214)
47 #pragma warning(disable:4115)
48 #pragma warning(disable:4514)
57 #include <linux/string.h>
60 #if defined (__QNXNTO__)
64 #include "img_types.h"
66 #include "pvr_debug.h"
67 #include "dbgdrvif_srv5.h"
72 #pragma warning(default:4214)
73 #pragma warning(default:4115)
77 /******************************************************************************
79 ******************************************************************************/
81 #define DBG_STREAM_NAME_MAX 30
84 Per-buffer control structure.
86 typedef struct _DBG_STREAM_
88 struct _DBG_STREAM_* psNext;
89 struct _DBG_STREAM_* psInitStream;
90 struct _DBG_STREAM_* psDeinitStream;
91 IMG_UINT32 ui32Flags; /*!< flags (see DEBUG_FLAGS) */
97 IMG_UINT32 ui32Marker; /*!< Size marker for file splitting */
99 IMG_UINT32 ui32InitPhaseWOff; /*!< snapshot offset for init phase end for follow-on pdump */
101 IMG_CHAR szName[DBG_STREAM_NAME_MAX]; /* Give this a size, some compilers don't like [] */
104 /* Check 4xDBG_STREAM will fit in one page */
105 BLD_ASSERT(sizeof(DBG_STREAM)<<2<HOST_PAGESIZE,dbgdriv_c)
107 /******************************************************************************
109 ******************************************************************************/
111 static PDBG_STREAM g_psStreamList = 0;
113 /* Mutex used to prevent UM threads (via the dbgdrv ioctl interface) and KM
114 * threads (from pvrsrvkm via the ExtDBG API) entering the debug driver core
115 * and changing the state of share data at the same time.
117 IMG_VOID * g_pvAPIMutex=IMG_NULL;
119 static IMG_UINT32 g_PDumpCurrentFrameNo = 0;
121 DBGKM_SERVICE_TABLE g_sDBGKMServices =
123 sizeof (DBGKM_SERVICE_TABLE),
124 ExtDBGDrivCreateStream,
125 ExtDBGDrivDestroyStream,
128 ExtDBGDrivWaitForEvent,
129 ExtDBGDrivGetCtrlState,
134 /***************************************************************************
136 ***************************************************************************/
138 IMG_BOOL IMG_CALLCONV DBGDrivCreateStream(IMG_CHAR *pszName, IMG_UINT32 ui32Flags, IMG_UINT32 ui32Pages, IMG_HANDLE* phInit, IMG_HANDLE* phMain, IMG_HANDLE* phDeinit);
139 IMG_VOID IMG_CALLCONV DBGDrivDestroyStream(IMG_HANDLE hInit,IMG_HANDLE hMain, IMG_HANDLE hDeinit);
140 IMG_VOID * IMG_CALLCONV DBGDrivFindStream(IMG_CHAR * pszName, IMG_BOOL bResetStream);
141 IMG_UINT32 IMG_CALLCONV DBGDrivRead(PDBG_STREAM psStream, IMG_UINT32 ui32BufID, IMG_UINT32 ui32OutBufferSize,IMG_UINT8 *pui8OutBuf);
142 IMG_VOID IMG_CALLCONV DBGDrivSetCaptureMode(PDBG_STREAM psStream,IMG_UINT32 ui32Mode,IMG_UINT32 ui32Start,IMG_UINT32 ui32Stop,IMG_UINT32 ui32SampleRate);
143 IMG_UINT32 IMG_CALLCONV DBGDrivWrite2(PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize);
144 IMG_VOID IMG_CALLCONV DBGDrivSetMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker);
145 IMG_UINT32 IMG_CALLCONV DBGDrivGetMarker(PDBG_STREAM psStream);
146 IMG_VOID IMG_CALLCONV DBGDrivWaitForEvent(DBG_EVENT eEvent);
147 IMG_UINT32 IMG_CALLCONV DBGDrivGetCtrlState(PDBG_STREAM psStream, IMG_UINT32 ui32StateID);
148 IMG_UINT32 IMG_CALLCONV DBGDrivGetFrame(void);
149 IMG_VOID IMG_CALLCONV DBGDrivSetFrame(IMG_UINT32 ui32Frame);
150 IMG_VOID DestroyAllStreams(IMG_VOID);
152 /* Static function declarations */
153 static IMG_UINT32 SpaceInStream(PDBG_STREAM psStream);
154 static IMG_BOOL ExpandStreamBuffer(PDBG_STREAM psStream, IMG_UINT32 ui32NewSize);
155 static IMG_VOID InvalidateAllStreams(IMG_VOID);
158 /*****************************************************************************
160 *****************************************************************************/
163 @name ExtDBGDrivCreateStream
165 IMG_BOOL IMG_CALLCONV ExtDBGDrivCreateStream(IMG_CHAR *pszName, IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size, IMG_HANDLE* phInit, IMG_HANDLE* phMain, IMG_HANDLE* phDeinit)
169 /* Aquire API Mutex */
170 HostAquireMutex(g_pvAPIMutex);
172 pvRet=DBGDrivCreateStream(pszName, ui32Flags, ui32Size, phInit, phMain, phDeinit);
174 /* Release API Mutex */
175 HostReleaseMutex(g_pvAPIMutex);
181 @name ExtDBGDrivDestroyStream
183 IMG_VOID IMG_CALLCONV ExtDBGDrivDestroyStream(IMG_HANDLE hInit,IMG_HANDLE hMain, IMG_HANDLE hDeinit)
185 /* Aquire API Mutex */
186 HostAquireMutex(g_pvAPIMutex);
188 DBGDrivDestroyStream(hInit, hMain, hDeinit);
190 /* Release API Mutex */
191 HostReleaseMutex(g_pvAPIMutex);
197 @name ExtDBGDrivFindStream
199 IMG_VOID * IMG_CALLCONV ExtDBGDrivFindStream(IMG_CHAR * pszName, IMG_BOOL bResetStream)
203 /* Aquire API Mutex */
204 HostAquireMutex(g_pvAPIMutex);
206 pvRet=DBGDrivFindStream(pszName, bResetStream);
207 if (pvRet == IMG_NULL)
209 PVR_DPF((PVR_DBG_ERROR, "ExtDBGDrivFindStream: Stream not found"));
213 /* Release API Mutex */
214 HostReleaseMutex(g_pvAPIMutex);
222 IMG_UINT32 IMG_CALLCONV ExtDBGDrivRead(PDBG_STREAM psStream, IMG_UINT32 ui32BufID, IMG_UINT32 ui32OutBuffSize,IMG_UINT8 * pui8OutBuf)
226 /* Aquire API Mutex */
227 HostAquireMutex(g_pvAPIMutex);
229 ui32Ret=DBGDrivRead(psStream, ui32BufID, ui32OutBuffSize, pui8OutBuf);
231 /* Release API Mutex */
232 HostReleaseMutex(g_pvAPIMutex);
238 @name ExtDBGDrivWrite2
240 IMG_UINT32 IMG_CALLCONV ExtDBGDrivWrite2(PDBG_STREAM psStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize)
244 /* Aquire API Mutex */
245 HostAquireMutex(g_pvAPIMutex);
247 ui32Ret=DBGDrivWrite2(psStream, pui8InBuf, ui32InBuffSize);
249 /* Release API Mutex */
250 HostReleaseMutex(g_pvAPIMutex);
256 @name ExtDBGDrivSetMarker
258 IMG_VOID IMG_CALLCONV ExtDBGDrivSetMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker)
260 /* Aquire API Mutex */
261 HostAquireMutex(g_pvAPIMutex);
263 DBGDrivSetMarker(psStream, ui32Marker);
265 /* Release API Mutex */
266 HostReleaseMutex(g_pvAPIMutex);
272 @name ExtDBGDrivGetMarker
274 IMG_UINT32 IMG_CALLCONV ExtDBGDrivGetMarker(PDBG_STREAM psStream)
276 IMG_UINT32 ui32Marker;
278 /* Aquire API Mutex */
279 HostAquireMutex(g_pvAPIMutex);
281 ui32Marker = DBGDrivGetMarker(psStream);
283 /* Release API Mutex */
284 HostReleaseMutex(g_pvAPIMutex);
290 @name ExtDBGDrivWaitForEvent
292 IMG_VOID IMG_CALLCONV ExtDBGDrivWaitForEvent(DBG_EVENT eEvent)
294 #if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
295 DBGDrivWaitForEvent(eEvent);
296 #else /* defined(SUPPORT_DBGDRV_EVENT_OBJECTS) */
297 PVR_UNREFERENCED_PARAMETER(eEvent); /* PRQA S 3358 */
298 #endif /* defined(SUPPORT_DBGDRV_EVENT_OBJECTS) */
303 @name ExtDBGDrivGetCtrlState
305 IMG_UINT32 IMG_CALLCONV ExtDBGDrivGetCtrlState(PDBG_STREAM psStream, IMG_UINT32 ui32StateID)
307 IMG_UINT32 ui32State = 0;
309 /* Aquire API Mutex */
310 HostAquireMutex(g_pvAPIMutex);
312 ui32State = DBGDrivGetCtrlState(psStream, ui32StateID);
314 /* Release API Mutex */
315 HostReleaseMutex(g_pvAPIMutex);
321 @name ExtDBGDrivGetFrame
323 IMG_UINT32 IMG_CALLCONV ExtDBGDrivGetFrame(void)
325 IMG_UINT32 ui32Frame = 0;
327 /* Aquire API Mutex */
328 HostAquireMutex(g_pvAPIMutex);
330 ui32Frame = DBGDrivGetFrame();
332 /* Release API Mutex */
333 HostReleaseMutex(g_pvAPIMutex);
339 @name ExtDBGDrivGetCtrlState
341 IMG_VOID IMG_CALLCONV ExtDBGDrivSetFrame(IMG_UINT32 ui32Frame)
343 /* Aquire API Mutex */
344 HostAquireMutex(g_pvAPIMutex);
346 DBGDrivSetFrame(ui32Frame);
348 /* Release API Mutex */
349 HostReleaseMutex(g_pvAPIMutex);
356 /*!****************************************************************************
358 @brief Returns the integer value of a decimal string
359 @param szIn - String with hexadecimal value
360 @return IMG_UINT32 integer value, 0 if string is null or not valid
361 Based on Max`s one, now copes with (only) hex ui32ords, upper or lower case a-f.
362 *****************************************************************************/
363 IMG_UINT32 AtoI(IMG_CHAR *szIn)
366 IMG_UINT32 ui32Value = 0;
367 IMG_UINT32 ui32Digit=1;
368 IMG_UINT32 ui32Base=10;
373 while (szIn[iLen] > 0)
384 /* See if we have an 'x' or 'X' before the number to make it a hex number */
386 while (szIn[iPos] == '0')
390 if (szIn[iPos] == '\0')
394 if (szIn[iPos] == 'x' || szIn[iPos] == 'X')
400 //go through string from right (least significant) to left
401 for (iPos = iLen - 1; iPos >= 0; iPos --)
405 if ( (bc >= 'a') && (bc <= 'f') && ui32Base == 16) //handle lower case a-f
410 if ( (bc >= 'A') && (bc <= 'F') && ui32Base == 16) //handle upper case A-F
415 if ((bc >= '0') && (bc <= '9')) //if char out of range, return 0
422 ui32Value += (IMG_UINT32)bc * ui32Digit;
424 ui32Digit = ui32Digit * ui32Base;
430 /*!****************************************************************************
432 @brief Validates supplied debug buffer.
433 @param psStream - debug stream
434 @return true if valid
435 *****************************************************************************/
436 static IMG_BOOL StreamValid(PDBG_STREAM psStream)
440 psThis = g_psStreamList;
444 if (psStream && ((psThis == psStream) ||
445 (psThis->psInitStream == psStream) ||
446 (psThis->psDeinitStream == psStream)) )
452 psThis = psThis->psNext;
460 /*!****************************************************************************
461 @name StreamValidForRead
462 @brief Validates supplied debug buffer for read op.
463 @param psStream - debug stream
464 @return true if readable
465 *****************************************************************************/
466 static IMG_BOOL StreamValidForRead(PDBG_STREAM psStream)
468 if( StreamValid(psStream) &&
469 ((psStream->ui32Flags & DEBUG_FLAGS_WRITEONLY) == 0) )
477 /*!****************************************************************************
478 @name StreamValidForWrite
479 @brief Validates supplied debug buffer for write op.
480 @param psStream - debug stream
481 @return true if writable
482 *****************************************************************************/
483 static IMG_BOOL StreamValidForWrite(PDBG_STREAM psStream)
485 if( StreamValid(psStream) &&
486 ((psStream->ui32Flags & DEBUG_FLAGS_READONLY) == 0) )
494 /*!****************************************************************************
496 @brief Copies data from a buffer into selected stream. Stream size is fixed.
497 @param psStream - stream for output
498 @param pui8Data - input buffer
499 @param ui32InBuffSize - size of input
501 *****************************************************************************/
502 static IMG_VOID Write(PDBG_STREAM psStream,IMG_PUINT8 pui8Data,IMG_UINT32 ui32InBuffSize)
505 Split copy into two bits as necessary (if we're allowed to wrap).
507 if ((psStream->ui32Flags & DEBUG_FLAGS_CIRCULAR) == 0)
509 PVR_ASSERT( (psStream->ui32WPtr + ui32InBuffSize) < psStream->ui32Size );
512 if ((psStream->ui32WPtr + ui32InBuffSize) > psStream->ui32Size)
514 /* Yes we need two bits, calculate their sizes */
515 IMG_UINT32 ui32B1 = psStream->ui32Size - psStream->ui32WPtr;
516 IMG_UINT32 ui32B2 = ui32InBuffSize - ui32B1;
518 /* Copy first block to current location */
519 HostMemCopy((IMG_PVOID)((IMG_UINTPTR_T)psStream->pvBase + psStream->ui32WPtr),
520 (IMG_PVOID) pui8Data,
523 /* Copy second block to start of buffer */
524 HostMemCopy(psStream->pvBase,
525 (IMG_PVOID)(pui8Data + ui32B1),
528 /* Set pointer to be the new end point */
529 psStream->ui32WPtr = ui32B2;
532 { /* Can fit block in single chunk */
533 HostMemCopy((IMG_PVOID)((IMG_UINTPTR_T)psStream->pvBase + psStream->ui32WPtr),
534 (IMG_PVOID) pui8Data,
537 psStream->ui32WPtr += ui32InBuffSize;
539 if (psStream->ui32WPtr == psStream->ui32Size)
541 psStream->ui32WPtr = 0;
547 /*!****************************************************************************
548 @name WriteExpandingBuffer
549 @brief Copies data from a buffer into selected stream. Stream size may be expandable.
550 @param psStream - stream for output
551 @param pui8InBuf - input buffer
552 @param ui32InBuffSize - size of input
554 *****************************************************************************/
555 static IMG_UINT32 WriteExpandingBuffer(PDBG_STREAM psStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize)
560 How much space have we got in the buffer ?
562 ui32Space = SpaceInStream(psStream);
565 Check if we can expand the buffer
567 if (psStream->ui32Flags & DEBUG_FLAGS_NO_BUF_EXPANDSION)
570 Don't do anything if we've got less that 32 ui8tes of space and
571 we're not allowing expansion of buffer space...
575 PVR_DPF((PVR_DBG_ERROR, "WriteExpandingBuffer: buffer %p is full and isn't expandable", psStream));
581 if ((ui32Space < 32) || (ui32Space <= (ui32InBuffSize + 4)))
583 IMG_UINT32 ui32NewBufSize;
586 Find new buffer size, double the current size or increase by 1MB
588 ui32NewBufSize = MIN(psStream->ui32Size<<1,psStream->ui32Size+(1<<20));
589 ui32NewBufSize = MIN(ui32NewBufSize, (PDUMP_STREAMBUF_MAX_SIZE_MB<<20));
591 PVR_DPF((PVR_DBGDRIV_MESSAGE, "Expanding buffer size = %x, new size = %x",
592 psStream->ui32Size, ui32NewBufSize));
594 if (ui32InBuffSize > psStream->ui32Size)
596 ui32NewBufSize += ui32InBuffSize;
597 PVR_DPF((PVR_DBG_ERROR, "WriteExpandingBuffer: buffer %p is expanding by size of input buffer %u", psStream, ui32NewBufSize));
601 Attempt to expand the buffer
603 if ((ui32NewBufSize < psStream->ui32Size) ||
604 !ExpandStreamBuffer(psStream,ui32NewBufSize))
608 if((psStream->ui32Flags & DEBUG_FLAGS_CIRCULAR) != 0)
615 PVR_DPF((PVR_DBG_ERROR, "WriteExpandingBuffer: Unable to expand %p. Out of memory.", psStream));
616 InvalidateAllStreams();
617 return (0xFFFFFFFFUL);
623 Recalc the space in the buffer
625 ui32Space = SpaceInStream(psStream);
626 PVR_DPF((PVR_DBGDRIV_MESSAGE, "Expanded buffer, free space = %x",
632 Only copy what we can..
634 if (ui32Space <= (ui32InBuffSize + 4))
636 ui32InBuffSize = ui32Space - 4;
642 Write(psStream,pui8InBuf,ui32InBuffSize);
644 #if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
647 HostSignalEvent(DBG_EVENT_STREAM_DATA);
650 return(ui32InBuffSize);
653 /*****************************************************************************
654 ******************************************************************************
655 ******************************************************************************
657 ******************************************************************************
658 ******************************************************************************
659 *****************************************************************************/
661 static IMG_VOID DBGDrivSetStreamName(PDBG_STREAM psStream,
665 IMG_CHAR* pCh = psStream->szName;
666 IMG_CHAR* pChEnd = psStream->szName+DBG_STREAM_NAME_MAX-8;
670 for (pSrcCh = pszBase, pSrcChEnd = pszBase+strlen(pszBase);
671 (pSrcCh < pSrcChEnd) && (pCh < pChEnd) ;
677 for (pSrcCh = pszExt, pSrcChEnd = pszExt+strlen(pszExt);
678 (pSrcCh < pSrcChEnd) && (pCh < pChEnd) ;
687 /*!****************************************************************************
688 @name DBGDrivCreateStream
689 @brief Creates a pdump/debug stream
690 @param pszName - stream name
691 @param ui32Flags - output flags, text stream bit is set for pdumping
692 @param ui32Size - size of stream buffer in pages
694 *****************************************************************************/
695 IMG_BOOL IMG_CALLCONV DBGDrivCreateStream(IMG_CHAR *pszName,
696 IMG_UINT32 ui32Flags,
700 IMG_HANDLE* phDeinit)
702 IMG_BOOL bUseNonPagedMem4Buffers = ((ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0);
703 PDBG_STREAM psStream = IMG_NULL;
704 PDBG_STREAM psInitStream = IMG_NULL;
705 PDBG_STREAM psStreamDeinit = IMG_NULL;
706 IMG_VOID* pvBase = IMG_NULL;
709 If we already have a buffer using this name just return
712 psStream = (PDBG_STREAM) DBGDrivFindStream(pszName, IMG_FALSE);
715 *phInit = psStream->psInitStream;
717 *phDeinit = psStream->psDeinitStream;
722 Allocate memory for control structures
724 psStream = HostNonPageablePageAlloc(1);
727 PVR_DPF((PVR_DBG_ERROR,"DBGDriv: Couldn't alloc control structs\n\r"));
730 psInitStream = psStream+1;
731 psStreamDeinit = psStream+2;
734 /* Allocate memory for Main buffer */
735 psStream->pvBase = IMG_NULL;
736 if (bUseNonPagedMem4Buffers)
738 pvBase = HostNonPageablePageAlloc(ui32Size);
742 pvBase = HostPageablePageAlloc(ui32Size);
747 PVR_DPF((PVR_DBG_ERROR,"DBGDriv: Couldn't alloc Stream buffer\n\r"));
752 Setup debug buffer state.
754 psStream->psNext = 0;
755 psStream->pvBase = pvBase;
756 psStream->ui32Flags = ui32Flags | DEBUG_FLAGS_CIRCULAR;
757 psStream->ui32Size = ui32Size * HOST_PAGESIZE;
758 psStream->ui32RPtr = 0;
759 psStream->ui32WPtr = 0;
760 psStream->ui32Marker = 0;
761 psStream->ui32InitPhaseWOff = 0;
762 DBGDrivSetStreamName(psStream, pszName, "");
763 PVR_DPF((PVR_DBG_MESSAGE,"DBGDriv: Created stream with deinit name (%s)\n\r", psStream->szName));
765 /* Allocate memory for Init buffer */
766 psInitStream->pvBase = IMG_NULL;
767 if (bUseNonPagedMem4Buffers)
769 pvBase = HostNonPageablePageAlloc(ui32Size);
773 pvBase = HostPageablePageAlloc(ui32Size);
778 PVR_DPF((PVR_DBG_ERROR,"DBGDriv: Couldn't alloc InitStream buffer\n\r"));
782 /* Initialise the stream for the Init phase */
783 psInitStream->psNext = psInitStream->psInitStream = psInitStream->psDeinitStream = IMG_NULL;
784 psInitStream->ui32Flags = ui32Flags;
785 psInitStream->pvBase = pvBase;
786 psInitStream->ui32Size = ui32Size * HOST_PAGESIZE;
787 psInitStream->ui32RPtr = 0;
788 psInitStream->ui32WPtr = 0;
789 psInitStream->ui32Marker = 0;
790 psInitStream->ui32InitPhaseWOff = 0;
791 DBGDrivSetStreamName(psInitStream, pszName, "_Init");
792 PVR_DPF((PVR_DBG_MESSAGE,"DBGDriv: Created stream with init name (%s)\n\r", psInitStream->szName));
793 psStream->psInitStream = psInitStream;
795 /* Allocate memory for Deinit buffer */
796 psStreamDeinit->pvBase = IMG_NULL;
797 if (bUseNonPagedMem4Buffers)
799 pvBase = HostNonPageablePageAlloc(1);
803 pvBase = HostPageablePageAlloc(1);
808 PVR_DPF((PVR_DBG_ERROR,"DBGDriv: Couldn't alloc DeinitStream buffer\n\r"));
812 /* Initialise the stream for the Deinit phase */
813 psStreamDeinit->psNext = psStreamDeinit->psInitStream = psStreamDeinit->psDeinitStream = IMG_NULL;
814 psStreamDeinit->pvBase = pvBase;
815 psStreamDeinit->ui32Flags = ui32Flags;
816 psStreamDeinit->ui32Size = HOST_PAGESIZE;
817 psStreamDeinit->ui32RPtr = 0;
818 psStreamDeinit->ui32WPtr = 0;
819 psStreamDeinit->ui32Marker = 0;
820 psStreamDeinit->ui32InitPhaseWOff = 0;
821 DBGDrivSetStreamName(psStreamDeinit, pszName, "_Deinit");
822 PVR_DPF((PVR_DBG_MESSAGE,"DBGDriv: Created stream with deinit name (%s)\n\r", psStreamDeinit->szName));
824 psStream->psDeinitStream = psStreamDeinit;
829 psStream->psNext = g_psStreamList;
830 g_psStreamList = psStream;
832 AddSIDEntry(psStream);
834 *phInit = psStream->psInitStream;
836 *phDeinit = psStream->psDeinitStream;
841 if (bUseNonPagedMem4Buffers)
843 if (psStream) HostNonPageablePageFree(psStream->pvBase);
844 if (psInitStream) HostNonPageablePageFree(psInitStream->pvBase);
845 if (psStreamDeinit) HostNonPageablePageFree(psStreamDeinit->pvBase);
849 if (psStream) HostPageablePageFree(psStream->pvBase);
850 if (psInitStream) HostPageablePageFree(psInitStream->pvBase);
851 if (psStreamDeinit) HostPageablePageFree(psStreamDeinit->pvBase);
853 HostNonPageablePageFree(psStream);
854 psStream = psInitStream = psStreamDeinit = IMG_NULL;
858 /*!****************************************************************************
859 @name DBGDrivDestroyStream
860 @brief Delete a stream and free its memory
861 @param psStream - stream to be removed
863 *****************************************************************************/
864 IMG_VOID IMG_CALLCONV DBGDrivDestroyStream(IMG_HANDLE hInit,IMG_HANDLE hMain, IMG_HANDLE hDeinit)
866 PDBG_STREAM psStreamInit = (PDBG_STREAM) hInit;
867 PDBG_STREAM psStream = (PDBG_STREAM) hMain;
868 PDBG_STREAM psStreamDeinit = (PDBG_STREAM) hDeinit;
869 PDBG_STREAM psStreamThis;
870 PDBG_STREAM psStreamPrev;
872 PVR_DPF((PVR_DBG_MESSAGE, "DBGDriv: Destroying stream %s\r\n", psStream->szName ));
877 if (!StreamValid(psStream))
882 RemoveSIDEntry(psStream);
885 Remove from linked list.
887 psStreamThis = g_psStreamList;
892 if (psStreamThis == psStream)
896 psStreamPrev->psNext = psStreamThis->psNext;
900 g_psStreamList = psStreamThis->psNext;
907 psStreamPrev = psStreamThis;
908 psStreamThis = psStreamThis->psNext;
915 if ((psStream->ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
917 HostNonPageablePageFree(psStream->pvBase);
918 HostNonPageablePageFree(psStreamInit->pvBase);
919 HostNonPageablePageFree(psStreamDeinit->pvBase);
923 HostPageablePageFree(psStream->pvBase);
924 HostPageablePageFree(psStreamInit->pvBase);
925 HostPageablePageFree(psStreamDeinit->pvBase);
928 /* Free the shared page used for the three stream tuple */
929 HostNonPageablePageFree(psStream);
930 psStream = psStreamInit = psStreamDeinit = IMG_NULL;
932 if (g_psStreamList == 0)
934 PVR_DPF((PVR_DBG_MESSAGE,"DBGDriv: Stream list now empty" ));
940 /*!****************************************************************************
941 @name DBGDrivFindStream
942 @brief Finds/resets a named stream
943 @param pszName - stream name
944 @param bResetStream - whether to reset the stream, e.g. to end pdump init phase
946 *****************************************************************************/
947 IMG_VOID * IMG_CALLCONV DBGDrivFindStream(IMG_CHAR * pszName, IMG_BOOL bResetStream)
949 PDBG_STREAM psStream;
956 PVR_DPF((PVR_DBGDRIV_MESSAGE, "PDump client connecting to %s %s",
958 (bResetStream == IMG_TRUE) ? "with reset" : "no reset"));
961 Scan buffer names for supplied one.
963 for (psThis = g_psStreamList; psThis != IMG_NULL; psThis = psThis->psNext)
968 if (strlen(psThis->szName) == strlen(pszName))
970 while ((ui32Off < DBG_STREAM_NAME_MAX) && (psThis->szName[ui32Off] != 0) && (pszName[ui32Off] != 0) && bAreSame)
972 if (psThis->szName[ui32Off] != pszName[ui32Off])
974 bAreSame = IMG_FALSE;
982 bAreSame = IMG_FALSE;
994 psStream->psInitStream->ui32RPtr = 0;
995 psStream->psDeinitStream->ui32RPtr = 0;
996 psStream->ui32RPtr = 0;
999 /* This will erase any data written to the main stream
1000 * before the client starts. */
1001 psStream->ui32WPtr = 0;
1003 psStream->ui32Marker = psStream->psInitStream->ui32Marker = 0;
1006 /* mark init stream to prevent further reading by pdump client */
1007 /* Check for possible race condition */
1008 psStream->psInitStream->ui32InitPhaseWOff = psStream->psInitStream->ui32WPtr;
1010 PVR_DPF((PVR_DBGDRIV_MESSAGE, "Set %s client marker bo %x",
1012 psStream->psInitStream->ui32InitPhaseWOff));
1015 return((IMG_VOID *) psStream);
1018 static IMG_VOID IMG_CALLCONV DBGDrivInvalidateStream(PDBG_STREAM psStream)
1020 IMG_CHAR pszErrorMsg[] = "**OUTOFMEM\n";
1021 IMG_UINT32 ui32Space;
1022 IMG_UINT32 ui32Off = 0;
1023 IMG_UINT32 ui32WPtr = psStream->ui32WPtr;
1024 IMG_PUINT8 pui8Buffer = (IMG_UINT8 *) psStream->pvBase;
1026 PVR_DPF((PVR_DBG_ERROR, "DBGDrivInvalidateStream: An error occurred for stream %s", psStream->szName ));
1032 if (!StreamValid(psStream))
1037 /* Write what we can of the error message */
1038 ui32Space = SpaceInStream(psStream);
1040 /* Make sure there's space for termination character */
1047 PVR_DPF((PVR_DBG_ERROR, "DBGDrivInvalidateStream: Buffer full."));
1050 while((pszErrorMsg[ui32Off] != 0) && (ui32Off < ui32Space))
1052 pui8Buffer[ui32WPtr] = (IMG_UINT8)pszErrorMsg[ui32Off];
1056 pui8Buffer[ui32WPtr++] = '\0';
1057 psStream->ui32WPtr = ui32WPtr;
1059 /* Buffer will accept no more params from Services/client driver */
1060 psStream->ui32Flags |= DEBUG_FLAGS_READONLY;
1063 /*!****************************************************************************
1064 @name InvalidateAllStreams
1065 @brief invalidate all streams in list
1067 *****************************************************************************/
1068 static IMG_VOID InvalidateAllStreams(IMG_VOID)
1070 PDBG_STREAM psStream = g_psStreamList;
1071 while (psStream != IMG_NULL)
1073 DBGDrivInvalidateStream(psStream);
1074 DBGDrivInvalidateStream(psStream->psInitStream);
1075 DBGDrivInvalidateStream(psStream->psDeinitStream);
1076 psStream = psStream->psNext;
1081 /*!****************************************************************************
1083 @brief Copies data from a buffer into selected (expandable) stream.
1084 @param psStream - stream for output
1085 @param pui8InBuf - input buffer
1086 @param ui32InBuffSize - size of input
1087 @return bytes copied, 0 if recoverable error, -1 if unrecoverable error
1088 *****************************************************************************/
1089 IMG_UINT32 IMG_CALLCONV DBGDrivWrite2(PDBG_STREAM psStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize)
1095 if (!StreamValidForWrite(psStream))
1097 PVR_DPF((PVR_DBG_ERROR, "DBGDrivWrite2: stream not valid"));
1098 return(0xFFFFFFFFUL);
1101 PVR_DPF((PVR_DBGDRIV_MESSAGE, "Recv(exp) %d b for %s: Roff = %x, WOff = %x",
1105 psStream->ui32WPtr));
1107 return( WriteExpandingBuffer(psStream, pui8InBuf, ui32InBuffSize) );
1110 /*!****************************************************************************
1112 @brief Read from debug driver buffers
1113 @param psMainStream - stream
1114 @param ui32BufID - on of the DEBUG_READ_BUFID flags to indicate which buffer
1115 @param ui32OutBuffSize - available space in client buffer
1116 @param pui8OutBuf - output buffer
1117 @return bytes read, 0 if failure occurred
1118 *****************************************************************************/
1119 IMG_UINT32 IMG_CALLCONV DBGDrivRead(PDBG_STREAM psMainStream, IMG_UINT32 ui32BufID, IMG_UINT32 ui32OutBuffSize,IMG_UINT8 * pui8OutBuf)
1121 IMG_UINT32 ui32Data;
1122 DBG_STREAM *psStream;
1127 if (!StreamValidForRead(psMainStream))
1129 PVR_DPF((PVR_DBG_ERROR, "DBGDrivRead: buffer %p is invalid", psMainStream));
1133 if(ui32BufID == DEBUG_READ_BUFID_INIT)
1135 psStream = psMainStream->psInitStream;
1137 else if (ui32BufID == DEBUG_READ_BUFID_DEINIT)
1139 psStream = psMainStream->psDeinitStream;
1143 psStream = psMainStream;
1146 /* Don't read beyond the init phase marker point */
1147 if (psStream->ui32RPtr == psStream->ui32WPtr ||
1148 ((psStream->ui32InitPhaseWOff > 0) &&
1149 (psStream->ui32RPtr >= psStream->ui32InitPhaseWOff)) )
1155 Get amount of data in buffer.
1157 if (psStream->ui32RPtr <= psStream->ui32WPtr)
1159 ui32Data = psStream->ui32WPtr - psStream->ui32RPtr;
1163 ui32Data = psStream->ui32WPtr + (psStream->ui32Size - psStream->ui32RPtr);
1167 Don't read beyond the init phase marker point
1169 if ((psStream->ui32InitPhaseWOff > 0) &&
1170 (psStream->ui32InitPhaseWOff < psStream->ui32WPtr))
1172 ui32Data = psStream->ui32InitPhaseWOff - psStream->ui32RPtr;
1176 Only transfer what target buffer can handle.
1178 if (ui32Data > ui32OutBuffSize)
1180 ui32Data = ui32OutBuffSize;
1183 PVR_DPF((PVR_DBGDRIV_MESSAGE, "Send %x b from %s: Roff = %x, WOff = %x",
1187 psStream->ui32WPtr));
1190 Split copy into two bits or one depending on W/R position.
1192 if ((psStream->ui32RPtr + ui32Data) > psStream->ui32Size)
1193 { /* Calc block 1 and block 2 sizes */
1194 IMG_UINT32 ui32B1 = psStream->ui32Size - psStream->ui32RPtr;
1195 IMG_UINT32 ui32B2 = ui32Data - ui32B1;
1197 /* Copy up to end of circular buffer */
1198 HostMemCopy((IMG_VOID *) pui8OutBuf,
1199 (IMG_VOID *)((IMG_UINTPTR_T)psStream->pvBase + psStream->ui32RPtr),
1202 /* Copy from start of circular buffer */
1203 HostMemCopy((IMG_VOID *)(pui8OutBuf + ui32B1),
1207 /* Update read pointer now that we've copied the data out */
1208 psStream->ui32RPtr = ui32B2;
1211 { /* Copy data from wherever */
1212 HostMemCopy((IMG_VOID *) pui8OutBuf,
1213 (IMG_VOID *)((IMG_UINTPTR_T)psStream->pvBase + psStream->ui32RPtr),
1216 /* Update read pointer now that we've copied the data out */
1217 psStream->ui32RPtr += ui32Data;
1219 /* Check for wrapping */
1220 if ((psStream->ui32RPtr != psStream->ui32WPtr) &&
1221 (psStream->ui32RPtr >= psStream->ui32Size))
1223 psStream->ui32RPtr = 0;
1230 /*!****************************************************************************
1231 @name DBGDrivSetMarker
1232 @brief Sets the marker in the stream to split output files
1233 @param psStream, ui32Marker
1235 *****************************************************************************/
1236 IMG_VOID IMG_CALLCONV DBGDrivSetMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker)
1241 if (!StreamValid(psStream))
1246 /* Called by PDump client to reset the marker to zero after a file split */
1247 if ((ui32Marker == 0) && (psStream->ui32Marker == 0))
1249 PVR_DPF((PVR_DBG_ERROR, "DBGDrivSetMarker: Client resetting marker that is already zero!"));
1251 /* Called by pvrsrvkm to set the marker to signal a file split is required */
1252 if ((ui32Marker != 0) && (psStream->ui32Marker != 0))
1254 /* In this case a previous split request is still outstanding. The
1255 * client has not yet actioned and acknowledged the previous
1256 * marker. This may be an error if the client does not catch-up and
1257 * the stream's written data is allowed to pass the max file
1258 * size again. If this happens the PDump is invalid as the offsets
1259 * from the script file will be incorrect.
1261 PVR_DPF((PVR_DBG_ERROR, "DBGDrivSetMarker: Server setting marker that is already set!"));
1265 PVR_DPF((PVR_DBG_MESSAGE, "DBGDrivSetMarker: Setting stream split marker to %d (was %d)", ui32Marker, psStream->ui32Marker));
1268 psStream->ui32Marker = ui32Marker;
1271 /*!****************************************************************************
1272 @name DBGDrivGetMarker
1273 @brief Gets the marker in the stream to split output files
1274 @param psStream - stream
1275 @return marker offset
1276 *****************************************************************************/
1277 IMG_UINT32 IMG_CALLCONV DBGDrivGetMarker(PDBG_STREAM psStream)
1282 if (!StreamValid(psStream))
1287 return psStream->ui32Marker;
1290 /*!****************************************************************************
1291 @name DBGDrivGetServiceTable
1292 @brief get jump table for Services driver
1293 @return pointer to jump table
1294 *****************************************************************************/
1295 IMG_PVOID IMG_CALLCONV DBGDrivGetServiceTable(IMG_VOID)
1297 return((IMG_PVOID)&g_sDBGKMServices);
1301 #if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
1302 /*!****************************************************************************
1303 @name DBGDrivWaitForEvent
1304 @brief waits for an event
1305 @param eEvent - debug driver event
1307 *****************************************************************************/
1308 IMG_VOID IMG_CALLCONV DBGDrivWaitForEvent(DBG_EVENT eEvent)
1310 HostWaitForEvent(eEvent);
1314 /* Use PVR_DPF() to avoid state messages in release build */
1315 #if defined(PVR_DISABLE_LOGGING) || !defined(DEBUG)
1316 #define PVR_LOG(...)
1319 extern IMG_VOID PVRSRVDebugPrintf(IMG_UINT32 ui32DebugLevel,
1320 const IMG_CHAR* pszFileName,
1321 IMG_UINT32 ui32Line,
1322 const IMG_CHAR* pszFormat,
1324 /* Reproduce the PVR_LOG macro here but direct it to DPF */
1325 #define PVR_LOG(...) PVRSRVDebugPrintf( DBGPRIV_CALLTRACE, __FILE__, __LINE__ , __VA_ARGS__);
1330 /*!****************************************************************************
1331 @name DBGDrivGetCtrlState
1332 @brief Gets a state value from the debug driver or stream
1333 @param psStream - stream
1334 @param ui32StateID - state ID
1336 *****************************************************************************/
1337 IMG_UINT32 IMG_CALLCONV DBGDrivGetCtrlState(PDBG_STREAM psStream, IMG_UINT32 ui32StateID)
1339 /* Validate buffer */
1340 if (!StreamValid(psStream))
1342 return (0xFFFFFFFF);
1345 /* Retrieve the state asked for */
1346 switch (ui32StateID)
1348 case DBG_GET_STATE_FLAG_IS_READONLY:
1349 return ((psStream->ui32Flags & DEBUG_FLAGS_READONLY) != 0);
1352 case 0xFE: /* Dump the current stream state */
1353 PVR_LOG("------ PDUMP DBGDriv: psStream( %p ) ( -- %s -- ) ui32Flags( %x )",
1354 psStream, psStream->szName, psStream->ui32Flags);
1355 PVR_LOG("------ PDUMP DBGDriv: psStream->pvBase( %p ) psStream->ui32Size( %u )",
1356 psStream->pvBase, psStream->ui32Size);
1357 PVR_LOG("------ PDUMP DBGDriv: psStream->ui32RPtr( %u ) psStream->ui32WPtr( %u )",
1358 psStream->ui32RPtr, psStream->ui32WPtr);
1359 PVR_LOG("------ PDUMP DBGDriv: psStream->ui32Marker( %u ) psStream->ui32InitPhaseWOff( %u )",
1360 psStream->ui32Marker, psStream->ui32InitPhaseWOff);
1361 if (psStream->psInitStream)
1363 PVR_LOG("-------- PDUMP DBGDriv: psInitStream( %p ) ( -- %s -- ) ui32Flags( %x )",
1364 psStream->psInitStream, psStream->psInitStream->szName, psStream->ui32Flags);
1365 PVR_LOG("-------- PDUMP DBGDriv: psInitStream->pvBase( %p ) psInitStream->ui32Size( %u )",
1366 psStream->psInitStream->pvBase, psStream->psInitStream->ui32Size);
1367 PVR_LOG("-------- PDUMP DBGDriv: psInitStream->ui32RPtr( %u ) psInitStream->ui32WPtr( %u )",
1368 psStream->psInitStream->ui32RPtr, psStream->psInitStream->ui32WPtr);
1369 PVR_LOG("-------- PDUMP DBGDriv: psInitStream->ui32Marker( %u ) psInitStream->ui32InitPhaseWOff( %u ) ",
1370 psStream->psInitStream->ui32Marker, psStream->psInitStream->ui32InitPhaseWOff);
1375 case 0xFF: /* Dump driver state not in a stream */
1377 PVR_LOG("------ PDUMP DBGDriv: g_psStreamList( head %p ) g_pvAPIMutex( %p ) g_PDumpCurrentFrameNo( %u )", g_psStreamList, g_pvAPIMutex, g_PDumpCurrentFrameNo);
1385 return (0xFFFFFFFF);
1388 IMG_UINT32 IMG_CALLCONV DBGDrivGetFrame(void)
1390 return g_PDumpCurrentFrameNo;
1393 IMG_VOID IMG_CALLCONV DBGDrivSetFrame(IMG_UINT32 ui32Frame)
1395 g_PDumpCurrentFrameNo = ui32Frame;
1399 /*!****************************************************************************
1400 @name ExpandStreamBuffer
1401 @brief allocates a new buffer when the current one is full
1402 @param psStream - stream
1403 @param ui32NewSize - new size
1404 @return IMG_TRUE - if allocation succeeded, IMG_FALSE - if not
1405 *****************************************************************************/
1406 static IMG_BOOL ExpandStreamBuffer(PDBG_STREAM psStream, IMG_UINT32 ui32NewSize)
1408 IMG_VOID * pvNewBuf;
1409 IMG_UINT32 ui32NewSizeInPages;
1410 IMG_UINT32 ui32NewWOffset;
1411 IMG_UINT32 ui32NewROffset;
1412 IMG_UINT32 ui32SpaceInOldBuf;
1415 First check new size is bigger than existing size
1417 if (psStream->ui32Size >= ui32NewSize)
1423 Calc space in old buffer
1425 ui32SpaceInOldBuf = SpaceInStream(psStream);
1430 ui32NewSizeInPages = ((ui32NewSize + 0xfffUL) & ~0xfffUL) / 4096UL;
1432 if ((psStream->ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
1434 pvNewBuf = HostNonPageablePageAlloc(ui32NewSizeInPages);
1438 pvNewBuf = HostPageablePageAlloc(ui32NewSizeInPages);
1441 if (pvNewBuf == IMG_NULL)
1446 if ((psStream->ui32Flags & DEBUG_FLAGS_CIRCULAR) != 0)
1449 Copy over old buffer to new one, we place data at start of buffer
1450 even if Read offset is not at start of buffer
1452 if (psStream->ui32RPtr <= psStream->ui32WPtr)
1455 No wrapping of data so copy data to start of new buffer
1457 HostMemCopy(pvNewBuf,
1458 (IMG_VOID *)((IMG_UINTPTR_T)psStream->pvBase + psStream->ui32RPtr),
1459 psStream->ui32WPtr - psStream->ui32RPtr);
1463 IMG_UINT32 ui32FirstCopySize;
1466 The data has wrapped around the buffer, copy beginning of buffer first
1468 ui32FirstCopySize = psStream->ui32Size - psStream->ui32RPtr;
1470 HostMemCopy(pvNewBuf,
1471 (IMG_VOID *)((IMG_UINTPTR_T)psStream->pvBase + psStream->ui32RPtr),
1477 HostMemCopy((IMG_VOID *)((IMG_UINTPTR_T)pvNewBuf + ui32FirstCopySize),
1478 (IMG_VOID *)(IMG_PBYTE)psStream->pvBase,
1479 psStream->ui32WPtr);
1485 /* Copy everything in the old buffer to the new one */
1486 HostMemCopy(pvNewBuf, psStream->pvBase, psStream->ui32WPtr);
1487 ui32NewROffset = psStream->ui32RPtr;
1491 New Write offset is at end of data
1493 ui32NewWOffset = psStream->ui32Size - ui32SpaceInOldBuf;
1498 if ((psStream->ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
1500 HostNonPageablePageFree(psStream->pvBase);
1504 HostPageablePageFree(psStream->pvBase);
1508 Now set new params up
1510 psStream->pvBase = pvNewBuf;
1511 psStream->ui32RPtr = ui32NewROffset;
1512 psStream->ui32WPtr = ui32NewWOffset;
1513 psStream->ui32Size = ui32NewSizeInPages * 4096;
1518 /*!****************************************************************************
1520 @brief remaining space in stream
1521 @param psStream - stream
1522 @return bytes remaining
1523 *****************************************************************************/
1524 static IMG_UINT32 SpaceInStream(PDBG_STREAM psStream)
1526 IMG_UINT32 ui32Space;
1528 if ((psStream->ui32Flags & DEBUG_FLAGS_CIRCULAR) != 0)
1530 /* Allow overwriting the buffer which was already read */
1531 if (psStream->ui32RPtr > psStream->ui32WPtr)
1533 ui32Space = psStream->ui32RPtr - psStream->ui32WPtr;
1537 ui32Space = psStream->ui32RPtr + (psStream->ui32Size - psStream->ui32WPtr);
1542 /* Don't overwrite anything */
1543 ui32Space = psStream->ui32Size - psStream->ui32WPtr;
1550 /*!****************************************************************************
1551 @name DestroyAllStreams
1552 @brief delete all streams in list
1554 *****************************************************************************/
1555 IMG_VOID DestroyAllStreams(IMG_VOID)
1557 PDBG_STREAM psStream = g_psStreamList;
1558 PDBG_STREAM psStreamToFree;
1560 while (psStream != IMG_NULL)
1562 psStreamToFree = psStream;
1563 psStream = psStream->psNext;
1564 DBGDrivDestroyStream(psStreamToFree->psInitStream, psStreamToFree, psStreamToFree->psDeinitStream);
1566 g_psStreamList = IMG_NULL;
1570 /******************************************************************************
1571 End of file (DBGDRIV.C)
1572 ******************************************************************************/