17ec681f3Smrg/*
27ec681f3Smrg * Copyright 2021 Alyssa Rosenzweig
37ec681f3Smrg *
47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a
57ec681f3Smrg * copy of this software and associated documentation files (the "Software"),
67ec681f3Smrg * to deal in the Software without restriction, including without limitation
77ec681f3Smrg * on the rights to use, copy, modify, merge, publish, distribute, sub
87ec681f3Smrg * license, and/or sell copies of the Software, and to permit persons to whom
97ec681f3Smrg * the Software is furnished to do so, subject to the following conditions:
107ec681f3Smrg *
117ec681f3Smrg * The above copyright notice and this permission notice (including the next
127ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the
137ec681f3Smrg * Software.
147ec681f3Smrg *
157ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
167ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
177ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
187ec681f3Smrg * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
197ec681f3Smrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
207ec681f3Smrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
217ec681f3Smrg * USE OR OTHER DEALINGS IN THE SOFTWARE.
227ec681f3Smrg */
237ec681f3Smrg#
247ec681f3Smrg#include <stdint.h>
257ec681f3Smrg#include "agx_state.h"
267ec681f3Smrg#include "magic.h"
277ec681f3Smrg
287ec681f3Smrg/* The structures managed in this file appear to be software defined (either in
297ec681f3Smrg * the macOS kernel driver or in the AGX firmware) */
307ec681f3Smrg
317ec681f3Smrg/* Odd pattern */
327ec681f3Smrgstatic uint64_t
337ec681f3Smrgdemo_unk6(struct agx_pool *pool)
347ec681f3Smrg{
357ec681f3Smrg   struct agx_ptr ptr = agx_pool_alloc_aligned(pool, 0x4000 * sizeof(uint64_t), 64);
367ec681f3Smrg   uint64_t *buf = ptr.cpu;
377ec681f3Smrg   memset(buf, 0, sizeof(*buf));
387ec681f3Smrg
397ec681f3Smrg   for (unsigned i = 1; i < 0x3ff; ++i)
407ec681f3Smrg      buf[i] = (i + 1);
417ec681f3Smrg
427ec681f3Smrg   return ptr.gpu;
437ec681f3Smrg}
447ec681f3Smrg
457ec681f3Smrgstatic uint64_t
467ec681f3Smrgdemo_zero(struct agx_pool *pool, unsigned count)
477ec681f3Smrg{
487ec681f3Smrg   struct agx_ptr ptr = agx_pool_alloc_aligned(pool, count, 64);
497ec681f3Smrg   memset(ptr.cpu, 0, count);
507ec681f3Smrg   return ptr.gpu;
517ec681f3Smrg}
527ec681f3Smrg
537ec681f3Smrgunsigned
547ec681f3Smrgdemo_cmdbuf(uint64_t *buf, size_t size,
557ec681f3Smrg            struct agx_pool *pool,
567ec681f3Smrg            uint64_t encoder_ptr,
577ec681f3Smrg            uint64_t encoder_id,
587ec681f3Smrg            uint64_t scissor_ptr,
597ec681f3Smrg            unsigned width, unsigned height,
607ec681f3Smrg            uint32_t pipeline_null,
617ec681f3Smrg            uint32_t pipeline_clear,
627ec681f3Smrg            uint32_t pipeline_store,
637ec681f3Smrg            uint64_t rt0,
647ec681f3Smrg            bool clear_pipeline_textures)
657ec681f3Smrg{
667ec681f3Smrg   uint32_t *map = (uint32_t *) buf;
677ec681f3Smrg   memset(map, 0, 474 * 4);
687ec681f3Smrg
697ec681f3Smrg   map[54] = 0x6b0003;
707ec681f3Smrg   map[55] = 0x3a0012;
717ec681f3Smrg   map[56] = 1;
727ec681f3Smrg
737ec681f3Smrg   map[106] = 1;
747ec681f3Smrg   map[108] = 0x1c;
757ec681f3Smrg   map[112] = 0xffffffff;
767ec681f3Smrg   map[113] = 0xffffffff;
777ec681f3Smrg   map[114] = 0xffffffff;
787ec681f3Smrg
797ec681f3Smrg   uint64_t unk_buffer = demo_zero(pool, 0x1000);
807ec681f3Smrg   uint64_t unk_buffer_2 = demo_zero(pool, 0x8000);
817ec681f3Smrg
827ec681f3Smrg   // This is a pipeline bind
837ec681f3Smrg   map[156] = 0xffff8002 | (clear_pipeline_textures ? 0x210 : 0);
847ec681f3Smrg   map[158] = pipeline_clear | 0x4;
857ec681f3Smrg   map[163] = 0x12;
867ec681f3Smrg   map[164] = pipeline_store | 0x4;
877ec681f3Smrg   map[166] = scissor_ptr & 0xFFFFFFFF;
887ec681f3Smrg   map[167] = scissor_ptr >> 32;
897ec681f3Smrg   map[168] = unk_buffer & 0xFFFFFFFF;
907ec681f3Smrg   map[169] = unk_buffer >> 32;
917ec681f3Smrg
927ec681f3Smrg   map[220] = 4;
937ec681f3Smrg   map[222] = 0xc000;
947ec681f3Smrg   map[224] = width;
957ec681f3Smrg   map[225] = height;
967ec681f3Smrg   map[226] = unk_buffer_2 & 0xFFFFFFFF;
977ec681f3Smrg   map[227] = unk_buffer_2 >> 32;
987ec681f3Smrg
997ec681f3Smrg   float depth_clear = 1.0;
1007ec681f3Smrg   uint8_t stencil_clear = 0;
1017ec681f3Smrg
1027ec681f3Smrg   map[278] = fui(depth_clear);
1037ec681f3Smrg   map[279] = (0x3 << 8) | stencil_clear;
1047ec681f3Smrg   map[282] = 0x1000000;
1057ec681f3Smrg   map[284] = 0xffffffff;
1067ec681f3Smrg   map[285] = 0xffffffff;
1077ec681f3Smrg   map[286] = 0xffffffff;
1087ec681f3Smrg
1097ec681f3Smrg   map[298] = 0xffff8212;
1107ec681f3Smrg   map[300] = pipeline_null | 0x4;
1117ec681f3Smrg   map[305] = 0x12;
1127ec681f3Smrg   map[306] = pipeline_store | 0x4;
1137ec681f3Smrg   map[352] = 1;
1147ec681f3Smrg   map[360] = 0x1c;
1157ec681f3Smrg   map[362] = encoder_id;
1167ec681f3Smrg   map[365] = 0xffffffff;
1177ec681f3Smrg   map[366] = 1;
1187ec681f3Smrg
1197ec681f3Smrg   uint64_t unk6 = demo_unk6(pool);
1207ec681f3Smrg   map[370] = unk6 & 0xFFFFFFFF;
1217ec681f3Smrg   map[371] = unk6 >> 32;
1227ec681f3Smrg
1237ec681f3Smrg   map[374] = width;
1247ec681f3Smrg   map[375] = height;
1257ec681f3Smrg   map[376] = 1;
1267ec681f3Smrg   map[377] = 8;
1277ec681f3Smrg   map[378] = 8;
1287ec681f3Smrg
1297ec681f3Smrg   map[393] = 8;
1307ec681f3Smrg   map[394] = 32;
1317ec681f3Smrg   map[395] = 32;
1327ec681f3Smrg   map[396] = 1;
1337ec681f3Smrg
1347ec681f3Smrg   unsigned offset_unk = (458 * 4);
1357ec681f3Smrg   unsigned offset_attachments = (470 * 4);
1367ec681f3Smrg   unsigned nr_attachments = 1;
1377ec681f3Smrg
1387ec681f3Smrg   map[473] = nr_attachments;
1397ec681f3Smrg
1407ec681f3Smrg   /* A single attachment follows, depth/stencil have their own attachments */
1417ec681f3Smrg   agx_pack((map + (offset_attachments / 4) + 4), IOGPU_ATTACHMENT, cfg) {
1427ec681f3Smrg      cfg.address = rt0;
1437ec681f3Smrg      cfg.type = AGX_IOGPU_ATTACHMENT_TYPE_COLOUR;
1447ec681f3Smrg      cfg.unk_1 = 0x80000000;
1457ec681f3Smrg      cfg.unk_2 = 0x5;
1467ec681f3Smrg      cfg.bytes_per_pixel = 4;
1477ec681f3Smrg      cfg.percent = 100;
1487ec681f3Smrg   }
1497ec681f3Smrg
1507ec681f3Smrg   unsigned total_size = offset_attachments + (AGX_IOGPU_ATTACHMENT_LENGTH * nr_attachments) + 16;
1517ec681f3Smrg
1527ec681f3Smrg   agx_pack(map, IOGPU_HEADER, cfg) {
1537ec681f3Smrg      cfg.total_size = total_size;
1547ec681f3Smrg      cfg.attachment_offset_1 = offset_attachments;
1557ec681f3Smrg      cfg.attachment_offset_2 = offset_attachments;
1567ec681f3Smrg      cfg.attachment_length = nr_attachments * AGX_IOGPU_ATTACHMENT_LENGTH;
1577ec681f3Smrg      cfg.unknown_offset = offset_unk;
1587ec681f3Smrg      cfg.encoder = encoder_ptr;
1597ec681f3Smrg   }
1607ec681f3Smrg
1617ec681f3Smrg   return total_size;
1627ec681f3Smrg}
1637ec681f3Smrg
1647ec681f3Smrgstatic struct agx_map_header
1657ec681f3Smrgdemo_map_header(uint64_t cmdbuf_id, uint64_t encoder_id, unsigned cmdbuf_size, unsigned count)
1667ec681f3Smrg{
1677ec681f3Smrg   return (struct agx_map_header) {
1687ec681f3Smrg      .cmdbuf_id = cmdbuf_id,
1697ec681f3Smrg      .unk2 = 0x1,
1707ec681f3Smrg      .unk3 = 0x528, // 1320
1717ec681f3Smrg      .encoder_id = encoder_id,
1727ec681f3Smrg      .unk6 = 0x0,
1737ec681f3Smrg      .cmdbuf_size = cmdbuf_size,
1747ec681f3Smrg
1757ec681f3Smrg      /* +1 for the sentinel ending */
1767ec681f3Smrg      .nr_entries = count + 1,
1777ec681f3Smrg      .nr_handles = count + 1,
1787ec681f3Smrg      .indices = {0x0b},
1797ec681f3Smrg   };
1807ec681f3Smrg}
1817ec681f3Smrg
1827ec681f3Smrgvoid
1837ec681f3Smrgdemo_mem_map(void *map, size_t size, unsigned *handles, unsigned count,
1847ec681f3Smrg             uint64_t cmdbuf_id, uint64_t encoder_id, unsigned cmdbuf_size)
1857ec681f3Smrg{
1867ec681f3Smrg   struct agx_map_header *header = map;
1877ec681f3Smrg   struct agx_map_entry *entries = (struct agx_map_entry *) (((uint8_t *) map) + 0x40);
1887ec681f3Smrg   struct agx_map_entry *end = (struct agx_map_entry *) (((uint8_t *) map) + size);
1897ec681f3Smrg
1907ec681f3Smrg   /* Header precedes the entry */
1917ec681f3Smrg   *header = demo_map_header(cmdbuf_id, encoder_id, cmdbuf_size, count);
1927ec681f3Smrg
1937ec681f3Smrg   /* Add an entry for each BO mapped */
1947ec681f3Smrg   for (unsigned i = 0; i < count; ++i) {
1957ec681f3Smrg	   assert((entries + i) < end);
1967ec681f3Smrg      entries[i] = (struct agx_map_entry) {
1977ec681f3Smrg         .unkAAA = 0x20,
1987ec681f3Smrg         .unkBBB = 0x1,
1997ec681f3Smrg         .unka = 0x1ffff,
2007ec681f3Smrg         .indices = {handles[i]}
2017ec681f3Smrg      };
2027ec681f3Smrg   }
2037ec681f3Smrg
2047ec681f3Smrg   /* Final entry is a sentinel */
2057ec681f3Smrg   assert((entries + count) < end);
2067ec681f3Smrg   entries[count] = (struct agx_map_entry) {
2077ec681f3Smrg      .unkAAA = 0x40,
2087ec681f3Smrg      .unkBBB = 0x1,
2097ec681f3Smrg      .unka = 0x1ffff,
2107ec681f3Smrg   };
2117ec681f3Smrg}
212