2 * Copyright 2011 Jerome Glisse <glisse@freedesktop.org>
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:
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
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.
29 #define _FILE_OFFSET_BITS 64
38 #include "radeon_drm.h"
40 #ifndef RADEON_CHUNK_ID_FLAGS
41 #define RADEON_CHUNK_ID_FLAGS 0x03
42 /* The first dword of RADEON_CHUNK_ID_FLAGS is a uint32 of these flags: */
43 #define RADEON_CS_KEEP_TILING_FLAGS 0x01
49 #define RADEON_VA_MAP 1
50 #define RADEON_VA_UNMAP 2
51 #define RADEON_VA_RESULT_OK 0
52 #define RADEON_VA_RESULT_ERROR 1
53 #define RADEON_VA_RESULT_VA_EXIST 2
54 #define RADEON_VM_PAGE_VALID (1 << 0)
55 #define RADEON_VM_PAGE_READABLE (1 << 1)
56 #define RADEON_VM_PAGE_WRITEABLE (1 << 2)
57 #define RADEON_VM_PAGE_SYSTEM (1 << 3)
58 #define RADEON_VM_PAGE_SNOOPED (1 << 4)
59 struct drm_radeon_gem_va
{
66 #define DRM_RADEON_GEM_VA 0x2b
82 static void ctx_init(struct ctx
*ctx
)
84 ctx
->fd
= drmOpen("radeon", NULL
);
86 fprintf(stderr
, "failed to open radeon drm device file\n");
91 static void bo_wait(struct ctx
*ctx
, struct bo
*bo
)
93 struct drm_radeon_gem_wait_idle args
;
97 /* Zero out args to make valgrind happy */
98 memset(&args
, 0, sizeof(args
));
99 args
.handle
= bo
->handle
;
101 r
= drmCommandWriteRead(ctx
->fd
, DRM_RADEON_GEM_WAIT_IDLE
, &args
, sizeof(args
));
102 } while (r
== -EBUSY
);
106 static void ctx_cs(struct ctx
*ctx
, uint32_t *cs
, uint32_t cs_flags
[2], unsigned ndw
,
107 struct bo
**bo
, uint32_t *bo_relocs
, unsigned nbo
)
109 struct drm_radeon_cs args
;
110 struct drm_radeon_cs_chunk chunks
[3];
111 uint64_t chunk_array
[3];
116 for (i
= 0; i
< nbo
; i
++) {
117 bo_relocs
[i
*4+0] = bo
[i
]->handle
;
121 if (cs_flags
[0] || cs_flags
[1]) {
122 /* enable RADEON_CHUNK_ID_FLAGS */
125 args
.chunks
= (uint64_t)(uintptr_t)chunk_array
;
126 chunks
[0].chunk_id
= RADEON_CHUNK_ID_IB
;
127 chunks
[0].length_dw
= ndw
;
128 chunks
[0].chunk_data
= (uintptr_t)cs
;
129 chunks
[1].chunk_id
= RADEON_CHUNK_ID_RELOCS
;
130 chunks
[1].length_dw
= nbo
* 4;
131 chunks
[1].chunk_data
= (uintptr_t)bo_relocs
;
132 chunks
[2].chunk_id
= RADEON_CHUNK_ID_FLAGS
;
133 chunks
[2].length_dw
= 2;
134 chunks
[2].chunk_data
= (uintptr_t)cs_flags
;
135 chunk_array
[0] = (uintptr_t)&chunks
[0];
136 chunk_array
[1] = (uintptr_t)&chunks
[1];
137 chunk_array
[2] = (uintptr_t)&chunks
[2];
139 fprintf(stderr
, "emiting cs %ddw with %d bo\n", ndw
, nbo
);
140 r
= drmCommandWriteRead(ctx
->fd
, DRM_RADEON_CS
, &args
, sizeof(args
));
142 fprintf(stderr
, "cs submission failed with %d\n", r
);
147 static void bo_map(struct ctx
*ctx
, struct bo
*bo
)
149 struct drm_radeon_gem_mmap args
;
153 /* Zero out args to make valgrind happy */
154 memset(&args
, 0, sizeof(args
));
155 args
.handle
= bo
->handle
;
157 args
.size
= (uint64_t)bo
->size
;
158 r
= drmCommandWriteRead(ctx
->fd
, DRM_RADEON_GEM_MMAP
, &args
, sizeof(args
));
160 fprintf(stderr
, "error mapping %p 0x%08X (error = %d)\n", bo
, bo
->handle
, r
);
163 ptr
= mmap(0, args
.size
, PROT_READ
|PROT_WRITE
, MAP_SHARED
, ctx
->fd
, args
.addr_ptr
);
164 if (ptr
== MAP_FAILED
) {
165 fprintf(stderr
, "%s failed to map bo\n", __func__
);
171 static void bo_va(struct ctx
*ctx
, struct bo
*bo
)
173 struct drm_radeon_gem_va args
;
176 args
.handle
= bo
->handle
;
178 args
.operation
= RADEON_VA_MAP
;
179 args
.flags
= RADEON_VM_PAGE_READABLE
| RADEON_VM_PAGE_WRITEABLE
| RADEON_VM_PAGE_SNOOPED
;
180 args
.offset
= bo
->va
;
181 r
= drmCommandWriteRead(ctx
->fd
, DRM_RADEON_GEM_VA
, &args
, sizeof(args
));
182 if (r
&& args
.operation
== RADEON_VA_RESULT_ERROR
) {
183 fprintf(stderr
, "radeon: Failed to allocate virtual address for buffer:\n");
184 fprintf(stderr
, "radeon: size : %d bytes\n", bo
->size
);
185 fprintf(stderr
, "radeon: alignment : %d bytes\n", bo
->alignment
);
186 fprintf(stderr
, "radeon: va : 0x%016llx\n", (unsigned long long)bo
->va
);
191 static struct bo
*bo_new(struct ctx
*ctx
, unsigned ndw
, uint32_t *data
, uint64_t va
, uint32_t alignment
)
193 struct drm_radeon_gem_create args
;
197 bo
= calloc(1, sizeof(*bo
));
199 fprintf(stderr
, "failed to malloc bo struct\n");
202 bo
->size
= ndw
* 4ULL;
204 bo
->alignment
= alignment
;
206 args
.size
= bo
->size
;
207 args
.alignment
= bo
->alignment
;
208 args
.initial_domain
= RADEON_GEM_DOMAIN_GTT
;
212 r
= drmCommandWriteRead(ctx
->fd
, DRM_RADEON_GEM_CREATE
, &args
, sizeof(args
));
213 bo
->handle
= args
.handle
;
215 fprintf(stderr
, "Failed to allocate :\n");
216 fprintf(stderr
, " size : %d bytes\n", bo
->size
);
217 fprintf(stderr
, " alignment : %d bytes\n", bo
->alignment
);
224 memcpy(bo
->ptr
, data
, bo
->size
);