diff options
author | Jerome Glisse <jglisse@redhat.com> | 2011-09-30 10:24:48 -0400 |
---|---|---|
committer | Jerome Glisse <jglisse@redhat.com> | 2011-09-30 10:24:48 -0400 |
commit | 80799c0fa8e82822b223f0cd82cc554752d75add (patch) | |
tree | d386399a30ca5e205df1ede13e447f46ceff7e2c /jsoncs.c | |
parent | 49b32533f8008816b63c18226ac433b0bb26e1d1 (diff) |
bunch of new tools and update to previous one
Diffstat (limited to 'jsoncs.c')
-rw-r--r-- | jsoncs.c | 400 |
1 files changed, 400 insertions, 0 deletions
diff --git a/jsoncs.c b/jsoncs.c new file mode 100644 index 0000000..08dd424 --- /dev/null +++ b/jsoncs.c @@ -0,0 +1,400 @@ +/* + * Copyright 2011 Jerome Glisse <glisse@freedesktop.org> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Jerome Glisse + */ +#define _FILE_OFFSET_BITS 64 +#include <sys/mman.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <errno.h> +#include <jansson.h> +#include "xf86drm.h" +#include "radeon_drm.h" + +#pragma pack(1) +struct radeon_cs_reloc { + uint32_t handle; + uint32_t read_domain; + uint32_t write_domain; + uint32_t flags; +}; +#pragma pack() + +struct rbo { + unsigned refcount; + uint32_t handle; + unsigned size; + unsigned alignment; + void *data; +}; + +struct bo { + unsigned size; + uint32_t handle; + void *data; + struct rbo *rbo; +}; + +struct cs { + unsigned pm4_ndw; + unsigned reloc_ndw; + unsigned nbo; + struct bo *bo; + uint32_t device_id; + uint32_t *pm4; + uint32_t *reloc; +}; + +struct rbo *rbo(int fd, unsigned handle, unsigned size, unsigned alignment, void *ptr); +int rbo_map(int fd, struct rbo *bo); +void rbo_unmap(int fd, struct rbo *bo); +struct rbo *rbo_decref(int fd, struct rbo *bo); + +int copy_from_array(json_t *array, void *data) +{ + uint32_t *ptr = data; + unsigned i; + json_t *value; + + for (i = 0; i < json_array_size(array); i++) { + value = json_array_get(array, i); + if (value == NULL) { + return -EINVAL; + } + ptr[i] = strtoul(json_string_value(value), NULL, 0); + } + return 0; +} + +int cs_json_load(struct cs *cs, const char *filename) +{ + json_error_t error; + json_t *json, *tmp, *bo_array, *bo; + int i; + + memset(cs, 0, sizeof(struct cs)); + json = json_load_file(filename, &error); + if (json == NULL) { + return -EINVAL; + } + /* device */ + tmp = json_object_get(json, "device_id"); + if (tmp == NULL) { + fprintf(stderr, "no device id object\n"); + goto out_err; + } + cs->device_id = json_integer_value(tmp); + /* pm4 */ + tmp = json_object_get(json, "pm4"); + if (tmp == NULL) { + fprintf(stderr, "no pm4 object\n"); + goto out_err; + } + cs->pm4_ndw = json_array_size(tmp); + cs->pm4 = calloc(1, cs->pm4_ndw * 4); + if (copy_from_array(tmp, cs->pm4)) { + fprintf(stderr, "failed reading pm4 object\n"); + goto out_err; + } + /* reloc */ + tmp = json_object_get(json, "reloc"); + if (tmp == NULL) { + fprintf(stderr, "no reloc object\n"); + goto out_err; + } + cs->reloc_ndw = json_array_size(tmp); + cs->reloc = calloc(1, cs->reloc_ndw * 4); + if (copy_from_array(tmp, cs->reloc)) { + fprintf(stderr, "failed reading pm4 object\n"); + goto out_err; + } + /* bo */ + bo_array = json_object_get(json, "bo"); + if (bo_array == NULL) { + fprintf(stderr, "no bo object\n"); + goto out_err; + } + cs->nbo = json_array_size(bo_array); + cs->bo = calloc(1, sizeof(struct bo) * cs->nbo); + if (cs->bo == NULL) { + fprintf(stderr, "%s failed to allocate bo\n", __func__); + goto out_err; + } + for (i = 0; i < cs->nbo; i++) { + bo = json_array_get(bo_array, i); + if (bo == NULL) { + fprintf(stderr, "no bo[%d] object\n", i); + goto out_err; + } + tmp = json_object_get(bo, "size"); + if (tmp == NULL) { + fprintf(stderr, "no size object for bo[%d]\n", i); + goto out_err; + } + cs->bo[i].size = json_integer_value(tmp); + tmp = json_object_get(bo, "handle"); + if (tmp == NULL) { + fprintf(stderr, "no handle object for bo[%d]\n", i); + goto out_err; + } + cs->bo[i].handle = json_integer_value(tmp); + cs->bo[i].data = calloc(1, cs->bo[i].size); + if (cs->bo[i].data == NULL) { + fprintf(stderr, "failed to allocate bo[%d]\n", i); + goto out_err; + } + tmp = json_object_get(bo, "data"); + if (tmp == NULL) { + fprintf(stderr, "no data object for bo[%d]\n", i); + goto out_err; + } + if (copy_from_array(tmp, cs->bo[i].data)) { + fprintf(stderr, "failed reading pm4 object\n"); + goto out_err; + } + } + json_decref(json); + return 0; +out_err: + json_decref(json); + for (i = 0; i < cs->nbo; i++) { + free(cs->bo[i].data); + } + free(cs->pm4); + free(cs->reloc); + free(cs->bo); + memset(cs, 0, sizeof(struct cs)); + return -EINVAL; +} + +struct rbo *rbo(int fd, unsigned handle, unsigned size, unsigned alignment, void *ptr) +{ + struct rbo *bo; + int r; + + bo = calloc(1, sizeof(*bo)); + if (bo == NULL) { + return NULL; + } + bo->refcount = 1; + bo->size = size; + bo->handle = handle; + bo->alignment = alignment; + + if (handle) { + struct drm_gem_open open_arg; + + memset(&open_arg, 0, sizeof(open_arg)); + open_arg.name = handle; + r = drmIoctl(fd, DRM_IOCTL_GEM_OPEN, &open_arg); + if (r != 0) { + free(bo); + return NULL; + } + bo->handle = open_arg.handle; + } else { + struct drm_radeon_gem_create args; + + args.size = size; + args.alignment = alignment; + args.initial_domain = RADEON_GEM_DOMAIN_CPU; + args.flags = 0; + args.handle = 0; + r = drmCommandWriteRead(fd, DRM_RADEON_GEM_CREATE, &args, sizeof(args)); + bo->handle = args.handle; + if (r) { + fprintf(stderr, "Failed to allocate :\n"); + fprintf(stderr, " size : %d bytes\n", size); + fprintf(stderr, " alignment : %d bytes\n", alignment); + free(bo); + return NULL; + } + } + if (ptr) { + if (rbo_map(fd, bo)) { + fprintf(stderr, "%s failed to copy data into bo\n", __func__); + return rbo_decref(fd, bo); + } + memcpy(bo->data, ptr, size); + rbo_unmap(fd, bo); + } + return bo; +} + +int rbo_map(int fd, struct rbo *bo) +{ + struct drm_radeon_gem_mmap args; + void *ptr; + int r; + + /* Zero out args to make valgrind happy */ + memset(&args, 0, sizeof(args)); + args.handle = bo->handle; + args.offset = 0; + args.size = (uint64_t)bo->size; + r = drmCommandWriteRead(fd, DRM_RADEON_GEM_MMAP, &args, sizeof(args)); + if (r) { + fprintf(stderr, "error mapping %p 0x%08X (error = %d)\n", + bo, bo->handle, r); + return r; + } + ptr = mmap(0, args.size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, args.addr_ptr); + if (ptr == MAP_FAILED) { + fprintf(stderr, "%s failed to map bo\n", __func__); + return -errno; + } + bo->data = ptr; + return 0; +} + +void rbo_unmap(int fd, struct rbo *bo) +{ + munmap(bo->data, bo->size); + bo->data = NULL; +} + +struct rbo *rbo_decref(int fd, struct rbo *bo) +{ + struct drm_gem_close args; + + if (bo == NULL) + return NULL; + if (--bo->refcount > 0) { + return NULL; + } + + if (bo->data) { + munmap(bo->data, bo->size); + } + memset(&args, 0, sizeof(args)); + args.handle = bo->handle; + drmIoctl(fd, DRM_IOCTL_GEM_CLOSE, &args); + memset(bo, 0, sizeof(struct rbo)); + free(bo); + return NULL; +} + +int radeon_open_fd(void) +{ + return drmOpen("radeon", NULL); +} + +int cs_submit(int fd, struct cs *cs) +{ + struct drm_radeon_cs drmib; + struct drm_radeon_cs_chunk chunks[2]; + uint64_t chunk_array[2]; + int r = 0; + + drmib.num_chunks = 2; + drmib.chunks = (uint64_t)(uintptr_t)chunk_array; + chunks[0].chunk_id = RADEON_CHUNK_ID_IB; + chunks[0].length_dw = cs->pm4_ndw; + chunks[0].chunk_data = (uintptr_t)cs->pm4; + chunks[1].chunk_id = RADEON_CHUNK_ID_RELOCS; + chunks[1].length_dw = cs->reloc_ndw; + chunks[1].chunk_data = (uintptr_t)cs->reloc; + chunk_array[0] = (uintptr_t)&chunks[0]; + chunk_array[1] = (uintptr_t)&chunks[1]; +#if 1 + r = drmCommandWriteRead(fd, DRM_RADEON_CS, &drmib, sizeof(struct drm_radeon_cs)); +#endif + return r; +} + +int main(int argc, char *argv[]) +{ + unsigned i, j; + struct cs cs; + int radeonfd; + struct radeon_cs_reloc *reloc; + + if (argc != 2) { + fprintf(stderr, "usage : %s jsonfile\n", argv[0]); + return -EINVAL; + } + + radeonfd = radeon_open_fd(); + if (radeonfd < 0) { + fprintf(stderr, "failed to radeon fd\n"); + return -1; + } + + if (cs_json_load(&cs, argv[1])) { + fprintf(stderr, "failed to load json\n"); + return -EINVAL; + } + + /* allocate bo */ + for (i = 0; i < cs.nbo; i++) { + cs.bo[i].rbo = rbo(radeonfd, 0, cs.bo[i].size, 4096, cs.bo[i].data); + if (cs.bo[i].rbo == NULL) { + fprintf(stderr, "failed to allocate hw bo[%d]\n", i); + return -EINVAL; + } + if (!rbo_map(radeonfd, cs.bo[i].rbo)) { + fprintf(stderr, "bo[%d][0x%08X][0] =", i, cs.bo[i].rbo->size); + for (j = 0; j < 4; j++) { + fprintf(stderr, " 0x%08x", ((unsigned*)cs.bo[i].rbo->data)[j]); + } + fprintf(stderr, "\n"); + rbo_unmap(radeonfd, cs.bo[i].rbo); + } + } + /* update reloc */ + reloc = (struct radeon_cs_reloc *)cs.reloc; + for (i = 0; i < (cs.reloc_ndw / 4); i++) { + for (j = 0; j < cs.nbo; j++) { + if (reloc[i].handle == cs.bo[j].handle) { + reloc[i].handle = cs.bo[j].rbo->handle; + break; + } + } + if (j == cs.nbo) { + fprintf(stderr, "failed to find bo for handle %d\n", reloc[i].handle); + return -EINVAL; + } + } + + printf("ready to submit, press a key to proceed\n"); + getchar(); + + if (cs_submit(radeonfd, &cs)) { + fprintf(stderr, "cs submission failed\n"); + return -EINVAL; + } + for (i = 0; i < cs.nbo; i++) { + if (!rbo_map(radeonfd, cs.bo[i].rbo)) { + fprintf(stderr, "bo[%d][0x%08X][0] =", i, cs.bo[i].rbo->size); + for (j = 0; j < 4; j++) { + fprintf(stderr, " 0x%08x", ((unsigned*)cs.bo[i].rbo->data)[j]); + } + fprintf(stderr, "\n"); + rbo_unmap(radeonfd, cs.bo[i].rbo); + } + } + + return 0; +} |