Merge 'drm-3264' branch of rsync://rsync.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6

+1501 -10
+5
drivers/char/drm/Makefile
··· 19 19 ffb-objs := ffb_drv.o ffb_context.o 20 20 sis-objs := sis_drv.o sis_ds.o sis_mm.o 21 21 22 + ifeq ($(CONFIG_COMPAT),y) 23 + drm-objs += drm_ioc32.o 24 + radeon-objs += radeon_ioc32.o 25 + endif 26 + 22 27 obj-$(CONFIG_DRM) += drm.o 23 28 obj-$(CONFIG_DRM_GAMMA) += gamma.o 24 29 obj-$(CONFIG_DRM_TDFX) += tdfx.o
+5
drivers/char/drm/drmP.h
··· 316 316 typedef int drm_ioctl_t( struct inode *inode, struct file *filp, 317 317 unsigned int cmd, unsigned long arg ); 318 318 319 + typedef int drm_ioctl_compat_t(struct file *filp, unsigned int cmd, 320 + unsigned long arg); 321 + 319 322 typedef struct drm_ioctl_desc { 320 323 drm_ioctl_t *func; 321 324 int auth_needed; ··· 777 774 extern int drm_version(struct inode *inode, struct file *filp, 778 775 unsigned int cmd, unsigned long arg); 779 776 extern int drm_ioctl(struct inode *inode, struct file *filp, 777 + unsigned int cmd, unsigned long arg); 778 + extern long drm_compat_ioctl(struct file *filp, 780 779 unsigned int cmd, unsigned long arg); 781 780 extern int drm_takedown(drm_device_t * dev); 782 781
+18 -7
drivers/char/drm/drm_bufs.c
··· 60 60 } 61 61 EXPORT_SYMBOL(drm_order); 62 62 63 + #ifdef CONFIG_COMPAT 64 + /* 65 + * Used to allocate 32-bit handles for _DRM_SHM regions 66 + * The 0x10000000 value is chosen to be out of the way of 67 + * FB/register and GART physical addresses. 68 + */ 69 + static unsigned int map32_handle = 0x10000000; 70 + #endif 71 + 63 72 /** 64 73 * Ioctl to specify a range of memory that is available for mapping by a non-root process. 65 74 * ··· 196 187 197 188 down(&dev->struct_sem); 198 189 list_add(&list->head, &dev->maplist->head); 190 + #ifdef CONFIG_COMPAT 191 + /* Assign a 32-bit handle for _DRM_SHM mappings */ 192 + /* We do it here so that dev->struct_sem protects the increment */ 193 + if (map->type == _DRM_SHM) 194 + map->offset = map32_handle += PAGE_SIZE; 195 + #endif 199 196 up(&dev->struct_sem); 200 197 201 198 if ( copy_to_user( argp, map, sizeof(*map) ) ) 202 199 return -EFAULT; 203 - if ( map->type != _DRM_SHM ) { 204 - if ( copy_to_user( &argp->handle, 205 - &map->offset, 206 - sizeof(map->offset) ) ) 207 - return -EFAULT; 208 - } 200 + if (copy_to_user(&argp->handle, &map->offset, sizeof(map->offset))) 201 + return -EFAULT; 209 202 return 0; 210 203 } 211 204 ··· 251 240 r_list = list_entry(list, drm_map_list_t, head); 252 241 253 242 if(r_list->map && 254 - r_list->map->handle == request.handle && 243 + r_list->map->offset == (unsigned long) request.handle && 255 244 r_list->map->flags & _DRM_REMOVABLE) break; 256 245 } 257 246
+3 -3
drivers/char/drm/drm_context.c
··· 225 225 map = dev->context_sareas[request.ctx_id]; 226 226 up(&dev->struct_sem); 227 227 228 - request.handle = map->handle; 228 + request.handle = (void *) map->offset; 229 229 if (copy_to_user(argp, &request, sizeof(request))) 230 230 return -EFAULT; 231 231 return 0; ··· 261 261 down(&dev->struct_sem); 262 262 list_for_each(list, &dev->maplist->head) { 263 263 r_list = list_entry(list, drm_map_list_t, head); 264 - if(r_list->map && 265 - r_list->map->handle == request.handle) 264 + if (r_list->map 265 + && r_list->map->offset == (unsigned long) request.handle) 266 266 goto found; 267 267 } 268 268 bad:
+1069
drivers/char/drm/drm_ioc32.c
··· 1 + /** 2 + * \file drm_ioc32.c 3 + * 4 + * 32-bit ioctl compatibility routines for the 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 + #include <linux/ioctl32.h> 32 + 33 + #include "drmP.h" 34 + #include "drm_core.h" 35 + 36 + #define DRM_IOCTL_VERSION32 DRM_IOWR(0x00, drm_version32_t) 37 + #define DRM_IOCTL_GET_UNIQUE32 DRM_IOWR(0x01, drm_unique32_t) 38 + #define DRM_IOCTL_GET_MAP32 DRM_IOWR(0x04, drm_map32_t) 39 + #define DRM_IOCTL_GET_CLIENT32 DRM_IOWR(0x05, drm_client32_t) 40 + #define DRM_IOCTL_GET_STATS32 DRM_IOR( 0x06, drm_stats32_t) 41 + 42 + #define DRM_IOCTL_SET_UNIQUE32 DRM_IOW( 0x10, drm_unique32_t) 43 + #define DRM_IOCTL_ADD_MAP32 DRM_IOWR(0x15, drm_map32_t) 44 + #define DRM_IOCTL_ADD_BUFS32 DRM_IOWR(0x16, drm_buf_desc32_t) 45 + #define DRM_IOCTL_MARK_BUFS32 DRM_IOW( 0x17, drm_buf_desc32_t) 46 + #define DRM_IOCTL_INFO_BUFS32 DRM_IOWR(0x18, drm_buf_info32_t) 47 + #define DRM_IOCTL_MAP_BUFS32 DRM_IOWR(0x19, drm_buf_map32_t) 48 + #define DRM_IOCTL_FREE_BUFS32 DRM_IOW( 0x1a, drm_buf_free32_t) 49 + 50 + #define DRM_IOCTL_RM_MAP32 DRM_IOW( 0x1b, drm_map32_t) 51 + 52 + #define DRM_IOCTL_SET_SAREA_CTX32 DRM_IOW( 0x1c, drm_ctx_priv_map32_t) 53 + #define DRM_IOCTL_GET_SAREA_CTX32 DRM_IOWR(0x1d, drm_ctx_priv_map32_t) 54 + 55 + #define DRM_IOCTL_RES_CTX32 DRM_IOWR(0x26, drm_ctx_res32_t) 56 + #define DRM_IOCTL_DMA32 DRM_IOWR(0x29, drm_dma32_t) 57 + 58 + #define DRM_IOCTL_AGP_ENABLE32 DRM_IOW( 0x32, drm_agp_mode32_t) 59 + #define DRM_IOCTL_AGP_INFO32 DRM_IOR( 0x33, drm_agp_info32_t) 60 + #define DRM_IOCTL_AGP_ALLOC32 DRM_IOWR(0x34, drm_agp_buffer32_t) 61 + #define DRM_IOCTL_AGP_FREE32 DRM_IOW( 0x35, drm_agp_buffer32_t) 62 + #define DRM_IOCTL_AGP_BIND32 DRM_IOW( 0x36, drm_agp_binding32_t) 63 + #define DRM_IOCTL_AGP_UNBIND32 DRM_IOW( 0x37, drm_agp_binding32_t) 64 + 65 + #define DRM_IOCTL_SG_ALLOC32 DRM_IOW( 0x38, drm_scatter_gather32_t) 66 + #define DRM_IOCTL_SG_FREE32 DRM_IOW( 0x39, drm_scatter_gather32_t) 67 + 68 + #define DRM_IOCTL_WAIT_VBLANK32 DRM_IOWR(0x3a, drm_wait_vblank32_t) 69 + 70 + typedef struct drm_version_32 { 71 + int version_major; /**< Major version */ 72 + int version_minor; /**< Minor version */ 73 + int version_patchlevel;/**< Patch level */ 74 + u32 name_len; /**< Length of name buffer */ 75 + u32 name; /**< Name of driver */ 76 + u32 date_len; /**< Length of date buffer */ 77 + u32 date; /**< User-space buffer to hold date */ 78 + u32 desc_len; /**< Length of desc buffer */ 79 + u32 desc; /**< User-space buffer to hold desc */ 80 + } drm_version32_t; 81 + 82 + static int compat_drm_version(struct file *file, unsigned int cmd, 83 + unsigned long arg) 84 + { 85 + drm_version32_t v32; 86 + drm_version_t __user *version; 87 + int err; 88 + 89 + if (copy_from_user(&v32, (void __user *) arg, sizeof(v32))) 90 + return -EFAULT; 91 + 92 + version = compat_alloc_user_space(sizeof(*version)); 93 + if (!access_ok(VERIFY_WRITE, version, sizeof(*version))) 94 + return -EFAULT; 95 + if (__put_user(v32.name_len, &version->name_len) 96 + || __put_user((void __user *)(unsigned long)v32.name, 97 + &version->name) 98 + || __put_user(v32.date_len, &version->date_len) 99 + || __put_user((void __user *)(unsigned long)v32.date, 100 + &version->date) 101 + || __put_user(v32.desc_len, &version->desc_len) 102 + || __put_user((void __user *)(unsigned long)v32.desc, 103 + &version->desc)) 104 + return -EFAULT; 105 + 106 + err = drm_ioctl(file->f_dentry->d_inode, file, 107 + DRM_IOCTL_VERSION, (unsigned long) version); 108 + if (err) 109 + return err; 110 + 111 + if (__get_user(v32.version_major, &version->version_major) 112 + || __get_user(v32.version_minor, &version->version_minor) 113 + || __get_user(v32.version_patchlevel, &version->version_patchlevel) 114 + || __get_user(v32.name_len, &version->name_len) 115 + || __get_user(v32.date_len, &version->date_len) 116 + || __get_user(v32.desc_len, &version->desc_len)) 117 + return -EFAULT; 118 + 119 + if (copy_to_user((void __user *) arg, &v32, sizeof(v32))) 120 + return -EFAULT; 121 + return 0; 122 + } 123 + 124 + typedef struct drm_unique32 { 125 + u32 unique_len; /**< Length of unique */ 126 + u32 unique; /**< Unique name for driver instantiation */ 127 + } drm_unique32_t; 128 + 129 + static int compat_drm_getunique(struct file *file, unsigned int cmd, 130 + unsigned long arg) 131 + { 132 + drm_unique32_t uq32; 133 + drm_unique_t __user *u; 134 + int err; 135 + 136 + if (copy_from_user(&uq32, (void __user *) arg, sizeof(uq32))) 137 + return -EFAULT; 138 + 139 + u = compat_alloc_user_space(sizeof(*u)); 140 + if (!access_ok(VERIFY_WRITE, u, sizeof(*u))) 141 + return -EFAULT; 142 + if (__put_user(uq32.unique_len, &u->unique_len) 143 + || __put_user((void __user *)(unsigned long) uq32.unique, 144 + &u->unique)) 145 + return -EFAULT; 146 + 147 + err = drm_ioctl(file->f_dentry->d_inode, file, 148 + DRM_IOCTL_GET_UNIQUE, (unsigned long) u); 149 + if (err) 150 + return err; 151 + 152 + if (__get_user(uq32.unique_len, &u->unique_len)) 153 + return -EFAULT; 154 + if (copy_to_user((void __user *) arg, &uq32, sizeof(uq32))) 155 + return -EFAULT; 156 + return 0; 157 + } 158 + 159 + static int compat_drm_setunique(struct file *file, unsigned int cmd, 160 + unsigned long arg) 161 + { 162 + drm_unique32_t uq32; 163 + drm_unique_t __user *u; 164 + 165 + if (copy_from_user(&uq32, (void __user *) arg, sizeof(uq32))) 166 + return -EFAULT; 167 + 168 + u = compat_alloc_user_space(sizeof(*u)); 169 + if (!access_ok(VERIFY_WRITE, u, sizeof(*u))) 170 + return -EFAULT; 171 + if (__put_user(uq32.unique_len, &u->unique_len) 172 + || __put_user((void __user *)(unsigned long) uq32.unique, 173 + &u->unique)) 174 + return -EFAULT; 175 + 176 + return drm_ioctl(file->f_dentry->d_inode, file, 177 + DRM_IOCTL_SET_UNIQUE, (unsigned long) u); 178 + } 179 + 180 + typedef struct drm_map32 { 181 + u32 offset; /**< Requested physical address (0 for SAREA)*/ 182 + u32 size; /**< Requested physical size (bytes) */ 183 + drm_map_type_t type; /**< Type of memory to map */ 184 + drm_map_flags_t flags; /**< Flags */ 185 + u32 handle; /**< User-space: "Handle" to pass to mmap() */ 186 + int mtrr; /**< MTRR slot used */ 187 + } drm_map32_t; 188 + 189 + static int compat_drm_getmap(struct file *file, unsigned int cmd, 190 + unsigned long arg) 191 + { 192 + drm_map32_t __user *argp = (void __user *)arg; 193 + drm_map32_t m32; 194 + drm_map_t __user *map; 195 + int idx, err; 196 + void *handle; 197 + 198 + if (get_user(idx, &argp->offset)) 199 + return -EFAULT; 200 + 201 + map = compat_alloc_user_space(sizeof(*map)); 202 + if (!access_ok(VERIFY_WRITE, map, sizeof(*map))) 203 + return -EFAULT; 204 + if (__put_user(idx, &map->offset)) 205 + return -EFAULT; 206 + 207 + err = drm_ioctl(file->f_dentry->d_inode, file, 208 + DRM_IOCTL_GET_MAP, (unsigned long) map); 209 + if (err) 210 + return err; 211 + 212 + if (__get_user(m32.offset, &map->offset) 213 + || __get_user(m32.size, &map->size) 214 + || __get_user(m32.type, &map->type) 215 + || __get_user(m32.flags, &map->flags) 216 + || __get_user(handle, &map->handle) 217 + || __get_user(m32.mtrr, &map->mtrr)) 218 + return -EFAULT; 219 + 220 + m32.handle = (unsigned long) handle; 221 + if (copy_to_user(argp, &m32, sizeof(m32))) 222 + return -EFAULT; 223 + return 0; 224 + 225 + } 226 + 227 + static int compat_drm_addmap(struct file *file, unsigned int cmd, 228 + unsigned long arg) 229 + { 230 + drm_map32_t __user *argp = (void __user *)arg; 231 + drm_map32_t m32; 232 + drm_map_t __user *map; 233 + int err; 234 + void *handle; 235 + 236 + if (copy_from_user(&m32, argp, sizeof(m32))) 237 + return -EFAULT; 238 + 239 + map = compat_alloc_user_space(sizeof(*map)); 240 + if (!access_ok(VERIFY_WRITE, map, sizeof(*map))) 241 + return -EFAULT; 242 + if (__put_user(m32.offset, &map->offset) 243 + || __put_user(m32.size, &map->size) 244 + || __put_user(m32.type, &map->type) 245 + || __put_user(m32.flags, &map->flags)) 246 + return -EFAULT; 247 + 248 + err = drm_ioctl(file->f_dentry->d_inode, file, 249 + DRM_IOCTL_ADD_MAP, (unsigned long) map); 250 + if (err) 251 + return err; 252 + 253 + if (__get_user(m32.offset, &map->offset) 254 + || __get_user(m32.mtrr, &map->mtrr) 255 + || __get_user(handle, &map->handle)) 256 + return -EFAULT; 257 + 258 + m32.handle = (unsigned long) handle; 259 + if (m32.handle != (unsigned long) handle && printk_ratelimit()) 260 + printk(KERN_ERR "compat_drm_addmap truncated handle" 261 + " %p for type %d offset %x\n", 262 + handle, m32.type, m32.offset); 263 + 264 + if (copy_to_user(argp, &m32, sizeof(m32))) 265 + return -EFAULT; 266 + 267 + return 0; 268 + } 269 + 270 + static int compat_drm_rmmap(struct file *file, unsigned int cmd, 271 + unsigned long arg) 272 + { 273 + drm_map32_t __user *argp = (void __user *)arg; 274 + drm_map_t __user *map; 275 + u32 handle; 276 + 277 + if (get_user(handle, &argp->handle)) 278 + return -EFAULT; 279 + 280 + map = compat_alloc_user_space(sizeof(*map)); 281 + if (!access_ok(VERIFY_WRITE, map, sizeof(*map))) 282 + return -EFAULT; 283 + if (__put_user((void *)(unsigned long) handle, &map->handle)) 284 + return -EFAULT; 285 + 286 + return drm_ioctl(file->f_dentry->d_inode, file, 287 + DRM_IOCTL_RM_MAP, (unsigned long) map); 288 + } 289 + 290 + typedef struct drm_client32 { 291 + int idx; /**< Which client desired? */ 292 + int auth; /**< Is client authenticated? */ 293 + u32 pid; /**< Process ID */ 294 + u32 uid; /**< User ID */ 295 + u32 magic; /**< Magic */ 296 + u32 iocs; /**< Ioctl count */ 297 + } drm_client32_t; 298 + 299 + static int compat_drm_getclient(struct file *file, unsigned int cmd, 300 + unsigned long arg) 301 + { 302 + drm_client32_t c32; 303 + drm_client32_t __user *argp = (void __user *)arg; 304 + drm_client_t __user *client; 305 + int idx, err; 306 + 307 + if (get_user(idx, &argp->idx)) 308 + return -EFAULT; 309 + 310 + client = compat_alloc_user_space(sizeof(*client)); 311 + if (!access_ok(VERIFY_WRITE, client, sizeof(*client))) 312 + return -EFAULT; 313 + if (__put_user(idx, &client->idx)) 314 + return -EFAULT; 315 + 316 + err = drm_ioctl(file->f_dentry->d_inode, file, 317 + DRM_IOCTL_GET_CLIENT, (unsigned long) client); 318 + if (err) 319 + return err; 320 + 321 + if (__get_user(c32.auth, &client->auth) 322 + || __get_user(c32.pid, &client->pid) 323 + || __get_user(c32.uid, &client->uid) 324 + || __get_user(c32.magic, &client->magic) 325 + || __get_user(c32.iocs, &client->iocs)) 326 + return -EFAULT; 327 + 328 + if (copy_to_user(argp, &c32, sizeof(c32))) 329 + return -EFAULT; 330 + return 0; 331 + } 332 + 333 + typedef struct drm_stats32 { 334 + u32 count; 335 + struct { 336 + u32 value; 337 + drm_stat_type_t type; 338 + } data[15]; 339 + } drm_stats32_t; 340 + 341 + static int compat_drm_getstats(struct file *file, unsigned int cmd, 342 + unsigned long arg) 343 + { 344 + drm_stats32_t s32; 345 + drm_stats32_t __user *argp = (void __user *)arg; 346 + drm_stats_t __user *stats; 347 + int i, err; 348 + 349 + stats = compat_alloc_user_space(sizeof(*stats)); 350 + if (!access_ok(VERIFY_WRITE, stats, sizeof(*stats))) 351 + return -EFAULT; 352 + 353 + err = drm_ioctl(file->f_dentry->d_inode, file, 354 + DRM_IOCTL_GET_STATS, (unsigned long) stats); 355 + if (err) 356 + return err; 357 + 358 + if (__get_user(s32.count, &stats->count)) 359 + return -EFAULT; 360 + for (i = 0; i < 15; ++i) 361 + if (__get_user(s32.data[i].value, &stats->data[i].value) 362 + || __get_user(s32.data[i].type, &stats->data[i].type)) 363 + return -EFAULT; 364 + 365 + if (copy_to_user(argp, &s32, sizeof(s32))) 366 + return -EFAULT; 367 + return 0; 368 + } 369 + 370 + typedef struct drm_buf_desc32 { 371 + int count; /**< Number of buffers of this size */ 372 + int size; /**< Size in bytes */ 373 + int low_mark; /**< Low water mark */ 374 + int high_mark; /**< High water mark */ 375 + int flags; 376 + u32 agp_start; /**< Start address in the AGP aperture */ 377 + } drm_buf_desc32_t; 378 + 379 + static int compat_drm_addbufs(struct file *file, unsigned int cmd, 380 + unsigned long arg) 381 + { 382 + drm_buf_desc32_t __user *argp = (void __user *)arg; 383 + drm_buf_desc_t __user *buf; 384 + int err; 385 + unsigned long agp_start; 386 + 387 + buf = compat_alloc_user_space(sizeof(*buf)); 388 + if (!access_ok(VERIFY_WRITE, buf, sizeof(*buf)) 389 + || !access_ok(VERIFY_WRITE, argp, sizeof(*argp))) 390 + return -EFAULT; 391 + 392 + if (__copy_in_user(buf, argp, offsetof(drm_buf_desc32_t, agp_start)) 393 + || __get_user(agp_start, &argp->agp_start) 394 + || __put_user(agp_start, &buf->agp_start)) 395 + return -EFAULT; 396 + 397 + err = drm_ioctl(file->f_dentry->d_inode, file, 398 + DRM_IOCTL_ADD_BUFS, (unsigned long) buf); 399 + if (err) 400 + return err; 401 + 402 + if (__copy_in_user(argp, buf, offsetof(drm_buf_desc32_t, agp_start)) 403 + || __get_user(agp_start, &buf->agp_start) 404 + || __put_user(agp_start, &argp->agp_start)) 405 + return -EFAULT; 406 + 407 + return 0; 408 + } 409 + 410 + static int compat_drm_markbufs(struct file *file, unsigned int cmd, 411 + unsigned long arg) 412 + { 413 + drm_buf_desc32_t b32; 414 + drm_buf_desc32_t __user *argp = (void __user *)arg; 415 + drm_buf_desc_t __user *buf; 416 + 417 + if (copy_from_user(&b32, argp, sizeof(b32))) 418 + return -EFAULT; 419 + 420 + buf = compat_alloc_user_space(sizeof(*buf)); 421 + if (!access_ok(VERIFY_WRITE, buf, sizeof(*buf))) 422 + return -EFAULT; 423 + 424 + if (__put_user(b32.size, &buf->size) 425 + || __put_user(b32.low_mark, &buf->low_mark) 426 + || __put_user(b32.high_mark, &buf->high_mark)) 427 + return -EFAULT; 428 + 429 + return drm_ioctl(file->f_dentry->d_inode, file, 430 + DRM_IOCTL_MARK_BUFS, (unsigned long) buf); 431 + } 432 + 433 + typedef struct drm_buf_info32 { 434 + int count; /**< Entries in list */ 435 + u32 list; 436 + } drm_buf_info32_t; 437 + 438 + static int compat_drm_infobufs(struct file *file, unsigned int cmd, 439 + unsigned long arg) 440 + { 441 + drm_buf_info32_t req32; 442 + drm_buf_info32_t __user *argp = (void __user *)arg; 443 + drm_buf_desc32_t __user *to; 444 + drm_buf_info_t __user *request; 445 + drm_buf_desc_t __user *list; 446 + size_t nbytes; 447 + int i, err; 448 + int count, actual; 449 + 450 + if (copy_from_user(&req32, argp, sizeof(req32))) 451 + return -EFAULT; 452 + 453 + count = req32.count; 454 + to = (drm_buf_desc32_t __user *)(unsigned long) req32.list; 455 + if (count < 0) 456 + count = 0; 457 + if (count > 0 458 + && !access_ok(VERIFY_WRITE, to, count * sizeof(drm_buf_desc32_t))) 459 + return -EFAULT; 460 + 461 + nbytes = sizeof(*request) + count * sizeof(drm_buf_desc_t); 462 + request = compat_alloc_user_space(nbytes); 463 + if (!access_ok(VERIFY_WRITE, request, nbytes)) 464 + return -EFAULT; 465 + list = (drm_buf_desc_t *) (request + 1); 466 + 467 + if (__put_user(count, &request->count) 468 + || __put_user(list, &request->list)) 469 + return -EFAULT; 470 + 471 + err = drm_ioctl(file->f_dentry->d_inode, file, 472 + DRM_IOCTL_INFO_BUFS, (unsigned long) request); 473 + if (err) 474 + return err; 475 + 476 + if (__get_user(actual, &request->count)) 477 + return -EFAULT; 478 + if (count >= actual) 479 + for (i = 0; i < actual; ++i) 480 + if (__copy_in_user(&to[i], &list[i], 481 + offsetof(drm_buf_desc_t, flags))) 482 + return -EFAULT; 483 + 484 + if (__put_user(actual, &argp->count)) 485 + return -EFAULT; 486 + 487 + return 0; 488 + } 489 + 490 + typedef struct drm_buf_pub32 { 491 + int idx; /**< Index into the master buffer list */ 492 + int total; /**< Buffer size */ 493 + int used; /**< Amount of buffer in use (for DMA) */ 494 + u32 address; /**< Address of buffer */ 495 + } drm_buf_pub32_t; 496 + 497 + typedef struct drm_buf_map32 { 498 + int count; /**< Length of the buffer list */ 499 + u32 virtual; /**< Mmap'd area in user-virtual */ 500 + u32 list; /**< Buffer information */ 501 + } drm_buf_map32_t; 502 + 503 + static int compat_drm_mapbufs(struct file *file, unsigned int cmd, 504 + unsigned long arg) 505 + { 506 + drm_buf_map32_t __user *argp = (void __user *)arg; 507 + drm_buf_map32_t req32; 508 + drm_buf_pub32_t __user *list32; 509 + drm_buf_map_t __user *request; 510 + drm_buf_pub_t __user *list; 511 + int i, err; 512 + int count, actual; 513 + size_t nbytes; 514 + void __user *addr; 515 + 516 + if (copy_from_user(&req32, argp, sizeof(req32))) 517 + return -EFAULT; 518 + count = req32.count; 519 + list32 = (void __user *)(unsigned long)req32.list; 520 + 521 + if (count < 0) 522 + return -EINVAL; 523 + nbytes = sizeof(*request) + count * sizeof(drm_buf_pub_t); 524 + request = compat_alloc_user_space(nbytes); 525 + if (!access_ok(VERIFY_WRITE, request, nbytes)) 526 + return -EFAULT; 527 + list = (drm_buf_pub_t *) (request + 1); 528 + 529 + if (__put_user(count, &request->count) 530 + || __put_user(list, &request->list)) 531 + return -EFAULT; 532 + 533 + err = drm_ioctl(file->f_dentry->d_inode, file, 534 + DRM_IOCTL_MAP_BUFS, (unsigned long) request); 535 + if (err) 536 + return err; 537 + 538 + if (__get_user(actual, &request->count)) 539 + return -EFAULT; 540 + if (count >= actual) 541 + for (i = 0; i < actual; ++i) 542 + if (__copy_in_user(&list32[i], &list[i], 543 + offsetof(drm_buf_pub_t, address)) 544 + || __get_user(addr, &list[i].address) 545 + || __put_user((unsigned long) addr, 546 + &list32[i].address)) 547 + return -EFAULT; 548 + 549 + if (__put_user(actual, &argp->count) 550 + || __get_user(addr, &request->virtual) 551 + || __put_user((unsigned long) addr, &argp->virtual)) 552 + return -EFAULT; 553 + 554 + return 0; 555 + } 556 + 557 + typedef struct drm_buf_free32 { 558 + int count; 559 + u32 list; 560 + } drm_buf_free32_t; 561 + 562 + static int compat_drm_freebufs(struct file *file, unsigned int cmd, 563 + unsigned long arg) 564 + { 565 + drm_buf_free32_t req32; 566 + drm_buf_free_t __user *request; 567 + drm_buf_free32_t __user *argp = (void __user *)arg; 568 + 569 + if (copy_from_user(&req32, argp, sizeof(req32))) 570 + return -EFAULT; 571 + 572 + request = compat_alloc_user_space(sizeof(*request)); 573 + if (!access_ok(VERIFY_WRITE, request, sizeof(*request))) 574 + return -EFAULT; 575 + if (__put_user(req32.count, &request->count) 576 + || __put_user((int __user *)(unsigned long) req32.list, 577 + &request->list)) 578 + return -EFAULT; 579 + 580 + return drm_ioctl(file->f_dentry->d_inode, file, 581 + DRM_IOCTL_FREE_BUFS, (unsigned long) request); 582 + } 583 + 584 + typedef struct drm_ctx_priv_map32 { 585 + unsigned int ctx_id; /**< Context requesting private mapping */ 586 + u32 handle; /**< Handle of map */ 587 + } drm_ctx_priv_map32_t; 588 + 589 + static int compat_drm_setsareactx(struct file *file, unsigned int cmd, 590 + unsigned long arg) 591 + { 592 + drm_ctx_priv_map32_t req32; 593 + drm_ctx_priv_map_t __user *request; 594 + drm_ctx_priv_map32_t __user *argp = (void __user *)arg; 595 + 596 + if (copy_from_user(&req32, argp, sizeof(req32))) 597 + return -EFAULT; 598 + 599 + request = compat_alloc_user_space(sizeof(*request)); 600 + if (!access_ok(VERIFY_WRITE, request, sizeof(*request))) 601 + return -EFAULT; 602 + if (__put_user(req32.ctx_id, &request->ctx_id) 603 + || __put_user((void *)(unsigned long) req32.handle, 604 + &request->handle)) 605 + return -EFAULT; 606 + 607 + return drm_ioctl(file->f_dentry->d_inode, file, 608 + DRM_IOCTL_SET_SAREA_CTX, (unsigned long) request); 609 + } 610 + 611 + static int compat_drm_getsareactx(struct file *file, unsigned int cmd, 612 + unsigned long arg) 613 + { 614 + drm_ctx_priv_map_t __user *request; 615 + drm_ctx_priv_map32_t __user *argp = (void __user *)arg; 616 + int err; 617 + unsigned int ctx_id; 618 + void *handle; 619 + 620 + if (!access_ok(VERIFY_WRITE, argp, sizeof(*argp)) 621 + || __get_user(ctx_id, &argp->ctx_id)) 622 + return -EFAULT; 623 + 624 + request = compat_alloc_user_space(sizeof(*request)); 625 + if (!access_ok(VERIFY_WRITE, request, sizeof(*request))) 626 + return -EFAULT; 627 + if (__put_user(ctx_id, &request->ctx_id)) 628 + return -EFAULT; 629 + 630 + err = drm_ioctl(file->f_dentry->d_inode, file, 631 + DRM_IOCTL_GET_SAREA_CTX, (unsigned long) request); 632 + if (err) 633 + return err; 634 + 635 + if (__get_user(handle, &request->handle) 636 + || __put_user((unsigned long) handle, &argp->handle)) 637 + return -EFAULT; 638 + 639 + return 0; 640 + } 641 + 642 + typedef struct drm_ctx_res32 { 643 + int count; 644 + u32 contexts; 645 + } drm_ctx_res32_t; 646 + 647 + static int compat_drm_resctx(struct file *file, unsigned int cmd, 648 + unsigned long arg) 649 + { 650 + drm_ctx_res32_t __user *argp = (void __user *)arg; 651 + drm_ctx_res32_t res32; 652 + drm_ctx_res_t __user *res; 653 + int err; 654 + 655 + if (copy_from_user(&res32, argp, sizeof(res32))) 656 + return -EFAULT; 657 + 658 + res = compat_alloc_user_space(sizeof(*res)); 659 + if (!access_ok(VERIFY_WRITE, res, sizeof(*res))) 660 + return -EFAULT; 661 + if (__put_user(res32.count, &res->count) 662 + || __put_user((drm_ctx_t __user *)(unsigned long) res32.contexts, 663 + &res->contexts)) 664 + return -EFAULT; 665 + 666 + err = drm_ioctl(file->f_dentry->d_inode, file, 667 + DRM_IOCTL_RES_CTX, (unsigned long) res); 668 + if (err) 669 + return err; 670 + 671 + if (__get_user(res32.count, &res->count) 672 + || __put_user(res32.count, &argp->count)) 673 + return -EFAULT; 674 + 675 + return 0; 676 + } 677 + 678 + typedef struct drm_dma32 { 679 + int context; /**< Context handle */ 680 + int send_count; /**< Number of buffers to send */ 681 + u32 send_indices; /**< List of handles to buffers */ 682 + u32 send_sizes; /**< Lengths of data to send */ 683 + drm_dma_flags_t flags; /**< Flags */ 684 + int request_count; /**< Number of buffers requested */ 685 + int request_size; /**< Desired size for buffers */ 686 + u32 request_indices; /**< Buffer information */ 687 + u32 request_sizes; 688 + int granted_count; /**< Number of buffers granted */ 689 + } drm_dma32_t; 690 + 691 + static int compat_drm_dma(struct file *file, unsigned int cmd, 692 + unsigned long arg) 693 + { 694 + drm_dma32_t d32; 695 + drm_dma32_t __user *argp = (void __user *) arg; 696 + drm_dma_t __user *d; 697 + int err; 698 + 699 + if (copy_from_user(&d32, argp, sizeof(d32))) 700 + return -EFAULT; 701 + 702 + d = compat_alloc_user_space(sizeof(*d)); 703 + if (!access_ok(VERIFY_WRITE, d, sizeof(*d))) 704 + return -EFAULT; 705 + 706 + if (__put_user(d32.context, &d->context) 707 + || __put_user(d32.send_count, &d->send_count) 708 + || __put_user((int __user *)(unsigned long) d32.send_indices, 709 + &d->send_indices) 710 + || __put_user((int __user *)(unsigned long) d32.send_sizes, 711 + &d->send_sizes) 712 + || __put_user(d32.flags, &d->flags) 713 + || __put_user(d32.request_count, &d->request_count) 714 + || __put_user((int __user *)(unsigned long) d32.request_indices, 715 + &d->request_indices) 716 + || __put_user((int __user *)(unsigned long) d32.request_sizes, 717 + &d->request_sizes)) 718 + return -EFAULT; 719 + 720 + err = drm_ioctl(file->f_dentry->d_inode, file, 721 + DRM_IOCTL_DMA, (unsigned long) d); 722 + if (err) 723 + return err; 724 + 725 + if (__get_user(d32.request_size, &d->request_size) 726 + || __get_user(d32.granted_count, &d->granted_count) 727 + || __put_user(d32.request_size, &argp->request_size) 728 + || __put_user(d32.granted_count, &argp->granted_count)) 729 + return -EFAULT; 730 + 731 + return 0; 732 + } 733 + 734 + #if __OS_HAS_AGP 735 + typedef struct drm_agp_mode32 { 736 + u32 mode; /**< AGP mode */ 737 + } drm_agp_mode32_t; 738 + 739 + static int compat_drm_agp_enable(struct file *file, unsigned int cmd, 740 + unsigned long arg) 741 + { 742 + drm_agp_mode32_t __user *argp = (void __user *)arg; 743 + drm_agp_mode32_t m32; 744 + drm_agp_mode_t __user *mode; 745 + 746 + if (get_user(m32.mode, &argp->mode)) 747 + return -EFAULT; 748 + 749 + mode = compat_alloc_user_space(sizeof(*mode)); 750 + if (put_user(m32.mode, &mode->mode)) 751 + return -EFAULT; 752 + 753 + return drm_ioctl(file->f_dentry->d_inode, file, 754 + DRM_IOCTL_AGP_ENABLE, (unsigned long) mode); 755 + } 756 + 757 + typedef struct drm_agp_info32 { 758 + int agp_version_major; 759 + int agp_version_minor; 760 + u32 mode; 761 + u32 aperture_base; /* physical address */ 762 + u32 aperture_size; /* bytes */ 763 + u32 memory_allowed; /* bytes */ 764 + u32 memory_used; 765 + 766 + /* PCI information */ 767 + unsigned short id_vendor; 768 + unsigned short id_device; 769 + } drm_agp_info32_t; 770 + 771 + static int compat_drm_agp_info(struct file *file, unsigned int cmd, 772 + unsigned long arg) 773 + { 774 + drm_agp_info32_t __user *argp = (void __user *)arg; 775 + drm_agp_info32_t i32; 776 + drm_agp_info_t __user *info; 777 + int err; 778 + 779 + info = compat_alloc_user_space(sizeof(*info)); 780 + if (!access_ok(VERIFY_WRITE, info, sizeof(*info))) 781 + return -EFAULT; 782 + 783 + err = drm_ioctl(file->f_dentry->d_inode, file, 784 + DRM_IOCTL_AGP_INFO, (unsigned long) info); 785 + if (err) 786 + return err; 787 + 788 + if (__get_user(i32.agp_version_major, &info->agp_version_major) 789 + || __get_user(i32.agp_version_minor, &info->agp_version_minor) 790 + || __get_user(i32.mode, &info->mode) 791 + || __get_user(i32.aperture_base, &info->aperture_base) 792 + || __get_user(i32.aperture_size, &info->aperture_size) 793 + || __get_user(i32.memory_allowed, &info->memory_allowed) 794 + || __get_user(i32.memory_used, &info->memory_used) 795 + || __get_user(i32.id_vendor, &info->id_vendor) 796 + || __get_user(i32.id_device, &info->id_device)) 797 + return -EFAULT; 798 + 799 + if (copy_to_user(argp, &i32, sizeof(i32))) 800 + return -EFAULT; 801 + 802 + return 0; 803 + } 804 + 805 + typedef struct drm_agp_buffer32 { 806 + u32 size; /**< In bytes -- will round to page boundary */ 807 + u32 handle; /**< Used for binding / unbinding */ 808 + u32 type; /**< Type of memory to allocate */ 809 + u32 physical; /**< Physical used by i810 */ 810 + } drm_agp_buffer32_t; 811 + 812 + static int compat_drm_agp_alloc(struct file *file, unsigned int cmd, 813 + unsigned long arg) 814 + { 815 + drm_agp_buffer32_t __user *argp = (void __user *)arg; 816 + drm_agp_buffer32_t req32; 817 + drm_agp_buffer_t __user *request; 818 + int err; 819 + 820 + if (copy_from_user(&req32, argp, sizeof(req32))) 821 + return -EFAULT; 822 + 823 + request = compat_alloc_user_space(sizeof(*request)); 824 + if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) 825 + || __put_user(req32.size, &request->size) 826 + || __put_user(req32.type, &request->type)) 827 + return -EFAULT; 828 + 829 + err = drm_ioctl(file->f_dentry->d_inode, file, 830 + DRM_IOCTL_AGP_ALLOC, (unsigned long) request); 831 + if (err) 832 + return err; 833 + 834 + if (__get_user(req32.handle, &request->handle) 835 + || __get_user(req32.physical, &request->physical) 836 + || copy_to_user(argp, &req32, sizeof(req32))) { 837 + drm_ioctl(file->f_dentry->d_inode, file, 838 + DRM_IOCTL_AGP_FREE, (unsigned long) request); 839 + return -EFAULT; 840 + } 841 + 842 + return 0; 843 + } 844 + 845 + static int compat_drm_agp_free(struct file *file, unsigned int cmd, 846 + unsigned long arg) 847 + { 848 + drm_agp_buffer32_t __user *argp = (void __user *)arg; 849 + drm_agp_buffer_t __user *request; 850 + u32 handle; 851 + 852 + request = compat_alloc_user_space(sizeof(*request)); 853 + if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) 854 + || get_user(handle, &argp->handle) 855 + || __put_user(handle, &request->handle)) 856 + return -EFAULT; 857 + 858 + return drm_ioctl(file->f_dentry->d_inode, file, 859 + DRM_IOCTL_AGP_FREE, (unsigned long) request); 860 + } 861 + 862 + typedef struct drm_agp_binding32 { 863 + u32 handle; /**< From drm_agp_buffer */ 864 + u32 offset; /**< In bytes -- will round to page boundary */ 865 + } drm_agp_binding32_t; 866 + 867 + static int compat_drm_agp_bind(struct file *file, unsigned int cmd, 868 + unsigned long arg) 869 + { 870 + drm_agp_binding32_t __user *argp = (void __user *)arg; 871 + drm_agp_binding32_t req32; 872 + drm_agp_binding_t __user *request; 873 + 874 + if (copy_from_user(&req32, argp, sizeof(req32))) 875 + return -EFAULT; 876 + 877 + request = compat_alloc_user_space(sizeof(*request)); 878 + if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) 879 + || __put_user(req32.handle, &request->handle) 880 + || __put_user(req32.offset, &request->offset)) 881 + return -EFAULT; 882 + 883 + return drm_ioctl(file->f_dentry->d_inode, file, 884 + DRM_IOCTL_AGP_BIND, (unsigned long) request); 885 + } 886 + 887 + static int compat_drm_agp_unbind(struct file *file, unsigned int cmd, 888 + unsigned long arg) 889 + { 890 + drm_agp_binding32_t __user *argp = (void __user *)arg; 891 + drm_agp_binding_t __user *request; 892 + u32 handle; 893 + 894 + request = compat_alloc_user_space(sizeof(*request)); 895 + if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) 896 + || get_user(handle, &argp->handle) 897 + || __put_user(handle, &request->handle)) 898 + return -EFAULT; 899 + 900 + return drm_ioctl(file->f_dentry->d_inode, file, 901 + DRM_IOCTL_AGP_UNBIND, (unsigned long) request); 902 + } 903 + #endif /* __OS_HAS_AGP */ 904 + 905 + typedef struct drm_scatter_gather32 { 906 + u32 size; /**< In bytes -- will round to page boundary */ 907 + u32 handle; /**< Used for mapping / unmapping */ 908 + } drm_scatter_gather32_t; 909 + 910 + static int compat_drm_sg_alloc(struct file *file, unsigned int cmd, 911 + unsigned long arg) 912 + { 913 + drm_scatter_gather32_t __user *argp = (void __user *)arg; 914 + drm_scatter_gather_t __user *request; 915 + int err; 916 + unsigned long x; 917 + 918 + request = compat_alloc_user_space(sizeof(*request)); 919 + if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) 920 + || !access_ok(VERIFY_WRITE, argp, sizeof(*argp)) 921 + || __get_user(x, &argp->size) 922 + || __put_user(x, &request->size)) 923 + return -EFAULT; 924 + 925 + err = drm_ioctl(file->f_dentry->d_inode, file, 926 + DRM_IOCTL_SG_ALLOC, (unsigned long) request); 927 + if (err) 928 + return err; 929 + 930 + /* XXX not sure about the handle conversion here... */ 931 + if (__get_user(x, &request->handle) 932 + || __put_user(x >> PAGE_SHIFT, &argp->handle)) 933 + return -EFAULT; 934 + 935 + return 0; 936 + } 937 + 938 + static int compat_drm_sg_free(struct file *file, unsigned int cmd, 939 + unsigned long arg) 940 + { 941 + drm_scatter_gather32_t __user *argp = (void __user *)arg; 942 + drm_scatter_gather_t __user *request; 943 + unsigned long x; 944 + 945 + request = compat_alloc_user_space(sizeof(*request)); 946 + if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) 947 + || !access_ok(VERIFY_WRITE, argp, sizeof(*argp)) 948 + || __get_user(x, &argp->handle) 949 + || __put_user(x << PAGE_SHIFT, &request->handle)) 950 + return -EFAULT; 951 + 952 + return drm_ioctl(file->f_dentry->d_inode, file, 953 + DRM_IOCTL_SG_FREE, (unsigned long) request); 954 + } 955 + 956 + struct drm_wait_vblank_request32 { 957 + drm_vblank_seq_type_t type; 958 + unsigned int sequence; 959 + u32 signal; 960 + }; 961 + 962 + struct drm_wait_vblank_reply32 { 963 + drm_vblank_seq_type_t type; 964 + unsigned int sequence; 965 + s32 tval_sec; 966 + s32 tval_usec; 967 + }; 968 + 969 + typedef union drm_wait_vblank32 { 970 + struct drm_wait_vblank_request32 request; 971 + struct drm_wait_vblank_reply32 reply; 972 + } drm_wait_vblank32_t; 973 + 974 + static int compat_drm_wait_vblank(struct file *file, unsigned int cmd, 975 + unsigned long arg) 976 + { 977 + drm_wait_vblank32_t __user *argp = (void __user *)arg; 978 + drm_wait_vblank32_t req32; 979 + drm_wait_vblank_t __user *request; 980 + int err; 981 + 982 + if (copy_from_user(&req32, argp, sizeof(req32))) 983 + return -EFAULT; 984 + 985 + request = compat_alloc_user_space(sizeof(*request)); 986 + if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) 987 + || __put_user(req32.request.type, &request->request.type) 988 + || __put_user(req32.request.sequence, &request->request.sequence) 989 + || __put_user(req32.request.signal, &request->request.signal)) 990 + return -EFAULT; 991 + 992 + err = drm_ioctl(file->f_dentry->d_inode, file, 993 + DRM_IOCTL_WAIT_VBLANK, (unsigned long) request); 994 + if (err) 995 + return err; 996 + 997 + if (__get_user(req32.reply.type, &request->reply.type) 998 + || __get_user(req32.reply.sequence, &request->reply.sequence) 999 + || __get_user(req32.reply.tval_sec, &request->reply.tval_sec) 1000 + || __get_user(req32.reply.tval_usec, &request->reply.tval_usec)) 1001 + return -EFAULT; 1002 + 1003 + if (copy_to_user(argp, &req32, sizeof(req32))) 1004 + return -EFAULT; 1005 + 1006 + return 0; 1007 + } 1008 + 1009 + drm_ioctl_compat_t *drm_compat_ioctls[] = { 1010 + [DRM_IOCTL_NR(DRM_IOCTL_VERSION32)] = compat_drm_version, 1011 + [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE32)] = compat_drm_getunique, 1012 + [DRM_IOCTL_NR(DRM_IOCTL_GET_MAP32)] = compat_drm_getmap, 1013 + [DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT32)] = compat_drm_getclient, 1014 + [DRM_IOCTL_NR(DRM_IOCTL_GET_STATS32)] = compat_drm_getstats, 1015 + [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE32)] = compat_drm_setunique, 1016 + [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP32)] = compat_drm_addmap, 1017 + [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS32)] = compat_drm_addbufs, 1018 + [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS32)] = compat_drm_markbufs, 1019 + [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS32)] = compat_drm_infobufs, 1020 + [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS32)] = compat_drm_mapbufs, 1021 + [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS32)] = compat_drm_freebufs, 1022 + [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP32)] = compat_drm_rmmap, 1023 + [DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX32)] = compat_drm_setsareactx, 1024 + [DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX32)] = compat_drm_getsareactx, 1025 + [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX32)] = compat_drm_resctx, 1026 + [DRM_IOCTL_NR(DRM_IOCTL_DMA32)] = compat_drm_dma, 1027 + #if __OS_HAS_AGP 1028 + [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE32)] = compat_drm_agp_enable, 1029 + [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO32)] = compat_drm_agp_info, 1030 + [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC32)] = compat_drm_agp_alloc, 1031 + [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE32)] = compat_drm_agp_free, 1032 + [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND32)] = compat_drm_agp_bind, 1033 + [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND32)] = compat_drm_agp_unbind, 1034 + #endif 1035 + [DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC32)] = compat_drm_sg_alloc, 1036 + [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE32)] = compat_drm_sg_free, 1037 + [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK32)] = compat_drm_wait_vblank, 1038 + }; 1039 + 1040 + /** 1041 + * Called whenever a 32-bit process running under a 64-bit kernel 1042 + * performs an ioctl on /dev/drm. 1043 + * 1044 + * \param filp file pointer. 1045 + * \param cmd command. 1046 + * \param arg user argument. 1047 + * \return zero on success or negative number on failure. 1048 + */ 1049 + long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 1050 + { 1051 + unsigned int nr = DRM_IOCTL_NR(cmd); 1052 + drm_ioctl_compat_t *fn; 1053 + int ret; 1054 + 1055 + if (nr >= DRM_ARRAY_SIZE(drm_compat_ioctls)) 1056 + return -ENOTTY; 1057 + 1058 + fn = drm_compat_ioctls[nr]; 1059 + 1060 + lock_kernel(); /* XXX for now */ 1061 + if (fn != NULL) 1062 + ret = (*fn)(filp, cmd, arg); 1063 + else 1064 + ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg); 1065 + unlock_kernel(); 1066 + 1067 + return ret; 1068 + } 1069 + EXPORT_SYMBOL(drm_compat_ioctl);
+3
drivers/char/drm/radeon_drv.c
··· 101 101 .mmap = drm_mmap, 102 102 .poll = drm_poll, 103 103 .fasync = drm_fasync, 104 + #ifdef CONFIG_COMPAT 105 + .compat_ioctl = radeon_compat_ioctl, 106 + #endif 104 107 }, 105 108 .pci_driver = { 106 109 .name = DRIVER_NAME,
+3
drivers/char/drm/radeon_drv.h
··· 317 317 extern int radeon_postinit( struct drm_device *dev, unsigned long flags ); 318 318 extern int radeon_postcleanup( struct drm_device *dev ); 319 319 320 + extern long radeon_compat_ioctl(struct file *filp, unsigned int cmd, 321 + unsigned long arg); 322 + 320 323 /* Flags for stats.boxes 321 324 */ 322 325 #define RADEON_BOX_DMA_IDLE 0x1
+395
drivers/char/drm/radeon_ioc32.c
··· 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 + #include <linux/ioctl32.h> 32 + 33 + #include "drmP.h" 34 + #include "drm.h" 35 + #include "radeon_drm.h" 36 + #include "radeon_drv.h" 37 + 38 + typedef struct drm_radeon_init32 { 39 + int func; 40 + u32 sarea_priv_offset; 41 + int is_pci; 42 + int cp_mode; 43 + int gart_size; 44 + int ring_size; 45 + int usec_timeout; 46 + 47 + unsigned int fb_bpp; 48 + unsigned int front_offset, front_pitch; 49 + unsigned int back_offset, back_pitch; 50 + unsigned int depth_bpp; 51 + unsigned int depth_offset, depth_pitch; 52 + 53 + u32 fb_offset; 54 + u32 mmio_offset; 55 + u32 ring_offset; 56 + u32 ring_rptr_offset; 57 + u32 buffers_offset; 58 + u32 gart_textures_offset; 59 + } drm_radeon_init32_t; 60 + 61 + static int compat_radeon_cp_init(struct file *file, unsigned int cmd, 62 + unsigned long arg) 63 + { 64 + drm_radeon_init32_t init32; 65 + drm_radeon_init_t __user *init; 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.is_pci, &init->is_pci) 75 + || __put_user(init32.cp_mode, &init->cp_mode) 76 + || __put_user(init32.gart_size, &init->gart_size) 77 + || __put_user(init32.ring_size, &init->ring_size) 78 + || __put_user(init32.usec_timeout, &init->usec_timeout) 79 + || __put_user(init32.fb_bpp, &init->fb_bpp) 80 + || __put_user(init32.front_offset, &init->front_offset) 81 + || __put_user(init32.front_pitch, &init->front_pitch) 82 + || __put_user(init32.back_offset, &init->back_offset) 83 + || __put_user(init32.back_pitch, &init->back_pitch) 84 + || __put_user(init32.depth_bpp, &init->depth_bpp) 85 + || __put_user(init32.depth_offset, &init->depth_offset) 86 + || __put_user(init32.depth_pitch, &init->depth_pitch) 87 + || __put_user(init32.fb_offset, &init->fb_offset) 88 + || __put_user(init32.mmio_offset, &init->mmio_offset) 89 + || __put_user(init32.ring_offset, &init->ring_offset) 90 + || __put_user(init32.ring_rptr_offset, &init->ring_rptr_offset) 91 + || __put_user(init32.buffers_offset, &init->buffers_offset) 92 + || __put_user(init32.gart_textures_offset, 93 + &init->gart_textures_offset)) 94 + return -EFAULT; 95 + 96 + return drm_ioctl(file->f_dentry->d_inode, file, 97 + DRM_IOCTL_RADEON_CP_INIT, (unsigned long) init); 98 + } 99 + 100 + typedef struct drm_radeon_clear32 { 101 + unsigned int flags; 102 + unsigned int clear_color; 103 + unsigned int clear_depth; 104 + unsigned int color_mask; 105 + unsigned int depth_mask; /* misnamed field: should be stencil */ 106 + u32 depth_boxes; 107 + } drm_radeon_clear32_t; 108 + 109 + static int compat_radeon_cp_clear(struct file *file, unsigned int cmd, 110 + unsigned long arg) 111 + { 112 + drm_radeon_clear32_t clr32; 113 + drm_radeon_clear_t __user *clr; 114 + 115 + if (copy_from_user(&clr32, (void __user *)arg, sizeof(clr32))) 116 + return -EFAULT; 117 + 118 + clr = compat_alloc_user_space(sizeof(*clr)); 119 + if (!access_ok(VERIFY_WRITE, clr, sizeof(*clr)) 120 + || __put_user(clr32.flags, &clr->flags) 121 + || __put_user(clr32.clear_color, &clr->clear_color) 122 + || __put_user(clr32.clear_depth, &clr->clear_depth) 123 + || __put_user(clr32.color_mask, &clr->color_mask) 124 + || __put_user(clr32.depth_mask, &clr->depth_mask) 125 + || __put_user((void __user *)(unsigned long)clr32.depth_boxes, 126 + &clr->depth_boxes)) 127 + return -EFAULT; 128 + 129 + return drm_ioctl(file->f_dentry->d_inode, file, 130 + DRM_IOCTL_RADEON_CLEAR, (unsigned long) clr); 131 + } 132 + 133 + typedef struct drm_radeon_stipple32 { 134 + u32 mask; 135 + } drm_radeon_stipple32_t; 136 + 137 + static int compat_radeon_cp_stipple(struct file *file, unsigned int cmd, 138 + unsigned long arg) 139 + { 140 + drm_radeon_stipple32_t __user *argp = (void __user *) arg; 141 + drm_radeon_stipple_t __user *request; 142 + u32 mask; 143 + 144 + if (get_user(mask, &argp->mask)) 145 + return -EFAULT; 146 + 147 + request = compat_alloc_user_space(sizeof(*request)); 148 + if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) 149 + || __put_user((unsigned int __user *)(unsigned long) mask, 150 + &request->mask)) 151 + return -EFAULT; 152 + 153 + return drm_ioctl(file->f_dentry->d_inode, file, 154 + DRM_IOCTL_RADEON_STIPPLE, (unsigned long) request); 155 + } 156 + 157 + typedef struct drm_radeon_tex_image32 { 158 + unsigned int x, y; /* Blit coordinates */ 159 + unsigned int width, height; 160 + u32 data; 161 + } drm_radeon_tex_image32_t; 162 + 163 + typedef struct drm_radeon_texture32 { 164 + unsigned int offset; 165 + int pitch; 166 + int format; 167 + int width; /* Texture image coordinates */ 168 + int height; 169 + u32 image; 170 + } drm_radeon_texture32_t; 171 + 172 + static int compat_radeon_cp_texture(struct file *file, unsigned int cmd, 173 + unsigned long arg) 174 + { 175 + drm_radeon_texture32_t req32; 176 + drm_radeon_texture_t __user *request; 177 + drm_radeon_tex_image32_t img32; 178 + drm_radeon_tex_image_t __user *image; 179 + 180 + if (copy_from_user(&req32, (void __user *) arg, sizeof(req32))) 181 + return -EFAULT; 182 + if (req32.image == 0) 183 + return -EINVAL; 184 + if (copy_from_user(&img32, (void __user *)(unsigned long)req32.image, 185 + sizeof(img32))) 186 + return -EFAULT; 187 + 188 + request = compat_alloc_user_space(sizeof(*request) + sizeof(*image)); 189 + if (!access_ok(VERIFY_WRITE, request, 190 + sizeof(*request) + sizeof(*image))) 191 + return -EFAULT; 192 + image = (drm_radeon_tex_image_t __user *) (request + 1); 193 + 194 + if (__put_user(req32.offset, &request->offset) 195 + || __put_user(req32.pitch, &request->pitch) 196 + || __put_user(req32.format, &request->format) 197 + || __put_user(req32.width, &request->width) 198 + || __put_user(req32.height, &request->height) 199 + || __put_user(image, &request->image) 200 + || __put_user(img32.x, &image->x) 201 + || __put_user(img32.y, &image->y) 202 + || __put_user(img32.width, &image->width) 203 + || __put_user(img32.height, &image->height) 204 + || __put_user((const void __user *)(unsigned long)img32.data, 205 + &image->data)) 206 + return -EFAULT; 207 + 208 + return drm_ioctl(file->f_dentry->d_inode, file, 209 + DRM_IOCTL_RADEON_TEXTURE, (unsigned long) request); 210 + } 211 + 212 + typedef struct drm_radeon_vertex2_32 { 213 + int idx; /* Index of vertex buffer */ 214 + int discard; /* Client finished with buffer? */ 215 + int nr_states; 216 + u32 state; 217 + int nr_prims; 218 + u32 prim; 219 + } drm_radeon_vertex2_32_t; 220 + 221 + static int compat_radeon_cp_vertex2(struct file *file, unsigned int cmd, 222 + unsigned long arg) 223 + { 224 + drm_radeon_vertex2_32_t req32; 225 + drm_radeon_vertex2_t __user *request; 226 + 227 + if (copy_from_user(&req32, (void __user *) arg, sizeof(req32))) 228 + return -EFAULT; 229 + 230 + request = compat_alloc_user_space(sizeof(*request)); 231 + if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) 232 + || __put_user(req32.idx, &request->idx) 233 + || __put_user(req32.discard, &request->discard) 234 + || __put_user(req32.nr_states, &request->nr_states) 235 + || __put_user((void __user *)(unsigned long)req32.state, 236 + &request->state) 237 + || __put_user(req32.nr_prims, &request->nr_prims) 238 + || __put_user((void __user *)(unsigned long)req32.prim, 239 + &request->prim)) 240 + return -EFAULT; 241 + 242 + return drm_ioctl(file->f_dentry->d_inode, file, 243 + DRM_IOCTL_RADEON_VERTEX2, (unsigned long) request); 244 + } 245 + 246 + typedef struct drm_radeon_cmd_buffer32 { 247 + int bufsz; 248 + u32 buf; 249 + int nbox; 250 + u32 boxes; 251 + } drm_radeon_cmd_buffer32_t; 252 + 253 + static int compat_radeon_cp_cmdbuf(struct file *file, unsigned int cmd, 254 + unsigned long arg) 255 + { 256 + drm_radeon_cmd_buffer32_t req32; 257 + drm_radeon_cmd_buffer_t __user *request; 258 + 259 + if (copy_from_user(&req32, (void __user *) arg, sizeof(req32))) 260 + return -EFAULT; 261 + 262 + request = compat_alloc_user_space(sizeof(*request)); 263 + if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) 264 + || __put_user(req32.bufsz, &request->bufsz) 265 + || __put_user((void __user *)(unsigned long)req32.buf, 266 + &request->buf) 267 + || __put_user(req32.nbox, &request->nbox) 268 + || __put_user((void __user *)(unsigned long)req32.boxes, 269 + &request->boxes)) 270 + return -EFAULT; 271 + 272 + return drm_ioctl(file->f_dentry->d_inode, file, 273 + DRM_IOCTL_RADEON_CMDBUF, (unsigned long) request); 274 + } 275 + 276 + typedef struct drm_radeon_getparam32 { 277 + int param; 278 + u32 value; 279 + } drm_radeon_getparam32_t; 280 + 281 + static int compat_radeon_cp_getparam(struct file *file, unsigned int cmd, 282 + unsigned long arg) 283 + { 284 + drm_radeon_getparam32_t req32; 285 + drm_radeon_getparam_t __user *request; 286 + 287 + if (copy_from_user(&req32, (void __user *) arg, sizeof(req32))) 288 + return -EFAULT; 289 + 290 + request = compat_alloc_user_space(sizeof(*request)); 291 + if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) 292 + || __put_user(req32.param, &request->param) 293 + || __put_user((void __user *)(unsigned long)req32.value, 294 + &request->value)) 295 + return -EFAULT; 296 + 297 + return drm_ioctl(file->f_dentry->d_inode, file, 298 + DRM_IOCTL_RADEON_GETPARAM, (unsigned long) request); 299 + } 300 + 301 + typedef struct drm_radeon_mem_alloc32 { 302 + int region; 303 + int alignment; 304 + int size; 305 + u32 region_offset; /* offset from start of fb or GART */ 306 + } drm_radeon_mem_alloc32_t; 307 + 308 + static int compat_radeon_mem_alloc(struct file *file, unsigned int cmd, 309 + unsigned long arg) 310 + { 311 + drm_radeon_mem_alloc32_t req32; 312 + drm_radeon_mem_alloc_t __user *request; 313 + 314 + if (copy_from_user(&req32, (void __user *) arg, sizeof(req32))) 315 + return -EFAULT; 316 + 317 + request = compat_alloc_user_space(sizeof(*request)); 318 + if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) 319 + || __put_user(req32.region, &request->region) 320 + || __put_user(req32.alignment, &request->alignment) 321 + || __put_user(req32.size, &request->size) 322 + || __put_user((int __user *)(unsigned long)req32.region_offset, 323 + &request->region_offset)) 324 + return -EFAULT; 325 + 326 + return drm_ioctl(file->f_dentry->d_inode, file, 327 + DRM_IOCTL_RADEON_ALLOC, (unsigned long) request); 328 + } 329 + 330 + typedef struct drm_radeon_irq_emit32 { 331 + u32 irq_seq; 332 + } drm_radeon_irq_emit32_t; 333 + 334 + static int compat_radeon_irq_emit(struct file *file, unsigned int cmd, 335 + unsigned long arg) 336 + { 337 + drm_radeon_irq_emit32_t req32; 338 + drm_radeon_irq_emit_t __user *request; 339 + 340 + if (copy_from_user(&req32, (void __user *) arg, sizeof(req32))) 341 + return -EFAULT; 342 + 343 + request = compat_alloc_user_space(sizeof(*request)); 344 + if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) 345 + || __put_user((int __user *)(unsigned long)req32.irq_seq, 346 + &request->irq_seq)) 347 + return -EFAULT; 348 + 349 + return drm_ioctl(file->f_dentry->d_inode, file, 350 + DRM_IOCTL_RADEON_IRQ_EMIT, (unsigned long) request); 351 + } 352 + 353 + drm_ioctl_compat_t *radeon_compat_ioctls[] = { 354 + [DRM_RADEON_CP_INIT] = compat_radeon_cp_init, 355 + [DRM_RADEON_CLEAR] = compat_radeon_cp_clear, 356 + [DRM_RADEON_STIPPLE] = compat_radeon_cp_stipple, 357 + [DRM_RADEON_TEXTURE] = compat_radeon_cp_texture, 358 + [DRM_RADEON_VERTEX2] = compat_radeon_cp_vertex2, 359 + [DRM_RADEON_CMDBUF] = compat_radeon_cp_cmdbuf, 360 + [DRM_RADEON_GETPARAM] = compat_radeon_cp_getparam, 361 + [DRM_RADEON_ALLOC] = compat_radeon_mem_alloc, 362 + [DRM_RADEON_IRQ_EMIT] = compat_radeon_irq_emit, 363 + }; 364 + 365 + /** 366 + * Called whenever a 32-bit process running under a 64-bit kernel 367 + * performs an ioctl on /dev/dri/card<n>. 368 + * 369 + * \param filp file pointer. 370 + * \param cmd command. 371 + * \param arg user argument. 372 + * \return zero on success or negative number on failure. 373 + */ 374 + long radeon_compat_ioctl(struct file *filp, unsigned int cmd, 375 + unsigned long arg) 376 + { 377 + unsigned int nr = DRM_IOCTL_NR(cmd); 378 + drm_ioctl_compat_t *fn = NULL; 379 + int ret; 380 + 381 + if (nr < DRM_COMMAND_BASE) 382 + return drm_compat_ioctl(filp, cmd, arg); 383 + 384 + if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(radeon_compat_ioctls)) 385 + fn = radeon_compat_ioctls[nr - DRM_COMMAND_BASE]; 386 + 387 + lock_kernel(); /* XXX for now */ 388 + if (fn != NULL) 389 + ret = (*fn)(filp, cmd, arg); 390 + else 391 + ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg); 392 + unlock_kernel(); 393 + 394 + return ret; 395 + }