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