1/** 2 * \file mga_ioc32.c 3 * 4 * 32-bit ioctl compatibility routines for the MGA DRM. 5 * 6 * \author Dave Airlie <airlied@linux.ie> with code from patches by Egbert Eich 7 * 8 * 9 * Copyright (C) Paul Mackerras 2005 10 * Copyright (C) Egbert Eich 2003,2004 11 * Copyright (C) Dave Airlie 2005 12 * All Rights Reserved. 13 * 14 * Permission is hereby granted, free of charge, to any person obtaining a 15 * copy of this software and associated documentation files (the "Software"), 16 * to deal in the Software without restriction, including without limitation 17 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 18 * and/or sell copies of the Software, and to permit persons to whom the 19 * Software is furnished to do so, subject to the following conditions: 20 * 21 * The above copyright notice and this permission notice (including the next 22 * paragraph) shall be included in all copies or substantial portions of the 23 * Software. 24 * 25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 28 * THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 29 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 31 * IN THE SOFTWARE. 32 */ 33 34#include <linux/compat.h> 35 36#include "mga_drv.h" 37 38typedef struct drm32_mga_init { 39 int func; 40 u32 sarea_priv_offset; 41 int chipset; 42 int sgram; 43 unsigned int maccess; 44 unsigned int fb_cpp; 45 unsigned int front_offset, front_pitch; 46 unsigned int back_offset, back_pitch; 47 unsigned int depth_cpp; 48 unsigned int depth_offset, depth_pitch; 49 unsigned int texture_offset[MGA_NR_TEX_HEAPS]; 50 unsigned int texture_size[MGA_NR_TEX_HEAPS]; 51 u32 fb_offset; 52 u32 mmio_offset; 53 u32 status_offset; 54 u32 warp_offset; 55 u32 primary_offset; 56 u32 buffers_offset; 57} drm_mga_init32_t; 58 59static int compat_mga_init(struct file *file, unsigned int cmd, 60 unsigned long arg) 61{ 62 drm_mga_init32_t init32; 63 drm_mga_init_t init; 64 65 if (copy_from_user(&init32, (void __user *)arg, sizeof(init32))) 66 return -EFAULT; 67 68 init.func = init32.func; 69 init.sarea_priv_offset = init32.sarea_priv_offset; 70 memcpy(&init.chipset, &init32.chipset, 71 offsetof(drm_mga_init_t, fb_offset) - 72 offsetof(drm_mga_init_t, chipset)); 73 init.fb_offset = init32.fb_offset; 74 init.mmio_offset = init32.mmio_offset; 75 init.status_offset = init32.status_offset; 76 init.warp_offset = init32.warp_offset; 77 init.primary_offset = init32.primary_offset; 78 init.buffers_offset = init32.buffers_offset; 79 80 return drm_ioctl_kernel(file, mga_dma_init, &init, 81 DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY); 82} 83 84typedef struct drm_mga_getparam32 { 85 int param; 86 u32 value; 87} drm_mga_getparam32_t; 88 89static int compat_mga_getparam(struct file *file, unsigned int cmd, 90 unsigned long arg) 91{ 92 drm_mga_getparam32_t getparam32; 93 drm_mga_getparam_t getparam; 94 95 if (copy_from_user(&getparam32, (void __user *)arg, sizeof(getparam32))) 96 return -EFAULT; 97 98 getparam.param = getparam32.param; 99 getparam.value = compat_ptr(getparam32.value); 100 return drm_ioctl_kernel(file, mga_getparam, &getparam, DRM_AUTH); 101} 102 103typedef struct drm_mga_drm_bootstrap32 { 104 u32 texture_handle; 105 u32 texture_size; 106 u32 primary_size; 107 u32 secondary_bin_count; 108 u32 secondary_bin_size; 109 u32 agp_mode; 110 u8 agp_size; 111} drm_mga_dma_bootstrap32_t; 112 113static int compat_mga_dma_bootstrap(struct file *file, unsigned int cmd, 114 unsigned long arg) 115{ 116 drm_mga_dma_bootstrap32_t dma_bootstrap32; 117 drm_mga_dma_bootstrap_t dma_bootstrap; 118 int err; 119 120 if (copy_from_user(&dma_bootstrap32, (void __user *)arg, 121 sizeof(dma_bootstrap32))) 122 return -EFAULT; 123 124 dma_bootstrap.texture_handle = dma_bootstrap32.texture_handle; 125 dma_bootstrap.texture_size = dma_bootstrap32.texture_size; 126 dma_bootstrap.primary_size = dma_bootstrap32.primary_size; 127 dma_bootstrap.secondary_bin_count = dma_bootstrap32.secondary_bin_count; 128 dma_bootstrap.secondary_bin_size = dma_bootstrap32.secondary_bin_size; 129 dma_bootstrap.agp_mode = dma_bootstrap32.agp_mode; 130 dma_bootstrap.agp_size = dma_bootstrap32.agp_size; 131 132 err = drm_ioctl_kernel(file, mga_dma_bootstrap, &dma_bootstrap, 133 DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY); 134 if (err) 135 return err; 136 137 dma_bootstrap32.texture_handle = dma_bootstrap.texture_handle; 138 dma_bootstrap32.texture_size = dma_bootstrap.texture_size; 139 dma_bootstrap32.primary_size = dma_bootstrap.primary_size; 140 dma_bootstrap32.secondary_bin_count = dma_bootstrap.secondary_bin_count; 141 dma_bootstrap32.secondary_bin_size = dma_bootstrap.secondary_bin_size; 142 dma_bootstrap32.agp_mode = dma_bootstrap.agp_mode; 143 dma_bootstrap32.agp_size = dma_bootstrap.agp_size; 144 if (copy_to_user((void __user *)arg, &dma_bootstrap32, 145 sizeof(dma_bootstrap32))) 146 return -EFAULT; 147 148 return 0; 149} 150 151static struct { 152 drm_ioctl_compat_t *fn; 153 char *name; 154} mga_compat_ioctls[] = { 155#define DRM_IOCTL32_DEF(n, f)[DRM_##n] = {.fn = f, .name = #n} 156 DRM_IOCTL32_DEF(MGA_INIT, compat_mga_init), 157 DRM_IOCTL32_DEF(MGA_GETPARAM, compat_mga_getparam), 158 DRM_IOCTL32_DEF(MGA_DMA_BOOTSTRAP, compat_mga_dma_bootstrap), 159}; 160 161/** 162 * Called whenever a 32-bit process running under a 64-bit kernel 163 * performs an ioctl on /dev/dri/card<n>. 164 * 165 * \param filp file pointer. 166 * \param cmd command. 167 * \param arg user argument. 168 * \return zero on success or negative number on failure. 169 */ 170long mga_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 171{ 172 unsigned int nr = DRM_IOCTL_NR(cmd); 173 struct drm_file *file_priv = filp->private_data; 174 drm_ioctl_compat_t *fn = NULL; 175 int ret; 176 177 if (nr < DRM_COMMAND_BASE) 178 return drm_compat_ioctl(filp, cmd, arg); 179 180 if (nr >= DRM_COMMAND_BASE + ARRAY_SIZE(mga_compat_ioctls)) 181 return drm_ioctl(filp, cmd, arg); 182 183 fn = mga_compat_ioctls[nr - DRM_COMMAND_BASE].fn; 184 if (!fn) 185 return drm_ioctl(filp, cmd, arg); 186 187 DRM_DEBUG("pid=%d, dev=0x%lx, auth=%d, %s\n", 188 task_pid_nr(current), 189 (long)old_encode_dev(file_priv->minor->kdev->devt), 190 file_priv->authenticated, 191 mga_compat_ioctls[nr - DRM_COMMAND_BASE].name); 192 ret = (*fn) (filp, cmd, arg); 193 if (ret) 194 DRM_DEBUG("ret = %d\n", ret); 195 return ret; 196} 197