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