Home | History | Annotate | Line # | Download | only in netbsd32
      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
     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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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