Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.27-rc2 424 lines 14 kB view raw
1/** 2 * \file radeon_ioc32.c 3 * 4 * 32-bit ioctl compatibility routines for the Radeon DRM. 5 * 6 * \author Paul Mackerras <paulus@samba.org> 7 * 8 * Copyright (C) Paul Mackerras 2005 9 * All Rights Reserved. 10 * 11 * Permission is hereby granted, free of charge, to any person obtaining a 12 * copy of this software and associated documentation files (the "Software"), 13 * to deal in the Software without restriction, including without limitation 14 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 15 * and/or sell copies of the Software, and to permit persons to whom the 16 * Software is furnished to do so, subject to the following conditions: 17 * 18 * The above copyright notice and this permission notice (including the next 19 * paragraph) shall be included in all copies or substantial portions of the 20 * Software. 21 * 22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 25 * THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 26 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 28 * IN THE SOFTWARE. 29 */ 30#include <linux/compat.h> 31 32#include "drmP.h" 33#include "drm.h" 34#include "radeon_drm.h" 35#include "radeon_drv.h" 36 37typedef struct drm_radeon_init32 { 38 int func; 39 u32 sarea_priv_offset; 40 int is_pci; 41 int cp_mode; 42 int gart_size; 43 int ring_size; 44 int usec_timeout; 45 46 unsigned int fb_bpp; 47 unsigned int front_offset, front_pitch; 48 unsigned int back_offset, back_pitch; 49 unsigned int depth_bpp; 50 unsigned int depth_offset, depth_pitch; 51 52 u32 fb_offset; 53 u32 mmio_offset; 54 u32 ring_offset; 55 u32 ring_rptr_offset; 56 u32 buffers_offset; 57 u32 gart_textures_offset; 58} drm_radeon_init32_t; 59 60static int compat_radeon_cp_init(struct file *file, unsigned int cmd, 61 unsigned long arg) 62{ 63 drm_radeon_init32_t init32; 64 drm_radeon_init_t __user *init; 65 66 if (copy_from_user(&init32, (void __user *)arg, sizeof(init32))) 67 return -EFAULT; 68 69 init = compat_alloc_user_space(sizeof(*init)); 70 if (!access_ok(VERIFY_WRITE, init, sizeof(*init)) 71 || __put_user(init32.func, &init->func) 72 || __put_user(init32.sarea_priv_offset, &init->sarea_priv_offset) 73 || __put_user(init32.is_pci, &init->is_pci) 74 || __put_user(init32.cp_mode, &init->cp_mode) 75 || __put_user(init32.gart_size, &init->gart_size) 76 || __put_user(init32.ring_size, &init->ring_size) 77 || __put_user(init32.usec_timeout, &init->usec_timeout) 78 || __put_user(init32.fb_bpp, &init->fb_bpp) 79 || __put_user(init32.front_offset, &init->front_offset) 80 || __put_user(init32.front_pitch, &init->front_pitch) 81 || __put_user(init32.back_offset, &init->back_offset) 82 || __put_user(init32.back_pitch, &init->back_pitch) 83 || __put_user(init32.depth_bpp, &init->depth_bpp) 84 || __put_user(init32.depth_offset, &init->depth_offset) 85 || __put_user(init32.depth_pitch, &init->depth_pitch) 86 || __put_user(init32.fb_offset, &init->fb_offset) 87 || __put_user(init32.mmio_offset, &init->mmio_offset) 88 || __put_user(init32.ring_offset, &init->ring_offset) 89 || __put_user(init32.ring_rptr_offset, &init->ring_rptr_offset) 90 || __put_user(init32.buffers_offset, &init->buffers_offset) 91 || __put_user(init32.gart_textures_offset, 92 &init->gart_textures_offset)) 93 return -EFAULT; 94 95 return drm_ioctl(file->f_path.dentry->d_inode, file, 96 DRM_IOCTL_RADEON_CP_INIT, (unsigned long)init); 97} 98 99typedef struct drm_radeon_clear32 { 100 unsigned int flags; 101 unsigned int clear_color; 102 unsigned int clear_depth; 103 unsigned int color_mask; 104 unsigned int depth_mask; /* misnamed field: should be stencil */ 105 u32 depth_boxes; 106} drm_radeon_clear32_t; 107 108static int compat_radeon_cp_clear(struct file *file, unsigned int cmd, 109 unsigned long arg) 110{ 111 drm_radeon_clear32_t clr32; 112 drm_radeon_clear_t __user *clr; 113 114 if (copy_from_user(&clr32, (void __user *)arg, sizeof(clr32))) 115 return -EFAULT; 116 117 clr = compat_alloc_user_space(sizeof(*clr)); 118 if (!access_ok(VERIFY_WRITE, clr, sizeof(*clr)) 119 || __put_user(clr32.flags, &clr->flags) 120 || __put_user(clr32.clear_color, &clr->clear_color) 121 || __put_user(clr32.clear_depth, &clr->clear_depth) 122 || __put_user(clr32.color_mask, &clr->color_mask) 123 || __put_user(clr32.depth_mask, &clr->depth_mask) 124 || __put_user((void __user *)(unsigned long)clr32.depth_boxes, 125 &clr->depth_boxes)) 126 return -EFAULT; 127 128 return drm_ioctl(file->f_path.dentry->d_inode, file, 129 DRM_IOCTL_RADEON_CLEAR, (unsigned long)clr); 130} 131 132typedef struct drm_radeon_stipple32 { 133 u32 mask; 134} drm_radeon_stipple32_t; 135 136static int compat_radeon_cp_stipple(struct file *file, unsigned int cmd, 137 unsigned long arg) 138{ 139 drm_radeon_stipple32_t __user *argp = (void __user *)arg; 140 drm_radeon_stipple_t __user *request; 141 u32 mask; 142 143 if (get_user(mask, &argp->mask)) 144 return -EFAULT; 145 146 request = compat_alloc_user_space(sizeof(*request)); 147 if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) 148 || __put_user((unsigned int __user *)(unsigned long)mask, 149 &request->mask)) 150 return -EFAULT; 151 152 return drm_ioctl(file->f_path.dentry->d_inode, file, 153 DRM_IOCTL_RADEON_STIPPLE, (unsigned long)request); 154} 155 156typedef struct drm_radeon_tex_image32 { 157 unsigned int x, y; /* Blit coordinates */ 158 unsigned int width, height; 159 u32 data; 160} drm_radeon_tex_image32_t; 161 162typedef struct drm_radeon_texture32 { 163 unsigned int offset; 164 int pitch; 165 int format; 166 int width; /* Texture image coordinates */ 167 int height; 168 u32 image; 169} drm_radeon_texture32_t; 170 171static int compat_radeon_cp_texture(struct file *file, unsigned int cmd, 172 unsigned long arg) 173{ 174 drm_radeon_texture32_t req32; 175 drm_radeon_texture_t __user *request; 176 drm_radeon_tex_image32_t img32; 177 drm_radeon_tex_image_t __user *image; 178 179 if (copy_from_user(&req32, (void __user *)arg, sizeof(req32))) 180 return -EFAULT; 181 if (req32.image == 0) 182 return -EINVAL; 183 if (copy_from_user(&img32, (void __user *)(unsigned long)req32.image, 184 sizeof(img32))) 185 return -EFAULT; 186 187 request = compat_alloc_user_space(sizeof(*request) + sizeof(*image)); 188 if (!access_ok(VERIFY_WRITE, request, 189 sizeof(*request) + sizeof(*image))) 190 return -EFAULT; 191 image = (drm_radeon_tex_image_t __user *) (request + 1); 192 193 if (__put_user(req32.offset, &request->offset) 194 || __put_user(req32.pitch, &request->pitch) 195 || __put_user(req32.format, &request->format) 196 || __put_user(req32.width, &request->width) 197 || __put_user(req32.height, &request->height) 198 || __put_user(image, &request->image) 199 || __put_user(img32.x, &image->x) 200 || __put_user(img32.y, &image->y) 201 || __put_user(img32.width, &image->width) 202 || __put_user(img32.height, &image->height) 203 || __put_user((const void __user *)(unsigned long)img32.data, 204 &image->data)) 205 return -EFAULT; 206 207 return drm_ioctl(file->f_path.dentry->d_inode, file, 208 DRM_IOCTL_RADEON_TEXTURE, (unsigned long)request); 209} 210 211typedef struct drm_radeon_vertex2_32 { 212 int idx; /* Index of vertex buffer */ 213 int discard; /* Client finished with buffer? */ 214 int nr_states; 215 u32 state; 216 int nr_prims; 217 u32 prim; 218} drm_radeon_vertex2_32_t; 219 220static int compat_radeon_cp_vertex2(struct file *file, unsigned int cmd, 221 unsigned long arg) 222{ 223 drm_radeon_vertex2_32_t req32; 224 drm_radeon_vertex2_t __user *request; 225 226 if (copy_from_user(&req32, (void __user *)arg, sizeof(req32))) 227 return -EFAULT; 228 229 request = compat_alloc_user_space(sizeof(*request)); 230 if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) 231 || __put_user(req32.idx, &request->idx) 232 || __put_user(req32.discard, &request->discard) 233 || __put_user(req32.nr_states, &request->nr_states) 234 || __put_user((void __user *)(unsigned long)req32.state, 235 &request->state) 236 || __put_user(req32.nr_prims, &request->nr_prims) 237 || __put_user((void __user *)(unsigned long)req32.prim, 238 &request->prim)) 239 return -EFAULT; 240 241 return drm_ioctl(file->f_path.dentry->d_inode, file, 242 DRM_IOCTL_RADEON_VERTEX2, (unsigned long)request); 243} 244 245typedef struct drm_radeon_cmd_buffer32 { 246 int bufsz; 247 u32 buf; 248 int nbox; 249 u32 boxes; 250} drm_radeon_cmd_buffer32_t; 251 252static int compat_radeon_cp_cmdbuf(struct file *file, unsigned int cmd, 253 unsigned long arg) 254{ 255 drm_radeon_cmd_buffer32_t req32; 256 drm_radeon_cmd_buffer_t __user *request; 257 258 if (copy_from_user(&req32, (void __user *)arg, sizeof(req32))) 259 return -EFAULT; 260 261 request = compat_alloc_user_space(sizeof(*request)); 262 if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) 263 || __put_user(req32.bufsz, &request->bufsz) 264 || __put_user((void __user *)(unsigned long)req32.buf, 265 &request->buf) 266 || __put_user(req32.nbox, &request->nbox) 267 || __put_user((void __user *)(unsigned long)req32.boxes, 268 &request->boxes)) 269 return -EFAULT; 270 271 return drm_ioctl(file->f_path.dentry->d_inode, file, 272 DRM_IOCTL_RADEON_CMDBUF, (unsigned long)request); 273} 274 275typedef struct drm_radeon_getparam32 { 276 int param; 277 u32 value; 278} drm_radeon_getparam32_t; 279 280static int compat_radeon_cp_getparam(struct file *file, unsigned int cmd, 281 unsigned long arg) 282{ 283 drm_radeon_getparam32_t req32; 284 drm_radeon_getparam_t __user *request; 285 286 if (copy_from_user(&req32, (void __user *)arg, sizeof(req32))) 287 return -EFAULT; 288 289 request = compat_alloc_user_space(sizeof(*request)); 290 if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) 291 || __put_user(req32.param, &request->param) 292 || __put_user((void __user *)(unsigned long)req32.value, 293 &request->value)) 294 return -EFAULT; 295 296 return drm_ioctl(file->f_path.dentry->d_inode, file, 297 DRM_IOCTL_RADEON_GETPARAM, (unsigned long)request); 298} 299 300typedef struct drm_radeon_mem_alloc32 { 301 int region; 302 int alignment; 303 int size; 304 u32 region_offset; /* offset from start of fb or GART */ 305} drm_radeon_mem_alloc32_t; 306 307static int compat_radeon_mem_alloc(struct file *file, unsigned int cmd, 308 unsigned long arg) 309{ 310 drm_radeon_mem_alloc32_t req32; 311 drm_radeon_mem_alloc_t __user *request; 312 313 if (copy_from_user(&req32, (void __user *)arg, sizeof(req32))) 314 return -EFAULT; 315 316 request = compat_alloc_user_space(sizeof(*request)); 317 if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) 318 || __put_user(req32.region, &request->region) 319 || __put_user(req32.alignment, &request->alignment) 320 || __put_user(req32.size, &request->size) 321 || __put_user((int __user *)(unsigned long)req32.region_offset, 322 &request->region_offset)) 323 return -EFAULT; 324 325 return drm_ioctl(file->f_path.dentry->d_inode, file, 326 DRM_IOCTL_RADEON_ALLOC, (unsigned long)request); 327} 328 329typedef struct drm_radeon_irq_emit32 { 330 u32 irq_seq; 331} drm_radeon_irq_emit32_t; 332 333static int compat_radeon_irq_emit(struct file *file, unsigned int cmd, 334 unsigned long arg) 335{ 336 drm_radeon_irq_emit32_t req32; 337 drm_radeon_irq_emit_t __user *request; 338 339 if (copy_from_user(&req32, (void __user *)arg, sizeof(req32))) 340 return -EFAULT; 341 342 request = compat_alloc_user_space(sizeof(*request)); 343 if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) 344 || __put_user((int __user *)(unsigned long)req32.irq_seq, 345 &request->irq_seq)) 346 return -EFAULT; 347 348 return drm_ioctl(file->f_path.dentry->d_inode, file, 349 DRM_IOCTL_RADEON_IRQ_EMIT, (unsigned long)request); 350} 351 352/* The two 64-bit arches where alignof(u64)==4 in 32-bit code */ 353#if defined (CONFIG_X86_64) || defined(CONFIG_IA64) 354typedef struct drm_radeon_setparam32 { 355 int param; 356 u64 value; 357} __attribute__((packed)) drm_radeon_setparam32_t; 358 359static int compat_radeon_cp_setparam(struct file *file, unsigned int cmd, 360 unsigned long arg) 361{ 362 drm_radeon_setparam32_t req32; 363 drm_radeon_setparam_t __user *request; 364 365 if (copy_from_user(&req32, (void __user *) arg, sizeof(req32))) 366 return -EFAULT; 367 368 request = compat_alloc_user_space(sizeof(*request)); 369 if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) 370 || __put_user(req32.param, &request->param) 371 || __put_user((void __user *)(unsigned long)req32.value, 372 &request->value)) 373 return -EFAULT; 374 375 return drm_ioctl(file->f_dentry->d_inode, file, 376 DRM_IOCTL_RADEON_SETPARAM, (unsigned long) request); 377} 378#else 379#define compat_radeon_cp_setparam NULL 380#endif /* X86_64 || IA64 */ 381 382drm_ioctl_compat_t *radeon_compat_ioctls[] = { 383 [DRM_RADEON_CP_INIT] = compat_radeon_cp_init, 384 [DRM_RADEON_CLEAR] = compat_radeon_cp_clear, 385 [DRM_RADEON_STIPPLE] = compat_radeon_cp_stipple, 386 [DRM_RADEON_TEXTURE] = compat_radeon_cp_texture, 387 [DRM_RADEON_VERTEX2] = compat_radeon_cp_vertex2, 388 [DRM_RADEON_CMDBUF] = compat_radeon_cp_cmdbuf, 389 [DRM_RADEON_GETPARAM] = compat_radeon_cp_getparam, 390 [DRM_RADEON_SETPARAM] = compat_radeon_cp_setparam, 391 [DRM_RADEON_ALLOC] = compat_radeon_mem_alloc, 392 [DRM_RADEON_IRQ_EMIT] = compat_radeon_irq_emit, 393}; 394 395/** 396 * Called whenever a 32-bit process running under a 64-bit kernel 397 * performs an ioctl on /dev/dri/card<n>. 398 * 399 * \param filp file pointer. 400 * \param cmd command. 401 * \param arg user argument. 402 * \return zero on success or negative number on failure. 403 */ 404long radeon_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 405{ 406 unsigned int nr = DRM_IOCTL_NR(cmd); 407 drm_ioctl_compat_t *fn = NULL; 408 int ret; 409 410 if (nr < DRM_COMMAND_BASE) 411 return drm_compat_ioctl(filp, cmd, arg); 412 413 if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(radeon_compat_ioctls)) 414 fn = radeon_compat_ioctls[nr - DRM_COMMAND_BASE]; 415 416 lock_kernel(); /* XXX for now */ 417 if (fn != NULL) 418 ret = (*fn) (filp, cmd, arg); 419 else 420 ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg); 421 unlock_kernel(); 422 423 return ret; 424}