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>
31 #include <linux/ioctl32.h>
35 #include "radeon_drm.h"
36 #include "radeon_drv.h"
38 typedef struct drm_radeon_init32
{
40 u32 sarea_priv_offset
;
48 unsigned int front_offset
, front_pitch
;
49 unsigned int back_offset
, back_pitch
;
50 unsigned int depth_bpp
;
51 unsigned int depth_offset
, depth_pitch
;
58 u32 gart_textures_offset
;
59 } drm_radeon_init32_t
;
61 static int compat_radeon_cp_init(struct file
*file
, unsigned int cmd
,
64 drm_radeon_init32_t init32
;
65 drm_radeon_init_t __user
*init
;
67 if (copy_from_user(&init32
, (void __user
*)arg
, sizeof(init32
)))
70 init
= compat_alloc_user_space(sizeof(*init
));
71 if (!access_ok(VERIFY_WRITE
, init
, sizeof(*init
))
72 || __put_user(init32
.func
, &init
->func
)
73 || __put_user(init32
.sarea_priv_offset
, &init
->sarea_priv_offset
)
74 || __put_user(init32
.is_pci
, &init
->is_pci
)
75 || __put_user(init32
.cp_mode
, &init
->cp_mode
)
76 || __put_user(init32
.gart_size
, &init
->gart_size
)
77 || __put_user(init32
.ring_size
, &init
->ring_size
)
78 || __put_user(init32
.usec_timeout
, &init
->usec_timeout
)
79 || __put_user(init32
.fb_bpp
, &init
->fb_bpp
)
80 || __put_user(init32
.front_offset
, &init
->front_offset
)
81 || __put_user(init32
.front_pitch
, &init
->front_pitch
)
82 || __put_user(init32
.back_offset
, &init
->back_offset
)
83 || __put_user(init32
.back_pitch
, &init
->back_pitch
)
84 || __put_user(init32
.depth_bpp
, &init
->depth_bpp
)
85 || __put_user(init32
.depth_offset
, &init
->depth_offset
)
86 || __put_user(init32
.depth_pitch
, &init
->depth_pitch
)
87 || __put_user(init32
.fb_offset
, &init
->fb_offset
)
88 || __put_user(init32
.mmio_offset
, &init
->mmio_offset
)
89 || __put_user(init32
.ring_offset
, &init
->ring_offset
)
90 || __put_user(init32
.ring_rptr_offset
, &init
->ring_rptr_offset
)
91 || __put_user(init32
.buffers_offset
, &init
->buffers_offset
)
92 || __put_user(init32
.gart_textures_offset
,
93 &init
->gart_textures_offset
))
96 return drm_ioctl(file
->f_dentry
->d_inode
, file
,
97 DRM_IOCTL_RADEON_CP_INIT
, (unsigned long) init
);
100 typedef struct drm_radeon_clear32
{
102 unsigned int clear_color
;
103 unsigned int clear_depth
;
104 unsigned int color_mask
;
105 unsigned int depth_mask
; /* misnamed field: should be stencil */
107 } drm_radeon_clear32_t
;
109 static int compat_radeon_cp_clear(struct file
*file
, unsigned int cmd
,
112 drm_radeon_clear32_t clr32
;
113 drm_radeon_clear_t __user
*clr
;
115 if (copy_from_user(&clr32
, (void __user
*)arg
, sizeof(clr32
)))
118 clr
= compat_alloc_user_space(sizeof(*clr
));
119 if (!access_ok(VERIFY_WRITE
, clr
, sizeof(*clr
))
120 || __put_user(clr32
.flags
, &clr
->flags
)
121 || __put_user(clr32
.clear_color
, &clr
->clear_color
)
122 || __put_user(clr32
.clear_depth
, &clr
->clear_depth
)
123 || __put_user(clr32
.color_mask
, &clr
->color_mask
)
124 || __put_user(clr32
.depth_mask
, &clr
->depth_mask
)
125 || __put_user((void __user
*)(unsigned long)clr32
.depth_boxes
,
129 return drm_ioctl(file
->f_dentry
->d_inode
, file
,
130 DRM_IOCTL_RADEON_CLEAR
, (unsigned long) clr
);
133 typedef struct drm_radeon_stipple32
{
135 } drm_radeon_stipple32_t
;
137 static int compat_radeon_cp_stipple(struct file
*file
, unsigned int cmd
,
140 drm_radeon_stipple32_t __user
*argp
= (void __user
*) arg
;
141 drm_radeon_stipple_t __user
*request
;
144 if (get_user(mask
, &argp
->mask
))
147 request
= compat_alloc_user_space(sizeof(*request
));
148 if (!access_ok(VERIFY_WRITE
, request
, sizeof(*request
))
149 || __put_user((unsigned int __user
*)(unsigned long) mask
,
153 return drm_ioctl(file
->f_dentry
->d_inode
, file
,
154 DRM_IOCTL_RADEON_STIPPLE
, (unsigned long) request
);
157 typedef struct drm_radeon_tex_image32
{
158 unsigned int x
, y
; /* Blit coordinates */
159 unsigned int width
, height
;
161 } drm_radeon_tex_image32_t
;
163 typedef struct drm_radeon_texture32
{
167 int width
; /* Texture image coordinates */
170 } drm_radeon_texture32_t
;
172 static int compat_radeon_cp_texture(struct file
*file
, unsigned int cmd
,
175 drm_radeon_texture32_t req32
;
176 drm_radeon_texture_t __user
*request
;
177 drm_radeon_tex_image32_t img32
;
178 drm_radeon_tex_image_t __user
*image
;
180 if (copy_from_user(&req32
, (void __user
*) arg
, sizeof(req32
)))
182 if (req32
.image
== 0)
184 if (copy_from_user(&img32
, (void __user
*)(unsigned long)req32
.image
,
188 request
= compat_alloc_user_space(sizeof(*request
) + sizeof(*image
));
189 if (!access_ok(VERIFY_WRITE
, request
,
190 sizeof(*request
) + sizeof(*image
)))
192 image
= (drm_radeon_tex_image_t __user
*) (request
+ 1);
194 if (__put_user(req32
.offset
, &request
->offset
)
195 || __put_user(req32
.pitch
, &request
->pitch
)
196 || __put_user(req32
.format
, &request
->format
)
197 || __put_user(req32
.width
, &request
->width
)
198 || __put_user(req32
.height
, &request
->height
)
199 || __put_user(image
, &request
->image
)
200 || __put_user(img32
.x
, &image
->x
)
201 || __put_user(img32
.y
, &image
->y
)
202 || __put_user(img32
.width
, &image
->width
)
203 || __put_user(img32
.height
, &image
->height
)
204 || __put_user((const void __user
*)(unsigned long)img32
.data
,
208 return drm_ioctl(file
->f_dentry
->d_inode
, file
,
209 DRM_IOCTL_RADEON_TEXTURE
, (unsigned long) request
);
212 typedef struct drm_radeon_vertex2_32
{
213 int idx
; /* Index of vertex buffer */
214 int discard
; /* Client finished with buffer? */
219 } drm_radeon_vertex2_32_t
;
221 static int compat_radeon_cp_vertex2(struct file
*file
, unsigned int cmd
,
224 drm_radeon_vertex2_32_t req32
;
225 drm_radeon_vertex2_t __user
*request
;
227 if (copy_from_user(&req32
, (void __user
*) arg
, sizeof(req32
)))
230 request
= compat_alloc_user_space(sizeof(*request
));
231 if (!access_ok(VERIFY_WRITE
, request
, sizeof(*request
))
232 || __put_user(req32
.idx
, &request
->idx
)
233 || __put_user(req32
.discard
, &request
->discard
)
234 || __put_user(req32
.nr_states
, &request
->nr_states
)
235 || __put_user((void __user
*)(unsigned long)req32
.state
,
237 || __put_user(req32
.nr_prims
, &request
->nr_prims
)
238 || __put_user((void __user
*)(unsigned long)req32
.prim
,
242 return drm_ioctl(file
->f_dentry
->d_inode
, file
,
243 DRM_IOCTL_RADEON_VERTEX2
, (unsigned long) request
);
246 typedef struct drm_radeon_cmd_buffer32
{
251 } drm_radeon_cmd_buffer32_t
;
253 static int compat_radeon_cp_cmdbuf(struct file
*file
, unsigned int cmd
,
256 drm_radeon_cmd_buffer32_t req32
;
257 drm_radeon_cmd_buffer_t __user
*request
;
259 if (copy_from_user(&req32
, (void __user
*) arg
, sizeof(req32
)))
262 request
= compat_alloc_user_space(sizeof(*request
));
263 if (!access_ok(VERIFY_WRITE
, request
, sizeof(*request
))
264 || __put_user(req32
.bufsz
, &request
->bufsz
)
265 || __put_user((void __user
*)(unsigned long)req32
.buf
,
267 || __put_user(req32
.nbox
, &request
->nbox
)
268 || __put_user((void __user
*)(unsigned long)req32
.boxes
,
272 return drm_ioctl(file
->f_dentry
->d_inode
, file
,
273 DRM_IOCTL_RADEON_CMDBUF
, (unsigned long) request
);
276 typedef struct drm_radeon_getparam32
{
279 } drm_radeon_getparam32_t
;
281 static int compat_radeon_cp_getparam(struct file
*file
, unsigned int cmd
,
284 drm_radeon_getparam32_t req32
;
285 drm_radeon_getparam_t __user
*request
;
287 if (copy_from_user(&req32
, (void __user
*) arg
, sizeof(req32
)))
290 request
= compat_alloc_user_space(sizeof(*request
));
291 if (!access_ok(VERIFY_WRITE
, request
, sizeof(*request
))
292 || __put_user(req32
.param
, &request
->param
)
293 || __put_user((void __user
*)(unsigned long)req32
.value
,
297 return drm_ioctl(file
->f_dentry
->d_inode
, file
,
298 DRM_IOCTL_RADEON_GETPARAM
, (unsigned long) request
);
301 typedef struct drm_radeon_mem_alloc32
{
305 u32 region_offset
; /* offset from start of fb or GART */
306 } drm_radeon_mem_alloc32_t
;
308 static int compat_radeon_mem_alloc(struct file
*file
, unsigned int cmd
,
311 drm_radeon_mem_alloc32_t req32
;
312 drm_radeon_mem_alloc_t __user
*request
;
314 if (copy_from_user(&req32
, (void __user
*) arg
, sizeof(req32
)))
317 request
= compat_alloc_user_space(sizeof(*request
));
318 if (!access_ok(VERIFY_WRITE
, request
, sizeof(*request
))
319 || __put_user(req32
.region
, &request
->region
)
320 || __put_user(req32
.alignment
, &request
->alignment
)
321 || __put_user(req32
.size
, &request
->size
)
322 || __put_user((int __user
*)(unsigned long)req32
.region_offset
,
323 &request
->region_offset
))
326 return drm_ioctl(file
->f_dentry
->d_inode
, file
,
327 DRM_IOCTL_RADEON_ALLOC
, (unsigned long) request
);
330 typedef struct drm_radeon_irq_emit32
{
332 } drm_radeon_irq_emit32_t
;
334 static int compat_radeon_irq_emit(struct file
*file
, unsigned int cmd
,
337 drm_radeon_irq_emit32_t req32
;
338 drm_radeon_irq_emit_t __user
*request
;
340 if (copy_from_user(&req32
, (void __user
*) arg
, sizeof(req32
)))
343 request
= compat_alloc_user_space(sizeof(*request
));
344 if (!access_ok(VERIFY_WRITE
, request
, sizeof(*request
))
345 || __put_user((int __user
*)(unsigned long)req32
.irq_seq
,
349 return drm_ioctl(file
->f_dentry
->d_inode
, file
,
350 DRM_IOCTL_RADEON_IRQ_EMIT
, (unsigned long) request
);
353 drm_ioctl_compat_t
*radeon_compat_ioctls
[] = {
354 [DRM_RADEON_CP_INIT
] = compat_radeon_cp_init
,
355 [DRM_RADEON_CLEAR
] = compat_radeon_cp_clear
,
356 [DRM_RADEON_STIPPLE
] = compat_radeon_cp_stipple
,
357 [DRM_RADEON_TEXTURE
] = compat_radeon_cp_texture
,
358 [DRM_RADEON_VERTEX2
] = compat_radeon_cp_vertex2
,
359 [DRM_RADEON_CMDBUF
] = compat_radeon_cp_cmdbuf
,
360 [DRM_RADEON_GETPARAM
] = compat_radeon_cp_getparam
,
361 [DRM_RADEON_ALLOC
] = compat_radeon_mem_alloc
,
362 [DRM_RADEON_IRQ_EMIT
] = compat_radeon_irq_emit
,
366 * Called whenever a 32-bit process running under a 64-bit kernel
367 * performs an ioctl on /dev/dri/card<n>.
369 * \param filp file pointer.
370 * \param cmd command.
371 * \param arg user argument.
372 * \return zero on success or negative number on failure.
374 long radeon_compat_ioctl(struct file
*filp
, unsigned int cmd
,
377 unsigned int nr
= DRM_IOCTL_NR(cmd
);
378 drm_ioctl_compat_t
*fn
= NULL
;
381 if (nr
< DRM_COMMAND_BASE
)
382 return drm_compat_ioctl(filp
, cmd
, arg
);
384 if (nr
< DRM_COMMAND_BASE
+ DRM_ARRAY_SIZE(radeon_compat_ioctls
))
385 fn
= radeon_compat_ioctls
[nr
- DRM_COMMAND_BASE
];
387 lock_kernel(); /* XXX for now */
389 ret
= (*fn
)(filp
, cmd
, arg
);
391 ret
= drm_ioctl(filp
->f_dentry
->d_inode
, filp
, cmd
, arg
);