mga_ioc32.c revision 1.1.1.2.30.1 1 /* $NetBSD: mga_ioc32.c,v 1.1.1.2.30.1 2019/06/10 22:08:06 christos Exp $ */
2
3 /**
4 * \file mga_ioc32.c
5 *
6 * 32-bit ioctl compatibility routines for the MGA DRM.
7 *
8 * \author Dave Airlie <airlied (at) linux.ie> with code from patches by Egbert Eich
9 *
10 *
11 * Copyright (C) Paul Mackerras 2005
12 * Copyright (C) Egbert Eich 2003,2004
13 * Copyright (C) Dave Airlie 2005
14 * All Rights Reserved.
15 *
16 * Permission is hereby granted, free of charge, to any person obtaining a
17 * copy of this software and associated documentation files (the "Software"),
18 * to deal in the Software without restriction, including without limitation
19 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
20 * and/or sell copies of the Software, and to permit persons to whom the
21 * Software is furnished to do so, subject to the following conditions:
22 *
23 * The above copyright notice and this permission notice (including the next
24 * paragraph) shall be included in all copies or substantial portions of the
25 * Software.
26 *
27 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
30 * THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
31 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
32 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
33 * IN THE SOFTWARE.
34 */
35 #include <sys/cdefs.h>
36 __KERNEL_RCSID(0, "$NetBSD: mga_ioc32.c,v 1.1.1.2.30.1 2019/06/10 22:08:06 christos Exp $");
37
38 #include <linux/compat.h>
39
40 #include <drm/drmP.h>
41 #include <drm/mga_drm.h>
42 #include "mga_drv.h"
43
44 typedef struct drm32_mga_init {
45 int func;
46 u32 sarea_priv_offset;
47 int chipset;
48 int sgram;
49 unsigned int maccess;
50 unsigned int fb_cpp;
51 unsigned int front_offset, front_pitch;
52 unsigned int back_offset, back_pitch;
53 unsigned int depth_cpp;
54 unsigned int depth_offset, depth_pitch;
55 unsigned int texture_offset[MGA_NR_TEX_HEAPS];
56 unsigned int texture_size[MGA_NR_TEX_HEAPS];
57 u32 fb_offset;
58 u32 mmio_offset;
59 u32 status_offset;
60 u32 warp_offset;
61 u32 primary_offset;
62 u32 buffers_offset;
63 } drm_mga_init32_t;
64
65 static int compat_mga_init(struct file *file, unsigned int cmd,
66 unsigned long arg)
67 {
68 drm_mga_init32_t init32;
69 drm_mga_init_t __user *init;
70 int err = 0, i;
71
72 if (copy_from_user(&init32, (void __user *)arg, sizeof(init32)))
73 return -EFAULT;
74
75 init = compat_alloc_user_space(sizeof(*init));
76 if (!access_ok(VERIFY_WRITE, init, sizeof(*init))
77 || __put_user(init32.func, &init->func)
78 || __put_user(init32.sarea_priv_offset, &init->sarea_priv_offset)
79 || __put_user(init32.chipset, &init->chipset)
80 || __put_user(init32.sgram, &init->sgram)
81 || __put_user(init32.maccess, &init->maccess)
82 || __put_user(init32.fb_cpp, &init->fb_cpp)
83 || __put_user(init32.front_offset, &init->front_offset)
84 || __put_user(init32.front_pitch, &init->front_pitch)
85 || __put_user(init32.back_offset, &init->back_offset)
86 || __put_user(init32.back_pitch, &init->back_pitch)
87 || __put_user(init32.depth_cpp, &init->depth_cpp)
88 || __put_user(init32.depth_offset, &init->depth_offset)
89 || __put_user(init32.depth_pitch, &init->depth_pitch)
90 || __put_user(init32.fb_offset, &init->fb_offset)
91 || __put_user(init32.mmio_offset, &init->mmio_offset)
92 || __put_user(init32.status_offset, &init->status_offset)
93 || __put_user(init32.warp_offset, &init->warp_offset)
94 || __put_user(init32.primary_offset, &init->primary_offset)
95 || __put_user(init32.buffers_offset, &init->buffers_offset))
96 return -EFAULT;
97
98 for (i = 0; i < MGA_NR_TEX_HEAPS; i++) {
99 err |=
100 __put_user(init32.texture_offset[i],
101 &init->texture_offset[i]);
102 err |=
103 __put_user(init32.texture_size[i], &init->texture_size[i]);
104 }
105 if (err)
106 return -EFAULT;
107
108 return drm_ioctl(file, DRM_IOCTL_MGA_INIT, (unsigned long)init);
109 }
110
111 typedef struct drm_mga_getparam32 {
112 int param;
113 u32 value;
114 } drm_mga_getparam32_t;
115
116 static int compat_mga_getparam(struct file *file, unsigned int cmd,
117 unsigned long arg)
118 {
119 drm_mga_getparam32_t getparam32;
120 drm_mga_getparam_t __user *getparam;
121
122 if (copy_from_user(&getparam32, (void __user *)arg, sizeof(getparam32)))
123 return -EFAULT;
124
125 getparam = compat_alloc_user_space(sizeof(*getparam));
126 if (!access_ok(VERIFY_WRITE, getparam, sizeof(*getparam))
127 || __put_user(getparam32.param, &getparam->param)
128 || __put_user((void __user *)(unsigned long)getparam32.value,
129 &getparam->value))
130 return -EFAULT;
131
132 return drm_ioctl(file, DRM_IOCTL_MGA_GETPARAM, (unsigned long)getparam);
133 }
134
135 typedef struct drm_mga_drm_bootstrap32 {
136 u32 texture_handle;
137 u32 texture_size;
138 u32 primary_size;
139 u32 secondary_bin_count;
140 u32 secondary_bin_size;
141 u32 agp_mode;
142 u8 agp_size;
143 } drm_mga_dma_bootstrap32_t;
144
145 static int compat_mga_dma_bootstrap(struct file *file, unsigned int cmd,
146 unsigned long arg)
147 {
148 drm_mga_dma_bootstrap32_t dma_bootstrap32;
149 drm_mga_dma_bootstrap_t __user *dma_bootstrap;
150 int err;
151
152 if (copy_from_user(&dma_bootstrap32, (void __user *)arg,
153 sizeof(dma_bootstrap32)))
154 return -EFAULT;
155
156 dma_bootstrap = compat_alloc_user_space(sizeof(*dma_bootstrap));
157 if (!access_ok(VERIFY_WRITE, dma_bootstrap, sizeof(*dma_bootstrap))
158 || __put_user(dma_bootstrap32.texture_handle,
159 &dma_bootstrap->texture_handle)
160 || __put_user(dma_bootstrap32.texture_size,
161 &dma_bootstrap->texture_size)
162 || __put_user(dma_bootstrap32.primary_size,
163 &dma_bootstrap->primary_size)
164 || __put_user(dma_bootstrap32.secondary_bin_count,
165 &dma_bootstrap->secondary_bin_count)
166 || __put_user(dma_bootstrap32.secondary_bin_size,
167 &dma_bootstrap->secondary_bin_size)
168 || __put_user(dma_bootstrap32.agp_mode, &dma_bootstrap->agp_mode)
169 || __put_user(dma_bootstrap32.agp_size, &dma_bootstrap->agp_size))
170 return -EFAULT;
171
172 err = drm_ioctl(file, DRM_IOCTL_MGA_DMA_BOOTSTRAP,
173 (unsigned long)dma_bootstrap);
174 if (err)
175 return err;
176
177 if (__get_user(dma_bootstrap32.texture_handle,
178 &dma_bootstrap->texture_handle)
179 || __get_user(dma_bootstrap32.texture_size,
180 &dma_bootstrap->texture_size)
181 || __get_user(dma_bootstrap32.primary_size,
182 &dma_bootstrap->primary_size)
183 || __get_user(dma_bootstrap32.secondary_bin_count,
184 &dma_bootstrap->secondary_bin_count)
185 || __get_user(dma_bootstrap32.secondary_bin_size,
186 &dma_bootstrap->secondary_bin_size)
187 || __get_user(dma_bootstrap32.agp_mode, &dma_bootstrap->agp_mode)
188 || __get_user(dma_bootstrap32.agp_size, &dma_bootstrap->agp_size))
189 return -EFAULT;
190
191 if (copy_to_user((void __user *)arg, &dma_bootstrap32,
192 sizeof(dma_bootstrap32)))
193 return -EFAULT;
194
195 return 0;
196 }
197
198 drm_ioctl_compat_t *mga_compat_ioctls[] = {
199 [DRM_MGA_INIT] = compat_mga_init,
200 [DRM_MGA_GETPARAM] = compat_mga_getparam,
201 [DRM_MGA_DMA_BOOTSTRAP] = compat_mga_dma_bootstrap,
202 };
203
204 /**
205 * Called whenever a 32-bit process running under a 64-bit kernel
206 * performs an ioctl on /dev/dri/card<n>.
207 *
208 * \param filp file pointer.
209 * \param cmd command.
210 * \param arg user argument.
211 * \return zero on success or negative number on failure.
212 */
213 long mga_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
214 {
215 unsigned int nr = DRM_IOCTL_NR(cmd);
216 drm_ioctl_compat_t *fn = NULL;
217 int ret;
218
219 if (nr < DRM_COMMAND_BASE)
220 return drm_compat_ioctl(filp, cmd, arg);
221
222 if (nr < DRM_COMMAND_BASE + ARRAY_SIZE(mga_compat_ioctls))
223 fn = mga_compat_ioctls[nr - DRM_COMMAND_BASE];
224
225 if (fn != NULL)
226 ret = (*fn) (filp, cmd, arg);
227 else
228 ret = drm_ioctl(filp, cmd, arg);
229
230 return ret;
231 }
232