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