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#include <linux/compat.h> 34 35#include "drmP.h" 36#include "drm.h" 37#include "mga_drm.h" 38 39typedef struct drm32_mga_init { 40 int func; 41 u32 sarea_priv_offset; 42 int chipset; 43 int sgram; 44 unsigned int maccess; 45 unsigned int fb_cpp; 46 unsigned int front_offset, front_pitch; 47 unsigned int back_offset, back_pitch; 48 unsigned int depth_cpp; 49 unsigned int depth_offset, depth_pitch; 50 unsigned int texture_offset[MGA_NR_TEX_HEAPS]; 51 unsigned int texture_size[MGA_NR_TEX_HEAPS]; 52 u32 fb_offset; 53 u32 mmio_offset; 54 u32 status_offset; 55 u32 warp_offset; 56 u32 primary_offset; 57 u32 buffers_offset; 58} drm_mga_init32_t; 59 60static int compat_mga_init(struct file *file, unsigned int cmd, 61 unsigned long arg) 62{ 63 drm_mga_init32_t init32; 64 drm_mga_init_t __user *init; 65 int err = 0, i; 66 67 if (copy_from_user(&init32, (void __user *)arg, sizeof(init32))) 68 return -EFAULT; 69 70 init = compat_alloc_user_space(sizeof(*init)); 71 if (!access_ok(VERIFY_WRITE, init, sizeof(*init)) 72 || __put_user(init32.func, &init->func) 73 || __put_user(init32.sarea_priv_offset, &init->sarea_priv_offset) 74 || __put_user(init32.chipset, &init->chipset) 75 || __put_user(init32.sgram, &init->sgram) 76 || __put_user(init32.maccess, &init->maccess) 77 || __put_user(init32.fb_cpp, &init->fb_cpp) 78 || __put_user(init32.front_offset, &init->front_offset) 79 || __put_user(init32.front_pitch, &init->front_pitch) 80 || __put_user(init32.back_offset, &init->back_offset) 81 || __put_user(init32.back_pitch, &init->back_pitch) 82 || __put_user(init32.depth_cpp, &init->depth_cpp) 83 || __put_user(init32.depth_offset, &init->depth_offset) 84 || __put_user(init32.depth_pitch, &init->depth_pitch) 85 || __put_user(init32.fb_offset, &init->fb_offset) 86 || __put_user(init32.mmio_offset, &init->mmio_offset) 87 || __put_user(init32.status_offset, &init->status_offset) 88 || __put_user(init32.warp_offset, &init->warp_offset) 89 || __put_user(init32.primary_offset, &init->primary_offset) 90 || __put_user(init32.buffers_offset, &init->buffers_offset)) 91 return -EFAULT; 92 93 for (i = 0; i < MGA_NR_TEX_HEAPS; i++) { 94 err |= 95 __put_user(init32.texture_offset[i], 96 &init->texture_offset[i]); 97 err |= 98 __put_user(init32.texture_size[i], &init->texture_size[i]); 99 } 100 if (err) 101 return -EFAULT; 102 103 return drm_ioctl(file->f_path.dentry->d_inode, file, 104 DRM_IOCTL_MGA_INIT, (unsigned long)init); 105} 106 107typedef struct drm_mga_getparam32 { 108 int param; 109 u32 value; 110} drm_mga_getparam32_t; 111 112static int compat_mga_getparam(struct file *file, unsigned int cmd, 113 unsigned long arg) 114{ 115 drm_mga_getparam32_t getparam32; 116 drm_mga_getparam_t __user *getparam; 117 118 if (copy_from_user(&getparam32, (void __user *)arg, sizeof(getparam32))) 119 return -EFAULT; 120 121 getparam = compat_alloc_user_space(sizeof(*getparam)); 122 if (!access_ok(VERIFY_WRITE, getparam, sizeof(*getparam)) 123 || __put_user(getparam32.param, &getparam->param) 124 || __put_user((void __user *)(unsigned long)getparam32.value, 125 &getparam->value)) 126 return -EFAULT; 127 128 return drm_ioctl(file->f_path.dentry->d_inode, file, 129 DRM_IOCTL_MGA_GETPARAM, (unsigned long)getparam); 130} 131 132typedef struct drm_mga_drm_bootstrap32 { 133 u32 texture_handle; 134 u32 texture_size; 135 u32 primary_size; 136 u32 secondary_bin_count; 137 u32 secondary_bin_size; 138 u32 agp_mode; 139 u8 agp_size; 140} drm_mga_dma_bootstrap32_t; 141 142static int compat_mga_dma_bootstrap(struct file *file, unsigned int cmd, 143 unsigned long arg) 144{ 145 drm_mga_dma_bootstrap32_t dma_bootstrap32; 146 drm_mga_dma_bootstrap_t __user *dma_bootstrap; 147 int err; 148 149 if (copy_from_user(&dma_bootstrap32, (void __user *)arg, 150 sizeof(dma_bootstrap32))) 151 return -EFAULT; 152 153 dma_bootstrap = compat_alloc_user_space(sizeof(*dma_bootstrap)); 154 if (!access_ok(VERIFY_WRITE, dma_bootstrap, sizeof(*dma_bootstrap)) 155 || __put_user(dma_bootstrap32.texture_handle, 156 &dma_bootstrap->texture_handle) 157 || __put_user(dma_bootstrap32.texture_size, 158 &dma_bootstrap->texture_size) 159 || __put_user(dma_bootstrap32.primary_size, 160 &dma_bootstrap->primary_size) 161 || __put_user(dma_bootstrap32.secondary_bin_count, 162 &dma_bootstrap->secondary_bin_count) 163 || __put_user(dma_bootstrap32.secondary_bin_size, 164 &dma_bootstrap->secondary_bin_size) 165 || __put_user(dma_bootstrap32.agp_mode, &dma_bootstrap->agp_mode) 166 || __put_user(dma_bootstrap32.agp_size, &dma_bootstrap->agp_size)) 167 return -EFAULT; 168 169 err = drm_ioctl(file->f_path.dentry->d_inode, file, 170 DRM_IOCTL_MGA_DMA_BOOTSTRAP, 171 (unsigned long)dma_bootstrap); 172 if (err) 173 return err; 174 175 if (__get_user(dma_bootstrap32.texture_handle, 176 &dma_bootstrap->texture_handle) 177 || __get_user(dma_bootstrap32.texture_size, 178 &dma_bootstrap->texture_size) 179 || __get_user(dma_bootstrap32.primary_size, 180 &dma_bootstrap->primary_size) 181 || __get_user(dma_bootstrap32.secondary_bin_count, 182 &dma_bootstrap->secondary_bin_count) 183 || __get_user(dma_bootstrap32.secondary_bin_size, 184 &dma_bootstrap->secondary_bin_size) 185 || __get_user(dma_bootstrap32.agp_mode, &dma_bootstrap->agp_mode) 186 || __get_user(dma_bootstrap32.agp_size, &dma_bootstrap->agp_size)) 187 return -EFAULT; 188 189 if (copy_to_user((void __user *)arg, &dma_bootstrap32, 190 sizeof(dma_bootstrap32))) 191 return -EFAULT; 192 193 return 0; 194} 195 196drm_ioctl_compat_t *mga_compat_ioctls[] = { 197 [DRM_MGA_INIT] = compat_mga_init, 198 [DRM_MGA_GETPARAM] = compat_mga_getparam, 199 [DRM_MGA_DMA_BOOTSTRAP] = compat_mga_dma_bootstrap, 200}; 201 202/** 203 * Called whenever a 32-bit process running under a 64-bit kernel 204 * performs an ioctl on /dev/dri/card<n>. 205 * 206 * \param filp file pointer. 207 * \param cmd command. 208 * \param arg user argument. 209 * \return zero on success or negative number on failure. 210 */ 211long mga_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 212{ 213 unsigned int nr = DRM_IOCTL_NR(cmd); 214 drm_ioctl_compat_t *fn = NULL; 215 int ret; 216 217 if (nr < DRM_COMMAND_BASE) 218 return drm_compat_ioctl(filp, cmd, arg); 219 220 if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(mga_compat_ioctls)) 221 fn = mga_compat_ioctls[nr - DRM_COMMAND_BASE]; 222 223 lock_kernel(); 224 if (fn != NULL) 225 ret = (*fn) (filp, cmd, arg); 226 else 227 ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg); 228 unlock_kernel(); 229 230 return ret; 231} 232