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