4 * 32-bit ioctl compatibility routines for the Radeon DRM.
6 * \author Paul Mackerras <paulus@samba.org>
8 * Copyright (C) Paul Mackerras 2005
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:
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
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
30 #include <linux/compat.h>
34 #include "radeon_drm.h"
35 #include "radeon_drv.h"
37 typedef struct drm_radeon_init32
{
39 u32 sarea_priv_offset
;
47 unsigned int front_offset
, front_pitch
;
48 unsigned int back_offset
, back_pitch
;
49 unsigned int depth_bpp
;
50 unsigned int depth_offset
, depth_pitch
;
57 u32 gart_textures_offset
;
58 } drm_radeon_init32_t
;
60 static int compat_radeon_cp_init(struct file
*file
, unsigned int cmd
,
63 drm_radeon_init32_t init32
;
64 drm_radeon_init_t __user
*init
;
66 if (copy_from_user(&init32
, (void __user
*)arg
, sizeof(init32
)))
69 init
= compat_alloc_user_space(sizeof(*init
));
70 if (!access_ok(VERIFY_WRITE
, init
, sizeof(*init
))
71 || __put_user(init32
.func
, &init
->func
)
72 || __put_user(init32
.sarea_priv_offset
, &init
->sarea_priv_offset
)
73 || __put_user(init32
.is_pci
, &init
->is_pci
)
74 || __put_user(init32
.cp_mode
, &init
->cp_mode
)
75 || __put_user(init32
.gart_size
, &init
->gart_size
)
76 || __put_user(init32
.ring_size
, &init
->ring_size
)
77 || __put_user(init32
.usec_timeout
, &init
->usec_timeout
)
78 || __put_user(init32
.fb_bpp
, &init
->fb_bpp
)
79 || __put_user(init32
.front_offset
, &init
->front_offset
)
80 || __put_user(init32
.front_pitch
, &init
->front_pitch
)
81 || __put_user(init32
.back_offset
, &init
->back_offset
)
82 || __put_user(init32
.back_pitch
, &init
->back_pitch
)
83 || __put_user(init32
.depth_bpp
, &init
->depth_bpp
)
84 || __put_user(init32
.depth_offset
, &init
->depth_offset
)
85 || __put_user(init32
.depth_pitch
, &init
->depth_pitch
)
86 || __put_user(init32
.fb_offset
, &init
->fb_offset
)
87 || __put_user(init32
.mmio_offset
, &init
->mmio_offset
)
88 || __put_user(init32
.ring_offset
, &init
->ring_offset
)
89 || __put_user(init32
.ring_rptr_offset
, &init
->ring_rptr_offset
)
90 || __put_user(init32
.buffers_offset
, &init
->buffers_offset
)
91 || __put_user(init32
.gart_textures_offset
,
92 &init
->gart_textures_offset
))
95 return drm_ioctl(file
->f_path
.dentry
->d_inode
, file
,
96 DRM_IOCTL_RADEON_CP_INIT
, (unsigned long)init
);
99 typedef struct drm_radeon_clear32
{
101 unsigned int clear_color
;
102 unsigned int clear_depth
;
103 unsigned int color_mask
;
104 unsigned int depth_mask
; /* misnamed field: should be stencil */
106 } drm_radeon_clear32_t
;
108 static int compat_radeon_cp_clear(struct file
*file
, unsigned int cmd
,
111 drm_radeon_clear32_t clr32
;
112 drm_radeon_clear_t __user
*clr
;
114 if (copy_from_user(&clr32
, (void __user
*)arg
, sizeof(clr32
)))
117 clr
= compat_alloc_user_space(sizeof(*clr
));
118 if (!access_ok(VERIFY_WRITE
, clr
, sizeof(*clr
))
119 || __put_user(clr32
.flags
, &clr
->flags
)
120 || __put_user(clr32
.clear_color
, &clr
->clear_color
)
121 || __put_user(clr32
.clear_depth
, &clr
->clear_depth
)
122 || __put_user(clr32
.color_mask
, &clr
->color_mask
)
123 || __put_user(clr32
.depth_mask
, &clr
->depth_mask
)
124 || __put_user((void __user
*)(unsigned long)clr32
.depth_boxes
,
128 return drm_ioctl(file
->f_path
.dentry
->d_inode
, file
,
129 DRM_IOCTL_RADEON_CLEAR
, (unsigned long)clr
);
132 typedef struct drm_radeon_stipple32
{
134 } drm_radeon_stipple32_t
;
136 static int compat_radeon_cp_stipple(struct file
*file
, unsigned int cmd
,
139 drm_radeon_stipple32_t __user
*argp
= (void __user
*)arg
;
140 drm_radeon_stipple_t __user
*request
;
143 if (get_user(mask
, &argp
->mask
))
146 request
= compat_alloc_user_space(sizeof(*request
));
147 if (!access_ok(VERIFY_WRITE
, request
, sizeof(*request
))
148 || __put_user((unsigned int __user
*)(unsigned long)mask
,
152 return drm_ioctl(file
->f_path
.dentry
->d_inode
, file
,
153 DRM_IOCTL_RADEON_STIPPLE
, (unsigned long)request
);
156 typedef struct drm_radeon_tex_image32
{
157 unsigned int x
, y
; /* Blit coordinates */
158 unsigned int width
, height
;
160 } drm_radeon_tex_image32_t
;
162 typedef struct drm_radeon_texture32
{
166 int width
; /* Texture image coordinates */
169 } drm_radeon_texture32_t
;
171 static int compat_radeon_cp_texture(struct file
*file
, unsigned int cmd
,
174 drm_radeon_texture32_t req32
;
175 drm_radeon_texture_t __user
*request
;
176 drm_radeon_tex_image32_t img32
;
177 drm_radeon_tex_image_t __user
*image
;
179 if (copy_from_user(&req32
, (void __user
*)arg
, sizeof(req32
)))
181 if (req32
.image
== 0)
183 if (copy_from_user(&img32
, (void __user
*)(unsigned long)req32
.image
,
187 request
= compat_alloc_user_space(sizeof(*request
) + sizeof(*image
));
188 if (!access_ok(VERIFY_WRITE
, request
,
189 sizeof(*request
) + sizeof(*image
)))
191 image
= (drm_radeon_tex_image_t __user
*) (request
+ 1);
193 if (__put_user(req32
.offset
, &request
->offset
)
194 || __put_user(req32
.pitch
, &request
->pitch
)
195 || __put_user(req32
.format
, &request
->format
)
196 || __put_user(req32
.width
, &request
->width
)
197 || __put_user(req32
.height
, &request
->height
)
198 || __put_user(image
, &request
->image
)
199 || __put_user(img32
.x
, &image
->x
)
200 || __put_user(img32
.y
, &image
->y
)
201 || __put_user(img32
.width
, &image
->width
)
202 || __put_user(img32
.height
, &image
->height
)
203 || __put_user((const void __user
*)(unsigned long)img32
.data
,
207 return drm_ioctl(file
->f_path
.dentry
->d_inode
, file
,
208 DRM_IOCTL_RADEON_TEXTURE
, (unsigned long)request
);
211 typedef struct drm_radeon_vertex2_32
{
212 int idx
; /* Index of vertex buffer */
213 int discard
; /* Client finished with buffer? */
218 } drm_radeon_vertex2_32_t
;
220 static int compat_radeon_cp_vertex2(struct file
*file
, unsigned int cmd
,
223 drm_radeon_vertex2_32_t req32
;
224 drm_radeon_vertex2_t __user
*request
;
226 if (copy_from_user(&req32
, (void __user
*)arg
, sizeof(req32
)))
229 request
= compat_alloc_user_space(sizeof(*request
));
230 if (!access_ok(VERIFY_WRITE
, request
, sizeof(*request
))
231 || __put_user(req32
.idx
, &request
->idx
)
232 || __put_user(req32
.discard
, &request
->discard
)
233 || __put_user(req32
.nr_states
, &request
->nr_states
)
234 || __put_user((void __user
*)(unsigned long)req32
.state
,
236 || __put_user(req32
.nr_prims
, &request
->nr_prims
)
237 || __put_user((void __user
*)(unsigned long)req32
.prim
,
241 return drm_ioctl(file
->f_path
.dentry
->d_inode
, file
,
242 DRM_IOCTL_RADEON_VERTEX2
, (unsigned long)request
);
245 typedef struct drm_radeon_cmd_buffer32
{
250 } drm_radeon_cmd_buffer32_t
;
252 static int compat_radeon_cp_cmdbuf(struct file
*file
, unsigned int cmd
,
255 drm_radeon_cmd_buffer32_t req32
;
256 drm_radeon_cmd_buffer_t __user
*request
;
258 if (copy_from_user(&req32
, (void __user
*)arg
, sizeof(req32
)))
261 request
= compat_alloc_user_space(sizeof(*request
));
262 if (!access_ok(VERIFY_WRITE
, request
, sizeof(*request
))
263 || __put_user(req32
.bufsz
, &request
->bufsz
)
264 || __put_user((void __user
*)(unsigned long)req32
.buf
,
266 || __put_user(req32
.nbox
, &request
->nbox
)
267 || __put_user((void __user
*)(unsigned long)req32
.boxes
,
271 return drm_ioctl(file
->f_path
.dentry
->d_inode
, file
,
272 DRM_IOCTL_RADEON_CMDBUF
, (unsigned long)request
);
275 typedef struct drm_radeon_getparam32
{
278 } drm_radeon_getparam32_t
;
280 static int compat_radeon_cp_getparam(struct file
*file
, unsigned int cmd
,
283 drm_radeon_getparam32_t req32
;
284 drm_radeon_getparam_t __user
*request
;
286 if (copy_from_user(&req32
, (void __user
*)arg
, sizeof(req32
)))
289 request
= compat_alloc_user_space(sizeof(*request
));
290 if (!access_ok(VERIFY_WRITE
, request
, sizeof(*request
))
291 || __put_user(req32
.param
, &request
->param
)
292 || __put_user((void __user
*)(unsigned long)req32
.value
,
296 return drm_ioctl(file
->f_path
.dentry
->d_inode
, file
,
297 DRM_IOCTL_RADEON_GETPARAM
, (unsigned long)request
);
300 typedef struct drm_radeon_mem_alloc32
{
304 u32 region_offset
; /* offset from start of fb or GART */
305 } drm_radeon_mem_alloc32_t
;
307 static int compat_radeon_mem_alloc(struct file
*file
, unsigned int cmd
,
310 drm_radeon_mem_alloc32_t req32
;
311 drm_radeon_mem_alloc_t __user
*request
;
313 if (copy_from_user(&req32
, (void __user
*)arg
, sizeof(req32
)))
316 request
= compat_alloc_user_space(sizeof(*request
));
317 if (!access_ok(VERIFY_WRITE
, request
, sizeof(*request
))
318 || __put_user(req32
.region
, &request
->region
)
319 || __put_user(req32
.alignment
, &request
->alignment
)
320 || __put_user(req32
.size
, &request
->size
)
321 || __put_user((int __user
*)(unsigned long)req32
.region_offset
,
322 &request
->region_offset
))
325 return drm_ioctl(file
->f_path
.dentry
->d_inode
, file
,
326 DRM_IOCTL_RADEON_ALLOC
, (unsigned long)request
);
329 typedef struct drm_radeon_irq_emit32
{
331 } drm_radeon_irq_emit32_t
;
333 static int compat_radeon_irq_emit(struct file
*file
, unsigned int cmd
,
336 drm_radeon_irq_emit32_t req32
;
337 drm_radeon_irq_emit_t __user
*request
;
339 if (copy_from_user(&req32
, (void __user
*)arg
, sizeof(req32
)))
342 request
= compat_alloc_user_space(sizeof(*request
));
343 if (!access_ok(VERIFY_WRITE
, request
, sizeof(*request
))
344 || __put_user((int __user
*)(unsigned long)req32
.irq_seq
,
348 return drm_ioctl(file
->f_path
.dentry
->d_inode
, file
,
349 DRM_IOCTL_RADEON_IRQ_EMIT
, (unsigned long)request
);
352 /* The two 64-bit arches where alignof(u64)==4 in 32-bit code */
353 #if defined (CONFIG_X86_64) || defined(CONFIG_IA64)
354 typedef struct drm_radeon_setparam32
{
357 } __attribute__((packed
)) drm_radeon_setparam32_t
;
359 static int compat_radeon_cp_setparam(struct file
*file
, unsigned int cmd
,
362 drm_radeon_setparam32_t req32
;
363 drm_radeon_setparam_t __user
*request
;
365 if (copy_from_user(&req32
, (void __user
*) arg
, sizeof(req32
)))
368 request
= compat_alloc_user_space(sizeof(*request
));
369 if (!access_ok(VERIFY_WRITE
, request
, sizeof(*request
))
370 || __put_user(req32
.param
, &request
->param
)
371 || __put_user((void __user
*)(unsigned long)req32
.value
,
375 return drm_ioctl(file
->f_dentry
->d_inode
, file
,
376 DRM_IOCTL_RADEON_SETPARAM
, (unsigned long) request
);
379 #define compat_radeon_cp_setparam NULL
380 #endif /* X86_64 || IA64 */
382 drm_ioctl_compat_t
*radeon_compat_ioctls
[] = {
383 [DRM_RADEON_CP_INIT
] = compat_radeon_cp_init
,
384 [DRM_RADEON_CLEAR
] = compat_radeon_cp_clear
,
385 [DRM_RADEON_STIPPLE
] = compat_radeon_cp_stipple
,
386 [DRM_RADEON_TEXTURE
] = compat_radeon_cp_texture
,
387 [DRM_RADEON_VERTEX2
] = compat_radeon_cp_vertex2
,
388 [DRM_RADEON_CMDBUF
] = compat_radeon_cp_cmdbuf
,
389 [DRM_RADEON_GETPARAM
] = compat_radeon_cp_getparam
,
390 [DRM_RADEON_SETPARAM
] = compat_radeon_cp_setparam
,
391 [DRM_RADEON_ALLOC
] = compat_radeon_mem_alloc
,
392 [DRM_RADEON_IRQ_EMIT
] = compat_radeon_irq_emit
,
396 * Called whenever a 32-bit process running under a 64-bit kernel
397 * performs an ioctl on /dev/dri/card<n>.
399 * \param filp file pointer.
400 * \param cmd command.
401 * \param arg user argument.
402 * \return zero on success or negative number on failure.
404 long radeon_compat_ioctl(struct file
*filp
, unsigned int cmd
, unsigned long arg
)
406 unsigned int nr
= DRM_IOCTL_NR(cmd
);
407 drm_ioctl_compat_t
*fn
= NULL
;
410 if (nr
< DRM_COMMAND_BASE
)
411 return drm_compat_ioctl(filp
, cmd
, arg
);
413 if (nr
< DRM_COMMAND_BASE
+ DRM_ARRAY_SIZE(radeon_compat_ioctls
))
414 fn
= radeon_compat_ioctls
[nr
- DRM_COMMAND_BASE
];
416 lock_kernel(); /* XXX for now */
418 ret
= (*fn
) (filp
, cmd
, arg
);
420 ret
= drm_ioctl(filp
->f_path
.dentry
->d_inode
, filp
, cmd
, arg
);
426 long radeon_kms_compat_ioctl(struct file
*filp
, unsigned int cmd
, unsigned long arg
)
428 unsigned int nr
= DRM_IOCTL_NR(cmd
);
431 if (nr
< DRM_COMMAND_BASE
)
432 return drm_compat_ioctl(filp
, cmd
, arg
);
434 lock_kernel(); /* XXX for now */
435 ret
= drm_ioctl(filp
->f_path
.dentry
->d_inode
, filp
, cmd
, arg
);