1 /*
2 * Copyright © 2022 Imagination Technologies Ltd.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 */
23
24 #include <inttypes.h>
25 #include <stddef.h>
26 #include <stdint.h>
27 #include <stdio.h>
28 #include <vulkan/vulkan.h>
29
30 #include "pvr_bo.h"
31 #include "pvr_csb.h"
32 #include "pvr_csb_enum_helpers.h"
33 #include "pvr_device_info.h"
34 #include "pvr_dump.h"
35 #include "pvr_dump_bo.h"
36 #include "pvr_private.h"
37 #include "pvr_util.h"
38 #include "util/list.h"
39 #include "util/macros.h"
40 #include "util/u_math.h"
41 #include "vk_enum_to_str.h"
42
43 /*****************************************************************************
44 Utilities
45 ******************************************************************************/
46
47 #define PVR_DUMP_CSB_WORD_SIZE ((unsigned)sizeof(uint32_t))
48
49 enum buffer_type {
50 BUFFER_TYPE_NONE = 0,
51 BUFFER_TYPE_CDMCTRL,
52 BUFFER_TYPE_VDMCTRL,
53 BUFFER_TYPE_PPP,
54 BUFFER_TYPE_INVALID, /* Must be last. */
55 };
56
57 struct pvr_dump_csb_ctx {
58 struct pvr_dump_buffer_ctx base;
59
60 /* User-modifiable values */
61 uint32_t next_block_idx;
62 };
63
64 static inline bool
pvr_dump_csb_ctx_push(struct pvr_dump_csb_ctx * const ctx,struct pvr_dump_buffer_ctx * const parent_ctx)65 pvr_dump_csb_ctx_push(struct pvr_dump_csb_ctx *const ctx,
66 struct pvr_dump_buffer_ctx *const parent_ctx)
67 {
68 if (!pvr_dump_buffer_ctx_push(&ctx->base,
69 &parent_ctx->base,
70 parent_ctx->ptr,
71 parent_ctx->remaining_size)) {
72 return false;
73 }
74
75 ctx->next_block_idx = 0;
76
77 return true;
78 }
79
80 static inline struct pvr_dump_buffer_ctx *
pvr_dump_csb_ctx_pop(struct pvr_dump_csb_ctx * const ctx,bool advance_parent)81 pvr_dump_csb_ctx_pop(struct pvr_dump_csb_ctx *const ctx, bool advance_parent)
82 {
83 struct pvr_dump_buffer_ctx *parent;
84 struct pvr_dump_ctx *parent_base;
85 const uint64_t unused_words =
86 ctx->base.remaining_size / PVR_DUMP_CSB_WORD_SIZE;
87
88 if (unused_words) {
89 pvr_dump_buffer_print_header_line(&ctx->base,
90 "<%" PRIu64 " unused word%s (%" PRIu64
91 " bytes)>",
92 unused_words,
93 unused_words == 1 ? "" : "s",
94 unused_words * PVR_DUMP_CSB_WORD_SIZE);
95
96 pvr_dump_buffer_advance(&ctx->base,
97 unused_words * PVR_DUMP_CSB_WORD_SIZE);
98 }
99
100 pvr_dump_buffer_print_header_line(&ctx->base, "<end of buffer>");
101
102 parent_base = pvr_dump_buffer_ctx_pop(&ctx->base);
103 if (!parent_base)
104 return NULL;
105
106 parent = container_of(parent_base, struct pvr_dump_buffer_ctx, base);
107
108 if (advance_parent)
109 pvr_dump_buffer_advance(parent, ctx->base.capacity);
110
111 return parent;
112 }
113
114 struct pvr_dump_csb_block_ctx {
115 struct pvr_dump_buffer_ctx base;
116 };
117
118 #define pvr_dump_csb_block_ctx_push(ctx, \
119 parent_ctx, \
120 header_format, \
121 header_args...) \
122 ({ \
123 struct pvr_dump_csb_ctx *const _csb_ctx = (parent_ctx); \
124 pvr_dump_buffer_print_header_line(&_csb_ctx->base, \
125 "%" PRIu32 ": " header_format, \
126 _csb_ctx->next_block_idx, \
127 ##header_args); \
128 __pvr_dump_csb_block_ctx_push(ctx, _csb_ctx); \
129 })
130
131 static inline bool
__pvr_dump_csb_block_ctx_push(struct pvr_dump_csb_block_ctx * const ctx,struct pvr_dump_csb_ctx * const parent_ctx)132 __pvr_dump_csb_block_ctx_push(struct pvr_dump_csb_block_ctx *const ctx,
133 struct pvr_dump_csb_ctx *const parent_ctx)
134 {
135 pvr_dump_indent(&parent_ctx->base.base);
136
137 if (!pvr_dump_buffer_ctx_push(&ctx->base,
138 &parent_ctx->base.base,
139 parent_ctx->base.ptr,
140 parent_ctx->base.remaining_size)) {
141 return false;
142 }
143
144 parent_ctx->next_block_idx++;
145
146 return true;
147 }
148
149 static inline struct pvr_dump_csb_ctx *
pvr_dump_csb_block_ctx_pop(struct pvr_dump_csb_block_ctx * const ctx)150 pvr_dump_csb_block_ctx_pop(struct pvr_dump_csb_block_ctx *const ctx)
151 {
152 const uint64_t used_size = ctx->base.capacity - ctx->base.remaining_size;
153 struct pvr_dump_csb_ctx *parent_ctx;
154 struct pvr_dump_ctx *parent_base;
155
156 parent_base = pvr_dump_buffer_ctx_pop(&ctx->base);
157 if (!parent_base)
158 return NULL;
159
160 parent_ctx = container_of(parent_base, struct pvr_dump_csb_ctx, base.base);
161
162 /* No need to check this since it can never fail. */
163 pvr_dump_buffer_advance(&parent_ctx->base, used_size);
164
165 pvr_dump_dedent(parent_base);
166
167 return parent_ctx;
168 }
169
170 static inline const uint32_t *
pvr_dump_csb_block_take(struct pvr_dump_csb_block_ctx * const restrict ctx,const uint32_t nr_words)171 pvr_dump_csb_block_take(struct pvr_dump_csb_block_ctx *const restrict ctx,
172 const uint32_t nr_words)
173 {
174 return pvr_dump_buffer_take(&ctx->base, nr_words * PVR_DUMP_CSB_WORD_SIZE);
175 }
176
177 #define pvr_dump_csb_block_take_packed(ctx, cmd, dest) \
178 ({ \
179 struct pvr_dump_csb_block_ctx *const _block_ctx = (ctx); \
180 struct PVRX(cmd) *const _dest = (dest); \
181 const void *const _ptr = \
182 pvr_dump_csb_block_take(_block_ctx, pvr_cmd_length(cmd)); \
183 if (_ptr) { \
184 pvr_cmd_unpack(cmd)(_ptr, _dest); \
185 } else { \
186 pvr_dump_field_error(&_block_ctx->base.base, \
187 "failed to unpack word(s)"); \
188 } \
189 !!_ptr; \
190 })
191
192 /*****************************************************************************
193 Feature dumping
194 ******************************************************************************/
195
196 static inline void
__pvr_dump_field_needs_feature(struct pvr_dump_ctx * const ctx,const char * const name,const char * const feature)197 __pvr_dump_field_needs_feature(struct pvr_dump_ctx *const ctx,
198 const char *const name,
199 const char *const feature)
200 {
201 pvr_dump_field(ctx, name, "<feature %s not present>", feature);
202 }
203
204 #define pvr_dump_field_needs_feature(ctx, name, feature) \
205 do { \
206 (void)PVR_HAS_FEATURE((struct pvr_device_info *)NULL, feature); \
207 __pvr_dump_field_needs_feature(ctx, name, #feature); \
208 } while (0)
209
210 #define pvr_dump_field_member_needs_feature(ctx, compound, member, feature) \
211 do { \
212 (void)&(compound)->member; \
213 pvr_dump_field_needs_feature(ctx, #member, feature); \
214 } while (0)
215
216 /******************************************************************************
217 Sub buffer printer declaration
218 ******************************************************************************/
219
220 static bool print_sub_buffer(struct pvr_dump_ctx *ctx,
221 struct pvr_device *device,
222 enum buffer_type type,
223 pvr_dev_addr_t addr,
224 uint64_t expected_size,
225 char const *size_src);
226
227 /******************************************************************************
228 Block printers
229 ******************************************************************************/
230
231 static uint32_t
print_block_cdmctrl_kernel(struct pvr_dump_csb_ctx * const csb_ctx,struct pvr_device * const device)232 print_block_cdmctrl_kernel(struct pvr_dump_csb_ctx *const csb_ctx,
233 struct pvr_device *const device)
234 {
235 const pvr_dev_addr_t pds_heap_base = device->heaps.pds_heap->base_addr;
236
237 struct pvr_dump_csb_block_ctx ctx;
238 struct pvr_dump_ctx *const base_ctx = &ctx.base.base;
239 uint32_t words_read = 0;
240 bool ret = false;
241
242 struct PVRX(CDMCTRL_KERNEL0) kernel0 = { 0 };
243 struct PVRX(CDMCTRL_KERNEL1) kernel1 = { 0 };
244 struct PVRX(CDMCTRL_KERNEL2) kernel2 = { 0 };
245 struct PVRX(CDMCTRL_KERNEL3) kernel3 = { 0 };
246 struct PVRX(CDMCTRL_KERNEL4) kernel4 = { 0 };
247 struct PVRX(CDMCTRL_KERNEL5) kernel5 = { 0 };
248 struct PVRX(CDMCTRL_KERNEL6) kernel6 = { 0 };
249 struct PVRX(CDMCTRL_KERNEL7) kernel7 = { 0 };
250 struct PVRX(CDMCTRL_KERNEL8) kernel8 = { 0 };
251 struct PVRX(CDMCTRL_KERNEL9) kernel9 = { 0 };
252 struct PVRX(CDMCTRL_KERNEL10) kernel10 = { 0 };
253 struct PVRX(CDMCTRL_KERNEL11) kernel11 = { 0 };
254
255 if (!pvr_dump_csb_block_ctx_push(&ctx, csb_ctx, "KERNEL"))
256 goto end_out;
257
258 if (!pvr_dump_csb_block_take_packed(&ctx, CDMCTRL_KERNEL0, &kernel0) ||
259 !pvr_dump_csb_block_take_packed(&ctx, CDMCTRL_KERNEL1, &kernel1) ||
260 !pvr_dump_csb_block_take_packed(&ctx, CDMCTRL_KERNEL2, &kernel2)) {
261 goto end_pop_ctx;
262 }
263 words_read += 3;
264
265 if (!kernel0.indirect_present) {
266 if (!pvr_dump_csb_block_take_packed(&ctx, CDMCTRL_KERNEL3, &kernel3) ||
267 !pvr_dump_csb_block_take_packed(&ctx, CDMCTRL_KERNEL4, &kernel4) ||
268 !pvr_dump_csb_block_take_packed(&ctx, CDMCTRL_KERNEL5, &kernel5)) {
269 goto end_pop_ctx;
270 }
271 words_read += 3;
272 } else {
273 if (!pvr_dump_csb_block_take_packed(&ctx, CDMCTRL_KERNEL6, &kernel6) ||
274 !pvr_dump_csb_block_take_packed(&ctx, CDMCTRL_KERNEL7, &kernel7)) {
275 goto end_pop_ctx;
276 }
277 words_read += 2;
278 }
279
280 if (!pvr_dump_csb_block_take_packed(&ctx, CDMCTRL_KERNEL8, &kernel8))
281 goto end_pop_ctx;
282 words_read += 1;
283
284 if (!pvr_dump_csb_block_take_packed(&ctx, CDMCTRL_KERNEL9, &kernel9) ||
285 !pvr_dump_csb_block_take_packed(&ctx, CDMCTRL_KERNEL10, &kernel10) ||
286 !pvr_dump_csb_block_take_packed(&ctx, CDMCTRL_KERNEL11, &kernel11)) {
287 goto end_pop_ctx;
288 }
289 words_read += 3;
290
291 pvr_dump_field_member_bool(base_ctx, &kernel0, indirect_present);
292 pvr_dump_field_member_bool(base_ctx, &kernel0, global_offsets_present);
293 pvr_dump_field_member_bool(base_ctx, &kernel0, event_object_present);
294 pvr_dump_field_member_u32_scaled_units(
295 base_ctx,
296 &kernel0,
297 usc_common_size,
298 PVRX(CDMCTRL_KERNEL0_USC_COMMON_SIZE_UNIT_SIZE),
299 "bytes");
300 pvr_dump_field_member_u32_scaled_units(
301 base_ctx,
302 &kernel0,
303 usc_unified_size,
304 PVRX(CDMCTRL_KERNEL0_USC_UNIFIED_SIZE_UNIT_SIZE),
305 "bytes");
306 pvr_dump_field_member_u32_scaled_units(
307 base_ctx,
308 &kernel0,
309 pds_temp_size,
310 PVRX(CDMCTRL_KERNEL0_PDS_TEMP_SIZE_UNIT_SIZE),
311 "bytes");
312 pvr_dump_field_member_u32_scaled_units(
313 base_ctx,
314 &kernel0,
315 pds_data_size,
316 PVRX(CDMCTRL_KERNEL0_PDS_DATA_SIZE_UNIT_SIZE),
317 "bytes");
318 pvr_dump_field_member_enum(base_ctx,
319 &kernel0,
320 usc_target,
321 pvr_cmd_enum_to_str(CDMCTRL_USC_TARGET));
322 pvr_dump_field_member_bool(base_ctx, &kernel0, fence);
323
324 pvr_dump_field_member_addr_offset(base_ctx,
325 &kernel1,
326 data_addr,
327 pds_heap_base);
328 ret = print_sub_buffer(
329 base_ctx,
330 device,
331 BUFFER_TYPE_NONE,
332 PVR_DEV_ADDR_OFFSET(pds_heap_base, kernel1.data_addr.addr),
333 kernel0.pds_data_size * PVRX(CDMCTRL_KERNEL0_PDS_DATA_SIZE_UNIT_SIZE),
334 "pds_data_size");
335 if (!ret)
336 goto end_pop_ctx;
337
338 pvr_dump_field_member_enum(base_ctx,
339 &kernel1,
340 sd_type,
341 pvr_cmd_enum_to_str(CDMCTRL_SD_TYPE));
342 pvr_dump_field_member_bool(base_ctx, &kernel1, usc_common_shared);
343
344 pvr_dump_field_member_addr_offset(base_ctx,
345 &kernel2,
346 code_addr,
347 pds_heap_base);
348 /* FIXME: Determine the exact size of the PDS code section once disassembly
349 * is implemented.
350 */
351 ret = print_sub_buffer(base_ctx,
352 device,
353 BUFFER_TYPE_NONE,
354 PVR_DEV_ADDR_OFFSET(pds_heap_base,
355 kernel2.code_addr.addr),
356 0,
357 NULL);
358 if (!ret)
359 goto end_pop_ctx;
360
361 pvr_dump_field_member_bool(base_ctx, &kernel2, one_wg_per_task);
362
363 if (!kernel0.indirect_present) {
364 pvr_dump_field_member_u32_offset(base_ctx, &kernel3, workgroup_x, 1);
365 pvr_dump_field_member_u32_offset(base_ctx, &kernel4, workgroup_y, 1);
366 pvr_dump_field_member_u32_offset(base_ctx, &kernel5, workgroup_z, 1);
367
368 pvr_dump_field_not_present(base_ctx, "indirect_addr");
369 } else {
370 pvr_dump_field_member_not_present(base_ctx, &kernel3, workgroup_x);
371 pvr_dump_field_member_not_present(base_ctx, &kernel4, workgroup_y);
372 pvr_dump_field_member_not_present(base_ctx, &kernel5, workgroup_z);
373
374 pvr_dump_field_addr_split(base_ctx,
375 "indirect_addr",
376 kernel6.indirect_addrmsb,
377 kernel7.indirect_addrlsb);
378 }
379
380 pvr_dump_field_member_u32_zero(base_ctx, &kernel8, max_instances, 32);
381 pvr_dump_field_member_u32_offset(base_ctx, &kernel8, workgroup_size_x, 1);
382 pvr_dump_field_member_u32_offset(base_ctx, &kernel8, workgroup_size_y, 1);
383 pvr_dump_field_member_u32_offset(base_ctx, &kernel8, workgroup_size_z, 1);
384
385 if (kernel0.event_object_present) {
386 pvr_dump_field_member_u32(base_ctx, &kernel9, global_offset_x);
387 pvr_dump_field_member_u32(base_ctx, &kernel10, global_offset_y);
388 pvr_dump_field_member_u32(base_ctx, &kernel11, global_offset_z);
389 } else {
390 pvr_dump_field_member_not_present(base_ctx, &kernel9, global_offset_x);
391 pvr_dump_field_member_not_present(base_ctx, &kernel10, global_offset_y);
392 pvr_dump_field_member_not_present(base_ctx, &kernel11, global_offset_z);
393 }
394
395 ret = true;
396
397 end_pop_ctx:
398 pvr_dump_csb_block_ctx_pop(&ctx);
399
400 end_out:
401 return ret ? words_read : 0;
402 }
403
404 static uint32_t
print_block_cdmctrl_stream_link(struct pvr_dump_csb_ctx * const csb_ctx)405 print_block_cdmctrl_stream_link(struct pvr_dump_csb_ctx *const csb_ctx)
406 {
407 struct pvr_dump_csb_block_ctx ctx;
408 struct pvr_dump_ctx *const base_ctx = &ctx.base.base;
409 uint32_t words_read = 0;
410 bool ret = false;
411
412 struct PVRX(CDMCTRL_STREAM_LINK0) link0 = { 0 };
413 struct PVRX(CDMCTRL_STREAM_LINK1) link1 = { 0 };
414
415 if (!pvr_dump_csb_block_ctx_push(&ctx, csb_ctx, "STREAM_LINK"))
416 goto end_out;
417
418 if (!pvr_dump_csb_block_take_packed(&ctx, CDMCTRL_STREAM_LINK0, &link0) ||
419 !pvr_dump_csb_block_take_packed(&ctx, CDMCTRL_STREAM_LINK1, &link1)) {
420 goto end_pop_ctx;
421 }
422 words_read += 2;
423
424 pvr_dump_field_addr_split(base_ctx,
425 "link_addr",
426 link0.link_addrmsb,
427 link1.link_addrlsb);
428
429 ret = true;
430
431 end_pop_ctx:
432 pvr_dump_csb_block_ctx_pop(&ctx);
433
434 end_out:
435 return ret ? words_read : 0;
436 }
437
438 static uint32_t
print_block_cdmctrl_stream_terminate(struct pvr_dump_csb_ctx * const csb_ctx)439 print_block_cdmctrl_stream_terminate(struct pvr_dump_csb_ctx *const csb_ctx)
440 {
441 struct pvr_dump_csb_block_ctx ctx;
442 struct pvr_dump_ctx *const base_ctx = &ctx.base.base;
443 uint32_t words_read = 0;
444 bool ret = false;
445
446 struct PVRX(CDMCTRL_STREAM_TERMINATE) terminate = { 0 };
447
448 if (!pvr_dump_csb_block_ctx_push(&ctx, csb_ctx, "TERMINATE"))
449 goto end_out;
450
451 if (!pvr_dump_csb_block_take_packed(&ctx,
452 CDMCTRL_STREAM_TERMINATE,
453 &terminate)) {
454 goto end_pop_ctx;
455 }
456 words_read += 1;
457
458 pvr_dump_field_no_fields(base_ctx);
459
460 ret = true;
461
462 end_pop_ctx:
463 pvr_dump_csb_block_ctx_pop(&ctx);
464
465 end_out:
466 return ret ? words_read : 0;
467 }
468
469 static uint32_t
print_block_vdmctrl_ppp_state_update(struct pvr_dump_csb_ctx * const csb_ctx,struct pvr_device * const device)470 print_block_vdmctrl_ppp_state_update(struct pvr_dump_csb_ctx *const csb_ctx,
471 struct pvr_device *const device)
472 {
473 struct pvr_dump_csb_block_ctx ctx;
474 struct pvr_dump_ctx *const base_ctx = &ctx.base.base;
475 uint32_t words_read = 0;
476 bool ret = false;
477
478 struct PVRX(VDMCTRL_PPP_STATE0) state0 = { 0 };
479 struct PVRX(VDMCTRL_PPP_STATE1) state1 = { 0 };
480
481 if (!pvr_dump_csb_block_ctx_push(&ctx, csb_ctx, "PPP_STATE_UPDATE"))
482 goto end_out;
483
484 if (!pvr_dump_csb_block_take_packed(&ctx, VDMCTRL_PPP_STATE0, &state0) ||
485 !pvr_dump_csb_block_take_packed(&ctx, VDMCTRL_PPP_STATE1, &state1)) {
486 goto end_pop_ctx;
487 }
488 words_read += 2;
489
490 pvr_dump_field_member_u32_zero(base_ctx, &state0, word_count, 256);
491 pvr_dump_field_addr_split(base_ctx, "addr", state0.addrmsb, state1.addrlsb);
492 ret = print_sub_buffer(
493 base_ctx,
494 device,
495 BUFFER_TYPE_PPP,
496 PVR_DEV_ADDR(state0.addrmsb.addr | state1.addrlsb.addr),
497 (state0.word_count ? state0.word_count : 256) * PVR_DUMP_CSB_WORD_SIZE,
498 "word_count");
499 if (!ret)
500 goto end_pop_ctx;
501
502 ret = true;
503
504 end_pop_ctx:
505 pvr_dump_csb_block_ctx_pop(&ctx);
506
507 end_out:
508 return ret ? words_read : 0;
509 }
510
511 static uint32_t
print_block_vdmctrl_pds_state_update(struct pvr_dump_csb_ctx * const csb_ctx,struct pvr_device * const device)512 print_block_vdmctrl_pds_state_update(struct pvr_dump_csb_ctx *const csb_ctx,
513 struct pvr_device *const device)
514 {
515 const pvr_dev_addr_t pds_heap_base = device->heaps.pds_heap->base_addr;
516
517 struct pvr_dump_csb_block_ctx ctx;
518 struct pvr_dump_ctx *const base_ctx = &ctx.base.base;
519 uint32_t words_read = 0;
520 bool ret = false;
521
522 struct PVRX(VDMCTRL_PDS_STATE0) state0 = { 0 };
523 struct PVRX(VDMCTRL_PDS_STATE1) state1 = { 0 };
524 struct PVRX(VDMCTRL_PDS_STATE2) state2 = { 0 };
525
526 if (!pvr_dump_csb_block_ctx_push(&ctx, csb_ctx, "PDS_STATE_UPDATE"))
527 goto end_out;
528
529 if (!pvr_dump_csb_block_take_packed(&ctx, VDMCTRL_PDS_STATE0, &state0) ||
530 !pvr_dump_csb_block_take_packed(&ctx, VDMCTRL_PDS_STATE1, &state1) ||
531 !pvr_dump_csb_block_take_packed(&ctx, VDMCTRL_PDS_STATE2, &state2)) {
532 goto end_pop_ctx;
533 }
534 words_read += 3;
535
536 pvr_dump_field_member_enum(base_ctx,
537 &state0,
538 dm_target,
539 pvr_cmd_enum_to_str(VDMCTRL_DM_TARGET));
540 pvr_dump_field_member_enum(base_ctx,
541 &state0,
542 usc_target,
543 pvr_cmd_enum_to_str(VDMCTRL_USC_TARGET));
544 pvr_dump_field_member_u32_scaled_units(
545 base_ctx,
546 &state0,
547 usc_common_size,
548 PVRX(VDMCTRL_PDS_STATE0_USC_COMMON_SIZE_UNIT_SIZE),
549 "bytes");
550 pvr_dump_field_member_u32_scaled_units(
551 base_ctx,
552 &state0,
553 usc_unified_size,
554 PVRX(VDMCTRL_PDS_STATE0_USC_UNIFIED_SIZE_UNIT_SIZE),
555 "bytes");
556 pvr_dump_field_member_u32_scaled_units(
557 base_ctx,
558 &state0,
559 pds_temp_size,
560 PVRX(VDMCTRL_PDS_STATE0_PDS_TEMP_SIZE_UNIT_SIZE),
561 "bytes");
562 pvr_dump_field_member_u32_scaled_units(
563 base_ctx,
564 &state0,
565 pds_data_size,
566 PVRX(VDMCTRL_PDS_STATE0_PDS_DATA_SIZE_UNIT_SIZE),
567 "bytes");
568
569 pvr_dump_field_member_addr_offset(base_ctx,
570 &state1,
571 pds_data_addr,
572 pds_heap_base);
573 ret = print_sub_buffer(
574 base_ctx,
575 device,
576 BUFFER_TYPE_NONE,
577 PVR_DEV_ADDR_OFFSET(pds_heap_base, state1.pds_data_addr.addr),
578 state0.pds_data_size * PVRX(VDMCTRL_PDS_STATE0_PDS_DATA_SIZE_UNIT_SIZE),
579 "pds_data_size");
580 if (!ret)
581 goto end_pop_ctx;
582
583 pvr_dump_field_member_enum(base_ctx,
584 &state1,
585 sd_type,
586 pvr_cmd_enum_to_str(VDMCTRL_SD_TYPE));
587 pvr_dump_field_member_enum(base_ctx,
588 &state1,
589 sd_next_type,
590 pvr_cmd_enum_to_str(VDMCTRL_SD_TYPE));
591
592 pvr_dump_field_member_addr_offset(base_ctx,
593 &state2,
594 pds_code_addr,
595 pds_heap_base);
596 /* FIXME: Determine the exact size of the PDS code section once disassembly
597 * is implemented.
598 */
599 ret = print_sub_buffer(base_ctx,
600 device,
601 BUFFER_TYPE_NONE,
602 PVR_DEV_ADDR_OFFSET(pds_heap_base,
603 state2.pds_code_addr.addr),
604 0,
605 NULL);
606 if (!ret)
607 goto end_pop_ctx;
608
609 ret = true;
610
611 end_pop_ctx:
612 pvr_dump_csb_block_ctx_pop(&ctx);
613
614 end_out:
615 return ret ? words_read : 0;
616 }
617
618 static uint32_t
print_block_vdmctrl_vdm_state_update(struct pvr_dump_csb_ctx * const csb_ctx,struct pvr_device * const device)619 print_block_vdmctrl_vdm_state_update(struct pvr_dump_csb_ctx *const csb_ctx,
620 struct pvr_device *const device)
621 {
622 const pvr_dev_addr_t pds_heap_base = device->heaps.pds_heap->base_addr;
623
624 struct pvr_dump_csb_block_ctx ctx;
625 struct pvr_dump_ctx *const base_ctx = &ctx.base.base;
626 uint32_t words_read = 0;
627 bool ret = false;
628
629 struct PVRX(VDMCTRL_VDM_STATE0) state0 = { 0 };
630 struct PVRX(VDMCTRL_VDM_STATE1) state1 = { 0 };
631 struct PVRX(VDMCTRL_VDM_STATE2) state2 = { 0 };
632 struct PVRX(VDMCTRL_VDM_STATE3) state3 = { 0 };
633 struct PVRX(VDMCTRL_VDM_STATE4) state4 = { 0 };
634 struct PVRX(VDMCTRL_VDM_STATE5) state5 = { 0 };
635
636 if (!pvr_dump_csb_block_ctx_push(&ctx, csb_ctx, "VDM_STATE_UPDATE"))
637 goto end_out;
638
639 if (!pvr_dump_csb_block_take_packed(&ctx, VDMCTRL_VDM_STATE0, &state0))
640 goto end_pop_ctx;
641 words_read += 1;
642
643 if (state0.cut_index_present) {
644 if (!pvr_dump_csb_block_take_packed(&ctx, VDMCTRL_VDM_STATE1, &state1))
645 goto end_pop_ctx;
646 words_read += 1;
647 }
648
649 if (state0.vs_data_addr_present) {
650 if (!pvr_dump_csb_block_take_packed(&ctx, VDMCTRL_VDM_STATE2, &state2))
651 goto end_pop_ctx;
652 words_read += 1;
653 }
654
655 if (state0.vs_other_present) {
656 if (!pvr_dump_csb_block_take_packed(&ctx, VDMCTRL_VDM_STATE3, &state3) ||
657 !pvr_dump_csb_block_take_packed(&ctx, VDMCTRL_VDM_STATE4, &state4) ||
658 !pvr_dump_csb_block_take_packed(&ctx, VDMCTRL_VDM_STATE5, &state5)) {
659 goto end_pop_ctx;
660 }
661 words_read += 3;
662 }
663
664 if (state0.cut_index_present) {
665 pvr_dump_field_member_x32(base_ctx, &state1, cut_index, 8);
666 } else {
667 pvr_dump_field_member_not_present(base_ctx, &state1, cut_index);
668 }
669
670 if (state0.vs_data_addr_present) {
671 pvr_dump_field_member_addr_offset(base_ctx,
672 &state2,
673 vs_pds_data_base_addr,
674 pds_heap_base);
675 if (state0.vs_other_present) {
676 ret = print_sub_buffer(
677 base_ctx,
678 device,
679 BUFFER_TYPE_NONE,
680 PVR_DEV_ADDR_OFFSET(pds_heap_base,
681 state2.vs_pds_data_base_addr.addr),
682 state5.vs_pds_data_size *
683 PVRX(VDMCTRL_VDM_STATE5_VS_PDS_DATA_SIZE_UNIT_SIZE),
684 "pds_data_size");
685 } else {
686 /* FIXME: Determine the exact size of the PDS data section when no
687 * code section is present once disassembly is implemented.
688 */
689 ret = print_sub_buffer(
690 base_ctx,
691 device,
692 BUFFER_TYPE_NONE,
693 PVR_DEV_ADDR_OFFSET(pds_heap_base,
694 state2.vs_pds_data_base_addr.addr),
695 0,
696 NULL);
697 }
698 if (!ret)
699 goto end_pop_ctx;
700 } else {
701 pvr_dump_field_member_not_present(base_ctx,
702 &state2,
703 vs_pds_data_base_addr);
704 }
705
706 if (state0.vs_other_present) {
707 pvr_dump_field_member_addr_offset(base_ctx,
708 &state3,
709 vs_pds_code_base_addr,
710 pds_heap_base);
711 /* FIXME: Determine the exact size of the PDS code section once
712 * disassembly is implemented.
713 */
714 ret = print_sub_buffer(
715 base_ctx,
716 device,
717 BUFFER_TYPE_NONE,
718 PVR_DEV_ADDR_OFFSET(pds_heap_base, state3.vs_pds_code_base_addr.addr),
719 0,
720 NULL);
721 if (!ret)
722 goto end_pop_ctx;
723
724 pvr_dump_field_member_u32_scaled_units(
725 base_ctx,
726 &state4,
727 vs_output_size,
728 PVRX(VDMCTRL_VDM_STATE4_VS_OUTPUT_SIZE_UNIT_SIZE),
729 "bytes");
730
731 pvr_dump_field_member_u32_zero(base_ctx, &state5, vs_max_instances, 32);
732 pvr_dump_field_member_u32_scaled_units(
733 base_ctx,
734 &state5,
735 vs_usc_common_size,
736 PVRX(VDMCTRL_VDM_STATE5_VS_USC_COMMON_SIZE_UNIT_SIZE),
737 "bytes");
738 pvr_dump_field_member_u32_scaled_units(
739 base_ctx,
740 &state5,
741 vs_usc_unified_size,
742 PVRX(VDMCTRL_VDM_STATE5_VS_USC_UNIFIED_SIZE_UNIT_SIZE),
743 "bytes");
744 pvr_dump_field_member_u32_scaled_units(
745 base_ctx,
746 &state5,
747 vs_pds_temp_size,
748 PVRX(VDMCTRL_VDM_STATE5_VS_PDS_TEMP_SIZE_UNIT_SIZE),
749 "bytes");
750 pvr_dump_field_member_u32_scaled_units(
751 base_ctx,
752 &state5,
753 vs_pds_data_size,
754 PVRX(VDMCTRL_VDM_STATE5_VS_PDS_DATA_SIZE_UNIT_SIZE),
755 "bytes");
756 } else {
757 pvr_dump_field_member_not_present(base_ctx,
758 &state3,
759 vs_pds_code_base_addr);
760 pvr_dump_field_member_not_present(base_ctx, &state4, vs_output_size);
761 pvr_dump_field_member_not_present(base_ctx, &state5, vs_max_instances);
762 pvr_dump_field_member_not_present(base_ctx, &state5, vs_usc_common_size);
763 pvr_dump_field_member_not_present(base_ctx, &state5, vs_usc_unified_size);
764 pvr_dump_field_member_not_present(base_ctx, &state5, vs_pds_temp_size);
765 pvr_dump_field_member_not_present(base_ctx, &state5, vs_pds_data_size);
766 }
767
768 pvr_dump_field_member_bool(base_ctx, &state0, ds_present);
769 pvr_dump_field_member_bool(base_ctx, &state0, gs_present);
770 pvr_dump_field_member_bool(base_ctx, &state0, hs_present);
771 pvr_dump_field_member_u32_offset(base_ctx, &state0, cam_size, 1);
772 pvr_dump_field_member_enum(
773 base_ctx,
774 &state0,
775 uvs_scratch_size_select,
776 pvr_cmd_enum_to_str(VDMCTRL_UVS_SCRATCH_SIZE_SELECT));
777 pvr_dump_field_member_bool(base_ctx, &state0, cut_index_enable);
778 pvr_dump_field_member_bool(base_ctx, &state0, tess_enable);
779 pvr_dump_field_member_bool(base_ctx, &state0, gs_enable);
780 pvr_dump_field_member_enum(base_ctx,
781 &state0,
782 flatshade_control,
783 pvr_cmd_enum_to_str(VDMCTRL_FLATSHADE_CONTROL));
784 pvr_dump_field_member_bool(base_ctx, &state0, generate_primitive_id);
785
786 ret = true;
787
788 end_pop_ctx:
789 pvr_dump_csb_block_ctx_pop(&ctx);
790
791 end_out:
792 return ret ? words_read : 0;
793 }
794
795 static uint32_t
print_block_vdmctrl_index_list(struct pvr_dump_csb_ctx * const csb_ctx,struct pvr_device * const device)796 print_block_vdmctrl_index_list(struct pvr_dump_csb_ctx *const csb_ctx,
797 struct pvr_device *const device)
798 {
799 const struct pvr_device_info *const dev_info = &device->pdevice->dev_info;
800
801 struct pvr_dump_csb_block_ctx ctx;
802 struct pvr_dump_ctx *const base_ctx = &ctx.base.base;
803 uint32_t words_read = 0;
804 bool ret = false;
805
806 struct PVRX(VDMCTRL_INDEX_LIST0) index_list0 = { 0 };
807 struct PVRX(VDMCTRL_INDEX_LIST1) index_list1 = { 0 };
808 struct PVRX(VDMCTRL_INDEX_LIST2) index_list2 = { 0 };
809 struct PVRX(VDMCTRL_INDEX_LIST3) index_list3 = { 0 };
810 struct PVRX(VDMCTRL_INDEX_LIST4) index_list4 = { 0 };
811 struct PVRX(VDMCTRL_INDEX_LIST5) index_list5 = { 0 };
812 struct PVRX(VDMCTRL_INDEX_LIST6) index_list6 = { 0 };
813 struct PVRX(VDMCTRL_INDEX_LIST7) index_list7 = { 0 };
814 struct PVRX(VDMCTRL_INDEX_LIST8) index_list8 = { 0 };
815 struct PVRX(VDMCTRL_INDEX_LIST9) index_list9 = { 0 };
816
817 if (!pvr_dump_csb_block_ctx_push(&ctx, csb_ctx, "INDEX_LIST"))
818 goto end_out;
819
820 if (!pvr_dump_csb_block_take_packed(&ctx, VDMCTRL_INDEX_LIST0, &index_list0))
821 goto end_pop_ctx;
822 words_read += 1;
823
824 if (index_list0.index_addr_present) {
825 if (!pvr_dump_csb_block_take_packed(&ctx,
826 VDMCTRL_INDEX_LIST1,
827 &index_list1)) {
828 goto end_pop_ctx;
829 }
830 words_read += 1;
831 }
832
833 if (index_list0.index_count_present) {
834 if (!pvr_dump_csb_block_take_packed(&ctx,
835 VDMCTRL_INDEX_LIST2,
836 &index_list2)) {
837 goto end_pop_ctx;
838 }
839 words_read += 1;
840 }
841
842 if (index_list0.index_instance_count_present) {
843 if (!pvr_dump_csb_block_take_packed(&ctx,
844 VDMCTRL_INDEX_LIST3,
845 &index_list3)) {
846 goto end_pop_ctx;
847 }
848 words_read += 1;
849 }
850
851 if (index_list0.index_offset_present) {
852 if (!pvr_dump_csb_block_take_packed(&ctx,
853 VDMCTRL_INDEX_LIST4,
854 &index_list4)) {
855 goto end_pop_ctx;
856 }
857 words_read += 1;
858 }
859
860 if (index_list0.start_present) {
861 if (!pvr_dump_csb_block_take_packed(&ctx,
862 VDMCTRL_INDEX_LIST5,
863 &index_list5) ||
864 !pvr_dump_csb_block_take_packed(&ctx,
865 VDMCTRL_INDEX_LIST6,
866 &index_list6)) {
867 goto end_pop_ctx;
868 }
869 words_read += 2;
870 }
871
872 if (index_list0.indirect_addr_present) {
873 if (!pvr_dump_csb_block_take_packed(&ctx,
874 VDMCTRL_INDEX_LIST7,
875 &index_list7) ||
876 !pvr_dump_csb_block_take_packed(&ctx,
877 VDMCTRL_INDEX_LIST8,
878 &index_list8)) {
879 goto end_pop_ctx;
880 }
881 words_read += 2;
882 }
883
884 if (index_list0.split_count_present) {
885 if (!pvr_dump_csb_block_take_packed(&ctx,
886 VDMCTRL_INDEX_LIST9,
887 &index_list9))
888 goto end_pop_ctx;
889 words_read += 1;
890 }
891
892 if (PVR_HAS_FEATURE(dev_info, vdm_degenerate_culling)) {
893 pvr_dump_field_member_bool(base_ctx, &index_list0, degen_cull_enable);
894 } else {
895 pvr_dump_field_member_needs_feature(base_ctx,
896 &index_list0,
897 degen_cull_enable,
898 vdm_degenerate_culling);
899 }
900
901 pvr_dump_field_member_enum(base_ctx,
902 &index_list0,
903 index_size,
904 pvr_cmd_enum_to_str(VDMCTRL_INDEX_SIZE));
905 pvr_dump_field_member_u32_offset(base_ctx, &index_list0, patch_count, 1);
906 pvr_dump_field_member_enum(base_ctx,
907 &index_list0,
908 primitive_topology,
909 pvr_cmd_enum_to_str(VDMCTRL_PRIMITIVE_TOPOLOGY));
910
911 if (index_list0.index_addr_present) {
912 pvr_dump_field_addr_split(base_ctx,
913 "index_base_addr",
914 index_list0.index_base_addrmsb,
915 index_list1.index_base_addrlsb);
916 const uint32_t index_size =
917 pvr_vdmctrl_index_size_nr_bytes(index_list0.index_size);
918
919 if (!index_list0.index_count_present) {
920 ret = pvr_dump_error(base_ctx, "index_addr requires index_count");
921 goto end_pop_ctx;
922 }
923
924 ret = print_sub_buffer(base_ctx,
925 device,
926 BUFFER_TYPE_NONE,
927 PVR_DEV_ADDR(index_list0.index_base_addrmsb.addr |
928 index_list1.index_base_addrlsb.addr),
929 index_list2.index_count * index_size,
930 "index_count * index_size");
931 if (!ret)
932 goto end_pop_ctx;
933 } else {
934 pvr_dump_field_not_present(base_ctx, "index_base_addr");
935 }
936
937 if (index_list0.index_count_present) {
938 pvr_dump_field_member_u32(base_ctx, &index_list2, index_count);
939 } else {
940 pvr_dump_field_member_not_present(base_ctx, &index_list2, index_count);
941 }
942
943 if (index_list0.index_instance_count_present) {
944 pvr_dump_field_member_u32_offset(base_ctx,
945 &index_list3,
946 instance_count,
947 1);
948 } else {
949 pvr_dump_field_member_not_present(base_ctx, &index_list3, instance_count);
950 }
951
952 if (index_list0.index_offset_present) {
953 pvr_dump_field_member_u32(base_ctx, &index_list4, index_offset);
954 } else {
955 pvr_dump_field_member_not_present(base_ctx, &index_list4, index_offset);
956 }
957
958 if (index_list0.start_present) {
959 pvr_dump_field_member_u32(base_ctx, &index_list5, start_index);
960 pvr_dump_field_member_u32(base_ctx, &index_list6, start_instance);
961 } else {
962 pvr_dump_field_member_not_present(base_ctx, &index_list5, start_index);
963 pvr_dump_field_member_not_present(base_ctx, &index_list6, start_instance);
964 }
965
966 if (index_list0.indirect_addr_present) {
967 pvr_dump_field_addr_split(base_ctx,
968 "indirect_base_addr",
969 index_list7.indirect_base_addrmsb,
970 index_list8.indirect_base_addrlsb);
971 ret =
972 print_sub_buffer(base_ctx,
973 device,
974 BUFFER_TYPE_NONE,
975 PVR_DEV_ADDR(index_list7.indirect_base_addrmsb.addr |
976 index_list8.indirect_base_addrlsb.addr),
977 0,
978 NULL);
979 if (!ret)
980 goto end_pop_ctx;
981 } else {
982 pvr_dump_field_not_present(base_ctx, "indirect_base_addr");
983 }
984
985 if (index_list0.split_count_present) {
986 pvr_dump_field_member_u32(base_ctx, &index_list9, split_count);
987 } else {
988 pvr_dump_field_member_not_present(base_ctx, &index_list9, split_count);
989 }
990
991 ret = true;
992
993 end_pop_ctx:
994 pvr_dump_csb_block_ctx_pop(&ctx);
995
996 end_out:
997 return ret ? words_read : 0;
998 }
999
1000 static uint32_t
print_block_vdmctrl_stream_link(struct pvr_dump_csb_ctx * const csb_ctx)1001 print_block_vdmctrl_stream_link(struct pvr_dump_csb_ctx *const csb_ctx)
1002 {
1003 struct pvr_dump_csb_block_ctx ctx;
1004 struct pvr_dump_ctx *const base_ctx = &ctx.base.base;
1005 uint32_t words_read = 0;
1006 bool ret = false;
1007
1008 struct PVRX(VDMCTRL_STREAM_LINK0) link0 = { 0 };
1009 struct PVRX(VDMCTRL_STREAM_LINK1) link1 = { 0 };
1010
1011 if (!pvr_dump_csb_block_ctx_push(&ctx, csb_ctx, "STREAM_LINK"))
1012 goto end_out;
1013
1014 if (!pvr_dump_csb_block_take_packed(&ctx, VDMCTRL_STREAM_LINK0, &link0) ||
1015 !pvr_dump_csb_block_take_packed(&ctx, VDMCTRL_STREAM_LINK1, &link1)) {
1016 goto end_pop_ctx;
1017 }
1018 words_read += 2;
1019
1020 pvr_dump_field_member_bool(base_ctx, &link0, with_return);
1021
1022 if (link0.compare_present) {
1023 pvr_dump_field_member_u32(base_ctx, &link0, compare_mode);
1024 pvr_dump_field_member_u32(base_ctx, &link0, compare_data);
1025 } else {
1026 pvr_dump_field_member_not_present(base_ctx, &link0, compare_mode);
1027 pvr_dump_field_member_not_present(base_ctx, &link0, compare_data);
1028 }
1029
1030 pvr_dump_field_addr_split(base_ctx,
1031 "link_addr",
1032 link0.link_addrmsb,
1033 link1.link_addrlsb);
1034
1035 ret = true;
1036
1037 end_pop_ctx:
1038 pvr_dump_csb_block_ctx_pop(&ctx);
1039
1040 end_out:
1041 return ret ? words_read : 0;
1042 }
1043
1044 static uint32_t
print_block_vdmctrl_stream_return(struct pvr_dump_csb_ctx * const csb_ctx)1045 print_block_vdmctrl_stream_return(struct pvr_dump_csb_ctx *const csb_ctx)
1046 {
1047 struct pvr_dump_csb_block_ctx ctx;
1048 struct pvr_dump_ctx *const base_ctx = &ctx.base.base;
1049 uint32_t words_read = 0;
1050 bool ret = false;
1051
1052 struct PVRX(VDMCTRL_STREAM_RETURN) return_ = { 0 };
1053
1054 if (!pvr_dump_csb_block_ctx_push(&ctx, csb_ctx, "STREAM_RETURN"))
1055 goto end_out;
1056
1057 if (!pvr_dump_csb_block_take_packed(&ctx, VDMCTRL_STREAM_RETURN, &return_))
1058 goto end_pop_ctx;
1059 words_read += 1;
1060
1061 pvr_dump_field_no_fields(base_ctx);
1062
1063 ret = true;
1064
1065 end_pop_ctx:
1066 pvr_dump_csb_block_ctx_pop(&ctx);
1067
1068 end_out:
1069 return ret ? words_read : 0;
1070 }
1071
1072 static uint32_t
print_block_vdmctrl_stream_terminate(struct pvr_dump_csb_ctx * const csb_ctx)1073 print_block_vdmctrl_stream_terminate(struct pvr_dump_csb_ctx *const csb_ctx)
1074 {
1075 struct pvr_dump_csb_block_ctx ctx;
1076 struct pvr_dump_ctx *const base_ctx = &ctx.base.base;
1077 uint32_t words_read = 0;
1078 bool ret = false;
1079
1080 struct PVRX(VDMCTRL_STREAM_TERMINATE) terminate = { 0 };
1081
1082 if (!pvr_dump_csb_block_ctx_push(&ctx, csb_ctx, "TERMINATE"))
1083 goto end_out;
1084
1085 if (!pvr_dump_csb_block_take_packed(&ctx,
1086 VDMCTRL_STREAM_TERMINATE,
1087 &terminate)) {
1088 goto end_pop_ctx;
1089 }
1090 words_read += 1;
1091
1092 pvr_dump_field_member_bool(base_ctx, &terminate, context);
1093
1094 ret = true;
1095
1096 end_pop_ctx:
1097 pvr_dump_csb_block_ctx_pop(&ctx);
1098
1099 end_out:
1100 return ret ? words_read : 0;
1101 }
1102
1103 static uint32_t
print_block_ppp_state_header(struct pvr_dump_csb_ctx * const csb_ctx,struct PVRX (TA_STATE_HEADER)* const header_out)1104 print_block_ppp_state_header(struct pvr_dump_csb_ctx *const csb_ctx,
1105 struct PVRX(TA_STATE_HEADER) *const header_out)
1106 {
1107 struct pvr_dump_csb_block_ctx ctx;
1108 struct pvr_dump_ctx *const base_ctx = &ctx.base.base;
1109 uint32_t words_read = 0;
1110 bool ret = false;
1111
1112 struct PVRX(TA_STATE_HEADER) header = { 0 };
1113
1114 if (!pvr_dump_csb_block_ctx_push(&ctx, csb_ctx, "STATE_HEADER"))
1115 goto end_out;
1116
1117 if (!pvr_dump_csb_block_take_packed(&ctx, TA_STATE_HEADER, &header))
1118 goto end_pop_ctx;
1119 words_read += 1;
1120
1121 pvr_dump_field_member_bool(base_ctx, &header, pres_ispctl);
1122 pvr_dump_field_member_bool(base_ctx, &header, pres_ispctl_fa);
1123 pvr_dump_field_member_bool(base_ctx, &header, pres_ispctl_fb);
1124 pvr_dump_field_member_bool(base_ctx, &header, pres_ispctl_ba);
1125 pvr_dump_field_member_bool(base_ctx, &header, pres_ispctl_bb);
1126 pvr_dump_field_member_bool(base_ctx, &header, pres_ispctl_dbsc);
1127 pvr_dump_field_member_bool(base_ctx, &header, pres_pds_state_ptr0);
1128 pvr_dump_field_member_bool(base_ctx, &header, pres_pds_state_ptr1);
1129 pvr_dump_field_member_bool(base_ctx, &header, pres_pds_state_ptr2);
1130 pvr_dump_field_member_bool(base_ctx, &header, pres_pds_state_ptr3);
1131 pvr_dump_field_member_bool(base_ctx, &header, pres_region_clip);
1132 pvr_dump_field_member_bool(base_ctx, &header, pres_viewport);
1133 pvr_dump_field_member_u32_offset(base_ctx, &header, view_port_count, 1);
1134 pvr_dump_field_member_bool(base_ctx, &header, pres_wclamp);
1135 pvr_dump_field_member_bool(base_ctx, &header, pres_outselects);
1136 pvr_dump_field_member_bool(base_ctx, &header, pres_varying_word0);
1137 pvr_dump_field_member_bool(base_ctx, &header, pres_varying_word1);
1138 pvr_dump_field_member_bool(base_ctx, &header, pres_varying_word2);
1139 pvr_dump_field_member_bool(base_ctx, &header, pres_ppp_ctrl);
1140 pvr_dump_field_member_bool(base_ctx, &header, pres_stream_out_size);
1141 pvr_dump_field_member_bool(base_ctx, &header, pres_stream_out_program);
1142 pvr_dump_field_member_bool(base_ctx, &header, context_switch);
1143 pvr_dump_field_member_bool(base_ctx, &header, pres_terminate);
1144 pvr_dump_field_member_bool(base_ctx, &header, not_final_term);
1145
1146 if (header_out)
1147 *header_out = header;
1148
1149 ret = true;
1150
1151 end_pop_ctx:
1152 pvr_dump_csb_block_ctx_pop(&ctx);
1153
1154 end_out:
1155 return ret ? words_read : 0;
1156 }
1157
print_block_ppp_state_isp_one_side(struct pvr_dump_csb_block_ctx * const ctx,const struct PVRX (TA_STATE_ISPA)* const isp_a,const struct PVRX (TA_STATE_ISPB)* const isp_b,const bool has_b)1158 static void print_block_ppp_state_isp_one_side(
1159 struct pvr_dump_csb_block_ctx *const ctx,
1160 const struct PVRX(TA_STATE_ISPA) *const isp_a,
1161 const struct PVRX(TA_STATE_ISPB) *const isp_b,
1162 const bool has_b)
1163 {
1164 struct pvr_dump_ctx *const base_ctx = &ctx->base.base;
1165
1166 pvr_dump_indent(base_ctx);
1167
1168 pvr_dump_field_member_enum(base_ctx,
1169 isp_a,
1170 objtype,
1171 pvr_cmd_enum_to_str(TA_OBJTYPE));
1172 pvr_dump_field_member_enum(base_ctx,
1173 isp_a,
1174 passtype,
1175 pvr_cmd_enum_to_str(TA_PASSTYPE));
1176 pvr_dump_field_member_bool(base_ctx, isp_a, ovgvispassmaskop);
1177 pvr_dump_field_member_bool(base_ctx, isp_a, maskval);
1178 pvr_dump_field_member_bool(base_ctx, isp_a, dwritedisable);
1179 pvr_dump_field_member_bool(base_ctx, isp_a, dfbztestenable);
1180 pvr_dump_field_member_enum(base_ctx,
1181 isp_a,
1182 dcmpmode,
1183 pvr_cmd_enum_to_str(TA_CMPMODE));
1184 pvr_dump_field_member_bool(base_ctx, isp_a, linefilllastpixel);
1185 pvr_dump_field_member_uq4_4_offset(base_ctx, isp_a, pointlinewidth, 0x01);
1186 pvr_dump_field_member_u32(base_ctx, isp_a, sref);
1187
1188 if (has_b) {
1189 pvr_dump_field_member_enum(base_ctx,
1190 isp_b,
1191 scmpmode,
1192 pvr_cmd_enum_to_str(TA_CMPMODE));
1193 pvr_dump_field_member_enum(base_ctx,
1194 isp_b,
1195 sop1,
1196 pvr_cmd_enum_to_str(TA_ISPB_STENCILOP));
1197 pvr_dump_field_member_enum(base_ctx,
1198 isp_b,
1199 sop2,
1200 pvr_cmd_enum_to_str(TA_ISPB_STENCILOP));
1201 pvr_dump_field_member_enum(base_ctx,
1202 isp_b,
1203 sop3,
1204 pvr_cmd_enum_to_str(TA_ISPB_STENCILOP));
1205 pvr_dump_field_member_x32(base_ctx, isp_b, scmpmask, 2);
1206 pvr_dump_field_member_x32(base_ctx, isp_b, swmask, 2);
1207 } else {
1208 pvr_dump_field_member_not_present(base_ctx, isp_b, scmpmode);
1209 pvr_dump_field_member_not_present(base_ctx, isp_b, sop1);
1210 pvr_dump_field_member_not_present(base_ctx, isp_b, sop2);
1211 pvr_dump_field_member_not_present(base_ctx, isp_b, sop3);
1212 pvr_dump_field_member_not_present(base_ctx, isp_b, scmpmask);
1213 pvr_dump_field_member_not_present(base_ctx, isp_b, swmask);
1214 }
1215
1216 pvr_dump_dedent(base_ctx);
1217 }
1218
1219 static uint32_t
print_block_ppp_state_isp(struct pvr_dump_csb_ctx * const csb_ctx,const bool has_fa,const bool has_fb,const bool has_ba,const bool has_bb,const bool has_dbsc)1220 print_block_ppp_state_isp(struct pvr_dump_csb_ctx *const csb_ctx,
1221 const bool has_fa,
1222 const bool has_fb,
1223 const bool has_ba,
1224 const bool has_bb,
1225 const bool has_dbsc)
1226 {
1227 struct pvr_dump_csb_block_ctx ctx;
1228 struct pvr_dump_ctx *const base_ctx = &ctx.base.base;
1229 uint32_t words_read = 0;
1230 bool ret = false;
1231
1232 struct PVRX(TA_STATE_ISPCTL) isp_ctl = { 0 };
1233 struct PVRX(TA_STATE_ISPA) isp_fa = { 0 };
1234 struct PVRX(TA_STATE_ISPB) isp_fb = { 0 };
1235 struct PVRX(TA_STATE_ISPA) isp_ba = { 0 };
1236 struct PVRX(TA_STATE_ISPB) isp_bb = { 0 };
1237 struct PVRX(TA_STATE_ISPDBSC) isp_dbsc = { 0 };
1238
1239 if (!pvr_dump_csb_block_ctx_push(&ctx, csb_ctx, "STATE_ISP"))
1240 goto end_out;
1241
1242 if (!pvr_dump_csb_block_take_packed(&ctx, TA_STATE_ISPCTL, &isp_ctl))
1243 goto end_pop_ctx;
1244 words_read += 1;
1245
1246 /* In most blocks, we try to read all words before printing anything. In
1247 * this case, there can be ambiguity in which words to parse (which results
1248 * in an error from the conditional below). To aid in debugging when this
1249 * ambiguity is present, print the control word's contents before continuing
1250 * so the fields which create the ambiguity are dumped even when the rest of
1251 * the block isn't.
1252 */
1253 pvr_dump_field_member_u32(base_ctx, &isp_ctl, visreg);
1254 pvr_dump_field_member_bool(base_ctx, &isp_ctl, visbool);
1255 pvr_dump_field_member_bool(base_ctx, &isp_ctl, vistest);
1256 pvr_dump_field_member_bool(base_ctx, &isp_ctl, scenable);
1257 pvr_dump_field_member_bool(base_ctx, &isp_ctl, dbenable);
1258 pvr_dump_field_member_bool(base_ctx, &isp_ctl, bpres);
1259 pvr_dump_field_member_bool(base_ctx, &isp_ctl, two_sided);
1260 pvr_dump_field_member_bool(base_ctx, &isp_ctl, ovgmtestdisable);
1261 pvr_dump_field_member_bool(base_ctx, &isp_ctl, tagwritedisable);
1262 pvr_dump_field_member_u32(base_ctx, &isp_ctl, upass);
1263 pvr_dump_field_member_u32(base_ctx, &isp_ctl, validid);
1264
1265 if (!has_fa || has_fb != isp_ctl.bpres || has_ba != isp_ctl.two_sided ||
1266 has_bb != (isp_ctl.bpres && isp_ctl.two_sided)) {
1267 pvr_dump_error(
1268 base_ctx,
1269 "words declared by ppp header do not match requirements of ispctl word");
1270 goto end_pop_ctx;
1271 }
1272
1273 if (!pvr_dump_csb_block_take_packed(&ctx, TA_STATE_ISPA, &isp_fa))
1274 return false;
1275 words_read += 1;
1276
1277 if (has_fb) {
1278 if (!pvr_dump_csb_block_take_packed(&ctx, TA_STATE_ISPB, &isp_fb))
1279 return false;
1280 words_read += 1;
1281 }
1282
1283 if (has_ba) {
1284 if (!pvr_dump_csb_block_take_packed(&ctx, TA_STATE_ISPA, &isp_ba))
1285 return false;
1286 words_read += 1;
1287 }
1288
1289 if (has_bb) {
1290 if (!pvr_dump_csb_block_take_packed(&ctx, TA_STATE_ISPB, &isp_bb))
1291 return false;
1292 words_read += 1;
1293 }
1294
1295 if (has_dbsc) {
1296 if (!pvr_dump_csb_block_take_packed(&ctx, TA_STATE_ISPDBSC, &isp_dbsc))
1297 goto end_pop_ctx;
1298 words_read += 1;
1299 }
1300
1301 pvr_dump_println(base_ctx, "front");
1302 print_block_ppp_state_isp_one_side(&ctx, &isp_fa, &isp_fb, isp_ctl.bpres);
1303
1304 if (isp_ctl.two_sided) {
1305 pvr_dump_println(base_ctx, "back");
1306 print_block_ppp_state_isp_one_side(&ctx, &isp_ba, &isp_bb, isp_ctl.bpres);
1307 } else {
1308 pvr_dump_field_not_present(base_ctx, "back");
1309 }
1310
1311 if (has_dbsc) {
1312 pvr_dump_field_member_u32(base_ctx, &isp_dbsc, dbindex);
1313 pvr_dump_field_member_u32(base_ctx, &isp_dbsc, scindex);
1314 } else {
1315 pvr_dump_field_member_not_present(base_ctx, &isp_dbsc, dbindex);
1316 pvr_dump_field_member_not_present(base_ctx, &isp_dbsc, scindex);
1317 }
1318
1319 ret = true;
1320
1321 end_pop_ctx:
1322 pvr_dump_csb_block_ctx_pop(&ctx);
1323
1324 end_out:
1325 return ret ? words_read : 0;
1326 }
1327
1328 static uint32_t
print_block_ppp_state_pds(struct pvr_dump_csb_ctx * const csb_ctx,struct pvr_device * const device,const bool has_initial_words,const bool has_varying,const bool has_texturedata,const bool has_uniformdata)1329 print_block_ppp_state_pds(struct pvr_dump_csb_ctx *const csb_ctx,
1330 struct pvr_device *const device,
1331 const bool has_initial_words,
1332 const bool has_varying,
1333 const bool has_texturedata,
1334 const bool has_uniformdata)
1335 {
1336 const pvr_dev_addr_t pds_heap_base = device->heaps.pds_heap->base_addr;
1337
1338 struct pvr_dump_csb_block_ctx ctx;
1339 struct pvr_dump_ctx *const base_ctx = &ctx.base.base;
1340 uint32_t words_read = 0;
1341 bool ret = false;
1342
1343 struct PVRX(TA_STATE_PDS_SHADERBASE) shader_base = { 0 };
1344 struct PVRX(TA_STATE_PDS_TEXUNICODEBASE) tex_unicode_base = { 0 };
1345 struct PVRX(TA_STATE_PDS_SIZEINFO1) size_info1 = { 0 };
1346 struct PVRX(TA_STATE_PDS_SIZEINFO2) size_info2 = { 0 };
1347 struct PVRX(TA_STATE_PDS_VARYINGBASE) varying_base = { 0 };
1348 struct PVRX(TA_STATE_PDS_TEXTUREDATABASE) texture_data_base = { 0 };
1349 struct PVRX(TA_STATE_PDS_UNIFORMDATABASE) uniform_data_base = { 0 };
1350
1351 if (!pvr_dump_csb_block_ctx_push(&ctx, csb_ctx, "STATE_PDS"))
1352 goto end_out;
1353
1354 if (has_initial_words) {
1355 if (!pvr_dump_csb_block_take_packed(&ctx,
1356 TA_STATE_PDS_SHADERBASE,
1357 &shader_base) ||
1358 !pvr_dump_csb_block_take_packed(&ctx,
1359 TA_STATE_PDS_TEXUNICODEBASE,
1360 &tex_unicode_base) ||
1361 !pvr_dump_csb_block_take_packed(&ctx,
1362 TA_STATE_PDS_SIZEINFO1,
1363 &size_info1) ||
1364 !pvr_dump_csb_block_take_packed(&ctx,
1365 TA_STATE_PDS_SIZEINFO2,
1366 &size_info2)) {
1367 goto end_pop_ctx;
1368 }
1369 words_read += 4;
1370 }
1371
1372 if (has_varying) {
1373 if (!pvr_dump_csb_block_take_packed(&ctx,
1374 TA_STATE_PDS_VARYINGBASE,
1375 &varying_base)) {
1376 goto end_pop_ctx;
1377 }
1378 words_read += 1;
1379 }
1380
1381 if (has_texturedata) {
1382 if (!pvr_dump_csb_block_take_packed(&ctx,
1383 TA_STATE_PDS_TEXTUREDATABASE,
1384 &texture_data_base)) {
1385 goto end_pop_ctx;
1386 }
1387 words_read += 1;
1388 }
1389
1390 if (has_uniformdata) {
1391 if (!pvr_dump_csb_block_take_packed(&ctx,
1392 TA_STATE_PDS_UNIFORMDATABASE,
1393 &uniform_data_base)) {
1394 goto end_pop_ctx;
1395 }
1396 words_read += 1;
1397 }
1398
1399 if (has_initial_words) {
1400 pvr_dump_field_addr_offset(base_ctx,
1401 "shaderbase",
1402 shader_base.addr,
1403 pds_heap_base);
1404 pvr_dump_field_addr_offset(base_ctx,
1405 "texunicodebase",
1406 tex_unicode_base.addr,
1407 pds_heap_base);
1408
1409 pvr_dump_field_member_u32_scaled_units(
1410 base_ctx,
1411 &size_info1,
1412 pds_uniformsize,
1413 PVRX(TA_STATE_PDS_SIZEINFO1_PDS_UNIFORMSIZE_UNIT_SIZE),
1414 "words");
1415 pvr_dump_field_member_u32_scaled_units(
1416 base_ctx,
1417 &size_info1,
1418 pds_texturestatesize,
1419 PVRX(TA_STATE_PDS_SIZEINFO1_PDS_TEXTURESTATESIZE_UNIT_SIZE),
1420 "words");
1421 pvr_dump_field_member_u32_scaled_units(
1422 base_ctx,
1423 &size_info1,
1424 pds_varyingsize,
1425 PVRX(TA_STATE_PDS_SIZEINFO1_PDS_VARYINGSIZE_UNIT_SIZE),
1426 "words");
1427 pvr_dump_field_member_u32_scaled_units(
1428 base_ctx,
1429 &size_info1,
1430 usc_varyingsize,
1431 PVRX(TA_STATE_PDS_SIZEINFO1_USC_VARYINGSIZE_UNIT_SIZE),
1432 "words");
1433 pvr_dump_field_member_u32_scaled_units(
1434 base_ctx,
1435 &size_info1,
1436 pds_tempsize,
1437 PVRX(TA_STATE_PDS_SIZEINFO1_PDS_TEMPSIZE_UNIT_SIZE),
1438 "words");
1439
1440 pvr_dump_field_member_u32_scaled_units(
1441 base_ctx,
1442 &size_info2,
1443 usc_sharedsize,
1444 PVRX(TA_STATE_PDS_SIZEINFO2_USC_SHAREDSIZE_UNIT_SIZE),
1445 "words");
1446 pvr_dump_field_member_bool(base_ctx, &size_info2, pds_tri_merge_disable);
1447 pvr_dump_field_member_u32(base_ctx, &size_info2, pds_batchnum);
1448 } else {
1449 pvr_dump_field_not_present(base_ctx, "shaderbase");
1450 pvr_dump_field_not_present(base_ctx, "texunicodebase");
1451 pvr_dump_field_member_not_present(base_ctx, &size_info1, pds_uniformsize);
1452 pvr_dump_field_member_not_present(base_ctx,
1453 &size_info1,
1454 pds_texturestatesize);
1455 pvr_dump_field_member_not_present(base_ctx, &size_info1, pds_varyingsize);
1456 pvr_dump_field_member_not_present(base_ctx, &size_info1, usc_varyingsize);
1457 pvr_dump_field_member_not_present(base_ctx, &size_info1, pds_tempsize);
1458 pvr_dump_field_member_not_present(base_ctx, &size_info2, usc_sharedsize);
1459 pvr_dump_field_member_not_present(base_ctx,
1460 &size_info2,
1461 pds_tri_merge_disable);
1462 pvr_dump_field_member_not_present(base_ctx, &size_info2, pds_batchnum);
1463 }
1464
1465 if (has_varying) {
1466 pvr_dump_field_addr_offset(base_ctx,
1467 "varyingbase",
1468 varying_base.addr,
1469 pds_heap_base);
1470 } else {
1471 pvr_dump_field_not_present(base_ctx, "varyingbase");
1472 }
1473
1474 if (has_texturedata) {
1475 pvr_dump_field_addr_offset(base_ctx,
1476 "texturedatabase",
1477 texture_data_base.addr,
1478 pds_heap_base);
1479 } else {
1480 pvr_dump_field_not_present(base_ctx, "texturedatabase");
1481 }
1482
1483 if (has_uniformdata) {
1484 pvr_dump_field_addr_offset(base_ctx,
1485 "uniformdatabase",
1486 uniform_data_base.addr,
1487 pds_heap_base);
1488 } else {
1489 pvr_dump_field_not_present(base_ctx, "uniformdatabase");
1490 }
1491
1492 ret = true;
1493
1494 end_pop_ctx:
1495 pvr_dump_csb_block_ctx_pop(&ctx);
1496
1497 end_out:
1498 return ret ? words_read : 0;
1499 }
1500
1501 static uint32_t
print_block_ppp_region_clip(struct pvr_dump_csb_ctx * const csb_ctx)1502 print_block_ppp_region_clip(struct pvr_dump_csb_ctx *const csb_ctx)
1503 {
1504 struct pvr_dump_csb_block_ctx ctx;
1505 struct pvr_dump_ctx *const base_ctx = &ctx.base.base;
1506 uint32_t words_read = 0;
1507 bool ret = false;
1508
1509 struct PVRX(TA_REGION_CLIP0) clip0 = { 0 };
1510 struct PVRX(TA_REGION_CLIP1) clip1 = { 0 };
1511
1512 if (!pvr_dump_csb_block_ctx_push(&ctx, csb_ctx, "REGION_CLIP"))
1513 goto end_out;
1514
1515 if (!pvr_dump_csb_block_take_packed(&ctx, TA_REGION_CLIP0, &clip0) ||
1516 !pvr_dump_csb_block_take_packed(&ctx, TA_REGION_CLIP1, &clip1)) {
1517 goto end_pop_ctx;
1518 }
1519 words_read += 2;
1520
1521 pvr_dump_field_member_enum(base_ctx,
1522 &clip0,
1523 mode,
1524 pvr_cmd_enum_to_str(TA_REGION_CLIP_MODE));
1525 pvr_dump_field_member_u32_scaled_units(base_ctx, &clip0, left, 32, "pixels");
1526 pvr_dump_field_member_u32_scaled_units(base_ctx, &clip0, right, 32, "pixels");
1527
1528 pvr_dump_field_member_u32_scaled_units(base_ctx, &clip1, top, 32, "pixels");
1529 pvr_dump_field_member_u32_scaled_units(base_ctx,
1530 &clip1,
1531 bottom,
1532 32,
1533 "pixels");
1534
1535 ret = true;
1536
1537 end_pop_ctx:
1538 pvr_dump_csb_block_ctx_pop(&ctx);
1539
1540 end_out:
1541 return ret ? words_read : 0;
1542 }
1543
print_block_ppp_viewport(struct pvr_dump_csb_ctx * const csb_ctx,const uint32_t idx)1544 static uint32_t print_block_ppp_viewport(struct pvr_dump_csb_ctx *const csb_ctx,
1545 const uint32_t idx)
1546 {
1547 static char const *const field_names[] = {
1548 "a0", "m0", "a1", "m1", "a2", "m2"
1549 };
1550
1551 struct pvr_dump_csb_block_ctx ctx;
1552 struct pvr_dump_ctx *const base_ctx = &ctx.base.base;
1553 uint32_t words_read = 0;
1554 bool ret = false;
1555
1556 STATIC_ASSERT(sizeof(float) == 4);
1557
1558 if (!pvr_dump_csb_block_ctx_push(&ctx, csb_ctx, "VIEWPORT %" PRIu32, idx))
1559 goto end_out;
1560
1561 for (uint32_t i = 0; i < ARRAY_SIZE(field_names); i++) {
1562 const uint32_t *const value = pvr_dump_csb_block_take(&ctx, 1);
1563 if (!value)
1564 goto end_pop_ctx;
1565 words_read += 1;
1566
1567 pvr_dump_field_f32(base_ctx, field_names[i], uif(*value));
1568 }
1569
1570 ret = true;
1571
1572 end_pop_ctx:
1573 pvr_dump_csb_block_ctx_pop(&ctx);
1574
1575 end_out:
1576 return ret ? words_read : 0;
1577 }
1578
print_block_ppp_wclamp(struct pvr_dump_csb_ctx * const csb_ctx)1579 static uint32_t print_block_ppp_wclamp(struct pvr_dump_csb_ctx *const csb_ctx)
1580 {
1581 struct pvr_dump_csb_block_ctx ctx;
1582 struct pvr_dump_ctx *const base_ctx = &ctx.base.base;
1583 uint32_t words_read = 0;
1584 bool ret = false;
1585
1586 STATIC_ASSERT(sizeof(float) == 4);
1587
1588 if (!pvr_dump_csb_block_ctx_push(&ctx, csb_ctx, "WCLAMP"))
1589 goto end_out;
1590
1591 const uint32_t *const value = pvr_dump_csb_block_take(&ctx, 1);
1592 if (!value)
1593 goto end_pop_ctx;
1594 words_read += 1;
1595
1596 pvr_dump_field_f32(base_ctx, "value", uif(*value));
1597
1598 ret = true;
1599
1600 end_pop_ctx:
1601 pvr_dump_csb_block_ctx_pop(&ctx);
1602
1603 end_out:
1604 return ret ? words_read : 0;
1605 }
1606
1607 static uint32_t
print_block_ppp_output_sel(struct pvr_dump_csb_ctx * const csb_ctx)1608 print_block_ppp_output_sel(struct pvr_dump_csb_ctx *const csb_ctx)
1609 {
1610 struct pvr_dump_csb_block_ctx ctx;
1611 struct pvr_dump_ctx *const base_ctx = &ctx.base.base;
1612 uint32_t words_read = 0;
1613 bool ret = false;
1614
1615 struct PVRX(TA_OUTPUT_SEL) output_sel = { 0 };
1616
1617 if (!pvr_dump_csb_block_ctx_push(&ctx, csb_ctx, "OUTPUT_SEL"))
1618 goto end_out;
1619
1620 if (!pvr_dump_csb_block_take_packed(&ctx, TA_OUTPUT_SEL, &output_sel))
1621 goto end_pop_ctx;
1622 words_read += 1;
1623
1624 pvr_dump_field_member_bool(base_ctx, &output_sel, plane0);
1625 pvr_dump_field_member_bool(base_ctx, &output_sel, plane1);
1626 pvr_dump_field_member_bool(base_ctx, &output_sel, plane2);
1627 pvr_dump_field_member_bool(base_ctx, &output_sel, plane3);
1628 pvr_dump_field_member_bool(base_ctx, &output_sel, plane4);
1629 pvr_dump_field_member_bool(base_ctx, &output_sel, plane5);
1630 pvr_dump_field_member_bool(base_ctx, &output_sel, plane6);
1631 pvr_dump_field_member_bool(base_ctx, &output_sel, plane7);
1632 pvr_dump_field_member_bool(base_ctx, &output_sel, cullplane0);
1633 pvr_dump_field_member_bool(base_ctx, &output_sel, cullplane1);
1634 pvr_dump_field_member_bool(base_ctx, &output_sel, cullplane2);
1635 pvr_dump_field_member_bool(base_ctx, &output_sel, cullplane3);
1636 pvr_dump_field_member_bool(base_ctx, &output_sel, cullplane4);
1637 pvr_dump_field_member_bool(base_ctx, &output_sel, cullplane5);
1638 pvr_dump_field_member_bool(base_ctx, &output_sel, cullplane6);
1639 pvr_dump_field_member_bool(base_ctx, &output_sel, cullplane7);
1640 pvr_dump_field_member_bool(base_ctx, &output_sel, rhw_pres);
1641 pvr_dump_field_member_bool(base_ctx,
1642 &output_sel,
1643 isp_position_depth_clamp_z);
1644 pvr_dump_field_member_bool(base_ctx, &output_sel, psprite_size_pres);
1645 pvr_dump_field_member_bool(base_ctx, &output_sel, vpt_tgt_pres);
1646 pvr_dump_field_member_bool(base_ctx, &output_sel, render_tgt_pres);
1647 pvr_dump_field_member_bool(base_ctx, &output_sel, tsp_unclamped_z_pres);
1648 pvr_dump_field_member_u32(base_ctx, &output_sel, vtxsize);
1649
1650 ret = true;
1651
1652 end_pop_ctx:
1653 pvr_dump_csb_block_ctx_pop(&ctx);
1654
1655 end_out:
1656 return ret ? words_read : 0;
1657 }
1658
1659 static uint32_t
print_block_ppp_state_varying(struct pvr_dump_csb_ctx * const csb_ctx,const bool has_word0,const bool has_word1,const bool has_word2)1660 print_block_ppp_state_varying(struct pvr_dump_csb_ctx *const csb_ctx,
1661 const bool has_word0,
1662 const bool has_word1,
1663 const bool has_word2)
1664 {
1665 struct pvr_dump_csb_block_ctx ctx;
1666 struct pvr_dump_ctx *const base_ctx = &ctx.base.base;
1667 uint32_t words_read = 0;
1668 bool ret = false;
1669
1670 struct PVRX(TA_STATE_VARYING0) varying0 = { 0 };
1671 struct PVRX(TA_STATE_VARYING1) varying1 = { 0 };
1672 struct PVRX(TA_STATE_VARYING2) varying2 = { 0 };
1673
1674 if (!pvr_dump_csb_block_ctx_push(&ctx, csb_ctx, "STATE_VARYING"))
1675 goto end_out;
1676
1677 if (has_word0) {
1678 if (!pvr_dump_csb_block_take_packed(&ctx, TA_STATE_VARYING0, &varying0))
1679 goto end_pop_ctx;
1680 words_read += 1;
1681 }
1682
1683 if (has_word1) {
1684 if (!pvr_dump_csb_block_take_packed(&ctx, TA_STATE_VARYING1, &varying1))
1685 goto end_pop_ctx;
1686 words_read += 1;
1687 }
1688
1689 if (has_word2) {
1690 if (!pvr_dump_csb_block_take_packed(&ctx, TA_STATE_VARYING2, &varying2))
1691 goto end_pop_ctx;
1692 words_read += 1;
1693 }
1694
1695 if (has_word0) {
1696 pvr_dump_field_member_u32(base_ctx, &varying0, f32_linear);
1697 pvr_dump_field_member_u32(base_ctx, &varying0, f32_flat);
1698 pvr_dump_field_member_u32(base_ctx, &varying0, f32_npc);
1699 } else {
1700 pvr_dump_field_member_not_present(base_ctx, &varying0, f32_linear);
1701 pvr_dump_field_member_not_present(base_ctx, &varying0, f32_flat);
1702 pvr_dump_field_member_not_present(base_ctx, &varying0, f32_npc);
1703 }
1704
1705 if (has_word1) {
1706 pvr_dump_field_member_u32(base_ctx, &varying1, f16_linear);
1707 pvr_dump_field_member_u32(base_ctx, &varying1, f16_flat);
1708 pvr_dump_field_member_u32(base_ctx, &varying1, f16_npc);
1709 } else {
1710 pvr_dump_field_member_not_present(base_ctx, &varying1, f16_linear);
1711 pvr_dump_field_member_not_present(base_ctx, &varying1, f16_flat);
1712 pvr_dump_field_member_not_present(base_ctx, &varying1, f16_npc);
1713 }
1714
1715 if (has_word2) {
1716 pvr_dump_field_member_u32(base_ctx, &varying2, output_clip_planes);
1717 } else {
1718 pvr_dump_field_member_not_present(base_ctx,
1719 &varying2,
1720 output_clip_planes);
1721 }
1722
1723 ret = true;
1724
1725 end_pop_ctx:
1726 pvr_dump_csb_block_ctx_pop(&ctx);
1727
1728 end_out:
1729 return ret ? words_read : 0;
1730 }
1731
1732 static uint32_t
print_block_ppp_state_ppp_ctrl(struct pvr_dump_csb_ctx * const csb_ctx)1733 print_block_ppp_state_ppp_ctrl(struct pvr_dump_csb_ctx *const csb_ctx)
1734 {
1735 struct pvr_dump_csb_block_ctx ctx;
1736 struct pvr_dump_ctx *const base_ctx = &ctx.base.base;
1737 uint32_t words_read = 0;
1738 bool ret = false;
1739
1740 struct PVRX(TA_STATE_PPP_CTRL) ppp_ctrl = { 0 };
1741
1742 if (!pvr_dump_csb_block_ctx_push(&ctx, csb_ctx, "STATE_PPP_CTRL"))
1743 goto end_out;
1744
1745 if (!pvr_dump_csb_block_take_packed(&ctx, TA_STATE_PPP_CTRL, &ppp_ctrl))
1746 goto end_pop_ctx;
1747 words_read += 1;
1748
1749 pvr_dump_field_member_enum(base_ctx,
1750 &ppp_ctrl,
1751 cullmode,
1752 pvr_cmd_enum_to_str(TA_CULLMODE));
1753 pvr_dump_field_member_bool(base_ctx, &ppp_ctrl, updatebbox);
1754 pvr_dump_field_member_bool(base_ctx, &ppp_ctrl, resetbbox);
1755 pvr_dump_field_member_bool(base_ctx, &ppp_ctrl, wbuffen);
1756 pvr_dump_field_member_bool(base_ctx, &ppp_ctrl, wclampen);
1757 pvr_dump_field_member_bool(base_ctx, &ppp_ctrl, pretransform);
1758 pvr_dump_field_member_enum(base_ctx,
1759 &ppp_ctrl,
1760 flatshade_vtx,
1761 pvr_cmd_enum_to_str(TA_FLATSHADE));
1762 pvr_dump_field_member_bool(base_ctx, &ppp_ctrl, drawclippededges);
1763 pvr_dump_field_member_enum(base_ctx,
1764 &ppp_ctrl,
1765 clip_mode,
1766 pvr_cmd_enum_to_str(TA_CLIP_MODE));
1767 pvr_dump_field_member_bool(base_ctx, &ppp_ctrl, pres_prim_id);
1768 pvr_dump_field_member_enum(base_ctx,
1769 &ppp_ctrl,
1770 gs_output_topology,
1771 pvr_cmd_enum_to_str(TA_GS_OUTPUT_TOPOLOGY));
1772 pvr_dump_field_member_bool(base_ctx, &ppp_ctrl, prim_msaa);
1773
1774 ret = true;
1775
1776 end_pop_ctx:
1777 pvr_dump_csb_block_ctx_pop(&ctx);
1778
1779 end_out:
1780 return ret ? words_read : 0;
1781 }
1782
1783 static uint32_t
print_block_ppp_state_stream_out(struct pvr_dump_csb_ctx * const csb_ctx,struct pvr_device * const device,const bool has_word0,const bool has_words12)1784 print_block_ppp_state_stream_out(struct pvr_dump_csb_ctx *const csb_ctx,
1785 struct pvr_device *const device,
1786 const bool has_word0,
1787 const bool has_words12)
1788 {
1789 const pvr_dev_addr_t pds_heap_base = device->heaps.pds_heap->base_addr;
1790
1791 struct pvr_dump_csb_block_ctx ctx;
1792 struct pvr_dump_ctx *const base_ctx = &ctx.base.base;
1793 uint32_t words_read = 0;
1794 bool ret = false;
1795
1796 struct PVRX(TA_STATE_STREAM_OUT0) stream_out0 = { 0 };
1797 struct PVRX(TA_STATE_STREAM_OUT1) stream_out1 = { 0 };
1798 struct PVRX(TA_STATE_STREAM_OUT2) stream_out2 = { 0 };
1799
1800 if (!pvr_dump_csb_block_ctx_push(&ctx, csb_ctx, "STATE_STREAM_OUT"))
1801 goto end_out;
1802
1803 if (has_word0) {
1804 if (!pvr_dump_csb_block_take_packed(&ctx,
1805 TA_STATE_STREAM_OUT0,
1806 &stream_out0)) {
1807 goto end_pop_ctx;
1808 }
1809 words_read += 1;
1810 }
1811
1812 if (has_words12) {
1813 if (!pvr_dump_csb_block_take_packed(&ctx,
1814 TA_STATE_STREAM_OUT1,
1815 &stream_out1) ||
1816 !pvr_dump_csb_block_take_packed(&ctx,
1817 TA_STATE_STREAM_OUT2,
1818 &stream_out2)) {
1819 goto end_pop_ctx;
1820 }
1821 words_read += 2;
1822 }
1823
1824 if (has_word0) {
1825 pvr_dump_field_member_bool(base_ctx, &stream_out0, stream0_ta_output);
1826 pvr_dump_field_member_bool(base_ctx, &stream_out0, stream0_mem_output);
1827 pvr_dump_field_member_u32_units(base_ctx,
1828 &stream_out0,
1829 stream1_size,
1830 "words");
1831 pvr_dump_field_member_u32_units(base_ctx,
1832 &stream_out0,
1833 stream2_size,
1834 "words");
1835 pvr_dump_field_member_u32_units(base_ctx,
1836 &stream_out0,
1837 stream3_size,
1838 "words");
1839 } else {
1840 pvr_dump_field_member_not_present(base_ctx,
1841 &stream_out0,
1842 stream0_ta_output);
1843 pvr_dump_field_member_not_present(base_ctx,
1844 &stream_out0,
1845 stream0_mem_output);
1846 pvr_dump_field_member_not_present(base_ctx, &stream_out0, stream1_size);
1847 pvr_dump_field_member_not_present(base_ctx, &stream_out0, stream2_size);
1848 pvr_dump_field_member_not_present(base_ctx, &stream_out0, stream3_size);
1849 }
1850
1851 if (has_words12) {
1852 pvr_dump_field_member_u32_scaled_units(
1853 base_ctx,
1854 &stream_out1,
1855 pds_temp_size,
1856 PVRX(TA_STATE_STREAM_OUT1_PDS_TEMP_SIZE_UNIT_SIZE),
1857 "bytes");
1858 pvr_dump_field_member_u32_scaled_units(
1859 base_ctx,
1860 &stream_out1,
1861 pds_data_size,
1862 PVRX(TA_STATE_STREAM_OUT1_PDS_DATA_SIZE_UNIT_SIZE),
1863 "bytes");
1864 pvr_dump_field_member_bool(base_ctx, &stream_out1, sync);
1865 pvr_dump_field_member_addr_offset(base_ctx,
1866 &stream_out2,
1867 pds_data_addr,
1868 pds_heap_base);
1869 ret = print_sub_buffer(
1870 base_ctx,
1871 device,
1872 BUFFER_TYPE_NONE,
1873 PVR_DEV_ADDR_OFFSET(pds_heap_base, stream_out2.pds_data_addr.addr),
1874 stream_out1.pds_data_size,
1875 "pds_data_size");
1876 if (!ret)
1877 goto end_pop_ctx;
1878 } else {
1879 pvr_dump_field_member_not_present(base_ctx, &stream_out1, pds_temp_size);
1880 pvr_dump_field_member_not_present(base_ctx, &stream_out1, pds_data_size);
1881 pvr_dump_field_member_not_present(base_ctx, &stream_out1, sync);
1882 pvr_dump_field_member_not_present(base_ctx, &stream_out2, pds_data_addr);
1883 }
1884
1885 ret = true;
1886
1887 end_pop_ctx:
1888 pvr_dump_csb_block_ctx_pop(&ctx);
1889
1890 end_out:
1891 return ret ? words_read : 0;
1892 }
1893
1894 static uint32_t
print_block_ppp_state_terminate(struct pvr_dump_csb_ctx * const csb_ctx)1895 print_block_ppp_state_terminate(struct pvr_dump_csb_ctx *const csb_ctx)
1896 {
1897 struct pvr_dump_csb_block_ctx ctx;
1898 struct pvr_dump_ctx *const base_ctx = &ctx.base.base;
1899 uint32_t words_read = 0;
1900 bool ret = false;
1901
1902 struct PVRX(TA_STATE_TERMINATE0) terminate0 = { 0 };
1903 struct PVRX(TA_STATE_TERMINATE1) terminate1 = { 0 };
1904
1905 if (!pvr_dump_csb_block_ctx_push(&ctx, csb_ctx, "STATE_TERMINATE"))
1906 goto end_out;
1907
1908 if (!pvr_dump_csb_block_take_packed(&ctx, TA_STATE_TERMINATE0, &terminate0) ||
1909 !pvr_dump_csb_block_take_packed(&ctx, TA_STATE_TERMINATE1, &terminate1)) {
1910 goto end_pop_ctx;
1911 }
1912 words_read += 2;
1913
1914 pvr_dump_field_member_u32_scaled_units(base_ctx,
1915 &terminate0,
1916 clip_right,
1917 32,
1918 "pixels");
1919 pvr_dump_field_member_u32_scaled_units(base_ctx,
1920 &terminate0,
1921 clip_top,
1922 32,
1923 "pixels");
1924 pvr_dump_field_member_u32_scaled_units(base_ctx,
1925 &terminate0,
1926 clip_bottom,
1927 32,
1928 "pixels");
1929 pvr_dump_field_member_u32_scaled_units(base_ctx,
1930 &terminate1,
1931 clip_left,
1932 32,
1933 "pixels");
1934 pvr_dump_field_member_u32(base_ctx, &terminate1, render_target);
1935
1936 ret = true;
1937
1938 end_pop_ctx:
1939 pvr_dump_csb_block_ctx_pop(&ctx);
1940
1941 end_out:
1942 return ret ? words_read : 0;
1943 }
1944
1945 /******************************************************************************
1946 Buffer printers
1947 ******************************************************************************/
1948
print_block_hex(struct pvr_dump_buffer_ctx * const ctx,const uint32_t nr_words)1949 static bool print_block_hex(struct pvr_dump_buffer_ctx *const ctx,
1950 const uint32_t nr_words)
1951 {
1952 const uint32_t nr_bytes = nr_words * PVR_DUMP_CSB_WORD_SIZE;
1953
1954 if (!nr_words)
1955 return false;
1956
1957 pvr_dump_indent(&ctx->base);
1958
1959 pvr_dump_field_u32_units(&ctx->base, "<raw>", nr_bytes, "bytes");
1960
1961 pvr_dump_indent(&ctx->base);
1962 pvr_dump_buffer_rewind(ctx, nr_bytes);
1963 pvr_dump_buffer_hex(ctx, nr_bytes);
1964 pvr_dump_dedent(&ctx->base);
1965
1966 pvr_dump_dedent(&ctx->base);
1967
1968 return true;
1969 }
1970
print_cdmctrl_buffer(struct pvr_dump_buffer_ctx * const parent_ctx,struct pvr_device * const device)1971 static bool print_cdmctrl_buffer(struct pvr_dump_buffer_ctx *const parent_ctx,
1972 struct pvr_device *const device)
1973 {
1974 struct pvr_dump_csb_ctx ctx;
1975 bool ret = true;
1976
1977 /* All blocks contain a block_type member in the first word at the same
1978 * position. We could unpack any block to pick out this discriminant field,
1979 * but this one has been chosen because it's only one word long.
1980 */
1981 STATIC_ASSERT(pvr_cmd_length(CDMCTRL_STREAM_TERMINATE) == 1);
1982
1983 if (!pvr_dump_csb_ctx_push(&ctx, parent_ctx))
1984 return false;
1985
1986 do {
1987 enum PVRX(CDMCTRL_BLOCK_TYPE) block_type;
1988 const uint32_t *next_word;
1989 uint32_t words_read = 0;
1990
1991 next_word = pvr_dump_buffer_peek(&ctx.base, sizeof(*next_word));
1992 if (!next_word) {
1993 ret = false;
1994 goto end_pop_ctx;
1995 }
1996
1997 block_type =
1998 pvr_csb_unpack(next_word, CDMCTRL_STREAM_TERMINATE).block_type;
1999 switch (block_type) {
2000 case PVRX(CDMCTRL_BLOCK_TYPE_COMPUTE_KERNEL):
2001 words_read = print_block_cdmctrl_kernel(&ctx, device);
2002 break;
2003
2004 case PVRX(CDMCTRL_BLOCK_TYPE_STREAM_LINK):
2005 words_read = print_block_cdmctrl_stream_link(&ctx);
2006 break;
2007
2008 case PVRX(CDMCTRL_BLOCK_TYPE_STREAM_TERMINATE):
2009 words_read = print_block_cdmctrl_stream_terminate(&ctx);
2010 break;
2011
2012 default:
2013 pvr_dump_buffer_print_header_line(
2014 &ctx.base,
2015 "<could not decode CDMCTRL block (%u)>",
2016 block_type);
2017 break;
2018 }
2019
2020 if (!print_block_hex(&ctx.base, words_read))
2021 ret = false;
2022
2023 if (block_type == PVRX(CDMCTRL_BLOCK_TYPE_STREAM_TERMINATE))
2024 break;
2025 } while (ret);
2026
2027 end_pop_ctx:
2028 pvr_dump_csb_ctx_pop(&ctx, true);
2029
2030 return ret;
2031 }
2032
print_vdmctrl_buffer(struct pvr_dump_buffer_ctx * const parent_ctx,struct pvr_device * const device)2033 static bool print_vdmctrl_buffer(struct pvr_dump_buffer_ctx *const parent_ctx,
2034 struct pvr_device *const device)
2035 {
2036 struct pvr_dump_csb_ctx ctx;
2037 bool ret = true;
2038
2039 /* All blocks contain a block_type member in the first word at the same
2040 * position. We could unpack any block to pick out this discriminant field,
2041 * but this one has been chosen because it's only one word long.
2042 */
2043 STATIC_ASSERT(pvr_cmd_length(VDMCTRL_STREAM_RETURN) == 1);
2044
2045 if (!pvr_dump_csb_ctx_push(&ctx, parent_ctx))
2046 return false;
2047
2048 do {
2049 enum PVRX(VDMCTRL_BLOCK_TYPE) block_type;
2050 const uint32_t *next_word;
2051 uint32_t words_read = 0;
2052
2053 next_word = pvr_dump_buffer_peek(&ctx.base, sizeof(*next_word));
2054 if (!next_word) {
2055 ret = false;
2056 goto end_pop_ctx;
2057 }
2058
2059 block_type = pvr_csb_unpack(next_word, VDMCTRL_STREAM_RETURN).block_type;
2060 switch (block_type) {
2061 case PVRX(VDMCTRL_BLOCK_TYPE_PPP_STATE_UPDATE):
2062 words_read = print_block_vdmctrl_ppp_state_update(&ctx, device);
2063 break;
2064
2065 case PVRX(VDMCTRL_BLOCK_TYPE_PDS_STATE_UPDATE):
2066 words_read = print_block_vdmctrl_pds_state_update(&ctx, device);
2067 break;
2068
2069 case PVRX(VDMCTRL_BLOCK_TYPE_VDM_STATE_UPDATE):
2070 words_read = print_block_vdmctrl_vdm_state_update(&ctx, device);
2071 break;
2072
2073 case PVRX(VDMCTRL_BLOCK_TYPE_INDEX_LIST):
2074 words_read = print_block_vdmctrl_index_list(&ctx, device);
2075 break;
2076
2077 case PVRX(VDMCTRL_BLOCK_TYPE_STREAM_LINK):
2078 words_read = print_block_vdmctrl_stream_link(&ctx);
2079 break;
2080
2081 case PVRX(VDMCTRL_BLOCK_TYPE_STREAM_RETURN):
2082 words_read = print_block_vdmctrl_stream_return(&ctx);
2083 break;
2084
2085 case PVRX(VDMCTRL_BLOCK_TYPE_STREAM_TERMINATE):
2086 words_read = print_block_vdmctrl_stream_terminate(&ctx);
2087 break;
2088
2089 default:
2090 pvr_dump_buffer_print_header_line(
2091 &ctx.base,
2092 "<could not decode VDMCTRL block (%u)>",
2093 block_type);
2094 break;
2095 }
2096
2097 if (!print_block_hex(&ctx.base, words_read))
2098 ret = false;
2099
2100 if (block_type == PVRX(VDMCTRL_BLOCK_TYPE_STREAM_TERMINATE))
2101 break;
2102 } while (ret);
2103
2104 end_pop_ctx:
2105 pvr_dump_csb_ctx_pop(&ctx, true);
2106
2107 return ret;
2108 }
2109
print_ppp_buffer(struct pvr_dump_buffer_ctx * const parent_ctx,struct pvr_device * const device)2110 static bool print_ppp_buffer(struct pvr_dump_buffer_ctx *const parent_ctx,
2111 struct pvr_device *const device)
2112 {
2113 struct pvr_dump_csb_ctx ctx;
2114 uint32_t words_read;
2115 bool ret = false;
2116
2117 struct PVRX(TA_STATE_HEADER) header = { 0 };
2118
2119 if (!pvr_dump_csb_ctx_push(&ctx, parent_ctx))
2120 goto end_out;
2121
2122 words_read = print_block_ppp_state_header(&ctx, &header);
2123 if (!print_block_hex(&ctx.base, words_read))
2124 goto end_pop_ctx;
2125
2126 if (header.pres_ispctl_fa || header.pres_ispctl_fb ||
2127 header.pres_ispctl_ba || header.pres_ispctl_bb ||
2128 header.pres_ispctl_dbsc) {
2129 if (!header.pres_ispctl) {
2130 ret =
2131 pvr_dump_field_error(&ctx.base.base, "missing ispctl control word");
2132 goto end_pop_ctx;
2133 }
2134
2135 words_read = print_block_ppp_state_isp(&ctx,
2136 header.pres_ispctl_fa,
2137 header.pres_ispctl_fb,
2138 header.pres_ispctl_ba,
2139 header.pres_ispctl_bb,
2140 header.pres_ispctl_dbsc);
2141 if (!print_block_hex(&ctx.base, words_read))
2142 goto end_pop_ctx;
2143 }
2144
2145 if (header.pres_pds_state_ptr0 || header.pres_pds_state_ptr1 ||
2146 header.pres_pds_state_ptr2 || header.pres_pds_state_ptr3) {
2147 words_read = print_block_ppp_state_pds(&ctx,
2148 device,
2149 header.pres_pds_state_ptr0,
2150 header.pres_pds_state_ptr1,
2151 header.pres_pds_state_ptr2,
2152 header.pres_pds_state_ptr3);
2153 if (!print_block_hex(&ctx.base, words_read))
2154 goto end_pop_ctx;
2155 }
2156
2157 if (header.pres_region_clip) {
2158 words_read = print_block_ppp_region_clip(&ctx);
2159 if (!print_block_hex(&ctx.base, words_read))
2160 goto end_pop_ctx;
2161 }
2162
2163 if (header.pres_viewport) {
2164 for (uint32_t i = 0; i < header.view_port_count + 1; i++) {
2165 words_read = print_block_ppp_viewport(&ctx, i);
2166 if (!print_block_hex(&ctx.base, words_read))
2167 goto end_pop_ctx;
2168 }
2169 }
2170
2171 if (header.pres_wclamp) {
2172 words_read = print_block_ppp_wclamp(&ctx);
2173 if (!print_block_hex(&ctx.base, words_read))
2174 goto end_pop_ctx;
2175 }
2176
2177 if (header.pres_outselects) {
2178 words_read = print_block_ppp_output_sel(&ctx);
2179 if (!print_block_hex(&ctx.base, words_read))
2180 goto end_pop_ctx;
2181 }
2182
2183 if (header.pres_varying_word0 || header.pres_varying_word1 ||
2184 header.pres_varying_word2) {
2185 words_read = print_block_ppp_state_varying(&ctx,
2186 header.pres_varying_word0,
2187 header.pres_varying_word1,
2188 header.pres_varying_word2);
2189 if (!print_block_hex(&ctx.base, words_read))
2190 goto end_pop_ctx;
2191 }
2192
2193 if (header.pres_ppp_ctrl) {
2194 words_read = print_block_ppp_state_ppp_ctrl(&ctx);
2195 if (!print_block_hex(&ctx.base, words_read))
2196 goto end_pop_ctx;
2197 }
2198
2199 if (header.pres_stream_out_size || header.pres_stream_out_program) {
2200 words_read =
2201 print_block_ppp_state_stream_out(&ctx,
2202 device,
2203 header.pres_stream_out_size,
2204 header.pres_stream_out_program);
2205 if (!print_block_hex(&ctx.base, words_read))
2206 goto end_pop_ctx;
2207 }
2208
2209 if (header.pres_terminate) {
2210 words_read = print_block_ppp_state_terminate(&ctx);
2211 if (!print_block_hex(&ctx.base, words_read))
2212 goto end_pop_ctx;
2213 }
2214
2215 ret = true;
2216
2217 end_pop_ctx:
2218 pvr_dump_csb_ctx_pop(&ctx, true);
2219
2220 end_out:
2221 return ret;
2222 }
2223
2224 /******************************************************************************
2225 Sub buffer printer definition
2226 ******************************************************************************/
2227
print_sub_buffer(struct pvr_dump_ctx * const ctx,struct pvr_device * const device,const enum buffer_type type,const pvr_dev_addr_t addr,const uint64_t expected_size,const char * const size_src)2228 static bool print_sub_buffer(struct pvr_dump_ctx *const ctx,
2229 struct pvr_device *const device,
2230 const enum buffer_type type,
2231 const pvr_dev_addr_t addr,
2232 const uint64_t expected_size,
2233 const char *const size_src)
2234 {
2235 struct pvr_dump_bo_ctx sub_ctx;
2236 struct pvr_dump_ctx *base_ctx;
2237 struct pvr_bo *bo;
2238 uint64_t real_size;
2239 uint64_t offset;
2240 bool ret = false;
2241
2242 pvr_dump_indent(ctx);
2243
2244 bo = pvr_bo_store_lookup(device, addr);
2245 if (!bo) {
2246 if (expected_size) {
2247 pvr_dump_field(ctx,
2248 "<buffer size>",
2249 "%" PRIu64 " bytes (from %s)",
2250 expected_size,
2251 size_src);
2252 } else {
2253 pvr_dump_field(ctx, "<buffer size>", "<unknown>");
2254 }
2255
2256 /* FIXME: Trace pvr_buffer allocations with pvr_bo_store. */
2257 pvr_dump_warn(ctx, "no mapping found at " PVR_DEV_ADDR_FMT, addr.addr);
2258
2259 /* Not a fatal error; don't let a single bad address halt the dump. */
2260 ret = true;
2261 goto end_out;
2262 }
2263
2264 offset = addr.addr - bo->vma->dev_addr.addr;
2265
2266 if (!pvr_dump_bo_ctx_push(&sub_ctx, ctx, device, bo)) {
2267 pvr_dump_println(&sub_ctx.base.base, "<unable to read buffer>");
2268 goto end_out;
2269 }
2270
2271 base_ctx = &sub_ctx.base.base;
2272
2273 if (!pvr_dump_buffer_advance(&sub_ctx.base, offset))
2274 goto end_pop_ctx;
2275
2276 real_size = sub_ctx.base.remaining_size;
2277
2278 if (!expected_size) {
2279 pvr_dump_field(base_ctx,
2280 "<buffer size>",
2281 "%" PRIu64 " bytes mapped",
2282 real_size);
2283 } else if (expected_size > real_size) {
2284 pvr_dump_field(base_ctx,
2285 "<buffer size>",
2286 "%" PRIu64 " bytes mapped, expected %" PRIu64
2287 " bytes (from %s)",
2288 real_size,
2289 expected_size,
2290 size_src);
2291 } else {
2292 pvr_dump_field(base_ctx,
2293 "<buffer size>",
2294 "%" PRIu64 " bytes (from %s)",
2295 expected_size,
2296 size_src);
2297 pvr_dump_buffer_truncate(&sub_ctx.base, expected_size);
2298 }
2299
2300 if (sub_ctx.bo_mapped_in_ctx)
2301 pvr_dump_field(base_ctx, "<host addr>", "<unmapped>");
2302 else
2303 pvr_dump_field(base_ctx, "<host addr>", "%p", sub_ctx.base.ptr);
2304
2305 switch (type) {
2306 case BUFFER_TYPE_NONE:
2307 pvr_dump_field(base_ctx, "<content>", "<not decoded>");
2308 ret = true;
2309 break;
2310
2311 case BUFFER_TYPE_PPP:
2312 pvr_dump_field(base_ctx, "<content>", "<decoded as PPP>");
2313 ret = print_ppp_buffer(&sub_ctx.base, device);
2314 break;
2315
2316 default:
2317 pvr_dump_field(base_ctx, "<content>", "<unsupported format>");
2318 ret = false;
2319 }
2320
2321 pvr_dump_field_u32_units(&sub_ctx.base.base,
2322 "<raw>",
2323 sub_ctx.base.capacity,
2324 "bytes");
2325
2326 pvr_dump_indent(&sub_ctx.base.base);
2327 pvr_dump_buffer_restart(&sub_ctx.base);
2328 pvr_dump_buffer_hex(&sub_ctx.base, 0);
2329 pvr_dump_dedent(&sub_ctx.base.base);
2330
2331 end_pop_ctx:
2332 pvr_dump_bo_ctx_pop(&sub_ctx);
2333
2334 end_out:
2335 pvr_dump_dedent(ctx);
2336
2337 return ret;
2338 }
2339
2340 /******************************************************************************
2341 Top-level dumping
2342 ******************************************************************************/
2343
dump_first_buffer(struct pvr_dump_buffer_ctx * const ctx,const enum pvr_cmd_stream_type stream_type,struct pvr_device * const device)2344 static bool dump_first_buffer(struct pvr_dump_buffer_ctx *const ctx,
2345 const enum pvr_cmd_stream_type stream_type,
2346 struct pvr_device *const device)
2347 {
2348 bool ret = false;
2349
2350 pvr_dump_mark_section(&ctx->base, "First buffer content");
2351 switch (stream_type) {
2352 case PVR_CMD_STREAM_TYPE_GRAPHICS:
2353 ret = print_vdmctrl_buffer(ctx, device);
2354 break;
2355
2356 case PVR_CMD_STREAM_TYPE_COMPUTE:
2357 ret = print_cdmctrl_buffer(ctx, device);
2358 break;
2359
2360 default:
2361 unreachable("Unknown stream type");
2362 }
2363
2364 if (!ret)
2365 pvr_dump_println(&ctx->base,
2366 "<error while decoding at 0x%tx>",
2367 (uint8_t *)ctx->ptr - (uint8_t *)ctx->initial_ptr);
2368
2369 pvr_dump_buffer_restart(ctx);
2370 pvr_dump_mark_section(&ctx->base, "First buffer hexdump");
2371 return pvr_dump_buffer_hex(ctx, 0);
2372 }
2373
2374 /******************************************************************************
2375 Public functions
2376 ******************************************************************************/
2377
pvr_csb_dump(const struct pvr_csb * const csb,const uint32_t frame_num,const uint32_t job_num)2378 void pvr_csb_dump(const struct pvr_csb *const csb,
2379 const uint32_t frame_num,
2380 const uint32_t job_num)
2381 {
2382 const uint32_t nr_bos = list_length(&csb->pvr_bo_list);
2383 struct pvr_device *const device = csb->device;
2384
2385 struct pvr_dump_bo_ctx first_bo_ctx;
2386 struct pvr_dump_ctx root_ctx;
2387
2388 pvr_bo_store_dump(device);
2389
2390 pvr_dump_begin(&root_ctx, stderr, "CONTROL STREAM DUMP", 6);
2391
2392 pvr_dump_field_u32(&root_ctx, "Frame num", frame_num);
2393 pvr_dump_field_u32(&root_ctx, "Job num", job_num);
2394 pvr_dump_field_enum(&root_ctx, "Status", csb->status, vk_Result_to_str);
2395 pvr_dump_field_enum(&root_ctx,
2396 "Stream type",
2397 csb->stream_type,
2398 pvr_cmd_stream_type_to_str);
2399
2400 if (nr_bos <= 1) {
2401 pvr_dump_field_u32(&root_ctx, "Nr of BOs", nr_bos);
2402 } else {
2403 /* TODO: Implement multi-buffer dumping. */
2404 pvr_dump_field_computed(&root_ctx,
2405 "Nr of BOs",
2406 "%" PRIu32,
2407 "only the first buffer will be dumped",
2408 nr_bos);
2409 }
2410
2411 if (nr_bos == 0)
2412 goto end_dump;
2413
2414 pvr_dump_mark_section(&root_ctx, "Buffer objects");
2415 pvr_bo_list_dump(&root_ctx, &csb->pvr_bo_list, nr_bos);
2416
2417 if (!pvr_dump_bo_ctx_push(
2418 &first_bo_ctx,
2419 &root_ctx,
2420 device,
2421 list_first_entry(&csb->pvr_bo_list, struct pvr_bo, link))) {
2422 pvr_dump_mark_section(&root_ctx, "First buffer");
2423 pvr_dump_println(&root_ctx, "<unable to read buffer>");
2424 goto end_dump;
2425 }
2426
2427 dump_first_buffer(&first_bo_ctx.base, csb->stream_type, device);
2428
2429 pvr_dump_bo_ctx_pop(&first_bo_ctx);
2430
2431 end_dump:
2432 pvr_dump_end(&root_ctx);
2433 }
2434