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