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