Merge branch 'x86-cleanups-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[pandora-kernel.git] / drivers / gpu / 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/ratelimit.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_UPDATE_DRAW32         DRM_IOW( 0x3f, drm_update_draw32_t)
69
70 #define DRM_IOCTL_WAIT_VBLANK32         DRM_IOWR(0x3a, drm_wait_vblank32_t)
71
72 typedef struct drm_version_32 {
73         int version_major;        /**< Major version */
74         int version_minor;        /**< Minor version */
75         int version_patchlevel;    /**< Patch level */
76         u32 name_len;             /**< Length of name buffer */
77         u32 name;                 /**< Name of driver */
78         u32 date_len;             /**< Length of date buffer */
79         u32 date;                 /**< User-space buffer to hold date */
80         u32 desc_len;             /**< Length of desc buffer */
81         u32 desc;                 /**< User-space buffer to hold desc */
82 } drm_version32_t;
83
84 static int compat_drm_version(struct file *file, unsigned int cmd,
85                               unsigned long arg)
86 {
87         drm_version32_t v32;
88         struct drm_version __user *version;
89         int err;
90
91         if (copy_from_user(&v32, (void __user *)arg, sizeof(v32)))
92                 return -EFAULT;
93
94         version = compat_alloc_user_space(sizeof(*version));
95         if (!access_ok(VERIFY_WRITE, version, sizeof(*version)))
96                 return -EFAULT;
97         if (__put_user(v32.name_len, &version->name_len)
98             || __put_user((void __user *)(unsigned long)v32.name,
99                           &version->name)
100             || __put_user(v32.date_len, &version->date_len)
101             || __put_user((void __user *)(unsigned long)v32.date,
102                           &version->date)
103             || __put_user(v32.desc_len, &version->desc_len)
104             || __put_user((void __user *)(unsigned long)v32.desc,
105                           &version->desc))
106                 return -EFAULT;
107
108         err = drm_ioctl(file,
109                         DRM_IOCTL_VERSION, (unsigned long)version);
110         if (err)
111                 return err;
112
113         if (__get_user(v32.version_major, &version->version_major)
114             || __get_user(v32.version_minor, &version->version_minor)
115             || __get_user(v32.version_patchlevel, &version->version_patchlevel)
116             || __get_user(v32.name_len, &version->name_len)
117             || __get_user(v32.date_len, &version->date_len)
118             || __get_user(v32.desc_len, &version->desc_len))
119                 return -EFAULT;
120
121         if (copy_to_user((void __user *)arg, &v32, sizeof(v32)))
122                 return -EFAULT;
123         return 0;
124 }
125
126 typedef struct drm_unique32 {
127         u32 unique_len; /**< Length of unique */
128         u32 unique;     /**< Unique name for driver instantiation */
129 } drm_unique32_t;
130
131 static int compat_drm_getunique(struct file *file, unsigned int cmd,
132                                 unsigned long arg)
133 {
134         drm_unique32_t uq32;
135         struct drm_unique __user *u;
136         int err;
137
138         if (copy_from_user(&uq32, (void __user *)arg, sizeof(uq32)))
139                 return -EFAULT;
140
141         u = compat_alloc_user_space(sizeof(*u));
142         if (!access_ok(VERIFY_WRITE, u, sizeof(*u)))
143                 return -EFAULT;
144         if (__put_user(uq32.unique_len, &u->unique_len)
145             || __put_user((void __user *)(unsigned long)uq32.unique,
146                           &u->unique))
147                 return -EFAULT;
148
149         err = drm_ioctl(file, DRM_IOCTL_GET_UNIQUE, (unsigned long)u);
150         if (err)
151                 return err;
152
153         if (__get_user(uq32.unique_len, &u->unique_len))
154                 return -EFAULT;
155         if (copy_to_user((void __user *)arg, &uq32, sizeof(uq32)))
156                 return -EFAULT;
157         return 0;
158 }
159
160 static int compat_drm_setunique(struct file *file, unsigned int cmd,
161                                 unsigned long arg)
162 {
163         drm_unique32_t uq32;
164         struct drm_unique __user *u;
165
166         if (copy_from_user(&uq32, (void __user *)arg, sizeof(uq32)))
167                 return -EFAULT;
168
169         u = compat_alloc_user_space(sizeof(*u));
170         if (!access_ok(VERIFY_WRITE, u, sizeof(*u)))
171                 return -EFAULT;
172         if (__put_user(uq32.unique_len, &u->unique_len)
173             || __put_user((void __user *)(unsigned long)uq32.unique,
174                           &u->unique))
175                 return -EFAULT;
176
177         return drm_ioctl(file, 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         enum drm_map_type type; /**< Type of memory to map */
184         enum drm_map_flags 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         struct drm_map __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, DRM_IOCTL_GET_MAP, (unsigned long)map);
208         if (err)
209                 return err;
210
211         if (__get_user(m32.offset, &map->offset)
212             || __get_user(m32.size, &map->size)
213             || __get_user(m32.type, &map->type)
214             || __get_user(m32.flags, &map->flags)
215             || __get_user(handle, &map->handle)
216             || __get_user(m32.mtrr, &map->mtrr))
217                 return -EFAULT;
218
219         m32.handle = (unsigned long)handle;
220         if (copy_to_user(argp, &m32, sizeof(m32)))
221                 return -EFAULT;
222         return 0;
223
224 }
225
226 static int compat_drm_addmap(struct file *file, unsigned int cmd,
227                              unsigned long arg)
228 {
229         drm_map32_t __user *argp = (void __user *)arg;
230         drm_map32_t m32;
231         struct drm_map __user *map;
232         int err;
233         void *handle;
234
235         if (copy_from_user(&m32, argp, sizeof(m32)))
236                 return -EFAULT;
237
238         map = compat_alloc_user_space(sizeof(*map));
239         if (!access_ok(VERIFY_WRITE, map, sizeof(*map)))
240                 return -EFAULT;
241         if (__put_user(m32.offset, &map->offset)
242             || __put_user(m32.size, &map->size)
243             || __put_user(m32.type, &map->type)
244             || __put_user(m32.flags, &map->flags))
245                 return -EFAULT;
246
247         err = drm_ioctl(file, DRM_IOCTL_ADD_MAP, (unsigned long)map);
248         if (err)
249                 return err;
250
251         if (__get_user(m32.offset, &map->offset)
252             || __get_user(m32.mtrr, &map->mtrr)
253             || __get_user(handle, &map->handle))
254                 return -EFAULT;
255
256         m32.handle = (unsigned long)handle;
257         if (m32.handle != (unsigned long)handle)
258                 printk_ratelimited(KERN_ERR "compat_drm_addmap truncated handle"
259                                    " %p for type %d offset %x\n",
260                                    handle, m32.type, m32.offset);
261
262         if (copy_to_user(argp, &m32, sizeof(m32)))
263                 return -EFAULT;
264
265         return 0;
266 }
267
268 static int compat_drm_rmmap(struct file *file, unsigned int cmd,
269                             unsigned long arg)
270 {
271         drm_map32_t __user *argp = (void __user *)arg;
272         struct drm_map __user *map;
273         u32 handle;
274
275         if (get_user(handle, &argp->handle))
276                 return -EFAULT;
277
278         map = compat_alloc_user_space(sizeof(*map));
279         if (!access_ok(VERIFY_WRITE, map, sizeof(*map)))
280                 return -EFAULT;
281         if (__put_user((void *)(unsigned long)handle, &map->handle))
282                 return -EFAULT;
283
284         return drm_ioctl(file, DRM_IOCTL_RM_MAP, (unsigned long)map);
285 }
286
287 typedef struct drm_client32 {
288         int idx;        /**< Which client desired? */
289         int auth;       /**< Is client authenticated? */
290         u32 pid;        /**< Process ID */
291         u32 uid;        /**< User ID */
292         u32 magic;      /**< Magic */
293         u32 iocs;       /**< Ioctl count */
294 } drm_client32_t;
295
296 static int compat_drm_getclient(struct file *file, unsigned int cmd,
297                                 unsigned long arg)
298 {
299         drm_client32_t c32;
300         drm_client32_t __user *argp = (void __user *)arg;
301         struct drm_client __user *client;
302         int idx, err;
303
304         if (get_user(idx, &argp->idx))
305                 return -EFAULT;
306
307         client = compat_alloc_user_space(sizeof(*client));
308         if (!access_ok(VERIFY_WRITE, client, sizeof(*client)))
309                 return -EFAULT;
310         if (__put_user(idx, &client->idx))
311                 return -EFAULT;
312
313         err = drm_ioctl(file, DRM_IOCTL_GET_CLIENT, (unsigned long)client);
314         if (err)
315                 return err;
316
317         if (__get_user(c32.auth, &client->auth)
318             || __get_user(c32.pid, &client->pid)
319             || __get_user(c32.uid, &client->uid)
320             || __get_user(c32.magic, &client->magic)
321             || __get_user(c32.iocs, &client->iocs))
322                 return -EFAULT;
323
324         if (copy_to_user(argp, &c32, sizeof(c32)))
325                 return -EFAULT;
326         return 0;
327 }
328
329 typedef struct drm_stats32 {
330         u32 count;
331         struct {
332                 u32 value;
333                 enum drm_stat_type type;
334         } data[15];
335 } drm_stats32_t;
336
337 static int compat_drm_getstats(struct file *file, unsigned int cmd,
338                                unsigned long arg)
339 {
340         drm_stats32_t s32;
341         drm_stats32_t __user *argp = (void __user *)arg;
342         struct drm_stats __user *stats;
343         int i, err;
344
345         stats = compat_alloc_user_space(sizeof(*stats));
346         if (!access_ok(VERIFY_WRITE, stats, sizeof(*stats)))
347                 return -EFAULT;
348
349         err = drm_ioctl(file, DRM_IOCTL_GET_STATS, (unsigned long)stats);
350         if (err)
351                 return err;
352
353         if (__get_user(s32.count, &stats->count))
354                 return -EFAULT;
355         for (i = 0; i < 15; ++i)
356                 if (__get_user(s32.data[i].value, &stats->data[i].value)
357                     || __get_user(s32.data[i].type, &stats->data[i].type))
358                         return -EFAULT;
359
360         if (copy_to_user(argp, &s32, sizeof(s32)))
361                 return -EFAULT;
362         return 0;
363 }
364
365 typedef struct drm_buf_desc32 {
366         int count;               /**< Number of buffers of this size */
367         int size;                /**< Size in bytes */
368         int low_mark;            /**< Low water mark */
369         int high_mark;           /**< High water mark */
370         int flags;
371         u32 agp_start;           /**< Start address in the AGP aperture */
372 } drm_buf_desc32_t;
373
374 static int compat_drm_addbufs(struct file *file, unsigned int cmd,
375                               unsigned long arg)
376 {
377         drm_buf_desc32_t __user *argp = (void __user *)arg;
378         struct drm_buf_desc __user *buf;
379         int err;
380         unsigned long agp_start;
381
382         buf = compat_alloc_user_space(sizeof(*buf));
383         if (!access_ok(VERIFY_WRITE, buf, sizeof(*buf))
384             || !access_ok(VERIFY_WRITE, argp, sizeof(*argp)))
385                 return -EFAULT;
386
387         if (__copy_in_user(buf, argp, offsetof(drm_buf_desc32_t, agp_start))
388             || __get_user(agp_start, &argp->agp_start)
389             || __put_user(agp_start, &buf->agp_start))
390                 return -EFAULT;
391
392         err = drm_ioctl(file, DRM_IOCTL_ADD_BUFS, (unsigned long)buf);
393         if (err)
394                 return err;
395
396         if (__copy_in_user(argp, buf, offsetof(drm_buf_desc32_t, agp_start))
397             || __get_user(agp_start, &buf->agp_start)
398             || __put_user(agp_start, &argp->agp_start))
399                 return -EFAULT;
400
401         return 0;
402 }
403
404 static int compat_drm_markbufs(struct file *file, unsigned int cmd,
405                                unsigned long arg)
406 {
407         drm_buf_desc32_t b32;
408         drm_buf_desc32_t __user *argp = (void __user *)arg;
409         struct drm_buf_desc __user *buf;
410
411         if (copy_from_user(&b32, argp, sizeof(b32)))
412                 return -EFAULT;
413
414         buf = compat_alloc_user_space(sizeof(*buf));
415         if (!access_ok(VERIFY_WRITE, buf, sizeof(*buf)))
416                 return -EFAULT;
417
418         if (__put_user(b32.size, &buf->size)
419             || __put_user(b32.low_mark, &buf->low_mark)
420             || __put_user(b32.high_mark, &buf->high_mark))
421                 return -EFAULT;
422
423         return drm_ioctl(file, DRM_IOCTL_MARK_BUFS, (unsigned long)buf);
424 }
425
426 typedef struct drm_buf_info32 {
427         int count;              /**< Entries in list */
428         u32 list;
429 } drm_buf_info32_t;
430
431 static int compat_drm_infobufs(struct file *file, unsigned int cmd,
432                                unsigned long arg)
433 {
434         drm_buf_info32_t req32;
435         drm_buf_info32_t __user *argp = (void __user *)arg;
436         drm_buf_desc32_t __user *to;
437         struct drm_buf_info __user *request;
438         struct drm_buf_desc __user *list;
439         size_t nbytes;
440         int i, err;
441         int count, actual;
442
443         if (copy_from_user(&req32, argp, sizeof(req32)))
444                 return -EFAULT;
445
446         count = req32.count;
447         to = (drm_buf_desc32_t __user *) (unsigned long)req32.list;
448         if (count < 0)
449                 count = 0;
450         if (count > 0
451             && !access_ok(VERIFY_WRITE, to, count * sizeof(drm_buf_desc32_t)))
452                 return -EFAULT;
453
454         nbytes = sizeof(*request) + count * sizeof(struct drm_buf_desc);
455         request = compat_alloc_user_space(nbytes);
456         if (!access_ok(VERIFY_WRITE, request, nbytes))
457                 return -EFAULT;
458         list = (struct drm_buf_desc *) (request + 1);
459
460         if (__put_user(count, &request->count)
461             || __put_user(list, &request->list))
462                 return -EFAULT;
463
464         err = drm_ioctl(file, DRM_IOCTL_INFO_BUFS, (unsigned long)request);
465         if (err)
466                 return err;
467
468         if (__get_user(actual, &request->count))
469                 return -EFAULT;
470         if (count >= actual)
471                 for (i = 0; i < actual; ++i)
472                         if (__copy_in_user(&to[i], &list[i],
473                                            offsetof(struct drm_buf_desc, flags)))
474                                 return -EFAULT;
475
476         if (__put_user(actual, &argp->count))
477                 return -EFAULT;
478
479         return 0;
480 }
481
482 typedef struct drm_buf_pub32 {
483         int idx;                /**< Index into the master buffer list */
484         int total;              /**< Buffer size */
485         int used;               /**< Amount of buffer in use (for DMA) */
486         u32 address;            /**< Address of buffer */
487 } drm_buf_pub32_t;
488
489 typedef struct drm_buf_map32 {
490         int count;              /**< Length of the buffer list */
491         u32 virtual;            /**< Mmap'd area in user-virtual */
492         u32 list;               /**< Buffer information */
493 } drm_buf_map32_t;
494
495 static int compat_drm_mapbufs(struct file *file, unsigned int cmd,
496                               unsigned long arg)
497 {
498         drm_buf_map32_t __user *argp = (void __user *)arg;
499         drm_buf_map32_t req32;
500         drm_buf_pub32_t __user *list32;
501         struct drm_buf_map __user *request;
502         struct drm_buf_pub __user *list;
503         int i, err;
504         int count, actual;
505         size_t nbytes;
506         void __user *addr;
507
508         if (copy_from_user(&req32, argp, sizeof(req32)))
509                 return -EFAULT;
510         count = req32.count;
511         list32 = (void __user *)(unsigned long)req32.list;
512
513         if (count < 0)
514                 return -EINVAL;
515         nbytes = sizeof(*request) + count * sizeof(struct drm_buf_pub);
516         request = compat_alloc_user_space(nbytes);
517         if (!access_ok(VERIFY_WRITE, request, nbytes))
518                 return -EFAULT;
519         list = (struct drm_buf_pub *) (request + 1);
520
521         if (__put_user(count, &request->count)
522             || __put_user(list, &request->list))
523                 return -EFAULT;
524
525         err = drm_ioctl(file, DRM_IOCTL_MAP_BUFS, (unsigned long)request);
526         if (err)
527                 return err;
528
529         if (__get_user(actual, &request->count))
530                 return -EFAULT;
531         if (count >= actual)
532                 for (i = 0; i < actual; ++i)
533                         if (__copy_in_user(&list32[i], &list[i],
534                                            offsetof(struct drm_buf_pub, address))
535                             || __get_user(addr, &list[i].address)
536                             || __put_user((unsigned long)addr,
537                                           &list32[i].address))
538                                 return -EFAULT;
539
540         if (__put_user(actual, &argp->count)
541             || __get_user(addr, &request->virtual)
542             || __put_user((unsigned long)addr, &argp->virtual))
543                 return -EFAULT;
544
545         return 0;
546 }
547
548 typedef struct drm_buf_free32 {
549         int count;
550         u32 list;
551 } drm_buf_free32_t;
552
553 static int compat_drm_freebufs(struct file *file, unsigned int cmd,
554                                unsigned long arg)
555 {
556         drm_buf_free32_t req32;
557         struct drm_buf_free __user *request;
558         drm_buf_free32_t __user *argp = (void __user *)arg;
559
560         if (copy_from_user(&req32, argp, sizeof(req32)))
561                 return -EFAULT;
562
563         request = compat_alloc_user_space(sizeof(*request));
564         if (!access_ok(VERIFY_WRITE, request, sizeof(*request)))
565                 return -EFAULT;
566         if (__put_user(req32.count, &request->count)
567             || __put_user((int __user *)(unsigned long)req32.list,
568                           &request->list))
569                 return -EFAULT;
570
571         return drm_ioctl(file, DRM_IOCTL_FREE_BUFS, (unsigned long)request);
572 }
573
574 typedef struct drm_ctx_priv_map32 {
575         unsigned int ctx_id;     /**< Context requesting private mapping */
576         u32 handle;             /**< Handle of map */
577 } drm_ctx_priv_map32_t;
578
579 static int compat_drm_setsareactx(struct file *file, unsigned int cmd,
580                                   unsigned long arg)
581 {
582         drm_ctx_priv_map32_t req32;
583         struct drm_ctx_priv_map __user *request;
584         drm_ctx_priv_map32_t __user *argp = (void __user *)arg;
585
586         if (copy_from_user(&req32, argp, sizeof(req32)))
587                 return -EFAULT;
588
589         request = compat_alloc_user_space(sizeof(*request));
590         if (!access_ok(VERIFY_WRITE, request, sizeof(*request)))
591                 return -EFAULT;
592         if (__put_user(req32.ctx_id, &request->ctx_id)
593             || __put_user((void *)(unsigned long)req32.handle,
594                           &request->handle))
595                 return -EFAULT;
596
597         return drm_ioctl(file, DRM_IOCTL_SET_SAREA_CTX, (unsigned long)request);
598 }
599
600 static int compat_drm_getsareactx(struct file *file, unsigned int cmd,
601                                   unsigned long arg)
602 {
603         struct drm_ctx_priv_map __user *request;
604         drm_ctx_priv_map32_t __user *argp = (void __user *)arg;
605         int err;
606         unsigned int ctx_id;
607         void *handle;
608
609         if (!access_ok(VERIFY_WRITE, argp, sizeof(*argp))
610             || __get_user(ctx_id, &argp->ctx_id))
611                 return -EFAULT;
612
613         request = compat_alloc_user_space(sizeof(*request));
614         if (!access_ok(VERIFY_WRITE, request, sizeof(*request)))
615                 return -EFAULT;
616         if (__put_user(ctx_id, &request->ctx_id))
617                 return -EFAULT;
618
619         err = drm_ioctl(file, DRM_IOCTL_GET_SAREA_CTX, (unsigned long)request);
620         if (err)
621                 return err;
622
623         if (__get_user(handle, &request->handle)
624             || __put_user((unsigned long)handle, &argp->handle))
625                 return -EFAULT;
626
627         return 0;
628 }
629
630 typedef struct drm_ctx_res32 {
631         int count;
632         u32 contexts;
633 } drm_ctx_res32_t;
634
635 static int compat_drm_resctx(struct file *file, unsigned int cmd,
636                              unsigned long arg)
637 {
638         drm_ctx_res32_t __user *argp = (void __user *)arg;
639         drm_ctx_res32_t res32;
640         struct drm_ctx_res __user *res;
641         int err;
642
643         if (copy_from_user(&res32, argp, sizeof(res32)))
644                 return -EFAULT;
645
646         res = compat_alloc_user_space(sizeof(*res));
647         if (!access_ok(VERIFY_WRITE, res, sizeof(*res)))
648                 return -EFAULT;
649         if (__put_user(res32.count, &res->count)
650             || __put_user((struct drm_ctx __user *) (unsigned long)res32.contexts,
651                           &res->contexts))
652                 return -EFAULT;
653
654         err = drm_ioctl(file, DRM_IOCTL_RES_CTX, (unsigned long)res);
655         if (err)
656                 return err;
657
658         if (__get_user(res32.count, &res->count)
659             || __put_user(res32.count, &argp->count))
660                 return -EFAULT;
661
662         return 0;
663 }
664
665 typedef struct drm_dma32 {
666         int context;              /**< Context handle */
667         int send_count;           /**< Number of buffers to send */
668         u32 send_indices;         /**< List of handles to buffers */
669         u32 send_sizes;           /**< Lengths of data to send */
670         enum drm_dma_flags flags;                 /**< Flags */
671         int request_count;        /**< Number of buffers requested */
672         int request_size;         /**< Desired size for buffers */
673         u32 request_indices;      /**< Buffer information */
674         u32 request_sizes;
675         int granted_count;        /**< Number of buffers granted */
676 } drm_dma32_t;
677
678 static int compat_drm_dma(struct file *file, unsigned int cmd,
679                           unsigned long arg)
680 {
681         drm_dma32_t d32;
682         drm_dma32_t __user *argp = (void __user *)arg;
683         struct drm_dma __user *d;
684         int err;
685
686         if (copy_from_user(&d32, argp, sizeof(d32)))
687                 return -EFAULT;
688
689         d = compat_alloc_user_space(sizeof(*d));
690         if (!access_ok(VERIFY_WRITE, d, sizeof(*d)))
691                 return -EFAULT;
692
693         if (__put_user(d32.context, &d->context)
694             || __put_user(d32.send_count, &d->send_count)
695             || __put_user((int __user *)(unsigned long)d32.send_indices,
696                           &d->send_indices)
697             || __put_user((int __user *)(unsigned long)d32.send_sizes,
698                           &d->send_sizes)
699             || __put_user(d32.flags, &d->flags)
700             || __put_user(d32.request_count, &d->request_count)
701             || __put_user((int __user *)(unsigned long)d32.request_indices,
702                           &d->request_indices)
703             || __put_user((int __user *)(unsigned long)d32.request_sizes,
704                           &d->request_sizes))
705                 return -EFAULT;
706
707         err = drm_ioctl(file, DRM_IOCTL_DMA, (unsigned long)d);
708         if (err)
709                 return err;
710
711         if (__get_user(d32.request_size, &d->request_size)
712             || __get_user(d32.granted_count, &d->granted_count)
713             || __put_user(d32.request_size, &argp->request_size)
714             || __put_user(d32.granted_count, &argp->granted_count))
715                 return -EFAULT;
716
717         return 0;
718 }
719
720 #if __OS_HAS_AGP
721 typedef struct drm_agp_mode32 {
722         u32 mode;       /**< AGP mode */
723 } drm_agp_mode32_t;
724
725 static int compat_drm_agp_enable(struct file *file, unsigned int cmd,
726                                  unsigned long arg)
727 {
728         drm_agp_mode32_t __user *argp = (void __user *)arg;
729         drm_agp_mode32_t m32;
730         struct drm_agp_mode __user *mode;
731
732         if (get_user(m32.mode, &argp->mode))
733                 return -EFAULT;
734
735         mode = compat_alloc_user_space(sizeof(*mode));
736         if (put_user(m32.mode, &mode->mode))
737                 return -EFAULT;
738
739         return drm_ioctl(file, DRM_IOCTL_AGP_ENABLE, (unsigned long)mode);
740 }
741
742 typedef struct drm_agp_info32 {
743         int agp_version_major;
744         int agp_version_minor;
745         u32 mode;
746         u32 aperture_base;      /* physical address */
747         u32 aperture_size;      /* bytes */
748         u32 memory_allowed;     /* bytes */
749         u32 memory_used;
750
751         /* PCI information */
752         unsigned short id_vendor;
753         unsigned short id_device;
754 } drm_agp_info32_t;
755
756 static int compat_drm_agp_info(struct file *file, unsigned int cmd,
757                                unsigned long arg)
758 {
759         drm_agp_info32_t __user *argp = (void __user *)arg;
760         drm_agp_info32_t i32;
761         struct drm_agp_info __user *info;
762         int err;
763
764         info = compat_alloc_user_space(sizeof(*info));
765         if (!access_ok(VERIFY_WRITE, info, sizeof(*info)))
766                 return -EFAULT;
767
768         err = drm_ioctl(file, DRM_IOCTL_AGP_INFO, (unsigned long)info);
769         if (err)
770                 return err;
771
772         if (__get_user(i32.agp_version_major, &info->agp_version_major)
773             || __get_user(i32.agp_version_minor, &info->agp_version_minor)
774             || __get_user(i32.mode, &info->mode)
775             || __get_user(i32.aperture_base, &info->aperture_base)
776             || __get_user(i32.aperture_size, &info->aperture_size)
777             || __get_user(i32.memory_allowed, &info->memory_allowed)
778             || __get_user(i32.memory_used, &info->memory_used)
779             || __get_user(i32.id_vendor, &info->id_vendor)
780             || __get_user(i32.id_device, &info->id_device))
781                 return -EFAULT;
782
783         if (copy_to_user(argp, &i32, sizeof(i32)))
784                 return -EFAULT;
785
786         return 0;
787 }
788
789 typedef struct drm_agp_buffer32 {
790         u32 size;       /**< In bytes -- will round to page boundary */
791         u32 handle;     /**< Used for binding / unbinding */
792         u32 type;       /**< Type of memory to allocate */
793         u32 physical;   /**< Physical used by i810 */
794 } drm_agp_buffer32_t;
795
796 static int compat_drm_agp_alloc(struct file *file, unsigned int cmd,
797                                 unsigned long arg)
798 {
799         drm_agp_buffer32_t __user *argp = (void __user *)arg;
800         drm_agp_buffer32_t req32;
801         struct drm_agp_buffer __user *request;
802         int err;
803
804         if (copy_from_user(&req32, argp, sizeof(req32)))
805                 return -EFAULT;
806
807         request = compat_alloc_user_space(sizeof(*request));
808         if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
809             || __put_user(req32.size, &request->size)
810             || __put_user(req32.type, &request->type))
811                 return -EFAULT;
812
813         err = drm_ioctl(file, DRM_IOCTL_AGP_ALLOC, (unsigned long)request);
814         if (err)
815                 return err;
816
817         if (__get_user(req32.handle, &request->handle)
818             || __get_user(req32.physical, &request->physical)
819             || copy_to_user(argp, &req32, sizeof(req32))) {
820                 drm_ioctl(file, DRM_IOCTL_AGP_FREE, (unsigned long)request);
821                 return -EFAULT;
822         }
823
824         return 0;
825 }
826
827 static int compat_drm_agp_free(struct file *file, unsigned int cmd,
828                                unsigned long arg)
829 {
830         drm_agp_buffer32_t __user *argp = (void __user *)arg;
831         struct drm_agp_buffer __user *request;
832         u32 handle;
833
834         request = compat_alloc_user_space(sizeof(*request));
835         if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
836             || get_user(handle, &argp->handle)
837             || __put_user(handle, &request->handle))
838                 return -EFAULT;
839
840         return drm_ioctl(file, DRM_IOCTL_AGP_FREE, (unsigned long)request);
841 }
842
843 typedef struct drm_agp_binding32 {
844         u32 handle;     /**< From drm_agp_buffer */
845         u32 offset;     /**< In bytes -- will round to page boundary */
846 } drm_agp_binding32_t;
847
848 static int compat_drm_agp_bind(struct file *file, unsigned int cmd,
849                                unsigned long arg)
850 {
851         drm_agp_binding32_t __user *argp = (void __user *)arg;
852         drm_agp_binding32_t req32;
853         struct drm_agp_binding __user *request;
854
855         if (copy_from_user(&req32, argp, sizeof(req32)))
856                 return -EFAULT;
857
858         request = compat_alloc_user_space(sizeof(*request));
859         if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
860             || __put_user(req32.handle, &request->handle)
861             || __put_user(req32.offset, &request->offset))
862                 return -EFAULT;
863
864         return drm_ioctl(file, DRM_IOCTL_AGP_BIND, (unsigned long)request);
865 }
866
867 static int compat_drm_agp_unbind(struct file *file, unsigned int cmd,
868                                  unsigned long arg)
869 {
870         drm_agp_binding32_t __user *argp = (void __user *)arg;
871         struct drm_agp_binding __user *request;
872         u32 handle;
873
874         request = compat_alloc_user_space(sizeof(*request));
875         if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
876             || get_user(handle, &argp->handle)
877             || __put_user(handle, &request->handle))
878                 return -EFAULT;
879
880         return drm_ioctl(file, DRM_IOCTL_AGP_UNBIND, (unsigned long)request);
881 }
882 #endif                          /* __OS_HAS_AGP */
883
884 typedef struct drm_scatter_gather32 {
885         u32 size;       /**< In bytes -- will round to page boundary */
886         u32 handle;     /**< Used for mapping / unmapping */
887 } drm_scatter_gather32_t;
888
889 static int compat_drm_sg_alloc(struct file *file, unsigned int cmd,
890                                unsigned long arg)
891 {
892         drm_scatter_gather32_t __user *argp = (void __user *)arg;
893         struct drm_scatter_gather __user *request;
894         int err;
895         unsigned long x;
896
897         request = compat_alloc_user_space(sizeof(*request));
898         if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
899             || !access_ok(VERIFY_WRITE, argp, sizeof(*argp))
900             || __get_user(x, &argp->size)
901             || __put_user(x, &request->size))
902                 return -EFAULT;
903
904         err = drm_ioctl(file, DRM_IOCTL_SG_ALLOC, (unsigned long)request);
905         if (err)
906                 return err;
907
908         /* XXX not sure about the handle conversion here... */
909         if (__get_user(x, &request->handle)
910             || __put_user(x >> PAGE_SHIFT, &argp->handle))
911                 return -EFAULT;
912
913         return 0;
914 }
915
916 static int compat_drm_sg_free(struct file *file, unsigned int cmd,
917                               unsigned long arg)
918 {
919         drm_scatter_gather32_t __user *argp = (void __user *)arg;
920         struct drm_scatter_gather __user *request;
921         unsigned long x;
922
923         request = compat_alloc_user_space(sizeof(*request));
924         if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
925             || !access_ok(VERIFY_WRITE, argp, sizeof(*argp))
926             || __get_user(x, &argp->handle)
927             || __put_user(x << PAGE_SHIFT, &request->handle))
928                 return -EFAULT;
929
930         return drm_ioctl(file, DRM_IOCTL_SG_FREE, (unsigned long)request);
931 }
932
933 #if defined(CONFIG_X86) || defined(CONFIG_IA64)
934 typedef struct drm_update_draw32 {
935         drm_drawable_t handle;
936         unsigned int type;
937         unsigned int num;
938         /* 64-bit version has a 32-bit pad here */
939         u64 data;       /**< Pointer */
940 } __attribute__((packed)) drm_update_draw32_t;
941
942 static int compat_drm_update_draw(struct file *file, unsigned int cmd,
943                                   unsigned long arg)
944 {
945         drm_update_draw32_t update32;
946         struct drm_update_draw __user *request;
947         int err;
948
949         if (copy_from_user(&update32, (void __user *)arg, sizeof(update32)))
950                 return -EFAULT;
951
952         request = compat_alloc_user_space(sizeof(*request));
953         if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) ||
954             __put_user(update32.handle, &request->handle) ||
955             __put_user(update32.type, &request->type) ||
956             __put_user(update32.num, &request->num) ||
957             __put_user(update32.data, &request->data))
958                 return -EFAULT;
959
960         err = drm_ioctl(file, DRM_IOCTL_UPDATE_DRAW, (unsigned long)request);
961         return err;
962 }
963 #endif
964
965 struct drm_wait_vblank_request32 {
966         enum drm_vblank_seq_type type;
967         unsigned int sequence;
968         u32 signal;
969 };
970
971 struct drm_wait_vblank_reply32 {
972         enum drm_vblank_seq_type type;
973         unsigned int sequence;
974         s32 tval_sec;
975         s32 tval_usec;
976 };
977
978 typedef union drm_wait_vblank32 {
979         struct drm_wait_vblank_request32 request;
980         struct drm_wait_vblank_reply32 reply;
981 } drm_wait_vblank32_t;
982
983 static int compat_drm_wait_vblank(struct file *file, unsigned int cmd,
984                                   unsigned long arg)
985 {
986         drm_wait_vblank32_t __user *argp = (void __user *)arg;
987         drm_wait_vblank32_t req32;
988         union drm_wait_vblank __user *request;
989         int err;
990
991         if (copy_from_user(&req32, argp, sizeof(req32)))
992                 return -EFAULT;
993
994         request = compat_alloc_user_space(sizeof(*request));
995         if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
996             || __put_user(req32.request.type, &request->request.type)
997             || __put_user(req32.request.sequence, &request->request.sequence)
998             || __put_user(req32.request.signal, &request->request.signal))
999                 return -EFAULT;
1000
1001         err = drm_ioctl(file, DRM_IOCTL_WAIT_VBLANK, (unsigned long)request);
1002         if (err)
1003                 return err;
1004
1005         if (__get_user(req32.reply.type, &request->reply.type)
1006             || __get_user(req32.reply.sequence, &request->reply.sequence)
1007             || __get_user(req32.reply.tval_sec, &request->reply.tval_sec)
1008             || __get_user(req32.reply.tval_usec, &request->reply.tval_usec))
1009                 return -EFAULT;
1010
1011         if (copy_to_user(argp, &req32, sizeof(req32)))
1012                 return -EFAULT;
1013
1014         return 0;
1015 }
1016
1017 drm_ioctl_compat_t *drm_compat_ioctls[] = {
1018         [DRM_IOCTL_NR(DRM_IOCTL_VERSION32)] = compat_drm_version,
1019         [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE32)] = compat_drm_getunique,
1020         [DRM_IOCTL_NR(DRM_IOCTL_GET_MAP32)] = compat_drm_getmap,
1021         [DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT32)] = compat_drm_getclient,
1022         [DRM_IOCTL_NR(DRM_IOCTL_GET_STATS32)] = compat_drm_getstats,
1023         [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE32)] = compat_drm_setunique,
1024         [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP32)] = compat_drm_addmap,
1025         [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS32)] = compat_drm_addbufs,
1026         [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS32)] = compat_drm_markbufs,
1027         [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS32)] = compat_drm_infobufs,
1028         [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS32)] = compat_drm_mapbufs,
1029         [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS32)] = compat_drm_freebufs,
1030         [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP32)] = compat_drm_rmmap,
1031         [DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX32)] = compat_drm_setsareactx,
1032         [DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX32)] = compat_drm_getsareactx,
1033         [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX32)] = compat_drm_resctx,
1034         [DRM_IOCTL_NR(DRM_IOCTL_DMA32)] = compat_drm_dma,
1035 #if __OS_HAS_AGP
1036         [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE32)] = compat_drm_agp_enable,
1037         [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO32)] = compat_drm_agp_info,
1038         [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC32)] = compat_drm_agp_alloc,
1039         [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE32)] = compat_drm_agp_free,
1040         [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND32)] = compat_drm_agp_bind,
1041         [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND32)] = compat_drm_agp_unbind,
1042 #endif
1043         [DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC32)] = compat_drm_sg_alloc,
1044         [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE32)] = compat_drm_sg_free,
1045 #if defined(CONFIG_X86) || defined(CONFIG_IA64)
1046         [DRM_IOCTL_NR(DRM_IOCTL_UPDATE_DRAW32)] = compat_drm_update_draw,
1047 #endif
1048         [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK32)] = compat_drm_wait_vblank,
1049 };
1050
1051 /**
1052  * Called whenever a 32-bit process running under a 64-bit kernel
1053  * performs an ioctl on /dev/drm.
1054  *
1055  * \param file_priv DRM file private.
1056  * \param cmd command.
1057  * \param arg user argument.
1058  * \return zero on success or negative number on failure.
1059  */
1060 long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
1061 {
1062         unsigned int nr = DRM_IOCTL_NR(cmd);
1063         drm_ioctl_compat_t *fn;
1064         int ret;
1065
1066         /* Assume that ioctls without an explicit compat routine will just
1067          * work.  This may not always be a good assumption, but it's better
1068          * than always failing.
1069          */
1070         if (nr >= ARRAY_SIZE(drm_compat_ioctls))
1071                 return drm_ioctl(filp, cmd, arg);
1072
1073         fn = drm_compat_ioctls[nr];
1074
1075         if (fn != NULL)
1076                 ret = (*fn) (filp, cmd, arg);
1077         else
1078                 ret = drm_ioctl(filp, cmd, arg);
1079
1080         return ret;
1081 }
1082
1083 EXPORT_SYMBOL(drm_compat_ioctl);