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