1/* 2 * Copyright (c) 2019 Etnaviv Project 3 * Copyright (c) 2019 Zodiac Inflight Innovations 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sub license, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice (including the 13 * next paragraph) shall be included in all copies or substantial portions 14 * of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 * DEALINGS IN THE SOFTWARE. 23 * 24 * Authors: 25 * Christian Gmeiner <christian.gmeiner@gmail.com> 26 */ 27 28#include <stdio.h> 29#include <sys/ioctl.h> 30#include "drm-uapi/etnaviv_drm.h" 31#include "drm-shim/drm_shim.h" 32#include "util/u_debug.h" 33 34bool drm_shim_driver_prefers_first_render_node = true; 35 36struct etna_shim_gpu 37{ 38 const char *name; 39 const uint64_t *reg_map; 40}; 41 42static const struct etna_shim_gpu gpus[] = { 43 { 44 .name = "GC400", 45 .reg_map = (const uint64_t[]){ 46 [ETNAVIV_PARAM_GPU_MODEL] = 0x400, 47 [ETNAVIV_PARAM_GPU_REVISION] = 0x4652, 48 [ETNAVIV_PARAM_GPU_FEATURES_0] = 0xa0e9e004, 49 [ETNAVIV_PARAM_GPU_FEATURES_1] = 0xe1299fff, 50 [ETNAVIV_PARAM_GPU_FEATURES_2] = 0xbe13b219, 51 [ETNAVIV_PARAM_GPU_FEATURES_3] = 0xce110010, 52 [ETNAVIV_PARAM_GPU_FEATURES_4] = 0x8000001, 53 [ETNAVIV_PARAM_GPU_FEATURES_5] = 0x20102, 54 [ETNAVIV_PARAM_GPU_FEATURES_6] = 0x120000, 55 [ETNAVIV_PARAM_GPU_FEATURES_7] = 0x0, 56 [ETNAVIV_PARAM_GPU_STREAM_COUNT] = 0x4, 57 [ETNAVIV_PARAM_GPU_REGISTER_MAX] = 0x40, 58 [ETNAVIV_PARAM_GPU_THREAD_COUNT] = 0x80, 59 [ETNAVIV_PARAM_GPU_VERTEX_CACHE_SIZE] = 0x8, 60 [ETNAVIV_PARAM_GPU_SHADER_CORE_COUNT] = 0x1, 61 [ETNAVIV_PARAM_GPU_PIXEL_PIPES] = 0x1, 62 [ETNAVIV_PARAM_GPU_VERTEX_OUTPUT_BUFFER_SIZE] = 0x80, 63 [ETNAVIV_PARAM_GPU_BUFFER_SIZE] = 0x0, 64 [ETNAVIV_PARAM_GPU_INSTRUCTION_COUNT] = 0x100, 65 [ETNAVIV_PARAM_GPU_NUM_CONSTANTS] = 0x140, 66 [ETNAVIV_PARAM_GPU_NUM_VARYINGS] = 0x8, 67 [ETNAVIV_PARAM_SOFTPIN_START_ADDR] = ~0ULL, 68 } 69 }, 70 { 71 .name = "GC2000", 72 .reg_map = (const uint64_t[]){ 73 [ETNAVIV_PARAM_GPU_MODEL] = 0x2000, 74 [ETNAVIV_PARAM_GPU_REVISION] = 0x5108, 75 [ETNAVIV_PARAM_GPU_FEATURES_0] = 0xe0296cad, 76 [ETNAVIV_PARAM_GPU_FEATURES_1] = 0xc9799eff, 77 [ETNAVIV_PARAM_GPU_FEATURES_2] = 0x2efbf2d9, 78 [ETNAVIV_PARAM_GPU_FEATURES_3] = 0x0, 79 [ETNAVIV_PARAM_GPU_FEATURES_4] = 0x0, 80 [ETNAVIV_PARAM_GPU_FEATURES_5] = 0x0, 81 [ETNAVIV_PARAM_GPU_FEATURES_6] = 0x0, 82 [ETNAVIV_PARAM_GPU_FEATURES_7] = 0x0, 83 [ETNAVIV_PARAM_GPU_STREAM_COUNT] = 0x8, 84 [ETNAVIV_PARAM_GPU_REGISTER_MAX] = 0x40, 85 [ETNAVIV_PARAM_GPU_THREAD_COUNT] = 0x400, 86 [ETNAVIV_PARAM_GPU_VERTEX_CACHE_SIZE] = 0x10, 87 [ETNAVIV_PARAM_GPU_SHADER_CORE_COUNT] = 0x4, 88 [ETNAVIV_PARAM_GPU_PIXEL_PIPES] = 0x2, 89 [ETNAVIV_PARAM_GPU_VERTEX_OUTPUT_BUFFER_SIZE] = 0x200, 90 [ETNAVIV_PARAM_GPU_BUFFER_SIZE] = 0x0, 91 [ETNAVIV_PARAM_GPU_INSTRUCTION_COUNT] = 0x200, 92 [ETNAVIV_PARAM_GPU_NUM_CONSTANTS] = 0xa8, 93 [ETNAVIV_PARAM_GPU_NUM_VARYINGS] = 0xb, 94 [ETNAVIV_PARAM_SOFTPIN_START_ADDR] = ~0ULL, 95 } 96 }, 97 { 98 .name = "GC3000", 99 .reg_map = (const uint64_t[]){ 100 [ETNAVIV_PARAM_GPU_MODEL] = 0x3000, 101 [ETNAVIV_PARAM_GPU_REVISION] = 0x5450, 102 [ETNAVIV_PARAM_GPU_FEATURES_0] = 0xe0287cad, 103 [ETNAVIV_PARAM_GPU_FEATURES_1] = 0xc9799efb, 104 [ETNAVIV_PARAM_GPU_FEATURES_2] = 0xfefbfadb, 105 [ETNAVIV_PARAM_GPU_FEATURES_3] = 0xeb9d4bbf, 106 [ETNAVIV_PARAM_GPU_FEATURES_4] = 0xedffdced, 107 [ETNAVIV_PARAM_GPU_FEATURES_5] = 0x930d2f47, 108 [ETNAVIV_PARAM_GPU_FEATURES_6] = 0x10000133, 109 [ETNAVIV_PARAM_GPU_FEATURES_7] = 0x0, 110 [ETNAVIV_PARAM_GPU_STREAM_COUNT] = 0x10, 111 [ETNAVIV_PARAM_GPU_REGISTER_MAX] = 0x40, 112 [ETNAVIV_PARAM_GPU_THREAD_COUNT] = 0x400, 113 [ETNAVIV_PARAM_GPU_VERTEX_CACHE_SIZE] = 0x10, 114 [ETNAVIV_PARAM_GPU_SHADER_CORE_COUNT] = 0x4, 115 [ETNAVIV_PARAM_GPU_PIXEL_PIPES] = 0x2, 116 [ETNAVIV_PARAM_GPU_VERTEX_OUTPUT_BUFFER_SIZE] = 0x400, 117 [ETNAVIV_PARAM_GPU_BUFFER_SIZE] = 0x0, 118 [ETNAVIV_PARAM_GPU_INSTRUCTION_COUNT] = 0x100, 119 [ETNAVIV_PARAM_GPU_NUM_CONSTANTS] = 0x140, 120 [ETNAVIV_PARAM_GPU_NUM_VARYINGS] = 0x10, 121 [ETNAVIV_PARAM_SOFTPIN_START_ADDR] = ~0ULL, 122 } 123 }, 124 { 125 .name = "GC7000L", 126 .reg_map = (const uint64_t[]){ 127 [ETNAVIV_PARAM_GPU_MODEL] = 0x7000, 128 [ETNAVIV_PARAM_GPU_REVISION] = 0x6214, 129 [ETNAVIV_PARAM_GPU_FEATURES_0] = 0xe0287cad, 130 [ETNAVIV_PARAM_GPU_FEATURES_1] = 0xc1799eff, 131 [ETNAVIV_PARAM_GPU_FEATURES_2] = 0xfefbfad9, 132 [ETNAVIV_PARAM_GPU_FEATURES_3] = 0xeb9d4fbf, 133 [ETNAVIV_PARAM_GPU_FEATURES_4] = 0xedfffced, 134 [ETNAVIV_PARAM_GPU_FEATURES_5] = 0xdb0dafc7, 135 [ETNAVIV_PARAM_GPU_FEATURES_6] = 0xbb5ac333, 136 [ETNAVIV_PARAM_GPU_FEATURES_7] = 0xfc8ee200, 137 [ETNAVIV_PARAM_GPU_STREAM_COUNT] = 0x10, 138 [ETNAVIV_PARAM_GPU_REGISTER_MAX] = 0x40, 139 [ETNAVIV_PARAM_GPU_THREAD_COUNT] = 0x400, 140 [ETNAVIV_PARAM_GPU_VERTEX_CACHE_SIZE] = 0x10, 141 [ETNAVIV_PARAM_GPU_SHADER_CORE_COUNT] = 0x4, 142 [ETNAVIV_PARAM_GPU_PIXEL_PIPES] = 0x2, 143 [ETNAVIV_PARAM_GPU_VERTEX_OUTPUT_BUFFER_SIZE] = 0x400, 144 [ETNAVIV_PARAM_GPU_BUFFER_SIZE] = 0x0, 145 [ETNAVIV_PARAM_GPU_INSTRUCTION_COUNT] = 0x200, 146 [ETNAVIV_PARAM_GPU_NUM_CONSTANTS] = 0x140, 147 [ETNAVIV_PARAM_GPU_NUM_VARYINGS] = 0x10, 148 [ETNAVIV_PARAM_SOFTPIN_START_ADDR] = 0x00400000, 149 } 150 } 151}; 152 153static const struct etna_shim_gpu *shim_gpu; 154 155static int 156etnaviv_ioctl_noop(int fd, unsigned long request, void *arg) 157{ 158 return 0; 159} 160 161static int 162etnaviv_ioctl_gem_new(int fd, unsigned long request, void *arg) 163{ 164 struct shim_fd *shim_fd = drm_shim_fd_lookup(fd); 165 struct drm_etnaviv_gem_new *create = arg; 166 struct shim_bo *bo = calloc(1, sizeof(*bo)); 167 168 drm_shim_bo_init(bo, create->size); 169 create->handle = drm_shim_bo_get_handle(shim_fd, bo); 170 drm_shim_bo_put(bo); 171 172 return 0; 173} 174 175static int 176etnaviv_ioctl_gem_info(int fd, unsigned long request, void *arg) 177{ 178 struct shim_fd *shim_fd = drm_shim_fd_lookup(fd); 179 struct drm_etnaviv_gem_info *args = arg; 180 struct shim_bo *bo = drm_shim_bo_lookup(shim_fd, args->handle); 181 182 args->offset = drm_shim_bo_get_mmap_offset(shim_fd, bo); 183 drm_shim_bo_put(bo); 184 185 return 0; 186} 187 188static int 189etnaviv_ioctl_get_param(int fd, unsigned long request, void *arg) 190{ 191 struct drm_etnaviv_param *gp = arg; 192 193 if (gp->param > ETNAVIV_PARAM_SOFTPIN_START_ADDR) { 194 fprintf(stderr, "Unknown DRM_IOCTL_ETNAVIV_GET_PARAM %d\n", gp->param); 195 return -1; 196 } 197 198 gp->value = shim_gpu->reg_map[gp->param]; 199 200 return 0; 201} 202 203static ioctl_fn_t driver_ioctls[] = { 204 [DRM_ETNAVIV_GET_PARAM] = etnaviv_ioctl_get_param, 205 [DRM_ETNAVIV_GEM_NEW] = etnaviv_ioctl_gem_new, 206 [DRM_ETNAVIV_GEM_INFO] = etnaviv_ioctl_gem_info, 207 [DRM_ETNAVIV_GEM_CPU_PREP] = etnaviv_ioctl_noop, 208 [DRM_ETNAVIV_GEM_CPU_FINI] = etnaviv_ioctl_noop, 209 [DRM_ETNAVIV_GEM_SUBMIT] = etnaviv_ioctl_noop, 210 [DRM_ETNAVIV_WAIT_FENCE] = etnaviv_ioctl_noop, 211 [DRM_ETNAVIV_GEM_USERPTR] = etnaviv_ioctl_noop, 212 [DRM_ETNAVIV_GEM_WAIT] = etnaviv_ioctl_noop, 213 [DRM_ETNAVIV_PM_QUERY_DOM] = etnaviv_ioctl_noop, 214 [DRM_ETNAVIV_PM_QUERY_SIG] = etnaviv_ioctl_noop, 215}; 216 217void 218drm_shim_driver_init(void) 219{ 220 shim_device.bus_type = DRM_BUS_PLATFORM; 221 shim_device.driver_name = "etnaviv"; 222 shim_device.driver_ioctls = driver_ioctls; 223 shim_device.driver_ioctl_count = ARRAY_SIZE(driver_ioctls); 224 225 /* etnaviv uses the DRM version to expose features, instead of getparam. */ 226 shim_device.version_major = 1; 227 shim_device.version_minor = 1; 228 shim_device.version_patchlevel = 0; 229 230 drm_shim_override_file("DRIVER=etnaviv\n" 231 "MODALIAS=platform:etnaviv\n", 232 "/sys/dev/char/%d:%d/device/uevent", 233 DRM_MAJOR, render_node_minor); 234 235 /* decide what GPU to emulate */ 236 const char *gpu = debug_get_option("ETNA_SHIM_GPU", "GC2000"); 237 238 for (unsigned i = 0; i < ARRAY_SIZE(gpus); i++) { 239 if (strncasecmp(gpu, gpus[i].name, strlen(gpus[i].name)) == 0) { 240 shim_gpu = &gpus[i]; 241 break; 242 } 243 } 244 245 /* NOTE: keep keep default value and fallback index in sync */ 246 if (!shim_gpu) 247 shim_gpu = &gpus[1]; 248 249 fprintf(stderr, "Using %s as shim gpu\n", shim_gpu->name); 250} 251