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>
33 #include <drm/radeon_drm.h>
34 #include "radeon_drv.h"
36 typedef struct drm_radeon_init32
{
38 u32 sarea_priv_offset
;
46 unsigned int front_offset
, front_pitch
;
47 unsigned int back_offset
, back_pitch
;
48 unsigned int depth_bpp
;
49 unsigned int depth_offset
, depth_pitch
;
56 u32 gart_textures_offset
;
57 } drm_radeon_init32_t
;
59 static int compat_radeon_cp_init(struct file
*file
, unsigned int cmd
,
62 drm_radeon_init32_t init32
;
63 drm_radeon_init_t __user
*init
;
65 if (copy_from_user(&init32
, (void __user
*)arg
, sizeof(init32
)))
68 init
= compat_alloc_user_space(sizeof(*init
));
69 if (!access_ok(VERIFY_WRITE
, init
, sizeof(*init
))
70 || __put_user(init32
.func
, &init
->func
)
71 || __put_user(init32
.sarea_priv_offset
, &init
->sarea_priv_offset
)
72 || __put_user(init32
.is_pci
, &init
->is_pci
)
73 || __put_user(init32
.cp_mode
, &init
->cp_mode
)
74 || __put_user(init32
.gart_size
, &init
->gart_size
)
75 || __put_user(init32
.ring_size
, &init
->ring_size
)
76 || __put_user(init32
.usec_timeout
, &init
->usec_timeout
)
77 || __put_user(init32
.fb_bpp
, &init
->fb_bpp
)
78 || __put_user(init32
.front_offset
, &init
->front_offset
)
79 || __put_user(init32
.front_pitch
, &init
->front_pitch
)
80 || __put_user(init32
.back_offset
, &init
->back_offset
)
81 || __put_user(init32
.back_pitch
, &init
->back_pitch
)
82 || __put_user(init32
.depth_bpp
, &init
->depth_bpp
)
83 || __put_user(init32
.depth_offset
, &init
->depth_offset
)
84 || __put_user(init32
.depth_pitch
, &init
->depth_pitch
)
85 || __put_user(init32
.fb_offset
, &init
->fb_offset
)
86 || __put_user(init32
.mmio_offset
, &init
->mmio_offset
)
87 || __put_user(init32
.ring_offset
, &init
->ring_offset
)
88 || __put_user(init32
.ring_rptr_offset
, &init
->ring_rptr_offset
)
89 || __put_user(init32
.buffers_offset
, &init
->buffers_offset
)
90 || __put_user(init32
.gart_textures_offset
,
91 &init
->gart_textures_offset
))
94 return drm_ioctl(file
, DRM_IOCTL_RADEON_CP_INIT
, (unsigned long)init
);
97 typedef struct drm_radeon_clear32
{
99 unsigned int clear_color
;
100 unsigned int clear_depth
;
101 unsigned int color_mask
;
102 unsigned int depth_mask
; /* misnamed field: should be stencil */
104 } drm_radeon_clear32_t
;
106 static int compat_radeon_cp_clear(struct file
*file
, unsigned int cmd
,
109 drm_radeon_clear32_t clr32
;
110 drm_radeon_clear_t __user
*clr
;
112 if (copy_from_user(&clr32
, (void __user
*)arg
, sizeof(clr32
)))
115 clr
= compat_alloc_user_space(sizeof(*clr
));
116 if (!access_ok(VERIFY_WRITE
, clr
, sizeof(*clr
))
117 || __put_user(clr32
.flags
, &clr
->flags
)
118 || __put_user(clr32
.clear_color
, &clr
->clear_color
)
119 || __put_user(clr32
.clear_depth
, &clr
->clear_depth
)
120 || __put_user(clr32
.color_mask
, &clr
->color_mask
)
121 || __put_user(clr32
.depth_mask
, &clr
->depth_mask
)
122 || __put_user((void __user
*)(unsigned long)clr32
.depth_boxes
,
126 return drm_ioctl(file
, DRM_IOCTL_RADEON_CLEAR
, (unsigned long)clr
);
129 typedef struct drm_radeon_stipple32
{
131 } drm_radeon_stipple32_t
;
133 static int compat_radeon_cp_stipple(struct file
*file
, unsigned int cmd
,
136 drm_radeon_stipple32_t __user
*argp
= (void __user
*)arg
;
137 drm_radeon_stipple_t __user
*request
;
140 if (get_user(mask
, &argp
->mask
))
143 request
= compat_alloc_user_space(sizeof(*request
));
144 if (!access_ok(VERIFY_WRITE
, request
, sizeof(*request
))
145 || __put_user((unsigned int __user
*)(unsigned long)mask
,
149 return drm_ioctl(file
, DRM_IOCTL_RADEON_STIPPLE
, (unsigned long)request
);
152 typedef struct drm_radeon_tex_image32
{
153 unsigned int x
, y
; /* Blit coordinates */
154 unsigned int width
, height
;
156 } drm_radeon_tex_image32_t
;
158 typedef struct drm_radeon_texture32
{
162 int width
; /* Texture image coordinates */
165 } drm_radeon_texture32_t
;
167 static int compat_radeon_cp_texture(struct file
*file
, unsigned int cmd
,
170 drm_radeon_texture32_t req32
;
171 drm_radeon_texture_t __user
*request
;
172 drm_radeon_tex_image32_t img32
;
173 drm_radeon_tex_image_t __user
*image
;
175 if (copy_from_user(&req32
, (void __user
*)arg
, sizeof(req32
)))
177 if (req32
.image
== 0)
179 if (copy_from_user(&img32
, (void __user
*)(unsigned long)req32
.image
,
183 request
= compat_alloc_user_space(sizeof(*request
) + sizeof(*image
));
184 if (!access_ok(VERIFY_WRITE
, request
,
185 sizeof(*request
) + sizeof(*image
)))
187 image
= (drm_radeon_tex_image_t __user
*) (request
+ 1);
189 if (__put_user(req32
.offset
, &request
->offset
)
190 || __put_user(req32
.pitch
, &request
->pitch
)
191 || __put_user(req32
.format
, &request
->format
)
192 || __put_user(req32
.width
, &request
->width
)
193 || __put_user(req32
.height
, &request
->height
)
194 || __put_user(image
, &request
->image
)
195 || __put_user(img32
.x
, &image
->x
)
196 || __put_user(img32
.y
, &image
->y
)
197 || __put_user(img32
.width
, &image
->width
)
198 || __put_user(img32
.height
, &image
->height
)
199 || __put_user((const void __user
*)(unsigned long)img32
.data
,
203 return drm_ioctl(file
, DRM_IOCTL_RADEON_TEXTURE
, (unsigned long)request
);
206 typedef struct drm_radeon_vertex2_32
{
207 int idx
; /* Index of vertex buffer */
208 int discard
; /* Client finished with buffer? */
213 } drm_radeon_vertex2_32_t
;
215 static int compat_radeon_cp_vertex2(struct file
*file
, unsigned int cmd
,
218 drm_radeon_vertex2_32_t req32
;
219 drm_radeon_vertex2_t __user
*request
;
221 if (copy_from_user(&req32
, (void __user
*)arg
, sizeof(req32
)))
224 request
= compat_alloc_user_space(sizeof(*request
));
225 if (!access_ok(VERIFY_WRITE
, request
, sizeof(*request
))
226 || __put_user(req32
.idx
, &request
->idx
)
227 || __put_user(req32
.discard
, &request
->discard
)
228 || __put_user(req32
.nr_states
, &request
->nr_states
)
229 || __put_user((void __user
*)(unsigned long)req32
.state
,
231 || __put_user(req32
.nr_prims
, &request
->nr_prims
)
232 || __put_user((void __user
*)(unsigned long)req32
.prim
,
236 return drm_ioctl(file
, DRM_IOCTL_RADEON_VERTEX2
, (unsigned long)request
);
239 typedef struct drm_radeon_cmd_buffer32
{
244 } drm_radeon_cmd_buffer32_t
;
246 static int compat_radeon_cp_cmdbuf(struct file
*file
, unsigned int cmd
,
249 drm_radeon_cmd_buffer32_t req32
;
250 drm_radeon_cmd_buffer_t __user
*request
;
252 if (copy_from_user(&req32
, (void __user
*)arg
, sizeof(req32
)))
255 request
= compat_alloc_user_space(sizeof(*request
));
256 if (!access_ok(VERIFY_WRITE
, request
, sizeof(*request
))
257 || __put_user(req32
.bufsz
, &request
->bufsz
)
258 || __put_user((void __user
*)(unsigned long)req32
.buf
,
260 || __put_user(req32
.nbox
, &request
->nbox
)
261 || __put_user((void __user
*)(unsigned long)req32
.boxes
,
265 return drm_ioctl(file
, DRM_IOCTL_RADEON_CMDBUF
, (unsigned long)request
);
268 typedef struct drm_radeon_getparam32
{
271 } drm_radeon_getparam32_t
;
273 static int compat_radeon_cp_getparam(struct file
*file
, unsigned int cmd
,
276 drm_radeon_getparam32_t req32
;
277 drm_radeon_getparam_t __user
*request
;
279 if (copy_from_user(&req32
, (void __user
*)arg
, sizeof(req32
)))
282 request
= compat_alloc_user_space(sizeof(*request
));
283 if (!access_ok(VERIFY_WRITE
, request
, sizeof(*request
))
284 || __put_user(req32
.param
, &request
->param
)
285 || __put_user((void __user
*)(unsigned long)req32
.value
,
289 return drm_ioctl(file
, DRM_IOCTL_RADEON_GETPARAM
, (unsigned long)request
);
292 typedef struct drm_radeon_mem_alloc32
{
296 u32 region_offset
; /* offset from start of fb or GART */
297 } drm_radeon_mem_alloc32_t
;
299 static int compat_radeon_mem_alloc(struct file
*file
, unsigned int cmd
,
302 drm_radeon_mem_alloc32_t req32
;
303 drm_radeon_mem_alloc_t __user
*request
;
305 if (copy_from_user(&req32
, (void __user
*)arg
, sizeof(req32
)))
308 request
= compat_alloc_user_space(sizeof(*request
));
309 if (!access_ok(VERIFY_WRITE
, request
, sizeof(*request
))
310 || __put_user(req32
.region
, &request
->region
)
311 || __put_user(req32
.alignment
, &request
->alignment
)
312 || __put_user(req32
.size
, &request
->size
)
313 || __put_user((int __user
*)(unsigned long)req32
.region_offset
,
314 &request
->region_offset
))
317 return drm_ioctl(file
, DRM_IOCTL_RADEON_ALLOC
, (unsigned long)request
);
320 typedef struct drm_radeon_irq_emit32
{
322 } drm_radeon_irq_emit32_t
;
324 static int compat_radeon_irq_emit(struct file
*file
, unsigned int cmd
,
327 drm_radeon_irq_emit32_t req32
;
328 drm_radeon_irq_emit_t __user
*request
;
330 if (copy_from_user(&req32
, (void __user
*)arg
, sizeof(req32
)))
333 request
= compat_alloc_user_space(sizeof(*request
));
334 if (!access_ok(VERIFY_WRITE
, request
, sizeof(*request
))
335 || __put_user((int __user
*)(unsigned long)req32
.irq_seq
,
339 return drm_ioctl(file
, DRM_IOCTL_RADEON_IRQ_EMIT
, (unsigned long)request
);
342 /* The two 64-bit arches where alignof(u64)==4 in 32-bit code */
343 #if defined (CONFIG_X86_64) || defined(CONFIG_IA64)
344 typedef struct drm_radeon_setparam32
{
347 } __attribute__((packed
)) drm_radeon_setparam32_t
;
349 static int compat_radeon_cp_setparam(struct file
*file
, unsigned int cmd
,
352 drm_radeon_setparam32_t req32
;
353 drm_radeon_setparam_t __user
*request
;
355 if (copy_from_user(&req32
, (void __user
*) arg
, sizeof(req32
)))
358 request
= compat_alloc_user_space(sizeof(*request
));
359 if (!access_ok(VERIFY_WRITE
, request
, sizeof(*request
))
360 || __put_user(req32
.param
, &request
->param
)
361 || __put_user((void __user
*)(unsigned long)req32
.value
,
365 return drm_ioctl(file
, DRM_IOCTL_RADEON_SETPARAM
, (unsigned long) request
);
368 #define compat_radeon_cp_setparam NULL
369 #endif /* X86_64 || IA64 */
371 static drm_ioctl_compat_t
*radeon_compat_ioctls
[] = {
372 [DRM_RADEON_CP_INIT
] = compat_radeon_cp_init
,
373 [DRM_RADEON_CLEAR
] = compat_radeon_cp_clear
,
374 [DRM_RADEON_STIPPLE
] = compat_radeon_cp_stipple
,
375 [DRM_RADEON_TEXTURE
] = compat_radeon_cp_texture
,
376 [DRM_RADEON_VERTEX2
] = compat_radeon_cp_vertex2
,
377 [DRM_RADEON_CMDBUF
] = compat_radeon_cp_cmdbuf
,
378 [DRM_RADEON_GETPARAM
] = compat_radeon_cp_getparam
,
379 [DRM_RADEON_SETPARAM
] = compat_radeon_cp_setparam
,
380 [DRM_RADEON_ALLOC
] = compat_radeon_mem_alloc
,
381 [DRM_RADEON_IRQ_EMIT
] = compat_radeon_irq_emit
,
385 * Called whenever a 32-bit process running under a 64-bit kernel
386 * performs an ioctl on /dev/dri/card<n>.
388 * \param filp file pointer.
389 * \param cmd command.
390 * \param arg user argument.
391 * \return zero on success or negative number on failure.
393 long radeon_compat_ioctl(struct file
*filp
, unsigned int cmd
, unsigned long arg
)
395 unsigned int nr
= DRM_IOCTL_NR(cmd
);
396 drm_ioctl_compat_t
*fn
= NULL
;
399 if (nr
< DRM_COMMAND_BASE
)
400 return drm_compat_ioctl(filp
, cmd
, arg
);
402 if (nr
< DRM_COMMAND_BASE
+ ARRAY_SIZE(radeon_compat_ioctls
))
403 fn
= radeon_compat_ioctls
[nr
- DRM_COMMAND_BASE
];
406 ret
= (*fn
) (filp
, cmd
, arg
);
408 ret
= drm_ioctl(filp
, cmd
, arg
);
413 long radeon_kms_compat_ioctl(struct file
*filp
, unsigned int cmd
, unsigned long arg
)
415 unsigned int nr
= DRM_IOCTL_NR(cmd
);
418 if (nr
< DRM_COMMAND_BASE
)
419 return drm_compat_ioctl(filp
, cmd
, arg
);
421 ret
= radeon_drm_ioctl(filp
, cmd
, arg
);