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