r600g: zero memory of ioctl parameters
[mesa.git] / src / gallium / winsys / r600 / drm / r600_drm.c
1 /*
2 * Copyright 2010 Jerome Glisse <glisse@freedesktop.org>
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 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the 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 NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE.
22 *
23 * Authors:
24 * Jerome Glisse
25 * Corbin Simpson <MostAwesomeDude@gmail.com>
26 * Joakim Sindholt <opensource@zhasha.com>
27 */
28 #include <stdio.h>
29 #include <errno.h>
30 #include <sys/ioctl.h>
31 #include "util/u_inlines.h"
32 #include "util/u_debug.h"
33 #include "util/u_hash_table.h"
34 #include <pipebuffer/pb_bufmgr.h>
35 #include "r600.h"
36 #include "r600_priv.h"
37 #include "r600_drm_public.h"
38 #include "xf86drm.h"
39 #include "radeon_drm.h"
40
41 #ifndef RADEON_INFO_TILING_CONFIG
42 #define RADEON_INFO_TILING_CONFIG 0x6
43 #endif
44
45 #ifndef RADEON_INFO_CLOCK_CRYSTAL_FREQ
46 #define RADEON_INFO_CLOCK_CRYSTAL_FREQ 0x9
47 #endif
48
49 #ifndef RADEON_INFO_NUM_BACKENDS
50 #define RADEON_INFO_NUM_BACKENDS 0xa
51 #endif
52
53 enum radeon_family r600_get_family(struct radeon *r600)
54 {
55 return r600->family;
56 }
57
58 enum chip_class r600_get_family_class(struct radeon *radeon)
59 {
60 return radeon->chip_class;
61 }
62
63 struct r600_tiling_info *r600_get_tiling_info(struct radeon *radeon)
64 {
65 return &radeon->tiling_info;
66 }
67
68 unsigned r600_get_clock_crystal_freq(struct radeon *radeon)
69 {
70 return radeon->clock_crystal_freq;
71 }
72
73 unsigned r600_get_num_backends(struct radeon *radeon)
74 {
75 return radeon->num_backends;
76 }
77
78 unsigned r600_get_minor_version(struct radeon *radeon)
79 {
80 return radeon->minor_version;
81 }
82
83
84 static int radeon_get_device(struct radeon *radeon)
85 {
86 struct drm_radeon_info info = {};
87 int r;
88
89 radeon->device = 0;
90 info.request = RADEON_INFO_DEVICE_ID;
91 info.value = (uintptr_t)&radeon->device;
92 r = drmCommandWriteRead(radeon->fd, DRM_RADEON_INFO, &info,
93 sizeof(struct drm_radeon_info));
94 return r;
95 }
96
97 static int r600_interpret_tiling(struct radeon *radeon, uint32_t tiling_config)
98 {
99 switch ((tiling_config & 0xe) >> 1) {
100 case 0:
101 radeon->tiling_info.num_channels = 1;
102 break;
103 case 1:
104 radeon->tiling_info.num_channels = 2;
105 break;
106 case 2:
107 radeon->tiling_info.num_channels = 4;
108 break;
109 case 3:
110 radeon->tiling_info.num_channels = 8;
111 break;
112 default:
113 return -EINVAL;
114 }
115
116 switch ((tiling_config & 0x30) >> 4) {
117 case 0:
118 radeon->tiling_info.num_banks = 4;
119 break;
120 case 1:
121 radeon->tiling_info.num_banks = 8;
122 break;
123 default:
124 return -EINVAL;
125
126 }
127 switch ((tiling_config & 0xc0) >> 6) {
128 case 0:
129 radeon->tiling_info.group_bytes = 256;
130 break;
131 case 1:
132 radeon->tiling_info.group_bytes = 512;
133 break;
134 default:
135 return -EINVAL;
136 }
137 return 0;
138 }
139
140 static int eg_interpret_tiling(struct radeon *radeon, uint32_t tiling_config)
141 {
142 switch (tiling_config & 0xf) {
143 case 0:
144 radeon->tiling_info.num_channels = 1;
145 break;
146 case 1:
147 radeon->tiling_info.num_channels = 2;
148 break;
149 case 2:
150 radeon->tiling_info.num_channels = 4;
151 break;
152 case 3:
153 radeon->tiling_info.num_channels = 8;
154 break;
155 default:
156 return -EINVAL;
157 }
158
159 switch ((tiling_config & 0xf0) >> 4) {
160 case 0:
161 radeon->tiling_info.num_banks = 4;
162 break;
163 case 1:
164 radeon->tiling_info.num_banks = 8;
165 break;
166 case 2:
167 radeon->tiling_info.num_banks = 16;
168 break;
169 default:
170 return -EINVAL;
171
172 }
173
174 switch ((tiling_config & 0xf00) >> 8) {
175 case 0:
176 radeon->tiling_info.group_bytes = 256;
177 break;
178 case 1:
179 radeon->tiling_info.group_bytes = 512;
180 break;
181 default:
182 return -EINVAL;
183 }
184 return 0;
185 }
186
187 static int radeon_drm_get_tiling(struct radeon *radeon)
188 {
189 struct drm_radeon_info info = {};
190 int r;
191 uint32_t tiling_config = 0;
192
193 info.request = RADEON_INFO_TILING_CONFIG;
194 info.value = (uintptr_t)&tiling_config;
195 r = drmCommandWriteRead(radeon->fd, DRM_RADEON_INFO, &info,
196 sizeof(struct drm_radeon_info));
197
198 if (r)
199 return 0;
200
201 if (radeon->chip_class == R600 || radeon->chip_class == R700) {
202 r = r600_interpret_tiling(radeon, tiling_config);
203 } else {
204 r = eg_interpret_tiling(radeon, tiling_config);
205 }
206 return r;
207 }
208
209 static int radeon_get_clock_crystal_freq(struct radeon *radeon)
210 {
211 struct drm_radeon_info info = {};
212 uint32_t clock_crystal_freq;
213 int r;
214
215 info.request = RADEON_INFO_CLOCK_CRYSTAL_FREQ;
216 info.value = (uintptr_t)&clock_crystal_freq;
217 r = drmCommandWriteRead(radeon->fd, DRM_RADEON_INFO, &info,
218 sizeof(struct drm_radeon_info));
219 if (r)
220 return r;
221
222 radeon->clock_crystal_freq = clock_crystal_freq;
223 return 0;
224 }
225
226
227 static int radeon_get_num_backends(struct radeon *radeon)
228 {
229 struct drm_radeon_info info = {};
230 uint32_t num_backends;
231 int r;
232
233 info.request = RADEON_INFO_NUM_BACKENDS;
234 info.value = (uintptr_t)&num_backends;
235 r = drmCommandWriteRead(radeon->fd, DRM_RADEON_INFO, &info,
236 sizeof(struct drm_radeon_info));
237 if (r)
238 return r;
239
240 radeon->num_backends = num_backends;
241 return 0;
242 }
243
244
245 static int radeon_init_fence(struct radeon *radeon)
246 {
247 radeon->fence = 1;
248 radeon->fence_bo = r600_bo(radeon, 4096, 0, 0, 0);
249 if (radeon->fence_bo == NULL) {
250 return -ENOMEM;
251 }
252 radeon->cfence = r600_bo_map(radeon, radeon->fence_bo, PB_USAGE_UNSYNCHRONIZED, NULL);
253 *radeon->cfence = 0;
254 return 0;
255 }
256
257 #define PTR_TO_UINT(x) ((unsigned)((intptr_t)(x)))
258
259 static unsigned handle_hash(void *key)
260 {
261 return PTR_TO_UINT(key);
262 }
263
264 static int handle_compare(void *key1, void *key2)
265 {
266 return PTR_TO_UINT(key1) != PTR_TO_UINT(key2);
267 }
268
269 static struct radeon *radeon_new(int fd, unsigned device)
270 {
271 struct radeon *radeon;
272 int r;
273 drmVersionPtr version;
274
275 radeon = calloc(1, sizeof(*radeon));
276 if (radeon == NULL) {
277 return NULL;
278 }
279 radeon->fd = fd;
280 radeon->device = device;
281 radeon->refcount = 1;
282
283 version = drmGetVersion(radeon->fd);
284 if (version->version_major != 2) {
285 fprintf(stderr, "%s: DRM version is %d.%d.%d but this driver is "
286 "only compatible with 2.x.x\n", __FUNCTION__,
287 version->version_major, version->version_minor,
288 version->version_patchlevel);
289 drmFreeVersion(version);
290 exit(1);
291 }
292
293 radeon->minor_version = version->version_minor;
294
295 drmFreeVersion(version);
296
297 r = radeon_get_device(radeon);
298 if (r) {
299 fprintf(stderr, "Failed to get device id\n");
300 return radeon_decref(radeon);
301 }
302
303 radeon->family = radeon_family_from_device(radeon->device);
304 if (radeon->family == CHIP_UNKNOWN) {
305 fprintf(stderr, "Unknown chipset 0x%04X\n", radeon->device);
306 return radeon_decref(radeon);
307 }
308 /* setup class */
309 switch (radeon->family) {
310 case CHIP_R600:
311 case CHIP_RV610:
312 case CHIP_RV630:
313 case CHIP_RV670:
314 case CHIP_RV620:
315 case CHIP_RV635:
316 case CHIP_RS780:
317 case CHIP_RS880:
318 radeon->chip_class = R600;
319 /* set default group bytes, overridden by tiling info ioctl */
320 radeon->tiling_info.group_bytes = 256;
321 break;
322 case CHIP_RV770:
323 case CHIP_RV730:
324 case CHIP_RV710:
325 case CHIP_RV740:
326 radeon->chip_class = R700;
327 /* set default group bytes, overridden by tiling info ioctl */
328 radeon->tiling_info.group_bytes = 256;
329 break;
330 case CHIP_CEDAR:
331 case CHIP_REDWOOD:
332 case CHIP_JUNIPER:
333 case CHIP_CYPRESS:
334 case CHIP_HEMLOCK:
335 case CHIP_PALM:
336 case CHIP_SUMO:
337 case CHIP_SUMO2:
338 case CHIP_BARTS:
339 case CHIP_TURKS:
340 case CHIP_CAICOS:
341 radeon->chip_class = EVERGREEN;
342 /* set default group bytes, overridden by tiling info ioctl */
343 radeon->tiling_info.group_bytes = 512;
344 break;
345 case CHIP_CAYMAN:
346 radeon->chip_class = CAYMAN;
347 /* set default group bytes, overridden by tiling info ioctl */
348 radeon->tiling_info.group_bytes = 512;
349 break;
350 default:
351 fprintf(stderr, "%s unknown or unsupported chipset 0x%04X\n",
352 __func__, radeon->device);
353 break;
354 }
355
356 if (radeon_drm_get_tiling(radeon))
357 return NULL;
358
359 /* get the GPU counter frequency, failure is non fatal */
360 radeon_get_clock_crystal_freq(radeon);
361
362 if (radeon->minor_version >= 9)
363 radeon_get_num_backends(radeon);
364
365 radeon->bomgr = r600_bomgr_create(radeon, 1000000);
366 if (radeon->bomgr == NULL) {
367 return NULL;
368 }
369 r = radeon_init_fence(radeon);
370 if (r) {
371 radeon_decref(radeon);
372 return NULL;
373 }
374
375 radeon->bo_handles = util_hash_table_create(handle_hash, handle_compare);
376 pipe_mutex_init(radeon->bo_handles_mutex);
377 return radeon;
378 }
379
380 struct radeon *r600_drm_winsys_create(int drmfd)
381 {
382 return radeon_new(drmfd, 0);
383 }
384
385 struct radeon *radeon_decref(struct radeon *radeon)
386 {
387 if (radeon == NULL)
388 return NULL;
389 if (--radeon->refcount > 0) {
390 return NULL;
391 }
392
393 util_hash_table_destroy(radeon->bo_handles);
394 pipe_mutex_destroy(radeon->bo_handles_mutex);
395 if (radeon->fence_bo) {
396 r600_bo_reference(radeon, &radeon->fence_bo, NULL);
397 }
398
399 if (radeon->bomgr)
400 r600_bomgr_destroy(radeon->bomgr);
401
402 free(radeon);
403 return NULL;
404 }