| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* $Id: ioctl32.c,v 1.136 2002/01/14 09:49:52 davem Exp $ | 
|  | 2 | * ioctl32.c: Conversion between 32bit and 64bit native ioctls. | 
|  | 3 | * | 
|  | 4 | * Copyright (C) 1997-2000  Jakub Jelinek  (jakub@redhat.com) | 
|  | 5 | * Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be) | 
|  | 6 | * Copyright (C) 2003  Pavel Machek (pavel@suse.cz) | 
|  | 7 | * | 
|  | 8 | * These routines maintain argument size conversion between 32bit and 64bit | 
|  | 9 | * ioctls. | 
|  | 10 | */ | 
|  | 11 |  | 
|  | 12 | #define INCLUDES | 
|  | 13 | #include "compat_ioctl.c" | 
|  | 14 | #include <linux/ncp_fs.h> | 
|  | 15 | #include <linux/syscalls.h> | 
|  | 16 | #include <asm/fbio.h> | 
|  | 17 | #include <asm/kbio.h> | 
|  | 18 | #include <asm/vuid_event.h> | 
|  | 19 | #include <asm/envctrl.h> | 
|  | 20 | #include <asm/display7seg.h> | 
|  | 21 | #include <asm/openpromio.h> | 
|  | 22 | #include <asm/audioio.h> | 
|  | 23 | #include <asm/watchdog.h> | 
|  | 24 |  | 
|  | 25 | /* Use this to get at 32-bit user passed pointers. | 
|  | 26 | * See sys_sparc32.c for description about it. | 
|  | 27 | */ | 
|  | 28 | #define A(__x) compat_ptr(__x) | 
|  | 29 |  | 
|  | 30 | static __inline__ void *alloc_user_space(long len) | 
|  | 31 | { | 
|  | 32 | struct pt_regs *regs = current_thread_info()->kregs; | 
|  | 33 | unsigned long usp = regs->u_regs[UREG_I6]; | 
|  | 34 |  | 
|  | 35 | if (!(test_thread_flag(TIF_32BIT))) | 
|  | 36 | usp += STACK_BIAS; | 
|  | 37 |  | 
|  | 38 | return (void *) (usp - len); | 
|  | 39 | } | 
|  | 40 |  | 
|  | 41 | #define CODE | 
|  | 42 | #include "compat_ioctl.c" | 
|  | 43 |  | 
|  | 44 | struct  fbcmap32 { | 
|  | 45 | int             index;          /* first element (0 origin) */ | 
|  | 46 | int             count; | 
|  | 47 | u32		red; | 
|  | 48 | u32		green; | 
|  | 49 | u32		blue; | 
|  | 50 | }; | 
|  | 51 |  | 
|  | 52 | #define FBIOPUTCMAP32	_IOW('F', 3, struct fbcmap32) | 
|  | 53 | #define FBIOGETCMAP32	_IOW('F', 4, struct fbcmap32) | 
|  | 54 |  | 
|  | 55 | static int fbiogetputcmap(unsigned int fd, unsigned int cmd, unsigned long arg) | 
|  | 56 | { | 
|  | 57 | struct fbcmap32 __user *argp = (void __user *)arg; | 
|  | 58 | struct fbcmap __user *p = compat_alloc_user_space(sizeof(*p)); | 
|  | 59 | u32 addr; | 
|  | 60 | int ret; | 
|  | 61 |  | 
|  | 62 | ret = copy_in_user(p, argp, 2 * sizeof(int)); | 
|  | 63 | ret |= get_user(addr, &argp->red); | 
|  | 64 | ret |= put_user(compat_ptr(addr), &p->red); | 
|  | 65 | ret |= get_user(addr, &argp->green); | 
|  | 66 | ret |= put_user(compat_ptr(addr), &p->green); | 
|  | 67 | ret |= get_user(addr, &argp->blue); | 
|  | 68 | ret |= put_user(compat_ptr(addr), &p->blue); | 
|  | 69 | if (ret) | 
|  | 70 | return -EFAULT; | 
|  | 71 | return sys_ioctl(fd, (cmd == FBIOPUTCMAP32) ? FBIOPUTCMAP_SPARC : FBIOGETCMAP_SPARC, (unsigned long)p); | 
|  | 72 | } | 
|  | 73 |  | 
|  | 74 | struct fbcursor32 { | 
|  | 75 | short set;		/* what to set, choose from the list above */ | 
|  | 76 | short enable;		/* cursor on/off */ | 
|  | 77 | struct fbcurpos pos;	/* cursor position */ | 
|  | 78 | struct fbcurpos hot;	/* cursor hot spot */ | 
|  | 79 | struct fbcmap32 cmap;	/* color map info */ | 
|  | 80 | struct fbcurpos size;	/* cursor bit map size */ | 
|  | 81 | u32	image;		/* cursor image bits */ | 
|  | 82 | u32	mask;		/* cursor mask bits */ | 
|  | 83 | }; | 
|  | 84 |  | 
|  | 85 | #define FBIOSCURSOR32	_IOW('F', 24, struct fbcursor32) | 
|  | 86 | #define FBIOGCURSOR32	_IOW('F', 25, struct fbcursor32) | 
|  | 87 |  | 
|  | 88 | static int fbiogscursor(unsigned int fd, unsigned int cmd, unsigned long arg) | 
|  | 89 | { | 
|  | 90 | struct fbcursor __user *p = compat_alloc_user_space(sizeof(*p)); | 
|  | 91 | struct fbcursor32 __user *argp =  (void __user *)arg; | 
|  | 92 | compat_uptr_t addr; | 
|  | 93 | int ret; | 
|  | 94 |  | 
|  | 95 | ret = copy_in_user(p, argp, | 
|  | 96 | 2 * sizeof (short) + 2 * sizeof(struct fbcurpos)); | 
|  | 97 | ret |= copy_in_user(&p->size, &argp->size, sizeof(struct fbcurpos)); | 
|  | 98 | ret |= copy_in_user(&p->cmap, &argp->cmap, 2 * sizeof(int)); | 
|  | 99 | ret |= get_user(addr, &argp->cmap.red); | 
|  | 100 | ret |= put_user(compat_ptr(addr), &p->cmap.red); | 
|  | 101 | ret |= get_user(addr, &argp->cmap.green); | 
|  | 102 | ret |= put_user(compat_ptr(addr), &p->cmap.green); | 
|  | 103 | ret |= get_user(addr, &argp->cmap.blue); | 
|  | 104 | ret |= put_user(compat_ptr(addr), &p->cmap.blue); | 
|  | 105 | ret |= get_user(addr, &argp->mask); | 
|  | 106 | ret |= put_user(compat_ptr(addr), &p->mask); | 
|  | 107 | ret |= get_user(addr, &argp->image); | 
|  | 108 | ret |= put_user(compat_ptr(addr), &p->image); | 
|  | 109 | if (ret) | 
|  | 110 | return -EFAULT; | 
|  | 111 | return sys_ioctl (fd, FBIOSCURSOR, (unsigned long)p); | 
|  | 112 | } | 
|  | 113 |  | 
|  | 114 | #if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE) | 
|  | 115 | /* This really belongs in include/linux/drm.h -DaveM */ | 
|  | 116 | #include "../../../drivers/char/drm/drm.h" | 
|  | 117 |  | 
|  | 118 | typedef struct drm32_version { | 
|  | 119 | int    version_major;	  /* Major version			    */ | 
|  | 120 | int    version_minor;	  /* Minor version			    */ | 
|  | 121 | int    version_patchlevel;/* Patch level			    */ | 
|  | 122 | int    name_len;	  /* Length of name buffer		    */ | 
|  | 123 | u32    name;		  /* Name of driver			    */ | 
|  | 124 | int    date_len;	  /* Length of date buffer		    */ | 
|  | 125 | u32    date;		  /* User-space buffer to hold date	    */ | 
|  | 126 | int    desc_len;	  /* Length of desc buffer		    */ | 
|  | 127 | u32    desc;		  /* User-space buffer to hold desc	    */ | 
|  | 128 | } drm32_version_t; | 
|  | 129 | #define DRM32_IOCTL_VERSION    DRM_IOWR(0x00, drm32_version_t) | 
|  | 130 |  | 
|  | 131 | static int drm32_version(unsigned int fd, unsigned int cmd, unsigned long arg) | 
|  | 132 | { | 
|  | 133 | drm32_version_t __user *uversion = (drm32_version_t __user *)arg; | 
|  | 134 | drm_version_t __user *p = compat_alloc_user_space(sizeof(*p)); | 
|  | 135 | compat_uptr_t addr; | 
|  | 136 | int n; | 
|  | 137 | int ret; | 
|  | 138 |  | 
|  | 139 | if (clear_user(p, 3 * sizeof(int)) || | 
|  | 140 | get_user(n, &uversion->name_len) || | 
|  | 141 | put_user(n, &p->name_len) || | 
|  | 142 | get_user(addr, &uversion->name) || | 
|  | 143 | put_user(compat_ptr(addr), &p->name) || | 
|  | 144 | get_user(n, &uversion->date_len) || | 
|  | 145 | put_user(n, &p->date_len) || | 
|  | 146 | get_user(addr, &uversion->date) || | 
|  | 147 | put_user(compat_ptr(addr), &p->date) || | 
|  | 148 | get_user(n, &uversion->desc_len) || | 
|  | 149 | put_user(n, &p->desc_len) || | 
|  | 150 | get_user(addr, &uversion->desc) || | 
|  | 151 | put_user(compat_ptr(addr), &p->desc)) | 
|  | 152 | return -EFAULT; | 
|  | 153 |  | 
|  | 154 | ret = sys_ioctl(fd, DRM_IOCTL_VERSION, (unsigned long)p); | 
|  | 155 | if (ret) | 
|  | 156 | return ret; | 
|  | 157 |  | 
|  | 158 | if (copy_in_user(uversion, p, 3 * sizeof(int)) || | 
|  | 159 | get_user(n, &p->name_len) || | 
|  | 160 | put_user(n, &uversion->name_len) || | 
|  | 161 | get_user(n, &p->date_len) || | 
|  | 162 | put_user(n, &uversion->date_len) || | 
|  | 163 | get_user(n, &p->desc_len) || | 
|  | 164 | put_user(n, &uversion->desc_len)) | 
|  | 165 | return -EFAULT; | 
|  | 166 |  | 
|  | 167 | return 0; | 
|  | 168 | } | 
|  | 169 |  | 
|  | 170 | typedef struct drm32_unique { | 
|  | 171 | int	unique_len;	  /* Length of unique			    */ | 
|  | 172 | u32	unique;		  /* Unique name for driver instantiation   */ | 
|  | 173 | } drm32_unique_t; | 
|  | 174 | #define DRM32_IOCTL_GET_UNIQUE DRM_IOWR(0x01, drm32_unique_t) | 
|  | 175 | #define DRM32_IOCTL_SET_UNIQUE DRM_IOW( 0x10, drm32_unique_t) | 
|  | 176 |  | 
|  | 177 | static int drm32_getsetunique(unsigned int fd, unsigned int cmd, unsigned long arg) | 
|  | 178 | { | 
|  | 179 | drm32_unique_t __user *uarg = (drm32_unique_t __user *)arg; | 
|  | 180 | drm_unique_t __user *p = compat_alloc_user_space(sizeof(*p)); | 
|  | 181 | compat_uptr_t addr; | 
|  | 182 | int n; | 
|  | 183 | int ret; | 
|  | 184 |  | 
|  | 185 | if (get_user(n, &uarg->unique_len) || | 
|  | 186 | put_user(n, &p->unique_len) || | 
|  | 187 | get_user(addr, &uarg->unique) || | 
|  | 188 | put_user(compat_ptr(addr), &p->unique)) | 
|  | 189 | return -EFAULT; | 
|  | 190 |  | 
|  | 191 | if (cmd == DRM32_IOCTL_GET_UNIQUE) | 
|  | 192 | ret = sys_ioctl (fd, DRM_IOCTL_GET_UNIQUE, (unsigned long)p); | 
|  | 193 | else | 
|  | 194 | ret = sys_ioctl (fd, DRM_IOCTL_SET_UNIQUE, (unsigned long)p); | 
|  | 195 |  | 
|  | 196 | if (ret) | 
|  | 197 | return ret; | 
|  | 198 |  | 
|  | 199 | if (get_user(n, &p->unique_len) || put_user(n, &uarg->unique_len)) | 
|  | 200 | return -EFAULT; | 
|  | 201 |  | 
|  | 202 | return 0; | 
|  | 203 | } | 
|  | 204 |  | 
|  | 205 | typedef struct drm32_map { | 
|  | 206 | u32		offset;	 /* Requested physical address (0 for SAREA)*/ | 
|  | 207 | u32		size;	 /* Requested physical size (bytes)	    */ | 
|  | 208 | drm_map_type_t	type;	 /* Type of memory to map		    */ | 
|  | 209 | drm_map_flags_t flags;	 /* Flags				    */ | 
|  | 210 | u32		handle;  /* User-space: "Handle" to pass to mmap    */ | 
|  | 211 | /* Kernel-space: kernel-virtual address    */ | 
|  | 212 | int		mtrr;	 /* MTRR slot used			    */ | 
|  | 213 | /* Private data			    */ | 
|  | 214 | } drm32_map_t; | 
|  | 215 | #define DRM32_IOCTL_ADD_MAP    DRM_IOWR(0x15, drm32_map_t) | 
|  | 216 |  | 
|  | 217 | static int drm32_addmap(unsigned int fd, unsigned int cmd, unsigned long arg) | 
|  | 218 | { | 
|  | 219 | drm32_map_t __user *uarg = (drm32_map_t __user *) arg; | 
|  | 220 | drm_map_t karg; | 
|  | 221 | mm_segment_t old_fs; | 
|  | 222 | u32 tmp; | 
|  | 223 | int ret; | 
|  | 224 |  | 
|  | 225 | ret  = get_user(karg.offset, &uarg->offset); | 
|  | 226 | ret |= get_user(karg.size, &uarg->size); | 
|  | 227 | ret |= get_user(karg.type, &uarg->type); | 
|  | 228 | ret |= get_user(karg.flags, &uarg->flags); | 
|  | 229 | ret |= get_user(tmp, &uarg->handle); | 
|  | 230 | ret |= get_user(karg.mtrr, &uarg->mtrr); | 
|  | 231 | if (ret) | 
|  | 232 | return -EFAULT; | 
|  | 233 |  | 
|  | 234 | karg.handle = (void *) (unsigned long) tmp; | 
|  | 235 |  | 
|  | 236 | old_fs = get_fs(); | 
|  | 237 | set_fs(KERNEL_DS); | 
|  | 238 | ret = sys_ioctl(fd, DRM_IOCTL_ADD_MAP, (unsigned long) &karg); | 
|  | 239 | set_fs(old_fs); | 
|  | 240 |  | 
|  | 241 | if (!ret) { | 
|  | 242 | ret  = put_user(karg.offset, &uarg->offset); | 
|  | 243 | ret |= put_user(karg.size, &uarg->size); | 
|  | 244 | ret |= put_user(karg.type, &uarg->type); | 
|  | 245 | ret |= put_user(karg.flags, &uarg->flags); | 
|  | 246 | tmp = (u32) (long)karg.handle; | 
|  | 247 | ret |= put_user(tmp, &uarg->handle); | 
|  | 248 | ret |= put_user(karg.mtrr, &uarg->mtrr); | 
|  | 249 | if (ret) | 
|  | 250 | ret = -EFAULT; | 
|  | 251 | } | 
|  | 252 |  | 
|  | 253 | return ret; | 
|  | 254 | } | 
|  | 255 |  | 
|  | 256 | typedef struct drm32_buf_info { | 
|  | 257 | int	       count;	/* Entries in list			     */ | 
|  | 258 | u32	       list;    /* (drm_buf_desc_t *) */ | 
|  | 259 | } drm32_buf_info_t; | 
|  | 260 | #define DRM32_IOCTL_INFO_BUFS  DRM_IOWR(0x18, drm32_buf_info_t) | 
|  | 261 |  | 
|  | 262 | static int drm32_info_bufs(unsigned int fd, unsigned int cmd, unsigned long arg) | 
|  | 263 | { | 
|  | 264 | drm32_buf_info_t __user *uarg = (drm32_buf_info_t __user *)arg; | 
|  | 265 | drm_buf_info_t __user *p = compat_alloc_user_space(sizeof(*p)); | 
|  | 266 | compat_uptr_t addr; | 
|  | 267 | int n; | 
|  | 268 | int ret; | 
|  | 269 |  | 
|  | 270 | if (get_user(n, &uarg->count) || put_user(n, &p->count) || | 
|  | 271 | get_user(addr, &uarg->list) || put_user(compat_ptr(addr), &p->list)) | 
|  | 272 | return -EFAULT; | 
|  | 273 |  | 
|  | 274 | ret = sys_ioctl(fd, DRM_IOCTL_INFO_BUFS, (unsigned long)p); | 
|  | 275 | if (ret) | 
|  | 276 | return ret; | 
|  | 277 |  | 
|  | 278 | if (get_user(n, &p->count) || put_user(n, &uarg->count)) | 
|  | 279 | return -EFAULT; | 
|  | 280 |  | 
|  | 281 | return 0; | 
|  | 282 | } | 
|  | 283 |  | 
|  | 284 | typedef struct drm32_buf_free { | 
|  | 285 | int	       count; | 
|  | 286 | u32	       list;	/* (int *) */ | 
|  | 287 | } drm32_buf_free_t; | 
|  | 288 | #define DRM32_IOCTL_FREE_BUFS  DRM_IOW( 0x1a, drm32_buf_free_t) | 
|  | 289 |  | 
|  | 290 | static int drm32_free_bufs(unsigned int fd, unsigned int cmd, unsigned long arg) | 
|  | 291 | { | 
|  | 292 | drm32_buf_free_t __user *uarg = (drm32_buf_free_t __user *)arg; | 
|  | 293 | drm_buf_free_t __user *p = compat_alloc_user_space(sizeof(*p)); | 
|  | 294 | compat_uptr_t addr; | 
|  | 295 | int n; | 
|  | 296 |  | 
|  | 297 | if (get_user(n, &uarg->count) || put_user(n, &p->count) || | 
|  | 298 | get_user(addr, &uarg->list) || put_user(compat_ptr(addr), &p->list)) | 
|  | 299 | return -EFAULT; | 
|  | 300 |  | 
|  | 301 | return sys_ioctl(fd, DRM_IOCTL_FREE_BUFS, (unsigned long)p); | 
|  | 302 | } | 
|  | 303 |  | 
|  | 304 | typedef struct drm32_buf_pub { | 
|  | 305 | int		  idx;	       /* Index into master buflist	     */ | 
|  | 306 | int		  total;       /* Buffer size			     */ | 
|  | 307 | int		  used;	       /* Amount of buffer in use (for DMA)  */ | 
|  | 308 | u32		  address;     /* Address of buffer (void *)	     */ | 
|  | 309 | } drm32_buf_pub_t; | 
|  | 310 |  | 
|  | 311 | typedef struct drm32_buf_map { | 
|  | 312 | int	      count;	/* Length of buflist			    */ | 
|  | 313 | u32	      virtual;	/* Mmaped area in user-virtual (void *)	    */ | 
|  | 314 | u32 	      list;	/* Buffer information (drm_buf_pub_t *)	    */ | 
|  | 315 | } drm32_buf_map_t; | 
|  | 316 | #define DRM32_IOCTL_MAP_BUFS   DRM_IOWR(0x19, drm32_buf_map_t) | 
|  | 317 |  | 
|  | 318 | static int drm32_map_bufs(unsigned int fd, unsigned int cmd, unsigned long arg) | 
|  | 319 | { | 
|  | 320 | drm32_buf_map_t __user *uarg = (drm32_buf_map_t __user *)arg; | 
|  | 321 | drm32_buf_pub_t __user *ulist; | 
|  | 322 | drm_buf_map_t __user *arg64; | 
|  | 323 | drm_buf_pub_t __user *list; | 
|  | 324 | int orig_count, ret, i; | 
|  | 325 | int n; | 
|  | 326 | compat_uptr_t addr; | 
|  | 327 |  | 
|  | 328 | if (get_user(orig_count, &uarg->count)) | 
|  | 329 | return -EFAULT; | 
|  | 330 |  | 
|  | 331 | arg64 = compat_alloc_user_space(sizeof(drm_buf_map_t) + | 
|  | 332 | (size_t)orig_count * sizeof(drm_buf_pub_t)); | 
|  | 333 | list = (void __user *)(arg64 + 1); | 
|  | 334 |  | 
|  | 335 | if (put_user(orig_count, &arg64->count) || | 
|  | 336 | put_user(list, &arg64->list) || | 
|  | 337 | get_user(addr, &uarg->virtual) || | 
|  | 338 | put_user(compat_ptr(addr), &arg64->virtual) || | 
|  | 339 | get_user(addr, &uarg->list)) | 
|  | 340 | return -EFAULT; | 
|  | 341 |  | 
|  | 342 | ulist = compat_ptr(addr); | 
|  | 343 |  | 
|  | 344 | for (i = 0; i < orig_count; i++) { | 
|  | 345 | if (get_user(n, &ulist[i].idx) || | 
|  | 346 | put_user(n, &list[i].idx) || | 
|  | 347 | get_user(n, &ulist[i].total) || | 
|  | 348 | put_user(n, &list[i].total) || | 
|  | 349 | get_user(n, &ulist[i].used) || | 
|  | 350 | put_user(n, &list[i].used) || | 
|  | 351 | get_user(addr, &ulist[i].address) || | 
|  | 352 | put_user(compat_ptr(addr), &list[i].address)) | 
|  | 353 | return -EFAULT; | 
|  | 354 | } | 
|  | 355 |  | 
|  | 356 | ret = sys_ioctl(fd, DRM_IOCTL_MAP_BUFS, (unsigned long) arg64); | 
|  | 357 | if (ret) | 
|  | 358 | return ret; | 
|  | 359 |  | 
|  | 360 | for (i = 0; i < orig_count; i++) { | 
|  | 361 | void __user *p; | 
|  | 362 | if (get_user(n, &list[i].idx) || | 
|  | 363 | put_user(n, &ulist[i].idx) || | 
|  | 364 | get_user(n, &list[i].total) || | 
|  | 365 | put_user(n, &ulist[i].total) || | 
|  | 366 | get_user(n, &list[i].used) || | 
|  | 367 | put_user(n, &ulist[i].used) || | 
|  | 368 | get_user(p, &list[i].address) || | 
|  | 369 | put_user((unsigned long)p, &ulist[i].address)) | 
|  | 370 | return -EFAULT; | 
|  | 371 | } | 
|  | 372 |  | 
|  | 373 | if (get_user(n, &arg64->count) || put_user(n, &uarg->count)) | 
|  | 374 | return -EFAULT; | 
|  | 375 |  | 
|  | 376 | return 0; | 
|  | 377 | } | 
|  | 378 |  | 
|  | 379 | typedef struct drm32_dma { | 
|  | 380 | /* Indices here refer to the offset into | 
|  | 381 | buflist in drm_buf_get_t.  */ | 
|  | 382 | int		context;	  /* Context handle		    */ | 
|  | 383 | int		send_count;	  /* Number of buffers to send	    */ | 
|  | 384 | u32		send_indices;	  /* List of handles to buffers (int *) */ | 
|  | 385 | u32		send_sizes;	  /* Lengths of data to send (int *) */ | 
|  | 386 | drm_dma_flags_t flags;		  /* Flags			    */ | 
|  | 387 | int		request_count;	  /* Number of buffers requested    */ | 
|  | 388 | int		request_size;	  /* Desired size for buffers	    */ | 
|  | 389 | u32		request_indices;  /* Buffer information (int *)	    */ | 
|  | 390 | u32		request_sizes;    /* (int *) */ | 
|  | 391 | int		granted_count;	  /* Number of buffers granted	    */ | 
|  | 392 | } drm32_dma_t; | 
|  | 393 | #define DRM32_IOCTL_DMA	     DRM_IOWR(0x29, drm32_dma_t) | 
|  | 394 |  | 
|  | 395 | /* RED PEN	The DRM layer blindly dereferences the send/request | 
|  | 396 | * 		index/size arrays even though they are userland | 
|  | 397 | * 		pointers.  -DaveM | 
|  | 398 | */ | 
|  | 399 | static int drm32_dma(unsigned int fd, unsigned int cmd, unsigned long arg) | 
|  | 400 | { | 
|  | 401 | drm32_dma_t __user *uarg = (drm32_dma_t __user *) arg; | 
|  | 402 | drm_dma_t __user *p = compat_alloc_user_space(sizeof(*p)); | 
|  | 403 | compat_uptr_t addr; | 
|  | 404 | int ret; | 
|  | 405 |  | 
|  | 406 | if (copy_in_user(p, uarg, 2 * sizeof(int)) || | 
|  | 407 | get_user(addr, &uarg->send_indices) || | 
|  | 408 | put_user(compat_ptr(addr), &p->send_indices) || | 
|  | 409 | get_user(addr, &uarg->send_sizes) || | 
|  | 410 | put_user(compat_ptr(addr), &p->send_sizes) || | 
|  | 411 | copy_in_user(&p->flags, &uarg->flags, sizeof(drm_dma_flags_t)) || | 
|  | 412 | copy_in_user(&p->request_count, &uarg->request_count, sizeof(int))|| | 
|  | 413 | copy_in_user(&p->request_size, &uarg->request_size, sizeof(int)) || | 
|  | 414 | get_user(addr, &uarg->request_indices) || | 
|  | 415 | put_user(compat_ptr(addr), &p->request_indices) || | 
|  | 416 | get_user(addr, &uarg->request_sizes) || | 
|  | 417 | put_user(compat_ptr(addr), &p->request_sizes) || | 
|  | 418 | copy_in_user(&p->granted_count, &uarg->granted_count, sizeof(int))) | 
|  | 419 | return -EFAULT; | 
|  | 420 |  | 
|  | 421 | ret = sys_ioctl(fd, DRM_IOCTL_DMA, (unsigned long)p); | 
|  | 422 | if (ret) | 
|  | 423 | return ret; | 
|  | 424 |  | 
|  | 425 | if (copy_in_user(uarg, p, 2 * sizeof(int)) || | 
|  | 426 | copy_in_user(&uarg->flags, &p->flags, sizeof(drm_dma_flags_t)) || | 
|  | 427 | copy_in_user(&uarg->request_count, &p->request_count, sizeof(int))|| | 
|  | 428 | copy_in_user(&uarg->request_size, &p->request_size, sizeof(int)) || | 
|  | 429 | copy_in_user(&uarg->granted_count, &p->granted_count, sizeof(int))) | 
|  | 430 | return -EFAULT; | 
|  | 431 |  | 
|  | 432 | return 0; | 
|  | 433 | } | 
|  | 434 |  | 
|  | 435 | typedef struct drm32_ctx_res { | 
|  | 436 | int		count; | 
|  | 437 | u32		contexts; /* (drm_ctx_t *) */ | 
|  | 438 | } drm32_ctx_res_t; | 
|  | 439 | #define DRM32_IOCTL_RES_CTX    DRM_IOWR(0x26, drm32_ctx_res_t) | 
|  | 440 |  | 
|  | 441 | static int drm32_res_ctx(unsigned int fd, unsigned int cmd, unsigned long arg) | 
|  | 442 | { | 
|  | 443 | drm32_ctx_res_t __user *uarg = (drm32_ctx_res_t __user *) arg; | 
|  | 444 | drm_ctx_res_t __user *p = compat_alloc_user_space(sizeof(*p)); | 
|  | 445 | compat_uptr_t addr; | 
|  | 446 | int ret; | 
|  | 447 |  | 
|  | 448 | if (copy_in_user(p, uarg, sizeof(int)) || | 
|  | 449 | get_user(addr, &uarg->contexts) || | 
|  | 450 | put_user(compat_ptr(addr), &p->contexts)) | 
|  | 451 | return -EFAULT; | 
|  | 452 |  | 
|  | 453 | ret = sys_ioctl(fd, DRM_IOCTL_RES_CTX, (unsigned long)p); | 
|  | 454 | if (ret) | 
|  | 455 | return ret; | 
|  | 456 |  | 
|  | 457 | if (copy_in_user(uarg, p, sizeof(int))) | 
|  | 458 | return -EFAULT; | 
|  | 459 |  | 
|  | 460 | return 0; | 
|  | 461 | } | 
|  | 462 |  | 
|  | 463 | #endif | 
|  | 464 |  | 
|  | 465 | typedef int (* ioctl32_handler_t)(unsigned int, unsigned int, unsigned long, struct file *); | 
|  | 466 |  | 
|  | 467 | #define COMPATIBLE_IOCTL(cmd)		HANDLE_IOCTL((cmd),sys_ioctl) | 
|  | 468 | #define HANDLE_IOCTL(cmd,handler)	{ (cmd), (ioctl32_handler_t)(handler), NULL }, | 
|  | 469 | #define IOCTL_TABLE_START \ | 
|  | 470 | struct ioctl_trans ioctl_start[] = { | 
|  | 471 | #define IOCTL_TABLE_END \ | 
|  | 472 | }; | 
|  | 473 |  | 
|  | 474 | IOCTL_TABLE_START | 
|  | 475 | #include <linux/compat_ioctl.h> | 
|  | 476 | #define DECLARES | 
|  | 477 | #include "compat_ioctl.c" | 
|  | 478 | COMPATIBLE_IOCTL(TIOCSTART) | 
|  | 479 | COMPATIBLE_IOCTL(TIOCSTOP) | 
|  | 480 | COMPATIBLE_IOCTL(TIOCSLTC) | 
|  | 481 | COMPATIBLE_IOCTL(FBIOGTYPE) | 
|  | 482 | COMPATIBLE_IOCTL(FBIOSATTR) | 
|  | 483 | COMPATIBLE_IOCTL(FBIOGATTR) | 
|  | 484 | COMPATIBLE_IOCTL(FBIOSVIDEO) | 
|  | 485 | COMPATIBLE_IOCTL(FBIOGVIDEO) | 
|  | 486 | COMPATIBLE_IOCTL(FBIOGCURSOR32)  /* This is not implemented yet. Later it should be converted... */ | 
|  | 487 | COMPATIBLE_IOCTL(FBIOSCURPOS) | 
|  | 488 | COMPATIBLE_IOCTL(FBIOGCURPOS) | 
|  | 489 | COMPATIBLE_IOCTL(FBIOGCURMAX) | 
|  | 490 | /* Little k */ | 
|  | 491 | COMPATIBLE_IOCTL(KIOCTYPE) | 
|  | 492 | COMPATIBLE_IOCTL(KIOCLAYOUT) | 
|  | 493 | COMPATIBLE_IOCTL(KIOCGTRANS) | 
|  | 494 | COMPATIBLE_IOCTL(KIOCTRANS) | 
|  | 495 | COMPATIBLE_IOCTL(KIOCCMD) | 
|  | 496 | COMPATIBLE_IOCTL(KIOCSDIRECT) | 
|  | 497 | COMPATIBLE_IOCTL(KIOCSLED) | 
|  | 498 | COMPATIBLE_IOCTL(KIOCGLED) | 
|  | 499 | COMPATIBLE_IOCTL(KIOCSRATE) | 
|  | 500 | COMPATIBLE_IOCTL(KIOCGRATE) | 
|  | 501 | COMPATIBLE_IOCTL(VUIDSFORMAT) | 
|  | 502 | COMPATIBLE_IOCTL(VUIDGFORMAT) | 
|  | 503 | /* Little v, the video4linux ioctls */ | 
|  | 504 | COMPATIBLE_IOCTL(_IOR('p', 20, int[7])) /* RTCGET */ | 
|  | 505 | COMPATIBLE_IOCTL(_IOW('p', 21, int[7])) /* RTCSET */ | 
|  | 506 | COMPATIBLE_IOCTL(ENVCTRL_RD_WARNING_TEMPERATURE) | 
|  | 507 | COMPATIBLE_IOCTL(ENVCTRL_RD_SHUTDOWN_TEMPERATURE) | 
|  | 508 | COMPATIBLE_IOCTL(ENVCTRL_RD_CPU_TEMPERATURE) | 
|  | 509 | COMPATIBLE_IOCTL(ENVCTRL_RD_FAN_STATUS) | 
|  | 510 | COMPATIBLE_IOCTL(ENVCTRL_RD_VOLTAGE_STATUS) | 
|  | 511 | COMPATIBLE_IOCTL(ENVCTRL_RD_SCSI_TEMPERATURE) | 
|  | 512 | COMPATIBLE_IOCTL(ENVCTRL_RD_ETHERNET_TEMPERATURE) | 
|  | 513 | COMPATIBLE_IOCTL(ENVCTRL_RD_MTHRBD_TEMPERATURE) | 
|  | 514 | COMPATIBLE_IOCTL(ENVCTRL_RD_CPU_VOLTAGE) | 
|  | 515 | COMPATIBLE_IOCTL(ENVCTRL_RD_GLOBALADDRESS) | 
|  | 516 | /* COMPATIBLE_IOCTL(D7SIOCRD) same value as ENVCTRL_RD_VOLTAGE_STATUS */ | 
|  | 517 | COMPATIBLE_IOCTL(D7SIOCWR) | 
|  | 518 | COMPATIBLE_IOCTL(D7SIOCTM) | 
|  | 519 | /* OPENPROMIO, SunOS/Solaris only, the NetBSD one's have | 
|  | 520 | * embedded pointers in the arg which we'd need to clean up... | 
|  | 521 | */ | 
|  | 522 | COMPATIBLE_IOCTL(OPROMGETOPT) | 
|  | 523 | COMPATIBLE_IOCTL(OPROMSETOPT) | 
|  | 524 | COMPATIBLE_IOCTL(OPROMNXTOPT) | 
|  | 525 | COMPATIBLE_IOCTL(OPROMSETOPT2) | 
|  | 526 | COMPATIBLE_IOCTL(OPROMNEXT) | 
|  | 527 | COMPATIBLE_IOCTL(OPROMCHILD) | 
|  | 528 | COMPATIBLE_IOCTL(OPROMGETPROP) | 
|  | 529 | COMPATIBLE_IOCTL(OPROMNXTPROP) | 
|  | 530 | COMPATIBLE_IOCTL(OPROMU2P) | 
|  | 531 | COMPATIBLE_IOCTL(OPROMGETCONS) | 
|  | 532 | COMPATIBLE_IOCTL(OPROMGETFBNAME) | 
|  | 533 | COMPATIBLE_IOCTL(OPROMGETBOOTARGS) | 
|  | 534 | COMPATIBLE_IOCTL(OPROMSETCUR) | 
|  | 535 | COMPATIBLE_IOCTL(OPROMPCI2NODE) | 
|  | 536 | COMPATIBLE_IOCTL(OPROMPATH2NODE) | 
|  | 537 | /* Big L */ | 
|  | 538 | COMPATIBLE_IOCTL(LOOP_SET_STATUS64) | 
|  | 539 | COMPATIBLE_IOCTL(LOOP_GET_STATUS64) | 
|  | 540 | /* Big A */ | 
|  | 541 | COMPATIBLE_IOCTL(AUDIO_GETINFO) | 
|  | 542 | COMPATIBLE_IOCTL(AUDIO_SETINFO) | 
|  | 543 | COMPATIBLE_IOCTL(AUDIO_DRAIN) | 
|  | 544 | COMPATIBLE_IOCTL(AUDIO_GETDEV) | 
|  | 545 | COMPATIBLE_IOCTL(AUDIO_GETDEV_SUNOS) | 
|  | 546 | COMPATIBLE_IOCTL(AUDIO_FLUSH) | 
|  | 547 | COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE_MULTI) | 
|  | 548 | #if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE) | 
|  | 549 | COMPATIBLE_IOCTL(DRM_IOCTL_GET_MAGIC) | 
|  | 550 | COMPATIBLE_IOCTL(DRM_IOCTL_IRQ_BUSID) | 
|  | 551 | COMPATIBLE_IOCTL(DRM_IOCTL_AUTH_MAGIC) | 
|  | 552 | COMPATIBLE_IOCTL(DRM_IOCTL_BLOCK) | 
|  | 553 | COMPATIBLE_IOCTL(DRM_IOCTL_UNBLOCK) | 
|  | 554 | COMPATIBLE_IOCTL(DRM_IOCTL_CONTROL) | 
|  | 555 | COMPATIBLE_IOCTL(DRM_IOCTL_ADD_BUFS) | 
|  | 556 | COMPATIBLE_IOCTL(DRM_IOCTL_MARK_BUFS) | 
|  | 557 | COMPATIBLE_IOCTL(DRM_IOCTL_ADD_CTX) | 
|  | 558 | COMPATIBLE_IOCTL(DRM_IOCTL_RM_CTX) | 
|  | 559 | COMPATIBLE_IOCTL(DRM_IOCTL_MOD_CTX) | 
|  | 560 | COMPATIBLE_IOCTL(DRM_IOCTL_GET_CTX) | 
|  | 561 | COMPATIBLE_IOCTL(DRM_IOCTL_SWITCH_CTX) | 
|  | 562 | COMPATIBLE_IOCTL(DRM_IOCTL_NEW_CTX) | 
|  | 563 | COMPATIBLE_IOCTL(DRM_IOCTL_ADD_DRAW) | 
|  | 564 | COMPATIBLE_IOCTL(DRM_IOCTL_RM_DRAW) | 
|  | 565 | COMPATIBLE_IOCTL(DRM_IOCTL_LOCK) | 
|  | 566 | COMPATIBLE_IOCTL(DRM_IOCTL_UNLOCK) | 
|  | 567 | COMPATIBLE_IOCTL(DRM_IOCTL_FINISH) | 
|  | 568 | #endif /* DRM */ | 
|  | 569 | COMPATIBLE_IOCTL(WIOCSTART) | 
|  | 570 | COMPATIBLE_IOCTL(WIOCSTOP) | 
|  | 571 | COMPATIBLE_IOCTL(WIOCGSTAT) | 
|  | 572 | /* And these ioctls need translation */ | 
|  | 573 | /* Note SIOCRTMSG is no longer, so this is safe and * the user would have seen just an -EINVAL anyways. */ | 
|  | 574 | HANDLE_IOCTL(FBIOPUTCMAP32, fbiogetputcmap) | 
|  | 575 | HANDLE_IOCTL(FBIOGETCMAP32, fbiogetputcmap) | 
|  | 576 | HANDLE_IOCTL(FBIOSCURSOR32, fbiogscursor) | 
|  | 577 | #if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE) | 
|  | 578 | HANDLE_IOCTL(DRM32_IOCTL_VERSION, drm32_version) | 
|  | 579 | HANDLE_IOCTL(DRM32_IOCTL_GET_UNIQUE, drm32_getsetunique) | 
|  | 580 | HANDLE_IOCTL(DRM32_IOCTL_SET_UNIQUE, drm32_getsetunique) | 
|  | 581 | HANDLE_IOCTL(DRM32_IOCTL_ADD_MAP, drm32_addmap) | 
|  | 582 | HANDLE_IOCTL(DRM32_IOCTL_INFO_BUFS, drm32_info_bufs) | 
|  | 583 | HANDLE_IOCTL(DRM32_IOCTL_FREE_BUFS, drm32_free_bufs) | 
|  | 584 | HANDLE_IOCTL(DRM32_IOCTL_MAP_BUFS, drm32_map_bufs) | 
|  | 585 | HANDLE_IOCTL(DRM32_IOCTL_DMA, drm32_dma) | 
|  | 586 | HANDLE_IOCTL(DRM32_IOCTL_RES_CTX, drm32_res_ctx) | 
|  | 587 | #endif /* DRM */ | 
|  | 588 | #if 0 | 
|  | 589 | HANDLE_IOCTL(RTC32_IRQP_READ, do_rtc_ioctl) | 
|  | 590 | HANDLE_IOCTL(RTC32_IRQP_SET, do_rtc_ioctl) | 
|  | 591 | HANDLE_IOCTL(RTC32_EPOCH_READ, do_rtc_ioctl) | 
|  | 592 | HANDLE_IOCTL(RTC32_EPOCH_SET, do_rtc_ioctl) | 
|  | 593 | #endif | 
|  | 594 | /* take care of sizeof(sizeof()) breakage */ | 
|  | 595 | IOCTL_TABLE_END | 
|  | 596 |  | 
|  | 597 | int ioctl_table_size = ARRAY_SIZE(ioctl_start); |