12640981fSDaniel Vetter /*
2c0e09200SDave Airlie * \file drm_ioc32.c
3c0e09200SDave Airlie *
4c0e09200SDave Airlie * 32-bit ioctl compatibility routines for the DRM.
5c0e09200SDave Airlie *
6c0e09200SDave Airlie * \author Paul Mackerras <paulus@samba.org>
7c0e09200SDave Airlie *
8c0e09200SDave Airlie * Copyright (C) Paul Mackerras 2005.
9c0e09200SDave Airlie * All Rights Reserved.
10c0e09200SDave Airlie *
11c0e09200SDave Airlie * Permission is hereby granted, free of charge, to any person obtaining a
12c0e09200SDave Airlie * copy of this software and associated documentation files (the "Software"),
13c0e09200SDave Airlie * to deal in the Software without restriction, including without limitation
14c0e09200SDave Airlie * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15c0e09200SDave Airlie * and/or sell copies of the Software, and to permit persons to whom the
16c0e09200SDave Airlie * Software is furnished to do so, subject to the following conditions:
17c0e09200SDave Airlie *
18c0e09200SDave Airlie * The above copyright notice and this permission notice (including the next
19c0e09200SDave Airlie * paragraph) shall be included in all copies or substantial portions of the
20c0e09200SDave Airlie * Software.
21c0e09200SDave Airlie *
22c0e09200SDave Airlie * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23c0e09200SDave Airlie * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24c0e09200SDave Airlie * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25c0e09200SDave Airlie * THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26c0e09200SDave Airlie * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27c0e09200SDave Airlie * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
28c0e09200SDave Airlie * IN THE SOFTWARE.
29c0e09200SDave Airlie */
30c0e09200SDave Airlie #include <linux/compat.h>
31cafe8d84SChristian Dietrich #include <linux/ratelimit.h>
322d1a8a48SPaul Gortmaker #include <linux/export.h>
33c0e09200SDave Airlie
340500c04eSSam Ravnborg #include <drm/drm_file.h>
350500c04eSSam Ravnborg #include <drm/drm_print.h>
360500c04eSSam Ravnborg
37d6c56613SAl Viro #include "drm_crtc_internal.h"
380500c04eSSam Ravnborg #include "drm_internal.h"
390500c04eSSam Ravnborg #include "drm_legacy.h"
40c0e09200SDave Airlie
41c0e09200SDave Airlie #define DRM_IOCTL_VERSION32 DRM_IOWR(0x00, drm_version32_t)
42c0e09200SDave Airlie #define DRM_IOCTL_GET_UNIQUE32 DRM_IOWR(0x01, drm_unique32_t)
43c0e09200SDave Airlie #define DRM_IOCTL_GET_MAP32 DRM_IOWR(0x04, drm_map32_t)
44c0e09200SDave Airlie #define DRM_IOCTL_GET_CLIENT32 DRM_IOWR(0x05, drm_client32_t)
45c0e09200SDave Airlie #define DRM_IOCTL_GET_STATS32 DRM_IOR( 0x06, drm_stats32_t)
46c0e09200SDave Airlie
47c0e09200SDave Airlie #define DRM_IOCTL_SET_UNIQUE32 DRM_IOW( 0x10, drm_unique32_t)
48c0e09200SDave Airlie #define DRM_IOCTL_ADD_MAP32 DRM_IOWR(0x15, drm_map32_t)
49c0e09200SDave Airlie #define DRM_IOCTL_ADD_BUFS32 DRM_IOWR(0x16, drm_buf_desc32_t)
50c0e09200SDave Airlie #define DRM_IOCTL_MARK_BUFS32 DRM_IOW( 0x17, drm_buf_desc32_t)
51c0e09200SDave Airlie #define DRM_IOCTL_INFO_BUFS32 DRM_IOWR(0x18, drm_buf_info32_t)
52c0e09200SDave Airlie #define DRM_IOCTL_MAP_BUFS32 DRM_IOWR(0x19, drm_buf_map32_t)
53c0e09200SDave Airlie #define DRM_IOCTL_FREE_BUFS32 DRM_IOW( 0x1a, drm_buf_free32_t)
54c0e09200SDave Airlie
55c0e09200SDave Airlie #define DRM_IOCTL_RM_MAP32 DRM_IOW( 0x1b, drm_map32_t)
56c0e09200SDave Airlie
57c0e09200SDave Airlie #define DRM_IOCTL_SET_SAREA_CTX32 DRM_IOW( 0x1c, drm_ctx_priv_map32_t)
58c0e09200SDave Airlie #define DRM_IOCTL_GET_SAREA_CTX32 DRM_IOWR(0x1d, drm_ctx_priv_map32_t)
59c0e09200SDave Airlie
60c0e09200SDave Airlie #define DRM_IOCTL_RES_CTX32 DRM_IOWR(0x26, drm_ctx_res32_t)
61c0e09200SDave Airlie #define DRM_IOCTL_DMA32 DRM_IOWR(0x29, drm_dma32_t)
62c0e09200SDave Airlie
63c0e09200SDave Airlie #define DRM_IOCTL_AGP_ENABLE32 DRM_IOW( 0x32, drm_agp_mode32_t)
64c0e09200SDave Airlie #define DRM_IOCTL_AGP_INFO32 DRM_IOR( 0x33, drm_agp_info32_t)
65c0e09200SDave Airlie #define DRM_IOCTL_AGP_ALLOC32 DRM_IOWR(0x34, drm_agp_buffer32_t)
66c0e09200SDave Airlie #define DRM_IOCTL_AGP_FREE32 DRM_IOW( 0x35, drm_agp_buffer32_t)
67c0e09200SDave Airlie #define DRM_IOCTL_AGP_BIND32 DRM_IOW( 0x36, drm_agp_binding32_t)
68c0e09200SDave Airlie #define DRM_IOCTL_AGP_UNBIND32 DRM_IOW( 0x37, drm_agp_binding32_t)
69c0e09200SDave Airlie
70c0e09200SDave Airlie #define DRM_IOCTL_SG_ALLOC32 DRM_IOW( 0x38, drm_scatter_gather32_t)
71c0e09200SDave Airlie #define DRM_IOCTL_SG_FREE32 DRM_IOW( 0x39, drm_scatter_gather32_t)
72c0e09200SDave Airlie
7349568873SEric Anholt #define DRM_IOCTL_UPDATE_DRAW32 DRM_IOW( 0x3f, drm_update_draw32_t)
7449568873SEric Anholt
75c0e09200SDave Airlie #define DRM_IOCTL_WAIT_VBLANK32 DRM_IOWR(0x3a, drm_wait_vblank32_t)
76c0e09200SDave Airlie
77c631d5f9STvrtko Ursulin #define DRM_IOCTL_MODE_ADDFB232 DRM_IOWR(0xb8, drm_mode_fb_cmd232_t)
78c631d5f9STvrtko Ursulin
79c0e09200SDave Airlie typedef struct drm_version_32 {
802640981fSDaniel Vetter int version_major; /* Major version */
812640981fSDaniel Vetter int version_minor; /* Minor version */
822640981fSDaniel Vetter int version_patchlevel; /* Patch level */
832640981fSDaniel Vetter u32 name_len; /* Length of name buffer */
842640981fSDaniel Vetter u32 name; /* Name of driver */
852640981fSDaniel Vetter u32 date_len; /* Length of date buffer */
862640981fSDaniel Vetter u32 date; /* User-space buffer to hold date */
872640981fSDaniel Vetter u32 desc_len; /* Length of desc buffer */
882640981fSDaniel Vetter u32 desc; /* User-space buffer to hold desc */
89c0e09200SDave Airlie } drm_version32_t;
90c0e09200SDave Airlie
compat_drm_version(struct file * file,unsigned int cmd,unsigned long arg)91c0e09200SDave Airlie static int compat_drm_version(struct file *file, unsigned int cmd,
92c0e09200SDave Airlie unsigned long arg)
93c0e09200SDave Airlie {
94c0e09200SDave Airlie drm_version32_t v32;
95012c6741SAl Viro struct drm_version v;
96c0e09200SDave Airlie int err;
97c0e09200SDave Airlie
98c0e09200SDave Airlie if (copy_from_user(&v32, (void __user *)arg, sizeof(v32)))
99c0e09200SDave Airlie return -EFAULT;
100c0e09200SDave Airlie
101e926c474SDaniel Vetter memset(&v, 0, sizeof(v));
102e926c474SDaniel Vetter
103012c6741SAl Viro v = (struct drm_version) {
104012c6741SAl Viro .name_len = v32.name_len,
105012c6741SAl Viro .name = compat_ptr(v32.name),
106012c6741SAl Viro .date_len = v32.date_len,
107012c6741SAl Viro .date = compat_ptr(v32.date),
108012c6741SAl Viro .desc_len = v32.desc_len,
109012c6741SAl Viro .desc = compat_ptr(v32.desc),
110012c6741SAl Viro };
111012c6741SAl Viro err = drm_ioctl_kernel(file, drm_version, &v,
11275426367SDaniel Vetter DRM_RENDER_ALLOW);
113c0e09200SDave Airlie if (err)
114c0e09200SDave Airlie return err;
115c0e09200SDave Airlie
116012c6741SAl Viro v32.version_major = v.version_major;
117012c6741SAl Viro v32.version_minor = v.version_minor;
118012c6741SAl Viro v32.version_patchlevel = v.version_patchlevel;
119266530b3SJeffy Chen v32.name_len = v.name_len;
120266530b3SJeffy Chen v32.date_len = v.date_len;
121266530b3SJeffy Chen v32.desc_len = v.desc_len;
122c0e09200SDave Airlie if (copy_to_user((void __user *)arg, &v32, sizeof(v32)))
123c0e09200SDave Airlie return -EFAULT;
124c0e09200SDave Airlie return 0;
125c0e09200SDave Airlie }
126c0e09200SDave Airlie
127c0e09200SDave Airlie typedef struct drm_unique32 {
1282640981fSDaniel Vetter u32 unique_len; /* Length of unique */
1292640981fSDaniel Vetter u32 unique; /* Unique name for driver instantiation */
130c0e09200SDave Airlie } drm_unique32_t;
131c0e09200SDave Airlie
compat_drm_getunique(struct file * file,unsigned int cmd,unsigned long arg)132c0e09200SDave Airlie static int compat_drm_getunique(struct file *file, unsigned int cmd,
133c0e09200SDave Airlie unsigned long arg)
134c0e09200SDave Airlie {
135c0e09200SDave Airlie drm_unique32_t uq32;
13617e3dadeSAl Viro struct drm_unique uq;
137c0e09200SDave Airlie int err;
138c0e09200SDave Airlie
139c0e09200SDave Airlie if (copy_from_user(&uq32, (void __user *)arg, sizeof(uq32)))
140c0e09200SDave Airlie return -EFAULT;
141e926c474SDaniel Vetter
142e926c474SDaniel Vetter memset(&uq, 0, sizeof(uq));
143e926c474SDaniel Vetter
14417e3dadeSAl Viro uq = (struct drm_unique){
14517e3dadeSAl Viro .unique_len = uq32.unique_len,
14617e3dadeSAl Viro .unique = compat_ptr(uq32.unique),
14717e3dadeSAl Viro };
148c0e09200SDave Airlie
14975426367SDaniel Vetter err = drm_ioctl_kernel(file, drm_getunique, &uq, 0);
150c0e09200SDave Airlie if (err)
151c0e09200SDave Airlie return err;
152c0e09200SDave Airlie
15317e3dadeSAl Viro uq32.unique_len = uq.unique_len;
154c0e09200SDave Airlie if (copy_to_user((void __user *)arg, &uq32, sizeof(uq32)))
155c0e09200SDave Airlie return -EFAULT;
156c0e09200SDave Airlie return 0;
157c0e09200SDave Airlie }
158c0e09200SDave Airlie
compat_drm_setunique(struct file * file,unsigned int cmd,unsigned long arg)159c0e09200SDave Airlie static int compat_drm_setunique(struct file *file, unsigned int cmd,
160c0e09200SDave Airlie unsigned long arg)
161c0e09200SDave Airlie {
16256c275ccSAl Viro /* it's dead */
16356c275ccSAl Viro return -EINVAL;
164c0e09200SDave Airlie }
165c0e09200SDave Airlie
16661ae2270SDave Airlie #if IS_ENABLED(CONFIG_DRM_LEGACY)
167c0e09200SDave Airlie typedef struct drm_map32 {
1682640981fSDaniel Vetter u32 offset; /* Requested physical address (0 for SAREA) */
1692640981fSDaniel Vetter u32 size; /* Requested physical size (bytes) */
1702640981fSDaniel Vetter enum drm_map_type type; /* Type of memory to map */
1712640981fSDaniel Vetter enum drm_map_flags flags; /* Flags */
1722640981fSDaniel Vetter u32 handle; /* User-space: "Handle" to pass to mmap() */
1732640981fSDaniel Vetter int mtrr; /* MTRR slot used */
174c0e09200SDave Airlie } drm_map32_t;
175c0e09200SDave Airlie
compat_drm_getmap(struct file * file,unsigned int cmd,unsigned long arg)176c0e09200SDave Airlie static int compat_drm_getmap(struct file *file, unsigned int cmd,
177c0e09200SDave Airlie unsigned long arg)
178c0e09200SDave Airlie {
179c0e09200SDave Airlie drm_map32_t __user *argp = (void __user *)arg;
180c0e09200SDave Airlie drm_map32_t m32;
1818c4fe499SAl Viro struct drm_map map;
1828c4fe499SAl Viro int err;
183c0e09200SDave Airlie
1848c4fe499SAl Viro if (copy_from_user(&m32, argp, sizeof(m32)))
185c0e09200SDave Airlie return -EFAULT;
186c0e09200SDave Airlie
1878c4fe499SAl Viro map.offset = m32.offset;
18875426367SDaniel Vetter err = drm_ioctl_kernel(file, drm_legacy_getmap_ioctl, &map, 0);
189c0e09200SDave Airlie if (err)
190c0e09200SDave Airlie return err;
191c0e09200SDave Airlie
1928c4fe499SAl Viro m32.offset = map.offset;
1938c4fe499SAl Viro m32.size = map.size;
1948c4fe499SAl Viro m32.type = map.type;
1958c4fe499SAl Viro m32.flags = map.flags;
196e552f085SBen Dooks m32.handle = ptr_to_compat((void __user *)map.handle);
1978c4fe499SAl Viro m32.mtrr = map.mtrr;
198c0e09200SDave Airlie if (copy_to_user(argp, &m32, sizeof(m32)))
199c0e09200SDave Airlie return -EFAULT;
200c0e09200SDave Airlie return 0;
201c0e09200SDave Airlie
202c0e09200SDave Airlie }
203c0e09200SDave Airlie
compat_drm_addmap(struct file * file,unsigned int cmd,unsigned long arg)204c0e09200SDave Airlie static int compat_drm_addmap(struct file *file, unsigned int cmd,
205c0e09200SDave Airlie unsigned long arg)
206c0e09200SDave Airlie {
207c0e09200SDave Airlie drm_map32_t __user *argp = (void __user *)arg;
208c0e09200SDave Airlie drm_map32_t m32;
209b36180a3SAl Viro struct drm_map map;
210c0e09200SDave Airlie int err;
211c0e09200SDave Airlie
212c0e09200SDave Airlie if (copy_from_user(&m32, argp, sizeof(m32)))
213c0e09200SDave Airlie return -EFAULT;
214c0e09200SDave Airlie
215b36180a3SAl Viro map.offset = m32.offset;
216b36180a3SAl Viro map.size = m32.size;
217b36180a3SAl Viro map.type = m32.type;
218b36180a3SAl Viro map.flags = m32.flags;
219c0e09200SDave Airlie
220b36180a3SAl Viro err = drm_ioctl_kernel(file, drm_legacy_addmap_ioctl, &map,
221b36180a3SAl Viro DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
222c0e09200SDave Airlie if (err)
223c0e09200SDave Airlie return err;
224c0e09200SDave Airlie
225b36180a3SAl Viro m32.offset = map.offset;
226b36180a3SAl Viro m32.mtrr = map.mtrr;
227e552f085SBen Dooks m32.handle = ptr_to_compat((void __user *)map.handle);
228b36180a3SAl Viro if (map.handle != compat_ptr(m32.handle))
229499447dbSJoe Perches pr_err_ratelimited("compat_drm_addmap truncated handle %p for type %d offset %x\n",
230b36180a3SAl Viro map.handle, m32.type, m32.offset);
231c0e09200SDave Airlie
232c0e09200SDave Airlie if (copy_to_user(argp, &m32, sizeof(m32)))
233c0e09200SDave Airlie return -EFAULT;
234c0e09200SDave Airlie
235c0e09200SDave Airlie return 0;
236c0e09200SDave Airlie }
237c0e09200SDave Airlie
compat_drm_rmmap(struct file * file,unsigned int cmd,unsigned long arg)238c0e09200SDave Airlie static int compat_drm_rmmap(struct file *file, unsigned int cmd,
239c0e09200SDave Airlie unsigned long arg)
240c0e09200SDave Airlie {
241c0e09200SDave Airlie drm_map32_t __user *argp = (void __user *)arg;
2426113252dSAl Viro struct drm_map map;
243c0e09200SDave Airlie u32 handle;
244c0e09200SDave Airlie
245c0e09200SDave Airlie if (get_user(handle, &argp->handle))
246c0e09200SDave Airlie return -EFAULT;
2476113252dSAl Viro map.handle = compat_ptr(handle);
2486113252dSAl Viro return drm_ioctl_kernel(file, drm_legacy_rmmap_ioctl, &map, DRM_AUTH);
249c0e09200SDave Airlie }
25061ae2270SDave Airlie #endif
251c0e09200SDave Airlie
252c0e09200SDave Airlie typedef struct drm_client32 {
2532640981fSDaniel Vetter int idx; /* Which client desired? */
2542640981fSDaniel Vetter int auth; /* Is client authenticated? */
2552640981fSDaniel Vetter u32 pid; /* Process ID */
2562640981fSDaniel Vetter u32 uid; /* User ID */
2572640981fSDaniel Vetter u32 magic; /* Magic */
2582640981fSDaniel Vetter u32 iocs; /* Ioctl count */
259c0e09200SDave Airlie } drm_client32_t;
260c0e09200SDave Airlie
compat_drm_getclient(struct file * file,unsigned int cmd,unsigned long arg)261c0e09200SDave Airlie static int compat_drm_getclient(struct file *file, unsigned int cmd,
262c0e09200SDave Airlie unsigned long arg)
263c0e09200SDave Airlie {
264c0e09200SDave Airlie drm_client32_t c32;
265c0e09200SDave Airlie drm_client32_t __user *argp = (void __user *)arg;
2669e92662dSAl Viro struct drm_client client;
2679e92662dSAl Viro int err;
268c0e09200SDave Airlie
2699e92662dSAl Viro if (copy_from_user(&c32, argp, sizeof(c32)))
270c0e09200SDave Airlie return -EFAULT;
271c0e09200SDave Airlie
272e926c474SDaniel Vetter memset(&client, 0, sizeof(client));
273e926c474SDaniel Vetter
2749e92662dSAl Viro client.idx = c32.idx;
275c0e09200SDave Airlie
27675426367SDaniel Vetter err = drm_ioctl_kernel(file, drm_getclient, &client, 0);
277c0e09200SDave Airlie if (err)
278c0e09200SDave Airlie return err;
279c0e09200SDave Airlie
2809e92662dSAl Viro c32.idx = client.idx;
2819e92662dSAl Viro c32.auth = client.auth;
2829e92662dSAl Viro c32.pid = client.pid;
2839e92662dSAl Viro c32.uid = client.uid;
2849e92662dSAl Viro c32.magic = client.magic;
2859e92662dSAl Viro c32.iocs = client.iocs;
286c0e09200SDave Airlie
287c0e09200SDave Airlie if (copy_to_user(argp, &c32, sizeof(c32)))
288c0e09200SDave Airlie return -EFAULT;
289c0e09200SDave Airlie return 0;
290c0e09200SDave Airlie }
291c0e09200SDave Airlie
292c0e09200SDave Airlie typedef struct drm_stats32 {
293c0e09200SDave Airlie u32 count;
294c0e09200SDave Airlie struct {
295c0e09200SDave Airlie u32 value;
296c0e09200SDave Airlie enum drm_stat_type type;
297c0e09200SDave Airlie } data[15];
298c0e09200SDave Airlie } drm_stats32_t;
299c0e09200SDave Airlie
compat_drm_getstats(struct file * file,unsigned int cmd,unsigned long arg)300c0e09200SDave Airlie static int compat_drm_getstats(struct file *file, unsigned int cmd,
301c0e09200SDave Airlie unsigned long arg)
302c0e09200SDave Airlie {
303c0e09200SDave Airlie drm_stats32_t __user *argp = (void __user *)arg;
304c0e09200SDave Airlie
3052da9a1a2SDaniel Vetter /* getstats is defunct, just clear */
3068547ee9dSAl Viro if (clear_user(argp, sizeof(drm_stats32_t)))
307c0e09200SDave Airlie return -EFAULT;
308c0e09200SDave Airlie return 0;
309c0e09200SDave Airlie }
310c0e09200SDave Airlie
31161ae2270SDave Airlie #if IS_ENABLED(CONFIG_DRM_LEGACY)
312c0e09200SDave Airlie typedef struct drm_buf_desc32 {
3132640981fSDaniel Vetter int count; /* Number of buffers of this size */
3142640981fSDaniel Vetter int size; /* Size in bytes */
3152640981fSDaniel Vetter int low_mark; /* Low water mark */
3162640981fSDaniel Vetter int high_mark; /* High water mark */
317c0e09200SDave Airlie int flags;
3182640981fSDaniel Vetter u32 agp_start; /* Start address in the AGP aperture */
319c0e09200SDave Airlie } drm_buf_desc32_t;
320c0e09200SDave Airlie
compat_drm_addbufs(struct file * file,unsigned int cmd,unsigned long arg)321c0e09200SDave Airlie static int compat_drm_addbufs(struct file *file, unsigned int cmd,
322c0e09200SDave Airlie unsigned long arg)
323c0e09200SDave Airlie {
324c0e09200SDave Airlie drm_buf_desc32_t __user *argp = (void __user *)arg;
325ff22ff9eSAl Viro drm_buf_desc32_t desc32;
326ff22ff9eSAl Viro struct drm_buf_desc desc;
327c0e09200SDave Airlie int err;
328c0e09200SDave Airlie
329ff22ff9eSAl Viro if (copy_from_user(&desc32, argp, sizeof(drm_buf_desc32_t)))
330c0e09200SDave Airlie return -EFAULT;
331c0e09200SDave Airlie
332ff22ff9eSAl Viro desc = (struct drm_buf_desc){
333ff22ff9eSAl Viro desc32.count, desc32.size, desc32.low_mark, desc32.high_mark,
334ff22ff9eSAl Viro desc32.flags, desc32.agp_start
335ff22ff9eSAl Viro };
336c0e09200SDave Airlie
337ff22ff9eSAl Viro err = drm_ioctl_kernel(file, drm_legacy_addbufs, &desc,
338ff22ff9eSAl Viro DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
339c0e09200SDave Airlie if (err)
340c0e09200SDave Airlie return err;
341c0e09200SDave Airlie
342ff22ff9eSAl Viro desc32 = (drm_buf_desc32_t){
343ff22ff9eSAl Viro desc.count, desc.size, desc.low_mark, desc.high_mark,
344ff22ff9eSAl Viro desc.flags, desc.agp_start
345ff22ff9eSAl Viro };
346ff22ff9eSAl Viro if (copy_to_user(argp, &desc32, sizeof(drm_buf_desc32_t)))
347c0e09200SDave Airlie return -EFAULT;
348c0e09200SDave Airlie
349c0e09200SDave Airlie return 0;
350c0e09200SDave Airlie }
351c0e09200SDave Airlie
compat_drm_markbufs(struct file * file,unsigned int cmd,unsigned long arg)352c0e09200SDave Airlie static int compat_drm_markbufs(struct file *file, unsigned int cmd,
353c0e09200SDave Airlie unsigned long arg)
354c0e09200SDave Airlie {
355c0e09200SDave Airlie drm_buf_desc32_t b32;
356c0e09200SDave Airlie drm_buf_desc32_t __user *argp = (void __user *)arg;
357b87b786bSAl Viro struct drm_buf_desc buf;
358c0e09200SDave Airlie
359c0e09200SDave Airlie if (copy_from_user(&b32, argp, sizeof(b32)))
360c0e09200SDave Airlie return -EFAULT;
361c0e09200SDave Airlie
362dbae740eSAl Viro buf.size = b32.size;
363dbae740eSAl Viro buf.low_mark = b32.low_mark;
364dbae740eSAl Viro buf.high_mark = b32.high_mark;
365c0e09200SDave Airlie
366dbae740eSAl Viro return drm_ioctl_kernel(file, drm_legacy_markbufs, &buf,
367dbae740eSAl Viro DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
368c0e09200SDave Airlie }
369c0e09200SDave Airlie
370c0e09200SDave Airlie typedef struct drm_buf_info32 {
371c0e09200SDave Airlie int count; /**< Entries in list */
372c0e09200SDave Airlie u32 list;
373c0e09200SDave Airlie } drm_buf_info32_t;
374c0e09200SDave Airlie
copy_one_buf32(void * data,int count,struct drm_buf_entry * from)3755c7640abSAl Viro static int copy_one_buf32(void *data, int count, struct drm_buf_entry *from)
3765c7640abSAl Viro {
3775c7640abSAl Viro drm_buf_info32_t *request = data;
3785c7640abSAl Viro drm_buf_desc32_t __user *to = compat_ptr(request->list);
3795c7640abSAl Viro drm_buf_desc32_t v = {.count = from->buf_count,
3805c7640abSAl Viro .size = from->buf_size,
3815c7640abSAl Viro .low_mark = from->low_mark,
3825c7640abSAl Viro .high_mark = from->high_mark};
38374b67efaSDan Carpenter
38474b67efaSDan Carpenter if (copy_to_user(to + count, &v, offsetof(drm_buf_desc32_t, flags)))
38574b67efaSDan Carpenter return -EFAULT;
38674b67efaSDan Carpenter return 0;
3875c7640abSAl Viro }
3885c7640abSAl Viro
drm_legacy_infobufs32(struct drm_device * dev,void * data,struct drm_file * file_priv)3895c7640abSAl Viro static int drm_legacy_infobufs32(struct drm_device *dev, void *data,
3905c7640abSAl Viro struct drm_file *file_priv)
3915c7640abSAl Viro {
3925c7640abSAl Viro drm_buf_info32_t *request = data;
393948de842SSuraj Upadhyay
3945c7640abSAl Viro return __drm_legacy_infobufs(dev, data, &request->count, copy_one_buf32);
3955c7640abSAl Viro }
3965c7640abSAl Viro
compat_drm_infobufs(struct file * file,unsigned int cmd,unsigned long arg)397c0e09200SDave Airlie static int compat_drm_infobufs(struct file *file, unsigned int cmd,
398c0e09200SDave Airlie unsigned long arg)
399c0e09200SDave Airlie {
400c0e09200SDave Airlie drm_buf_info32_t req32;
401c0e09200SDave Airlie drm_buf_info32_t __user *argp = (void __user *)arg;
4025c7640abSAl Viro int err;
403c0e09200SDave Airlie
404c0e09200SDave Airlie if (copy_from_user(&req32, argp, sizeof(req32)))
405c0e09200SDave Airlie return -EFAULT;
406c0e09200SDave Airlie
4075c7640abSAl Viro if (req32.count < 0)
4085c7640abSAl Viro req32.count = 0;
409c0e09200SDave Airlie
4105c7640abSAl Viro err = drm_ioctl_kernel(file, drm_legacy_infobufs32, &req32, DRM_AUTH);
411c0e09200SDave Airlie if (err)
412c0e09200SDave Airlie return err;
413c0e09200SDave Airlie
4145c7640abSAl Viro if (put_user(req32.count, &argp->count))
415c0e09200SDave Airlie return -EFAULT;
416c0e09200SDave Airlie
417c0e09200SDave Airlie return 0;
418c0e09200SDave Airlie }
419c0e09200SDave Airlie
420c0e09200SDave Airlie typedef struct drm_buf_pub32 {
421c0e09200SDave Airlie int idx; /**< Index into the master buffer list */
422c0e09200SDave Airlie int total; /**< Buffer size */
423c0e09200SDave Airlie int used; /**< Amount of buffer in use (for DMA) */
424c0e09200SDave Airlie u32 address; /**< Address of buffer */
425c0e09200SDave Airlie } drm_buf_pub32_t;
426c0e09200SDave Airlie
427c0e09200SDave Airlie typedef struct drm_buf_map32 {
428c0e09200SDave Airlie int count; /**< Length of the buffer list */
429c0e09200SDave Airlie u32 virtual; /**< Mmap'd area in user-virtual */
430c0e09200SDave Airlie u32 list; /**< Buffer information */
431c0e09200SDave Airlie } drm_buf_map32_t;
432c0e09200SDave Airlie
map_one_buf32(void * data,int idx,unsigned long virtual,struct drm_buf * buf)43387d3ce11SAl Viro static int map_one_buf32(void *data, int idx, unsigned long virtual,
43487d3ce11SAl Viro struct drm_buf *buf)
43587d3ce11SAl Viro {
43687d3ce11SAl Viro drm_buf_map32_t *request = data;
43787d3ce11SAl Viro drm_buf_pub32_t __user *to = compat_ptr(request->list) + idx;
43887d3ce11SAl Viro drm_buf_pub32_t v;
43987d3ce11SAl Viro
44087d3ce11SAl Viro v.idx = buf->idx;
44187d3ce11SAl Viro v.total = buf->total;
44287d3ce11SAl Viro v.used = 0;
44387d3ce11SAl Viro v.address = virtual + buf->offset;
44487d3ce11SAl Viro if (copy_to_user(to, &v, sizeof(v)))
44587d3ce11SAl Viro return -EFAULT;
44687d3ce11SAl Viro return 0;
44787d3ce11SAl Viro }
44887d3ce11SAl Viro
drm_legacy_mapbufs32(struct drm_device * dev,void * data,struct drm_file * file_priv)44987d3ce11SAl Viro static int drm_legacy_mapbufs32(struct drm_device *dev, void *data,
45087d3ce11SAl Viro struct drm_file *file_priv)
45187d3ce11SAl Viro {
45287d3ce11SAl Viro drm_buf_map32_t *request = data;
45387d3ce11SAl Viro void __user *v;
45487d3ce11SAl Viro int err = __drm_legacy_mapbufs(dev, data, &request->count,
45587d3ce11SAl Viro &v, map_one_buf32,
45687d3ce11SAl Viro file_priv);
45787d3ce11SAl Viro request->virtual = ptr_to_compat(v);
45887d3ce11SAl Viro return err;
45987d3ce11SAl Viro }
46087d3ce11SAl Viro
compat_drm_mapbufs(struct file * file,unsigned int cmd,unsigned long arg)461c0e09200SDave Airlie static int compat_drm_mapbufs(struct file *file, unsigned int cmd,
462c0e09200SDave Airlie unsigned long arg)
463c0e09200SDave Airlie {
464c0e09200SDave Airlie drm_buf_map32_t __user *argp = (void __user *)arg;
465c0e09200SDave Airlie drm_buf_map32_t req32;
46687d3ce11SAl Viro int err;
467c0e09200SDave Airlie
468c0e09200SDave Airlie if (copy_from_user(&req32, argp, sizeof(req32)))
469c0e09200SDave Airlie return -EFAULT;
47087d3ce11SAl Viro if (req32.count < 0)
471c0e09200SDave Airlie return -EINVAL;
472c0e09200SDave Airlie
47387d3ce11SAl Viro err = drm_ioctl_kernel(file, drm_legacy_mapbufs32, &req32, DRM_AUTH);
474c0e09200SDave Airlie if (err)
475c0e09200SDave Airlie return err;
476c0e09200SDave Airlie
47787d3ce11SAl Viro if (put_user(req32.count, &argp->count)
47887d3ce11SAl Viro || put_user(req32.virtual, &argp->virtual))
479c0e09200SDave Airlie return -EFAULT;
480c0e09200SDave Airlie
481c0e09200SDave Airlie return 0;
482c0e09200SDave Airlie }
483c0e09200SDave Airlie
484c0e09200SDave Airlie typedef struct drm_buf_free32 {
485c0e09200SDave Airlie int count;
486c0e09200SDave Airlie u32 list;
487c0e09200SDave Airlie } drm_buf_free32_t;
488c0e09200SDave Airlie
compat_drm_freebufs(struct file * file,unsigned int cmd,unsigned long arg)489c0e09200SDave Airlie static int compat_drm_freebufs(struct file *file, unsigned int cmd,
490c0e09200SDave Airlie unsigned long arg)
491c0e09200SDave Airlie {
492c0e09200SDave Airlie drm_buf_free32_t req32;
4938c9e4cfbSAl Viro struct drm_buf_free request;
494c0e09200SDave Airlie drm_buf_free32_t __user *argp = (void __user *)arg;
495c0e09200SDave Airlie
496c0e09200SDave Airlie if (copy_from_user(&req32, argp, sizeof(req32)))
497c0e09200SDave Airlie return -EFAULT;
498c0e09200SDave Airlie
4998c9e4cfbSAl Viro request.count = req32.count;
5008c9e4cfbSAl Viro request.list = compat_ptr(req32.list);
5018c9e4cfbSAl Viro return drm_ioctl_kernel(file, drm_legacy_freebufs, &request, DRM_AUTH);
502c0e09200SDave Airlie }
503c0e09200SDave Airlie
504c0e09200SDave Airlie typedef struct drm_ctx_priv_map32 {
505c0e09200SDave Airlie unsigned int ctx_id; /**< Context requesting private mapping */
506c0e09200SDave Airlie u32 handle; /**< Handle of map */
507c0e09200SDave Airlie } drm_ctx_priv_map32_t;
508c0e09200SDave Airlie
compat_drm_setsareactx(struct file * file,unsigned int cmd,unsigned long arg)509c0e09200SDave Airlie static int compat_drm_setsareactx(struct file *file, unsigned int cmd,
510c0e09200SDave Airlie unsigned long arg)
511c0e09200SDave Airlie {
512c0e09200SDave Airlie drm_ctx_priv_map32_t req32;
5137900c600SAl Viro struct drm_ctx_priv_map request;
514c0e09200SDave Airlie drm_ctx_priv_map32_t __user *argp = (void __user *)arg;
515c0e09200SDave Airlie
516c0e09200SDave Airlie if (copy_from_user(&req32, argp, sizeof(req32)))
517c0e09200SDave Airlie return -EFAULT;
518c0e09200SDave Airlie
5197900c600SAl Viro request.ctx_id = req32.ctx_id;
5207900c600SAl Viro request.handle = compat_ptr(req32.handle);
5217900c600SAl Viro return drm_ioctl_kernel(file, drm_legacy_setsareactx, &request,
5227900c600SAl Viro DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
523c0e09200SDave Airlie }
524c0e09200SDave Airlie
compat_drm_getsareactx(struct file * file,unsigned int cmd,unsigned long arg)525c0e09200SDave Airlie static int compat_drm_getsareactx(struct file *file, unsigned int cmd,
526c0e09200SDave Airlie unsigned long arg)
527c0e09200SDave Airlie {
528d7631e30SAl Viro struct drm_ctx_priv_map req;
529d7631e30SAl Viro drm_ctx_priv_map32_t req32;
530c0e09200SDave Airlie drm_ctx_priv_map32_t __user *argp = (void __user *)arg;
531c0e09200SDave Airlie int err;
532c0e09200SDave Airlie
533d7631e30SAl Viro if (copy_from_user(&req32, argp, sizeof(req32)))
534c0e09200SDave Airlie return -EFAULT;
535c0e09200SDave Airlie
536d7631e30SAl Viro req.ctx_id = req32.ctx_id;
537d7631e30SAl Viro err = drm_ioctl_kernel(file, drm_legacy_getsareactx, &req, DRM_AUTH);
538c0e09200SDave Airlie if (err)
539c0e09200SDave Airlie return err;
540c0e09200SDave Airlie
541e552f085SBen Dooks req32.handle = ptr_to_compat((void __user *)req.handle);
542d7631e30SAl Viro if (copy_to_user(argp, &req32, sizeof(req32)))
543c0e09200SDave Airlie return -EFAULT;
544c0e09200SDave Airlie
545c0e09200SDave Airlie return 0;
546c0e09200SDave Airlie }
547c0e09200SDave Airlie
548c0e09200SDave Airlie typedef struct drm_ctx_res32 {
549c0e09200SDave Airlie int count;
550c0e09200SDave Airlie u32 contexts;
551c0e09200SDave Airlie } drm_ctx_res32_t;
552c0e09200SDave Airlie
compat_drm_resctx(struct file * file,unsigned int cmd,unsigned long arg)553c0e09200SDave Airlie static int compat_drm_resctx(struct file *file, unsigned int cmd,
554c0e09200SDave Airlie unsigned long arg)
555c0e09200SDave Airlie {
556c0e09200SDave Airlie drm_ctx_res32_t __user *argp = (void __user *)arg;
557c0e09200SDave Airlie drm_ctx_res32_t res32;
5589e075680SAl Viro struct drm_ctx_res res;
559c0e09200SDave Airlie int err;
560c0e09200SDave Airlie
561c0e09200SDave Airlie if (copy_from_user(&res32, argp, sizeof(res32)))
562c0e09200SDave Airlie return -EFAULT;
563c0e09200SDave Airlie
5649e075680SAl Viro res.count = res32.count;
5659e075680SAl Viro res.contexts = compat_ptr(res32.contexts);
5669e075680SAl Viro err = drm_ioctl_kernel(file, drm_legacy_resctx, &res, DRM_AUTH);
567c0e09200SDave Airlie if (err)
568c0e09200SDave Airlie return err;
569c0e09200SDave Airlie
5709e075680SAl Viro res32.count = res.count;
5719e075680SAl Viro if (copy_to_user(argp, &res32, sizeof(res32)))
572c0e09200SDave Airlie return -EFAULT;
573c0e09200SDave Airlie
574c0e09200SDave Airlie return 0;
575c0e09200SDave Airlie }
576c0e09200SDave Airlie
577c0e09200SDave Airlie typedef struct drm_dma32 {
578c0e09200SDave Airlie int context; /**< Context handle */
579c0e09200SDave Airlie int send_count; /**< Number of buffers to send */
580c0e09200SDave Airlie u32 send_indices; /**< List of handles to buffers */
581c0e09200SDave Airlie u32 send_sizes; /**< Lengths of data to send */
582c0e09200SDave Airlie enum drm_dma_flags flags; /**< Flags */
583c0e09200SDave Airlie int request_count; /**< Number of buffers requested */
584c0e09200SDave Airlie int request_size; /**< Desired size for buffers */
585c0e09200SDave Airlie u32 request_indices; /**< Buffer information */
586c0e09200SDave Airlie u32 request_sizes;
587c0e09200SDave Airlie int granted_count; /**< Number of buffers granted */
588c0e09200SDave Airlie } drm_dma32_t;
589c0e09200SDave Airlie
compat_drm_dma(struct file * file,unsigned int cmd,unsigned long arg)590c0e09200SDave Airlie static int compat_drm_dma(struct file *file, unsigned int cmd,
591c0e09200SDave Airlie unsigned long arg)
592c0e09200SDave Airlie {
593c0e09200SDave Airlie drm_dma32_t d32;
594c0e09200SDave Airlie drm_dma32_t __user *argp = (void __user *)arg;
595c6f08966SAl Viro struct drm_dma d;
596c0e09200SDave Airlie int err;
597c0e09200SDave Airlie
598c0e09200SDave Airlie if (copy_from_user(&d32, argp, sizeof(d32)))
599c0e09200SDave Airlie return -EFAULT;
600c0e09200SDave Airlie
601c6f08966SAl Viro d.context = d32.context;
602c6f08966SAl Viro d.send_count = d32.send_count;
603c6f08966SAl Viro d.send_indices = compat_ptr(d32.send_indices);
604c6f08966SAl Viro d.send_sizes = compat_ptr(d32.send_sizes);
605c6f08966SAl Viro d.flags = d32.flags;
606c6f08966SAl Viro d.request_count = d32.request_count;
607c6f08966SAl Viro d.request_indices = compat_ptr(d32.request_indices);
608c6f08966SAl Viro d.request_sizes = compat_ptr(d32.request_sizes);
609c6f08966SAl Viro err = drm_ioctl_kernel(file, drm_legacy_dma_ioctl, &d, DRM_AUTH);
610c0e09200SDave Airlie if (err)
611c0e09200SDave Airlie return err;
612c0e09200SDave Airlie
613c6f08966SAl Viro if (put_user(d.request_size, &argp->request_size)
614c6f08966SAl Viro || put_user(d.granted_count, &argp->granted_count))
615c0e09200SDave Airlie return -EFAULT;
616c0e09200SDave Airlie
617c0e09200SDave Airlie return 0;
618c0e09200SDave Airlie }
61961ae2270SDave Airlie #endif
620c0e09200SDave Airlie
62104dfe19aSThomas Zimmermann #if IS_ENABLED(CONFIG_DRM_LEGACY)
622a7fb8a23SDaniel Vetter #if IS_ENABLED(CONFIG_AGP)
623c0e09200SDave Airlie typedef struct drm_agp_mode32 {
624c0e09200SDave Airlie u32 mode; /**< AGP mode */
625c0e09200SDave Airlie } drm_agp_mode32_t;
626c0e09200SDave Airlie
compat_drm_agp_enable(struct file * file,unsigned int cmd,unsigned long arg)627c0e09200SDave Airlie static int compat_drm_agp_enable(struct file *file, unsigned int cmd,
628c0e09200SDave Airlie unsigned long arg)
629c0e09200SDave Airlie {
630c0e09200SDave Airlie drm_agp_mode32_t __user *argp = (void __user *)arg;
631e92673edSAl Viro struct drm_agp_mode mode;
632c0e09200SDave Airlie
633e92673edSAl Viro if (get_user(mode.mode, &argp->mode))
634c0e09200SDave Airlie return -EFAULT;
635c0e09200SDave Airlie
63604dfe19aSThomas Zimmermann return drm_ioctl_kernel(file, drm_legacy_agp_enable_ioctl, &mode,
637e92673edSAl Viro DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
638c0e09200SDave Airlie }
639c0e09200SDave Airlie
640c0e09200SDave Airlie typedef struct drm_agp_info32 {
641c0e09200SDave Airlie int agp_version_major;
642c0e09200SDave Airlie int agp_version_minor;
643c0e09200SDave Airlie u32 mode;
644c0e09200SDave Airlie u32 aperture_base; /* physical address */
645c0e09200SDave Airlie u32 aperture_size; /* bytes */
646c0e09200SDave Airlie u32 memory_allowed; /* bytes */
647c0e09200SDave Airlie u32 memory_used;
648c0e09200SDave Airlie
649c0e09200SDave Airlie /* PCI information */
650c0e09200SDave Airlie unsigned short id_vendor;
651c0e09200SDave Airlie unsigned short id_device;
652c0e09200SDave Airlie } drm_agp_info32_t;
653c0e09200SDave Airlie
compat_drm_agp_info(struct file * file,unsigned int cmd,unsigned long arg)654c0e09200SDave Airlie static int compat_drm_agp_info(struct file *file, unsigned int cmd,
655c0e09200SDave Airlie unsigned long arg)
656c0e09200SDave Airlie {
657c0e09200SDave Airlie drm_agp_info32_t __user *argp = (void __user *)arg;
658c0e09200SDave Airlie drm_agp_info32_t i32;
659e92673edSAl Viro struct drm_agp_info info;
660c0e09200SDave Airlie int err;
661c0e09200SDave Airlie
66204dfe19aSThomas Zimmermann err = drm_ioctl_kernel(file, drm_legacy_agp_info_ioctl, &info, DRM_AUTH);
663c0e09200SDave Airlie if (err)
664c0e09200SDave Airlie return err;
665c0e09200SDave Airlie
666e92673edSAl Viro i32.agp_version_major = info.agp_version_major;
667e92673edSAl Viro i32.agp_version_minor = info.agp_version_minor;
668e92673edSAl Viro i32.mode = info.mode;
669e92673edSAl Viro i32.aperture_base = info.aperture_base;
670e92673edSAl Viro i32.aperture_size = info.aperture_size;
671e92673edSAl Viro i32.memory_allowed = info.memory_allowed;
672e92673edSAl Viro i32.memory_used = info.memory_used;
673e92673edSAl Viro i32.id_vendor = info.id_vendor;
674e92673edSAl Viro i32.id_device = info.id_device;
675c0e09200SDave Airlie if (copy_to_user(argp, &i32, sizeof(i32)))
676c0e09200SDave Airlie return -EFAULT;
677c0e09200SDave Airlie
678c0e09200SDave Airlie return 0;
679c0e09200SDave Airlie }
680c0e09200SDave Airlie
681c0e09200SDave Airlie typedef struct drm_agp_buffer32 {
682c0e09200SDave Airlie u32 size; /**< In bytes -- will round to page boundary */
683c0e09200SDave Airlie u32 handle; /**< Used for binding / unbinding */
684c0e09200SDave Airlie u32 type; /**< Type of memory to allocate */
685c0e09200SDave Airlie u32 physical; /**< Physical used by i810 */
686c0e09200SDave Airlie } drm_agp_buffer32_t;
687c0e09200SDave Airlie
compat_drm_agp_alloc(struct file * file,unsigned int cmd,unsigned long arg)688c0e09200SDave Airlie static int compat_drm_agp_alloc(struct file *file, unsigned int cmd,
689c0e09200SDave Airlie unsigned long arg)
690c0e09200SDave Airlie {
691c0e09200SDave Airlie drm_agp_buffer32_t __user *argp = (void __user *)arg;
692c0e09200SDave Airlie drm_agp_buffer32_t req32;
693e92673edSAl Viro struct drm_agp_buffer request;
694c0e09200SDave Airlie int err;
695c0e09200SDave Airlie
696c0e09200SDave Airlie if (copy_from_user(&req32, argp, sizeof(req32)))
697c0e09200SDave Airlie return -EFAULT;
698c0e09200SDave Airlie
699e92673edSAl Viro request.size = req32.size;
700e92673edSAl Viro request.type = req32.type;
70104dfe19aSThomas Zimmermann err = drm_ioctl_kernel(file, drm_legacy_agp_alloc_ioctl, &request,
702e92673edSAl Viro DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
703c0e09200SDave Airlie if (err)
704c0e09200SDave Airlie return err;
705c0e09200SDave Airlie
706e92673edSAl Viro req32.handle = request.handle;
707e92673edSAl Viro req32.physical = request.physical;
708e92673edSAl Viro if (copy_to_user(argp, &req32, sizeof(req32))) {
70904dfe19aSThomas Zimmermann drm_ioctl_kernel(file, drm_legacy_agp_free_ioctl, &request,
710e92673edSAl Viro DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
711c0e09200SDave Airlie return -EFAULT;
712c0e09200SDave Airlie }
713c0e09200SDave Airlie
714c0e09200SDave Airlie return 0;
715c0e09200SDave Airlie }
716c0e09200SDave Airlie
compat_drm_agp_free(struct file * file,unsigned int cmd,unsigned long arg)717c0e09200SDave Airlie static int compat_drm_agp_free(struct file *file, unsigned int cmd,
718c0e09200SDave Airlie unsigned long arg)
719c0e09200SDave Airlie {
720c0e09200SDave Airlie drm_agp_buffer32_t __user *argp = (void __user *)arg;
721e92673edSAl Viro struct drm_agp_buffer request;
722c0e09200SDave Airlie
723e92673edSAl Viro if (get_user(request.handle, &argp->handle))
724c0e09200SDave Airlie return -EFAULT;
725c0e09200SDave Airlie
72604dfe19aSThomas Zimmermann return drm_ioctl_kernel(file, drm_legacy_agp_free_ioctl, &request,
727e92673edSAl Viro DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
728c0e09200SDave Airlie }
729c0e09200SDave Airlie
730c0e09200SDave Airlie typedef struct drm_agp_binding32 {
731c0e09200SDave Airlie u32 handle; /**< From drm_agp_buffer */
732c0e09200SDave Airlie u32 offset; /**< In bytes -- will round to page boundary */
733c0e09200SDave Airlie } drm_agp_binding32_t;
734c0e09200SDave Airlie
compat_drm_agp_bind(struct file * file,unsigned int cmd,unsigned long arg)735c0e09200SDave Airlie static int compat_drm_agp_bind(struct file *file, unsigned int cmd,
736c0e09200SDave Airlie unsigned long arg)
737c0e09200SDave Airlie {
738c0e09200SDave Airlie drm_agp_binding32_t __user *argp = (void __user *)arg;
739c0e09200SDave Airlie drm_agp_binding32_t req32;
740e92673edSAl Viro struct drm_agp_binding request;
741c0e09200SDave Airlie
742c0e09200SDave Airlie if (copy_from_user(&req32, argp, sizeof(req32)))
743c0e09200SDave Airlie return -EFAULT;
744c0e09200SDave Airlie
745e92673edSAl Viro request.handle = req32.handle;
746e92673edSAl Viro request.offset = req32.offset;
74704dfe19aSThomas Zimmermann return drm_ioctl_kernel(file, drm_legacy_agp_bind_ioctl, &request,
748e92673edSAl Viro DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
749c0e09200SDave Airlie }
750c0e09200SDave Airlie
compat_drm_agp_unbind(struct file * file,unsigned int cmd,unsigned long arg)751c0e09200SDave Airlie static int compat_drm_agp_unbind(struct file *file, unsigned int cmd,
752c0e09200SDave Airlie unsigned long arg)
753c0e09200SDave Airlie {
754c0e09200SDave Airlie drm_agp_binding32_t __user *argp = (void __user *)arg;
755e92673edSAl Viro struct drm_agp_binding request;
756c0e09200SDave Airlie
757e92673edSAl Viro if (get_user(request.handle, &argp->handle))
758c0e09200SDave Airlie return -EFAULT;
759c0e09200SDave Airlie
76004dfe19aSThomas Zimmermann return drm_ioctl_kernel(file, drm_legacy_agp_unbind_ioctl, &request,
761e92673edSAl Viro DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
762c0e09200SDave Airlie }
763a7fb8a23SDaniel Vetter #endif /* CONFIG_AGP */
764c0e09200SDave Airlie
765c0e09200SDave Airlie typedef struct drm_scatter_gather32 {
766c0e09200SDave Airlie u32 size; /**< In bytes -- will round to page boundary */
767c0e09200SDave Airlie u32 handle; /**< Used for mapping / unmapping */
768c0e09200SDave Airlie } drm_scatter_gather32_t;
769c0e09200SDave Airlie
compat_drm_sg_alloc(struct file * file,unsigned int cmd,unsigned long arg)770c0e09200SDave Airlie static int compat_drm_sg_alloc(struct file *file, unsigned int cmd,
771c0e09200SDave Airlie unsigned long arg)
772c0e09200SDave Airlie {
773c0e09200SDave Airlie drm_scatter_gather32_t __user *argp = (void __user *)arg;
774314ed736SAl Viro struct drm_scatter_gather request;
775c0e09200SDave Airlie int err;
776c0e09200SDave Airlie
777314ed736SAl Viro if (get_user(request.size, &argp->size))
778c0e09200SDave Airlie return -EFAULT;
779c0e09200SDave Airlie
780314ed736SAl Viro err = drm_ioctl_kernel(file, drm_legacy_sg_alloc, &request,
781314ed736SAl Viro DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
782c0e09200SDave Airlie if (err)
783c0e09200SDave Airlie return err;
784c0e09200SDave Airlie
785c0e09200SDave Airlie /* XXX not sure about the handle conversion here... */
786314ed736SAl Viro if (put_user(request.handle >> PAGE_SHIFT, &argp->handle))
787c0e09200SDave Airlie return -EFAULT;
788c0e09200SDave Airlie
789c0e09200SDave Airlie return 0;
790c0e09200SDave Airlie }
791c0e09200SDave Airlie
compat_drm_sg_free(struct file * file,unsigned int cmd,unsigned long arg)792c0e09200SDave Airlie static int compat_drm_sg_free(struct file *file, unsigned int cmd,
793c0e09200SDave Airlie unsigned long arg)
794c0e09200SDave Airlie {
795c0e09200SDave Airlie drm_scatter_gather32_t __user *argp = (void __user *)arg;
796314ed736SAl Viro struct drm_scatter_gather request;
797c0e09200SDave Airlie unsigned long x;
798c0e09200SDave Airlie
799314ed736SAl Viro if (get_user(x, &argp->handle))
800c0e09200SDave Airlie return -EFAULT;
801314ed736SAl Viro request.handle = x << PAGE_SHIFT;
802314ed736SAl Viro return drm_ioctl_kernel(file, drm_legacy_sg_free, &request,
803314ed736SAl Viro DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
804c0e09200SDave Airlie }
80561ae2270SDave Airlie #endif
8069cc73ce2SAl Viro #if defined(CONFIG_X86)
80749568873SEric Anholt typedef struct drm_update_draw32 {
80849568873SEric Anholt drm_drawable_t handle;
80949568873SEric Anholt unsigned int type;
81049568873SEric Anholt unsigned int num;
81149568873SEric Anholt /* 64-bit version has a 32-bit pad here */
81249568873SEric Anholt u64 data; /**< Pointer */
81349568873SEric Anholt } __attribute__((packed)) drm_update_draw32_t;
81449568873SEric Anholt
compat_drm_update_draw(struct file * file,unsigned int cmd,unsigned long arg)81549568873SEric Anholt static int compat_drm_update_draw(struct file *file, unsigned int cmd,
81649568873SEric Anholt unsigned long arg)
81749568873SEric Anholt {
8182da9a1a2SDaniel Vetter /* update_draw is defunct */
8192da9a1a2SDaniel Vetter return 0;
82049568873SEric Anholt }
82109e40d65SDavid Miller #endif
82249568873SEric Anholt
823c0e09200SDave Airlie struct drm_wait_vblank_request32 {
824c0e09200SDave Airlie enum drm_vblank_seq_type type;
825c0e09200SDave Airlie unsigned int sequence;
826c0e09200SDave Airlie u32 signal;
827c0e09200SDave Airlie };
828c0e09200SDave Airlie
829c0e09200SDave Airlie struct drm_wait_vblank_reply32 {
830c0e09200SDave Airlie enum drm_vblank_seq_type type;
831c0e09200SDave Airlie unsigned int sequence;
832c0e09200SDave Airlie s32 tval_sec;
833c0e09200SDave Airlie s32 tval_usec;
834c0e09200SDave Airlie };
835c0e09200SDave Airlie
836c0e09200SDave Airlie typedef union drm_wait_vblank32 {
837c0e09200SDave Airlie struct drm_wait_vblank_request32 request;
838c0e09200SDave Airlie struct drm_wait_vblank_reply32 reply;
839c0e09200SDave Airlie } drm_wait_vblank32_t;
840c0e09200SDave Airlie
compat_drm_wait_vblank(struct file * file,unsigned int cmd,unsigned long arg)841c0e09200SDave Airlie static int compat_drm_wait_vblank(struct file *file, unsigned int cmd,
842c0e09200SDave Airlie unsigned long arg)
843c0e09200SDave Airlie {
844c0e09200SDave Airlie drm_wait_vblank32_t __user *argp = (void __user *)arg;
845c0e09200SDave Airlie drm_wait_vblank32_t req32;
846d5288c88SAl Viro union drm_wait_vblank req;
847c0e09200SDave Airlie int err;
848c0e09200SDave Airlie
849c0e09200SDave Airlie if (copy_from_user(&req32, argp, sizeof(req32)))
850c0e09200SDave Airlie return -EFAULT;
851c0e09200SDave Airlie
852e926c474SDaniel Vetter memset(&req, 0, sizeof(req));
853e926c474SDaniel Vetter
854d5288c88SAl Viro req.request.type = req32.request.type;
855d5288c88SAl Viro req.request.sequence = req32.request.sequence;
856d5288c88SAl Viro req.request.signal = req32.request.signal;
857af055598SDaniel Vetter err = drm_ioctl_kernel(file, drm_wait_vblank_ioctl, &req, DRM_UNLOCKED);
858c0e09200SDave Airlie
859d5288c88SAl Viro req32.reply.type = req.reply.type;
860d5288c88SAl Viro req32.reply.sequence = req.reply.sequence;
861d5288c88SAl Viro req32.reply.tval_sec = req.reply.tval_sec;
862d5288c88SAl Viro req32.reply.tval_usec = req.reply.tval_usec;
863c0e09200SDave Airlie if (copy_to_user(argp, &req32, sizeof(req32)))
864c0e09200SDave Airlie return -EFAULT;
865c0e09200SDave Airlie
866fa0b1ef5SMark Yacoub return err;
867c0e09200SDave Airlie }
868c0e09200SDave Airlie
8699cc73ce2SAl Viro #if defined(CONFIG_X86)
870c631d5f9STvrtko Ursulin typedef struct drm_mode_fb_cmd232 {
871c631d5f9STvrtko Ursulin u32 fb_id;
872c631d5f9STvrtko Ursulin u32 width;
873c631d5f9STvrtko Ursulin u32 height;
874c631d5f9STvrtko Ursulin u32 pixel_format;
875c631d5f9STvrtko Ursulin u32 flags;
876c631d5f9STvrtko Ursulin u32 handles[4];
877c631d5f9STvrtko Ursulin u32 pitches[4];
878c631d5f9STvrtko Ursulin u32 offsets[4];
879c631d5f9STvrtko Ursulin u64 modifier[4];
880c631d5f9STvrtko Ursulin } __attribute__((packed)) drm_mode_fb_cmd232_t;
881c631d5f9STvrtko Ursulin
compat_drm_mode_addfb2(struct file * file,unsigned int cmd,unsigned long arg)882c631d5f9STvrtko Ursulin static int compat_drm_mode_addfb2(struct file *file, unsigned int cmd,
883c631d5f9STvrtko Ursulin unsigned long arg)
884c631d5f9STvrtko Ursulin {
885c631d5f9STvrtko Ursulin struct drm_mode_fb_cmd232 __user *argp = (void __user *)arg;
886b87b786bSAl Viro struct drm_mode_fb_cmd2 req64;
887c631d5f9STvrtko Ursulin int err;
888c631d5f9STvrtko Ursulin
889e926c474SDaniel Vetter memset(&req64, 0, sizeof(req64));
890e926c474SDaniel Vetter
891d6c56613SAl Viro if (copy_from_user(&req64, argp,
892d6c56613SAl Viro offsetof(drm_mode_fb_cmd232_t, modifier)))
893c631d5f9STvrtko Ursulin return -EFAULT;
894c631d5f9STvrtko Ursulin
895d6c56613SAl Viro if (copy_from_user(&req64.modifier, &argp->modifier,
896d6c56613SAl Viro sizeof(req64.modifier)))
897c631d5f9STvrtko Ursulin return -EFAULT;
898c631d5f9STvrtko Ursulin
89975426367SDaniel Vetter err = drm_ioctl_kernel(file, drm_mode_addfb2, &req64, 0);
900c631d5f9STvrtko Ursulin if (err)
901c631d5f9STvrtko Ursulin return err;
902c631d5f9STvrtko Ursulin
903d6c56613SAl Viro if (put_user(req64.fb_id, &argp->fb_id))
904c631d5f9STvrtko Ursulin return -EFAULT;
905c631d5f9STvrtko Ursulin
906c631d5f9STvrtko Ursulin return 0;
907c631d5f9STvrtko Ursulin }
908a988588bSKristian H. Kristensen #endif
909c631d5f9STvrtko Ursulin
9109f43e542SAl Viro static struct {
9119f43e542SAl Viro drm_ioctl_compat_t *fn;
9129f43e542SAl Viro char *name;
9139f43e542SAl Viro } drm_compat_ioctls[] = {
914ff22ff9eSAl Viro #define DRM_IOCTL32_DEF(n, f) [DRM_IOCTL_NR(n##32)] = {.fn = f, .name = #n}
915012c6741SAl Viro DRM_IOCTL32_DEF(DRM_IOCTL_VERSION, compat_drm_version),
91617e3dadeSAl Viro DRM_IOCTL32_DEF(DRM_IOCTL_GET_UNIQUE, compat_drm_getunique),
91761ae2270SDave Airlie #if IS_ENABLED(CONFIG_DRM_LEGACY)
9188c4fe499SAl Viro DRM_IOCTL32_DEF(DRM_IOCTL_GET_MAP, compat_drm_getmap),
91961ae2270SDave Airlie #endif
9209e92662dSAl Viro DRM_IOCTL32_DEF(DRM_IOCTL_GET_CLIENT, compat_drm_getclient),
9218547ee9dSAl Viro DRM_IOCTL32_DEF(DRM_IOCTL_GET_STATS, compat_drm_getstats),
92256c275ccSAl Viro DRM_IOCTL32_DEF(DRM_IOCTL_SET_UNIQUE, compat_drm_setunique),
92361ae2270SDave Airlie #if IS_ENABLED(CONFIG_DRM_LEGACY)
924b36180a3SAl Viro DRM_IOCTL32_DEF(DRM_IOCTL_ADD_MAP, compat_drm_addmap),
925ff22ff9eSAl Viro DRM_IOCTL32_DEF(DRM_IOCTL_ADD_BUFS, compat_drm_addbufs),
926dbae740eSAl Viro DRM_IOCTL32_DEF(DRM_IOCTL_MARK_BUFS, compat_drm_markbufs),
9275c7640abSAl Viro DRM_IOCTL32_DEF(DRM_IOCTL_INFO_BUFS, compat_drm_infobufs),
92887d3ce11SAl Viro DRM_IOCTL32_DEF(DRM_IOCTL_MAP_BUFS, compat_drm_mapbufs),
9298c9e4cfbSAl Viro DRM_IOCTL32_DEF(DRM_IOCTL_FREE_BUFS, compat_drm_freebufs),
9306113252dSAl Viro DRM_IOCTL32_DEF(DRM_IOCTL_RM_MAP, compat_drm_rmmap),
9317900c600SAl Viro DRM_IOCTL32_DEF(DRM_IOCTL_SET_SAREA_CTX, compat_drm_setsareactx),
932d7631e30SAl Viro DRM_IOCTL32_DEF(DRM_IOCTL_GET_SAREA_CTX, compat_drm_getsareactx),
9339e075680SAl Viro DRM_IOCTL32_DEF(DRM_IOCTL_RES_CTX, compat_drm_resctx),
934c6f08966SAl Viro DRM_IOCTL32_DEF(DRM_IOCTL_DMA, compat_drm_dma),
935a7fb8a23SDaniel Vetter #if IS_ENABLED(CONFIG_AGP)
936e92673edSAl Viro DRM_IOCTL32_DEF(DRM_IOCTL_AGP_ENABLE, compat_drm_agp_enable),
937e92673edSAl Viro DRM_IOCTL32_DEF(DRM_IOCTL_AGP_INFO, compat_drm_agp_info),
938e92673edSAl Viro DRM_IOCTL32_DEF(DRM_IOCTL_AGP_ALLOC, compat_drm_agp_alloc),
939e92673edSAl Viro DRM_IOCTL32_DEF(DRM_IOCTL_AGP_FREE, compat_drm_agp_free),
940e92673edSAl Viro DRM_IOCTL32_DEF(DRM_IOCTL_AGP_BIND, compat_drm_agp_bind),
941e92673edSAl Viro DRM_IOCTL32_DEF(DRM_IOCTL_AGP_UNBIND, compat_drm_agp_unbind),
942c0e09200SDave Airlie #endif
94304dfe19aSThomas Zimmermann #endif
94461ae2270SDave Airlie #if IS_ENABLED(CONFIG_DRM_LEGACY)
945314ed736SAl Viro DRM_IOCTL32_DEF(DRM_IOCTL_SG_ALLOC, compat_drm_sg_alloc),
946314ed736SAl Viro DRM_IOCTL32_DEF(DRM_IOCTL_SG_FREE, compat_drm_sg_free),
94761ae2270SDave Airlie #endif
94809e40d65SDavid Miller #if defined(CONFIG_X86) || defined(CONFIG_IA64)
9491a36bf1dSAl Viro DRM_IOCTL32_DEF(DRM_IOCTL_UPDATE_DRAW, compat_drm_update_draw),
95009e40d65SDavid Miller #endif
951d5288c88SAl Viro DRM_IOCTL32_DEF(DRM_IOCTL_WAIT_VBLANK, compat_drm_wait_vblank),
952a988588bSKristian H. Kristensen #if defined(CONFIG_X86) || defined(CONFIG_IA64)
953d6c56613SAl Viro DRM_IOCTL32_DEF(DRM_IOCTL_MODE_ADDFB2, compat_drm_mode_addfb2),
954a988588bSKristian H. Kristensen #endif
955c0e09200SDave Airlie };
956c0e09200SDave Airlie
957c0e09200SDave Airlie /**
9582640981fSDaniel Vetter * drm_compat_ioctl - 32bit IOCTL compatibility handler for DRM drivers
9592640981fSDaniel Vetter * @filp: file this ioctl is called on
9602640981fSDaniel Vetter * @cmd: ioctl cmd number
9612640981fSDaniel Vetter * @arg: user argument
962c0e09200SDave Airlie *
9632640981fSDaniel Vetter * Compatibility handler for 32 bit userspace running on 64 kernels. All actual
9642640981fSDaniel Vetter * IOCTL handling is forwarded to drm_ioctl(), while marshalling structures as
9652640981fSDaniel Vetter * appropriate. Note that this only handles DRM core IOCTLs, if the driver has
9662640981fSDaniel Vetter * botched IOCTL itself, it must handle those by wrapping this function.
9672640981fSDaniel Vetter *
9682640981fSDaniel Vetter * Returns:
9692640981fSDaniel Vetter * Zero on success, negative error code on failure.
970c0e09200SDave Airlie */
drm_compat_ioctl(struct file * filp,unsigned int cmd,unsigned long arg)971c0e09200SDave Airlie long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
972c0e09200SDave Airlie {
973c0e09200SDave Airlie unsigned int nr = DRM_IOCTL_NR(cmd);
97488e3cb07SAl Viro struct drm_file *file_priv = filp->private_data;
975*723dad97STvrtko Ursulin struct drm_device *dev = file_priv->minor->dev;
976c0e09200SDave Airlie drm_ioctl_compat_t *fn;
977c0e09200SDave Airlie int ret;
978c0e09200SDave Airlie
979c0e09200SDave Airlie /* Assume that ioctls without an explicit compat routine will just
980c0e09200SDave Airlie * work. This may not always be a good assumption, but it's better
981c0e09200SDave Airlie * than always failing.
982c0e09200SDave Airlie */
983c0e09200SDave Airlie if (nr >= ARRAY_SIZE(drm_compat_ioctls))
984ed8b6704SArnd Bergmann return drm_ioctl(filp, cmd, arg);
985c0e09200SDave Airlie
9869f43e542SAl Viro fn = drm_compat_ioctls[nr].fn;
9879f43e542SAl Viro if (!fn)
9889f43e542SAl Viro return drm_ioctl(filp, cmd, arg);
989c0e09200SDave Airlie
990*723dad97STvrtko Ursulin drm_dbg_core(dev, "comm=\"%s\", pid=%d, dev=0x%lx, auth=%d, %s\n",
9915a2ba992SEmil Velikov current->comm, task_pid_nr(current),
9929f43e542SAl Viro (long)old_encode_dev(file_priv->minor->kdev->devt),
9939f43e542SAl Viro file_priv->authenticated,
9949f43e542SAl Viro drm_compat_ioctls[nr].name);
995c0e09200SDave Airlie ret = (*fn)(filp, cmd, arg);
9969f43e542SAl Viro if (ret)
997*723dad97STvrtko Ursulin drm_dbg_core(dev, "ret = %d\n", ret);
998c0e09200SDave Airlie return ret;
999c0e09200SDave Airlie }
1000c0e09200SDave Airlie EXPORT_SYMBOL(drm_compat_ioctl);
1001