1 /** 2 * \file xf86drm.c 3 * User-level interface to DRM device 4 * 5 * \author Rickard E. (Rik) Faith <faith (at) valinux.com> 6 * \author Kevin E. Martin <martin (at) valinux.com> 7 */ 8 9 /* 10 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. 11 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 12 * All Rights Reserved. 13 * 14 * Permission is hereby granted, free of charge, to any person obtaining a 15 * copy of this software and associated documentation files (the "Software"), 16 * to deal in the Software without restriction, including without limitation 17 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 18 * and/or sell copies of the Software, and to permit persons to whom the 19 * Software is furnished to do so, subject to the following conditions: 20 * 21 * The above copyright notice and this permission notice (including the next 22 * paragraph) shall be included in all copies or substantial portions of the 23 * Software. 24 * 25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 28 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 29 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 30 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 31 * DEALINGS IN THE SOFTWARE. 32 */ 33 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <stdbool.h> 37 #include <unistd.h> 38 #include <string.h> 39 #include <strings.h> 40 #include <ctype.h> 41 #include <dirent.h> 42 #include <stddef.h> 43 #include <fcntl.h> 44 #include <errno.h> 45 #include <libgen.h> 46 #include <limits.h> 47 #include <signal.h> 48 #include <time.h> 49 #include <sys/types.h> 50 #include <sys/stat.h> 51 #define stat_t struct stat 52 #include <sys/ioctl.h> 53 #include <sys/time.h> 54 #include <stdarg.h> 55 #ifdef MAJOR_IN_MKDEV 56 #include <sys/mkdev.h> 57 #endif 58 #ifdef MAJOR_IN_SYSMACROS 59 #include <sys/sysmacros.h> 60 #endif 61 #if HAVE_SYS_SYSCTL_H 62 #include <sys/sysctl.h> 63 #endif 64 #include <inttypes.h> 65 66 #if defined(__FreeBSD__) 67 #include <sys/param.h> 68 #include <sys/pciio.h> 69 #endif 70 71 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) 72 73 /* Not all systems have MAP_FAILED defined */ 74 #ifndef MAP_FAILED 75 #define MAP_FAILED ((void *)-1) 76 #endif 77 78 #include "xf86drm.h" 79 #include "libdrm_macros.h" 80 #include "drm_fourcc.h" 81 82 #include "util_math.h" 83 84 #ifdef __DragonFly__ 85 #define DRM_MAJOR 145 86 #endif 87 88 #ifdef __NetBSD__ 89 #undef DRM_MAJOR 90 #define DRM_MAJOR 180 91 #include <sys/param.h> 92 #include <dev/pci/pcireg.h> 93 #include <pci.h> 94 #endif 95 96 #ifdef __OpenBSD__ 97 #ifdef __i386__ 98 #define DRM_MAJOR 88 99 #else 100 #define DRM_MAJOR 87 101 #endif 102 #endif /* __OpenBSD__ */ 103 104 #ifndef DRM_MAJOR 105 #define DRM_MAJOR 226 /* Linux */ 106 #endif 107 108 #if defined(__OpenBSD__) || defined(__DragonFly__) 109 struct drm_pciinfo { 110 uint16_t domain; 111 uint8_t bus; 112 uint8_t dev; 113 uint8_t func; 114 uint16_t vendor_id; 115 uint16_t device_id; 116 uint16_t subvendor_id; 117 uint16_t subdevice_id; 118 uint8_t revision_id; 119 }; 120 121 #define DRM_IOCTL_GET_PCIINFO DRM_IOR(0x15, struct drm_pciinfo) 122 #endif 123 124 #define DRM_MSG_VERBOSITY 3 125 126 #define memclear(s) memset(&s, 0, sizeof(s)) 127 128 static drmServerInfoPtr drm_server_info; 129 130 static bool drmNodeIsDRM(int maj, int min); 131 static char *drmGetMinorNameForFD(int fd, int type); 132 133 #define DRM_MODIFIER(v, f, f_name) \ 134 .modifier = DRM_FORMAT_MOD_##v ## _ ##f, \ 135 .modifier_name = #f_name 136 137 #define DRM_MODIFIER_INVALID(v, f_name) \ 138 .modifier = DRM_FORMAT_MOD_INVALID, .modifier_name = #f_name 139 140 #define DRM_MODIFIER_LINEAR(v, f_name) \ 141 .modifier = DRM_FORMAT_MOD_LINEAR, .modifier_name = #f_name 142 143 /* Intel is abit special as the format doesn't follow other vendors naming 144 * scheme */ 145 #define DRM_MODIFIER_INTEL(f, f_name) \ 146 .modifier = I915_FORMAT_MOD_##f, .modifier_name = #f_name 147 148 struct drmFormatModifierInfo { 149 uint64_t modifier; 150 const char *modifier_name; 151 }; 152 153 struct drmFormatModifierVendorInfo { 154 uint8_t vendor; 155 const char *vendor_name; 156 }; 157 158 #include "generated_static_table_fourcc.h" 159 160 struct drmVendorInfo { 161 uint8_t vendor; 162 char *(*vendor_cb)(uint64_t modifier); 163 }; 164 165 struct drmFormatVendorModifierInfo { 166 uint64_t modifier; 167 const char *modifier_name; 168 }; 169 170 static char * 171 drmGetFormatModifierNameFromArm(uint64_t modifier); 172 173 static char * 174 drmGetFormatModifierNameFromNvidia(uint64_t modifier); 175 176 static char * 177 drmGetFormatModifierNameFromAmd(uint64_t modifier); 178 179 static char * 180 drmGetFormatModifierNameFromAmlogic(uint64_t modifier); 181 182 static char * 183 drmGetFormatModifierNameFromVivante(uint64_t modifier); 184 185 static const struct drmVendorInfo modifier_format_vendor_table[] = { 186 { DRM_FORMAT_MOD_VENDOR_ARM, drmGetFormatModifierNameFromArm }, 187 { DRM_FORMAT_MOD_VENDOR_NVIDIA, drmGetFormatModifierNameFromNvidia }, 188 { DRM_FORMAT_MOD_VENDOR_AMD, drmGetFormatModifierNameFromAmd }, 189 { DRM_FORMAT_MOD_VENDOR_AMLOGIC, drmGetFormatModifierNameFromAmlogic }, 190 { DRM_FORMAT_MOD_VENDOR_VIVANTE, drmGetFormatModifierNameFromVivante }, 191 }; 192 193 #ifndef AFBC_FORMAT_MOD_MODE_VALUE_MASK 194 #define AFBC_FORMAT_MOD_MODE_VALUE_MASK 0x000fffffffffffffULL 195 #endif 196 197 static const struct drmFormatVendorModifierInfo arm_mode_value_table[] = { 198 { AFBC_FORMAT_MOD_YTR, "YTR" }, 199 { AFBC_FORMAT_MOD_SPLIT, "SPLIT" }, 200 { AFBC_FORMAT_MOD_SPARSE, "SPARSE" }, 201 { AFBC_FORMAT_MOD_CBR, "CBR" }, 202 { AFBC_FORMAT_MOD_TILED, "TILED" }, 203 { AFBC_FORMAT_MOD_SC, "SC" }, 204 { AFBC_FORMAT_MOD_DB, "DB" }, 205 { AFBC_FORMAT_MOD_BCH, "BCH" }, 206 { AFBC_FORMAT_MOD_USM, "USM" }, 207 }; 208 209 static bool 210 drmGetAfbcFormatModifierNameFromArm(uint64_t modifier, FILE *fp) 211 { 212 uint64_t mode_value = modifier & AFBC_FORMAT_MOD_MODE_VALUE_MASK; 213 uint64_t block_size = mode_value & AFBC_FORMAT_MOD_BLOCK_SIZE_MASK; 214 215 const char *block = NULL; 216 const char *mode = NULL; 217 bool did_print_mode = false; 218 219 /* add block, can only have a (single) block */ 220 switch (block_size) { 221 case AFBC_FORMAT_MOD_BLOCK_SIZE_16x16: 222 block = "16x16"; 223 break; 224 case AFBC_FORMAT_MOD_BLOCK_SIZE_32x8: 225 block = "32x8"; 226 break; 227 case AFBC_FORMAT_MOD_BLOCK_SIZE_64x4: 228 block = "64x4"; 229 break; 230 case AFBC_FORMAT_MOD_BLOCK_SIZE_32x8_64x4: 231 block = "32x8_64x4"; 232 break; 233 } 234 235 if (!block) { 236 return false; 237 } 238 239 fprintf(fp, "BLOCK_SIZE=%s,", block); 240 241 /* add mode */ 242 for (unsigned int i = 0; i < ARRAY_SIZE(arm_mode_value_table); i++) { 243 if (arm_mode_value_table[i].modifier & mode_value) { 244 mode = arm_mode_value_table[i].modifier_name; 245 if (!did_print_mode) { 246 fprintf(fp, "MODE=%s", mode); 247 did_print_mode = true; 248 } else { 249 fprintf(fp, "|%s", mode); 250 } 251 } 252 } 253 254 return true; 255 } 256 257 static bool 258 drmGetAfrcFormatModifierNameFromArm(uint64_t modifier, FILE *fp) 259 { 260 bool scan_layout; 261 for (unsigned int i = 0; i < 2; ++i) { 262 uint64_t coding_unit_block = 263 (modifier >> (i * 4)) & AFRC_FORMAT_MOD_CU_SIZE_MASK; 264 const char *coding_unit_size = NULL; 265 266 switch (coding_unit_block) { 267 case AFRC_FORMAT_MOD_CU_SIZE_16: 268 coding_unit_size = "CU_16"; 269 break; 270 case AFRC_FORMAT_MOD_CU_SIZE_24: 271 coding_unit_size = "CU_24"; 272 break; 273 case AFRC_FORMAT_MOD_CU_SIZE_32: 274 coding_unit_size = "CU_32"; 275 break; 276 } 277 278 if (!coding_unit_size) { 279 if (i == 0) { 280 return false; 281 } 282 break; 283 } 284 285 if (i == 0) { 286 fprintf(fp, "P0=%s,", coding_unit_size); 287 } else { 288 fprintf(fp, "P12=%s,", coding_unit_size); 289 } 290 } 291 292 scan_layout = 293 (modifier & AFRC_FORMAT_MOD_LAYOUT_SCAN) == AFRC_FORMAT_MOD_LAYOUT_SCAN; 294 if (scan_layout) { 295 fprintf(fp, "SCAN"); 296 } else { 297 fprintf(fp, "ROT"); 298 } 299 return true; 300 } 301 302 static char * 303 drmGetFormatModifierNameFromArm(uint64_t modifier) 304 { 305 uint64_t type = (modifier >> 52) & 0xf; 306 307 FILE *fp; 308 size_t size = 0; 309 char *modifier_name = NULL; 310 bool result = false; 311 312 fp = open_memstream(&modifier_name, &size); 313 if (!fp) 314 return NULL; 315 316 switch (type) { 317 case DRM_FORMAT_MOD_ARM_TYPE_AFBC: 318 result = drmGetAfbcFormatModifierNameFromArm(modifier, fp); 319 break; 320 case DRM_FORMAT_MOD_ARM_TYPE_AFRC: 321 result = drmGetAfrcFormatModifierNameFromArm(modifier, fp); 322 break; 323 /* misc type is already handled by the static table */ 324 case DRM_FORMAT_MOD_ARM_TYPE_MISC: 325 default: 326 result = false; 327 break; 328 } 329 330 fclose(fp); 331 if (!result) { 332 free(modifier_name); 333 return NULL; 334 } 335 336 return modifier_name; 337 } 338 339 static char * 340 drmGetFormatModifierNameFromNvidia(uint64_t modifier) 341 { 342 uint64_t height, kind, gen, sector, compression; 343 344 height = modifier & 0xf; 345 kind = (modifier >> 12) & 0xff; 346 347 gen = (modifier >> 20) & 0x3; 348 sector = (modifier >> 22) & 0x1; 349 compression = (modifier >> 23) & 0x7; 350 351 /* just in case there could other simpler modifiers, not yet added, avoid 352 * testing against TEGRA_TILE */ 353 if ((modifier & 0x10) == 0x10) { 354 char *mod_nvidia; 355 if (asprintf(&mod_nvidia, "BLOCK_LINEAR_2D,HEIGHT=%"PRIu64",KIND=%"PRIu64"," 356 "GEN=%"PRIu64",SECTOR=%"PRIu64",COMPRESSION=%"PRIu64"", height, 357 kind, gen, sector, compression) < 0) 358 mod_nvidia = NULL; 359 return mod_nvidia; 360 } 361 362 return NULL; 363 } 364 365 static char * 366 drmGetFormatModifierNameFromAmd(uint64_t modifier) 367 { 368 static const char *gfx9_gfx11_tile_strings[32] = { 369 "LINEAR", 370 "256B_S", 371 "256B_D", 372 "256B_R", 373 "4KB_Z", 374 "4KB_S", 375 "4KB_D", 376 "4KB_R", 377 "64KB_Z", 378 "64KB_S", 379 "64KB_D", 380 "64KB_R", 381 "INVALID12", 382 "INVALID13", 383 "INVALID14", 384 "INVALID15", 385 "64KB_Z_T", 386 "64KB_S_T", 387 "64KB_D_T", 388 "64KB_R_T", 389 "4KB_Z_X", 390 "4KB_S_X", 391 "4KB_D_X", 392 "4KB_R_X", 393 "64KB_Z_X", 394 "64KB_S_X", 395 "64KB_D_X", 396 "64KB_R_X", 397 "256KB_Z_X", 398 "256KB_S_X", 399 "256KB_D_X", 400 "256KB_R_X", 401 }; 402 static const char *gfx12_tile_strings[32] = { 403 "LINEAR", 404 "256B_2D", 405 "4KB_2D", 406 "64KB_2D", 407 "256KB_2D", 408 "4KB_3D", 409 "64KB_3D", 410 "256KB_3D", 411 /* other values are unused */ 412 }; 413 uint64_t tile_version = AMD_FMT_MOD_GET(TILE_VERSION, modifier); 414 FILE *fp; 415 char *mod_amd = NULL; 416 size_t size = 0; 417 418 fp = open_memstream(&mod_amd, &size); 419 if (!fp) 420 return NULL; 421 422 switch (tile_version) { 423 case AMD_FMT_MOD_TILE_VER_GFX9: 424 fprintf(fp, "GFX9"); 425 break; 426 case AMD_FMT_MOD_TILE_VER_GFX10: 427 fprintf(fp, "GFX10"); 428 break; 429 case AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS: 430 fprintf(fp, "GFX10_RBPLUS"); 431 break; 432 case AMD_FMT_MOD_TILE_VER_GFX11: 433 fprintf(fp, "GFX11"); 434 break; 435 case AMD_FMT_MOD_TILE_VER_GFX12: 436 fprintf(fp, "GFX12"); 437 break; 438 default: 439 fclose(fp); 440 free(mod_amd); 441 return NULL; 442 } 443 444 if (tile_version >= AMD_FMT_MOD_TILE_VER_GFX12) { 445 unsigned tile = AMD_FMT_MOD_GET(TILE, modifier); 446 447 fprintf(fp, ",%s", gfx12_tile_strings[tile]); 448 449 if (AMD_FMT_MOD_GET(DCC, modifier)) { 450 fprintf(fp, ",DCC,DCC_MAX_COMPRESSED_BLOCK=%uB", 451 64 << AMD_FMT_MOD_GET(DCC_MAX_COMPRESSED_BLOCK, modifier)); 452 453 /* Other DCC fields are unused by GFX12. */ 454 } 455 } else { 456 unsigned tile = AMD_FMT_MOD_GET(TILE, modifier); 457 458 fprintf(fp, ",%s", gfx9_gfx11_tile_strings[tile]); 459 460 /* All *_T and *_X modes are affected by chip-specific fields. */ 461 if (tile >= 16) { 462 fprintf(fp, ",PIPE_XOR_BITS=%u", 463 (unsigned)AMD_FMT_MOD_GET(PIPE_XOR_BITS, modifier)); 464 465 switch (tile_version) { 466 case AMD_FMT_MOD_TILE_VER_GFX9: 467 fprintf(fp, ",BANK_XOR_BITS=%u", 468 (unsigned)AMD_FMT_MOD_GET(BANK_XOR_BITS, modifier)); 469 break; 470 471 case AMD_FMT_MOD_TILE_VER_GFX10: 472 /* Nothing else for GFX10. */ 473 break; 474 475 case AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS: 476 case AMD_FMT_MOD_TILE_VER_GFX11: 477 /* This also determines the DCC layout, but DCC is only legal 478 * with tile=27 and tile=31 (*_R_X modes). 479 */ 480 fprintf(fp, ",PACKERS=%u", 481 (unsigned)AMD_FMT_MOD_GET(PACKERS, modifier)); 482 break; 483 } 484 } 485 486 if (AMD_FMT_MOD_GET(DCC, modifier)) { 487 if (tile_version == AMD_FMT_MOD_TILE_VER_GFX9 && 488 (AMD_FMT_MOD_GET(DCC_PIPE_ALIGN, modifier) || 489 AMD_FMT_MOD_GET(DCC_RETILE, modifier))) { 490 /* These two only determine the layout of 491 * the non-displayable DCC plane. 492 */ 493 fprintf(fp, ",RB=%u", 494 (unsigned)AMD_FMT_MOD_GET(RB, modifier)); 495 fprintf(fp, ",PIPE=%u", 496 (unsigned)AMD_FMT_MOD_GET(PIPE, modifier)); 497 } 498 499 fprintf(fp, ",DCC,DCC_MAX_COMPRESSED_BLOCK=%uB", 500 64 << AMD_FMT_MOD_GET(DCC_MAX_COMPRESSED_BLOCK, modifier)); 501 502 if (AMD_FMT_MOD_GET(DCC_INDEPENDENT_64B, modifier)) 503 fprintf(fp, ",DCC_INDEPENDENT_64B"); 504 505 if (AMD_FMT_MOD_GET(DCC_INDEPENDENT_128B, modifier)) 506 fprintf(fp, ",DCC_INDEPENDENT_128B"); 507 508 if (AMD_FMT_MOD_GET(DCC_CONSTANT_ENCODE, modifier)) 509 fprintf(fp, ",DCC_CONSTANT_ENCODE"); 510 511 if (AMD_FMT_MOD_GET(DCC_PIPE_ALIGN, modifier)) 512 fprintf(fp, ",DCC_PIPE_ALIGN"); 513 514 if (AMD_FMT_MOD_GET(DCC_RETILE, modifier)) 515 fprintf(fp, ",DCC_RETILE"); 516 } 517 } 518 519 fclose(fp); 520 return mod_amd; 521 } 522 523 static char * 524 drmGetFormatModifierNameFromAmlogic(uint64_t modifier) 525 { 526 uint64_t layout = modifier & 0xff; 527 uint64_t options = (modifier >> 8) & 0xff; 528 char *mod_amlogic = NULL; 529 530 const char *layout_str; 531 const char *opts_str; 532 533 switch (layout) { 534 case AMLOGIC_FBC_LAYOUT_BASIC: 535 layout_str = "BASIC"; 536 break; 537 case AMLOGIC_FBC_LAYOUT_SCATTER: 538 layout_str = "SCATTER"; 539 break; 540 default: 541 layout_str = "INVALID_LAYOUT"; 542 break; 543 } 544 545 if (options & AMLOGIC_FBC_OPTION_MEM_SAVING) 546 opts_str = "MEM_SAVING"; 547 else 548 opts_str = "0"; 549 550 if (asprintf(&mod_amlogic, "FBC,LAYOUT=%s,OPTIONS=%s", layout_str, opts_str) < 0) 551 mod_amlogic = NULL; 552 return mod_amlogic; 553 } 554 555 static char * 556 drmGetFormatModifierNameFromVivante(uint64_t modifier) 557 { 558 const char *color_tiling, *tile_status, *compression; 559 char *mod_vivante = NULL; 560 561 switch (modifier & VIVANTE_MOD_TS_MASK) { 562 case 0: 563 tile_status = ""; 564 break; 565 case VIVANTE_MOD_TS_64_4: 566 tile_status = ",TS=64B_4"; 567 break; 568 case VIVANTE_MOD_TS_64_2: 569 tile_status = ",TS=64B_2"; 570 break; 571 case VIVANTE_MOD_TS_128_4: 572 tile_status = ",TS=128B_4"; 573 break; 574 case VIVANTE_MOD_TS_256_4: 575 tile_status = ",TS=256B_4"; 576 break; 577 default: 578 tile_status = ",TS=UNKNOWN"; 579 break; 580 } 581 582 switch (modifier & VIVANTE_MOD_COMP_MASK) { 583 case 0: 584 compression = ""; 585 break; 586 case VIVANTE_MOD_COMP_DEC400: 587 compression = ",COMP=DEC400"; 588 break; 589 default: 590 compression = ",COMP=UNKNOWN"; 591 break; 592 } 593 594 switch (modifier & ~VIVANTE_MOD_EXT_MASK) { 595 case 0: 596 color_tiling = "LINEAR"; 597 break; 598 case DRM_FORMAT_MOD_VIVANTE_TILED: 599 color_tiling = "TILED"; 600 break; 601 case DRM_FORMAT_MOD_VIVANTE_SUPER_TILED: 602 color_tiling = "SUPER_TILED"; 603 break; 604 case DRM_FORMAT_MOD_VIVANTE_SPLIT_TILED: 605 color_tiling = "SPLIT_TILED"; 606 break; 607 case DRM_FORMAT_MOD_VIVANTE_SPLIT_SUPER_TILED: 608 color_tiling = "SPLIT_SUPER_TILED"; 609 break; 610 default: 611 color_tiling = "UNKNOWN"; 612 break; 613 } 614 615 if (asprintf(&mod_vivante, "%s%s%s", color_tiling, tile_status, compression) < 0) 616 mod_vivante = NULL; 617 return mod_vivante; 618 } 619 620 static unsigned log2_int(unsigned x) 621 { 622 unsigned l; 623 624 if (x < 2) { 625 return 0; 626 } 627 for (l = 2; ; l++) { 628 if ((unsigned)(1 << l) > x) { 629 return l - 1; 630 } 631 } 632 return 0; 633 } 634 635 636 drm_public void drmSetServerInfo(drmServerInfoPtr info) 637 { 638 drm_server_info = info; 639 } 640 641 /** 642 * Output a message to stderr. 643 * 644 * \param format printf() like format string. 645 * 646 * \internal 647 * This function is a wrapper around vfprintf(). 648 */ 649 650 static int DRM_PRINTFLIKE(1, 0) 651 drmDebugPrint(const char *format, va_list ap) 652 { 653 return vfprintf(stderr, format, ap); 654 } 655 656 drm_public void 657 drmMsg(const char *format, ...) 658 { 659 va_list ap; 660 const char *env; 661 if (((env = getenv("LIBGL_DEBUG")) && strstr(env, "verbose")) || 662 (drm_server_info && drm_server_info->debug_print)) 663 { 664 va_start(ap, format); 665 if (drm_server_info) { 666 drm_server_info->debug_print(format,ap); 667 } else { 668 drmDebugPrint(format, ap); 669 } 670 va_end(ap); 671 } 672 } 673 674 static void *drmHashTable = NULL; /* Context switch callbacks */ 675 676 drm_public void *drmGetHashTable(void) 677 { 678 return drmHashTable; 679 } 680 681 drm_public void *drmMalloc(int size) 682 { 683 return calloc(1, size); 684 } 685 686 drm_public void drmFree(void *pt) 687 { 688 free(pt); 689 } 690 691 /** 692 * Call ioctl, restarting if it is interrupted 693 */ 694 drm_public int 695 drmIoctl(int fd, unsigned long request, void *arg) 696 { 697 int ret; 698 699 do { 700 ret = ioctl(fd, request, arg); 701 } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); 702 return ret; 703 } 704 705 static unsigned long drmGetKeyFromFd(int fd) 706 { 707 stat_t st; 708 709 st.st_rdev = 0; 710 fstat(fd, &st); 711 return st.st_rdev; 712 } 713 714 drm_public drmHashEntry *drmGetEntry(int fd) 715 { 716 unsigned long key = drmGetKeyFromFd(fd); 717 void *value; 718 drmHashEntry *entry; 719 720 if (!drmHashTable) 721 drmHashTable = drmHashCreate(); 722 723 if (drmHashLookup(drmHashTable, key, &value)) { 724 entry = drmMalloc(sizeof(*entry)); 725 entry->fd = fd; 726 entry->f = NULL; 727 entry->tagTable = drmHashCreate(); 728 drmHashInsert(drmHashTable, key, entry); 729 } else { 730 entry = value; 731 } 732 return entry; 733 } 734 735 /** 736 * Compare two busid strings 737 * 738 * \param first 739 * \param second 740 * 741 * \return 1 if matched. 742 * 743 * \internal 744 * This function compares two bus ID strings. It understands the older 745 * PCI:b:d:f format and the newer pci:oooo:bb:dd.f format. In the format, o is 746 * domain, b is bus, d is device, f is function. 747 */ 748 static int drmMatchBusID(const char *id1, const char *id2, int pci_domain_ok) 749 { 750 /* First, check if the IDs are exactly the same */ 751 if (strcasecmp(id1, id2) == 0) 752 return 1; 753 754 /* Try to match old/new-style PCI bus IDs. */ 755 if (strncasecmp(id1, "pci", 3) == 0) { 756 unsigned int o1, b1, d1, f1; 757 unsigned int o2, b2, d2, f2; 758 int ret; 759 760 ret = sscanf(id1, "pci:%04x:%02x:%02x.%u", &o1, &b1, &d1, &f1); 761 if (ret != 4) { 762 o1 = 0; 763 ret = sscanf(id1, "PCI:%u:%u:%u", &b1, &d1, &f1); 764 if (ret != 3) 765 return 0; 766 } 767 768 ret = sscanf(id2, "pci:%04x:%02x:%02x.%u", &o2, &b2, &d2, &f2); 769 if (ret != 4) { 770 o2 = 0; 771 ret = sscanf(id2, "PCI:%u:%u:%u", &b2, &d2, &f2); 772 if (ret != 3) 773 return 0; 774 } 775 776 /* If domains aren't properly supported by the kernel interface, 777 * just ignore them, which sucks less than picking a totally random 778 * card with "open by name" 779 */ 780 if (!pci_domain_ok) 781 o1 = o2 = 0; 782 783 if ((o1 != o2) || (b1 != b2) || (d1 != d2) || (f1 != f2)) 784 return 0; 785 else 786 return 1; 787 } 788 return 0; 789 } 790 791 /** 792 * Handles error checking for chown call. 793 * 794 * \param path to file. 795 * \param id of the new owner. 796 * \param id of the new group. 797 * 798 * \return zero if success or -1 if failure. 799 * 800 * \internal 801 * Checks for failure. If failure was caused by signal call chown again. 802 * If any other failure happened then it will output error message using 803 * drmMsg() call. 804 */ 805 #if !UDEV 806 static int chown_check_return(const char *path, uid_t owner, gid_t group) 807 { 808 int rv; 809 810 do { 811 rv = chown(path, owner, group); 812 } while (rv != 0 && errno == EINTR); 813 814 if (rv == 0) 815 return 0; 816 817 drmMsg("Failed to change owner or group for file %s! %d: %s\n", 818 path, errno, strerror(errno)); 819 return -1; 820 } 821 #endif 822 823 static const char *drmGetDeviceName(int type) 824 { 825 switch (type) { 826 case DRM_NODE_PRIMARY: 827 return DRM_DEV_NAME; 828 case DRM_NODE_RENDER: 829 return DRM_RENDER_DEV_NAME; 830 } 831 return NULL; 832 } 833 834 /** 835 * Open the DRM device, creating it if necessary. 836 * 837 * \param dev major and minor numbers of the device. 838 * \param minor minor number of the device. 839 * 840 * \return a file descriptor on success, or a negative value on error. 841 * 842 * \internal 843 * Assembles the device name from \p minor and opens it, creating the device 844 * special file node with the major and minor numbers specified by \p dev and 845 * parent directory if necessary and was called by root. 846 */ 847 static int drmOpenDevice(dev_t dev, int minor, int type) 848 { 849 stat_t st; 850 const char *dev_name = drmGetDeviceName(type); 851 char buf[DRM_NODE_NAME_MAX]; 852 int fd; 853 mode_t devmode = DRM_DEV_MODE, serv_mode; 854 gid_t serv_group; 855 #if !UDEV 856 int isroot = !geteuid(); 857 uid_t user = DRM_DEV_UID; 858 gid_t group = DRM_DEV_GID; 859 #endif 860 861 if (!dev_name) 862 return -EINVAL; 863 864 sprintf(buf, dev_name, DRM_DIR_NAME, minor); 865 drmMsg("drmOpenDevice: node name is %s\n", buf); 866 867 if (drm_server_info && drm_server_info->get_perms) { 868 drm_server_info->get_perms(&serv_group, &serv_mode); 869 devmode = serv_mode ? serv_mode : DRM_DEV_MODE; 870 devmode &= ~(S_IXUSR|S_IXGRP|S_IXOTH); 871 } 872 873 #if !UDEV 874 if (stat(DRM_DIR_NAME, &st)) { 875 if (!isroot) 876 return DRM_ERR_NOT_ROOT; 877 mkdir(DRM_DIR_NAME, DRM_DEV_DIRMODE); 878 chown_check_return(DRM_DIR_NAME, 0, 0); /* root:root */ 879 chmod(DRM_DIR_NAME, DRM_DEV_DIRMODE); 880 } 881 882 /* Check if the device node exists and create it if necessary. */ 883 if (stat(buf, &st)) { 884 if (!isroot) 885 return DRM_ERR_NOT_ROOT; 886 remove(buf); 887 mknod(buf, S_IFCHR | devmode, dev); 888 } 889 890 if (drm_server_info && drm_server_info->get_perms) { 891 group = ((int)serv_group >= 0) ? serv_group : DRM_DEV_GID; 892 chown_check_return(buf, user, group); 893 chmod(buf, devmode); 894 } 895 #else 896 /* if we modprobed then wait for udev */ 897 { 898 int udev_count = 0; 899 wait_for_udev: 900 if (stat(DRM_DIR_NAME, &st)) { 901 usleep(20); 902 udev_count++; 903 904 if (udev_count == 50) 905 return -1; 906 goto wait_for_udev; 907 } 908 909 if (stat(buf, &st)) { 910 usleep(20); 911 udev_count++; 912 913 if (udev_count == 50) 914 return -1; 915 goto wait_for_udev; 916 } 917 } 918 #endif 919 920 fd = open(buf, O_RDWR | O_CLOEXEC); 921 drmMsg("drmOpenDevice: open result is %d, (%s)\n", 922 fd, fd < 0 ? strerror(errno) : "OK"); 923 if (fd >= 0) 924 return fd; 925 926 #if !UDEV 927 /* Check if the device node is not what we expect it to be, and recreate it 928 * and try again if so. 929 */ 930 if (st.st_rdev != dev) { 931 if (!isroot) 932 return DRM_ERR_NOT_ROOT; 933 remove(buf); 934 mknod(buf, S_IFCHR | devmode, dev); 935 if (drm_server_info && drm_server_info->get_perms) { 936 chown_check_return(buf, user, group); 937 chmod(buf, devmode); 938 } 939 } 940 fd = open(buf, O_RDWR | O_CLOEXEC); 941 drmMsg("drmOpenDevice: open result is %d, (%s)\n", 942 fd, fd < 0 ? strerror(errno) : "OK"); 943 if (fd >= 0) 944 return fd; 945 946 drmMsg("drmOpenDevice: Open failed\n"); 947 remove(buf); 948 #endif 949 return -errno; 950 } 951 952 953 /** 954 * Open the DRM device 955 * 956 * \param minor device minor number. 957 * \param create allow to create the device if set. 958 * 959 * \return a file descriptor on success, or a negative value on error. 960 * 961 * \internal 962 * Calls drmOpenDevice() if \p create is set, otherwise assembles the device 963 * name from \p minor and opens it. 964 */ 965 static int drmOpenMinor(int minor, int create, int type) 966 { 967 int fd; 968 char buf[DRM_NODE_NAME_MAX]; 969 const char *dev_name = drmGetDeviceName(type); 970 971 if (create) 972 return drmOpenDevice(makedev(DRM_MAJOR, minor), minor, type); 973 974 if (!dev_name) 975 return -EINVAL; 976 977 sprintf(buf, dev_name, DRM_DIR_NAME, minor); 978 if ((fd = open(buf, O_RDWR | O_CLOEXEC)) >= 0) 979 return fd; 980 return -errno; 981 } 982 983 984 /** 985 * Determine whether the DRM kernel driver has been loaded. 986 * 987 * \return 1 if the DRM driver is loaded, 0 otherwise. 988 * 989 * \deprecated 990 * This function doesn't work when a device goes away (as is often the case 991 * with simpledrm). drmGetDevices2 should be used instead to enumerate DRM 992 * devices. 993 * 994 * \internal 995 * Determine the presence of the kernel driver by attempting to open the 0 996 * minor and get version information. For backward compatibility with older 997 * Linux implementations, /proc/dri is also checked. 998 */ 999 drm_public int drmAvailable(void) 1000 { 1001 drmVersionPtr version; 1002 int retval = 0; 1003 int fd; 1004 1005 if ((fd = drmOpenMinor(0, 1, DRM_NODE_PRIMARY)) < 0) { 1006 #ifdef __linux__ 1007 /* Try proc for backward Linux compatibility */ 1008 if (!access("/proc/dri/0", R_OK)) 1009 return 1; 1010 #endif 1011 return 0; 1012 } 1013 1014 if ((version = drmGetVersion(fd))) { 1015 retval = 1; 1016 drmFreeVersion(version); 1017 } 1018 close(fd); 1019 1020 return retval; 1021 } 1022 1023 static int drmGetMinorBase(int type) 1024 { 1025 switch (type) { 1026 case DRM_NODE_PRIMARY: 1027 return 0; 1028 case DRM_NODE_RENDER: 1029 return 128; 1030 default: 1031 return -1; 1032 }; 1033 } 1034 1035 static int drmGetMinorType(int major, int minor) 1036 { 1037 #ifdef __FreeBSD__ 1038 char name[SPECNAMELEN]; 1039 int id; 1040 1041 if (!devname_r(makedev(major, minor), S_IFCHR, name, sizeof(name))) 1042 return -1; 1043 1044 if (sscanf(name, "drm/%d", &id) != 1) { 1045 // If not in /dev/drm/ we have the type in the name 1046 if (sscanf(name, "dri/card%d\n", &id) >= 1) 1047 return DRM_NODE_PRIMARY; 1048 else if (sscanf(name, "dri/renderD%d\n", &id) >= 1) 1049 return DRM_NODE_RENDER; 1050 return -1; 1051 } 1052 1053 minor = id; 1054 #endif 1055 char path[DRM_NODE_NAME_MAX]; 1056 const char *dev_name; 1057 int i; 1058 1059 for (i = DRM_NODE_PRIMARY; i < DRM_NODE_MAX; i++) { 1060 dev_name = drmGetDeviceName(i); 1061 if (!dev_name) 1062 continue; 1063 snprintf(path, sizeof(path), dev_name, DRM_DIR_NAME, minor); 1064 if (!access(path, F_OK)) 1065 return i; 1066 } 1067 1068 return -1; 1069 } 1070 1071 static const char *drmGetMinorName(int type) 1072 { 1073 switch (type) { 1074 case DRM_NODE_PRIMARY: 1075 return DRM_PRIMARY_MINOR_NAME; 1076 case DRM_NODE_RENDER: 1077 return DRM_RENDER_MINOR_NAME; 1078 default: 1079 return NULL; 1080 } 1081 } 1082 1083 /** 1084 * Open the device by bus ID. 1085 * 1086 * \param busid bus ID. 1087 * \param type device node type. 1088 * 1089 * \return a file descriptor on success, or a negative value on error. 1090 * 1091 * \internal 1092 * This function attempts to open every possible minor (up to DRM_MAX_MINOR), 1093 * comparing the device bus ID with the one supplied. 1094 * 1095 * \sa drmOpenMinor() and drmGetBusid(). 1096 */ 1097 static int drmOpenByBusid(const char *busid, int type) 1098 { 1099 int i, pci_domain_ok = 1; 1100 int fd; 1101 const char *buf; 1102 drmSetVersion sv; 1103 int base = drmGetMinorBase(type); 1104 1105 if (base < 0) 1106 return -1; 1107 1108 drmMsg("drmOpenByBusid: Searching for BusID %s\n", busid); 1109 for (i = base; i < base + DRM_MAX_MINOR; i++) { 1110 fd = drmOpenMinor(i, 1, type); 1111 drmMsg("drmOpenByBusid: drmOpenMinor returns %d\n", fd); 1112 if (fd >= 0) { 1113 /* We need to try for 1.4 first for proper PCI domain support 1114 * and if that fails, we know the kernel is busted 1115 */ 1116 sv.drm_di_major = 1; 1117 sv.drm_di_minor = 4; 1118 sv.drm_dd_major = -1; /* Don't care */ 1119 sv.drm_dd_minor = -1; /* Don't care */ 1120 if (drmSetInterfaceVersion(fd, &sv)) { 1121 #ifndef __alpha__ 1122 pci_domain_ok = 0; 1123 #endif 1124 sv.drm_di_major = 1; 1125 sv.drm_di_minor = 1; 1126 sv.drm_dd_major = -1; /* Don't care */ 1127 sv.drm_dd_minor = -1; /* Don't care */ 1128 drmMsg("drmOpenByBusid: Interface 1.4 failed, trying 1.1\n"); 1129 drmSetInterfaceVersion(fd, &sv); 1130 } 1131 buf = drmGetBusid(fd); 1132 drmMsg("drmOpenByBusid: drmGetBusid reports %s\n", buf); 1133 if (buf && drmMatchBusID(buf, busid, pci_domain_ok)) { 1134 drmFreeBusid(buf); 1135 return fd; 1136 } 1137 if (buf) 1138 drmFreeBusid(buf); 1139 close(fd); 1140 } 1141 } 1142 return -1; 1143 } 1144 1145 1146 /** 1147 * Open the device by name. 1148 * 1149 * \param name driver name. 1150 * \param type the device node type. 1151 * 1152 * \return a file descriptor on success, or a negative value on error. 1153 * 1154 * \internal 1155 * This function opens the first minor number that matches the driver name and 1156 * isn't already in use. If it's in use it then it will already have a bus ID 1157 * assigned. 1158 * 1159 * \sa drmOpenMinor(), drmGetVersion() and drmGetBusid(). 1160 */ 1161 static int drmOpenByName(const char *name, int type) 1162 { 1163 int i; 1164 int fd; 1165 drmVersionPtr version; 1166 char * id; 1167 int base = drmGetMinorBase(type); 1168 1169 if (base < 0) 1170 return -1; 1171 1172 /* 1173 * Open the first minor number that matches the driver name and isn't 1174 * already in use. If it's in use it will have a busid assigned already. 1175 */ 1176 for (i = base; i < base + DRM_MAX_MINOR; i++) { 1177 if ((fd = drmOpenMinor(i, 1, type)) >= 0) { 1178 if ((version = drmGetVersion(fd))) { 1179 if (!strcmp(version->name, name)) { 1180 drmFreeVersion(version); 1181 id = drmGetBusid(fd); 1182 drmMsg("drmGetBusid returned '%s'\n", id ? id : "NULL"); 1183 if (!id || !*id) { 1184 if (id) 1185 drmFreeBusid(id); 1186 return fd; 1187 } else { 1188 drmFreeBusid(id); 1189 } 1190 } else { 1191 drmFreeVersion(version); 1192 } 1193 } 1194 close(fd); 1195 } 1196 } 1197 1198 #ifdef __linux__ 1199 /* Backward-compatibility /proc support */ 1200 for (i = 0; i < 8; i++) { 1201 char proc_name[64], buf[512]; 1202 char *driver, *pt, *devstring; 1203 int retcode; 1204 1205 sprintf(proc_name, "/proc/dri/%d/name", i); 1206 if ((fd = open(proc_name, O_RDONLY)) >= 0) { 1207 retcode = read(fd, buf, sizeof(buf)-1); 1208 close(fd); 1209 if (retcode) { 1210 buf[retcode-1] = '\0'; 1211 for (driver = pt = buf; *pt && *pt != ' '; ++pt) 1212 ; 1213 if (*pt) { /* Device is next */ 1214 *pt = '\0'; 1215 if (!strcmp(driver, name)) { /* Match */ 1216 for (devstring = ++pt; *pt && *pt != ' '; ++pt) 1217 ; 1218 if (*pt) { /* Found busid */ 1219 return drmOpenByBusid(++pt, type); 1220 } else { /* No busid */ 1221 return drmOpenDevice(strtol(devstring, NULL, 0),i, type); 1222 } 1223 } 1224 } 1225 } 1226 } 1227 } 1228 #endif 1229 1230 return -1; 1231 } 1232 1233 1234 /** 1235 * Open the DRM device. 1236 * 1237 * Looks up the specified name and bus ID, and opens the device found. The 1238 * entry in /dev/dri is created if necessary and if called by root. 1239 * 1240 * \param name driver name. Not referenced if bus ID is supplied. 1241 * \param busid bus ID. Zero if not known. 1242 * 1243 * \return a file descriptor on success, or a negative value on error. 1244 * 1245 * \internal 1246 * It calls drmOpenByBusid() if \p busid is specified or drmOpenByName() 1247 * otherwise. 1248 */ 1249 drm_public int drmOpen(const char *name, const char *busid) 1250 { 1251 return drmOpenWithType(name, busid, DRM_NODE_PRIMARY); 1252 } 1253 1254 /** 1255 * Open the DRM device with specified type. 1256 * 1257 * Looks up the specified name and bus ID, and opens the device found. The 1258 * entry in /dev/dri is created if necessary and if called by root. 1259 * 1260 * \param name driver name. Not referenced if bus ID is supplied. 1261 * \param busid bus ID. Zero if not known. 1262 * \param type the device node type to open, PRIMARY or RENDER 1263 * 1264 * \return a file descriptor on success, or a negative value on error. 1265 * 1266 * \internal 1267 * It calls drmOpenByBusid() if \p busid is specified or drmOpenByName() 1268 * otherwise. 1269 */ 1270 drm_public int drmOpenWithType(const char *name, const char *busid, int type) 1271 { 1272 if (name != NULL && drm_server_info && 1273 drm_server_info->load_module && !drmAvailable()) { 1274 /* try to load the kernel module */ 1275 if (!drm_server_info->load_module(name)) { 1276 drmMsg("[drm] failed to load kernel module \"%s\"\n", name); 1277 return -1; 1278 } 1279 } 1280 1281 if (busid) { 1282 int fd = drmOpenByBusid(busid, type); 1283 if (fd >= 0) 1284 return fd; 1285 } 1286 1287 if (name) 1288 return drmOpenByName(name, type); 1289 1290 return -1; 1291 } 1292 1293 drm_public int drmOpenControl(int minor) 1294 { 1295 return -EINVAL; 1296 } 1297 1298 drm_public int drmOpenRender(int minor) 1299 { 1300 return drmOpenMinor(minor, 0, DRM_NODE_RENDER); 1301 } 1302 1303 /** 1304 * Free the version information returned by drmGetVersion(). 1305 * 1306 * \param v pointer to the version information. 1307 * 1308 * \internal 1309 * It frees the memory pointed by \p %v as well as all the non-null strings 1310 * pointers in it. 1311 */ 1312 drm_public void drmFreeVersion(drmVersionPtr v) 1313 { 1314 if (!v) 1315 return; 1316 drmFree(v->name); 1317 drmFree(v->date); 1318 drmFree(v->desc); 1319 drmFree(v); 1320 } 1321 1322 1323 /** 1324 * Free the non-public version information returned by the kernel. 1325 * 1326 * \param v pointer to the version information. 1327 * 1328 * \internal 1329 * Used by drmGetVersion() to free the memory pointed by \p %v as well as all 1330 * the non-null strings pointers in it. 1331 */ 1332 static void drmFreeKernelVersion(drm_version_t *v) 1333 { 1334 if (!v) 1335 return; 1336 drmFree(v->name); 1337 drmFree(v->date); 1338 drmFree(v->desc); 1339 drmFree(v); 1340 } 1341 1342 1343 /** 1344 * Copy version information. 1345 * 1346 * \param d destination pointer. 1347 * \param s source pointer. 1348 * 1349 * \internal 1350 * Used by drmGetVersion() to translate the information returned by the ioctl 1351 * interface in a private structure into the public structure counterpart. 1352 */ 1353 static void drmCopyVersion(drmVersionPtr d, const drm_version_t *s) 1354 { 1355 d->version_major = s->version_major; 1356 d->version_minor = s->version_minor; 1357 d->version_patchlevel = s->version_patchlevel; 1358 d->name_len = s->name_len; 1359 d->name = s->name ? strdup(s->name) : NULL; 1360 d->date_len = s->date_len; 1361 d->date = s->date ? strdup(s->date) : NULL; 1362 d->desc_len = s->desc_len; 1363 d->desc = s->desc ? strdup(s->desc) : NULL; 1364 } 1365 1366 1367 /** 1368 * Query the driver version information. 1369 * 1370 * \param fd file descriptor. 1371 * 1372 * \return pointer to a drmVersion structure which should be freed with 1373 * drmFreeVersion(). 1374 * 1375 * \note Similar information is available via /proc/dri. 1376 * 1377 * \internal 1378 * It gets the version information via successive DRM_IOCTL_VERSION ioctls, 1379 * first with zeros to get the string lengths, and then the actually strings. 1380 * It also null-terminates them since they might not be already. 1381 */ 1382 drm_public drmVersionPtr drmGetVersion(int fd) 1383 { 1384 drmVersionPtr retval; 1385 drm_version_t *version = drmMalloc(sizeof(*version)); 1386 1387 if (drmIoctl(fd, DRM_IOCTL_VERSION, version)) { 1388 drmFreeKernelVersion(version); 1389 return NULL; 1390 } 1391 1392 if (version->name_len) 1393 version->name = drmMalloc(version->name_len + 1); 1394 if (version->date_len) 1395 version->date = drmMalloc(version->date_len + 1); 1396 if (version->desc_len) 1397 version->desc = drmMalloc(version->desc_len + 1); 1398 1399 if (drmIoctl(fd, DRM_IOCTL_VERSION, version)) { 1400 drmMsg("DRM_IOCTL_VERSION: %s\n", strerror(errno)); 1401 drmFreeKernelVersion(version); 1402 return NULL; 1403 } 1404 1405 /* The results might not be null-terminated strings, so terminate them. */ 1406 if (version->name_len) version->name[version->name_len] = '\0'; 1407 if (version->date_len) version->date[version->date_len] = '\0'; 1408 if (version->desc_len) version->desc[version->desc_len] = '\0'; 1409 1410 retval = drmMalloc(sizeof(*retval)); 1411 drmCopyVersion(retval, version); 1412 drmFreeKernelVersion(version); 1413 return retval; 1414 } 1415 1416 1417 /** 1418 * Get version information for the DRM user space library. 1419 * 1420 * This version number is driver independent. 1421 * 1422 * \param fd file descriptor. 1423 * 1424 * \return version information. 1425 * 1426 * \internal 1427 * This function allocates and fills a drm_version structure with a hard coded 1428 * version number. 1429 */ 1430 drm_public drmVersionPtr drmGetLibVersion(int fd) 1431 { 1432 drm_version_t *version = drmMalloc(sizeof(*version)); 1433 1434 /* Version history: 1435 * NOTE THIS MUST NOT GO ABOVE VERSION 1.X due to drivers needing it 1436 * revision 1.0.x = original DRM interface with no drmGetLibVersion 1437 * entry point and many drm<Device> extensions 1438 * revision 1.1.x = added drmCommand entry points for device extensions 1439 * added drmGetLibVersion to identify libdrm.a version 1440 * revision 1.2.x = added drmSetInterfaceVersion 1441 * modified drmOpen to handle both busid and name 1442 * revision 1.3.x = added server + memory manager 1443 */ 1444 version->version_major = 1; 1445 version->version_minor = 3; 1446 version->version_patchlevel = 0; 1447 1448 return (drmVersionPtr)version; 1449 } 1450 1451 drm_public int drmGetCap(int fd, uint64_t capability, uint64_t *value) 1452 { 1453 struct drm_get_cap cap; 1454 int ret; 1455 1456 memclear(cap); 1457 cap.capability = capability; 1458 1459 ret = drmIoctl(fd, DRM_IOCTL_GET_CAP, &cap); 1460 if (ret) 1461 return ret; 1462 1463 *value = cap.value; 1464 return 0; 1465 } 1466 1467 drm_public int drmSetClientCap(int fd, uint64_t capability, uint64_t value) 1468 { 1469 struct drm_set_client_cap cap; 1470 1471 memclear(cap); 1472 cap.capability = capability; 1473 cap.value = value; 1474 1475 return drmIoctl(fd, DRM_IOCTL_SET_CLIENT_CAP, &cap); 1476 } 1477 1478 /** 1479 * Free the bus ID information. 1480 * 1481 * \param busid bus ID information string as given by drmGetBusid(). 1482 * 1483 * \internal 1484 * This function is just frees the memory pointed by \p busid. 1485 */ 1486 drm_public void drmFreeBusid(const char *busid) 1487 { 1488 drmFree((void *)busid); 1489 } 1490 1491 1492 /** 1493 * Get the bus ID of the device. 1494 * 1495 * \param fd file descriptor. 1496 * 1497 * \return bus ID string. 1498 * 1499 * \internal 1500 * This function gets the bus ID via successive DRM_IOCTL_GET_UNIQUE ioctls to 1501 * get the string length and data, passing the arguments in a drm_unique 1502 * structure. 1503 */ 1504 drm_public char *drmGetBusid(int fd) 1505 { 1506 drm_unique_t u; 1507 1508 memclear(u); 1509 1510 if (drmIoctl(fd, DRM_IOCTL_GET_UNIQUE, &u)) 1511 return NULL; 1512 u.unique = drmMalloc(u.unique_len + 1); 1513 if (drmIoctl(fd, DRM_IOCTL_GET_UNIQUE, &u)) { 1514 drmFree(u.unique); 1515 return NULL; 1516 } 1517 u.unique[u.unique_len] = '\0'; 1518 1519 return u.unique; 1520 } 1521 1522 1523 /** 1524 * Set the bus ID of the device. 1525 * 1526 * \param fd file descriptor. 1527 * \param busid bus ID string. 1528 * 1529 * \return zero on success, negative on failure. 1530 * 1531 * \internal 1532 * This function is a wrapper around the DRM_IOCTL_SET_UNIQUE ioctl, passing 1533 * the arguments in a drm_unique structure. 1534 */ 1535 drm_public int drmSetBusid(int fd, const char *busid) 1536 { 1537 drm_unique_t u; 1538 1539 memclear(u); 1540 u.unique = (char *)busid; 1541 u.unique_len = strlen(busid); 1542 1543 if (drmIoctl(fd, DRM_IOCTL_SET_UNIQUE, &u)) { 1544 return -errno; 1545 } 1546 return 0; 1547 } 1548 1549 drm_public int drmGetMagic(int fd, drm_magic_t * magic) 1550 { 1551 drm_auth_t auth; 1552 1553 memclear(auth); 1554 1555 *magic = 0; 1556 if (drmIoctl(fd, DRM_IOCTL_GET_MAGIC, &auth)) 1557 return -errno; 1558 *magic = auth.magic; 1559 return 0; 1560 } 1561 1562 drm_public int drmAuthMagic(int fd, drm_magic_t magic) 1563 { 1564 drm_auth_t auth; 1565 1566 memclear(auth); 1567 auth.magic = magic; 1568 if (drmIoctl(fd, DRM_IOCTL_AUTH_MAGIC, &auth)) 1569 return -errno; 1570 return 0; 1571 } 1572 1573 /** 1574 * Specifies a range of memory that is available for mapping by a 1575 * non-root process. 1576 * 1577 * \param fd file descriptor. 1578 * \param offset usually the physical address. The actual meaning depends of 1579 * the \p type parameter. See below. 1580 * \param size of the memory in bytes. 1581 * \param type type of the memory to be mapped. 1582 * \param flags combination of several flags to modify the function actions. 1583 * \param handle will be set to a value that may be used as the offset 1584 * parameter for mmap(). 1585 * 1586 * \return zero on success or a negative value on error. 1587 * 1588 * \par Mapping the frame buffer 1589 * For the frame buffer 1590 * - \p offset will be the physical address of the start of the frame buffer, 1591 * - \p size will be the size of the frame buffer in bytes, and 1592 * - \p type will be DRM_FRAME_BUFFER. 1593 * 1594 * \par 1595 * The area mapped will be uncached. If MTRR support is available in the 1596 * kernel, the frame buffer area will be set to write combining. 1597 * 1598 * \par Mapping the MMIO register area 1599 * For the MMIO register area, 1600 * - \p offset will be the physical address of the start of the register area, 1601 * - \p size will be the size of the register area bytes, and 1602 * - \p type will be DRM_REGISTERS. 1603 * \par 1604 * The area mapped will be uncached. 1605 * 1606 * \par Mapping the SAREA 1607 * For the SAREA, 1608 * - \p offset will be ignored and should be set to zero, 1609 * - \p size will be the desired size of the SAREA in bytes, 1610 * - \p type will be DRM_SHM. 1611 * 1612 * \par 1613 * A shared memory area of the requested size will be created and locked in 1614 * kernel memory. This area may be mapped into client-space by using the handle 1615 * returned. 1616 * 1617 * \note May only be called by root. 1618 * 1619 * \internal 1620 * This function is a wrapper around the DRM_IOCTL_ADD_MAP ioctl, passing 1621 * the arguments in a drm_map structure. 1622 */ 1623 drm_public int drmAddMap(int fd, drm_handle_t offset, drmSize size, drmMapType type, 1624 drmMapFlags flags, drm_handle_t *handle) 1625 { 1626 drm_map_t map; 1627 1628 memclear(map); 1629 map.offset = offset; 1630 map.size = size; 1631 map.type = (enum drm_map_type)type; 1632 map.flags = (enum drm_map_flags)flags; 1633 if (drmIoctl(fd, DRM_IOCTL_ADD_MAP, &map)) 1634 return -errno; 1635 if (handle) 1636 *handle = (drm_handle_t)(uintptr_t)map.handle; 1637 return 0; 1638 } 1639 1640 drm_public int drmRmMap(int fd, drm_handle_t handle) 1641 { 1642 drm_map_t map; 1643 1644 memclear(map); 1645 map.handle = (void *)(uintptr_t)handle; 1646 1647 if(drmIoctl(fd, DRM_IOCTL_RM_MAP, &map)) 1648 return -errno; 1649 return 0; 1650 } 1651 1652 /** 1653 * Make buffers available for DMA transfers. 1654 * 1655 * \param fd file descriptor. 1656 * \param count number of buffers. 1657 * \param size size of each buffer. 1658 * \param flags buffer allocation flags. 1659 * \param agp_offset offset in the AGP aperture 1660 * 1661 * \return number of buffers allocated, negative on error. 1662 * 1663 * \internal 1664 * This function is a wrapper around DRM_IOCTL_ADD_BUFS ioctl. 1665 * 1666 * \sa drm_buf_desc. 1667 */ 1668 drm_public int drmAddBufs(int fd, int count, int size, drmBufDescFlags flags, 1669 int agp_offset) 1670 { 1671 drm_buf_desc_t request; 1672 1673 memclear(request); 1674 request.count = count; 1675 request.size = size; 1676 request.flags = (int)flags; 1677 request.agp_start = agp_offset; 1678 1679 if (drmIoctl(fd, DRM_IOCTL_ADD_BUFS, &request)) 1680 return -errno; 1681 return request.count; 1682 } 1683 1684 drm_public int drmMarkBufs(int fd, double low, double high) 1685 { 1686 drm_buf_info_t info; 1687 int i; 1688 1689 memclear(info); 1690 1691 if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info)) 1692 return -EINVAL; 1693 1694 if (!info.count) 1695 return -EINVAL; 1696 1697 if (!(info.list = drmMalloc(info.count * sizeof(*info.list)))) 1698 return -ENOMEM; 1699 1700 if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info)) { 1701 int retval = -errno; 1702 drmFree(info.list); 1703 return retval; 1704 } 1705 1706 for (i = 0; i < info.count; i++) { 1707 info.list[i].low_mark = low * info.list[i].count; 1708 info.list[i].high_mark = high * info.list[i].count; 1709 if (drmIoctl(fd, DRM_IOCTL_MARK_BUFS, &info.list[i])) { 1710 int retval = -errno; 1711 drmFree(info.list); 1712 return retval; 1713 } 1714 } 1715 drmFree(info.list); 1716 1717 return 0; 1718 } 1719 1720 /** 1721 * Free buffers. 1722 * 1723 * \param fd file descriptor. 1724 * \param count number of buffers to free. 1725 * \param list list of buffers to be freed. 1726 * 1727 * \return zero on success, or a negative value on failure. 1728 * 1729 * \note This function is primarily used for debugging. 1730 * 1731 * \internal 1732 * This function is a wrapper around the DRM_IOCTL_FREE_BUFS ioctl, passing 1733 * the arguments in a drm_buf_free structure. 1734 */ 1735 drm_public int drmFreeBufs(int fd, int count, int *list) 1736 { 1737 drm_buf_free_t request; 1738 1739 memclear(request); 1740 request.count = count; 1741 request.list = list; 1742 if (drmIoctl(fd, DRM_IOCTL_FREE_BUFS, &request)) 1743 return -errno; 1744 return 0; 1745 } 1746 1747 1748 /** 1749 * Close the device. 1750 * 1751 * \param fd file descriptor. 1752 * 1753 * \internal 1754 * This function closes the file descriptor. 1755 */ 1756 drm_public int drmClose(int fd) 1757 { 1758 unsigned long key = drmGetKeyFromFd(fd); 1759 drmHashEntry *entry = drmGetEntry(fd); 1760 1761 drmHashDestroy(entry->tagTable); 1762 entry->fd = 0; 1763 entry->f = NULL; 1764 entry->tagTable = NULL; 1765 1766 drmHashDelete(drmHashTable, key); 1767 drmFree(entry); 1768 1769 return close(fd); 1770 } 1771 1772 1773 /** 1774 * Map a region of memory. 1775 * 1776 * \param fd file descriptor. 1777 * \param handle handle returned by drmAddMap(). 1778 * \param size size in bytes. Must match the size used by drmAddMap(). 1779 * \param address will contain the user-space virtual address where the mapping 1780 * begins. 1781 * 1782 * \return zero on success, or a negative value on failure. 1783 * 1784 * \internal 1785 * This function is a wrapper for mmap(). 1786 */ 1787 drm_public int drmMap(int fd, drm_handle_t handle, drmSize size, 1788 drmAddressPtr address) 1789 { 1790 static unsigned long pagesize_mask = 0; 1791 1792 if (fd < 0) 1793 return -EINVAL; 1794 1795 if (!pagesize_mask) 1796 pagesize_mask = getpagesize() - 1; 1797 1798 size = (size + pagesize_mask) & ~pagesize_mask; 1799 1800 *address = drm_mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, handle); 1801 if (*address == MAP_FAILED) 1802 return -errno; 1803 return 0; 1804 } 1805 1806 1807 /** 1808 * Unmap mappings obtained with drmMap(). 1809 * 1810 * \param address address as given by drmMap(). 1811 * \param size size in bytes. Must match the size used by drmMap(). 1812 * 1813 * \return zero on success, or a negative value on failure. 1814 * 1815 * \internal 1816 * This function is a wrapper for munmap(). 1817 */ 1818 drm_public int drmUnmap(drmAddress address, drmSize size) 1819 { 1820 return drm_munmap(address, size); 1821 } 1822 1823 drm_public drmBufInfoPtr drmGetBufInfo(int fd) 1824 { 1825 drm_buf_info_t info; 1826 drmBufInfoPtr retval; 1827 int i; 1828 1829 memclear(info); 1830 1831 if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info)) 1832 return NULL; 1833 1834 if (info.count) { 1835 if (!(info.list = drmMalloc(info.count * sizeof(*info.list)))) 1836 return NULL; 1837 1838 if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info)) { 1839 drmFree(info.list); 1840 return NULL; 1841 } 1842 1843 retval = drmMalloc(sizeof(*retval)); 1844 retval->count = info.count; 1845 if (!(retval->list = drmMalloc(info.count * sizeof(*retval->list)))) { 1846 drmFree(retval); 1847 drmFree(info.list); 1848 return NULL; 1849 } 1850 1851 for (i = 0; i < info.count; i++) { 1852 retval->list[i].count = info.list[i].count; 1853 retval->list[i].size = info.list[i].size; 1854 retval->list[i].low_mark = info.list[i].low_mark; 1855 retval->list[i].high_mark = info.list[i].high_mark; 1856 } 1857 drmFree(info.list); 1858 return retval; 1859 } 1860 return NULL; 1861 } 1862 1863 /** 1864 * Map all DMA buffers into client-virtual space. 1865 * 1866 * \param fd file descriptor. 1867 * 1868 * \return a pointer to a ::drmBufMap structure. 1869 * 1870 * \note The client may not use these buffers until obtaining buffer indices 1871 * with drmDMA(). 1872 * 1873 * \internal 1874 * This function calls the DRM_IOCTL_MAP_BUFS ioctl and copies the returned 1875 * information about the buffers in a drm_buf_map structure into the 1876 * client-visible data structures. 1877 */ 1878 drm_public drmBufMapPtr drmMapBufs(int fd) 1879 { 1880 drm_buf_map_t bufs; 1881 drmBufMapPtr retval; 1882 int i; 1883 1884 memclear(bufs); 1885 if (drmIoctl(fd, DRM_IOCTL_MAP_BUFS, &bufs)) 1886 return NULL; 1887 1888 if (!bufs.count) 1889 return NULL; 1890 1891 if (!(bufs.list = drmMalloc(bufs.count * sizeof(*bufs.list)))) 1892 return NULL; 1893 1894 if (drmIoctl(fd, DRM_IOCTL_MAP_BUFS, &bufs)) { 1895 drmFree(bufs.list); 1896 return NULL; 1897 } 1898 1899 retval = drmMalloc(sizeof(*retval)); 1900 retval->count = bufs.count; 1901 retval->list = drmMalloc(bufs.count * sizeof(*retval->list)); 1902 for (i = 0; i < bufs.count; i++) { 1903 retval->list[i].idx = bufs.list[i].idx; 1904 retval->list[i].total = bufs.list[i].total; 1905 retval->list[i].used = 0; 1906 retval->list[i].address = bufs.list[i].address; 1907 } 1908 1909 drmFree(bufs.list); 1910 return retval; 1911 } 1912 1913 1914 /** 1915 * Unmap buffers allocated with drmMapBufs(). 1916 * 1917 * \return zero on success, or negative value on failure. 1918 * 1919 * \internal 1920 * Calls munmap() for every buffer stored in \p bufs and frees the 1921 * memory allocated by drmMapBufs(). 1922 */ 1923 drm_public int drmUnmapBufs(drmBufMapPtr bufs) 1924 { 1925 int i; 1926 1927 for (i = 0; i < bufs->count; i++) { 1928 drm_munmap(bufs->list[i].address, bufs->list[i].total); 1929 } 1930 1931 drmFree(bufs->list); 1932 drmFree(bufs); 1933 return 0; 1934 } 1935 1936 1937 #define DRM_DMA_RETRY 16 1938 1939 /** 1940 * Reserve DMA buffers. 1941 * 1942 * \param fd file descriptor. 1943 * \param request 1944 * 1945 * \return zero on success, or a negative value on failure. 1946 * 1947 * \internal 1948 * Assemble the arguments into a drm_dma structure and keeps issuing the 1949 * DRM_IOCTL_DMA ioctl until success or until maximum number of retries. 1950 */ 1951 drm_public int drmDMA(int fd, drmDMAReqPtr request) 1952 { 1953 drm_dma_t dma; 1954 int ret, i = 0; 1955 1956 dma.context = request->context; 1957 dma.send_count = request->send_count; 1958 dma.send_indices = request->send_list; 1959 dma.send_sizes = request->send_sizes; 1960 dma.flags = (enum drm_dma_flags)request->flags; 1961 dma.request_count = request->request_count; 1962 dma.request_size = request->request_size; 1963 dma.request_indices = request->request_list; 1964 dma.request_sizes = request->request_sizes; 1965 dma.granted_count = 0; 1966 1967 do { 1968 ret = ioctl( fd, DRM_IOCTL_DMA, &dma ); 1969 } while ( ret && errno == EAGAIN && i++ < DRM_DMA_RETRY ); 1970 1971 if ( ret == 0 ) { 1972 request->granted_count = dma.granted_count; 1973 return 0; 1974 } else { 1975 return -errno; 1976 } 1977 } 1978 1979 1980 /** 1981 * Obtain heavyweight hardware lock. 1982 * 1983 * \param fd file descriptor. 1984 * \param context context. 1985 * \param flags flags that determine the state of the hardware when the function 1986 * returns. 1987 * 1988 * \return always zero. 1989 * 1990 * \internal 1991 * This function translates the arguments into a drm_lock structure and issue 1992 * the DRM_IOCTL_LOCK ioctl until the lock is successfully acquired. 1993 */ 1994 drm_public int drmGetLock(int fd, drm_context_t context, drmLockFlags flags) 1995 { 1996 drm_lock_t lock; 1997 1998 memclear(lock); 1999 lock.context = context; 2000 lock.flags = 0; 2001 if (flags & DRM_LOCK_READY) lock.flags |= _DRM_LOCK_READY; 2002 if (flags & DRM_LOCK_QUIESCENT) lock.flags |= _DRM_LOCK_QUIESCENT; 2003 if (flags & DRM_LOCK_FLUSH) lock.flags |= _DRM_LOCK_FLUSH; 2004 if (flags & DRM_LOCK_FLUSH_ALL) lock.flags |= _DRM_LOCK_FLUSH_ALL; 2005 if (flags & DRM_HALT_ALL_QUEUES) lock.flags |= _DRM_HALT_ALL_QUEUES; 2006 if (flags & DRM_HALT_CUR_QUEUES) lock.flags |= _DRM_HALT_CUR_QUEUES; 2007 2008 while (drmIoctl(fd, DRM_IOCTL_LOCK, &lock)) 2009 ; 2010 return 0; 2011 } 2012 2013 /** 2014 * Release the hardware lock. 2015 * 2016 * \param fd file descriptor. 2017 * \param context context. 2018 * 2019 * \return zero on success, or a negative value on failure. 2020 * 2021 * \internal 2022 * This function is a wrapper around the DRM_IOCTL_UNLOCK ioctl, passing the 2023 * argument in a drm_lock structure. 2024 */ 2025 drm_public int drmUnlock(int fd, drm_context_t context) 2026 { 2027 drm_lock_t lock; 2028 2029 memclear(lock); 2030 lock.context = context; 2031 return drmIoctl(fd, DRM_IOCTL_UNLOCK, &lock); 2032 } 2033 2034 drm_public drm_context_t *drmGetReservedContextList(int fd, int *count) 2035 { 2036 drm_ctx_res_t res; 2037 drm_ctx_t *list; 2038 drm_context_t * retval; 2039 int i; 2040 2041 memclear(res); 2042 if (drmIoctl(fd, DRM_IOCTL_RES_CTX, &res)) 2043 return NULL; 2044 2045 if (!res.count) 2046 return NULL; 2047 2048 if (!(list = drmMalloc(res.count * sizeof(*list)))) 2049 return NULL; 2050 if (!(retval = drmMalloc(res.count * sizeof(*retval)))) 2051 goto err_free_list; 2052 2053 res.contexts = list; 2054 if (drmIoctl(fd, DRM_IOCTL_RES_CTX, &res)) 2055 goto err_free_context; 2056 2057 for (i = 0; i < res.count; i++) 2058 retval[i] = list[i].handle; 2059 drmFree(list); 2060 2061 *count = res.count; 2062 return retval; 2063 2064 err_free_list: 2065 drmFree(list); 2066 err_free_context: 2067 drmFree(retval); 2068 return NULL; 2069 } 2070 2071 drm_public void drmFreeReservedContextList(drm_context_t *pt) 2072 { 2073 drmFree(pt); 2074 } 2075 2076 /** 2077 * Create context. 2078 * 2079 * Used by the X server during GLXContext initialization. This causes 2080 * per-context kernel-level resources to be allocated. 2081 * 2082 * \param fd file descriptor. 2083 * \param handle is set on success. To be used by the client when requesting DMA 2084 * dispatch with drmDMA(). 2085 * 2086 * \return zero on success, or a negative value on failure. 2087 * 2088 * \note May only be called by root. 2089 * 2090 * \internal 2091 * This function is a wrapper around the DRM_IOCTL_ADD_CTX ioctl, passing the 2092 * argument in a drm_ctx structure. 2093 */ 2094 drm_public int drmCreateContext(int fd, drm_context_t *handle) 2095 { 2096 drm_ctx_t ctx; 2097 2098 memclear(ctx); 2099 if (drmIoctl(fd, DRM_IOCTL_ADD_CTX, &ctx)) 2100 return -errno; 2101 *handle = ctx.handle; 2102 return 0; 2103 } 2104 2105 drm_public int drmSwitchToContext(int fd, drm_context_t context) 2106 { 2107 drm_ctx_t ctx; 2108 2109 memclear(ctx); 2110 ctx.handle = context; 2111 if (drmIoctl(fd, DRM_IOCTL_SWITCH_CTX, &ctx)) 2112 return -errno; 2113 return 0; 2114 } 2115 2116 drm_public int drmSetContextFlags(int fd, drm_context_t context, 2117 drm_context_tFlags flags) 2118 { 2119 drm_ctx_t ctx; 2120 2121 /* 2122 * Context preserving means that no context switches are done between DMA 2123 * buffers from one context and the next. This is suitable for use in the 2124 * X server (which promises to maintain hardware context), or in the 2125 * client-side library when buffers are swapped on behalf of two threads. 2126 */ 2127 memclear(ctx); 2128 ctx.handle = context; 2129 if (flags & DRM_CONTEXT_PRESERVED) 2130 ctx.flags |= _DRM_CONTEXT_PRESERVED; 2131 if (flags & DRM_CONTEXT_2DONLY) 2132 ctx.flags |= _DRM_CONTEXT_2DONLY; 2133 if (drmIoctl(fd, DRM_IOCTL_MOD_CTX, &ctx)) 2134 return -errno; 2135 return 0; 2136 } 2137 2138 drm_public int drmGetContextFlags(int fd, drm_context_t context, 2139 drm_context_tFlagsPtr flags) 2140 { 2141 drm_ctx_t ctx; 2142 2143 memclear(ctx); 2144 ctx.handle = context; 2145 if (drmIoctl(fd, DRM_IOCTL_GET_CTX, &ctx)) 2146 return -errno; 2147 *flags = 0; 2148 if (ctx.flags & _DRM_CONTEXT_PRESERVED) 2149 *flags |= DRM_CONTEXT_PRESERVED; 2150 if (ctx.flags & _DRM_CONTEXT_2DONLY) 2151 *flags |= DRM_CONTEXT_2DONLY; 2152 return 0; 2153 } 2154 2155 /** 2156 * Destroy context. 2157 * 2158 * Free any kernel-level resources allocated with drmCreateContext() associated 2159 * with the context. 2160 * 2161 * \param fd file descriptor. 2162 * \param handle handle given by drmCreateContext(). 2163 * 2164 * \return zero on success, or a negative value on failure. 2165 * 2166 * \note May only be called by root. 2167 * 2168 * \internal 2169 * This function is a wrapper around the DRM_IOCTL_RM_CTX ioctl, passing the 2170 * argument in a drm_ctx structure. 2171 */ 2172 drm_public int drmDestroyContext(int fd, drm_context_t handle) 2173 { 2174 drm_ctx_t ctx; 2175 2176 memclear(ctx); 2177 ctx.handle = handle; 2178 if (drmIoctl(fd, DRM_IOCTL_RM_CTX, &ctx)) 2179 return -errno; 2180 return 0; 2181 } 2182 2183 drm_public int drmCreateDrawable(int fd, drm_drawable_t *handle) 2184 { 2185 drm_draw_t draw; 2186 2187 memclear(draw); 2188 if (drmIoctl(fd, DRM_IOCTL_ADD_DRAW, &draw)) 2189 return -errno; 2190 *handle = draw.handle; 2191 return 0; 2192 } 2193 2194 drm_public int drmDestroyDrawable(int fd, drm_drawable_t handle) 2195 { 2196 drm_draw_t draw; 2197 2198 memclear(draw); 2199 draw.handle = handle; 2200 if (drmIoctl(fd, DRM_IOCTL_RM_DRAW, &draw)) 2201 return -errno; 2202 return 0; 2203 } 2204 2205 drm_public int drmUpdateDrawableInfo(int fd, drm_drawable_t handle, 2206 drm_drawable_info_type_t type, 2207 unsigned int num, void *data) 2208 { 2209 drm_update_draw_t update; 2210 2211 memclear(update); 2212 update.handle = handle; 2213 update.type = type; 2214 update.num = num; 2215 update.data = (unsigned long long)(unsigned long)data; 2216 2217 if (drmIoctl(fd, DRM_IOCTL_UPDATE_DRAW, &update)) 2218 return -errno; 2219 2220 return 0; 2221 } 2222 2223 drm_public int drmCrtcGetSequence(int fd, uint32_t crtcId, uint64_t *sequence, 2224 uint64_t *ns) 2225 { 2226 struct drm_crtc_get_sequence get_seq; 2227 int ret; 2228 2229 memclear(get_seq); 2230 get_seq.crtc_id = crtcId; 2231 ret = drmIoctl(fd, DRM_IOCTL_CRTC_GET_SEQUENCE, &get_seq); 2232 if (ret) 2233 return ret; 2234 2235 if (sequence) 2236 *sequence = get_seq.sequence; 2237 if (ns) 2238 *ns = get_seq.sequence_ns; 2239 return 0; 2240 } 2241 2242 drm_public int drmCrtcQueueSequence(int fd, uint32_t crtcId, uint32_t flags, 2243 uint64_t sequence, 2244 uint64_t *sequence_queued, 2245 uint64_t user_data) 2246 { 2247 struct drm_crtc_queue_sequence queue_seq; 2248 int ret; 2249 2250 memclear(queue_seq); 2251 queue_seq.crtc_id = crtcId; 2252 queue_seq.flags = flags; 2253 queue_seq.sequence = sequence; 2254 queue_seq.user_data = user_data; 2255 2256 ret = drmIoctl(fd, DRM_IOCTL_CRTC_QUEUE_SEQUENCE, &queue_seq); 2257 if (ret == 0 && sequence_queued) 2258 *sequence_queued = queue_seq.sequence; 2259 2260 return ret; 2261 } 2262 2263 /** 2264 * Acquire the AGP device. 2265 * 2266 * Must be called before any of the other AGP related calls. 2267 * 2268 * \param fd file descriptor. 2269 * 2270 * \return zero on success, or a negative value on failure. 2271 * 2272 * \internal 2273 * This function is a wrapper around the DRM_IOCTL_AGP_ACQUIRE ioctl. 2274 */ 2275 drm_public int drmAgpAcquire(int fd) 2276 { 2277 if (drmIoctl(fd, DRM_IOCTL_AGP_ACQUIRE, NULL)) 2278 return -errno; 2279 return 0; 2280 } 2281 2282 2283 /** 2284 * Release the AGP device. 2285 * 2286 * \param fd file descriptor. 2287 * 2288 * \return zero on success, or a negative value on failure. 2289 * 2290 * \internal 2291 * This function is a wrapper around the DRM_IOCTL_AGP_RELEASE ioctl. 2292 */ 2293 drm_public int drmAgpRelease(int fd) 2294 { 2295 if (drmIoctl(fd, DRM_IOCTL_AGP_RELEASE, NULL)) 2296 return -errno; 2297 return 0; 2298 } 2299 2300 2301 /** 2302 * Set the AGP mode. 2303 * 2304 * \param fd file descriptor. 2305 * \param mode AGP mode. 2306 * 2307 * \return zero on success, or a negative value on failure. 2308 * 2309 * \internal 2310 * This function is a wrapper around the DRM_IOCTL_AGP_ENABLE ioctl, passing the 2311 * argument in a drm_agp_mode structure. 2312 */ 2313 drm_public int drmAgpEnable(int fd, unsigned long mode) 2314 { 2315 drm_agp_mode_t m; 2316 2317 memclear(m); 2318 m.mode = mode; 2319 if (drmIoctl(fd, DRM_IOCTL_AGP_ENABLE, &m)) 2320 return -errno; 2321 return 0; 2322 } 2323 2324 2325 /** 2326 * Allocate a chunk of AGP memory. 2327 * 2328 * \param fd file descriptor. 2329 * \param size requested memory size in bytes. Will be rounded to page boundary. 2330 * \param type type of memory to allocate. 2331 * \param address if not zero, will be set to the physical address of the 2332 * allocated memory. 2333 * \param handle on success will be set to a handle of the allocated memory. 2334 * 2335 * \return zero on success, or a negative value on failure. 2336 * 2337 * \internal 2338 * This function is a wrapper around the DRM_IOCTL_AGP_ALLOC ioctl, passing the 2339 * arguments in a drm_agp_buffer structure. 2340 */ 2341 drm_public int drmAgpAlloc(int fd, unsigned long size, unsigned long type, 2342 unsigned long *address, drm_handle_t *handle) 2343 { 2344 drm_agp_buffer_t b; 2345 2346 memclear(b); 2347 *handle = DRM_AGP_NO_HANDLE; 2348 b.size = size; 2349 b.type = type; 2350 if (drmIoctl(fd, DRM_IOCTL_AGP_ALLOC, &b)) 2351 return -errno; 2352 if (address != 0UL) 2353 *address = b.physical; 2354 *handle = b.handle; 2355 return 0; 2356 } 2357 2358 2359 /** 2360 * Free a chunk of AGP memory. 2361 * 2362 * \param fd file descriptor. 2363 * \param handle handle to the allocated memory, as given by drmAgpAllocate(). 2364 * 2365 * \return zero on success, or a negative value on failure. 2366 * 2367 * \internal 2368 * This function is a wrapper around the DRM_IOCTL_AGP_FREE ioctl, passing the 2369 * argument in a drm_agp_buffer structure. 2370 */ 2371 drm_public int drmAgpFree(int fd, drm_handle_t handle) 2372 { 2373 drm_agp_buffer_t b; 2374 2375 memclear(b); 2376 b.handle = handle; 2377 if (drmIoctl(fd, DRM_IOCTL_AGP_FREE, &b)) 2378 return -errno; 2379 return 0; 2380 } 2381 2382 2383 /** 2384 * Bind a chunk of AGP memory. 2385 * 2386 * \param fd file descriptor. 2387 * \param handle handle to the allocated memory, as given by drmAgpAllocate(). 2388 * \param offset offset in bytes. It will round to page boundary. 2389 * 2390 * \return zero on success, or a negative value on failure. 2391 * 2392 * \internal 2393 * This function is a wrapper around the DRM_IOCTL_AGP_BIND ioctl, passing the 2394 * argument in a drm_agp_binding structure. 2395 */ 2396 drm_public int drmAgpBind(int fd, drm_handle_t handle, unsigned long offset) 2397 { 2398 drm_agp_binding_t b; 2399 2400 memclear(b); 2401 b.handle = handle; 2402 b.offset = offset; 2403 if (drmIoctl(fd, DRM_IOCTL_AGP_BIND, &b)) 2404 return -errno; 2405 return 0; 2406 } 2407 2408 2409 /** 2410 * Unbind a chunk of AGP memory. 2411 * 2412 * \param fd file descriptor. 2413 * \param handle handle to the allocated memory, as given by drmAgpAllocate(). 2414 * 2415 * \return zero on success, or a negative value on failure. 2416 * 2417 * \internal 2418 * This function is a wrapper around the DRM_IOCTL_AGP_UNBIND ioctl, passing 2419 * the argument in a drm_agp_binding structure. 2420 */ 2421 drm_public int drmAgpUnbind(int fd, drm_handle_t handle) 2422 { 2423 drm_agp_binding_t b; 2424 2425 memclear(b); 2426 b.handle = handle; 2427 if (drmIoctl(fd, DRM_IOCTL_AGP_UNBIND, &b)) 2428 return -errno; 2429 return 0; 2430 } 2431 2432 2433 /** 2434 * Get AGP driver major version number. 2435 * 2436 * \param fd file descriptor. 2437 * 2438 * \return major version number on success, or a negative value on failure.. 2439 * 2440 * \internal 2441 * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the 2442 * necessary information in a drm_agp_info structure. 2443 */ 2444 drm_public int drmAgpVersionMajor(int fd) 2445 { 2446 drm_agp_info_t i; 2447 2448 memclear(i); 2449 2450 if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i)) 2451 return -errno; 2452 return i.agp_version_major; 2453 } 2454 2455 2456 /** 2457 * Get AGP driver minor version number. 2458 * 2459 * \param fd file descriptor. 2460 * 2461 * \return minor version number on success, or a negative value on failure. 2462 * 2463 * \internal 2464 * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the 2465 * necessary information in a drm_agp_info structure. 2466 */ 2467 drm_public int drmAgpVersionMinor(int fd) 2468 { 2469 drm_agp_info_t i; 2470 2471 memclear(i); 2472 2473 if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i)) 2474 return -errno; 2475 return i.agp_version_minor; 2476 } 2477 2478 2479 /** 2480 * Get AGP mode. 2481 * 2482 * \param fd file descriptor. 2483 * 2484 * \return mode on success, or zero on failure. 2485 * 2486 * \internal 2487 * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the 2488 * necessary information in a drm_agp_info structure. 2489 */ 2490 drm_public unsigned long drmAgpGetMode(int fd) 2491 { 2492 drm_agp_info_t i; 2493 2494 memclear(i); 2495 2496 if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i)) 2497 return 0; 2498 return i.mode; 2499 } 2500 2501 2502 /** 2503 * Get AGP aperture base. 2504 * 2505 * \param fd file descriptor. 2506 * 2507 * \return aperture base on success, zero on failure. 2508 * 2509 * \internal 2510 * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the 2511 * necessary information in a drm_agp_info structure. 2512 */ 2513 drm_public unsigned long drmAgpBase(int fd) 2514 { 2515 drm_agp_info_t i; 2516 2517 memclear(i); 2518 2519 if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i)) 2520 return 0; 2521 return i.aperture_base; 2522 } 2523 2524 2525 /** 2526 * Get AGP aperture size. 2527 * 2528 * \param fd file descriptor. 2529 * 2530 * \return aperture size on success, zero on failure. 2531 * 2532 * \internal 2533 * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the 2534 * necessary information in a drm_agp_info structure. 2535 */ 2536 drm_public unsigned long drmAgpSize(int fd) 2537 { 2538 drm_agp_info_t i; 2539 2540 memclear(i); 2541 2542 if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i)) 2543 return 0; 2544 return i.aperture_size; 2545 } 2546 2547 2548 /** 2549 * Get used AGP memory. 2550 * 2551 * \param fd file descriptor. 2552 * 2553 * \return memory used on success, or zero on failure. 2554 * 2555 * \internal 2556 * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the 2557 * necessary information in a drm_agp_info structure. 2558 */ 2559 drm_public unsigned long drmAgpMemoryUsed(int fd) 2560 { 2561 drm_agp_info_t i; 2562 2563 memclear(i); 2564 2565 if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i)) 2566 return 0; 2567 return i.memory_used; 2568 } 2569 2570 2571 /** 2572 * Get available AGP memory. 2573 * 2574 * \param fd file descriptor. 2575 * 2576 * \return memory available on success, or zero on failure. 2577 * 2578 * \internal 2579 * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the 2580 * necessary information in a drm_agp_info structure. 2581 */ 2582 drm_public unsigned long drmAgpMemoryAvail(int fd) 2583 { 2584 drm_agp_info_t i; 2585 2586 memclear(i); 2587 2588 if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i)) 2589 return 0; 2590 return i.memory_allowed; 2591 } 2592 2593 2594 /** 2595 * Get hardware vendor ID. 2596 * 2597 * \param fd file descriptor. 2598 * 2599 * \return vendor ID on success, or zero on failure. 2600 * 2601 * \internal 2602 * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the 2603 * necessary information in a drm_agp_info structure. 2604 */ 2605 drm_public unsigned int drmAgpVendorId(int fd) 2606 { 2607 drm_agp_info_t i; 2608 2609 memclear(i); 2610 2611 if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i)) 2612 return 0; 2613 return i.id_vendor; 2614 } 2615 2616 2617 /** 2618 * Get hardware device ID. 2619 * 2620 * \param fd file descriptor. 2621 * 2622 * \return zero on success, or zero on failure. 2623 * 2624 * \internal 2625 * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the 2626 * necessary information in a drm_agp_info structure. 2627 */ 2628 drm_public unsigned int drmAgpDeviceId(int fd) 2629 { 2630 drm_agp_info_t i; 2631 2632 memclear(i); 2633 2634 if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i)) 2635 return 0; 2636 return i.id_device; 2637 } 2638 2639 drm_public int drmScatterGatherAlloc(int fd, unsigned long size, 2640 drm_handle_t *handle) 2641 { 2642 drm_scatter_gather_t sg; 2643 2644 memclear(sg); 2645 2646 *handle = 0; 2647 sg.size = size; 2648 if (drmIoctl(fd, DRM_IOCTL_SG_ALLOC, &sg)) 2649 return -errno; 2650 *handle = sg.handle; 2651 return 0; 2652 } 2653 2654 drm_public int drmScatterGatherFree(int fd, drm_handle_t handle) 2655 { 2656 drm_scatter_gather_t sg; 2657 2658 memclear(sg); 2659 sg.handle = handle; 2660 if (drmIoctl(fd, DRM_IOCTL_SG_FREE, &sg)) 2661 return -errno; 2662 return 0; 2663 } 2664 2665 /** 2666 * Wait for VBLANK. 2667 * 2668 * \param fd file descriptor. 2669 * \param vbl pointer to a drmVBlank structure. 2670 * 2671 * \return zero on success, or a negative value on failure. 2672 * 2673 * \internal 2674 * This function is a wrapper around the DRM_IOCTL_WAIT_VBLANK ioctl. 2675 */ 2676 drm_public int drmWaitVBlank(int fd, drmVBlankPtr vbl) 2677 { 2678 struct timespec timeout, cur; 2679 int ret; 2680 2681 ret = clock_gettime(CLOCK_MONOTONIC, &timeout); 2682 if (ret < 0) { 2683 fprintf(stderr, "clock_gettime failed: %s\n", strerror(errno)); 2684 goto out; 2685 } 2686 timeout.tv_sec++; 2687 2688 do { 2689 ret = ioctl(fd, DRM_IOCTL_WAIT_VBLANK, vbl); 2690 vbl->request.type &= ~DRM_VBLANK_RELATIVE; 2691 if (ret && errno == EINTR) { 2692 clock_gettime(CLOCK_MONOTONIC, &cur); 2693 /* Timeout after 1s */ 2694 if (cur.tv_sec > timeout.tv_sec + 1 || 2695 (cur.tv_sec == timeout.tv_sec && cur.tv_nsec >= 2696 timeout.tv_nsec)) { 2697 errno = EBUSY; 2698 ret = -1; 2699 break; 2700 } 2701 } 2702 } while (ret && errno == EINTR); 2703 2704 out: 2705 return ret; 2706 } 2707 2708 drm_public int drmError(int err, const char *label) 2709 { 2710 switch (err) { 2711 case DRM_ERR_NO_DEVICE: 2712 fprintf(stderr, "%s: no device\n", label); 2713 break; 2714 case DRM_ERR_NO_ACCESS: 2715 fprintf(stderr, "%s: no access\n", label); 2716 break; 2717 case DRM_ERR_NOT_ROOT: 2718 fprintf(stderr, "%s: not root\n", label); 2719 break; 2720 case DRM_ERR_INVALID: 2721 fprintf(stderr, "%s: invalid args\n", label); 2722 break; 2723 default: 2724 if (err < 0) 2725 err = -err; 2726 fprintf( stderr, "%s: error %d (%s)\n", label, err, strerror(err) ); 2727 break; 2728 } 2729 2730 return 1; 2731 } 2732 2733 /** 2734 * Install IRQ handler. 2735 * 2736 * \param fd file descriptor. 2737 * \param irq IRQ number. 2738 * 2739 * \return zero on success, or a negative value on failure. 2740 * 2741 * \internal 2742 * This function is a wrapper around the DRM_IOCTL_CONTROL ioctl, passing the 2743 * argument in a drm_control structure. 2744 */ 2745 drm_public int drmCtlInstHandler(int fd, int irq) 2746 { 2747 drm_control_t ctl; 2748 2749 memclear(ctl); 2750 ctl.func = DRM_INST_HANDLER; 2751 ctl.irq = irq; 2752 if (drmIoctl(fd, DRM_IOCTL_CONTROL, &ctl)) 2753 return -errno; 2754 return 0; 2755 } 2756 2757 2758 /** 2759 * Uninstall IRQ handler. 2760 * 2761 * \param fd file descriptor. 2762 * 2763 * \return zero on success, or a negative value on failure. 2764 * 2765 * \internal 2766 * This function is a wrapper around the DRM_IOCTL_CONTROL ioctl, passing the 2767 * argument in a drm_control structure. 2768 */ 2769 drm_public int drmCtlUninstHandler(int fd) 2770 { 2771 drm_control_t ctl; 2772 2773 memclear(ctl); 2774 ctl.func = DRM_UNINST_HANDLER; 2775 ctl.irq = 0; 2776 if (drmIoctl(fd, DRM_IOCTL_CONTROL, &ctl)) 2777 return -errno; 2778 return 0; 2779 } 2780 2781 drm_public int drmFinish(int fd, int context, drmLockFlags flags) 2782 { 2783 drm_lock_t lock; 2784 2785 memclear(lock); 2786 lock.context = context; 2787 if (flags & DRM_LOCK_READY) lock.flags |= _DRM_LOCK_READY; 2788 if (flags & DRM_LOCK_QUIESCENT) lock.flags |= _DRM_LOCK_QUIESCENT; 2789 if (flags & DRM_LOCK_FLUSH) lock.flags |= _DRM_LOCK_FLUSH; 2790 if (flags & DRM_LOCK_FLUSH_ALL) lock.flags |= _DRM_LOCK_FLUSH_ALL; 2791 if (flags & DRM_HALT_ALL_QUEUES) lock.flags |= _DRM_HALT_ALL_QUEUES; 2792 if (flags & DRM_HALT_CUR_QUEUES) lock.flags |= _DRM_HALT_CUR_QUEUES; 2793 if (drmIoctl(fd, DRM_IOCTL_FINISH, &lock)) 2794 return -errno; 2795 return 0; 2796 } 2797 2798 /** 2799 * Get IRQ from bus ID. 2800 * 2801 * \param fd file descriptor. 2802 * \param busnum bus number. 2803 * \param devnum device number. 2804 * \param funcnum function number. 2805 * 2806 * \return IRQ number on success, or a negative value on failure. 2807 * 2808 * \internal 2809 * This function is a wrapper around the DRM_IOCTL_IRQ_BUSID ioctl, passing the 2810 * arguments in a drm_irq_busid structure. 2811 */ 2812 drm_public int drmGetInterruptFromBusID(int fd, int busnum, int devnum, 2813 int funcnum) 2814 { 2815 drm_irq_busid_t p; 2816 2817 memclear(p); 2818 p.busnum = busnum; 2819 p.devnum = devnum; 2820 p.funcnum = funcnum; 2821 if (drmIoctl(fd, DRM_IOCTL_IRQ_BUSID, &p)) 2822 return -errno; 2823 return p.irq; 2824 } 2825 2826 drm_public int drmAddContextTag(int fd, drm_context_t context, void *tag) 2827 { 2828 drmHashEntry *entry = drmGetEntry(fd); 2829 2830 if (drmHashInsert(entry->tagTable, context, tag)) { 2831 drmHashDelete(entry->tagTable, context); 2832 drmHashInsert(entry->tagTable, context, tag); 2833 } 2834 return 0; 2835 } 2836 2837 drm_public int drmDelContextTag(int fd, drm_context_t context) 2838 { 2839 drmHashEntry *entry = drmGetEntry(fd); 2840 2841 return drmHashDelete(entry->tagTable, context); 2842 } 2843 2844 drm_public void *drmGetContextTag(int fd, drm_context_t context) 2845 { 2846 drmHashEntry *entry = drmGetEntry(fd); 2847 void *value; 2848 2849 if (drmHashLookup(entry->tagTable, context, &value)) 2850 return NULL; 2851 2852 return value; 2853 } 2854 2855 drm_public int drmAddContextPrivateMapping(int fd, drm_context_t ctx_id, 2856 drm_handle_t handle) 2857 { 2858 drm_ctx_priv_map_t map; 2859 2860 memclear(map); 2861 map.ctx_id = ctx_id; 2862 map.handle = (void *)(uintptr_t)handle; 2863 2864 if (drmIoctl(fd, DRM_IOCTL_SET_SAREA_CTX, &map)) 2865 return -errno; 2866 return 0; 2867 } 2868 2869 drm_public int drmGetContextPrivateMapping(int fd, drm_context_t ctx_id, 2870 drm_handle_t *handle) 2871 { 2872 drm_ctx_priv_map_t map; 2873 2874 memclear(map); 2875 map.ctx_id = ctx_id; 2876 2877 if (drmIoctl(fd, DRM_IOCTL_GET_SAREA_CTX, &map)) 2878 return -errno; 2879 if (handle) 2880 *handle = (drm_handle_t)(uintptr_t)map.handle; 2881 2882 return 0; 2883 } 2884 2885 drm_public int drmGetMap(int fd, int idx, drm_handle_t *offset, drmSize *size, 2886 drmMapType *type, drmMapFlags *flags, 2887 drm_handle_t *handle, int *mtrr) 2888 { 2889 drm_map_t map; 2890 2891 memclear(map); 2892 map.offset = idx; 2893 if (drmIoctl(fd, DRM_IOCTL_GET_MAP, &map)) 2894 return -errno; 2895 *offset = map.offset; 2896 *size = map.size; 2897 *type = (drmMapType)map.type; 2898 *flags = (drmMapFlags)map.flags; 2899 *handle = (unsigned long)map.handle; 2900 *mtrr = map.mtrr; 2901 return 0; 2902 } 2903 2904 drm_public int drmGetClient(int fd, int idx, int *auth, int *pid, int *uid, 2905 unsigned long *magic, unsigned long *iocs) 2906 { 2907 drm_client_t client; 2908 2909 memclear(client); 2910 client.idx = idx; 2911 if (drmIoctl(fd, DRM_IOCTL_GET_CLIENT, &client)) 2912 return -errno; 2913 *auth = client.auth; 2914 *pid = client.pid; 2915 *uid = client.uid; 2916 *magic = client.magic; 2917 *iocs = client.iocs; 2918 return 0; 2919 } 2920 2921 drm_public int drmGetStats(int fd, drmStatsT *stats) 2922 { 2923 drm_stats_t s; 2924 unsigned i; 2925 2926 memclear(s); 2927 if (drmIoctl(fd, DRM_IOCTL_GET_STATS, &s)) 2928 return -errno; 2929 2930 stats->count = 0; 2931 memset(stats, 0, sizeof(*stats)); 2932 if (s.count > sizeof(stats->data)/sizeof(stats->data[0])) 2933 return -1; 2934 2935 #define SET_VALUE \ 2936 stats->data[i].long_format = "%-20.20s"; \ 2937 stats->data[i].rate_format = "%8.8s"; \ 2938 stats->data[i].isvalue = 1; \ 2939 stats->data[i].verbose = 0 2940 2941 #define SET_COUNT \ 2942 stats->data[i].long_format = "%-20.20s"; \ 2943 stats->data[i].rate_format = "%5.5s"; \ 2944 stats->data[i].isvalue = 0; \ 2945 stats->data[i].mult_names = "kgm"; \ 2946 stats->data[i].mult = 1000; \ 2947 stats->data[i].verbose = 0 2948 2949 #define SET_BYTE \ 2950 stats->data[i].long_format = "%-20.20s"; \ 2951 stats->data[i].rate_format = "%5.5s"; \ 2952 stats->data[i].isvalue = 0; \ 2953 stats->data[i].mult_names = "KGM"; \ 2954 stats->data[i].mult = 1024; \ 2955 stats->data[i].verbose = 0 2956 2957 2958 stats->count = s.count; 2959 for (i = 0; i < s.count; i++) { 2960 stats->data[i].value = s.data[i].value; 2961 switch (s.data[i].type) { 2962 case _DRM_STAT_LOCK: 2963 stats->data[i].long_name = "Lock"; 2964 stats->data[i].rate_name = "Lock"; 2965 SET_VALUE; 2966 break; 2967 case _DRM_STAT_OPENS: 2968 stats->data[i].long_name = "Opens"; 2969 stats->data[i].rate_name = "O"; 2970 SET_COUNT; 2971 stats->data[i].verbose = 1; 2972 break; 2973 case _DRM_STAT_CLOSES: 2974 stats->data[i].long_name = "Closes"; 2975 stats->data[i].rate_name = "Lock"; 2976 SET_COUNT; 2977 stats->data[i].verbose = 1; 2978 break; 2979 case _DRM_STAT_IOCTLS: 2980 stats->data[i].long_name = "Ioctls"; 2981 stats->data[i].rate_name = "Ioc/s"; 2982 SET_COUNT; 2983 break; 2984 case _DRM_STAT_LOCKS: 2985 stats->data[i].long_name = "Locks"; 2986 stats->data[i].rate_name = "Lck/s"; 2987 SET_COUNT; 2988 break; 2989 case _DRM_STAT_UNLOCKS: 2990 stats->data[i].long_name = "Unlocks"; 2991 stats->data[i].rate_name = "Unl/s"; 2992 SET_COUNT; 2993 break; 2994 case _DRM_STAT_IRQ: 2995 stats->data[i].long_name = "IRQs"; 2996 stats->data[i].rate_name = "IRQ/s"; 2997 SET_COUNT; 2998 break; 2999 case _DRM_STAT_PRIMARY: 3000 stats->data[i].long_name = "Primary Bytes"; 3001 stats->data[i].rate_name = "PB/s"; 3002 SET_BYTE; 3003 break; 3004 case _DRM_STAT_SECONDARY: 3005 stats->data[i].long_name = "Secondary Bytes"; 3006 stats->data[i].rate_name = "SB/s"; 3007 SET_BYTE; 3008 break; 3009 case _DRM_STAT_DMA: 3010 stats->data[i].long_name = "DMA"; 3011 stats->data[i].rate_name = "DMA/s"; 3012 SET_COUNT; 3013 break; 3014 case _DRM_STAT_SPECIAL: 3015 stats->data[i].long_name = "Special DMA"; 3016 stats->data[i].rate_name = "dma/s"; 3017 SET_COUNT; 3018 break; 3019 case _DRM_STAT_MISSED: 3020 stats->data[i].long_name = "Miss"; 3021 stats->data[i].rate_name = "Ms/s"; 3022 SET_COUNT; 3023 break; 3024 case _DRM_STAT_VALUE: 3025 stats->data[i].long_name = "Value"; 3026 stats->data[i].rate_name = "Value"; 3027 SET_VALUE; 3028 break; 3029 case _DRM_STAT_BYTE: 3030 stats->data[i].long_name = "Bytes"; 3031 stats->data[i].rate_name = "B/s"; 3032 SET_BYTE; 3033 break; 3034 case _DRM_STAT_COUNT: 3035 default: 3036 stats->data[i].long_name = "Count"; 3037 stats->data[i].rate_name = "Cnt/s"; 3038 SET_COUNT; 3039 break; 3040 } 3041 } 3042 return 0; 3043 } 3044 3045 /** 3046 * Issue a set-version ioctl. 3047 * 3048 * \param fd file descriptor. 3049 * \param drmCommandIndex command index 3050 * \param data source pointer of the data to be read and written. 3051 * \param size size of the data to be read and written. 3052 * 3053 * \return zero on success, or a negative value on failure. 3054 * 3055 * \internal 3056 * It issues a read-write ioctl given by 3057 * \code DRM_COMMAND_BASE + drmCommandIndex \endcode. 3058 */ 3059 drm_public int drmSetInterfaceVersion(int fd, drmSetVersion *version) 3060 { 3061 int retcode = 0; 3062 drm_set_version_t sv; 3063 3064 memclear(sv); 3065 sv.drm_di_major = version->drm_di_major; 3066 sv.drm_di_minor = version->drm_di_minor; 3067 sv.drm_dd_major = version->drm_dd_major; 3068 sv.drm_dd_minor = version->drm_dd_minor; 3069 3070 if (drmIoctl(fd, DRM_IOCTL_SET_VERSION, &sv)) { 3071 retcode = -errno; 3072 } 3073 3074 version->drm_di_major = sv.drm_di_major; 3075 version->drm_di_minor = sv.drm_di_minor; 3076 version->drm_dd_major = sv.drm_dd_major; 3077 version->drm_dd_minor = sv.drm_dd_minor; 3078 3079 return retcode; 3080 } 3081 3082 /** 3083 * Send a device-specific command. 3084 * 3085 * \param fd file descriptor. 3086 * \param drmCommandIndex command index 3087 * 3088 * \return zero on success, or a negative value on failure. 3089 * 3090 * \internal 3091 * It issues a ioctl given by 3092 * \code DRM_COMMAND_BASE + drmCommandIndex \endcode. 3093 */ 3094 drm_public int drmCommandNone(int fd, unsigned long drmCommandIndex) 3095 { 3096 unsigned long request; 3097 3098 request = DRM_IO( DRM_COMMAND_BASE + drmCommandIndex); 3099 3100 if (drmIoctl(fd, request, NULL)) { 3101 return -errno; 3102 } 3103 return 0; 3104 } 3105 3106 3107 /** 3108 * Send a device-specific read command. 3109 * 3110 * \param fd file descriptor. 3111 * \param drmCommandIndex command index 3112 * \param data destination pointer of the data to be read. 3113 * \param size size of the data to be read. 3114 * 3115 * \return zero on success, or a negative value on failure. 3116 * 3117 * \internal 3118 * It issues a read ioctl given by 3119 * \code DRM_COMMAND_BASE + drmCommandIndex \endcode. 3120 */ 3121 drm_public int drmCommandRead(int fd, unsigned long drmCommandIndex, 3122 void *data, unsigned long size) 3123 { 3124 unsigned long request; 3125 3126 request = DRM_IOC( DRM_IOC_READ, DRM_IOCTL_BASE, 3127 DRM_COMMAND_BASE + drmCommandIndex, size); 3128 3129 if (drmIoctl(fd, request, data)) { 3130 return -errno; 3131 } 3132 return 0; 3133 } 3134 3135 3136 /** 3137 * Send a device-specific write command. 3138 * 3139 * \param fd file descriptor. 3140 * \param drmCommandIndex command index 3141 * \param data source pointer of the data to be written. 3142 * \param size size of the data to be written. 3143 * 3144 * \return zero on success, or a negative value on failure. 3145 * 3146 * \internal 3147 * It issues a write ioctl given by 3148 * \code DRM_COMMAND_BASE + drmCommandIndex \endcode. 3149 */ 3150 drm_public int drmCommandWrite(int fd, unsigned long drmCommandIndex, 3151 void *data, unsigned long size) 3152 { 3153 unsigned long request; 3154 3155 request = DRM_IOC( DRM_IOC_WRITE, DRM_IOCTL_BASE, 3156 DRM_COMMAND_BASE + drmCommandIndex, size); 3157 3158 if (drmIoctl(fd, request, data)) { 3159 return -errno; 3160 } 3161 return 0; 3162 } 3163 3164 3165 /** 3166 * Send a device-specific read-write command. 3167 * 3168 * \param fd file descriptor. 3169 * \param drmCommandIndex command index 3170 * \param data source pointer of the data to be read and written. 3171 * \param size size of the data to be read and written. 3172 * 3173 * \return zero on success, or a negative value on failure. 3174 * 3175 * \internal 3176 * It issues a read-write ioctl given by 3177 * \code DRM_COMMAND_BASE + drmCommandIndex \endcode. 3178 */ 3179 drm_public int drmCommandWriteRead(int fd, unsigned long drmCommandIndex, 3180 void *data, unsigned long size) 3181 { 3182 unsigned long request; 3183 3184 request = DRM_IOC( DRM_IOC_READ|DRM_IOC_WRITE, DRM_IOCTL_BASE, 3185 DRM_COMMAND_BASE + drmCommandIndex, size); 3186 3187 if (drmIoctl(fd, request, data)) 3188 return -errno; 3189 return 0; 3190 } 3191 3192 #define DRM_MAX_FDS 16 3193 static struct { 3194 char *BusID; 3195 int fd; 3196 int refcount; 3197 int type; 3198 } connection[DRM_MAX_FDS]; 3199 3200 static int nr_fds = 0; 3201 3202 drm_public int drmOpenOnce(void *unused, const char *BusID, int *newlyopened) 3203 { 3204 return drmOpenOnceWithType(BusID, newlyopened, DRM_NODE_PRIMARY); 3205 } 3206 3207 drm_public int drmOpenOnceWithType(const char *BusID, int *newlyopened, 3208 int type) 3209 { 3210 int i; 3211 int fd; 3212 3213 for (i = 0; i < nr_fds; i++) 3214 if ((strcmp(BusID, connection[i].BusID) == 0) && 3215 (connection[i].type == type)) { 3216 connection[i].refcount++; 3217 *newlyopened = 0; 3218 return connection[i].fd; 3219 } 3220 3221 fd = drmOpenWithType(NULL, BusID, type); 3222 if (fd < 0 || nr_fds == DRM_MAX_FDS) 3223 return fd; 3224 3225 connection[nr_fds].BusID = strdup(BusID); 3226 connection[nr_fds].fd = fd; 3227 connection[nr_fds].refcount = 1; 3228 connection[nr_fds].type = type; 3229 *newlyopened = 1; 3230 3231 if (0) 3232 fprintf(stderr, "saved connection %d for %s %d\n", 3233 nr_fds, connection[nr_fds].BusID, 3234 strcmp(BusID, connection[nr_fds].BusID)); 3235 3236 nr_fds++; 3237 3238 return fd; 3239 } 3240 3241 drm_public void drmCloseOnce(int fd) 3242 { 3243 int i; 3244 3245 for (i = 0; i < nr_fds; i++) { 3246 if (fd == connection[i].fd) { 3247 if (--connection[i].refcount == 0) { 3248 drmClose(connection[i].fd); 3249 free(connection[i].BusID); 3250 3251 if (i < --nr_fds) 3252 connection[i] = connection[nr_fds]; 3253 3254 return; 3255 } 3256 } 3257 } 3258 } 3259 3260 drm_public int drmSetMaster(int fd) 3261 { 3262 return drmIoctl(fd, DRM_IOCTL_SET_MASTER, NULL); 3263 } 3264 3265 drm_public int drmDropMaster(int fd) 3266 { 3267 return drmIoctl(fd, DRM_IOCTL_DROP_MASTER, NULL); 3268 } 3269 3270 drm_public int drmIsMaster(int fd) 3271 { 3272 /* Detect master by attempting something that requires master. 3273 * 3274 * Authenticating magic tokens requires master and 0 is an 3275 * internal kernel detail which we could use. Attempting this on 3276 * a master fd would fail therefore fail with EINVAL because 0 3277 * is invalid. 3278 * 3279 * A non-master fd will fail with EACCES, as the kernel checks 3280 * for master before attempting to do anything else. 3281 * 3282 * Since we don't want to leak implementation details, use 3283 * EACCES. 3284 */ 3285 return drmAuthMagic(fd, 0) != -EACCES; 3286 } 3287 3288 drm_public char *drmGetDeviceNameFromFd(int fd) 3289 { 3290 #ifdef __FreeBSD__ 3291 struct stat sbuf; 3292 int maj, min; 3293 int nodetype; 3294 3295 if (fstat(fd, &sbuf)) 3296 return NULL; 3297 3298 maj = major(sbuf.st_rdev); 3299 min = minor(sbuf.st_rdev); 3300 nodetype = drmGetMinorType(maj, min); 3301 return drmGetMinorNameForFD(fd, nodetype); 3302 #else 3303 char name[128]; 3304 struct stat sbuf; 3305 dev_t d; 3306 int i; 3307 3308 /* The whole drmOpen thing is a fiasco and we need to find a way 3309 * back to just using open(2). For now, however, lets just make 3310 * things worse with even more ad hoc directory walking code to 3311 * discover the device file name. */ 3312 3313 fstat(fd, &sbuf); 3314 d = sbuf.st_rdev; 3315 3316 for (i = 0; i < DRM_MAX_MINOR; i++) { 3317 snprintf(name, sizeof name, DRM_DEV_NAME, DRM_DIR_NAME, i); 3318 if (stat(name, &sbuf) == 0 && sbuf.st_rdev == d) 3319 break; 3320 } 3321 if (i == DRM_MAX_MINOR) 3322 return NULL; 3323 3324 return strdup(name); 3325 #endif 3326 } 3327 3328 static bool drmNodeIsDRM(int maj, int min) 3329 { 3330 #ifdef __linux__ 3331 char path[64]; 3332 struct stat sbuf; 3333 3334 snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device/drm", 3335 maj, min); 3336 return stat(path, &sbuf) == 0; 3337 #elif defined(__FreeBSD__) 3338 char name[SPECNAMELEN]; 3339 3340 if (!devname_r(makedev(maj, min), S_IFCHR, name, sizeof(name))) 3341 return 0; 3342 /* Handle drm/ and dri/ as both are present in different FreeBSD version 3343 * FreeBSD on amd64/i386/powerpc external kernel modules create node in 3344 * in /dev/drm/ and links in /dev/dri while a WIP in kernel driver creates 3345 * only device nodes in /dev/dri/ */ 3346 return (!strncmp(name, "drm/", 4) || !strncmp(name, "dri/", 4)); 3347 #else 3348 return maj == DRM_MAJOR; 3349 #endif 3350 } 3351 3352 drm_public int drmGetNodeTypeFromFd(int fd) 3353 { 3354 struct stat sbuf; 3355 int maj, min, type; 3356 3357 if (fstat(fd, &sbuf)) 3358 return -1; 3359 3360 maj = major(sbuf.st_rdev); 3361 min = minor(sbuf.st_rdev); 3362 3363 if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode)) { 3364 errno = EINVAL; 3365 return -1; 3366 } 3367 3368 type = drmGetMinorType(maj, min); 3369 if (type == -1) 3370 errno = ENODEV; 3371 return type; 3372 } 3373 3374 drm_public int drmPrimeHandleToFD(int fd, uint32_t handle, uint32_t flags, 3375 int *prime_fd) 3376 { 3377 struct drm_prime_handle args; 3378 int ret; 3379 3380 memclear(args); 3381 args.fd = -1; 3382 args.handle = handle; 3383 args.flags = flags; 3384 ret = drmIoctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &args); 3385 if (ret) 3386 return ret; 3387 3388 *prime_fd = args.fd; 3389 return 0; 3390 } 3391 3392 drm_public int drmPrimeFDToHandle(int fd, int prime_fd, uint32_t *handle) 3393 { 3394 struct drm_prime_handle args; 3395 int ret; 3396 3397 memclear(args); 3398 args.fd = prime_fd; 3399 ret = drmIoctl(fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &args); 3400 if (ret) 3401 return ret; 3402 3403 *handle = args.handle; 3404 return 0; 3405 } 3406 3407 drm_public int drmCloseBufferHandle(int fd, uint32_t handle) 3408 { 3409 struct drm_gem_close args; 3410 3411 memclear(args); 3412 args.handle = handle; 3413 return drmIoctl(fd, DRM_IOCTL_GEM_CLOSE, &args); 3414 } 3415 3416 static char *drmGetMinorNameForFD(int fd, int type) 3417 { 3418 #ifdef __linux__ 3419 DIR *sysdir; 3420 struct dirent *ent; 3421 struct stat sbuf; 3422 const char *name = drmGetMinorName(type); 3423 int len; 3424 char dev_name[64], buf[64]; 3425 int maj, min; 3426 3427 if (!name) 3428 return NULL; 3429 3430 len = strlen(name); 3431 3432 if (fstat(fd, &sbuf)) 3433 return NULL; 3434 3435 maj = major(sbuf.st_rdev); 3436 min = minor(sbuf.st_rdev); 3437 3438 if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode)) 3439 return NULL; 3440 3441 snprintf(buf, sizeof(buf), "/sys/dev/char/%d:%d/device/drm", maj, min); 3442 3443 sysdir = opendir(buf); 3444 if (!sysdir) 3445 return NULL; 3446 3447 while ((ent = readdir(sysdir))) { 3448 if (strncmp(ent->d_name, name, len) == 0) { 3449 if (snprintf(dev_name, sizeof(dev_name), DRM_DIR_NAME "/%s", 3450 ent->d_name) < 0) 3451 return NULL; 3452 3453 closedir(sysdir); 3454 return strdup(dev_name); 3455 } 3456 } 3457 3458 closedir(sysdir); 3459 return NULL; 3460 #elif defined(__FreeBSD__) 3461 struct stat sbuf; 3462 char dname[SPECNAMELEN]; 3463 const char *mname; 3464 char name[SPECNAMELEN]; 3465 int id, maj, min, nodetype, i; 3466 3467 if (fstat(fd, &sbuf)) 3468 return NULL; 3469 3470 maj = major(sbuf.st_rdev); 3471 min = minor(sbuf.st_rdev); 3472 3473 if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode)) 3474 return NULL; 3475 3476 if (!devname_r(sbuf.st_rdev, S_IFCHR, dname, sizeof(dname))) 3477 return NULL; 3478 3479 /* Handle both /dev/drm and /dev/dri 3480 * FreeBSD on amd64/i386/powerpc external kernel modules create node in 3481 * in /dev/drm/ and links in /dev/dri while a WIP in kernel driver creates 3482 * only device nodes in /dev/dri/ */ 3483 3484 /* Get the node type represented by fd so we can deduce the target name */ 3485 nodetype = drmGetMinorType(maj, min); 3486 if (nodetype == -1) 3487 return (NULL); 3488 mname = drmGetMinorName(type); 3489 3490 for (i = 0; i < SPECNAMELEN; i++) { 3491 if (isalpha(dname[i]) == 0 && dname[i] != '/') 3492 break; 3493 } 3494 if (dname[i] == '\0') 3495 return (NULL); 3496 3497 id = (int)strtol(&dname[i], NULL, 10); 3498 id -= drmGetMinorBase(nodetype); 3499 snprintf(name, sizeof(name), DRM_DIR_NAME "/%s%d", mname, 3500 id + drmGetMinorBase(type)); 3501 3502 return strdup(name); 3503 #else 3504 struct stat sbuf; 3505 char buf[PATH_MAX + 1]; 3506 const char *dev_name = drmGetDeviceName(type); 3507 unsigned int maj, min; 3508 int n; 3509 3510 if (fstat(fd, &sbuf)) 3511 return NULL; 3512 3513 maj = major(sbuf.st_rdev); 3514 min = minor(sbuf.st_rdev); 3515 3516 if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode)) 3517 return NULL; 3518 3519 if (!dev_name) 3520 return NULL; 3521 3522 n = snprintf(buf, sizeof(buf), dev_name, DRM_DIR_NAME, min); 3523 if (n == -1 || n >= sizeof(buf)) 3524 return NULL; 3525 3526 return strdup(buf); 3527 #endif 3528 } 3529 3530 drm_public char *drmGetPrimaryDeviceNameFromFd(int fd) 3531 { 3532 return drmGetMinorNameForFD(fd, DRM_NODE_PRIMARY); 3533 } 3534 3535 drm_public char *drmGetRenderDeviceNameFromFd(int fd) 3536 { 3537 return drmGetMinorNameForFD(fd, DRM_NODE_RENDER); 3538 } 3539 3540 #ifdef __linux__ 3541 static char * DRM_PRINTFLIKE(2, 3) 3542 sysfs_uevent_get(const char *path, const char *fmt, ...) 3543 { 3544 char filename[PATH_MAX + 1], *key, *line = NULL, *value = NULL; 3545 size_t size = 0, len; 3546 ssize_t num; 3547 va_list ap; 3548 FILE *fp; 3549 3550 va_start(ap, fmt); 3551 num = vasprintf(&key, fmt, ap); 3552 va_end(ap); 3553 len = num; 3554 3555 snprintf(filename, sizeof(filename), "%s/uevent", path); 3556 3557 fp = fopen(filename, "r"); 3558 if (!fp) { 3559 free(key); 3560 return NULL; 3561 } 3562 3563 while ((num = getline(&line, &size, fp)) >= 0) { 3564 if ((strncmp(line, key, len) == 0) && (line[len] == '=')) { 3565 char *start = line + len + 1, *end = line + num - 1; 3566 3567 if (*end != '\n') 3568 end++; 3569 3570 value = strndup(start, end - start); 3571 break; 3572 } 3573 } 3574 3575 free(line); 3576 fclose(fp); 3577 3578 free(key); 3579 3580 return value; 3581 } 3582 #endif 3583 3584 /* Little white lie to avoid major rework of the existing code */ 3585 #define DRM_BUS_VIRTIO 0x10 3586 3587 #ifdef __linux__ 3588 static int get_subsystem_type(const char *device_path) 3589 { 3590 char path[PATH_MAX + 1] = ""; 3591 char link[PATH_MAX + 1] = ""; 3592 char *name; 3593 struct { 3594 const char *name; 3595 int bus_type; 3596 } bus_types[] = { 3597 { "/pci", DRM_BUS_PCI }, 3598 { "/usb", DRM_BUS_USB }, 3599 { "/platform", DRM_BUS_PLATFORM }, 3600 { "/spi", DRM_BUS_PLATFORM }, 3601 { "/host1x", DRM_BUS_HOST1X }, 3602 { "/virtio", DRM_BUS_VIRTIO }, 3603 { "/faux", DRM_BUS_FAUX }, 3604 }; 3605 3606 strncpy(path, device_path, PATH_MAX); 3607 strncat(path, "/subsystem", PATH_MAX); 3608 3609 if (readlink(path, link, PATH_MAX) < 0) 3610 return -errno; 3611 3612 name = strrchr(link, '/'); 3613 if (!name) 3614 return -EINVAL; 3615 3616 for (unsigned i = 0; i < ARRAY_SIZE(bus_types); i++) { 3617 if (strncmp(name, bus_types[i].name, strlen(bus_types[i].name)) == 0) 3618 return bus_types[i].bus_type; 3619 } 3620 3621 return -EINVAL; 3622 } 3623 #endif 3624 3625 static int drmParseSubsystemType(int maj, int min) 3626 { 3627 #ifdef __linux__ 3628 char path[PATH_MAX + 1] = ""; 3629 char real_path[PATH_MAX + 1] = ""; 3630 int subsystem_type; 3631 3632 snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min); 3633 3634 subsystem_type = get_subsystem_type(path); 3635 /* Try to get the parent (underlying) device type */ 3636 if (subsystem_type == DRM_BUS_VIRTIO) { 3637 /* Assume virtio-pci on error */ 3638 if (!realpath(path, real_path)) 3639 return DRM_BUS_VIRTIO; 3640 strncat(path, "/..", PATH_MAX); 3641 subsystem_type = get_subsystem_type(path); 3642 if (subsystem_type < 0) 3643 return DRM_BUS_VIRTIO; 3644 } 3645 #elif defined(__NetBSD__) 3646 int type, fd; 3647 drmSetVersion sv; 3648 char *buf; 3649 unsigned domain, bus, dev; 3650 int func; 3651 int ret; 3652 3653 /* Get the type of device we're looking for to pick the right pathname. */ 3654 type = drmGetMinorType(maj, min); 3655 if (type == -1) 3656 return -ENODEV; 3657 3658 /* Open the device. Don't try to create it if it's not there. */ 3659 fd = drmOpenMinor(min, 0, type); 3660 if (fd < 0) 3661 return -errno; 3662 3663 /* 3664 * Set the interface version to 1.4 or 1.1, which has the effect of 3665 * populating the bus id for us. 3666 */ 3667 sv.drm_di_major = 1; 3668 sv.drm_di_minor = 4; 3669 sv.drm_dd_major = -1; 3670 sv.drm_dd_minor = -1; 3671 if (drmSetInterfaceVersion(fd, &sv)) { 3672 sv.drm_di_major = 1; 3673 sv.drm_di_minor = 1; 3674 sv.drm_dd_major = -1; 3675 sv.drm_dd_minor = -1; 3676 if (drmSetInterfaceVersion(fd, &sv)) { 3677 /* 3678 * We're probably not the master. Hope the master already 3679 * set the version to >=1.1 so that we can get the busid. 3680 */ 3681 } 3682 } 3683 3684 /* Get the bus id. */ 3685 buf = drmGetBusid(fd); 3686 3687 /* We're done with the device now. */ 3688 (void)close(fd); 3689 3690 /* If there is no bus id, fail. */ 3691 if (buf == NULL) 3692 return -ENODEV; 3693 3694 /* Find a string we know about; otherwise -EINVAL. */ 3695 ret = -EINVAL; 3696 if (strncmp(buf, "pci:", 4) == 0) 3697 ret = DRM_BUS_PCI; 3698 3699 /* We're done with the bus id. */ 3700 free(buf); 3701 3702 /* Success or not, we're done. */ 3703 return ret; 3704 #elif defined(__OpenBSD__) || defined(__DragonFly__) 3705 return DRM_BUS_PCI; 3706 #else 3707 #warning "Missing implementation of drmParseSubsystemType" 3708 return -EINVAL; 3709 #endif 3710 } 3711 3712 #ifdef __linux__ 3713 static void 3714 get_pci_path(int maj, int min, char *pci_path) 3715 { 3716 char path[PATH_MAX + 1], *term; 3717 3718 snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min); 3719 if (!realpath(path, pci_path)) { 3720 strcpy(pci_path, path); 3721 return; 3722 } 3723 3724 term = strrchr(pci_path, '/'); 3725 if (term && strncmp(term, "/virtio", 7) == 0) 3726 *term = 0; 3727 } 3728 #endif 3729 3730 #ifdef __FreeBSD__ 3731 static int get_sysctl_pci_bus_info(int maj, int min, drmPciBusInfoPtr info) 3732 { 3733 char dname[SPECNAMELEN]; 3734 char sysctl_name[16]; 3735 char sysctl_val[256]; 3736 size_t sysctl_len; 3737 int id, type, nelem; 3738 unsigned int rdev, majmin, domain, bus, dev, func; 3739 3740 rdev = makedev(maj, min); 3741 if (!devname_r(rdev, S_IFCHR, dname, sizeof(dname))) 3742 return -EINVAL; 3743 3744 if (sscanf(dname, "drm/%d\n", &id) != 1) 3745 return -EINVAL; 3746 type = drmGetMinorType(maj, min); 3747 if (type == -1) 3748 return -EINVAL; 3749 3750 /* BUG: This above section is iffy, since it mandates that a driver will 3751 * create both card and render node. 3752 * If it does not, the next DRM device will create card#X and 3753 * renderD#(128+X)-1. 3754 * This is a possibility in FreeBSD but for now there is no good way for 3755 * obtaining the info. 3756 */ 3757 switch (type) { 3758 case DRM_NODE_PRIMARY: 3759 break; 3760 case DRM_NODE_RENDER: 3761 id -= 128; 3762 break; 3763 } 3764 if (id < 0) 3765 return -EINVAL; 3766 3767 if (snprintf(sysctl_name, sizeof(sysctl_name), "hw.dri.%d.busid", id) <= 0) 3768 return -EINVAL; 3769 sysctl_len = sizeof(sysctl_val); 3770 if (sysctlbyname(sysctl_name, sysctl_val, &sysctl_len, NULL, 0)) 3771 return -EINVAL; 3772 3773 #define bus_fmt "pci:%04x:%02x:%02x.%u" 3774 3775 nelem = sscanf(sysctl_val, bus_fmt, &domain, &bus, &dev, &func); 3776 if (nelem != 4) 3777 return -EINVAL; 3778 info->domain = domain; 3779 info->bus = bus; 3780 info->dev = dev; 3781 info->func = func; 3782 3783 return 0; 3784 } 3785 #endif 3786 3787 static int drmParsePciBusInfo(int maj, int min, drmPciBusInfoPtr info) 3788 { 3789 #ifdef __linux__ 3790 unsigned int domain, bus, dev, func; 3791 char pci_path[PATH_MAX + 1], *value; 3792 int num; 3793 3794 get_pci_path(maj, min, pci_path); 3795 3796 value = sysfs_uevent_get(pci_path, "PCI_SLOT_NAME"); 3797 if (!value) 3798 return -ENOENT; 3799 3800 num = sscanf(value, "%04x:%02x:%02x.%1u", &domain, &bus, &dev, &func); 3801 free(value); 3802 3803 if (num != 4) 3804 return -EINVAL; 3805 3806 info->domain = domain; 3807 info->bus = bus; 3808 info->dev = dev; 3809 info->func = func; 3810 3811 return 0; 3812 #elif defined(__NetBSD__) 3813 int type, fd; 3814 drmSetVersion sv; 3815 char *buf; 3816 unsigned domain, bus, dev; 3817 int func; 3818 int ret; 3819 3820 /* Get the type of device we're looking for to pick the right pathname. */ 3821 type = drmGetMinorType(maj, min); 3822 if (type == -1) 3823 return -ENODEV; 3824 3825 /* Open the device. Don't try to create it if it's not there. */ 3826 fd = drmOpenMinor(min, 0, type); 3827 if (fd < 0) 3828 return -errno; 3829 3830 /* 3831 * Set the interface version to 1.4 or 1.1, which has the effect of 3832 * populating the bus id for us. 3833 */ 3834 sv.drm_di_major = 1; 3835 sv.drm_di_minor = 4; 3836 sv.drm_dd_major = -1; 3837 sv.drm_dd_minor = -1; 3838 if (drmSetInterfaceVersion(fd, &sv)) { 3839 sv.drm_di_major = 1; 3840 sv.drm_di_minor = 1; 3841 sv.drm_dd_major = -1; 3842 sv.drm_dd_minor = -1; 3843 if (drmSetInterfaceVersion(fd, &sv)) { 3844 /* 3845 * We're probably not the master. Hope the master already 3846 * set the version to >=1.1 so that we can get the busid. 3847 */ 3848 } 3849 } 3850 3851 /* Get the bus id. */ 3852 buf = drmGetBusid(fd); 3853 3854 /* We're done with the device now. */ 3855 (void)close(fd); 3856 3857 /* If there is no bus id, fail. */ 3858 if (buf == NULL) 3859 return -ENODEV; 3860 3861 /* Parse the bus id. */ 3862 ret = sscanf(buf, "pci:%04x:%02x:%02x.%d", &domain, &bus, &dev, &func); 3863 3864 /* We're done with the bus id. */ 3865 free(buf); 3866 3867 /* If scanf didn't return 4 -- domain, bus, dev, func -- then fail. */ 3868 if (ret != 4) 3869 return -ENODEV; 3870 3871 /* Populate the results. */ 3872 info->domain = domain; 3873 info->bus = bus; 3874 info->dev = dev; 3875 info->func = func; 3876 3877 /* Success! */ 3878 return 0; 3879 #elif defined(__OpenBSD__) || defined(__DragonFly__) 3880 struct drm_pciinfo pinfo; 3881 int fd, type; 3882 3883 type = drmGetMinorType(maj, min); 3884 if (type == -1) 3885 return -ENODEV; 3886 3887 fd = drmOpenMinor(min, 0, type); 3888 if (fd < 0) 3889 return -errno; 3890 3891 if (drmIoctl(fd, DRM_IOCTL_GET_PCIINFO, &pinfo)) { 3892 close(fd); 3893 return -errno; 3894 } 3895 close(fd); 3896 3897 info->domain = pinfo.domain; 3898 info->bus = pinfo.bus; 3899 info->dev = pinfo.dev; 3900 info->func = pinfo.func; 3901 3902 return 0; 3903 #elif defined(__FreeBSD__) 3904 return get_sysctl_pci_bus_info(maj, min, info); 3905 #else 3906 #warning "Missing implementation of drmParsePciBusInfo" 3907 return -EINVAL; 3908 #endif 3909 } 3910 3911 drm_public int drmDevicesEqual(drmDevicePtr a, drmDevicePtr b) 3912 { 3913 if (a == NULL || b == NULL) 3914 return 0; 3915 3916 if (a->bustype != b->bustype) 3917 return 0; 3918 3919 switch (a->bustype) { 3920 case DRM_BUS_PCI: 3921 return memcmp(a->businfo.pci, b->businfo.pci, sizeof(drmPciBusInfo)) == 0; 3922 3923 case DRM_BUS_USB: 3924 return memcmp(a->businfo.usb, b->businfo.usb, sizeof(drmUsbBusInfo)) == 0; 3925 3926 case DRM_BUS_PLATFORM: 3927 return memcmp(a->businfo.platform, b->businfo.platform, sizeof(drmPlatformBusInfo)) == 0; 3928 3929 case DRM_BUS_HOST1X: 3930 return memcmp(a->businfo.host1x, b->businfo.host1x, sizeof(drmHost1xBusInfo)) == 0; 3931 3932 case DRM_BUS_FAUX: 3933 return memcmp(a->businfo.faux, b->businfo.faux, sizeof(drmFauxBusInfo)) == 0; 3934 3935 default: 3936 break; 3937 } 3938 3939 return 0; 3940 } 3941 3942 static int drmGetNodeType(const char *name) 3943 { 3944 if (strncmp(name, DRM_RENDER_MINOR_NAME, 3945 sizeof(DRM_RENDER_MINOR_NAME) - 1) == 0) 3946 return DRM_NODE_RENDER; 3947 3948 if (strncmp(name, DRM_PRIMARY_MINOR_NAME, 3949 sizeof(DRM_PRIMARY_MINOR_NAME) - 1) == 0) 3950 return DRM_NODE_PRIMARY; 3951 3952 return -EINVAL; 3953 } 3954 3955 static int drmGetMaxNodeName(void) 3956 { 3957 return sizeof(DRM_DIR_NAME) + 3958 MAX3(sizeof(DRM_PRIMARY_MINOR_NAME), 3959 sizeof(DRM_CONTROL_MINOR_NAME), 3960 sizeof(DRM_RENDER_MINOR_NAME)) + 3961 3 /* length of the node number */; 3962 } 3963 3964 #ifdef __linux__ 3965 static int parse_separate_sysfs_files(int maj, int min, 3966 drmPciDeviceInfoPtr device, 3967 bool ignore_revision) 3968 { 3969 static const char *attrs[] = { 3970 "revision", /* Older kernels are missing the file, so check for it first */ 3971 "vendor", 3972 "device", 3973 "subsystem_vendor", 3974 "subsystem_device", 3975 }; 3976 char path[PATH_MAX + 1], pci_path[PATH_MAX + 1]; 3977 unsigned int data[ARRAY_SIZE(attrs)]; 3978 FILE *fp; 3979 int ret; 3980 3981 get_pci_path(maj, min, pci_path); 3982 3983 for (unsigned i = ignore_revision ? 1 : 0; i < ARRAY_SIZE(attrs); i++) { 3984 if (snprintf(path, PATH_MAX, "%s/%s", pci_path, attrs[i]) < 0) 3985 return -errno; 3986 3987 fp = fopen(path, "r"); 3988 if (!fp) 3989 return -errno; 3990 3991 ret = fscanf(fp, "%x", &data[i]); 3992 fclose(fp); 3993 if (ret != 1) 3994 return -errno; 3995 3996 } 3997 3998 device->revision_id = ignore_revision ? 0xff : data[0] & 0xff; 3999 device->vendor_id = data[1] & 0xffff; 4000 device->device_id = data[2] & 0xffff; 4001 device->subvendor_id = data[3] & 0xffff; 4002 device->subdevice_id = data[4] & 0xffff; 4003 4004 return 0; 4005 } 4006 4007 static int parse_config_sysfs_file(int maj, int min, 4008 drmPciDeviceInfoPtr device) 4009 { 4010 char path[PATH_MAX + 1], pci_path[PATH_MAX + 1]; 4011 unsigned char config[64]; 4012 int fd, ret; 4013 4014 get_pci_path(maj, min, pci_path); 4015 4016 if (snprintf(path, PATH_MAX, "%s/config", pci_path) < 0) 4017 return -errno; 4018 4019 fd = open(path, O_RDONLY); 4020 if (fd < 0) 4021 return -errno; 4022 4023 ret = read(fd, config, sizeof(config)); 4024 close(fd); 4025 if (ret < 0) 4026 return -errno; 4027 4028 device->vendor_id = config[0] | (config[1] << 8); 4029 device->device_id = config[2] | (config[3] << 8); 4030 device->revision_id = config[8]; 4031 device->subvendor_id = config[44] | (config[45] << 8); 4032 device->subdevice_id = config[46] | (config[47] << 8); 4033 4034 return 0; 4035 } 4036 #endif 4037 4038 static int drmParsePciDeviceInfo(int maj, int min, 4039 drmPciDeviceInfoPtr device, 4040 uint32_t flags) 4041 { 4042 #ifdef __linux__ 4043 if (!(flags & DRM_DEVICE_GET_PCI_REVISION)) 4044 return parse_separate_sysfs_files(maj, min, device, true); 4045 4046 if (parse_separate_sysfs_files(maj, min, device, false)) 4047 return parse_config_sysfs_file(maj, min, device); 4048 4049 return 0; 4050 #elif defined(__NetBSD__) 4051 drmPciBusInfo businfo; 4052 char fname[PATH_MAX]; 4053 int pcifd; 4054 pcireg_t id, class, subsys; 4055 int ret; 4056 4057 /* Find where on the bus the device lives. */ 4058 ret = drmParsePciBusInfo(maj, min, &businfo); 4059 if (ret) 4060 return ret; 4061 4062 /* Open the pciN device node to get at its config registers. */ 4063 if (snprintf(fname, sizeof fname, "/dev/pci%u", businfo.domain) 4064 >= sizeof fname) 4065 return -ENODEV; 4066 if ((pcifd = open(fname, O_RDONLY)) == -1) 4067 return -errno; 4068 4069 ret = -1; 4070 /* Read the id and class pci config registers. */ 4071 if (pcibus_conf_read(pcifd, businfo.bus, businfo.dev, businfo.func, 4072 PCI_ID_REG, &id) == -1) 4073 goto out; 4074 if (pcibus_conf_read(pcifd, businfo.bus, businfo.dev, businfo.func, 4075 PCI_CLASS_REG, &class) == -1) 4076 goto out; 4077 if (pcibus_conf_read(pcifd, businfo.bus, businfo.dev, businfo.func, 4078 PCI_SUBSYS_ID_REG, &subsys) == -1) 4079 goto out; 4080 4081 ret = 0; 4082 device->vendor_id = PCI_VENDOR(id); 4083 device->device_id = PCI_PRODUCT(id); 4084 device->subvendor_id = PCI_SUBSYS_VENDOR(subsys); 4085 device->subdevice_id = PCI_SUBSYS_ID(subsys); 4086 device->revision_id = PCI_REVISION(class); 4087 out: 4088 if (ret == -1) 4089 ret = -errno; 4090 close(pcifd); 4091 return ret; 4092 #elif defined(__OpenBSD__) || defined(__DragonFly__) 4093 struct drm_pciinfo pinfo; 4094 int fd, type; 4095 4096 type = drmGetMinorType(maj, min); 4097 if (type == -1) 4098 return -ENODEV; 4099 4100 fd = drmOpenMinor(min, 0, type); 4101 if (fd < 0) 4102 return -errno; 4103 4104 if (drmIoctl(fd, DRM_IOCTL_GET_PCIINFO, &pinfo)) { 4105 close(fd); 4106 return -errno; 4107 } 4108 close(fd); 4109 4110 device->vendor_id = pinfo.vendor_id; 4111 device->device_id = pinfo.device_id; 4112 device->revision_id = pinfo.revision_id; 4113 device->subvendor_id = pinfo.subvendor_id; 4114 device->subdevice_id = pinfo.subdevice_id; 4115 4116 return 0; 4117 #elif defined(__FreeBSD__) 4118 drmPciBusInfo info; 4119 struct pci_conf_io pc; 4120 struct pci_match_conf patterns[1]; 4121 struct pci_conf results[1]; 4122 int fd, error; 4123 4124 if (get_sysctl_pci_bus_info(maj, min, &info) != 0) 4125 return -EINVAL; 4126 4127 fd = open("/dev/pci", O_RDONLY); 4128 if (fd < 0) 4129 return -errno; 4130 4131 bzero(&patterns, sizeof(patterns)); 4132 patterns[0].pc_sel.pc_domain = info.domain; 4133 patterns[0].pc_sel.pc_bus = info.bus; 4134 patterns[0].pc_sel.pc_dev = info.dev; 4135 patterns[0].pc_sel.pc_func = info.func; 4136 patterns[0].flags = PCI_GETCONF_MATCH_DOMAIN | PCI_GETCONF_MATCH_BUS 4137 | PCI_GETCONF_MATCH_DEV | PCI_GETCONF_MATCH_FUNC; 4138 bzero(&pc, sizeof(struct pci_conf_io)); 4139 pc.num_patterns = 1; 4140 pc.pat_buf_len = sizeof(patterns); 4141 pc.patterns = patterns; 4142 pc.match_buf_len = sizeof(results); 4143 pc.matches = results; 4144 4145 if (ioctl(fd, PCIOCGETCONF, &pc) || pc.status == PCI_GETCONF_ERROR) { 4146 error = errno; 4147 close(fd); 4148 return -error; 4149 } 4150 close(fd); 4151 4152 device->vendor_id = results[0].pc_vendor; 4153 device->device_id = results[0].pc_device; 4154 device->subvendor_id = results[0].pc_subvendor; 4155 device->subdevice_id = results[0].pc_subdevice; 4156 device->revision_id = results[0].pc_revid; 4157 4158 return 0; 4159 #else 4160 #warning "Missing implementation of drmParsePciDeviceInfo" 4161 return -EINVAL; 4162 #endif 4163 } 4164 4165 static void drmFreePlatformDevice(drmDevicePtr device) 4166 { 4167 if (device->deviceinfo.platform) { 4168 if (device->deviceinfo.platform->compatible) { 4169 char **compatible = device->deviceinfo.platform->compatible; 4170 4171 while (*compatible) { 4172 free(*compatible); 4173 compatible++; 4174 } 4175 4176 free(device->deviceinfo.platform->compatible); 4177 } 4178 } 4179 } 4180 4181 static void drmFreeHost1xDevice(drmDevicePtr device) 4182 { 4183 if (device->deviceinfo.host1x) { 4184 if (device->deviceinfo.host1x->compatible) { 4185 char **compatible = device->deviceinfo.host1x->compatible; 4186 4187 while (*compatible) { 4188 free(*compatible); 4189 compatible++; 4190 } 4191 4192 free(device->deviceinfo.host1x->compatible); 4193 } 4194 } 4195 } 4196 4197 drm_public void drmFreeDevice(drmDevicePtr *device) 4198 { 4199 if (device == NULL) 4200 return; 4201 4202 if (*device) { 4203 switch ((*device)->bustype) { 4204 case DRM_BUS_PLATFORM: 4205 drmFreePlatformDevice(*device); 4206 break; 4207 4208 case DRM_BUS_HOST1X: 4209 drmFreeHost1xDevice(*device); 4210 break; 4211 } 4212 } 4213 4214 free(*device); 4215 *device = NULL; 4216 } 4217 4218 drm_public void drmFreeDevices(drmDevicePtr devices[], int count) 4219 { 4220 int i; 4221 4222 if (devices == NULL) 4223 return; 4224 4225 for (i = 0; i < count; i++) 4226 if (devices[i]) 4227 drmFreeDevice(&devices[i]); 4228 } 4229 4230 static drmDevicePtr drmDeviceAlloc(unsigned int type, const char *node, 4231 size_t bus_size, size_t device_size, 4232 char **ptrp) 4233 { 4234 size_t max_node_length, extra, size; 4235 drmDevicePtr device; 4236 unsigned int i; 4237 char *ptr; 4238 4239 max_node_length = ALIGN(drmGetMaxNodeName(), sizeof(void *)); 4240 extra = DRM_NODE_MAX * (sizeof(void *) + max_node_length); 4241 4242 size = sizeof(*device) + extra + bus_size + device_size; 4243 4244 device = calloc(1, size); 4245 if (!device) 4246 return NULL; 4247 4248 device->available_nodes = 1 << type; 4249 4250 ptr = (char *)device + sizeof(*device); 4251 device->nodes = (char **)ptr; 4252 4253 ptr += DRM_NODE_MAX * sizeof(void *); 4254 4255 for (i = 0; i < DRM_NODE_MAX; i++) { 4256 device->nodes[i] = ptr; 4257 ptr += max_node_length; 4258 } 4259 4260 memcpy(device->nodes[type], node, max_node_length); 4261 4262 *ptrp = ptr; 4263 4264 return device; 4265 } 4266 4267 static int drmProcessPciDevice(drmDevicePtr *device, 4268 const char *node, int node_type, 4269 int maj, int min, bool fetch_deviceinfo, 4270 uint32_t flags) 4271 { 4272 drmDevicePtr dev; 4273 char *addr; 4274 int ret; 4275 4276 dev = drmDeviceAlloc(node_type, node, sizeof(drmPciBusInfo), 4277 sizeof(drmPciDeviceInfo), &addr); 4278 if (!dev) 4279 return -ENOMEM; 4280 4281 dev->bustype = DRM_BUS_PCI; 4282 4283 dev->businfo.pci = (drmPciBusInfoPtr)addr; 4284 4285 ret = drmParsePciBusInfo(maj, min, dev->businfo.pci); 4286 if (ret) 4287 goto free_device; 4288 4289 // Fetch the device info if the user has requested it 4290 if (fetch_deviceinfo) { 4291 addr += sizeof(drmPciBusInfo); 4292 dev->deviceinfo.pci = (drmPciDeviceInfoPtr)addr; 4293 4294 ret = drmParsePciDeviceInfo(maj, min, dev->deviceinfo.pci, flags); 4295 if (ret) 4296 goto free_device; 4297 } 4298 4299 *device = dev; 4300 4301 return 0; 4302 4303 free_device: 4304 free(dev); 4305 return ret; 4306 } 4307 4308 #ifdef __linux__ 4309 static int drm_usb_dev_path(int maj, int min, char *path, size_t len) 4310 { 4311 char *value, *tmp_path, *slash; 4312 bool usb_device, usb_interface; 4313 4314 snprintf(path, len, "/sys/dev/char/%d:%d/device", maj, min); 4315 4316 value = sysfs_uevent_get(path, "DEVTYPE"); 4317 if (!value) 4318 return -ENOENT; 4319 4320 usb_device = strcmp(value, "usb_device") == 0; 4321 usb_interface = strcmp(value, "usb_interface") == 0; 4322 free(value); 4323 4324 if (usb_device) 4325 return 0; 4326 if (!usb_interface) 4327 return -ENOTSUP; 4328 4329 /* The parent of a usb_interface is a usb_device */ 4330 4331 tmp_path = realpath(path, NULL); 4332 if (!tmp_path) 4333 return -errno; 4334 4335 slash = strrchr(tmp_path, '/'); 4336 if (!slash) { 4337 free(tmp_path); 4338 return -EINVAL; 4339 } 4340 4341 *slash = '\0'; 4342 4343 if (snprintf(path, len, "%s", tmp_path) >= (int)len) { 4344 free(tmp_path); 4345 return -EINVAL; 4346 } 4347 4348 free(tmp_path); 4349 return 0; 4350 } 4351 #endif 4352 4353 static int drmParseUsbBusInfo(int maj, int min, drmUsbBusInfoPtr info) 4354 { 4355 #ifdef __linux__ 4356 char path[PATH_MAX + 1], *value; 4357 unsigned int bus, dev; 4358 int ret; 4359 4360 ret = drm_usb_dev_path(maj, min, path, sizeof(path)); 4361 if (ret < 0) 4362 return ret; 4363 4364 value = sysfs_uevent_get(path, "BUSNUM"); 4365 if (!value) 4366 return -ENOENT; 4367 4368 ret = sscanf(value, "%03u", &bus); 4369 free(value); 4370 4371 if (ret <= 0) 4372 return -errno; 4373 4374 value = sysfs_uevent_get(path, "DEVNUM"); 4375 if (!value) 4376 return -ENOENT; 4377 4378 ret = sscanf(value, "%03u", &dev); 4379 free(value); 4380 4381 if (ret <= 0) 4382 return -errno; 4383 4384 info->bus = bus; 4385 info->dev = dev; 4386 4387 return 0; 4388 #else 4389 #warning "Missing implementation of drmParseUsbBusInfo" 4390 return -EINVAL; 4391 #endif 4392 } 4393 4394 static int drmParseUsbDeviceInfo(int maj, int min, drmUsbDeviceInfoPtr info) 4395 { 4396 #ifdef __linux__ 4397 char path[PATH_MAX + 1], *value; 4398 unsigned int vendor, product; 4399 int ret; 4400 4401 ret = drm_usb_dev_path(maj, min, path, sizeof(path)); 4402 if (ret < 0) 4403 return ret; 4404 4405 value = sysfs_uevent_get(path, "PRODUCT"); 4406 if (!value) 4407 return -ENOENT; 4408 4409 ret = sscanf(value, "%x/%x", &vendor, &product); 4410 free(value); 4411 4412 if (ret <= 0) 4413 return -errno; 4414 4415 info->vendor = vendor; 4416 info->product = product; 4417 4418 return 0; 4419 #else 4420 #warning "Missing implementation of drmParseUsbDeviceInfo" 4421 return -EINVAL; 4422 #endif 4423 } 4424 4425 static int drmProcessUsbDevice(drmDevicePtr *device, const char *node, 4426 int node_type, int maj, int min, 4427 bool fetch_deviceinfo, uint32_t flags) 4428 { 4429 drmDevicePtr dev; 4430 char *ptr; 4431 int ret; 4432 4433 dev = drmDeviceAlloc(node_type, node, sizeof(drmUsbBusInfo), 4434 sizeof(drmUsbDeviceInfo), &ptr); 4435 if (!dev) 4436 return -ENOMEM; 4437 4438 dev->bustype = DRM_BUS_USB; 4439 4440 dev->businfo.usb = (drmUsbBusInfoPtr)ptr; 4441 4442 ret = drmParseUsbBusInfo(maj, min, dev->businfo.usb); 4443 if (ret < 0) 4444 goto free_device; 4445 4446 if (fetch_deviceinfo) { 4447 ptr += sizeof(drmUsbBusInfo); 4448 dev->deviceinfo.usb = (drmUsbDeviceInfoPtr)ptr; 4449 4450 ret = drmParseUsbDeviceInfo(maj, min, dev->deviceinfo.usb); 4451 if (ret < 0) 4452 goto free_device; 4453 } 4454 4455 *device = dev; 4456 4457 return 0; 4458 4459 free_device: 4460 free(dev); 4461 return ret; 4462 } 4463 4464 static int drmParseOFBusInfo(int maj, int min, char *fullname) 4465 { 4466 #ifdef __linux__ 4467 char path[PATH_MAX + 1], *name, *tmp_name; 4468 4469 snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min); 4470 4471 name = sysfs_uevent_get(path, "OF_FULLNAME"); 4472 tmp_name = name; 4473 if (!name) { 4474 /* If the device lacks OF data, pick the MODALIAS info */ 4475 name = sysfs_uevent_get(path, "MODALIAS"); 4476 if (!name) 4477 return -ENOENT; 4478 4479 /* .. and strip the MODALIAS=[platform,usb...]: part. */ 4480 tmp_name = strrchr(name, ':'); 4481 if (!tmp_name) { 4482 free(name); 4483 return -ENOENT; 4484 } 4485 tmp_name++; 4486 } 4487 4488 strncpy(fullname, tmp_name, DRM_PLATFORM_DEVICE_NAME_LEN); 4489 fullname[DRM_PLATFORM_DEVICE_NAME_LEN - 1] = '\0'; 4490 free(name); 4491 4492 return 0; 4493 #else 4494 #warning "Missing implementation of drmParseOFBusInfo" 4495 return -EINVAL; 4496 #endif 4497 } 4498 4499 static int drmParseOFDeviceInfo(int maj, int min, char ***compatible) 4500 { 4501 #ifdef __linux__ 4502 char path[PATH_MAX + 1], *value, *tmp_name; 4503 unsigned int count, i; 4504 int err; 4505 4506 snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min); 4507 4508 value = sysfs_uevent_get(path, "OF_COMPATIBLE_N"); 4509 if (value) { 4510 sscanf(value, "%u", &count); 4511 free(value); 4512 } else { 4513 /* Assume one entry if the device lack OF data */ 4514 count = 1; 4515 } 4516 4517 *compatible = calloc(count + 1, sizeof(char *)); 4518 if (!*compatible) 4519 return -ENOMEM; 4520 4521 for (i = 0; i < count; i++) { 4522 value = sysfs_uevent_get(path, "OF_COMPATIBLE_%u", i); 4523 tmp_name = value; 4524 if (!value) { 4525 /* If the device lacks OF data, pick the MODALIAS info */ 4526 value = sysfs_uevent_get(path, "MODALIAS"); 4527 if (!value) { 4528 err = -ENOENT; 4529 goto free; 4530 } 4531 4532 /* .. and strip the MODALIAS=[platform,usb...]: part. */ 4533 tmp_name = strrchr(value, ':'); 4534 if (!tmp_name) { 4535 free(value); 4536 return -ENOENT; 4537 } 4538 tmp_name = strdup(tmp_name + 1); 4539 free(value); 4540 } 4541 4542 (*compatible)[i] = tmp_name; 4543 } 4544 4545 return 0; 4546 4547 free: 4548 while (i--) 4549 free((*compatible)[i]); 4550 4551 free(*compatible); 4552 return err; 4553 #else 4554 #warning "Missing implementation of drmParseOFDeviceInfo" 4555 return -EINVAL; 4556 #endif 4557 } 4558 4559 static int drmProcessPlatformDevice(drmDevicePtr *device, 4560 const char *node, int node_type, 4561 int maj, int min, bool fetch_deviceinfo, 4562 uint32_t flags) 4563 { 4564 drmDevicePtr dev; 4565 char *ptr; 4566 int ret; 4567 4568 dev = drmDeviceAlloc(node_type, node, sizeof(drmPlatformBusInfo), 4569 sizeof(drmPlatformDeviceInfo), &ptr); 4570 if (!dev) 4571 return -ENOMEM; 4572 4573 dev->bustype = DRM_BUS_PLATFORM; 4574 4575 dev->businfo.platform = (drmPlatformBusInfoPtr)ptr; 4576 4577 ret = drmParseOFBusInfo(maj, min, dev->businfo.platform->fullname); 4578 if (ret < 0) 4579 goto free_device; 4580 4581 if (fetch_deviceinfo) { 4582 ptr += sizeof(drmPlatformBusInfo); 4583 dev->deviceinfo.platform = (drmPlatformDeviceInfoPtr)ptr; 4584 4585 ret = drmParseOFDeviceInfo(maj, min, &dev->deviceinfo.platform->compatible); 4586 if (ret < 0) 4587 goto free_device; 4588 } 4589 4590 *device = dev; 4591 4592 return 0; 4593 4594 free_device: 4595 free(dev); 4596 return ret; 4597 } 4598 4599 static int drmProcessHost1xDevice(drmDevicePtr *device, 4600 const char *node, int node_type, 4601 int maj, int min, bool fetch_deviceinfo, 4602 uint32_t flags) 4603 { 4604 drmDevicePtr dev; 4605 char *ptr; 4606 int ret; 4607 4608 dev = drmDeviceAlloc(node_type, node, sizeof(drmHost1xBusInfo), 4609 sizeof(drmHost1xDeviceInfo), &ptr); 4610 if (!dev) 4611 return -ENOMEM; 4612 4613 dev->bustype = DRM_BUS_HOST1X; 4614 4615 dev->businfo.host1x = (drmHost1xBusInfoPtr)ptr; 4616 4617 ret = drmParseOFBusInfo(maj, min, dev->businfo.host1x->fullname); 4618 if (ret < 0) 4619 goto free_device; 4620 4621 if (fetch_deviceinfo) { 4622 ptr += sizeof(drmHost1xBusInfo); 4623 dev->deviceinfo.host1x = (drmHost1xDeviceInfoPtr)ptr; 4624 4625 ret = drmParseOFDeviceInfo(maj, min, &dev->deviceinfo.host1x->compatible); 4626 if (ret < 0) 4627 goto free_device; 4628 } 4629 4630 *device = dev; 4631 4632 return 0; 4633 4634 free_device: 4635 free(dev); 4636 return ret; 4637 } 4638 4639 static int drmParseFauxBusInfo(int maj, int min, char *fullname) 4640 { 4641 #ifdef __linux__ 4642 char path[PATH_MAX + 1] = ""; 4643 char real_path[PATH_MAX + 1] = ""; 4644 char *name; 4645 4646 snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min); 4647 4648 if (!realpath(path, real_path)) 4649 return -errno; 4650 4651 name = basename(real_path); 4652 if (!name) 4653 return -ENOENT; 4654 4655 strncpy(fullname, name, DRM_FAUX_DEVICE_NAME_LEN - 1); 4656 fullname[DRM_FAUX_DEVICE_NAME_LEN - 1] = '\0'; 4657 4658 return 0; 4659 #else 4660 #warning "Missing implementation of drmParseFauxBusInfo" 4661 return -EINVAL; 4662 #endif 4663 } 4664 4665 static int drmProcessFauxDevice(drmDevicePtr *device, 4666 const char *node, int node_type, 4667 int maj, int min, bool fetch_deviceinfo, 4668 uint32_t flags) 4669 { 4670 drmDevicePtr dev; 4671 char *ptr; 4672 int ret; 4673 4674 dev = drmDeviceAlloc(node_type, node, sizeof(drmFauxBusInfo), 0, &ptr); 4675 if (!dev) 4676 return -ENOMEM; 4677 4678 dev->bustype = DRM_BUS_FAUX; 4679 4680 dev->businfo.faux = (drmFauxBusInfoPtr)ptr; 4681 4682 ret = drmParseFauxBusInfo(maj, min, dev->businfo.faux->name); 4683 if (ret < 0) 4684 goto free_device; 4685 4686 *device = dev; 4687 4688 return 0; 4689 4690 free_device: 4691 free(dev); 4692 return ret; 4693 } 4694 4695 static int 4696 process_device(drmDevicePtr *device, const char *d_name, 4697 int req_subsystem_type, 4698 bool fetch_deviceinfo, uint32_t flags) 4699 { 4700 struct stat sbuf; 4701 char node[PATH_MAX + 1]; 4702 int node_type, subsystem_type, written; 4703 unsigned int maj, min; 4704 const int max_node_length = ALIGN(drmGetMaxNodeName(), sizeof(void *)); 4705 4706 node_type = drmGetNodeType(d_name); 4707 if (node_type < 0) 4708 return -1; 4709 4710 written = snprintf(node, PATH_MAX, "%s/%s", DRM_DIR_NAME, d_name); 4711 if (written < 0) 4712 return -1; 4713 4714 /* anything longer than this will be truncated in drmDeviceAlloc. 4715 * Account for NULL byte 4716 */ 4717 if (written + 1 > max_node_length) 4718 return -1; 4719 4720 if (stat(node, &sbuf)) 4721 return -1; 4722 4723 maj = major(sbuf.st_rdev); 4724 min = minor(sbuf.st_rdev); 4725 4726 if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode)) 4727 return -1; 4728 4729 subsystem_type = drmParseSubsystemType(maj, min); 4730 if (req_subsystem_type != -1 && req_subsystem_type != subsystem_type) 4731 return -1; 4732 4733 switch (subsystem_type) { 4734 case DRM_BUS_PCI: 4735 case DRM_BUS_VIRTIO: 4736 return drmProcessPciDevice(device, node, node_type, maj, min, 4737 fetch_deviceinfo, flags); 4738 case DRM_BUS_USB: 4739 return drmProcessUsbDevice(device, node, node_type, maj, min, 4740 fetch_deviceinfo, flags); 4741 case DRM_BUS_PLATFORM: 4742 return drmProcessPlatformDevice(device, node, node_type, maj, min, 4743 fetch_deviceinfo, flags); 4744 case DRM_BUS_HOST1X: 4745 return drmProcessHost1xDevice(device, node, node_type, maj, min, 4746 fetch_deviceinfo, flags); 4747 case DRM_BUS_FAUX: 4748 return drmProcessFauxDevice(device, node, node_type, maj, min, 4749 fetch_deviceinfo, flags); 4750 default: 4751 return -1; 4752 } 4753 } 4754 4755 /* Consider devices located on the same bus as duplicate and fold the respective 4756 * entries into a single one. 4757 * 4758 * Note: this leaves "gaps" in the array, while preserving the length. 4759 */ 4760 static void drmFoldDuplicatedDevices(drmDevicePtr local_devices[], int count) 4761 { 4762 int node_type, i, j; 4763 4764 for (i = 0; i < count; i++) { 4765 for (j = i + 1; j < count; j++) { 4766 if (drmDevicesEqual(local_devices[i], local_devices[j])) { 4767 local_devices[i]->available_nodes |= local_devices[j]->available_nodes; 4768 node_type = log2_int(local_devices[j]->available_nodes); 4769 memcpy(local_devices[i]->nodes[node_type], 4770 local_devices[j]->nodes[node_type], drmGetMaxNodeName()); 4771 drmFreeDevice(&local_devices[j]); 4772 } 4773 } 4774 } 4775 } 4776 4777 /* Check that the given flags are valid returning 0 on success */ 4778 static int 4779 drm_device_validate_flags(uint32_t flags) 4780 { 4781 return (flags & ~DRM_DEVICE_GET_PCI_REVISION); 4782 } 4783 4784 static bool 4785 drm_device_has_rdev(drmDevicePtr device, dev_t find_rdev) 4786 { 4787 struct stat sbuf; 4788 4789 for (int i = 0; i < DRM_NODE_MAX; i++) { 4790 if (device->available_nodes & 1 << i) { 4791 if (stat(device->nodes[i], &sbuf) == 0 && 4792 sbuf.st_rdev == find_rdev) 4793 return true; 4794 } 4795 } 4796 return false; 4797 } 4798 4799 /* 4800 * The kernel drm core has a number of places that assume maximum of 4801 * 3x64 devices nodes. That's 64 for each of primary, control and 4802 * render nodes. Rounded it up to 256 for simplicity. 4803 */ 4804 #define MAX_DRM_NODES 256 4805 4806 /** 4807 * Get information about a device from its dev_t identifier 4808 * 4809 * \param find_rdev dev_t identifier of the device 4810 * \param flags feature/behaviour bitmask 4811 * \param device the address of a drmDevicePtr where the information 4812 * will be allocated in stored 4813 * 4814 * \return zero on success, negative error code otherwise. 4815 */ 4816 drm_public int drmGetDeviceFromDevId(dev_t find_rdev, uint32_t flags, drmDevicePtr *device) 4817 { 4818 #ifdef __OpenBSD__ 4819 /* 4820 * DRI device nodes on OpenBSD are not in their own directory, they reside 4821 * in /dev along with a large number of statically generated /dev nodes. 4822 * Avoid stat'ing all of /dev needlessly by implementing this custom path. 4823 */ 4824 drmDevicePtr d; 4825 char node[PATH_MAX + 1]; 4826 const char *dev_name; 4827 int node_type, subsystem_type; 4828 int maj, min, n, ret; 4829 const int max_node_length = ALIGN(drmGetMaxNodeName(), sizeof(void *)); 4830 struct stat sbuf; 4831 4832 if (device == NULL) 4833 return -EINVAL; 4834 4835 maj = major(find_rdev); 4836 min = minor(find_rdev); 4837 4838 if (!drmNodeIsDRM(maj, min)) 4839 return -EINVAL; 4840 4841 node_type = drmGetMinorType(maj, min); 4842 if (node_type == -1) 4843 return -ENODEV; 4844 4845 dev_name = drmGetDeviceName(node_type); 4846 if (!dev_name) 4847 return -EINVAL; 4848 4849 /* anything longer than this will be truncated in drmDeviceAlloc. 4850 * Account for NULL byte 4851 */ 4852 n = snprintf(node, PATH_MAX, dev_name, DRM_DIR_NAME, min); 4853 if (n == -1 || n >= PATH_MAX) 4854 return -errno; 4855 if (n + 1 > max_node_length) 4856 return -EINVAL; 4857 if (stat(node, &sbuf)) 4858 return -EINVAL; 4859 4860 subsystem_type = drmParseSubsystemType(maj, min); 4861 if (subsystem_type != DRM_BUS_PCI) 4862 return -ENODEV; 4863 4864 ret = drmProcessPciDevice(&d, node, node_type, maj, min, true, flags); 4865 if (ret) 4866 return ret; 4867 4868 *device = d; 4869 4870 return 0; 4871 #else 4872 drmDevicePtr local_devices[MAX_DRM_NODES]; 4873 drmDevicePtr d; 4874 DIR *sysdir; 4875 struct dirent *dent; 4876 int subsystem_type; 4877 int maj, min; 4878 int ret, i, node_count; 4879 4880 if (drm_device_validate_flags(flags)) 4881 return -EINVAL; 4882 4883 if (device == NULL) 4884 return -EINVAL; 4885 4886 maj = major(find_rdev); 4887 min = minor(find_rdev); 4888 4889 if (!drmNodeIsDRM(maj, min)) 4890 return -EINVAL; 4891 4892 subsystem_type = drmParseSubsystemType(maj, min); 4893 if (subsystem_type < 0) 4894 return subsystem_type; 4895 4896 sysdir = opendir(DRM_DIR_NAME); 4897 if (!sysdir) 4898 return -errno; 4899 4900 i = 0; 4901 while ((dent = readdir(sysdir))) { 4902 ret = process_device(&d, dent->d_name, subsystem_type, true, flags); 4903 if (ret) 4904 continue; 4905 4906 if (i >= MAX_DRM_NODES) { 4907 fprintf(stderr, "More than %d drm nodes detected. " 4908 "Please report a bug - that should not happen.\n" 4909 "Skipping extra nodes\n", MAX_DRM_NODES); 4910 break; 4911 } 4912 local_devices[i] = d; 4913 i++; 4914 } 4915 node_count = i; 4916 4917 drmFoldDuplicatedDevices(local_devices, node_count); 4918 4919 *device = NULL; 4920 4921 for (i = 0; i < node_count; i++) { 4922 if (!local_devices[i]) 4923 continue; 4924 4925 if (drm_device_has_rdev(local_devices[i], find_rdev)) 4926 *device = local_devices[i]; 4927 else 4928 drmFreeDevice(&local_devices[i]); 4929 } 4930 4931 closedir(sysdir); 4932 if (*device == NULL) 4933 return -ENODEV; 4934 return 0; 4935 #endif 4936 } 4937 4938 drm_public int drmGetNodeTypeFromDevId(dev_t devid) 4939 { 4940 int maj, min, node_type; 4941 4942 maj = major(devid); 4943 min = minor(devid); 4944 4945 if (!drmNodeIsDRM(maj, min)) 4946 return -EINVAL; 4947 4948 node_type = drmGetMinorType(maj, min); 4949 if (node_type == -1) 4950 return -ENODEV; 4951 4952 return node_type; 4953 } 4954 4955 /** 4956 * Get information about the opened drm device 4957 * 4958 * \param fd file descriptor of the drm device 4959 * \param flags feature/behaviour bitmask 4960 * \param device the address of a drmDevicePtr where the information 4961 * will be allocated in stored 4962 * 4963 * \return zero on success, negative error code otherwise. 4964 * 4965 * \note Unlike drmGetDevice it does not retrieve the pci device revision field 4966 * unless the DRM_DEVICE_GET_PCI_REVISION \p flag is set. 4967 */ 4968 drm_public int drmGetDevice2(int fd, uint32_t flags, drmDevicePtr *device) 4969 { 4970 struct stat sbuf; 4971 4972 if (fd == -1) 4973 return -EINVAL; 4974 4975 if (fstat(fd, &sbuf)) 4976 return -errno; 4977 4978 if (!S_ISCHR(sbuf.st_mode)) 4979 return -EINVAL; 4980 4981 return drmGetDeviceFromDevId(sbuf.st_rdev, flags, device); 4982 } 4983 4984 /** 4985 * Get information about the opened drm device 4986 * 4987 * \param fd file descriptor of the drm device 4988 * \param device the address of a drmDevicePtr where the information 4989 * will be allocated in stored 4990 * 4991 * \return zero on success, negative error code otherwise. 4992 */ 4993 drm_public int drmGetDevice(int fd, drmDevicePtr *device) 4994 { 4995 return drmGetDevice2(fd, DRM_DEVICE_GET_PCI_REVISION, device); 4996 } 4997 4998 /** 4999 * Get drm devices on the system 5000 * 5001 * \param flags feature/behaviour bitmask 5002 * \param devices the array of devices with drmDevicePtr elements 5003 * can be NULL to get the device number first 5004 * \param max_devices the maximum number of devices for the array 5005 * 5006 * \return on error - negative error code, 5007 * if devices is NULL - total number of devices available on the system, 5008 * alternatively the number of devices stored in devices[], which is 5009 * capped by the max_devices. 5010 * 5011 * \note Unlike drmGetDevices it does not retrieve the pci device revision field 5012 * unless the DRM_DEVICE_GET_PCI_REVISION \p flag is set. 5013 */ 5014 drm_public int drmGetDevices2(uint32_t flags, drmDevicePtr devices[], 5015 int max_devices) 5016 { 5017 drmDevicePtr local_devices[MAX_DRM_NODES]; 5018 drmDevicePtr device; 5019 DIR *sysdir; 5020 struct dirent *dent; 5021 int ret, i, node_count, device_count; 5022 5023 if (drm_device_validate_flags(flags)) 5024 return -EINVAL; 5025 5026 sysdir = opendir(DRM_DIR_NAME); 5027 if (!sysdir) 5028 return -errno; 5029 5030 i = 0; 5031 while ((dent = readdir(sysdir))) { 5032 ret = process_device(&device, dent->d_name, -1, devices != NULL, flags); 5033 if (ret) 5034 continue; 5035 5036 if (i >= MAX_DRM_NODES) { 5037 fprintf(stderr, "More than %d drm nodes detected. " 5038 "Please report a bug - that should not happen.\n" 5039 "Skipping extra nodes\n", MAX_DRM_NODES); 5040 break; 5041 } 5042 local_devices[i] = device; 5043 i++; 5044 } 5045 node_count = i; 5046 5047 drmFoldDuplicatedDevices(local_devices, node_count); 5048 5049 device_count = 0; 5050 for (i = 0; i < node_count; i++) { 5051 if (!local_devices[i]) 5052 continue; 5053 5054 if ((devices != NULL) && (device_count < max_devices)) 5055 devices[device_count] = local_devices[i]; 5056 else 5057 drmFreeDevice(&local_devices[i]); 5058 5059 device_count++; 5060 } 5061 5062 closedir(sysdir); 5063 5064 if (devices != NULL) 5065 return MIN2(device_count, max_devices); 5066 5067 return device_count; 5068 } 5069 5070 /** 5071 * Get drm devices on the system 5072 * 5073 * \param devices the array of devices with drmDevicePtr elements 5074 * can be NULL to get the device number first 5075 * \param max_devices the maximum number of devices for the array 5076 * 5077 * \return on error - negative error code, 5078 * if devices is NULL - total number of devices available on the system, 5079 * alternatively the number of devices stored in devices[], which is 5080 * capped by the max_devices. 5081 */ 5082 drm_public int drmGetDevices(drmDevicePtr devices[], int max_devices) 5083 { 5084 return drmGetDevices2(DRM_DEVICE_GET_PCI_REVISION, devices, max_devices); 5085 } 5086 5087 drm_public char *drmGetDeviceNameFromFd2(int fd) 5088 { 5089 #ifdef __linux__ 5090 struct stat sbuf; 5091 char path[PATH_MAX + 1], *value; 5092 unsigned int maj, min; 5093 5094 if (fstat(fd, &sbuf)) 5095 return NULL; 5096 5097 maj = major(sbuf.st_rdev); 5098 min = minor(sbuf.st_rdev); 5099 5100 if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode)) 5101 return NULL; 5102 5103 snprintf(path, sizeof(path), "/sys/dev/char/%d:%d", maj, min); 5104 5105 value = sysfs_uevent_get(path, "DEVNAME"); 5106 if (!value) 5107 return NULL; 5108 5109 snprintf(path, sizeof(path), "/dev/%s", value); 5110 free(value); 5111 5112 return strdup(path); 5113 #elif defined(__FreeBSD__) 5114 return drmGetDeviceNameFromFd(fd); 5115 #else 5116 struct stat sbuf; 5117 char node[PATH_MAX + 1]; 5118 const char *dev_name; 5119 int node_type; 5120 int maj, min, n; 5121 5122 if (fstat(fd, &sbuf)) 5123 return NULL; 5124 5125 maj = major(sbuf.st_rdev); 5126 min = minor(sbuf.st_rdev); 5127 5128 if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode)) 5129 return NULL; 5130 5131 node_type = drmGetMinorType(maj, min); 5132 if (node_type == -1) 5133 return NULL; 5134 5135 dev_name = drmGetDeviceName(node_type); 5136 if (!dev_name) 5137 return NULL; 5138 5139 n = snprintf(node, PATH_MAX, dev_name, DRM_DIR_NAME, min); 5140 if (n == -1 || n >= PATH_MAX) 5141 return NULL; 5142 5143 return strdup(node); 5144 #endif 5145 } 5146 5147 drm_public int drmSyncobjCreate(int fd, uint32_t flags, uint32_t *handle) 5148 { 5149 struct drm_syncobj_create args; 5150 int ret; 5151 5152 memclear(args); 5153 args.flags = flags; 5154 args.handle = 0; 5155 ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_CREATE, &args); 5156 if (ret) 5157 return ret; 5158 *handle = args.handle; 5159 return 0; 5160 } 5161 5162 drm_public int drmSyncobjDestroy(int fd, uint32_t handle) 5163 { 5164 struct drm_syncobj_destroy args; 5165 5166 memclear(args); 5167 args.handle = handle; 5168 return drmIoctl(fd, DRM_IOCTL_SYNCOBJ_DESTROY, &args); 5169 } 5170 5171 drm_public int drmSyncobjHandleToFD(int fd, uint32_t handle, int *obj_fd) 5172 { 5173 struct drm_syncobj_handle args; 5174 int ret; 5175 5176 memclear(args); 5177 args.fd = -1; 5178 args.handle = handle; 5179 ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD, &args); 5180 if (ret) 5181 return ret; 5182 *obj_fd = args.fd; 5183 return 0; 5184 } 5185 5186 drm_public int drmSyncobjFDToHandle(int fd, int obj_fd, uint32_t *handle) 5187 { 5188 struct drm_syncobj_handle args; 5189 int ret; 5190 5191 memclear(args); 5192 args.fd = obj_fd; 5193 args.handle = 0; 5194 ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, &args); 5195 if (ret) 5196 return ret; 5197 *handle = args.handle; 5198 return 0; 5199 } 5200 5201 drm_public int drmSyncobjImportSyncFile(int fd, uint32_t handle, 5202 int sync_file_fd) 5203 { 5204 struct drm_syncobj_handle args; 5205 5206 memclear(args); 5207 args.fd = sync_file_fd; 5208 args.handle = handle; 5209 args.flags = DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE; 5210 return drmIoctl(fd, DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, &args); 5211 } 5212 5213 drm_public int drmSyncobjExportSyncFile(int fd, uint32_t handle, 5214 int *sync_file_fd) 5215 { 5216 struct drm_syncobj_handle args; 5217 int ret; 5218 5219 memclear(args); 5220 args.fd = -1; 5221 args.handle = handle; 5222 args.flags = DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE; 5223 ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD, &args); 5224 if (ret) 5225 return ret; 5226 *sync_file_fd = args.fd; 5227 return 0; 5228 } 5229 5230 drm_public int drmSyncobjWait(int fd, uint32_t *handles, unsigned num_handles, 5231 int64_t timeout_nsec, unsigned flags, 5232 uint32_t *first_signaled) 5233 { 5234 struct drm_syncobj_wait args; 5235 int ret; 5236 5237 memclear(args); 5238 args.handles = (uintptr_t)handles; 5239 args.timeout_nsec = timeout_nsec; 5240 args.count_handles = num_handles; 5241 args.flags = flags; 5242 5243 ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_WAIT, &args); 5244 if (ret < 0) 5245 return -errno; 5246 5247 if (first_signaled) 5248 *first_signaled = args.first_signaled; 5249 return ret; 5250 } 5251 5252 drm_public int drmSyncobjReset(int fd, const uint32_t *handles, 5253 uint32_t handle_count) 5254 { 5255 struct drm_syncobj_array args; 5256 int ret; 5257 5258 memclear(args); 5259 args.handles = (uintptr_t)handles; 5260 args.count_handles = handle_count; 5261 5262 ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_RESET, &args); 5263 return ret; 5264 } 5265 5266 drm_public int drmSyncobjSignal(int fd, const uint32_t *handles, 5267 uint32_t handle_count) 5268 { 5269 struct drm_syncobj_array args; 5270 int ret; 5271 5272 memclear(args); 5273 args.handles = (uintptr_t)handles; 5274 args.count_handles = handle_count; 5275 5276 ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_SIGNAL, &args); 5277 return ret; 5278 } 5279 5280 drm_public int drmSyncobjTimelineSignal(int fd, const uint32_t *handles, 5281 uint64_t *points, uint32_t handle_count) 5282 { 5283 struct drm_syncobj_timeline_array args; 5284 int ret; 5285 5286 memclear(args); 5287 args.handles = (uintptr_t)handles; 5288 args.points = (uintptr_t)points; 5289 args.count_handles = handle_count; 5290 5291 ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL, &args); 5292 return ret; 5293 } 5294 5295 drm_public int drmSyncobjTimelineWait(int fd, uint32_t *handles, uint64_t *points, 5296 unsigned num_handles, 5297 int64_t timeout_nsec, unsigned flags, 5298 uint32_t *first_signaled) 5299 { 5300 struct drm_syncobj_timeline_wait args; 5301 int ret; 5302 5303 memclear(args); 5304 args.handles = (uintptr_t)handles; 5305 args.points = (uintptr_t)points; 5306 args.timeout_nsec = timeout_nsec; 5307 args.count_handles = num_handles; 5308 args.flags = flags; 5309 5310 ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT, &args); 5311 if (ret < 0) 5312 return -errno; 5313 5314 if (first_signaled) 5315 *first_signaled = args.first_signaled; 5316 return ret; 5317 } 5318 5319 5320 drm_public int drmSyncobjQuery(int fd, uint32_t *handles, uint64_t *points, 5321 uint32_t handle_count) 5322 { 5323 struct drm_syncobj_timeline_array args; 5324 int ret; 5325 5326 memclear(args); 5327 args.handles = (uintptr_t)handles; 5328 args.points = (uintptr_t)points; 5329 args.count_handles = handle_count; 5330 5331 ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_QUERY, &args); 5332 if (ret) 5333 return ret; 5334 return 0; 5335 } 5336 5337 drm_public int drmSyncobjQuery2(int fd, uint32_t *handles, uint64_t *points, 5338 uint32_t handle_count, uint32_t flags) 5339 { 5340 struct drm_syncobj_timeline_array args; 5341 5342 memclear(args); 5343 args.handles = (uintptr_t)handles; 5344 args.points = (uintptr_t)points; 5345 args.count_handles = handle_count; 5346 args.flags = flags; 5347 5348 return drmIoctl(fd, DRM_IOCTL_SYNCOBJ_QUERY, &args); 5349 } 5350 5351 5352 drm_public int drmSyncobjTransfer(int fd, 5353 uint32_t dst_handle, uint64_t dst_point, 5354 uint32_t src_handle, uint64_t src_point, 5355 uint32_t flags) 5356 { 5357 struct drm_syncobj_transfer args; 5358 int ret; 5359 5360 memclear(args); 5361 args.src_handle = src_handle; 5362 args.dst_handle = dst_handle; 5363 args.src_point = src_point; 5364 args.dst_point = dst_point; 5365 args.flags = flags; 5366 5367 ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_TRANSFER, &args); 5368 5369 return ret; 5370 } 5371 5372 drm_public int drmSyncobjEventfd(int fd, uint32_t handle, uint64_t point, int ev_fd, 5373 uint32_t flags) 5374 { 5375 struct drm_syncobj_eventfd args; 5376 5377 memclear(args); 5378 args.handle = handle; 5379 args.point = point; 5380 args.fd = ev_fd; 5381 args.flags = flags; 5382 5383 return drmIoctl(fd, DRM_IOCTL_SYNCOBJ_EVENTFD, &args); 5384 } 5385 5386 static char * 5387 drmGetFormatModifierFromSimpleTokens(uint64_t modifier) 5388 { 5389 unsigned int i; 5390 5391 for (i = 0; i < ARRAY_SIZE(drm_format_modifier_table); i++) { 5392 if (drm_format_modifier_table[i].modifier == modifier) 5393 return strdup(drm_format_modifier_table[i].modifier_name); 5394 } 5395 5396 return NULL; 5397 } 5398 5399 /** Retrieves a human-readable representation of a vendor (as a string) from 5400 * the format token modifier 5401 * 5402 * \param modifier the format modifier token 5403 * \return a char pointer to the human-readable form of the vendor. Caller is 5404 * responsible for freeing it. 5405 */ 5406 drm_public char * 5407 drmGetFormatModifierVendor(uint64_t modifier) 5408 { 5409 unsigned int i; 5410 uint8_t vendor = fourcc_mod_get_vendor(modifier); 5411 5412 for (i = 0; i < ARRAY_SIZE(drm_format_modifier_vendor_table); i++) { 5413 if (drm_format_modifier_vendor_table[i].vendor == vendor) 5414 return strdup(drm_format_modifier_vendor_table[i].vendor_name); 5415 } 5416 5417 return NULL; 5418 } 5419 5420 /** Retrieves a human-readable representation string from a format token 5421 * modifier 5422 * 5423 * If the dedicated function was not able to extract a valid name or searching 5424 * the format modifier was not in the table, this function would return NULL. 5425 * 5426 * \param modifier the token format 5427 * \return a malloc'ed string representation of the modifier. Caller is 5428 * responsible for freeing the string returned. 5429 * 5430 */ 5431 drm_public char * 5432 drmGetFormatModifierName(uint64_t modifier) 5433 { 5434 uint8_t vendorid = fourcc_mod_get_vendor(modifier); 5435 char *modifier_found = NULL; 5436 unsigned int i; 5437 5438 for (i = 0; i < ARRAY_SIZE(modifier_format_vendor_table); i++) { 5439 if (modifier_format_vendor_table[i].vendor == vendorid) 5440 modifier_found = modifier_format_vendor_table[i].vendor_cb(modifier); 5441 } 5442 5443 if (!modifier_found) 5444 return drmGetFormatModifierFromSimpleTokens(modifier); 5445 5446 return modifier_found; 5447 } 5448 5449 /** 5450 * Get a human-readable name for a DRM FourCC format. 5451 * 5452 * \param format The format. 5453 * \return A malloc'ed string containing the format name. Caller is responsible 5454 * for freeing it. 5455 */ 5456 drm_public char * 5457 drmGetFormatName(uint32_t format) 5458 { 5459 char *str, code[5]; 5460 const char *be; 5461 size_t str_size, i; 5462 5463 be = (format & DRM_FORMAT_BIG_ENDIAN) ? "_BE" : ""; 5464 format &= ~DRM_FORMAT_BIG_ENDIAN; 5465 5466 if (format == DRM_FORMAT_INVALID) 5467 return strdup("INVALID"); 5468 5469 code[0] = (char) ((format >> 0) & 0xFF); 5470 code[1] = (char) ((format >> 8) & 0xFF); 5471 code[2] = (char) ((format >> 16) & 0xFF); 5472 code[3] = (char) ((format >> 24) & 0xFF); 5473 code[4] = '\0'; 5474 5475 /* Trim spaces at the end */ 5476 for (i = 3; i > 0 && code[i] == ' '; i--) 5477 code[i] = '\0'; 5478 5479 str_size = strlen(code) + strlen(be) + 1; 5480 str = malloc(str_size); 5481 if (!str) 5482 return NULL; 5483 5484 snprintf(str, str_size, "%s%s", code, be); 5485 5486 return str; 5487 } 5488