1 /*
2 * Copyright (C) 2021 Alyssa Rosenzweig <alyssa@rosenzweig.io>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is 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
18 * THE 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 #ifndef __AGX_IO_H
25 #define __AGX_IO_H
26
27 #include <stdbool.h>
28 #include "agx_bo.h"
29
30 #if __APPLE__
31 #include <mach/mach.h>
32 #include <IOKit/IODataQueueClient.h>
33 #endif
34
35 #define AGX_SERVICE_TYPE 0x100005
36
37 enum agx_selector {
38 AGX_SELECTOR_GET_GLOBAL_IDS = 0x6,
39 AGX_SELECTOR_SET_API = 0x7,
40 AGX_SELECTOR_CREATE_COMMAND_QUEUE = 0x8,
41 AGX_SELECTOR_FREE_COMMAND_QUEUE = 0x9,
42 AGX_SELECTOR_ALLOCATE_MEM = 0xA,
43 AGX_SELECTOR_FREE_MEM = 0xB,
44 AGX_SELECTOR_CREATE_SHMEM = 0xF,
45 AGX_SELECTOR_FREE_SHMEM = 0x10,
46 AGX_SELECTOR_CREATE_NOTIFICATION_QUEUE = 0x11,
47 AGX_SELECTOR_FREE_NOTIFICATION_QUEUE = 0x12,
48 AGX_SELECTOR_SUBMIT_COMMAND_BUFFERS = 0x1E,
49 AGX_SELECTOR_GET_VERSION = 0x23,
50 AGX_NUM_SELECTORS = 0x30
51 };
52
53 static const char *selector_table[AGX_NUM_SELECTORS] = {
54 "unk0",
55 "unk1",
56 "unk2",
57 "unk3",
58 "unk4",
59 "unk5",
60 "GET_GLOBAL_IDS",
61 "SET_API",
62 "CREATE_COMMAND_QUEUE",
63 "FREE_COMMAND_QUEUE",
64 "ALLOCATE_MEM",
65 "FREE_MEM",
66 "unkC",
67 "unkD",
68 "unkE",
69 "CREATE_SHMEM",
70 "FREE_SHMEM",
71 "CREATE_NOTIFICATION_QUEUE",
72 "FREE_NOTIFICATION_QUEUE",
73 "unk13",
74 "unk14",
75 "unk15",
76 "unk16",
77 "unk17",
78 "unk18",
79 "unk19",
80 "unk1A",
81 "unk1B",
82 "unk1C",
83 "unk1D",
84 "SUBMIT_COMMAND_BUFFERS",
85 "unk1F",
86 "unk20",
87 "unk21",
88 "unk22",
89 "GET_VERSION",
90 "unk24",
91 "unk25",
92 "unk26",
93 "unk27",
94 "unk28",
95 "unk29",
96 "unk2A",
97 "unk2B",
98 "unk2C",
99 "unk2D",
100 "unk2E",
101 "unk2F"
102 };
103
104 static inline const char *
wrap_selector_name(uint32_t selector)105 wrap_selector_name(uint32_t selector)
106 {
107 return (selector < AGX_NUM_SELECTORS) ? selector_table[selector] : "unk??";
108 }
109
110 struct agx_create_command_queue_resp {
111 uint64_t id;
112 uint32_t unk2; // 90 0A 08 27
113 uint32_t unk3; // 0
114 } __attribute__((packed));
115
116 struct agx_create_shmem_resp {
117 void *map;
118 uint32_t size;
119 uint32_t id;
120 } __attribute__((packed));
121
122 struct agx_create_notification_queue_resp {
123 #ifdef __APPLE__
124 IODataQueueMemory *queue;
125 #else
126 void *queue;
127 #endif
128 uint32_t unk2; // 1
129 uint32_t unk3; // 0
130 } __attribute__((packed));
131
132 struct agx_submit_cmdbuf_req {
133 uint32_t unk0;
134 uint32_t unk1;
135 uint32_t cmdbuf;
136 uint32_t mappings;
137 void *user_0;
138 void *user_1;
139 uint32_t unk2;
140 uint32_t unk3;
141 } __attribute__((packed));
142
143 /* Memory allocation isn't really understood yet. By comparing SHADER/CMDBUF_32
144 * vs everything else, it appears the 0x40000000 bit indicates the GPU VA must
145 * be be in the first 4GiB */
146
147 enum agx_memory_type {
148 AGX_MEMORY_TYPE_NORMAL = 0x00000000, /* used for user allocations */
149 AGX_MEMORY_TYPE_UNK = 0x08000000, /* unknown */
150 AGX_MEMORY_TYPE_CMDBUF_64 = 0x18000000, /* used for command buffer storage */
151 AGX_MEMORY_TYPE_SHADER = 0x48000000, /* used for shader memory, with VA = 0 */
152 AGX_MEMORY_TYPE_CMDBUF_32 = 0x58000000, /* used for command buffers, with VA < 32-bit */
153 AGX_MEMORY_TYPE_FRAMEBUFFER = 0x00888F00, /* used for framebuffer backing */
154 };
155
156 static inline const char *
agx_memory_type_name(uint32_t type)157 agx_memory_type_name(uint32_t type)
158 {
159 switch (type) {
160 case AGX_MEMORY_TYPE_NORMAL: return "normal";
161 case AGX_MEMORY_TYPE_UNK: return "unk";
162 case AGX_MEMORY_TYPE_CMDBUF_64: return "cmdbuf_64";
163 case AGX_MEMORY_TYPE_SHADER: return "shader";
164 case AGX_MEMORY_TYPE_CMDBUF_32: return "cmdbuf_32";
165 case AGX_MEMORY_TYPE_FRAMEBUFFER: return "framebuffer";
166 default: return NULL;
167 }
168 }
169
170 struct agx_notification_queue {
171 #ifdef __APPLE__
172 mach_port_t port;
173 IODataQueueMemory *queue;
174 #else
175 unsigned port;
176 void *queue;
177 #endif
178 unsigned id;
179 };
180
181 struct agx_command_queue {
182 unsigned id;
183 struct agx_notification_queue notif;
184 };
185
186 /* Not sure if this is hardware or software defined */
187
188 struct agx_map_header {
189 uint64_t cmdbuf_id; // GUID
190 uint32_t unk2; // 01 00 00 00
191 uint32_t unk3; // 28 05 00 80
192 uint64_t encoder_id; // GUID
193 uint32_t unk6; // 00 00 00 00
194 uint32_t cmdbuf_size;
195 uint32_t nr_handles;
196 uint32_t nr_entries;
197 uint32_t indices[6];
198 } __attribute__((packed));
199
200 struct agx_map_entry {
201 uint32_t unkAAA; // 20 00 00 00
202 uint32_t unk2; // 00 00 00 00
203 uint32_t unk3; // 00 00 00 00
204 uint32_t unk4; // 00 00 00 00
205 uint32_t unk5; // 00 00 00 00
206 uint32_t unk6; // 00 00 00 00
207 uint32_t unkBBB; // 01 00 00 00
208 uint32_t unk8; // 00 00 00 00
209 uint32_t unk9; // 00 00 00 00
210 uint32_t unka; // ff ff 01 00
211 uint32_t indices[6];
212 } __attribute__((packed));
213
214 uint64_t
215 agx_get_global_id(struct agx_device *dev);
216
217 #endif
218