RK3368 GPU version Rogue M 1.28
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / rogue_m / tools / services / debug / dbgdriv / common / dbgdriv.c
1 /*************************************************************************/ /*!
2 @File
3 @Title          Debug Driver
4 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
5 @Description    32 Bit kernel mode debug driver
6 @License        Dual MIT/GPLv2
7
8 The contents of this file are subject to the MIT license as set out below.
9
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:
16
17 The above copyright notice and this permission notice shall be included in
18 all copies or substantial portions of the Software.
19
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.
23
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.
31
32 This License is also included in this distribution in the file called
33 "MIT-COPYING".
34
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 */ /**************************************************************************/
43
44 #if defined(_WIN32)
45 #pragma  warning(disable:4201)
46 #pragma  warning(disable:4214)
47 #pragma  warning(disable:4115)
48 #pragma  warning(disable:4514)
49
50
51 #include <ntddk.h>
52 #include <windef.h>
53 #include <winerror.h>
54 #endif /* _WIN32 */
55
56 #ifdef LINUX
57 #include <linux/string.h>
58 #endif
59
60 #if defined (__QNXNTO__)
61 #include <string.h>
62 #endif
63
64 #include "img_types.h"
65 #include "img_defs.h"
66 #include "pvr_debug.h"
67 #include "dbgdrvif_srv5.h"
68 #include "dbgdriv.h"
69 #include "hostfunc.h"
70
71 #ifdef _WIN32
72 #pragma  warning(default:4214)
73 #pragma  warning(default:4115)
74 #endif /* _WIN32 */
75
76
77 /******************************************************************************
78  Types
79 ******************************************************************************/
80
81 #define DBG_STREAM_NAME_MAX             30
82
83 /*
84         Per-buffer control structure.
85 */
86 typedef struct _DBG_STREAM_
87 {
88         struct _DBG_STREAM_* psNext;
89         struct _DBG_STREAM_* psInitStream;
90         struct _DBG_STREAM_* psDeinitStream;
91         IMG_UINT32 ui32Flags;                   /*!< flags (see DEBUG_FLAGS) */
92         IMG_PVOID  pvBase;
93         IMG_UINT32 ui32Size;
94         IMG_UINT32 ui32RPtr;
95         IMG_UINT32 ui32WPtr;
96
97         IMG_UINT32 ui32Marker;                  /*!< Size marker for file splitting */
98
99         IMG_UINT32 ui32InitPhaseWOff;   /*!< snapshot offset for init phase end for follow-on pdump */
100
101         IMG_CHAR   szName[DBG_STREAM_NAME_MAX];                 /* Give this a size, some compilers don't like [] */
102 } DBG_STREAM;
103
104 /* Check 4xDBG_STREAM will fit in one page */
105 BLD_ASSERT(sizeof(DBG_STREAM)<<2<HOST_PAGESIZE,dbgdriv_c)
106
107 /******************************************************************************
108  Global variables
109 ******************************************************************************/
110
111 static PDBG_STREAM          g_psStreamList = 0;
112
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.
116  */
117 IMG_VOID *                  g_pvAPIMutex=IMG_NULL;
118
119 static IMG_UINT32                       g_PDumpCurrentFrameNo = 0;
120
121 DBGKM_SERVICE_TABLE g_sDBGKMServices =
122 {
123         sizeof (DBGKM_SERVICE_TABLE),
124         ExtDBGDrivCreateStream,
125         ExtDBGDrivDestroyStream,
126         ExtDBGDrivWrite2,
127         ExtDBGDrivSetMarker,
128         ExtDBGDrivWaitForEvent,
129         ExtDBGDrivGetCtrlState,
130         ExtDBGDrivSetFrame
131 };
132
133
134 /***************************************************************************
135  Forward declarations
136 ***************************************************************************/
137
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);
151
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);
156
157
158 /*****************************************************************************
159  Code
160 *****************************************************************************/
161
162 /*!
163  @name  ExtDBGDrivCreateStream
164  */
165 IMG_BOOL IMG_CALLCONV ExtDBGDrivCreateStream(IMG_CHAR *pszName, IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size, IMG_HANDLE* phInit, IMG_HANDLE* phMain, IMG_HANDLE* phDeinit)
166 {
167         IMG_BOOL pvRet;
168
169         /* Aquire API Mutex */
170         HostAquireMutex(g_pvAPIMutex);
171
172         pvRet=DBGDrivCreateStream(pszName, ui32Flags, ui32Size, phInit, phMain, phDeinit);
173
174         /* Release API Mutex */
175         HostReleaseMutex(g_pvAPIMutex);
176
177         return pvRet;
178 }
179
180 /*!
181  @name  ExtDBGDrivDestroyStream
182  */
183 IMG_VOID IMG_CALLCONV ExtDBGDrivDestroyStream(IMG_HANDLE hInit,IMG_HANDLE hMain, IMG_HANDLE hDeinit)
184 {
185         /* Aquire API Mutex */
186         HostAquireMutex(g_pvAPIMutex);
187
188         DBGDrivDestroyStream(hInit, hMain, hDeinit);
189
190         /* Release API Mutex */
191         HostReleaseMutex(g_pvAPIMutex);
192
193         return;
194 }
195
196 /*!
197  @name  ExtDBGDrivFindStream
198  */
199 IMG_VOID * IMG_CALLCONV ExtDBGDrivFindStream(IMG_CHAR * pszName, IMG_BOOL bResetStream)
200 {
201         IMG_VOID *      pvRet;
202
203         /* Aquire API Mutex */
204         HostAquireMutex(g_pvAPIMutex);
205
206         pvRet=DBGDrivFindStream(pszName, bResetStream);
207         if (pvRet == IMG_NULL)
208         {
209                 PVR_DPF((PVR_DBG_ERROR, "ExtDBGDrivFindStream: Stream not found"));
210         }
211
212
213         /* Release API Mutex */
214         HostReleaseMutex(g_pvAPIMutex);
215
216         return pvRet;
217 }
218
219 /*!
220  @name  ExtDBGDrivRead
221  */
222 IMG_UINT32 IMG_CALLCONV ExtDBGDrivRead(PDBG_STREAM psStream, IMG_UINT32 ui32BufID, IMG_UINT32 ui32OutBuffSize,IMG_UINT8 * pui8OutBuf)
223 {
224         IMG_UINT32 ui32Ret;
225
226         /* Aquire API Mutex */
227         HostAquireMutex(g_pvAPIMutex);
228
229         ui32Ret=DBGDrivRead(psStream, ui32BufID, ui32OutBuffSize, pui8OutBuf);
230
231         /* Release API Mutex */
232         HostReleaseMutex(g_pvAPIMutex);
233
234         return ui32Ret;
235 }
236
237 /*!
238  @name  ExtDBGDrivWrite2
239  */
240 IMG_UINT32 IMG_CALLCONV ExtDBGDrivWrite2(PDBG_STREAM psStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize)
241 {
242         IMG_UINT32      ui32Ret;
243
244         /* Aquire API Mutex */
245         HostAquireMutex(g_pvAPIMutex);
246
247         ui32Ret=DBGDrivWrite2(psStream, pui8InBuf, ui32InBuffSize);
248
249         /* Release API Mutex */
250         HostReleaseMutex(g_pvAPIMutex);
251
252         return ui32Ret;
253 }
254
255 /*!
256  @name  ExtDBGDrivSetMarker
257  */
258 IMG_VOID IMG_CALLCONV ExtDBGDrivSetMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker)
259 {
260         /* Aquire API Mutex */
261         HostAquireMutex(g_pvAPIMutex);
262
263         DBGDrivSetMarker(psStream, ui32Marker);
264
265         /* Release API Mutex */
266         HostReleaseMutex(g_pvAPIMutex);
267
268         return;
269 }
270
271 /*!
272  @name  ExtDBGDrivGetMarker
273  */
274 IMG_UINT32 IMG_CALLCONV ExtDBGDrivGetMarker(PDBG_STREAM psStream)
275 {
276         IMG_UINT32      ui32Marker;
277
278         /* Aquire API Mutex */
279         HostAquireMutex(g_pvAPIMutex);
280
281         ui32Marker = DBGDrivGetMarker(psStream);
282
283         /* Release API Mutex */
284         HostReleaseMutex(g_pvAPIMutex);
285
286         return ui32Marker;
287 }
288
289 /*!
290  @name  ExtDBGDrivWaitForEvent
291  */
292 IMG_VOID IMG_CALLCONV ExtDBGDrivWaitForEvent(DBG_EVENT eEvent)
293 {
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) */
299 }
300
301
302 /*!
303  @name  ExtDBGDrivGetCtrlState
304  */
305 IMG_UINT32 IMG_CALLCONV ExtDBGDrivGetCtrlState(PDBG_STREAM psStream, IMG_UINT32 ui32StateID)
306 {
307         IMG_UINT32 ui32State = 0;
308
309         /* Aquire API Mutex */
310         HostAquireMutex(g_pvAPIMutex);
311
312         ui32State = DBGDrivGetCtrlState(psStream, ui32StateID);
313
314         /* Release API Mutex */
315         HostReleaseMutex(g_pvAPIMutex);
316
317         return ui32State;
318 }
319
320 /*!
321  @name  ExtDBGDrivGetFrame
322  */
323 IMG_UINT32 IMG_CALLCONV ExtDBGDrivGetFrame(void)
324 {
325         IMG_UINT32 ui32Frame = 0;
326
327         /* Aquire API Mutex */
328         HostAquireMutex(g_pvAPIMutex);
329
330         ui32Frame = DBGDrivGetFrame();
331
332         /* Release API Mutex */
333         HostReleaseMutex(g_pvAPIMutex);
334
335         return ui32Frame;
336 }
337
338 /*!
339  @name  ExtDBGDrivGetCtrlState
340  */
341 IMG_VOID IMG_CALLCONV ExtDBGDrivSetFrame(IMG_UINT32 ui32Frame)
342 {
343         /* Aquire API Mutex */
344         HostAquireMutex(g_pvAPIMutex);
345
346         DBGDrivSetFrame(ui32Frame);
347
348         /* Release API Mutex */
349         HostReleaseMutex(g_pvAPIMutex);
350
351         return;
352 }
353
354
355
356 /*!****************************************************************************
357  @name          AtoI
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)
364 {
365         IMG_INT         iLen = 0;
366         IMG_UINT32      ui32Value = 0;
367         IMG_UINT32      ui32Digit=1;
368         IMG_UINT32      ui32Base=10;
369         IMG_INT         iPos;
370         IMG_CHAR        bc;
371
372         //get len of string
373         while (szIn[iLen] > 0)
374         {
375                 iLen ++;
376         }
377
378         //nothing to do
379         if (iLen == 0)
380         {
381                 return (0);
382         }
383
384         /* See if we have an 'x' or 'X' before the number to make it a hex number */
385         iPos=0;
386         while (szIn[iPos] == '0')
387         {
388                 iPos++;
389         }
390         if (szIn[iPos] == '\0')
391         {
392                 return 0;
393         }
394         if (szIn[iPos] == 'x' || szIn[iPos] == 'X')
395         {
396                 ui32Base=16;
397                 szIn[iPos]='0';
398         }
399
400         //go through string from right (least significant) to left
401         for (iPos = iLen - 1; iPos >= 0; iPos --)
402         {
403                 bc = szIn[iPos];
404
405                 if ( (bc >= 'a') && (bc <= 'f') && ui32Base == 16)                      //handle lower case a-f
406                 {
407                         bc -= 'a' - 0xa;
408                 }
409                 else
410                 if ( (bc >= 'A') && (bc <= 'F') && ui32Base == 16)                      //handle upper case A-F
411                 {
412                         bc -= 'A' - 0xa;
413                 }
414                 else
415                 if ((bc >= '0') && (bc <= '9'))                         //if char out of range, return 0
416                 {
417                         bc -= '0';
418                 }
419                 else
420                         return (0);
421
422                 ui32Value += (IMG_UINT32)bc  * ui32Digit;
423
424                 ui32Digit = ui32Digit * ui32Base;
425         }
426         return (ui32Value);
427 }
428
429
430 /*!****************************************************************************
431  @name          StreamValid
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)
437 {
438         PDBG_STREAM     psThis;
439
440         psThis = g_psStreamList;
441
442         while (psThis)
443         {
444                 if (psStream && ((psThis == psStream) ||
445                                                 (psThis->psInitStream == psStream) ||
446                                                 (psThis->psDeinitStream == psStream)) )
447                 {
448                         return(IMG_TRUE);
449                 }
450                 else
451                 {
452                         psThis = psThis->psNext;
453                 }
454         }
455
456         return(IMG_FALSE);
457 }
458
459
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)
467 {
468         if( StreamValid(psStream) &&
469                 ((psStream->ui32Flags & DEBUG_FLAGS_WRITEONLY) == 0) )
470         {
471                 return(IMG_TRUE);
472         }
473
474         return(IMG_FALSE);
475 }
476
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)
484 {
485         if( StreamValid(psStream) &&
486                 ((psStream->ui32Flags & DEBUG_FLAGS_READONLY) == 0) )
487         {
488                 return(IMG_TRUE);
489         }
490
491         return(IMG_FALSE);
492 }
493
494 /*!****************************************************************************
495  @name          Write
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
500  @return        none
501 *****************************************************************************/
502 static IMG_VOID Write(PDBG_STREAM psStream,IMG_PUINT8 pui8Data,IMG_UINT32 ui32InBuffSize)
503 {
504         /*
505                 Split copy into two bits as necessary (if we're allowed to wrap).
506         */
507         if ((psStream->ui32Flags & DEBUG_FLAGS_CIRCULAR) == 0)
508         {
509                 PVR_ASSERT( (psStream->ui32WPtr + ui32InBuffSize) < psStream->ui32Size );
510         }
511
512         if ((psStream->ui32WPtr + ui32InBuffSize) > psStream->ui32Size)
513         {
514                 /* Yes we need two bits, calculate their sizes */
515                 IMG_UINT32 ui32B1 = psStream->ui32Size - psStream->ui32WPtr;
516                 IMG_UINT32 ui32B2 = ui32InBuffSize - ui32B1;
517
518                 /* Copy first block to current location */
519                 HostMemCopy((IMG_PVOID)((IMG_UINTPTR_T)psStream->pvBase + psStream->ui32WPtr),
520                                 (IMG_PVOID) pui8Data,
521                                 ui32B1);
522
523                 /* Copy second block to start of buffer */
524                 HostMemCopy(psStream->pvBase,
525                                 (IMG_PVOID)(pui8Data + ui32B1),
526                                 ui32B2);
527
528                 /* Set pointer to be the new end point */
529                 psStream->ui32WPtr = ui32B2;
530         }
531         else
532         {       /* Can fit block in single chunk */
533                 HostMemCopy((IMG_PVOID)((IMG_UINTPTR_T)psStream->pvBase + psStream->ui32WPtr),
534                                 (IMG_PVOID) pui8Data,
535                                 ui32InBuffSize);
536
537                 psStream->ui32WPtr += ui32InBuffSize;
538
539                 if (psStream->ui32WPtr == psStream->ui32Size)
540                 {
541                         psStream->ui32WPtr = 0;
542                 }
543         }
544 }
545
546
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
553  @return        bytes copied
554 *****************************************************************************/
555 static IMG_UINT32 WriteExpandingBuffer(PDBG_STREAM psStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize)
556 {
557         IMG_UINT ui32Space;
558
559         /*
560                 How much space have we got in the buffer ?
561         */
562         ui32Space = SpaceInStream(psStream);
563
564         /*
565                 Check if we can expand the buffer 
566         */
567         if (psStream->ui32Flags & DEBUG_FLAGS_NO_BUF_EXPANDSION)
568         {
569                 /*
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...
572                 */
573                 if (ui32Space < 32)
574                 {
575                         PVR_DPF((PVR_DBG_ERROR, "WriteExpandingBuffer: buffer %p is full and isn't expandable", psStream));
576                         return(0);
577                 }
578         }
579         else
580         {
581                 if ((ui32Space < 32) || (ui32Space <= (ui32InBuffSize + 4)))
582                 {
583                         IMG_UINT32      ui32NewBufSize;
584
585                         /*
586                                 Find new buffer size, double the current size or increase by 1MB
587                         */
588                         ui32NewBufSize = MIN(psStream->ui32Size<<1,psStream->ui32Size+(1<<20));
589                         ui32NewBufSize = MIN(ui32NewBufSize, (PDUMP_STREAMBUF_MAX_SIZE_MB<<20));
590
591                         PVR_DPF((PVR_DBGDRIV_MESSAGE, "Expanding buffer size = %x, new size = %x",
592                                         psStream->ui32Size, ui32NewBufSize));
593
594                         if (ui32InBuffSize > psStream->ui32Size)
595                         {
596                                 ui32NewBufSize += ui32InBuffSize;
597                                 PVR_DPF((PVR_DBG_ERROR, "WriteExpandingBuffer: buffer %p is expanding by size of input buffer %u", psStream, ui32NewBufSize));
598                         }
599
600                         /* 
601                                 Attempt to expand the buffer 
602                         */
603                         if ((ui32NewBufSize < psStream->ui32Size) ||
604                                         !ExpandStreamBuffer(psStream,ui32NewBufSize))
605                         {
606                                 if (ui32Space < 32)
607                                 {
608                                         if((psStream->ui32Flags & DEBUG_FLAGS_CIRCULAR) != 0)
609                                         {
610                                                 return(0);
611                                         }
612                                         else
613                                         {
614                                                 /* out of memory */
615                                                 PVR_DPF((PVR_DBG_ERROR, "WriteExpandingBuffer: Unable to expand %p. Out of memory.", psStream));
616                                                 InvalidateAllStreams();
617                                                 return (0xFFFFFFFFUL);
618                                         }
619                                 }
620                         }
621
622                         /* 
623                                 Recalc the space in the buffer 
624                         */
625                         ui32Space = SpaceInStream(psStream);
626                         PVR_DPF((PVR_DBGDRIV_MESSAGE, "Expanded buffer, free space = %x",
627                                         ui32Space));
628                 }
629         }
630
631         /*
632                 Only copy what we can..
633         */
634         if (ui32Space <= (ui32InBuffSize + 4))
635         {
636                 ui32InBuffSize = ui32Space - 4;
637         }
638
639         /*
640                 Write the stuff...
641         */
642         Write(psStream,pui8InBuf,ui32InBuffSize);
643
644 #if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
645         if (ui32InBuffSize)
646         {
647                 HostSignalEvent(DBG_EVENT_STREAM_DATA);
648         }
649 #endif
650         return(ui32InBuffSize);
651 }
652
653 /*****************************************************************************
654 ******************************************************************************
655 ******************************************************************************
656  THE ACTUAL FUNCTIONS
657 ******************************************************************************
658 ******************************************************************************
659 *****************************************************************************/
660
661 static IMG_VOID DBGDrivSetStreamName(PDBG_STREAM psStream,
662                                                                          IMG_CHAR* pszBase,
663                                                                          IMG_CHAR* pszExt)
664 {
665         IMG_CHAR* pCh = psStream->szName;
666         IMG_CHAR* pChEnd = psStream->szName+DBG_STREAM_NAME_MAX-8;
667         IMG_CHAR* pSrcCh;
668         IMG_CHAR* pSrcChEnd;
669
670         for (pSrcCh = pszBase, pSrcChEnd = pszBase+strlen(pszBase);
671                         (pSrcCh < pSrcChEnd) && (pCh < pChEnd) ;
672                         pSrcCh++, pCh++)
673         {
674                 *pCh = *pSrcCh;
675         }
676
677         for (pSrcCh = pszExt, pSrcChEnd = pszExt+strlen(pszExt);
678                         (pSrcCh < pSrcChEnd) && (pCh < pChEnd) ;
679                         pSrcCh++, pCh++)
680         {
681                 *pCh = *pSrcCh;
682         }
683
684         *pCh = '\0';
685 }
686
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
693  @return        none
694 *****************************************************************************/
695 IMG_BOOL IMG_CALLCONV DBGDrivCreateStream(IMG_CHAR *pszName,
696                                           IMG_UINT32 ui32Flags,
697                                           IMG_UINT32 ui32Size,
698                                           IMG_HANDLE* phInit,
699                                           IMG_HANDLE* phMain,
700                                           IMG_HANDLE* phDeinit)
701 {
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;
707
708         /*
709                 If we already have a buffer using this name just return
710                 its handle.
711         */
712         psStream = (PDBG_STREAM) DBGDrivFindStream(pszName, IMG_FALSE);
713         if (psStream)
714         {
715                 *phInit = psStream->psInitStream;
716                 *phMain = psStream;
717                 *phDeinit = psStream->psDeinitStream;
718                 return IMG_TRUE;
719         }
720
721         /*
722                 Allocate memory for control structures
723         */
724         psStream = HostNonPageablePageAlloc(1);
725         if      (!psStream)
726         {
727                 PVR_DPF((PVR_DBG_ERROR,"DBGDriv: Couldn't alloc control structs\n\r"));
728                 goto errCleanup;
729         }
730         psInitStream = psStream+1;
731         psStreamDeinit = psStream+2;
732
733
734         /* Allocate memory for Main buffer */
735         psStream->pvBase = IMG_NULL;
736         if (bUseNonPagedMem4Buffers)
737         {
738                 pvBase = HostNonPageablePageAlloc(ui32Size);
739         }
740         else
741         {
742                 pvBase = HostPageablePageAlloc(ui32Size);
743         }
744
745         if (!pvBase)
746         {
747                 PVR_DPF((PVR_DBG_ERROR,"DBGDriv: Couldn't alloc Stream buffer\n\r"));
748                 goto errCleanup;
749         }
750
751         /*
752                 Setup debug buffer state.
753         */
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));
764
765         /* Allocate memory for Init buffer */
766         psInitStream->pvBase = IMG_NULL;
767         if (bUseNonPagedMem4Buffers)
768         {
769                 pvBase = HostNonPageablePageAlloc(ui32Size);
770         }
771         else
772         {
773                 pvBase = HostPageablePageAlloc(ui32Size);
774         }
775
776         if (!pvBase)
777         {
778                 PVR_DPF((PVR_DBG_ERROR,"DBGDriv: Couldn't alloc InitStream buffer\n\r"));
779                 goto errCleanup;
780         }
781
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;
794
795         /* Allocate memory for Deinit buffer */
796         psStreamDeinit->pvBase = IMG_NULL;
797         if (bUseNonPagedMem4Buffers)
798         {
799                 pvBase = HostNonPageablePageAlloc(1);
800         }
801         else
802         {
803                 pvBase = HostPageablePageAlloc(1);
804         }
805
806         if (!pvBase)
807         {
808                 PVR_DPF((PVR_DBG_ERROR,"DBGDriv: Couldn't alloc DeinitStream buffer\n\r"));
809                 goto errCleanup;
810         }
811
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));
823
824         psStream->psDeinitStream = psStreamDeinit;
825
826         /*
827                 Insert into list.
828         */
829         psStream->psNext = g_psStreamList;
830         g_psStreamList = psStream;
831
832         AddSIDEntry(psStream);
833         
834         *phInit = psStream->psInitStream;
835         *phMain = psStream;
836         *phDeinit = psStream->psDeinitStream;
837
838         return IMG_TRUE;
839
840 errCleanup:
841         if (bUseNonPagedMem4Buffers)
842         {
843                 if (psStream) HostNonPageablePageFree(psStream->pvBase);
844                 if (psInitStream) HostNonPageablePageFree(psInitStream->pvBase);
845                 if (psStreamDeinit) HostNonPageablePageFree(psStreamDeinit->pvBase);
846         }
847         else
848         {
849                 if (psStream) HostPageablePageFree(psStream->pvBase);
850                 if (psInitStream) HostPageablePageFree(psInitStream->pvBase);
851                 if (psStreamDeinit) HostPageablePageFree(psStreamDeinit->pvBase);
852         }
853         HostNonPageablePageFree(psStream);
854         psStream = psInitStream = psStreamDeinit = IMG_NULL;
855         return IMG_FALSE;
856 }
857
858 /*!****************************************************************************
859  @name          DBGDrivDestroyStream
860  @brief         Delete a stream and free its memory
861  @param         psStream - stream to be removed
862  @return        none
863 *****************************************************************************/
864 IMG_VOID IMG_CALLCONV DBGDrivDestroyStream(IMG_HANDLE hInit,IMG_HANDLE hMain, IMG_HANDLE hDeinit)
865 {
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;
871
872         PVR_DPF((PVR_DBG_MESSAGE, "DBGDriv: Destroying stream %s\r\n", psStream->szName ));
873
874         /*
875                 Validate buffer.
876         */
877         if (!StreamValid(psStream))
878         {
879                 return;
880         }
881
882         RemoveSIDEntry(psStream);
883         
884         /*
885                 Remove from linked list.
886         */
887         psStreamThis = g_psStreamList;
888         psStreamPrev = 0;
889
890         while (psStreamThis)
891         {
892                 if (psStreamThis == psStream)
893                 {
894                         if (psStreamPrev)
895                         {
896                                 psStreamPrev->psNext = psStreamThis->psNext;
897                         }
898                         else
899                         {
900                                 g_psStreamList = psStreamThis->psNext;
901                         }
902
903                         psStreamThis = 0;
904                 }
905                 else
906                 {
907                         psStreamPrev = psStreamThis;
908                         psStreamThis = psStreamThis->psNext;
909                 }
910         }
911
912         /*
913                 And free its memory.
914         */
915         if ((psStream->ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
916         {
917                 HostNonPageablePageFree(psStream->pvBase);
918                 HostNonPageablePageFree(psStreamInit->pvBase);
919                 HostNonPageablePageFree(psStreamDeinit->pvBase);
920         }
921         else
922         {
923                 HostPageablePageFree(psStream->pvBase);
924                 HostPageablePageFree(psStreamInit->pvBase);
925                 HostPageablePageFree(psStreamDeinit->pvBase);
926         }
927
928         /* Free the shared page used for the three stream tuple */
929         HostNonPageablePageFree(psStream);
930         psStream = psStreamInit = psStreamDeinit = IMG_NULL;
931
932         if (g_psStreamList == 0)
933         {
934                 PVR_DPF((PVR_DBG_MESSAGE,"DBGDriv: Stream list now empty" ));
935         }
936
937         return;
938 }
939
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
945  @return        none
946 *****************************************************************************/
947 IMG_VOID * IMG_CALLCONV DBGDrivFindStream(IMG_CHAR * pszName, IMG_BOOL bResetStream)
948 {
949         PDBG_STREAM     psStream;
950         PDBG_STREAM     psThis;
951         IMG_UINT32      ui32Off;
952         IMG_BOOL        bAreSame;
953
954         psStream = 0;
955
956         PVR_DPF((PVR_DBGDRIV_MESSAGE, "PDump client connecting to %s %s",
957                         pszName,
958                         (bResetStream == IMG_TRUE) ? "with reset" : "no reset"));
959
960         /*
961                 Scan buffer names for supplied one.
962         */
963         for (psThis = g_psStreamList; psThis != IMG_NULL; psThis = psThis->psNext)
964         {
965                 bAreSame = IMG_TRUE;
966                 ui32Off = 0;
967
968                 if (strlen(psThis->szName) == strlen(pszName))
969                 {
970                         while ((ui32Off < DBG_STREAM_NAME_MAX) && (psThis->szName[ui32Off] != 0) && (pszName[ui32Off] != 0) && bAreSame)
971                         {
972                                 if (psThis->szName[ui32Off] != pszName[ui32Off])
973                                 {
974                                         bAreSame = IMG_FALSE;
975                                 }
976
977                                 ui32Off++;
978                         }
979                 }
980                 else
981                 {
982                         bAreSame = IMG_FALSE;
983                 }
984
985                 if (bAreSame)
986                 {
987                         psStream = psThis;
988                         break;
989                 }
990         }
991
992         if(psStream)
993         {
994                 psStream->psInitStream->ui32RPtr = 0;
995                 psStream->psDeinitStream->ui32RPtr = 0;
996                 psStream->ui32RPtr = 0;
997                 if (bResetStream)
998                 {
999                         /* This will erase any data written to the main stream 
1000                          * before the client starts. */
1001                         psStream->ui32WPtr = 0;
1002                 }
1003                 psStream->ui32Marker = psStream->psInitStream->ui32Marker = 0;
1004
1005
1006                 /* mark init stream to prevent further reading by pdump client */
1007                 /* Check for possible race condition */
1008                 psStream->psInitStream->ui32InitPhaseWOff = psStream->psInitStream->ui32WPtr;
1009
1010                 PVR_DPF((PVR_DBGDRIV_MESSAGE, "Set %s client marker bo %x",
1011                                 psStream->szName,
1012                                 psStream->psInitStream->ui32InitPhaseWOff));
1013         }
1014
1015         return((IMG_VOID *) psStream);
1016 }
1017
1018 static IMG_VOID IMG_CALLCONV DBGDrivInvalidateStream(PDBG_STREAM psStream)
1019 {
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;
1025         
1026         PVR_DPF((PVR_DBG_ERROR, "DBGDrivInvalidateStream: An error occurred for stream %s", psStream->szName ));
1027
1028         /*
1029                 Validate buffer.
1030         */
1031         /*
1032         if (!StreamValid(psStream))
1033         {
1034                 return;
1035         }
1036 */
1037         /* Write what we can of the error message */
1038         ui32Space = SpaceInStream(psStream);
1039
1040         /* Make sure there's space for termination character */
1041         if(ui32Space > 0)
1042         {
1043                 ui32Space--;
1044         }
1045         else
1046         {
1047                 PVR_DPF((PVR_DBG_ERROR, "DBGDrivInvalidateStream: Buffer full."));
1048         }
1049
1050         while((pszErrorMsg[ui32Off] != 0) && (ui32Off < ui32Space))
1051         {
1052                 pui8Buffer[ui32WPtr] = (IMG_UINT8)pszErrorMsg[ui32Off];
1053                 ui32Off++;
1054                 ui32WPtr++;
1055         }
1056         pui8Buffer[ui32WPtr++] = '\0';
1057         psStream->ui32WPtr = ui32WPtr;
1058
1059         /* Buffer will accept no more params from Services/client driver */
1060         psStream->ui32Flags |= DEBUG_FLAGS_READONLY;
1061 }
1062
1063 /*!****************************************************************************
1064  @name          InvalidateAllStreams
1065  @brief         invalidate all streams in list
1066  @return        none
1067 *****************************************************************************/
1068 static IMG_VOID InvalidateAllStreams(IMG_VOID)
1069 {
1070         PDBG_STREAM psStream = g_psStreamList;
1071         while (psStream != IMG_NULL)
1072         {
1073                 DBGDrivInvalidateStream(psStream);
1074                 DBGDrivInvalidateStream(psStream->psInitStream);
1075                 DBGDrivInvalidateStream(psStream->psDeinitStream);
1076                 psStream = psStream->psNext;
1077         }
1078         return;
1079 }
1080
1081 /*!****************************************************************************
1082  @name          DBGDrivWrite2
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)
1090 {
1091
1092         /*
1093                 Validate buffer.
1094         */
1095         if (!StreamValidForWrite(psStream))
1096         {
1097                 PVR_DPF((PVR_DBG_ERROR, "DBGDrivWrite2: stream not valid"));
1098                 return(0xFFFFFFFFUL);
1099         }
1100
1101         PVR_DPF((PVR_DBGDRIV_MESSAGE, "Recv(exp) %d b for %s: Roff = %x, WOff = %x",
1102                         ui32InBuffSize,
1103                         psStream->szName,
1104                         psStream->ui32RPtr,
1105                         psStream->ui32WPtr));
1106
1107         return( WriteExpandingBuffer(psStream, pui8InBuf, ui32InBuffSize) );
1108 }
1109
1110 /*!****************************************************************************
1111  @name          DBGDrivRead
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)
1120 {
1121         IMG_UINT32 ui32Data;
1122         DBG_STREAM *psStream;
1123
1124         /*
1125                 Validate buffer.
1126         */
1127         if (!StreamValidForRead(psMainStream))
1128         {
1129                 PVR_DPF((PVR_DBG_ERROR, "DBGDrivRead: buffer %p is invalid", psMainStream));
1130                 return(0);
1131         }
1132
1133         if(ui32BufID == DEBUG_READ_BUFID_INIT)
1134         {
1135                 psStream = psMainStream->psInitStream;
1136         }
1137         else if (ui32BufID == DEBUG_READ_BUFID_DEINIT)
1138         {
1139                 psStream = psMainStream->psDeinitStream;
1140         }
1141         else
1142         {
1143                 psStream = psMainStream;
1144         }
1145
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)) )
1150         {
1151                 return(0);
1152         }
1153
1154         /*
1155                 Get amount of data in buffer.
1156         */
1157         if (psStream->ui32RPtr <= psStream->ui32WPtr)
1158         {
1159                 ui32Data = psStream->ui32WPtr - psStream->ui32RPtr;
1160         }
1161         else
1162         {
1163                 ui32Data = psStream->ui32WPtr + (psStream->ui32Size - psStream->ui32RPtr);
1164         }
1165
1166         /*
1167                 Don't read beyond the init phase marker point
1168         */
1169         if ((psStream->ui32InitPhaseWOff > 0) &&
1170                 (psStream->ui32InitPhaseWOff < psStream->ui32WPtr))
1171         {
1172                 ui32Data = psStream->ui32InitPhaseWOff - psStream->ui32RPtr;
1173         }
1174
1175         /*
1176                 Only transfer what target buffer can handle.
1177         */
1178         if (ui32Data > ui32OutBuffSize)
1179         {
1180                 ui32Data = ui32OutBuffSize;
1181         }
1182
1183         PVR_DPF((PVR_DBGDRIV_MESSAGE, "Send %x b from %s: Roff = %x, WOff = %x",
1184                         ui32Data,
1185                         psStream->szName,
1186                         psStream->ui32RPtr,
1187                         psStream->ui32WPtr));
1188
1189         /*
1190                 Split copy into two bits or one depending on W/R position.
1191         */
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;
1196
1197                 /* Copy up to end of circular buffer */
1198                 HostMemCopy((IMG_VOID *) pui8OutBuf,
1199                                 (IMG_VOID *)((IMG_UINTPTR_T)psStream->pvBase + psStream->ui32RPtr),
1200                                 ui32B1);
1201
1202                 /* Copy from start of circular buffer */
1203                 HostMemCopy((IMG_VOID *)(pui8OutBuf + ui32B1),
1204                                 psStream->pvBase,
1205                                 ui32B2);
1206
1207                 /* Update read pointer now that we've copied the data out */
1208                 psStream->ui32RPtr = ui32B2;
1209         }
1210         else
1211         {       /* Copy data from wherever */
1212                 HostMemCopy((IMG_VOID *) pui8OutBuf,
1213                                 (IMG_VOID *)((IMG_UINTPTR_T)psStream->pvBase + psStream->ui32RPtr),
1214                                 ui32Data);
1215
1216                 /* Update read pointer now that we've copied the data out */
1217                 psStream->ui32RPtr += ui32Data;
1218
1219                 /* Check for wrapping */
1220                 if ((psStream->ui32RPtr != psStream->ui32WPtr) &&
1221                         (psStream->ui32RPtr >= psStream->ui32Size))
1222                 {
1223                         psStream->ui32RPtr = 0;
1224                 }
1225         }
1226
1227         return(ui32Data);
1228 }
1229
1230 /*!****************************************************************************
1231  @name          DBGDrivSetMarker
1232  @brief         Sets the marker in the stream to split output files
1233  @param         psStream, ui32Marker
1234  @return        nothing
1235 *****************************************************************************/
1236 IMG_VOID IMG_CALLCONV DBGDrivSetMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker)
1237 {
1238         /*
1239                 Validate buffer
1240         */
1241         if (!StreamValid(psStream))
1242         {
1243                 return;
1244         }
1245
1246         /* Called by PDump client to reset the marker to zero after a file split */
1247         if ((ui32Marker == 0) && (psStream->ui32Marker == 0))
1248         {
1249                 PVR_DPF((PVR_DBG_ERROR, "DBGDrivSetMarker: Client resetting marker that is already zero!"));
1250         }
1251         /* Called by pvrsrvkm to set the marker to signal a file split is required */
1252         if ((ui32Marker != 0) && (psStream->ui32Marker != 0))
1253         {
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.
1260                  */
1261                 PVR_DPF((PVR_DBG_ERROR, "DBGDrivSetMarker: Server setting marker that is already set!"));
1262         }
1263         else
1264         {
1265                 PVR_DPF((PVR_DBG_MESSAGE, "DBGDrivSetMarker: Setting stream split marker to %d (was %d)", ui32Marker, psStream->ui32Marker));
1266         }
1267
1268         psStream->ui32Marker = ui32Marker;
1269 }
1270
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)
1278 {
1279         /*
1280                 Validate buffer
1281         */
1282         if (!StreamValid(psStream))
1283         {
1284                 return 0;
1285         }
1286
1287         return psStream->ui32Marker;
1288 }
1289
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)
1296 {
1297         return((IMG_PVOID)&g_sDBGKMServices);
1298 }
1299
1300
1301 #if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
1302 /*!****************************************************************************
1303  @name          DBGDrivWaitForEvent
1304  @brief         waits for an event
1305  @param         eEvent - debug driver event
1306  @return        IMG_VOID
1307 *****************************************************************************/
1308 IMG_VOID IMG_CALLCONV DBGDrivWaitForEvent(DBG_EVENT eEvent)
1309 {
1310         HostWaitForEvent(eEvent);
1311 }
1312 #endif
1313
1314 /*      Use PVR_DPF() to avoid state messages in release build */
1315 #if defined(PVR_DISABLE_LOGGING) || !defined(DEBUG)
1316 #define PVR_LOG(...)
1317 #else
1318
1319 extern IMG_VOID PVRSRVDebugPrintf(IMG_UINT32    ui32DebugLevel,
1320                                                 const IMG_CHAR* pszFileName,
1321                                                 IMG_UINT32      ui32Line,
1322                                                 const IMG_CHAR* pszFormat,
1323                                                 ...     );
1324 /* Reproduce the PVR_LOG macro here but direct it to DPF */
1325 #define PVR_LOG(...)    PVRSRVDebugPrintf( DBGPRIV_CALLTRACE, __FILE__, __LINE__ , __VA_ARGS__);
1326
1327 #endif
1328
1329
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
1335  @return        Nothing
1336 *****************************************************************************/
1337 IMG_UINT32 IMG_CALLCONV DBGDrivGetCtrlState(PDBG_STREAM psStream, IMG_UINT32 ui32StateID)
1338 {
1339         /* Validate buffer */
1340         if (!StreamValid(psStream))
1341         {
1342                 return (0xFFFFFFFF);
1343         }
1344
1345         /* Retrieve the state asked for */
1346         switch (ui32StateID)
1347         {
1348         case DBG_GET_STATE_FLAG_IS_READONLY:
1349                 return ((psStream->ui32Flags & DEBUG_FLAGS_READONLY) != 0);
1350                 break;
1351
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)
1362                 {
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);
1371                 }
1372
1373                 break;
1374
1375         case 0xFF: /* Dump driver state not in a stream */
1376                 {
1377                         PVR_LOG("------ PDUMP DBGDriv: g_psStreamList( head %p ) g_pvAPIMutex( %p ) g_PDumpCurrentFrameNo( %u )", g_psStreamList, g_pvAPIMutex, g_PDumpCurrentFrameNo);
1378                 }
1379                 break;
1380
1381         default:
1382                 PVR_ASSERT(0);
1383         }
1384
1385         return (0xFFFFFFFF);
1386 }
1387
1388 IMG_UINT32 IMG_CALLCONV DBGDrivGetFrame(void)
1389 {
1390         return g_PDumpCurrentFrameNo;
1391 }
1392
1393 IMG_VOID IMG_CALLCONV DBGDrivSetFrame(IMG_UINT32 ui32Frame)
1394 {
1395         g_PDumpCurrentFrameNo = ui32Frame;
1396 }
1397
1398
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)
1407 {
1408         IMG_VOID *      pvNewBuf;
1409         IMG_UINT32      ui32NewSizeInPages;
1410         IMG_UINT32      ui32NewWOffset;
1411         IMG_UINT32      ui32NewROffset;
1412         IMG_UINT32      ui32SpaceInOldBuf;
1413
1414         /* 
1415                 First check new size is bigger than existing size 
1416         */
1417         if (psStream->ui32Size >= ui32NewSize)
1418         {
1419                 return IMG_FALSE;
1420         }
1421
1422         /*
1423                 Calc space in old buffer 
1424         */
1425         ui32SpaceInOldBuf = SpaceInStream(psStream);
1426
1427         /*
1428                 Allocate new buffer 
1429         */
1430         ui32NewSizeInPages = ((ui32NewSize + 0xfffUL) & ~0xfffUL) / 4096UL;
1431
1432         if ((psStream->ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
1433         {
1434                 pvNewBuf = HostNonPageablePageAlloc(ui32NewSizeInPages);
1435         }
1436         else
1437         {
1438                 pvNewBuf = HostPageablePageAlloc(ui32NewSizeInPages);
1439         }
1440
1441         if (pvNewBuf == IMG_NULL)
1442         {
1443                 return IMG_FALSE;
1444         }
1445
1446         if ((psStream->ui32Flags & DEBUG_FLAGS_CIRCULAR) != 0)
1447         {
1448                 /*
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
1451                 */
1452                 if (psStream->ui32RPtr <= psStream->ui32WPtr)
1453                 {
1454                         /*
1455                                 No wrapping of data so copy data to start of new buffer 
1456                         */
1457                 HostMemCopy(pvNewBuf,
1458                                         (IMG_VOID *)((IMG_UINTPTR_T)psStream->pvBase + psStream->ui32RPtr),
1459                                         psStream->ui32WPtr - psStream->ui32RPtr);
1460                 }
1461                 else
1462                 {
1463                         IMG_UINT32      ui32FirstCopySize;
1464         
1465                         /*
1466                                 The data has wrapped around the buffer, copy beginning of buffer first 
1467                         */
1468                         ui32FirstCopySize = psStream->ui32Size - psStream->ui32RPtr;
1469         
1470                         HostMemCopy(pvNewBuf,
1471                                         (IMG_VOID *)((IMG_UINTPTR_T)psStream->pvBase + psStream->ui32RPtr),
1472                                         ui32FirstCopySize);
1473         
1474                         /*
1475                                 Now second half 
1476                         */
1477                         HostMemCopy((IMG_VOID *)((IMG_UINTPTR_T)pvNewBuf + ui32FirstCopySize),
1478                                         (IMG_VOID *)(IMG_PBYTE)psStream->pvBase,
1479                                         psStream->ui32WPtr);
1480                 }
1481                 ui32NewROffset = 0;
1482         }
1483         else
1484         {
1485                 /* Copy everything in the old buffer to the new one */
1486                 HostMemCopy(pvNewBuf, psStream->pvBase, psStream->ui32WPtr);
1487                 ui32NewROffset = psStream->ui32RPtr;
1488         }
1489
1490         /*
1491                 New Write offset is at end of data 
1492         */                                                        
1493         ui32NewWOffset = psStream->ui32Size - ui32SpaceInOldBuf;
1494
1495         /*
1496                 Free old buffer 
1497         */
1498         if ((psStream->ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
1499         {
1500                 HostNonPageablePageFree(psStream->pvBase);
1501         }
1502         else
1503         {
1504                 HostPageablePageFree(psStream->pvBase);
1505         }
1506
1507         /*
1508                 Now set new params up 
1509         */
1510         psStream->pvBase = pvNewBuf;
1511         psStream->ui32RPtr = ui32NewROffset;
1512         psStream->ui32WPtr = ui32NewWOffset;
1513         psStream->ui32Size = ui32NewSizeInPages * 4096;
1514
1515         return IMG_TRUE;
1516 }
1517
1518 /*!****************************************************************************
1519  @name          SpaceInStream
1520  @brief         remaining space in stream
1521  @param         psStream - stream
1522  @return        bytes remaining
1523 *****************************************************************************/
1524 static IMG_UINT32 SpaceInStream(PDBG_STREAM psStream)
1525 {
1526         IMG_UINT32      ui32Space;
1527
1528         if ((psStream->ui32Flags & DEBUG_FLAGS_CIRCULAR) != 0)
1529         {
1530                 /* Allow overwriting the buffer which was already read */
1531                 if (psStream->ui32RPtr > psStream->ui32WPtr)
1532                 {
1533                         ui32Space = psStream->ui32RPtr - psStream->ui32WPtr;
1534                 }
1535                 else
1536                 {
1537                         ui32Space = psStream->ui32RPtr + (psStream->ui32Size - psStream->ui32WPtr);
1538                 }
1539         }
1540         else
1541         {
1542                 /* Don't overwrite anything */
1543                 ui32Space = psStream->ui32Size - psStream->ui32WPtr;
1544         }
1545
1546         return ui32Space;
1547 }
1548
1549
1550 /*!****************************************************************************
1551  @name          DestroyAllStreams
1552  @brief         delete all streams in list
1553  @return        none
1554 *****************************************************************************/
1555 IMG_VOID DestroyAllStreams(IMG_VOID)
1556 {
1557         PDBG_STREAM psStream = g_psStreamList;
1558         PDBG_STREAM psStreamToFree;
1559
1560         while (psStream != IMG_NULL)
1561         {
1562                 psStreamToFree = psStream;
1563                 psStream = psStream->psNext;
1564                 DBGDrivDestroyStream(psStreamToFree->psInitStream, psStreamToFree, psStreamToFree->psDeinitStream);
1565         }
1566         g_psStreamList = IMG_NULL;
1567         return;
1568 }
1569
1570 /******************************************************************************
1571  End of file (DBGDRIV.C)
1572 ******************************************************************************/