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
, DRM_IOCTL_RADEON_CP_INIT
, (unsigned long)init
);
98 typedef struct drm_radeon_clear32
{
100 unsigned int clear_color
;
101 unsigned int clear_depth
;
102 unsigned int color_mask
;
103 unsigned int depth_mask
; /* misnamed field: should be stencil */
105 } drm_radeon_clear32_t
;
107 static int compat_radeon_cp_clear(struct file
*file
, unsigned int cmd
,
110 drm_radeon_clear32_t clr32
;
111 drm_radeon_clear_t __user
*clr
;
113 if (copy_from_user(&clr32
, (void __user
*)arg
, sizeof(clr32
)))
116 clr
= compat_alloc_user_space(sizeof(*clr
));
117 if (!access_ok(VERIFY_WRITE
, clr
, sizeof(*clr
))
118 || __put_user(clr32
.flags
, &clr
->flags
)
119 || __put_user(clr32
.clear_color
, &clr
->clear_color
)
120 || __put_user(clr32
.clear_depth
, &clr
->clear_depth
)
121 || __put_user(clr32
.color_mask
, &clr
->color_mask
)
122 || __put_user(clr32
.depth_mask
, &clr
->depth_mask
)
123 || __put_user((void __user
*)(unsigned long)clr32
.depth_boxes
,
127 return drm_ioctl(file
, DRM_IOCTL_RADEON_CLEAR
, (unsigned long)clr
);
130 typedef struct drm_radeon_stipple32
{
132 } drm_radeon_stipple32_t
;
134 static int compat_radeon_cp_stipple(struct file
*file
, unsigned int cmd
,
137 drm_radeon_stipple32_t __user
*argp
= (void __user
*)arg
;
138 drm_radeon_stipple_t __user
*request
;
141 if (get_user(mask
, &argp
->mask
))
144 request
= compat_alloc_user_space(sizeof(*request
));
145 if (!access_ok(VERIFY_WRITE
, request
, sizeof(*request
))
146 || __put_user((unsigned int __user
*)(unsigned long)mask
,
150 return drm_ioctl(file
, DRM_IOCTL_RADEON_STIPPLE
, (unsigned long)request
);
153 typedef struct drm_radeon_tex_image32
{
154 unsigned int x
, y
; /* Blit coordinates */
155 unsigned int width
, height
;
157 } drm_radeon_tex_image32_t
;
159 typedef struct drm_radeon_texture32
{
163 int width
; /* Texture image coordinates */
166 } drm_radeon_texture32_t
;
168 static int compat_radeon_cp_texture(struct file
*file
, unsigned int cmd
,
171 drm_radeon_texture32_t req32
;
172 drm_radeon_texture_t __user
*request
;
173 drm_radeon_tex_image32_t img32
;
174 drm_radeon_tex_image_t __user
*image
;
176 if (copy_from_user(&req32
, (void __user
*)arg
, sizeof(req32
)))
178 if (req32
.image
== 0)
180 if (copy_from_user(&img32
, (void __user
*)(unsigned long)req32
.image
,
184 request
= compat_alloc_user_space(sizeof(*request
) + sizeof(*image
));
185 if (!access_ok(VERIFY_WRITE
, request
,
186 sizeof(*request
) + sizeof(*image
)))
188 image
= (drm_radeon_tex_image_t __user
*) (request
+ 1);
190 if (__put_user(req32
.offset
, &request
->offset
)
191 || __put_user(req32
.pitch
, &request
->pitch
)
192 || __put_user(req32
.format
, &request
->format
)
193 || __put_user(req32
.width
, &request
->width
)
194 || __put_user(req32
.height
, &request
->height
)
195 || __put_user(image
, &request
->image
)
196 || __put_user(img32
.x
, &image
->x
)
197 || __put_user(img32
.y
, &image
->y
)
198 || __put_user(img32
.width
, &image
->width
)
199 || __put_user(img32
.height
, &image
->height
)
200 || __put_user((const void __user
*)(unsigned long)img32
.data
,
204 return drm_ioctl(file
, DRM_IOCTL_RADEON_TEXTURE
, (unsigned long)request
);
207 typedef struct drm_radeon_vertex2_32
{
208 int idx
; /* Index of vertex buffer */
209 int discard
; /* Client finished with buffer? */
214 } drm_radeon_vertex2_32_t
;
216 static int compat_radeon_cp_vertex2(struct file
*file
, unsigned int cmd
,
219 drm_radeon_vertex2_32_t req32
;
220 drm_radeon_vertex2_t __user
*request
;
222 if (copy_from_user(&req32
, (void __user
*)arg
, sizeof(req32
)))
225 request
= compat_alloc_user_space(sizeof(*request
));
226 if (!access_ok(VERIFY_WRITE
, request
, sizeof(*request
))
227 || __put_user(req32
.idx
, &request
->idx
)
228 || __put_user(req32
.discard
, &request
->discard
)
229 || __put_user(req32
.nr_states
, &request
->nr_states
)
230 || __put_user((void __user
*)(unsigned long)req32
.state
,
232 || __put_user(req32
.nr_prims
, &request
->nr_prims
)
233 || __put_user((void __user
*)(unsigned long)req32
.prim
,
237 return drm_ioctl(file
, DRM_IOCTL_RADEON_VERTEX2
, (unsigned long)request
);
240 typedef struct drm_radeon_cmd_buffer32
{
245 } drm_radeon_cmd_buffer32_t
;
247 static int compat_radeon_cp_cmdbuf(struct file
*file
, unsigned int cmd
,
250 drm_radeon_cmd_buffer32_t req32
;
251 drm_radeon_cmd_buffer_t __user
*request
;
253 if (copy_from_user(&req32
, (void __user
*)arg
, sizeof(req32
)))
256 request
= compat_alloc_user_space(sizeof(*request
));
257 if (!access_ok(VERIFY_WRITE
, request
, sizeof(*request
))
258 || __put_user(req32
.bufsz
, &request
->bufsz
)
259 || __put_user((void __user
*)(unsigned long)req32
.buf
,
261 || __put_user(req32
.nbox
, &request
->nbox
)
262 || __put_user((void __user
*)(unsigned long)req32
.boxes
,
266 return drm_ioctl(file
, DRM_IOCTL_RADEON_CMDBUF
, (unsigned long)request
);
269 typedef struct drm_radeon_getparam32
{
272 } drm_radeon_getparam32_t
;
274 static int compat_radeon_cp_getparam(struct file
*file
, unsigned int cmd
,
277 drm_radeon_getparam32_t req32
;
278 drm_radeon_getparam_t __user
*request
;
280 if (copy_from_user(&req32
, (void __user
*)arg
, sizeof(req32
)))
283 request
= compat_alloc_user_space(sizeof(*request
));
284 if (!access_ok(VERIFY_WRITE
, request
, sizeof(*request
))
285 || __put_user(req32
.param
, &request
->param
)
286 || __put_user((void __user
*)(unsigned long)req32
.value
,
290 return drm_ioctl(file
, DRM_IOCTL_RADEON_GETPARAM
, (unsigned long)request
);
293 typedef struct drm_radeon_mem_alloc32
{
297 u32 region_offset
; /* offset from start of fb or GART */
298 } drm_radeon_mem_alloc32_t
;
300 static int compat_radeon_mem_alloc(struct file
*file
, unsigned int cmd
,
303 drm_radeon_mem_alloc32_t req32
;
304 drm_radeon_mem_alloc_t __user
*request
;
306 if (copy_from_user(&req32
, (void __user
*)arg
, sizeof(req32
)))
309 request
= compat_alloc_user_space(sizeof(*request
));
310 if (!access_ok(VERIFY_WRITE
, request
, sizeof(*request
))
311 || __put_user(req32
.region
, &request
->region
)
312 || __put_user(req32
.alignment
, &request
->alignment
)
313 || __put_user(req32
.size
, &request
->size
)
314 || __put_user((int __user
*)(unsigned long)req32
.region_offset
,
315 &request
->region_offset
))
318 return drm_ioctl(file
, DRM_IOCTL_RADEON_ALLOC
, (unsigned long)request
);
321 typedef struct drm_radeon_irq_emit32
{
323 } drm_radeon_irq_emit32_t
;
325 static int compat_radeon_irq_emit(struct file
*file
, unsigned int cmd
,
328 drm_radeon_irq_emit32_t req32
;
329 drm_radeon_irq_emit_t __user
*request
;
331 if (copy_from_user(&req32
, (void __user
*)arg
, sizeof(req32
)))
334 request
= compat_alloc_user_space(sizeof(*request
));
335 if (!access_ok(VERIFY_WRITE
, request
, sizeof(*request
))
336 || __put_user((int __user
*)(unsigned long)req32
.irq_seq
,
340 return drm_ioctl(file
, DRM_IOCTL_RADEON_IRQ_EMIT
, (unsigned long)request
);
343 /* The two 64-bit arches where alignof(u64)==4 in 32-bit code */
344 #if defined (CONFIG_X86_64) || defined(CONFIG_IA64)
345 typedef struct drm_radeon_setparam32
{
348 } __attribute__((packed
)) drm_radeon_setparam32_t
;
350 static int compat_radeon_cp_setparam(struct file
*file
, unsigned int cmd
,
353 drm_radeon_setparam32_t req32
;
354 drm_radeon_setparam_t __user
*request
;
356 if (copy_from_user(&req32
, (void __user
*) arg
, sizeof(req32
)))
359 request
= compat_alloc_user_space(sizeof(*request
));
360 if (!access_ok(VERIFY_WRITE
, request
, sizeof(*request
))
361 || __put_user(req32
.param
, &request
->param
)
362 || __put_user((void __user
*)(unsigned long)req32
.value
,
366 return drm_ioctl(file
, DRM_IOCTL_RADEON_SETPARAM
, (unsigned long) request
);
369 #define compat_radeon_cp_setparam NULL
370 #endif /* X86_64 || IA64 */
372 drm_ioctl_compat_t
*radeon_compat_ioctls
[] = {
373 [DRM_RADEON_CP_INIT
] = compat_radeon_cp_init
,
374 [DRM_RADEON_CLEAR
] = compat_radeon_cp_clear
,
375 [DRM_RADEON_STIPPLE
] = compat_radeon_cp_stipple
,
376 [DRM_RADEON_TEXTURE
] = compat_radeon_cp_texture
,
377 [DRM_RADEON_VERTEX2
] = compat_radeon_cp_vertex2
,
378 [DRM_RADEON_CMDBUF
] = compat_radeon_cp_cmdbuf
,
379 [DRM_RADEON_GETPARAM
] = compat_radeon_cp_getparam
,
380 [DRM_RADEON_SETPARAM
] = compat_radeon_cp_setparam
,
381 [DRM_RADEON_ALLOC
] = compat_radeon_mem_alloc
,
382 [DRM_RADEON_IRQ_EMIT
] = compat_radeon_irq_emit
,
386 * Called whenever a 32-bit process running under a 64-bit kernel
387 * performs an ioctl on /dev/dri/card<n>.
389 * \param filp file pointer.
390 * \param cmd command.
391 * \param arg user argument.
392 * \return zero on success or negative number on failure.
394 long radeon_compat_ioctl(struct file
*filp
, unsigned int cmd
, unsigned long arg
)
396 unsigned int nr
= DRM_IOCTL_NR(cmd
);
397 drm_ioctl_compat_t
*fn
= NULL
;
400 if (nr
< DRM_COMMAND_BASE
)
401 return drm_compat_ioctl(filp
, cmd
, arg
);
403 if (nr
< DRM_COMMAND_BASE
+ DRM_ARRAY_SIZE(radeon_compat_ioctls
))
404 fn
= radeon_compat_ioctls
[nr
- DRM_COMMAND_BASE
];
407 ret
= (*fn
) (filp
, cmd
, arg
);
409 ret
= drm_ioctl(filp
, cmd
, arg
);
414 long radeon_kms_compat_ioctl(struct file
*filp
, unsigned int cmd
, unsigned long arg
)
416 unsigned int nr
= DRM_IOCTL_NR(cmd
);
419 if (nr
< DRM_COMMAND_BASE
)
420 return drm_compat_ioctl(filp
, cmd
, arg
);
422 ret
= drm_ioctl(filp
, cmd
, arg
);