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 v3.1-rc8 425 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, DRM_IOCTL_RADEON_CP_INIT, (unsigned long)init); 96} 97 98typedef struct drm_radeon_clear32 { 99 unsigned int flags; 100 unsigned int clear_color; 101 unsigned int clear_depth; 102 unsigned int color_mask; 103 unsigned int depth_mask; /* misnamed field: should be stencil */ 104 u32 depth_boxes; 105} drm_radeon_clear32_t; 106 107static int compat_radeon_cp_clear(struct file *file, unsigned int cmd, 108 unsigned long arg) 109{ 110 drm_radeon_clear32_t clr32; 111 drm_radeon_clear_t __user *clr; 112 113 if (copy_from_user(&clr32, (void __user *)arg, sizeof(clr32))) 114 return -EFAULT; 115 116 clr = compat_alloc_user_space(sizeof(*clr)); 117 if (!access_ok(VERIFY_WRITE, clr, sizeof(*clr)) 118 || __put_user(clr32.flags, &clr->flags) 119 || __put_user(clr32.clear_color, &clr->clear_color) 120 || __put_user(clr32.clear_depth, &clr->clear_depth) 121 || __put_user(clr32.color_mask, &clr->color_mask) 122 || __put_user(clr32.depth_mask, &clr->depth_mask) 123 || __put_user((void __user *)(unsigned long)clr32.depth_boxes, 124 &clr->depth_boxes)) 125 return -EFAULT; 126 127 return drm_ioctl(file, DRM_IOCTL_RADEON_CLEAR, (unsigned long)clr); 128} 129 130typedef struct drm_radeon_stipple32 { 131 u32 mask; 132} drm_radeon_stipple32_t; 133 134static int compat_radeon_cp_stipple(struct file *file, unsigned int cmd, 135 unsigned long arg) 136{ 137 drm_radeon_stipple32_t __user *argp = (void __user *)arg; 138 drm_radeon_stipple_t __user *request; 139 u32 mask; 140 141 if (get_user(mask, &argp->mask)) 142 return -EFAULT; 143 144 request = compat_alloc_user_space(sizeof(*request)); 145 if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) 146 || __put_user((unsigned int __user *)(unsigned long)mask, 147 &request->mask)) 148 return -EFAULT; 149 150 return drm_ioctl(file, DRM_IOCTL_RADEON_STIPPLE, (unsigned long)request); 151} 152 153typedef struct drm_radeon_tex_image32 { 154 unsigned int x, y; /* Blit coordinates */ 155 unsigned int width, height; 156 u32 data; 157} drm_radeon_tex_image32_t; 158 159typedef struct drm_radeon_texture32 { 160 unsigned int offset; 161 int pitch; 162 int format; 163 int width; /* Texture image coordinates */ 164 int height; 165 u32 image; 166} drm_radeon_texture32_t; 167 168static int compat_radeon_cp_texture(struct file *file, unsigned int cmd, 169 unsigned long arg) 170{ 171 drm_radeon_texture32_t req32; 172 drm_radeon_texture_t __user *request; 173 drm_radeon_tex_image32_t img32; 174 drm_radeon_tex_image_t __user *image; 175 176 if (copy_from_user(&req32, (void __user *)arg, sizeof(req32))) 177 return -EFAULT; 178 if (req32.image == 0) 179 return -EINVAL; 180 if (copy_from_user(&img32, (void __user *)(unsigned long)req32.image, 181 sizeof(img32))) 182 return -EFAULT; 183 184 request = compat_alloc_user_space(sizeof(*request) + sizeof(*image)); 185 if (!access_ok(VERIFY_WRITE, request, 186 sizeof(*request) + sizeof(*image))) 187 return -EFAULT; 188 image = (drm_radeon_tex_image_t __user *) (request + 1); 189 190 if (__put_user(req32.offset, &request->offset) 191 || __put_user(req32.pitch, &request->pitch) 192 || __put_user(req32.format, &request->format) 193 || __put_user(req32.width, &request->width) 194 || __put_user(req32.height, &request->height) 195 || __put_user(image, &request->image) 196 || __put_user(img32.x, &image->x) 197 || __put_user(img32.y, &image->y) 198 || __put_user(img32.width, &image->width) 199 || __put_user(img32.height, &image->height) 200 || __put_user((const void __user *)(unsigned long)img32.data, 201 &image->data)) 202 return -EFAULT; 203 204 return drm_ioctl(file, DRM_IOCTL_RADEON_TEXTURE, (unsigned long)request); 205} 206 207typedef struct drm_radeon_vertex2_32 { 208 int idx; /* Index of vertex buffer */ 209 int discard; /* Client finished with buffer? */ 210 int nr_states; 211 u32 state; 212 int nr_prims; 213 u32 prim; 214} drm_radeon_vertex2_32_t; 215 216static int compat_radeon_cp_vertex2(struct file *file, unsigned int cmd, 217 unsigned long arg) 218{ 219 drm_radeon_vertex2_32_t req32; 220 drm_radeon_vertex2_t __user *request; 221 222 if (copy_from_user(&req32, (void __user *)arg, sizeof(req32))) 223 return -EFAULT; 224 225 request = compat_alloc_user_space(sizeof(*request)); 226 if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) 227 || __put_user(req32.idx, &request->idx) 228 || __put_user(req32.discard, &request->discard) 229 || __put_user(req32.nr_states, &request->nr_states) 230 || __put_user((void __user *)(unsigned long)req32.state, 231 &request->state) 232 || __put_user(req32.nr_prims, &request->nr_prims) 233 || __put_user((void __user *)(unsigned long)req32.prim, 234 &request->prim)) 235 return -EFAULT; 236 237 return drm_ioctl(file, DRM_IOCTL_RADEON_VERTEX2, (unsigned long)request); 238} 239 240typedef struct drm_radeon_cmd_buffer32 { 241 int bufsz; 242 u32 buf; 243 int nbox; 244 u32 boxes; 245} drm_radeon_cmd_buffer32_t; 246 247static int compat_radeon_cp_cmdbuf(struct file *file, unsigned int cmd, 248 unsigned long arg) 249{ 250 drm_radeon_cmd_buffer32_t req32; 251 drm_radeon_cmd_buffer_t __user *request; 252 253 if (copy_from_user(&req32, (void __user *)arg, sizeof(req32))) 254 return -EFAULT; 255 256 request = compat_alloc_user_space(sizeof(*request)); 257 if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) 258 || __put_user(req32.bufsz, &request->bufsz) 259 || __put_user((void __user *)(unsigned long)req32.buf, 260 &request->buf) 261 || __put_user(req32.nbox, &request->nbox) 262 || __put_user((void __user *)(unsigned long)req32.boxes, 263 &request->boxes)) 264 return -EFAULT; 265 266 return drm_ioctl(file, DRM_IOCTL_RADEON_CMDBUF, (unsigned long)request); 267} 268 269typedef struct drm_radeon_getparam32 { 270 int param; 271 u32 value; 272} drm_radeon_getparam32_t; 273 274static int compat_radeon_cp_getparam(struct file *file, unsigned int cmd, 275 unsigned long arg) 276{ 277 drm_radeon_getparam32_t req32; 278 drm_radeon_getparam_t __user *request; 279 280 if (copy_from_user(&req32, (void __user *)arg, sizeof(req32))) 281 return -EFAULT; 282 283 request = compat_alloc_user_space(sizeof(*request)); 284 if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) 285 || __put_user(req32.param, &request->param) 286 || __put_user((void __user *)(unsigned long)req32.value, 287 &request->value)) 288 return -EFAULT; 289 290 return drm_ioctl(file, DRM_IOCTL_RADEON_GETPARAM, (unsigned long)request); 291} 292 293typedef struct drm_radeon_mem_alloc32 { 294 int region; 295 int alignment; 296 int size; 297 u32 region_offset; /* offset from start of fb or GART */ 298} drm_radeon_mem_alloc32_t; 299 300static int compat_radeon_mem_alloc(struct file *file, unsigned int cmd, 301 unsigned long arg) 302{ 303 drm_radeon_mem_alloc32_t req32; 304 drm_radeon_mem_alloc_t __user *request; 305 306 if (copy_from_user(&req32, (void __user *)arg, sizeof(req32))) 307 return -EFAULT; 308 309 request = compat_alloc_user_space(sizeof(*request)); 310 if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) 311 || __put_user(req32.region, &request->region) 312 || __put_user(req32.alignment, &request->alignment) 313 || __put_user(req32.size, &request->size) 314 || __put_user((int __user *)(unsigned long)req32.region_offset, 315 &request->region_offset)) 316 return -EFAULT; 317 318 return drm_ioctl(file, DRM_IOCTL_RADEON_ALLOC, (unsigned long)request); 319} 320 321typedef struct drm_radeon_irq_emit32 { 322 u32 irq_seq; 323} drm_radeon_irq_emit32_t; 324 325static int compat_radeon_irq_emit(struct file *file, unsigned int cmd, 326 unsigned long arg) 327{ 328 drm_radeon_irq_emit32_t req32; 329 drm_radeon_irq_emit_t __user *request; 330 331 if (copy_from_user(&req32, (void __user *)arg, sizeof(req32))) 332 return -EFAULT; 333 334 request = compat_alloc_user_space(sizeof(*request)); 335 if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) 336 || __put_user((int __user *)(unsigned long)req32.irq_seq, 337 &request->irq_seq)) 338 return -EFAULT; 339 340 return drm_ioctl(file, DRM_IOCTL_RADEON_IRQ_EMIT, (unsigned long)request); 341} 342 343/* The two 64-bit arches where alignof(u64)==4 in 32-bit code */ 344#if defined (CONFIG_X86_64) || defined(CONFIG_IA64) 345typedef struct drm_radeon_setparam32 { 346 int param; 347 u64 value; 348} __attribute__((packed)) drm_radeon_setparam32_t; 349 350static int compat_radeon_cp_setparam(struct file *file, unsigned int cmd, 351 unsigned long arg) 352{ 353 drm_radeon_setparam32_t req32; 354 drm_radeon_setparam_t __user *request; 355 356 if (copy_from_user(&req32, (void __user *) arg, sizeof(req32))) 357 return -EFAULT; 358 359 request = compat_alloc_user_space(sizeof(*request)); 360 if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) 361 || __put_user(req32.param, &request->param) 362 || __put_user((void __user *)(unsigned long)req32.value, 363 &request->value)) 364 return -EFAULT; 365 366 return drm_ioctl(file, DRM_IOCTL_RADEON_SETPARAM, (unsigned long) request); 367} 368#else 369#define compat_radeon_cp_setparam NULL 370#endif /* X86_64 || IA64 */ 371 372drm_ioctl_compat_t *radeon_compat_ioctls[] = { 373 [DRM_RADEON_CP_INIT] = compat_radeon_cp_init, 374 [DRM_RADEON_CLEAR] = compat_radeon_cp_clear, 375 [DRM_RADEON_STIPPLE] = compat_radeon_cp_stipple, 376 [DRM_RADEON_TEXTURE] = compat_radeon_cp_texture, 377 [DRM_RADEON_VERTEX2] = compat_radeon_cp_vertex2, 378 [DRM_RADEON_CMDBUF] = compat_radeon_cp_cmdbuf, 379 [DRM_RADEON_GETPARAM] = compat_radeon_cp_getparam, 380 [DRM_RADEON_SETPARAM] = compat_radeon_cp_setparam, 381 [DRM_RADEON_ALLOC] = compat_radeon_mem_alloc, 382 [DRM_RADEON_IRQ_EMIT] = compat_radeon_irq_emit, 383}; 384 385/** 386 * Called whenever a 32-bit process running under a 64-bit kernel 387 * performs an ioctl on /dev/dri/card<n>. 388 * 389 * \param filp file pointer. 390 * \param cmd command. 391 * \param arg user argument. 392 * \return zero on success or negative number on failure. 393 */ 394long radeon_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 395{ 396 unsigned int nr = DRM_IOCTL_NR(cmd); 397 drm_ioctl_compat_t *fn = NULL; 398 int ret; 399 400 if (nr < DRM_COMMAND_BASE) 401 return drm_compat_ioctl(filp, cmd, arg); 402 403 if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(radeon_compat_ioctls)) 404 fn = radeon_compat_ioctls[nr - DRM_COMMAND_BASE]; 405 406 if (fn != NULL) 407 ret = (*fn) (filp, cmd, arg); 408 else 409 ret = drm_ioctl(filp, cmd, arg); 410 411 return ret; 412} 413 414long radeon_kms_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 415{ 416 unsigned int nr = DRM_IOCTL_NR(cmd); 417 int ret; 418 419 if (nr < DRM_COMMAND_BASE) 420 return drm_compat_ioctl(filp, cmd, arg); 421 422 ret = drm_ioctl(filp, cmd, arg); 423 424 return ret; 425}