57f1fc719d1c377169bb0d01a0a1cdd0a765c04e
[sgx.git] / pvr / pdump.c
1 /**********************************************************************
2  *
3  * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms and conditions of the GNU General Public License,
7  * version 2, as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope it will be useful but, except
10  * as otherwise stated in writing, without any warranty; without even the
11  * implied warranty of merchantability or fitness for a particular purpose.
12  * See the GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
17  *
18  * The full GNU General Public License is included in this distribution in
19  * the file called "COPYING".
20  *
21  * Contact Information:
22  * Imagination Technologies Ltd. <gpl-support@imgtec.com>
23  * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
24  *
25  ******************************************************************************/
26
27 #if defined(PDUMP)
28 #include <asm/atomic.h>
29 #include <stdarg.h>
30 #include "sgxdefs.h"
31 #include "services_headers.h"
32
33 #include "pvrversion.h"
34 #include "pvr_debug.h"
35
36 #include "sgxmmu.h"
37 #include "mm.h"
38 #include "pdump_km.h"
39
40 #include <linux/tty.h>
41
42 #define DEBUG_CAPMODE_FRAMED            0x00000001
43 #define DEBUG_CAPMODE_CONTINUOUS        0x00000002
44 #define DEBUG_CAPMODE_HOTKEY            0x00000004
45 #define DEBUG_CAPMODE_POSTMORTEM        0x00000008
46
47 #define DEBUG_OUTMODE_STREAMENABLE      0x00000004
48
49 struct DBG_STREAM {
50         u32 ui32CapMode;
51         u32 ui32Start;
52         u32 ui32End;
53         IMG_BOOL bInitPhaseComplete;
54 };
55
56 #define MIN(a, b)                               (a > b ? b : a)
57
58 static atomic_t gsPDumpSuspended = ATOMIC_INIT(0);
59
60 #define PDUMP_STREAM_PARAM2                     0
61 #define PDUMP_STREAM_SCRIPT2                    1
62 #define PDUMP_NUM_STREAMS                       2
63
64 static char *pszStreamName[PDUMP_NUM_STREAMS] = { "ParamStream2",
65         "ScriptStream2"
66 };
67
68 static struct DBG_STREAM *gpsStream[PDUMP_NUM_STREAMS] = {NULL};
69
70 #define SZ_COMMENT_SIZE_MAX             PVRSRV_PDUMP_MAX_COMMENT_SIZE
71 #define SZ_SCRIPT_SIZE_MAX              (SZ_COMMENT_SIZE_MAX + 5)
72 #define SZ_FILENAME_SIZE_MAX            SZ_COMMENT_SIZE_MAX
73 static char *gpszComment;
74 static char *gpszScript;
75 static char *gpszFile;
76
77 void PDumpSuspendKM(void)
78 {
79         atomic_inc(&gsPDumpSuspended);
80 }
81
82 void PDumpResumeKM(void)
83 {
84         atomic_dec(&gsPDumpSuspended);
85 }
86
87 static inline IMG_BOOL PDumpSuspended(void)
88 {
89         return atomic_read(&gsPDumpSuspended) != 0;
90 }
91
92 /*
93  * empty pdump backend.
94  */
95 static void *
96 DbgDrvCreateStream(char *pszName, u32 ui32CapMode, u32 ui32OutMode,
97                    u32 ui32Flags, u32 ui32Pages)
98 {
99         return NULL;
100 }
101
102 static void
103 DbgDrvDestroyStream(struct DBG_STREAM *psStream)
104 {
105
106 }
107
108 static void
109 DbgDrvSetCaptureMode(struct DBG_STREAM *psStream, u32 ui32CapMode,
110                      u32 ui32Start, u32 ui32Stop, u32 ui32SampleRate)
111 {
112
113 }
114
115 static void
116 DbgDrvSetFrame(struct DBG_STREAM *psStream, u32 ui32Frame)
117 {
118
119 }
120
121 static void
122 DbgDrvDBGDrivWrite2(struct DBG_STREAM *psStream, u8 *pui8InBuf,
123                     u32 ui32InBuffSize, u32 ui32Level)
124 {
125
126 }
127
128 static void
129 DbgDrvWriteBINCM(struct DBG_STREAM *psStream, u8 *pui8InBuf,
130                  u32 ui32InBuffSize, u32 ui32Level)
131 {
132
133 }
134
135 static u32
136 DbgDrvIsCaptureFrame(struct DBG_STREAM *psStream, IMG_BOOL bCheckPreviousFrame)
137 {
138         return 1;
139 }
140
141 static u32
142 DbgDrvGetStreamOffset(struct DBG_STREAM *psStream)
143 {
144         return 0;
145 }
146
147 static enum PVRSRV_ERROR
148 pdump_write(struct DBG_STREAM *psStream, u8 *pui8Data, u32 ui32Count,
149             u32 ui32Flags)
150 {
151         if (!psStream) /* will always hit with the empty backend. */
152                 return PVRSRV_OK;
153
154         if (PDumpSuspended() || (ui32Flags & PDUMP_FLAGS_NEVER))
155                 return PVRSRV_OK;
156
157         if (ui32Flags & PDUMP_FLAGS_CONTINUOUS) {
158                 if ((psStream->ui32CapMode & DEBUG_CAPMODE_FRAMED) &&
159                     (psStream->ui32Start == 0xFFFFFFFF) &&
160                     (psStream->ui32End == 0xFFFFFFFF) &&
161                     psStream->bInitPhaseComplete)
162                         return PVRSRV_OK;
163                 else
164                         DbgDrvDBGDrivWrite2(psStream, pui8Data,
165                                             ui32Count, 1);
166         } else
167                 DbgDrvWriteBINCM(psStream, pui8Data, ui32Count, 1);
168
169         /* placeholder, will get proper error handling later. */
170         return PVRSRV_OK;
171 }
172
173 static void
174 pdump_print(u32 flags, char *pszFormat, ...)
175 {
176         va_list ap;
177
178         if (PDumpSuspended())
179                 return;
180
181         va_start(ap, pszFormat);
182         vsnprintf(gpszScript, SZ_SCRIPT_SIZE_MAX, pszFormat, ap);
183         va_end(ap);
184
185         (void) pdump_write(gpsStream[PDUMP_STREAM_SCRIPT2],
186                            (u8 *)gpszScript, strlen(gpszScript), flags);
187 }
188
189 void PDumpCommentKM(char *pszComment, u32 ui32Flags)
190 {
191         int len;
192
193         if (PDumpSuspended())
194                 return;
195
196         len = strlen(pszComment);
197
198         if ((len > 1) && (pszComment[len - 1] == '\n'))
199                 pszComment[len - 1] = 0;
200
201         if ((len > 2) && (pszComment[len - 2] == '\r'))
202                 pszComment[len - 2] = 0;
203
204         pdump_print(ui32Flags, "-- %s\r\n", pszComment);
205 }
206
207 void PDumpComment(char *pszFormat, ...)
208 {
209         va_list ap;
210
211         if (PDumpSuspended())
212                 return;
213
214         va_start(ap, pszFormat);
215         vsnprintf(gpszComment, SZ_COMMENT_SIZE_MAX, pszFormat, ap);
216         va_end(ap);
217
218         PDumpCommentKM(gpszComment, PDUMP_FLAGS_CONTINUOUS);
219 }
220
221 void PDumpCommentWithFlags(u32 ui32Flags, char *pszFormat, ...)
222 {
223         va_list ap;
224
225         if (PDumpSuspended())
226                 return;
227
228         va_start(ap, pszFormat);
229         vsnprintf(gpszComment, SZ_COMMENT_SIZE_MAX, pszFormat, ap);
230         va_end(ap);
231
232         PDumpCommentKM(gpszComment, ui32Flags);
233 }
234
235 void PDumpSetFrameKM(u32 ui32Frame)
236 {
237         u32 ui32Stream;
238
239         for (ui32Stream = 0; ui32Stream < PDUMP_NUM_STREAMS; ui32Stream++)
240                 if (gpsStream[ui32Stream])
241                         DbgDrvSetFrame(gpsStream[ui32Stream], ui32Frame);
242 }
243
244 IMG_BOOL PDumpIsCaptureFrameKM(void)
245 {
246         if (PDumpSuspended())
247                 return IMG_FALSE;
248         return DbgDrvIsCaptureFrame(gpsStream[PDUMP_STREAM_SCRIPT2],
249                                     IMG_FALSE);
250 }
251
252 void PDumpInit(void)
253 {
254         u32 i = 0;
255
256         if (!gpszFile)
257                 if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
258                                SZ_FILENAME_SIZE_MAX,
259                                (void **)&gpszFile,
260                                NULL) != PVRSRV_OK)
261                         goto init_failed;
262
263         if (!gpszComment)
264                 if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
265                                SZ_COMMENT_SIZE_MAX,
266                                (void **)&gpszComment,
267                                NULL) != PVRSRV_OK)
268                         goto init_failed;
269
270         if (!gpszScript)
271                 if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
272                                SZ_SCRIPT_SIZE_MAX,
273                                (void **)&gpszScript,
274                                NULL) != PVRSRV_OK)
275                         goto init_failed;
276
277         for (i = 0; i < PDUMP_NUM_STREAMS; i++) {
278                 gpsStream[i] =
279                         DbgDrvCreateStream(pszStreamName[i],
280                                            DEBUG_CAPMODE_FRAMED,
281                                            DEBUG_OUTMODE_STREAMENABLE,
282                                            0, 10);
283
284                 DbgDrvSetCaptureMode(gpsStream[i],
285                                      DEBUG_CAPMODE_FRAMED,
286                                      0xFFFFFFFF, 0xFFFFFFFF, 1);
287                 DbgDrvSetFrame(gpsStream[i], 0);
288         }
289
290         PDumpComment("Driver Product Name: %s", VS_PRODUCT_NAME);
291         PDumpComment("Driver Product Version: %s (%s)",
292                      PVRVERSION_STRING, PVRVERSION_FILE);
293         PDumpComment("Start of Init Phase");
294
295         return;
296
297  init_failed:
298
299         if (gpszFile) {
300                 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_FILENAME_SIZE_MAX,
301                           (void *)gpszFile, NULL);
302                 gpszFile = NULL;
303         }
304
305         if (gpszScript) {
306                 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_SCRIPT_SIZE_MAX,
307                           (void *)gpszScript, NULL);
308                 gpszScript = NULL;
309         }
310
311         if (gpszComment) {
312                 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_COMMENT_SIZE_MAX,
313                           (void *)gpszComment, NULL);
314                 gpszComment = NULL;
315         }
316 }
317
318 void PDumpDeInit(void)
319 {
320         u32 i = 0;
321
322         for (i = 0; i < PDUMP_NUM_STREAMS; i++)
323                 DbgDrvDestroyStream(gpsStream[i]);
324
325         if (gpszFile) {
326                 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_FILENAME_SIZE_MAX,
327                           (void *)gpszFile, NULL);
328                 gpszFile = NULL;
329         }
330
331         if (gpszScript) {
332                 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_SCRIPT_SIZE_MAX,
333                           (void *)gpszScript, NULL);
334                 gpszScript = NULL;
335         }
336
337         if (gpszComment) {
338                 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_COMMENT_SIZE_MAX,
339                           (void *)gpszComment, NULL);
340                 gpszComment = NULL;
341         }
342 }
343
344 void PDumpRegWithFlagsKM(u32 ui32Reg, u32 ui32Data, u32 ui32Flags)
345 {
346         if (PDumpSuspended())
347                 return;
348
349         pdump_print(ui32Flags,
350                     "WRW :SGXREG:0x%8.8X 0x%8.8X\r\n", ui32Reg, ui32Data);
351 }
352
353 void PDumpReg(u32 ui32Reg, u32 ui32Data)
354 {
355         if (PDumpSuspended())
356                 return;
357
358         pdump_print(PDUMP_FLAGS_CONTINUOUS,
359                     "WRW :SGXREG:0x%8.8X 0x%8.8X\r\n", ui32Reg, ui32Data);
360 }
361
362 void PDumpRegPolWithFlagsKM(u32 ui32RegAddr, u32 ui32RegValue,
363                             u32 ui32Mask, u32 ui32Flags)
364 {
365 #define POLL_DELAY              1000
366 #define POLL_COUNT_LONG         (2000000000 / POLL_DELAY)
367 #define POLL_COUNT_SHORT        (1000000 / POLL_DELAY)
368
369         u32 ui32PollCount;
370
371         if (PDumpSuspended())
372                 return;
373
374         if (((ui32RegAddr == EUR_CR_EVENT_STATUS) &&
375              (ui32RegValue & ui32Mask &
376               EUR_CR_EVENT_STATUS_TA_FINISHED_MASK)) ||
377             ((ui32RegAddr == EUR_CR_EVENT_STATUS) &&
378              (ui32RegValue & ui32Mask &
379               EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_MASK)) ||
380             ((ui32RegAddr == EUR_CR_EVENT_STATUS) &&
381               (ui32RegValue & ui32Mask &
382                EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_MASK)))
383                 ui32PollCount = POLL_COUNT_LONG;
384         else
385                 ui32PollCount = POLL_COUNT_SHORT;
386
387         pdump_print(ui32Flags,
388                     "POL :SGXREG:0x%8.8X 0x%8.8X 0x%8.8X %d %u %d\r\n",
389                     ui32RegAddr, ui32RegValue, ui32Mask, 0, ui32PollCount,
390                     POLL_DELAY);
391 }
392
393 void PDumpRegPolKM(u32 ui32RegAddr, u32 ui32RegValue, u32 ui32Mask)
394 {
395         PDumpRegPolWithFlagsKM(ui32RegAddr, ui32RegValue, ui32Mask,
396                                PDUMP_FLAGS_CONTINUOUS);
397 }
398
399 void PDumpMallocPages(enum PVRSRV_DEVICE_TYPE eDeviceType, u32 ui32DevVAddr,
400                       void *pvLinAddr, void *hOSMemHandle, u32 ui32NumBytes,
401                       u32 ui32PageSize, void *hUniqueTag)
402 {
403         u32 ui32Offset;
404         u32 ui32NumPages;
405         struct IMG_CPU_PHYADDR sCpuPAddr;
406         struct IMG_DEV_PHYADDR sDevPAddr;
407         u32 ui32Page;
408
409         if (PDumpSuspended())
410                 return;
411
412         PVR_UNREFERENCED_PARAMETER(pvLinAddr);
413
414         PVR_ASSERT(((u32) ui32DevVAddr & (ui32PageSize - 1)) == 0);
415         PVR_ASSERT(hOSMemHandle);
416         PVR_ASSERT(((u32) ui32NumBytes & (ui32PageSize - 1)) == 0);
417
418         PDumpComment("MALLOC :SGXMEM:VA_%8.8X 0x%8.8X %u\r\n",
419                      ui32DevVAddr, ui32NumBytes, ui32PageSize);
420
421         ui32Offset = 0;
422         ui32NumPages = ui32NumBytes / ui32PageSize;
423         while (ui32NumPages--) {
424                 sCpuPAddr = OSMemHandleToCpuPAddr(hOSMemHandle, ui32Offset);
425                 PVR_ASSERT((sCpuPAddr.uiAddr & (ui32PageSize - 1)) == 0);
426                 ui32Offset += ui32PageSize;
427                 sDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr);
428                 ui32Page = sDevPAddr.uiAddr / ui32PageSize;
429
430                 pdump_print(PDUMP_FLAGS_CONTINUOUS,
431                             "MALLOC :SGXMEM:PA_%8.8X%8.8X %u %u 0x%8.8X\r\n",
432                             (u32)hUniqueTag, ui32Page * ui32PageSize,
433                             ui32PageSize, ui32PageSize,
434                             ui32Page * ui32PageSize);
435         }
436 }
437
438 void PDumpMallocPageTable(enum PVRSRV_DEVICE_TYPE eDeviceType,
439                           void *pvLinAddr, u32 ui32PTSize, void *hUniqueTag)
440 {
441         u8 *pui8LinAddr;
442         u32 ui32NumPages;
443         struct IMG_CPU_PHYADDR sCpuPAddr;
444         struct IMG_DEV_PHYADDR sDevPAddr;
445         u32 ui32Page;
446
447         if (PDumpSuspended())
448                 return;
449
450         PVR_ASSERT(((u32) pvLinAddr & (ui32PTSize - 1)) == 0);
451
452         PDumpComment("MALLOC :SGXMEM:PAGE_TABLE 0x%8.8X %lu\r\n",
453                      ui32PTSize, SGX_MMU_PAGE_SIZE);
454
455         pui8LinAddr = (u8 *) pvLinAddr;
456
457         ui32NumPages = 1;
458
459         while (ui32NumPages--) {
460                 sCpuPAddr = OSMapLinToCPUPhys(pui8LinAddr);
461                 sDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr);
462                 ui32Page = sDevPAddr.uiAddr >> SGX_MMU_PAGE_SHIFT;
463
464                 pdump_print(PDUMP_FLAGS_CONTINUOUS, "MALLOC "
465                             ":SGXMEM:PA_%8.8X%8.8lX 0x%lX %lu 0x%8.8lX\r\n",
466                             (u32)hUniqueTag,
467                             ui32Page * SGX_MMU_PAGE_SIZE, SGX_MMU_PAGE_SIZE,
468                             SGX_MMU_PAGE_SIZE, ui32Page * SGX_MMU_PAGE_SIZE);
469
470                 pui8LinAddr += SGX_MMU_PAGE_SIZE;
471         }
472 }
473
474 void PDumpFreePages(struct BM_HEAP *psBMHeap, struct IMG_DEV_VIRTADDR sDevVAddr,
475                     u32 ui32NumBytes, u32 ui32PageSize, void *hUniqueTag,
476                     IMG_BOOL bInterleaved)
477 {
478         u32 ui32NumPages, ui32PageCounter;
479         struct IMG_DEV_PHYADDR sDevPAddr;
480         struct PVRSRV_DEVICE_NODE *psDeviceNode;
481
482         if (PDumpSuspended())
483                 return;
484
485         PVR_ASSERT(((u32) sDevVAddr.uiAddr & (ui32PageSize - 1)) == 0);
486         PVR_ASSERT(((u32) ui32NumBytes & (ui32PageSize - 1)) == 0);
487
488         PDumpComment("FREE :SGXMEM:VA_%8.8X\r\n", sDevVAddr.uiAddr);
489
490         ui32NumPages = ui32NumBytes / ui32PageSize;
491         psDeviceNode = psBMHeap->pBMContext->psDeviceNode;
492         for (ui32PageCounter = 0; ui32PageCounter < ui32NumPages;
493              ui32PageCounter++) {
494                 if (!bInterleaved || (ui32PageCounter % 2) == 0) {
495                         sDevPAddr =
496                             psDeviceNode->pfnMMUGetPhysPageAddr(psBMHeap->
497                                                                 pMMUHeap,
498                                                                 sDevVAddr);
499                         pdump_print(PDUMP_FLAGS_CONTINUOUS,
500                                     "FREE :SGXMEM:PA_%8.8X%8.8X\r\n",
501                                     (u32)hUniqueTag, sDevPAddr.uiAddr);
502                 } else {
503
504                 }
505
506                 sDevVAddr.uiAddr += ui32PageSize;
507         }
508 }
509
510 void PDumpFreePageTable(enum PVRSRV_DEVICE_TYPE eDeviceType,
511                         void *pvLinAddr, u32 ui32PTSize, void *hUniqueTag)
512 {
513         u8 *pui8LinAddr;
514         u32 ui32NumPages;
515         struct IMG_CPU_PHYADDR sCpuPAddr;
516         struct IMG_DEV_PHYADDR sDevPAddr;
517         u32 ui32Page;
518
519         if (PDumpSuspended())
520                 return;
521
522         PVR_ASSERT(((u32) pvLinAddr & (ui32PTSize - 1)) == 0);
523
524         PDumpComment("FREE :SGXMEM:PAGE_TABLE\r\n");
525
526         pui8LinAddr = (u8 *) pvLinAddr;
527
528         ui32NumPages = 1;
529
530         while (ui32NumPages--) {
531                 sCpuPAddr = OSMapLinToCPUPhys(pui8LinAddr);
532                 sDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr);
533                 ui32Page = sDevPAddr.uiAddr >> SGX_MMU_PAGE_SHIFT;
534                 pui8LinAddr += SGX_MMU_PAGE_SIZE;
535
536                 pdump_print(PDUMP_FLAGS_CONTINUOUS,
537                             "FREE :SGXMEM:PA_%8.8X%8.8lX\r\n", (u32)hUniqueTag,
538                             ui32Page * SGX_MMU_PAGE_SIZE);
539         }
540 }
541
542 void PDumpPDReg(u32 ui32Reg, u32 ui32Data, void *hUniqueTag)
543 {
544         if (PDumpSuspended())
545                 return;
546
547         pdump_print(PDUMP_FLAGS_CONTINUOUS,
548                     "WRW :SGXREG:0x%8.8X :SGXMEM:PA_%8.8X%8.8lX:0x%8.8lX\r\n",
549                     ui32Reg, (u32)hUniqueTag,
550                     ui32Data & ~(SGX_MMU_PAGE_SIZE - 1),
551                     ui32Data & (SGX_MMU_PAGE_SIZE - 1));
552 }
553
554 void PDumpPDRegWithFlags(u32 ui32Reg, u32 ui32Data, u32 ui32Flags,
555                          void *hUniqueTag)
556 {
557         if (PDumpSuspended())
558                 return;
559
560         pdump_print(ui32Flags,
561                     "WRW :SGXREG:0x%8.8X :SGXMEM:PA_%8.8X%8.8lX:0x%8.8lX\r\n",
562                     ui32Reg, (u32)hUniqueTag,
563                     ui32Data & ~(SGX_MMU_PAGE_SIZE - 1),
564                     ui32Data & (SGX_MMU_PAGE_SIZE - 1));
565 }
566
567 void PDumpMemPolKM(struct PVRSRV_KERNEL_MEM_INFO *psMemInfo,
568                    u32 ui32Offset, u32 ui32Value, u32 ui32Mask,
569                    enum PDUMP_POLL_OPERATOR eOperator, void *hUniqueTag)
570 {
571 #define MEMPOLL_DELAY           (1000)
572 #define MEMPOLL_COUNT           (2000000000 / MEMPOLL_DELAY)
573
574         u32 ui32PageOffset;
575         struct IMG_DEV_PHYADDR sDevPAddr;
576         struct IMG_DEV_VIRTADDR sDevVPageAddr;
577         struct IMG_CPU_PHYADDR CpuPAddr;
578
579         if (PDumpSuspended())
580                 return;
581
582         PVR_ASSERT((ui32Offset + sizeof(u32)) <=
583                    psMemInfo->ui32AllocSize);
584
585         CpuPAddr =
586             OSMemHandleToCpuPAddr(psMemInfo->sMemBlk.hOSMemHandle, ui32Offset);
587         ui32PageOffset = CpuPAddr.uiAddr & (PAGE_SIZE - 1);
588
589         sDevVPageAddr.uiAddr =
590             psMemInfo->sDevVAddr.uiAddr + ui32Offset - ui32PageOffset;
591
592         BM_GetPhysPageAddr(psMemInfo, sDevVPageAddr, &sDevPAddr);
593
594         sDevPAddr.uiAddr += ui32PageOffset;
595
596         pdump_print(0, "POL :SGXMEM:PA_%8.8X%8.8lX:0x%8.8lX 0x%8.8X "
597                     "0x%8.8X %d %d %d\r\n", (u32)hUniqueTag,
598                     sDevPAddr.uiAddr & ~(SGX_MMU_PAGE_SIZE - 1),
599                     sDevPAddr.uiAddr & (SGX_MMU_PAGE_SIZE - 1),
600                     ui32Value, ui32Mask, eOperator,
601                     MEMPOLL_COUNT, MEMPOLL_DELAY);
602 }
603
604 enum PVRSRV_ERROR
605 PDumpMemKM(void *pvAltLinAddr, struct PVRSRV_KERNEL_MEM_INFO *psMemInfo,
606            u32 ui32Offset, u32 ui32Bytes, u32 ui32Flags, void *hUniqueTag)
607 {
608         u32 ui32PageByteOffset;
609         u8 *pui8DataLinAddr = NULL;
610         struct IMG_DEV_VIRTADDR sDevVPageAddr;
611         struct IMG_DEV_VIRTADDR sDevVAddr;
612         struct IMG_DEV_PHYADDR sDevPAddr;
613         struct IMG_CPU_PHYADDR CpuPAddr;
614         u32 ui32ParamOutPos;
615         u32 ui32CurrentOffset;
616         u32 ui32BytesRemaining;
617         enum PVRSRV_ERROR eError;
618
619         if (PDumpSuspended())
620                 return PVRSRV_OK;
621
622         PVR_ASSERT((ui32Offset + ui32Bytes) <= psMemInfo->ui32AllocSize);
623
624         if (ui32Bytes == 0)
625                 return PVRSRV_ERROR_GENERIC;
626
627         if (pvAltLinAddr) {
628                 pui8DataLinAddr = pvAltLinAddr;
629         } else {
630                 if (psMemInfo->pvLinAddrKM)
631                         pui8DataLinAddr =
632                             (u8 *) psMemInfo->pvLinAddrKM + ui32Offset;
633
634         }
635
636         PVR_ASSERT(pui8DataLinAddr);
637
638         ui32ParamOutPos =
639             DbgDrvGetStreamOffset(gpsStream[PDUMP_STREAM_PARAM2]);
640
641         eError = pdump_write(gpsStream[PDUMP_STREAM_PARAM2], pui8DataLinAddr,
642                              ui32Bytes, ui32Flags);
643         if (eError != PVRSRV_OK)
644                 return eError;
645
646         PDumpCommentWithFlags(ui32Flags, "LDB :SGXMEM:VA_%8.8X:0x%8.8X "
647                               "0x%8.8X 0x%8.8X %%0%%.prm\r\n",
648                               psMemInfo->sDevVAddr.uiAddr, ui32Offset,
649                               ui32Bytes, ui32ParamOutPos);
650
651         CpuPAddr =
652             OSMemHandleToCpuPAddr(psMemInfo->sMemBlk.hOSMemHandle, ui32Offset);
653         ui32PageByteOffset = CpuPAddr.uiAddr & (PAGE_SIZE - 1);
654
655         sDevVAddr = psMemInfo->sDevVAddr;
656         sDevVAddr.uiAddr += ui32Offset;
657
658         ui32BytesRemaining = ui32Bytes;
659         ui32CurrentOffset = ui32Offset;
660
661         while (ui32BytesRemaining > 0) {
662                 u32 ui32BlockBytes = MIN(ui32BytesRemaining, PAGE_SIZE);
663                 CpuPAddr =
664                     OSMemHandleToCpuPAddr(psMemInfo->sMemBlk.hOSMemHandle,
665                                           ui32CurrentOffset);
666
667                 sDevVPageAddr.uiAddr =
668                     psMemInfo->sDevVAddr.uiAddr + ui32CurrentOffset -
669                     ui32PageByteOffset;
670
671                 BM_GetPhysPageAddr(psMemInfo, sDevVPageAddr, &sDevPAddr);
672
673                 sDevPAddr.uiAddr += ui32PageByteOffset;
674
675                 if (ui32PageByteOffset) {
676                         ui32BlockBytes =
677                             MIN(ui32BytesRemaining,
678                                 PAGE_ALIGN(CpuPAddr.uiAddr) - CpuPAddr.uiAddr);
679
680                         ui32PageByteOffset = 0;
681                 }
682
683                 pdump_print(ui32Flags, "LDB :SGXMEM:PA_%8.8X%8.8lX:0x%8.8lX"
684                             " 0x%8.8X 0x%8.8X %%0%%.prm\r\n", (u32) hUniqueTag,
685                             sDevPAddr.uiAddr & ~(SGX_MMU_PAGE_SIZE - 1),
686                             sDevPAddr.uiAddr & (SGX_MMU_PAGE_SIZE - 1),
687                             ui32BlockBytes, ui32ParamOutPos);
688
689                 ui32BytesRemaining -= ui32BlockBytes;
690                 ui32CurrentOffset += ui32BlockBytes;
691                 ui32ParamOutPos += ui32BlockBytes;
692         }
693         PVR_ASSERT(ui32BytesRemaining == 0);
694
695         return PVRSRV_OK;
696 }
697
698 enum PVRSRV_ERROR
699 PDumpMem2KM(enum PVRSRV_DEVICE_TYPE eDeviceType, void *pvLinAddr,
700             u32 ui32Bytes, u32 ui32Flags, IMG_BOOL bInitialisePages,
701             void *hUniqueTag1, void *hUniqueTag2)
702 {
703         u32 ui32NumPages;
704         u32 ui32PageOffset;
705         u32 ui32BlockBytes;
706         u8 *pui8LinAddr;
707         struct IMG_DEV_PHYADDR sDevPAddr;
708         struct IMG_CPU_PHYADDR sCpuPAddr;
709         u32 ui32Offset;
710         u32 ui32ParamOutPos;
711         enum PVRSRV_ERROR eError;
712
713         if (PDumpSuspended())
714                 return PVRSRV_OK;
715
716         if (!pvLinAddr)
717                 return PVRSRV_ERROR_GENERIC;
718
719         ui32ParamOutPos =
720             DbgDrvGetStreamOffset(gpsStream[PDUMP_STREAM_PARAM2]);
721
722         if (bInitialisePages) {
723                 eError = pdump_write(gpsStream[PDUMP_STREAM_PARAM2], pvLinAddr,
724                                      ui32Bytes, PDUMP_FLAGS_CONTINUOUS);
725                 if (eError != PVRSRV_OK)
726                         return eError;
727         }
728
729         ui32PageOffset = (u32) pvLinAddr & (HOST_PAGESIZE() - 1);
730         ui32NumPages =
731             (ui32PageOffset + ui32Bytes + HOST_PAGESIZE() - 1) /
732             HOST_PAGESIZE();
733         pui8LinAddr = (u8 *) pvLinAddr;
734
735         while (ui32NumPages--) {
736                 sCpuPAddr = OSMapLinToCPUPhys(pui8LinAddr);
737                 sDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr);
738
739                 if (ui32PageOffset + ui32Bytes > HOST_PAGESIZE())
740                         ui32BlockBytes = HOST_PAGESIZE() - ui32PageOffset;
741                 else
742                         ui32BlockBytes = ui32Bytes;
743
744                 if (bInitialisePages) {
745                         pdump_print(PDUMP_FLAGS_CONTINUOUS, "LDB :SGXMEM:"
746                                     "PA_%8.8X%8.8lX:0x%8.8lX 0x%8.8X 0x%8.8X "
747                                     "%%0%%.prm\r\n", (u32) hUniqueTag1,
748                                     sDevPAddr.uiAddr & ~(SGX_MMU_PAGE_SIZE - 1),
749                                     sDevPAddr.uiAddr & (SGX_MMU_PAGE_SIZE - 1),
750                                     ui32BlockBytes, ui32ParamOutPos);
751                 } else {
752                         for (ui32Offset = 0; ui32Offset < ui32BlockBytes;
753                              ui32Offset += sizeof(u32)) {
754                                 u32 ui32PTE =
755                                     *((u32 *) (pui8LinAddr +
756                                                       ui32Offset));
757
758                                 if ((ui32PTE & SGX_MMU_PDE_ADDR_MASK) != 0) {
759                                         pdump_print(PDUMP_FLAGS_CONTINUOUS,
760 "WRW :SGXMEM:PA_%8.8X%8.8lX:0x%8.8lX :SGXMEM:PA_%8.8X%8.8lX:0x%8.8lX\r\n",
761                                                  (u32)hUniqueTag1,
762                                                  (sDevPAddr.uiAddr +
763                                                       ui32Offset) &
764                                                        ~(SGX_MMU_PAGE_SIZE - 1),
765                                                  (sDevPAddr.uiAddr +
766                                                       ui32Offset) &
767                                                         (SGX_MMU_PAGE_SIZE - 1),
768                                                  (u32)hUniqueTag2,
769                                                  ui32PTE &
770                                                          SGX_MMU_PDE_ADDR_MASK,
771                                                  ui32PTE &
772                                                         ~SGX_MMU_PDE_ADDR_MASK);
773                                 } else {
774                                         PVR_ASSERT(!
775                                                    (ui32PTE &
776                                                     SGX_MMU_PTE_VALID));
777                                         pdump_print(PDUMP_FLAGS_CONTINUOUS,
778                 "WRW :SGXMEM:PA_%8.8X%8.8lX:0x%8.8lX 0x%8.8X%8.8X\r\n",
779                                                  (u32) hUniqueTag1,
780                                                  (sDevPAddr.uiAddr +
781                                                       ui32Offset) &
782                                                        ~(SGX_MMU_PAGE_SIZE - 1),
783                                                  (sDevPAddr.uiAddr +
784                                                       ui32Offset) &
785                                                         (SGX_MMU_PAGE_SIZE - 1),
786                                                  ui32PTE, (u32)hUniqueTag2);
787                                 }
788                         }
789                 }
790
791                 ui32PageOffset = 0;
792                 ui32Bytes -= ui32BlockBytes;
793                 pui8LinAddr += ui32BlockBytes;
794                 ui32ParamOutPos += ui32BlockBytes;
795         }
796
797         return PVRSRV_OK;
798 }
799
800 void
801 PDumpPDDevPAddrKM(struct PVRSRV_KERNEL_MEM_INFO *psMemInfo,
802                   u32 ui32Offset, struct IMG_DEV_PHYADDR sPDDevPAddr,
803                   void *hUniqueTag1, void *hUniqueTag2)
804 {
805         struct IMG_CPU_PHYADDR CpuPAddr;
806         u32 ui32PageByteOffset;
807         struct IMG_DEV_VIRTADDR sDevVAddr;
808         struct IMG_DEV_VIRTADDR sDevVPageAddr;
809         struct IMG_DEV_PHYADDR sDevPAddr;
810
811         if (PDumpSuspended())
812                 return;
813
814         CpuPAddr =
815             OSMemHandleToCpuPAddr(psMemInfo->sMemBlk.hOSMemHandle, ui32Offset);
816         ui32PageByteOffset = CpuPAddr.uiAddr & (PAGE_SIZE - 1);
817
818         sDevVAddr = psMemInfo->sDevVAddr;
819         sDevVAddr.uiAddr += ui32Offset;
820
821         sDevVPageAddr.uiAddr = sDevVAddr.uiAddr - ui32PageByteOffset;
822         BM_GetPhysPageAddr(psMemInfo, sDevVPageAddr, &sDevPAddr);
823         sDevPAddr.uiAddr += ui32PageByteOffset;
824
825         if ((sPDDevPAddr.uiAddr & SGX_MMU_PDE_ADDR_MASK) != 0) {
826                 pdump_print(PDUMP_FLAGS_CONTINUOUS,
827 "WRW :SGXMEM:PA_%8.8X%8.8lX:0x%8.8lX :SGXMEM:PA_%8.8X%8.8lX:0x%8.8lX\r\n",
828                             (u32) hUniqueTag1,
829                             sDevPAddr.uiAddr & ~(SGX_MMU_PAGE_SIZE - 1),
830                             sDevPAddr.uiAddr & (SGX_MMU_PAGE_SIZE - 1),
831                             (u32)hUniqueTag2,
832                             sPDDevPAddr.uiAddr & SGX_MMU_PDE_ADDR_MASK,
833                             sPDDevPAddr.uiAddr & ~SGX_MMU_PDE_ADDR_MASK);
834         } else {
835                 PVR_ASSERT(!(sDevPAddr.uiAddr & SGX_MMU_PTE_VALID));
836                 pdump_print(PDUMP_FLAGS_CONTINUOUS,
837                             "WRW :SGXMEM:PA_%8.8X%8.8lX:0x%8.8lX 0x%8.8X\r\n",
838                             (u32)hUniqueTag1,
839                             sDevPAddr.uiAddr & ~(SGX_MMU_PAGE_SIZE - 1),
840                             sDevPAddr.uiAddr & (SGX_MMU_PAGE_SIZE - 1),
841                             sPDDevPAddr.uiAddr);
842         }
843 }
844
845 void PDumpBitmapKM(char *pszFileName, u32 ui32FileOffset,
846                    u32 ui32Width, u32 ui32Height, u32 ui32StrideInBytes,
847                    struct IMG_DEV_VIRTADDR sDevBaseAddr,
848                    u32 ui32Size, enum PDUMP_PIXEL_FORMAT ePixelFormat,
849                    enum PDUMP_MEM_FORMAT eMemFormat, u32 ui32PDumpFlags)
850 {
851         if (PDumpSuspended())
852                 return;
853
854         PDumpCommentWithFlags(ui32PDumpFlags, "Dump bitmap of render\r\n");
855
856         pdump_print(ui32PDumpFlags,
857                     "SII %s %s.bin :SGXMEM:v:0x%08X 0x%08X "
858                     "0x%08X 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X\r\n",
859                     pszFileName, pszFileName, sDevBaseAddr.uiAddr, ui32Size,
860                     ui32FileOffset, ePixelFormat, ui32Width, ui32Height,
861                     ui32StrideInBytes, eMemFormat);
862 }
863
864 static void PDumpReadRegKM(char *pszFileName, u32 ui32FileOffset,
865                            u32 ui32Address, u32 ui32Size, u32 ui32PDumpFlags)
866 {
867         if (PDumpSuspended())
868                 return;
869
870         pdump_print(ui32PDumpFlags, "SAB :SGXREG:0x%08X 0x%08X %s\r\n",
871                     ui32Address, ui32FileOffset, pszFileName);
872 }
873
874 void PDump3DSignatureRegisters(u32 ui32DumpFrameNum,
875                                u32 *pui32Registers, u32 ui32NumRegisters)
876 {
877         u32 ui32FileOffset;
878         u32 i;
879
880         if (PDumpSuspended())
881                 return;
882
883         ui32FileOffset = 0;
884
885         PDumpCommentWithFlags(0, "Dump 3D signature registers\r\n");
886         snprintf(gpszFile, SZ_FILENAME_SIZE_MAX, "out%u_3d.sig",
887                  ui32DumpFrameNum);
888
889         for (i = 0; i < ui32NumRegisters; i++) {
890                 PDumpReadRegKM(gpszFile, ui32FileOffset, pui32Registers[i],
891                                sizeof(u32), 0);
892                 ui32FileOffset += sizeof(u32);
893         }
894 }
895
896 static void PDumpCountRead(char *pszFileName, u32 ui32Address, u32 ui32Size,
897                            u32 *pui32FileOffset)
898 {
899         if (PDumpSuspended())
900                 return;
901
902         pdump_print(0, "SAB :SGXREG:0x%08X 0x%08X %s\r\n", ui32Address,
903                     *pui32FileOffset, pszFileName);
904
905         *pui32FileOffset += ui32Size;
906 }
907
908 void PDumpCounterRegisters(u32 ui32DumpFrameNum,
909                            u32 *pui32Registers, u32 ui32NumRegisters)
910 {
911         u32 ui32FileOffset;
912         u32 i;
913
914         if (PDumpSuspended())
915                 return;
916
917         PDumpCommentWithFlags(0, "Dump counter registers\r\n");
918         snprintf(gpszFile, SZ_FILENAME_SIZE_MAX, "out%u.perf",
919                  ui32DumpFrameNum);
920         ui32FileOffset = 0;
921
922         for (i = 0; i < ui32NumRegisters; i++)
923                 PDumpCountRead(gpszFile, pui32Registers[i], sizeof(u32),
924                                &ui32FileOffset);
925 }
926
927 void PDumpTASignatureRegisters(u32 ui32DumpFrameNum, u32 ui32TAKickCount,
928                                u32 *pui32Registers, u32 ui32NumRegisters)
929 {
930         u32 ui32FileOffset;
931         u32 i;
932
933         if (PDumpSuspended())
934                 return;
935
936         PDumpCommentWithFlags(0, "Dump TA signature registers\r\n");
937         snprintf(gpszFile, SZ_FILENAME_SIZE_MAX, "out%u_ta.sig",
938                  ui32DumpFrameNum);
939
940         ui32FileOffset = ui32TAKickCount * ui32NumRegisters * sizeof(u32);
941
942         for (i = 0; i < ui32NumRegisters; i++) {
943                 PDumpReadRegKM(gpszFile, ui32FileOffset, pui32Registers[i],
944                                sizeof(u32), 0);
945                 ui32FileOffset += sizeof(u32);
946         }
947 }
948
949 void PDumpRegRead(const u32 ui32RegOffset, u32 ui32Flags)
950 {
951         if (PDumpSuspended())
952                 return;
953
954         pdump_print(ui32Flags, "RDW :SGXREG:0x%X\r\n", ui32RegOffset);
955 }
956
957 void PDumpCycleCountRegRead(const u32 ui32RegOffset)
958 {
959         if (PDumpSuspended())
960                 return;
961
962         pdump_print(0, "RDW :SGXREG:0x%X\r\n", ui32RegOffset);
963 }
964
965 void PDumpHWPerfCBKM(char *pszFileName, u32 ui32FileOffset,
966                      struct IMG_DEV_VIRTADDR sDevBaseAddr, u32 ui32Size,
967                      u32 ui32PDumpFlags)
968 {
969         if (PDumpSuspended())
970                 return;
971
972         PDumpCommentWithFlags(ui32PDumpFlags,
973                               "Dump Hardware Performance Circular Buffer\r\n");
974         pdump_print(ui32PDumpFlags,
975                     "SAB :SGXMEM:v:0x%08X 0x%08X 0x%08X %s.bin\r\n",
976                     sDevBaseAddr.uiAddr, ui32Size, ui32FileOffset, pszFileName);
977 }
978
979 void PDumpCBP(struct PVRSRV_KERNEL_MEM_INFO *psROffMemInfo,
980               u32 ui32ROffOffset, u32 ui32WPosVal, u32 ui32PacketSize,
981               u32 ui32BufferSize, u32 ui32Flags, void *hUniqueTag)
982 {
983         u32 ui32PageOffset;
984         struct IMG_DEV_VIRTADDR sDevVAddr;
985         struct IMG_DEV_PHYADDR sDevPAddr;
986         struct IMG_DEV_VIRTADDR sDevVPageAddr;
987         struct IMG_CPU_PHYADDR CpuPAddr;
988
989         if (PDumpSuspended())
990                 return;
991
992         PVR_ASSERT((ui32ROffOffset + sizeof(u32)) <=
993                    psROffMemInfo->ui32AllocSize);
994
995         sDevVAddr = psROffMemInfo->sDevVAddr;
996
997         sDevVAddr.uiAddr += ui32ROffOffset;
998
999         CpuPAddr =
1000             OSMemHandleToCpuPAddr(psROffMemInfo->sMemBlk.hOSMemHandle,
1001                                   ui32ROffOffset);
1002         ui32PageOffset = CpuPAddr.uiAddr & (PAGE_SIZE - 1);
1003
1004         sDevVPageAddr.uiAddr = sDevVAddr.uiAddr - ui32PageOffset;
1005
1006         BM_GetPhysPageAddr(psROffMemInfo, sDevVPageAddr, &sDevPAddr);
1007
1008         sDevPAddr.uiAddr += ui32PageOffset;
1009
1010         pdump_print(ui32Flags,
1011         "CBP :SGXMEM:PA_%8.8X%8.8lX:0x%8.8lX 0x%8.8X 0x%8.8X 0x%8.8X\r\n",
1012                     (u32) hUniqueTag,
1013                     sDevPAddr.uiAddr & ~(SGX_MMU_PAGE_SIZE - 1),
1014                     sDevPAddr.uiAddr & (SGX_MMU_PAGE_SIZE - 1),
1015                     ui32WPosVal, ui32PacketSize, ui32BufferSize);
1016 }
1017
1018 void PDumpIDLWithFlags(u32 ui32Clocks, u32 ui32Flags)
1019 {
1020         if (PDumpSuspended())
1021                 return;
1022
1023         pdump_print(ui32Flags, "IDL %u\r\n", ui32Clocks);
1024 }
1025
1026 #endif