xref: /netbsd-src/sys/compat/netbsd32/netbsd32_drm.c (revision 42ca6328b8fb78ca2abf0b418e399bd0a1c63ed4)
1 /*	$NetBSD: netbsd32_drm.c,v 1.4 2019/09/28 15:15:34 christos Exp $ */
2 
3 /*
4  * Copyright (c) 2019 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code was written by Surya Shankar for GSoC 2019.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30 
31 #include <sys/cdefs.h>
32 __KERNEL_RCSID(0, "$NetBSD: netbsd32_drm.c,v 1.4 2019/09/28 15:15:34 christos Exp $");
33 
34 #include <compat/netbsd32/netbsd32.h>
35 #include <compat/netbsd32/netbsd32_ioctl.h>
36 
37 #include <linux/types.h>
38 #include <drm/drmP.h>
39 
40 #define DRM_IOCTL_VERSION32		DRM_IOWR(0x00, drm_version32_t)
41 #define DRM_IOCTL_GET_UNIQUE32		DRM_IOWR(0x01, drm_unique32_t)
42 #define DRM_IOCTL_GET_MAP32		DRM_IOWR(0x04, drm_map32_t)
43 #define DRM_IOCTL_GET_CLIENT32		DRM_IOWR(0x05, drm_client32_t)
44 #define DRM_IOCTL_GET_STATS32		DRM_IOR( 0x06, drm_stats32_t)
45 
46 #define DRM_IOCTL_SET_UNIQUE32		DRM_IOW( 0x10, drm_unique32_t)
47 #define DRM_IOCTL_ADD_MAP32		DRM_IOWR(0x15, drm_map32_t)
48 #define DRM_IOCTL_ADD_BUFS32		DRM_IOWR(0x16, drm_buf_desc32_t)
49 #define DRM_IOCTL_MARK_BUFS32		DRM_IOW( 0x17, drm_buf_desc32_t)
50 #define DRM_IOCTL_INFO_BUFS32		DRM_IOWR(0x18, drm_buf_info32_t)
51 #define DRM_IOCTL_MAP_BUFS32		DRM_IOWR(0x19, drm_buf_map32_t)
52 #define DRM_IOCTL_FREE_BUFS32		DRM_IOW( 0x1a, drm_buf_free32_t)
53 
54 #define DRM_IOCTL_RM_MAP32		DRM_IOW( 0x1b, drm_map32_t)
55 
56 #define DRM_IOCTL_SET_SAREA_CTX32	DRM_IOW( 0x1c, drm_ctx_priv_map32_t)
57 #define DRM_IOCTL_GET_SAREA_CTX32	DRM_IOWR(0x1d, drm_ctx_priv_map32_t)
58 
59 #define DRM_IOCTL_RES_CTX32		DRM_IOWR(0x26, drm_ctx_res32_t)
60 #define DRM_IOCTL_DMA32			DRM_IOWR(0x29, drm_dma32_t)
61 
62 #define DRM_IOCTL_AGP_ENABLE32		DRM_IOW( 0x32, drm_agp_mode32_t)
63 #define DRM_IOCTL_AGP_INFO32		DRM_IOR( 0x33, drm_agp_info32_t)
64 #define DRM_IOCTL_AGP_ALLOC32		DRM_IOWR(0x34, drm_agp_buffer32_t)
65 #define DRM_IOCTL_AGP_FREE32		DRM_IOW( 0x35, drm_agp_buffer32_t)
66 #define DRM_IOCTL_AGP_BIND32		DRM_IOW( 0x36, drm_agp_binding32_t)
67 #define DRM_IOCTL_AGP_UNBIND32		DRM_IOW( 0x37, drm_agp_binding32_t)
68 
69 #define DRM_IOCTL_SG_ALLOC32		DRM_IOW( 0x38, drm_scatter_gather32_t)
70 #define DRM_IOCTL_SG_FREE32		DRM_IOW( 0x39, drm_scatter_gather32_t)
71 
72 #define DRM_IOCTL_UPDATE_DRAW32		DRM_IOW( 0x3f, drm_update_draw32_t)
73 
74 #define DRM_IOCTL_WAIT_VBLANK32		DRM_IOWR(0x3a, drm_wait_vblank32_t)
75 
76 #define DRM_IOCTL_MODE_ADDFB232		DRM_IOWR(0xb8, drm_mode_fb_cmd232_t)
77 
78 // Compat DRM Version Implementation
79 
80 typedef struct {
81 	int version_major;		/**< Major version */
82 	int version_minor;		/**< Minor version */
83 	int version_patchlevel;		/**< Patch level */
84 	uint32_t name_len;		/**< Length of name buffer */
85 	netbsd32_pointer_t name;	/**< Name of driver */
86 	uint32_t date_len;		/**< Length of date buffer */
87 	netbsd32_pointer_t date;	/**< User-space buffer to hold date */
88 	uint32_t desc_len;		/**< Length of desc buffer */
89 	netbsd32_pointer_t desc;	/**< User-space buffer to hold desc */
90 } drm_version32_t;
91 
92 static int
compat_drm_version(struct file * file,void * arg)93 compat_drm_version(struct file *file, void *arg)
94 {
95 	drm_version32_t v32;
96 	struct drm_version v64;
97 	int error;
98 
99 	if ((error = copyin(&v32, arg, sizeof(v32))) != 0)
100 		return error;
101 
102 	v64.name_len = v32.name_len;
103 	v64.name = NETBSD32PTR64(v32.name);
104 	v64.date_len = v32.date_len;
105 	v64.date = NETBSD32PTR64(v32.date);
106 	v64.desc_len = v32.desc_len;
107 	v64.desc = NETBSD32PTR64(v32.desc);
108 
109 	error = drm_ioctl(file, DRM_IOCTL_VERSION, &v64);
110 	if (error)
111 		return error;
112 
113 	v32.version_major = v64.version_major;
114 	v32.version_minor = v64.version_minor;
115 	v32.version_patchlevel = v64.version_patchlevel;
116 	/* strings have already been copied in place */
117 	v32.name_len = v64.name_len;
118 	v32.date_len = v64.date_len;
119 	v32.desc_len = v64.desc_len;
120 
121 	return copyout(arg, &v32, sizeof(v32));
122 }
123 
124 typedef struct drm_unique32 {
125 	uint32_t unique_len;
126 	netbsd32_pointer_t unique;
127 } drm_unique32_t;
128 
129 static int
compat_drm_getunique(struct file * file,void * arg)130 compat_drm_getunique(struct file *file, void *arg)
131 {
132 	drm_unique32_t uq32;
133 	struct drm_unique uq64;
134 	int error;
135 
136 	if ((error = copyin(&uq32, arg, sizeof(uq32))) != 0)
137 		return error;
138 
139 	uq64.unique_len = uq32.unique_len;
140 	uq64.unique = NETBSD32PTR64(uq32.unique);
141 
142 	error = drm_ioctl(file, DRM_IOCTL_GET_UNIQUE, &uq64);
143 	if (error)
144 		return error;
145 
146 	//unique should already be copied
147 	uq32.unique_len = uq64.unique_len;
148 
149 	if ((error = copyout(arg, &uq32, sizeof(uq32))) != 0)
150 		return error;
151 
152 	return 0;
153 }
154 
155 static int
compat_drm_setunique(struct file * file,void * arg)156 compat_drm_setunique(struct file *file, void *arg)
157 {
158 	drm_unique32_t uq32;
159 	struct drm_unique uq64;
160 	int error;
161 
162 	if ((error = copyin(&uq32, arg, sizeof(uq32))) != 0)
163 		return error;
164 
165 	uq64.unique_len = uq32.unique_len;
166 	uq64.unique = NETBSD32PTR64(uq32.unique);
167 
168 	error = drm_ioctl(file, DRM_IOCTL_SET_UNIQUE, &uq64);
169 	if (error)
170 		return error;
171 
172 	// XXX: do we need copyout and copying the fields here?
173 	uq32.unique_len = uq64.unique_len;
174 	NETBSD32PTR32(uq32.unique, uq64.unique);
175 
176 	return error;
177 }
178 
179 typedef struct drm_map32 {
180 	uint32_t offset;	  /**< Req. physical address (0 for SAREA) */
181 	uint32_t size;		  /**< Requested physical size (bytes) */
182 	enum drm_map_type type;	  /**< Type of memory to map */
183 	enum drm_map_flags flags; /**< Flags */
184 	netbsd32_pointer_t handle;/**< User-space: "Handle" to pass to mmap() */
185 	int mtrr;		  /**< MTRR slot used */
186 } drm_map32_t;
187 
188 static void
map32to64(struct drm_map * m64,const drm_map32_t * m32)189 map32to64(struct drm_map *m64, const drm_map32_t *m32)
190 {
191 	m64->offset = m32->offset;
192 	m64->size = m32->size;
193 	m64->type = m32->type;
194 	m64->flags = m32->flags;
195 	m64->handle = NETBSD32PTR64(m32->handle);
196 	m64->mtrr = m32->mtrr;
197 }
198 
199 static void
map64to32(drm_map32_t * m32,const struct drm_map * m64)200 map64to32(drm_map32_t *m32, const struct drm_map *m64)
201 {
202 	m32->offset = m64->offset;
203 	m32->size = m64->size;
204 	m32->type = m64->type;
205 	m32->flags = m64->flags;
206 	NETBSD32PTR32(m32->handle, m64->handle);
207 	m32->mtrr = m64->mtrr;
208 }
209 
210 static int
compat_drm_getmap(struct file * file,void * arg)211 compat_drm_getmap(struct file *file, void *arg)
212 {
213 	drm_map32_t m32;
214 	struct drm_map m64;
215 	int error;
216 
217 	if ((error = copyin(&m32, arg, sizeof(m32))) != 0)
218 		return error;
219 
220 	map32to64(&m64, &m32);
221 
222 	error = drm_ioctl(file, DRM_IOCTL_GET_MAP, &m64);
223 	if (error)
224 		return error;
225 
226 	map64to32(&m32, &m64);
227 
228 	return copyout(arg, &m32, sizeof(m32));
229 }
230 
231 static int
compat_drm_addmap(struct file * file,void * arg)232 compat_drm_addmap(struct file *file, void *arg)
233 {
234 	drm_map32_t m32;
235 	struct drm_map m64;
236 	int error;
237 
238 	if ((error = copyin(&m32, arg, sizeof(m32))) != 0)
239 		return error;
240 
241 	map32to64(&m64, &m32);
242 
243 	error = drm_ioctl(file, DRM_IOCTL_ADD_MAP, &m64);
244 	if (error)
245 		return error;
246 
247 	map64to32(&m32, &m64);
248 
249 	return copyout(arg, &m32, sizeof(m32));
250 }
251 
252 
253 static int
compat_drm_rmmap(struct file * file,void * arg)254 compat_drm_rmmap(struct file *file, void *arg)
255 {
256 	drm_map32_t m32;
257 	struct drm_map m64;
258 	int error;
259 	if ((error = copyin(&m32, arg, sizeof(m32))) != 0)
260 		return error;
261 
262 	map32to64(&m64, &m32);
263 
264 	error = drm_ioctl(file, DRM_IOCTL_RM_MAP, &m64);
265 	if (error)
266 		return error;
267 
268 	map64to32(&m32, &m64);
269 
270 	return copyout(arg, &m32, sizeof(m32));
271 }
272 
273 typedef struct drm_client32 {
274 	int idx;	/**< Which client desired? */
275 	int auth;	/**< Is client authenticated? */
276 	uint32_t pid;	/**< Process ID */
277 	uint32_t uid;	/**< User ID */
278 	uint32_t magic; /**< Magic */
279 	uint32_t iocs;	/**< Ioctl count */
280 } drm_client32_t;
281 
282 static void
client32to64(struct drm_client * c64,const drm_client32_t * c32)283 client32to64(struct drm_client *c64, const drm_client32_t *c32)
284 {
285 	c64->idx = c32->idx;
286 	c64->auth = c32->auth;
287 	c64->pid = c32->pid;
288 	c64->uid = c32->uid;
289 	c64->iocs = c64->iocs;
290 }
291 
292 static void
client64to32(drm_client32_t * c32,const struct drm_client * c64)293 client64to32(drm_client32_t *c32, const struct drm_client *c64)
294 {
295 	c32->idx = c64->idx;
296 	c32->auth = c64->auth;
297 	c32->pid = c64->pid;
298 	c32->uid = c64->uid;
299 	c32->iocs = c64->iocs;
300 }
301 static int
compat_drm_getclient(struct file * file,void * arg)302 compat_drm_getclient(struct file *file, void *arg)
303 {
304 	drm_client32_t c32;
305 	struct drm_client c64;
306 	int error;
307 
308 	if ((error = copyin(&c32, arg, sizeof(c32))) != 0)
309 		return error;
310 
311 	client32to64(&c64, &c32);
312 
313 	error = drm_ioctl(file, DRM_IOCTL_GET_CLIENT, &c64);
314 	if (error)
315 		return error;
316 
317 	client64to32(&c32, &c64);
318 
319 	return copyout(arg, &c32, sizeof(c32));
320 }
321 
322 typedef struct drm_stats32 {
323 	uint32_t count;
324 	struct {
325 		uint32_t value;
326 		enum drm_stat_type type;
327 	} data[15];
328 } drm_stats32_t;
329 
330 static int
compat_drm_getstats(struct file * file,void * arg)331 compat_drm_getstats(struct file *file, void *arg)
332 {
333 	drm_stats32_t st32;
334 	struct drm_stats st64;
335 	int error;
336 
337 	if ((error = copyin(&st32, arg, sizeof(st32))) != 0)
338 		return error;
339 
340 	st64.count = st32.count;
341 	if (st64.count > __arraycount(st64.data))
342 		return EINVAL;
343 
344 	error = drm_ioctl(file, DRM_IOCTL_GET_STATS, &st64);
345 	if (error)
346 		return error;
347 
348 	for (size_t i = 0; i < st64.count; ++i) {
349 		st32.data[i].value = st64.data[i].value;
350 		st32.data[i].type = st64.data[i].type;
351 	}
352 	st32.count = st64.count;
353 
354 	return copyout(arg, &st32, sizeof(s32));
355 }
356 
357 typedef struct drm_buf_desc32 {
358 	int count;		 /**< Number of buffers of this size */
359 	int size;		 /**< Size in bytes */
360 	int low_mark;		 /**< Low water mark */
361 	int high_mark;		 /**< High water mark */
362 	int flags;
363 	netbsd32_pointer_t agp_start;
364 				/**< Start address in the AGP aperture */
365 } drm_buf_desc32_t;
366 
367 static int
compat_drm_addbufs(struct file * file,void * arg)368 compat_drm_addbufs(struct file *file, void *arg)
369 {
370 	drm_buf_desc32_t buf32;
371 	struct drm_buf_desc buf64;
372 	int error;
373 
374 	if ((error = copyin(&buf32, arg, sizeof(buf32))) != 0)
375 		return error;
376 
377 	// XXX: assign 32->64
378 	buf64.agp_start = (unsigned long)NETBSD32PTR64(buf32.agp_start);
379 
380 	error = drm_ioctl(file, DRM_IOCTL_ADD_BUFS, &buf64);
381 	if (error)
382 		return error;
383 
384 	// XXX assign 64->32
385 	NETBSD32PTR32(buf32.agp_start, (void *)buf64.agp_start);
386 
387 	return copyout(&buf32, arg, sizeof(buf32));
388 }
389 
390 static int
compat_drm_markbufs(struct file * file,void * arg)391 compat_drm_markbufs(struct file *file, void *arg)
392 {
393 	drm_buf_desc32_t b32;
394 	struct drm_buf_desc b64;
395 	int error;
396 
397 	if ((error = copyin(&b32, arg, sizeof(b32))) != 0)
398 		return error;
399 
400 	b64.size = b32.size;
401 	b64.low_mark = b32.low_mark;
402 	b64.high_mark = b32.high_mark;
403 	//XXX: more stuff?
404 
405 	return drm_ioctl(file, DRM_IOCTL_MARK_BUFS, &b64);
406 }
407 
408 typedef struct drm_buf_info32 {
409 	int count;		 /**< Entries in list */
410 	netbsd32_pointer_t list;
411 } drm_buf_info32_t;
412 
413 typedef struct drm_buf_pub32 {
414 	int idx;		 /**< Index into the master buffer list */
415 	int total;		 /**< Buffer size */
416 	int used;		 /**< Amount of buffer in use (for DMA) */
417 	uint32_t address;	 /**< Address of buffer */
418 } drm_buf_pub32_t;
419 
420 typedef struct drm_buf_map32 {
421 	int count;		 /**< Length of the buffer list */
422 	uint32_t virtual;	 /**< Mmap'd area in user-virtual */
423 	netbsd32_pointer_t list; /**< Buffer information */
424 } drm_buf_map32_t;
425 
426 
427 typedef struct drm_buf_free32 {
428 	int count;
429 	netbsd32_pointer_t list;
430 } drm_buf_free32_t;
431 
432 static int
compat_drm_freebufs(struct file * file,void * arg)433 compat_drm_freebufs(struct file *file, void *arg)
434 {
435 	drm_buf_free32_t req32;
436 	struct drm_buf_free req64;
437 	int error;
438 
439 	if ((error = copyin(&req32, arg, sizeof(req32))) != 0)
440 		return error;
441 
442 	req64.count = req32.count;
443 	req64.list = NETBSD32PTR64(req32.list);
444 
445 	return drm_ioctl(file, DRM_IOCTL_FREE_BUFS, &req64);
446 }
447 
448 typedef struct drm_ctx_priv_map32 {
449 	unsigned int ctx_id;		 /**< Context requesting private mapping */
450 	netbsd32_pointer_t handle;	 /**< Handle of map */
451 } drm_ctx_priv_map32_t;
452 
453 static int
compat_drm_setsareactx(struct file * file,void * arg)454 compat_drm_setsareactx(struct file *file, void *arg)
455 {
456 	drm_ctx_priv_map32_t req32;
457 	struct drm_ctx_priv_map req64;
458 	int error;
459 
460 	if ((error = copyin(&req32, arg, sizeof(req32))) != 0)
461 		return error;
462 
463 	req64.ctx_id = req32.ctx_id;
464 	req64.handle = NETBSD32PTR64(req32.handle);
465 
466 	error = drm_ioctl(file, DRM_IOCTL_SET_SAREA_CTX, &req64);
467 	if(error)
468 		return error;
469 
470 	req32.ctx_id = req64.ctx_id;
471 	NETBSD32PTR32(req32.handle, req64.handle);
472 
473 	return 0;
474 }
475 
476 static int
compat_drm_getsareactx(struct file * file,void * arg)477 compat_drm_getsareactx(struct file *file, void *arg)
478 {
479 	struct drm_ctx_priv_map req64;
480 	drm_ctx_priv_map32_t req32;
481 	int error;
482 
483 	if ((error = copyin(&req32, arg, sizeof(req32))) != 0)
484 		return error;
485 
486 	req64.ctx_id = req32.ctx_id;
487 
488 	error = drm_ioctl(file, DRM_IOCTL_GET_SAREA_CTX, &req64);
489 	if (error)
490 		return error;
491 
492 	NETBSD32PTR32(req32.handle, req64.handle);
493 	// XXX: missing copyout?
494 
495 	return copyout(arg, &req32, sizeof(req32));
496 }
497 
498 typedef struct drm_ctx_res32 {
499 	int count;
500 	netbsd32_pointer_t contexts;
501 } drm_ctx_res32_t;
502 
503 static int
compat_drm_resctx(struct file * file,void * arg)504 compat_drm_resctx(struct file *file, void *arg)
505 {
506 	drm_ctx_res32_t res32;
507 	struct drm_ctx_res res64;
508 	int error;
509 
510 	if ((error = copyin(&res32, arg, sizeof(res32))) != 0)
511 		return error;
512 
513 	res64.count = res32.count;
514 	res64.contexts = NETBSD32PTR64(res32.contexts);
515 
516 	error = drm_ioctl(file, DRM_IOCTL_RES_CTX, &res64);
517 	if (error)
518 		return error;
519 
520 	res32.count = res64.count;
521 	NETBSD32PTR32(res32.contexts, res64.contexts);
522 	/* XXX: missing copyout */
523 
524 	return copyout(arg, &res32, sizeof(res32));
525 }
526 
527 typedef struct drm_dma32 {
528 	int context;			  /**< Context handle */
529 	int send_count;			  /**< Number of buffers to send */
530 	netbsd32_pointer_t send_indices;  /**< List of handles to buffers */
531 	netbsd32_pointer_t send_sizes;	  /**< Lengths of data to send */
532 	enum drm_dma_flags flags;	  /**< Flags */
533 	netbsd32_pointer_t request_count; /**< Number of buffers requested */
534 	int request_size;		  /**< Desired size for buffers */
535 	netbsd32_pointer_t request_indices; /**< Buffer information */
536 	netbsd32_pointer_t request_sizes;
537 	int granted_count;		  /**< Number of buffers granted */
538 } drm_dma32_t;
539 
540 static void
dma64to32(drm_dma32_t * d32,const struct drm_dma * d64)541 dma64to32(drm_dma32_t *d32, const struct drm_dma *d64)
542 {
543 	d32->send_count = d64->send_count;
544 	NETBSD32PTR32(d32->send_indices, d64->send_indices);
545 	NETBSD32PTR32(d32->send_sizes, d64->send_sizes);
546 	d32->flags = d64->flags;
547 	NETBSD32PTR32(d32->request_count, (void *)(long)d64->request_count);
548 	NETBSD32PTR32(d32->request_indices, d64->request_indices);
549 	NETBSD32PTR32(d32->request_sizes, d64->request_sizes);
550 
551 }
552 
553 static void
dma32to64(struct drm_dma * d64,const drm_dma32_t * d32)554 dma32to64(struct drm_dma *d64, const drm_dma32_t *d32)
555 {
556 	d64->request_size = d32->request_size;
557 	d64->granted_count = d32->granted_count;
558 }
559 
560 static int
compat_drm_dma(struct file * file,void * arg)561 compat_drm_dma(struct file *file, void *arg)
562 {
563 	drm_dma32_t d32;
564 	struct drm_dma d64;
565 	int error;
566 
567 	if ((error = copyin(&d32, arg, sizeof(d32))) != 0)
568 		return error;
569 
570 	dma32to64(&d64, &d32);
571 
572 	error = drm_ioctl(file, DRM_IOCTL_DMA, &d64);
573 	if (error)
574 		return error;
575 
576 	dma64to32(&d32, &d64);
577 
578 	return copyout(arg, &d32, sizeof(d32));
579 }
580 
581 //XXX:i commented the below line for later use
582 #if IS_ENABLED(CONFIG_AGP)
583 typedef struct drm_agp_mode32 {
584 	uint32_t mode;	/**< AGP mode */
585 } drm_agp_mode32_t;
586 
587 static int
compat_drm_agp_enable(struct file * file,void * arg)588 compat_drm_agp_enable(struct file *file, void *arg)
589 {
590 	drm_agp_mode32_t m32;
591 	struct drm_agp_mode m64;
592 	int error;
593 
594 	if ((error = copyin(&m32, arg, sizeof(m32))) != 0)
595 		return error;
596 
597 	m64.mode = m32.mode;
598 
599 	return drm_ioctl(file, DRM_IOCTL_AGP_ENABLE, &m64);
600 }
601 
602 typedef struct drm_agp_info32 {
603 	int agp_version_major;
604 	int agp_version_minor;
605 	uint32_t mode;
606 	uint32_t aperture_base;		/* physical address */
607 	uint32_t aperture_size;		/* bytes */
608 	uint32_t memory_allowed;	/* bytes */
609 	uint32_t memory_used;
610 
611 	/* PCI information */
612 	unsigned short id_vendor;
613 	unsigned short id_device;
614 } drm_agp_info32_t;
615 
616 static void
info64to32(drm_agp_info32_t * i32,const struct drm_agp_info * i64)617 info64to32(drm_agp_info32_t *i32, const struct drm_agp_info *i64)
618 {
619 	i32->agp_version_major = i64->agp_version_major;
620 	i32->agp_version_minor = i64->agp_version_minor;
621 	i32->mode = i64->mode;
622 	i32->aperture_base = i64->aperture_base;
623 	i32->aperture_size = i64->aperture_size;
624 	i32->memory_allowed = i64->memory_allowed;
625 	i32->memory_used = i64->memory_used;
626 	i32->id_vendor = i64->id_vendor;
627 	i32->id_device = i64->id_device;
628 }
629 
630 static int
compat_drm_agp_info(struct file * file,void * arg)631 compat_drm_agp_info(struct file *file, void *arg)
632 {
633 	drm_agp_info32_t i32;
634 	struct drm_agp_info i64;
635 	int error;
636 
637 	error = drm_ioctl(file, DRM_IOCTL_AGP_INFO, &i64);
638 	if (error)
639 		return error;
640 
641 	info64to32(&i32, &i64);
642 
643 	return copyout(arg, &i32, sizeof(i32));
644 
645 }
646 
647 typedef struct drm_agp_buffer32 {
648 	uint32_t size;		/**< In bytes -- will round to page boundary */
649 	uint32_t handle;	/**< Used for binding / unbinding */
650 	uint32_t type;		/**< Type of memory to allocate */
651 	uint32_t physical;	/**< Physical used by i810 */
652 } drm_agp_buffer32_t;
653 
654 static int
compat_drm_agp_alloc(struct file * file,void * arg)655 compat_drm_agp_alloc(struct file *file, void *arg)
656 {
657 	drm_agp_buffer32_t req32;
658 	struct drm_agp_buffer req64;
659 	int error;
660 
661 	if ((error = copyin(&req32, arg, sizeof(req32))) != 0)
662 		return error;
663 
664 	req64.size = req32.size;
665 	req64.type = req32.type;
666 
667 	error = drm_ioctl(file, DRM_IOCTL_AGP_ALLOC, &req64);
668 	if (error)
669 		return error;
670 
671 	req32.handle = req64.handle;
672 	req32.physical = req64.physical;
673 
674 	drm_ioctl(file, DRM_IOCTL_AGP_FREE, &req64);
675 
676 	return copyout(arg, &req32, sizeof(req32));
677 }
678 
679 static int
compat_drm_agp_free(struct file * file,void * arg)680 compat_drm_agp_free(struct file *file, void *arg)
681 {
682 	drm_agp_buffer32_t req32;
683 	struct drm_agp_buffer req64;
684 	int error;
685 	uint32_t handle;
686 
687 	if ((error = copyin(&req32, arg, sizeof(req32))) != 0)
688 		return error;
689 
690 	handle = req32.handle;
691 	req64.handle = handle;
692 
693 	return drm_ioctl(file, DRM_IOCTL_AGP_FREE, &req64);
694 }
695 
696 typedef struct drm_agp_binding32 {
697 	uint32_t handle;	/**< From drm_agp_buffer */
698 	uint32_t offset;	/**< In bytes -- will round to page boundary */
699 } drm_agp_binding32_t;
700 
701 static int
compat_drm_agp_bind(struct file * file,void * arg)702 compat_drm_agp_bind(struct file *file, void *arg)
703 {
704 	drm_agp_binding32_t req32;
705 	struct drm_agp_binding req64;
706 	int error;
707 
708 	if ((error = copyin(&req32, arg, sizeof(req32))) !=0 )
709 		return error;
710 
711 	req64.handle = req32.handle;
712 	req64.offset = req32.offset;
713 
714 	return drm_ioctl(file, DRM_IOCTL_AGP_BIND, &req64);
715 }
716 
717 static int
compat_drm_agp_unbind(struct file * file,void * arg)718 compat_drm_agp_unbind(struct file *file, void *arg)
719 {
720 	struct drm_agp_binding req64;
721 	drm_agp_binding32_t req32;
722 	uint32_t handle;
723 	int error;
724 
725 	if ((error = copyin(&req32, arg, sizeof(req32))) != 0)
726 		return error;
727 
728 	handle = req32.handle;
729 	req64.handle = handle;
730 
731 	return drm_ioctl(file, DRM_IOCTL_AGP_UNBIND, &req64);
732 }
733 #endif /* CONFIG_AGP */
734 
735 typedef struct drm_scatter_gather32 {
736 	uint32_t size;		/**< In bytes -- will round to page boundary */
737 	uint32_t handle;	/**< Used for mapping / unmapping */
738 } drm_scatter_gather32_t;
739 
740 static int
compat_drm_sg_alloc(struct file * file,void * arg)741 compat_drm_sg_alloc(struct file *file, void *arg)
742 {
743 	struct drm_scatter_gather req64;
744 	drm_scatter_gather32_t req32;
745 	int error;
746 
747 	if ((error = copyin(&req32, arg, sizeof(req32))) != 0)
748 		return error;
749 
750 	req64.size = req32.size;
751 
752 	error = drm_ioctl(file, DRM_IOCTL_SG_ALLOC, &req64);
753 	if (error)
754 		return error;
755 
756 	/* XXX not sure about the handle conversion here... */
757 	req32.handle = req64.handle >> PAGE_SHIFT;
758 
759 	return 0;
760 }
761 
762 static int
compat_drm_sg_free(struct file * file,void * arg)763 compat_drm_sg_free(struct file *file, void *arg)
764 {
765 	struct drm_scatter_gather req64;
766 	unsigned long x;
767 	drm_scatter_gather32_t req32;
768 	int error;
769 
770 	if((error = copyin(&req32, arg, sizeof(req32))) != 0)
771 		return error;
772 
773 	x = req32.handle;
774 	req64.handle = x << PAGE_SHIFT;
775 
776 	return drm_ioctl(file, DRM_IOCTL_SG_FREE, &req64);
777 }
778 
779 #if defined(CONFIG_X86) || defined(CONFIG_IA64)
780 typedef struct drm_update_draw32 {
781 	drm_drawable_t handle;
782 	unsigned int type;
783 	unsigned int num;
784 	/* 64-bit version has a 32-bit pad here */
785 	uint64_t data;	/**< Pointer */
786 } __attribute__((__packed__)) drm_update_draw32_t;
787 
788 static void
update32to64(struct drm_update_draw * req64,const drm_update_draw32_t * update32)789 update32to64(struct drm_update_draw *req64, const drm_update_draw32_t *update32)
790 {
791 	req64->handle = update32->handle;
792 	req64->type = update32->type;
793 	req64->num = update32->num;
794 	req64->data = update32->data;
795 }
796 static int
compat_drm_update_draw(struct file * file,void * arg)797 compat_drm_update_draw(struct file *file, void *arg)
798 {
799 	drm_update_draw32_t update32;
800 	struct drm_update_draw req64;
801 	int error;
802 
803 	if ((error = copyin(&update32, arg, sizeof(update32))) !=0)
804 		return error;
805 
806 	update32to64(&req64, &update32);
807 
808 	error = drm_ioctl(file, DRM_IOCTL_UPDATE_DRAW, &req64);
809 	return error;
810 }
811 #endif
812 
813 struct drm_wait_vblank_request32 {
814 	enum drm_vblank_seq_type type;
815 	unsigned int sequence;
816 	uint32_t signal;
817 };
818 
819 struct drm_wait_vblank_reply32 {
820 	enum drm_vblank_seq_type type;
821 	unsigned int sequence;
822 	s32 tval_sec;
823 	s32 tval_usec;
824 };
825 
826 typedef union drm_wait_vblank32 {
827 	struct drm_wait_vblank_request32 request;
828 	struct drm_wait_vblank_reply32 reply;
829 } drm_wait_vblank32_t;
830 
831 static void
req32to64(union drm_wait_vblank * req64,const drm_wait_vblank32_t * req32)832 req32to64(union drm_wait_vblank *req64, const drm_wait_vblank32_t *req32)
833 {
834 	req64->request.type = req32->request.type;
835 	req64->request.sequence = req32->request.sequence;
836 	req64->request.signal = req32->request.signal;
837 }
838 
839 static void
req64to32(drm_wait_vblank32_t * req32,const union drm_wait_vblank * req64)840 req64to32(drm_wait_vblank32_t *req32, const union drm_wait_vblank *req64)
841 {
842 	req32->reply.sequence = req64->reply.sequence;
843 	req32->reply.tval_sec = req64->reply.tval_sec;
844 	req32->reply.tval_usec = req64->reply.tval_usec;
845 }
846 
847 static int
compat_drm_wait_vblank(struct file * file,void * arg)848 compat_drm_wait_vblank(struct file *file, void *arg)
849 {
850 	drm_wait_vblank32_t req32;
851 	union drm_wait_vblank req64;
852 	int error;
853 
854 	if ((error = copyin(&req32, arg, sizeof(req32))) != 0)
855 		return error;
856 
857 	req32to64(&req64, &req32);
858 
859 	error = drm_ioctl(file, DRM_IOCTL_WAIT_VBLANK, &req64);
860 	if (error)
861 		return error;
862 
863 	req64to32(&req32, &req64);
864 
865 	return copyout(arg, &req32, sizeof(req32));
866 }
867 
868 #if defined(CONFIG_X86) || defined(CONFIG_IA64)
869 typedef struct drm_mode_fb_cmd232 {
870 	uint32_t fb_id;
871 	uint32_t width;
872 	uint32_t height;
873 	uint32_t pixel_format;
874 	uint32_t flags;
875 	uint32_t handles[4];
876 	uint32_t pitches[4];
877 	uint32_t offsets[4];
878 	uint64_t modifier[4];
879 } __attribute__((__packed__)) drm_mode_fb_cmd232_t;
880 
881 static void
map_req32to64(struct drm_mode_fb_cmd2 * req64,struct drm_mode_fb_cmd232 * req32)882 map_req32to64(struct drm_mode_fb_cmd2 *req64, struct drm_mode_fb_cmd232 *req32)
883 {
884 	req64->width = req32->width;
885 	req64->height = req32->height;
886 	req64->pixel_format = req32->pixel_format;
887 	req64->flags = req32->flags;
888 }
889 
890 static int
compat_drm_mode_addfb2(struct file * file,void * arg)891 compat_drm_mode_addfb2(struct file *file, void *arg)
892 {
893 	struct drm_mode_fb_cmd232 req32;
894 	struct drm_mode_fb_cmd2 req64;
895 	int error;
896 
897 	if ((error = copyin(&req32, arg, sizeof(req32))) != 0)
898 		return error;
899 
900 	map_req32to64(&req64, &req32);
901 
902 	for (int i = 0; i < 4; i++){
903 		req64.handles[i] = req32.handles[i];
904 		req64.pitches[i] = req32.pitches[i];
905 		req64.offsets[i] = req32.offsets[i];
906 		req64.modifier[i] = req32.modifier[i];
907 	}
908 
909 	error = drm_ioctl(file, DRM_IOCTL_MODE_ADDFB2, &req64);
910 	if (error)
911 		return error;
912 
913 	req32.fb_id = req64.fb_id;
914 
915 	return copyout(arg, &req32, sizeof(req32));
916 }
917 #endif
918 
919 int
netbsd32_drm_ioctl(struct file * file,unsigned long cmd,void * arg,struct lwp * l)920 netbsd32_drm_ioctl(struct file *file, unsigned long cmd, void *arg,
921     struct lwp *l)
922 {
923 	switch (cmd) {
924 	case DRM_IOCTL_VERSION32:
925 		return compat_drm_version(file, arg);
926 	case DRM_IOCTL_GET_UNIQUE32:
927 		return compat_drm_getunique(file, arg);
928 	case DRM_IOCTL_SET_UNIQUE32:
929 		return compat_drm_setunique(file, arg);
930 	case DRM_IOCTL_GET_MAP32:
931 		return compat_drm_getmap(file, arg);
932 	case DRM_IOCTL_ADD_MAP32:
933 		return compat_drm_addmap(file, arg);
934 	case DRM_IOCTL_RM_MAP32:
935 		return compat_drm_rmmap(file, arg);
936 	case DRM_IOCTL_GET_CLIENT32:
937 		return compat_drm_getclient(file, arg);
938 	case DRM_IOCTL_GET_STATS32:
939 		return compat_drm_getstats(file, arg);
940 	case DRM_IOCTL_ADD_BUFS32:
941 		return compat_drm_addbufs(file, arg);
942 	case DRM_IOCTL_MARK_BUFS32:
943 		return compat_drm_markbufs(file, arg);
944 	case DRM_IOCTL_FREE_BUFS32:
945 		return compat_drm_freebufs(file, arg);
946 	case DRM_IOCTL_SET_SAREA_CTX32:
947 		return compat_drm_setsareactx(file, arg);
948 	case DRM_IOCTL_GET_SAREA_CTX32:
949 		return compat_drm_getsareactx(file, arg);
950 	case DRM_IOCTL_RES_CTX32:
951 		return compat_drm_resctx(file, arg);
952 	case DRM_IOCTL_DMA32:
953 		return compat_drm_dma(file, arg);
954 	case  DRM_IOCTL_AGP_ENABLE32:
955 		return compat_drm_agp_enable(file, arg);
956 	case DRM_IOCTL_AGP_INFO32:
957 		return compat_drm_agp_info(file, arg);
958 	case DRM_IOCTL_AGP_ALLOC32:
959 		return compat_drm_agp_alloc(file,arg);
960 	case DRM_IOCTL_AGP_UNBIND32:
961 		return compat_drm_agp_unbind(file, arg);
962 	case DRM_IOCTL_AGP_BIND32:
963 		return compat_drm_agp_bind(file, arg);
964 	case DRM_IOCTL_AGP_FREE32:
965 		return compat_drm_agp_free(file, arg);
966 	case DRM_IOCTL_SG_ALLOC32:
967 		return compat_drm_sg_alloc(file, arg);
968 	case  DRM_IOCTL_MODE_ADDFB232:
969 		return compat_drm_mode_addfb2(file, arg);
970 	case DRM_IOCTL_WAIT_VBLANK32:
971 		return compat_drm_wait_vblank(file, arg);
972 	case DRM_IOCTL_UPDATE_DRAW32:
973 		return compat_drm_update_draw(file, arg);
974 	case DRM_IOCTL_SG_FREE32:
975 		return compat_drm_sg_free(file, arg);
976 	default:
977 		return EINVAL;
978 	}
979 }
980