xref: /aosp_15_r20/external/mesa3d/src/imagination/vulkan/pvr_dump_csb.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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