+ int ret;
+ struct drm_mode_map_dumb map = {
+ .handle = args->handle,
+ };
+
+ ret = drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &map);
+ args->offset = map.offset;
+
+ return ret;
+}
+
+static int
+vc4_simulator_gem_close_ioctl(int fd, struct drm_gem_close *args)
+{
+ /* Free the simulator's internal tracking. */
+ struct vc4_simulator_file *file = vc4_get_simulator_file_for_fd(fd);
+ struct vc4_simulator_bo *sim_bo = vc4_get_simulator_bo(file,
+ args->handle);
+
+ vc4_free_simulator_bo(sim_bo);
+
+ /* Pass the call on down. */
+ return drmIoctl(fd, DRM_IOCTL_GEM_CLOSE, args);
+}
+
+static int
+vc4_simulator_get_param_ioctl(int fd, struct drm_vc4_get_param *args)
+{
+ switch (args->param) {
+ case DRM_VC4_PARAM_SUPPORTS_BRANCHES:
+ case DRM_VC4_PARAM_SUPPORTS_ETC1:
+ case DRM_VC4_PARAM_SUPPORTS_THREADED_FS:
+ case DRM_VC4_PARAM_SUPPORTS_FIXED_RCL_ORDER:
+ args->value = true;
+ return 0;
+
+ case DRM_VC4_PARAM_SUPPORTS_MADVISE:
+ case DRM_VC4_PARAM_SUPPORTS_PERFMON:
+ errno = -EINVAL;
+ return -1;
+
+ case DRM_VC4_PARAM_V3D_IDENT0:
+ args->value = 0x02000000;
+ return 0;
+
+ case DRM_VC4_PARAM_V3D_IDENT1:
+ args->value = 0x00000001;
+ return 0;
+
+ default:
+ fprintf(stderr, "Unknown DRM_IOCTL_VC4_GET_PARAM(%lld)\n",
+ (long long)args->param);
+ abort();
+ };
+}
+
+int
+vc4_simulator_ioctl(int fd, unsigned long request, void *args)
+{
+ switch (request) {
+ case DRM_IOCTL_VC4_SUBMIT_CL:
+ return vc4_simulator_submit_cl_ioctl(fd, args);
+ case DRM_IOCTL_VC4_CREATE_BO:
+ return vc4_simulator_create_bo_ioctl(fd, args);
+ case DRM_IOCTL_VC4_CREATE_SHADER_BO:
+ return vc4_simulator_create_shader_bo_ioctl(fd, args);
+ case DRM_IOCTL_VC4_MMAP_BO:
+ return vc4_simulator_mmap_bo_ioctl(fd, args);
+
+ case DRM_IOCTL_VC4_WAIT_BO:
+ case DRM_IOCTL_VC4_WAIT_SEQNO:
+ /* We do all of the vc4 rendering synchronously, so we just
+ * return immediately on the wait ioctls. This ignores any
+ * native rendering to the host BO, so it does mean we race on
+ * front buffer rendering.
+ */
+ return 0;
+
+ case DRM_IOCTL_VC4_LABEL_BO:
+ /* This is just debug information, nothing to do. */
+ return 0;
+
+ case DRM_IOCTL_VC4_GET_TILING:
+ case DRM_IOCTL_VC4_SET_TILING:
+ /* Disable these for now, since the sharing with i965 requires
+ * linear buffers.
+ */
+ errno = -EINVAL;
+ return -1;
+
+ case DRM_IOCTL_VC4_GET_PARAM:
+ return vc4_simulator_get_param_ioctl(fd, args);
+
+ case DRM_IOCTL_GEM_CLOSE:
+ return vc4_simulator_gem_close_ioctl(fd, args);
+
+ case DRM_IOCTL_GEM_OPEN:
+ case DRM_IOCTL_GEM_FLINK:
+ return drmIoctl(fd, request, args);
+ default:
+ fprintf(stderr, "Unknown ioctl 0x%08x\n", (int)request);
+ abort();
+ }
+}
+
+static void
+vc4_simulator_init_global(void)
+{
+ mtx_lock(&sim_state.mutex);
+ if (sim_state.refcount++) {
+ mtx_unlock(&sim_state.mutex);
+ return;
+ }
+
+ sim_state.mem_size = 256 * 1024 * 1024;
+ sim_state.mem = calloc(sim_state.mem_size, 1);
+ if (!sim_state.mem)
+ abort();
+ sim_state.heap = u_mmInit(0, sim_state.mem_size);