xref: /openbmc/linux/drivers/gpu/drm/i915/i915_ioc32.c (revision c0e09200dc0813972442e550a5905a132768e56c)
1*c0e09200SDave Airlie /**
2*c0e09200SDave Airlie  * \file i915_ioc32.c
3*c0e09200SDave Airlie  *
4*c0e09200SDave Airlie  * 32-bit ioctl compatibility routines for the i915 DRM.
5*c0e09200SDave Airlie  *
6*c0e09200SDave Airlie  * \author Alan Hourihane <alanh@fairlite.demon.co.uk>
7*c0e09200SDave Airlie  *
8*c0e09200SDave Airlie  *
9*c0e09200SDave Airlie  * Copyright (C) Paul Mackerras 2005
10*c0e09200SDave Airlie  * Copyright (C) Alan Hourihane 2005
11*c0e09200SDave Airlie  * All Rights Reserved.
12*c0e09200SDave Airlie  *
13*c0e09200SDave Airlie  * Permission is hereby granted, free of charge, to any person obtaining a
14*c0e09200SDave Airlie  * copy of this software and associated documentation files (the "Software"),
15*c0e09200SDave Airlie  * to deal in the Software without restriction, including without limitation
16*c0e09200SDave Airlie  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
17*c0e09200SDave Airlie  * and/or sell copies of the Software, and to permit persons to whom the
18*c0e09200SDave Airlie  * Software is furnished to do so, subject to the following conditions:
19*c0e09200SDave Airlie  *
20*c0e09200SDave Airlie  * The above copyright notice and this permission notice (including the next
21*c0e09200SDave Airlie  * paragraph) shall be included in all copies or substantial portions of the
22*c0e09200SDave Airlie  * Software.
23*c0e09200SDave Airlie  *
24*c0e09200SDave Airlie  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25*c0e09200SDave Airlie  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26*c0e09200SDave Airlie  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
27*c0e09200SDave Airlie  * THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
28*c0e09200SDave Airlie  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29*c0e09200SDave Airlie  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
30*c0e09200SDave Airlie  * IN THE SOFTWARE.
31*c0e09200SDave Airlie  */
32*c0e09200SDave Airlie #include <linux/compat.h>
33*c0e09200SDave Airlie 
34*c0e09200SDave Airlie #include "drmP.h"
35*c0e09200SDave Airlie #include "drm.h"
36*c0e09200SDave Airlie #include "i915_drm.h"
37*c0e09200SDave Airlie 
38*c0e09200SDave Airlie typedef struct _drm_i915_batchbuffer32 {
39*c0e09200SDave Airlie 	int start;		/* agp offset */
40*c0e09200SDave Airlie 	int used;		/* nr bytes in use */
41*c0e09200SDave Airlie 	int DR1;		/* hw flags for GFX_OP_DRAWRECT_INFO */
42*c0e09200SDave Airlie 	int DR4;		/* window origin for GFX_OP_DRAWRECT_INFO */
43*c0e09200SDave Airlie 	int num_cliprects;	/* mulitpass with multiple cliprects? */
44*c0e09200SDave Airlie 	u32 cliprects;		/* pointer to userspace cliprects */
45*c0e09200SDave Airlie } drm_i915_batchbuffer32_t;
46*c0e09200SDave Airlie 
47*c0e09200SDave Airlie static int compat_i915_batchbuffer(struct file *file, unsigned int cmd,
48*c0e09200SDave Airlie 				   unsigned long arg)
49*c0e09200SDave Airlie {
50*c0e09200SDave Airlie 	drm_i915_batchbuffer32_t batchbuffer32;
51*c0e09200SDave Airlie 	drm_i915_batchbuffer_t __user *batchbuffer;
52*c0e09200SDave Airlie 
53*c0e09200SDave Airlie 	if (copy_from_user
54*c0e09200SDave Airlie 	    (&batchbuffer32, (void __user *)arg, sizeof(batchbuffer32)))
55*c0e09200SDave Airlie 		return -EFAULT;
56*c0e09200SDave Airlie 
57*c0e09200SDave Airlie 	batchbuffer = compat_alloc_user_space(sizeof(*batchbuffer));
58*c0e09200SDave Airlie 	if (!access_ok(VERIFY_WRITE, batchbuffer, sizeof(*batchbuffer))
59*c0e09200SDave Airlie 	    || __put_user(batchbuffer32.start, &batchbuffer->start)
60*c0e09200SDave Airlie 	    || __put_user(batchbuffer32.used, &batchbuffer->used)
61*c0e09200SDave Airlie 	    || __put_user(batchbuffer32.DR1, &batchbuffer->DR1)
62*c0e09200SDave Airlie 	    || __put_user(batchbuffer32.DR4, &batchbuffer->DR4)
63*c0e09200SDave Airlie 	    || __put_user(batchbuffer32.num_cliprects,
64*c0e09200SDave Airlie 			  &batchbuffer->num_cliprects)
65*c0e09200SDave Airlie 	    || __put_user((int __user *)(unsigned long)batchbuffer32.cliprects,
66*c0e09200SDave Airlie 			  &batchbuffer->cliprects))
67*c0e09200SDave Airlie 		return -EFAULT;
68*c0e09200SDave Airlie 
69*c0e09200SDave Airlie 	return drm_ioctl(file->f_path.dentry->d_inode, file,
70*c0e09200SDave Airlie 			 DRM_IOCTL_I915_BATCHBUFFER,
71*c0e09200SDave Airlie 			 (unsigned long)batchbuffer);
72*c0e09200SDave Airlie }
73*c0e09200SDave Airlie 
74*c0e09200SDave Airlie typedef struct _drm_i915_cmdbuffer32 {
75*c0e09200SDave Airlie 	u32 buf;		/* pointer to userspace command buffer */
76*c0e09200SDave Airlie 	int sz;			/* nr bytes in buf */
77*c0e09200SDave Airlie 	int DR1;		/* hw flags for GFX_OP_DRAWRECT_INFO */
78*c0e09200SDave Airlie 	int DR4;		/* window origin for GFX_OP_DRAWRECT_INFO */
79*c0e09200SDave Airlie 	int num_cliprects;	/* mulitpass with multiple cliprects? */
80*c0e09200SDave Airlie 	u32 cliprects;		/* pointer to userspace cliprects */
81*c0e09200SDave Airlie } drm_i915_cmdbuffer32_t;
82*c0e09200SDave Airlie 
83*c0e09200SDave Airlie static int compat_i915_cmdbuffer(struct file *file, unsigned int cmd,
84*c0e09200SDave Airlie 				 unsigned long arg)
85*c0e09200SDave Airlie {
86*c0e09200SDave Airlie 	drm_i915_cmdbuffer32_t cmdbuffer32;
87*c0e09200SDave Airlie 	drm_i915_cmdbuffer_t __user *cmdbuffer;
88*c0e09200SDave Airlie 
89*c0e09200SDave Airlie 	if (copy_from_user
90*c0e09200SDave Airlie 	    (&cmdbuffer32, (void __user *)arg, sizeof(cmdbuffer32)))
91*c0e09200SDave Airlie 		return -EFAULT;
92*c0e09200SDave Airlie 
93*c0e09200SDave Airlie 	cmdbuffer = compat_alloc_user_space(sizeof(*cmdbuffer));
94*c0e09200SDave Airlie 	if (!access_ok(VERIFY_WRITE, cmdbuffer, sizeof(*cmdbuffer))
95*c0e09200SDave Airlie 	    || __put_user((int __user *)(unsigned long)cmdbuffer32.buf,
96*c0e09200SDave Airlie 			  &cmdbuffer->buf)
97*c0e09200SDave Airlie 	    || __put_user(cmdbuffer32.sz, &cmdbuffer->sz)
98*c0e09200SDave Airlie 	    || __put_user(cmdbuffer32.DR1, &cmdbuffer->DR1)
99*c0e09200SDave Airlie 	    || __put_user(cmdbuffer32.DR4, &cmdbuffer->DR4)
100*c0e09200SDave Airlie 	    || __put_user(cmdbuffer32.num_cliprects, &cmdbuffer->num_cliprects)
101*c0e09200SDave Airlie 	    || __put_user((int __user *)(unsigned long)cmdbuffer32.cliprects,
102*c0e09200SDave Airlie 			  &cmdbuffer->cliprects))
103*c0e09200SDave Airlie 		return -EFAULT;
104*c0e09200SDave Airlie 
105*c0e09200SDave Airlie 	return drm_ioctl(file->f_path.dentry->d_inode, file,
106*c0e09200SDave Airlie 			 DRM_IOCTL_I915_CMDBUFFER, (unsigned long)cmdbuffer);
107*c0e09200SDave Airlie }
108*c0e09200SDave Airlie 
109*c0e09200SDave Airlie typedef struct drm_i915_irq_emit32 {
110*c0e09200SDave Airlie 	u32 irq_seq;
111*c0e09200SDave Airlie } drm_i915_irq_emit32_t;
112*c0e09200SDave Airlie 
113*c0e09200SDave Airlie static int compat_i915_irq_emit(struct file *file, unsigned int cmd,
114*c0e09200SDave Airlie 				unsigned long arg)
115*c0e09200SDave Airlie {
116*c0e09200SDave Airlie 	drm_i915_irq_emit32_t req32;
117*c0e09200SDave Airlie 	drm_i915_irq_emit_t __user *request;
118*c0e09200SDave Airlie 
119*c0e09200SDave Airlie 	if (copy_from_user(&req32, (void __user *)arg, sizeof(req32)))
120*c0e09200SDave Airlie 		return -EFAULT;
121*c0e09200SDave Airlie 
122*c0e09200SDave Airlie 	request = compat_alloc_user_space(sizeof(*request));
123*c0e09200SDave Airlie 	if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
124*c0e09200SDave Airlie 	    || __put_user((int __user *)(unsigned long)req32.irq_seq,
125*c0e09200SDave Airlie 			  &request->irq_seq))
126*c0e09200SDave Airlie 		return -EFAULT;
127*c0e09200SDave Airlie 
128*c0e09200SDave Airlie 	return drm_ioctl(file->f_path.dentry->d_inode, file,
129*c0e09200SDave Airlie 			 DRM_IOCTL_I915_IRQ_EMIT, (unsigned long)request);
130*c0e09200SDave Airlie }
131*c0e09200SDave Airlie typedef struct drm_i915_getparam32 {
132*c0e09200SDave Airlie 	int param;
133*c0e09200SDave Airlie 	u32 value;
134*c0e09200SDave Airlie } drm_i915_getparam32_t;
135*c0e09200SDave Airlie 
136*c0e09200SDave Airlie static int compat_i915_getparam(struct file *file, unsigned int cmd,
137*c0e09200SDave Airlie 				unsigned long arg)
138*c0e09200SDave Airlie {
139*c0e09200SDave Airlie 	drm_i915_getparam32_t req32;
140*c0e09200SDave Airlie 	drm_i915_getparam_t __user *request;
141*c0e09200SDave Airlie 
142*c0e09200SDave Airlie 	if (copy_from_user(&req32, (void __user *)arg, sizeof(req32)))
143*c0e09200SDave Airlie 		return -EFAULT;
144*c0e09200SDave Airlie 
145*c0e09200SDave Airlie 	request = compat_alloc_user_space(sizeof(*request));
146*c0e09200SDave Airlie 	if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
147*c0e09200SDave Airlie 	    || __put_user(req32.param, &request->param)
148*c0e09200SDave Airlie 	    || __put_user((void __user *)(unsigned long)req32.value,
149*c0e09200SDave Airlie 			  &request->value))
150*c0e09200SDave Airlie 		return -EFAULT;
151*c0e09200SDave Airlie 
152*c0e09200SDave Airlie 	return drm_ioctl(file->f_path.dentry->d_inode, file,
153*c0e09200SDave Airlie 			 DRM_IOCTL_I915_GETPARAM, (unsigned long)request);
154*c0e09200SDave Airlie }
155*c0e09200SDave Airlie 
156*c0e09200SDave Airlie typedef struct drm_i915_mem_alloc32 {
157*c0e09200SDave Airlie 	int region;
158*c0e09200SDave Airlie 	int alignment;
159*c0e09200SDave Airlie 	int size;
160*c0e09200SDave Airlie 	u32 region_offset;	/* offset from start of fb or agp */
161*c0e09200SDave Airlie } drm_i915_mem_alloc32_t;
162*c0e09200SDave Airlie 
163*c0e09200SDave Airlie static int compat_i915_alloc(struct file *file, unsigned int cmd,
164*c0e09200SDave Airlie 			     unsigned long arg)
165*c0e09200SDave Airlie {
166*c0e09200SDave Airlie 	drm_i915_mem_alloc32_t req32;
167*c0e09200SDave Airlie 	drm_i915_mem_alloc_t __user *request;
168*c0e09200SDave Airlie 
169*c0e09200SDave Airlie 	if (copy_from_user(&req32, (void __user *)arg, sizeof(req32)))
170*c0e09200SDave Airlie 		return -EFAULT;
171*c0e09200SDave Airlie 
172*c0e09200SDave Airlie 	request = compat_alloc_user_space(sizeof(*request));
173*c0e09200SDave Airlie 	if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
174*c0e09200SDave Airlie 	    || __put_user(req32.region, &request->region)
175*c0e09200SDave Airlie 	    || __put_user(req32.alignment, &request->alignment)
176*c0e09200SDave Airlie 	    || __put_user(req32.size, &request->size)
177*c0e09200SDave Airlie 	    || __put_user((void __user *)(unsigned long)req32.region_offset,
178*c0e09200SDave Airlie 			  &request->region_offset))
179*c0e09200SDave Airlie 		return -EFAULT;
180*c0e09200SDave Airlie 
181*c0e09200SDave Airlie 	return drm_ioctl(file->f_path.dentry->d_inode, file,
182*c0e09200SDave Airlie 			 DRM_IOCTL_I915_ALLOC, (unsigned long)request);
183*c0e09200SDave Airlie }
184*c0e09200SDave Airlie 
185*c0e09200SDave Airlie drm_ioctl_compat_t *i915_compat_ioctls[] = {
186*c0e09200SDave Airlie 	[DRM_I915_BATCHBUFFER] = compat_i915_batchbuffer,
187*c0e09200SDave Airlie 	[DRM_I915_CMDBUFFER] = compat_i915_cmdbuffer,
188*c0e09200SDave Airlie 	[DRM_I915_GETPARAM] = compat_i915_getparam,
189*c0e09200SDave Airlie 	[DRM_I915_IRQ_EMIT] = compat_i915_irq_emit,
190*c0e09200SDave Airlie 	[DRM_I915_ALLOC] = compat_i915_alloc
191*c0e09200SDave Airlie };
192*c0e09200SDave Airlie 
193*c0e09200SDave Airlie /**
194*c0e09200SDave Airlie  * Called whenever a 32-bit process running under a 64-bit kernel
195*c0e09200SDave Airlie  * performs an ioctl on /dev/dri/card<n>.
196*c0e09200SDave Airlie  *
197*c0e09200SDave Airlie  * \param filp file pointer.
198*c0e09200SDave Airlie  * \param cmd command.
199*c0e09200SDave Airlie  * \param arg user argument.
200*c0e09200SDave Airlie  * \return zero on success or negative number on failure.
201*c0e09200SDave Airlie  */
202*c0e09200SDave Airlie long i915_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
203*c0e09200SDave Airlie {
204*c0e09200SDave Airlie 	unsigned int nr = DRM_IOCTL_NR(cmd);
205*c0e09200SDave Airlie 	drm_ioctl_compat_t *fn = NULL;
206*c0e09200SDave Airlie 	int ret;
207*c0e09200SDave Airlie 
208*c0e09200SDave Airlie 	if (nr < DRM_COMMAND_BASE)
209*c0e09200SDave Airlie 		return drm_compat_ioctl(filp, cmd, arg);
210*c0e09200SDave Airlie 
211*c0e09200SDave Airlie 	if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(i915_compat_ioctls))
212*c0e09200SDave Airlie 		fn = i915_compat_ioctls[nr - DRM_COMMAND_BASE];
213*c0e09200SDave Airlie 
214*c0e09200SDave Airlie 	lock_kernel();		/* XXX for now */
215*c0e09200SDave Airlie 	if (fn != NULL)
216*c0e09200SDave Airlie 		ret = (*fn) (filp, cmd, arg);
217*c0e09200SDave Airlie 	else
218*c0e09200SDave Airlie 		ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg);
219*c0e09200SDave Airlie 	unlock_kernel();
220*c0e09200SDave Airlie 
221*c0e09200SDave Airlie 	return ret;
222*c0e09200SDave Airlie }
223