1 /** 2 * \file xf86drm.c 3 * User-level interface to DRM device 4 * 5 * \author Rickard E. (Rik) Faith <faith (at) valinux.com> 6 * \author Kevin E. Martin <martin (at) valinux.com> 7 */ 8 9 /* 10 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. 11 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 12 * All Rights Reserved. 13 * 14 * Permission is hereby granted, free of charge, to any person obtaining a 15 * copy of this software and associated documentation files (the "Software"), 16 * to deal in the Software without restriction, including without limitation 17 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 18 * and/or sell copies of the Software, and to permit persons to whom the 19 * Software is furnished to do so, subject to the following conditions: 20 * 21 * The above copyright notice and this permission notice (including the next 22 * paragraph) shall be included in all copies or substantial portions of the 23 * Software. 24 * 25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 28 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 29 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 30 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 31 * DEALINGS IN THE SOFTWARE. 32 */ 33 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <stdbool.h> 37 #include <unistd.h> 38 #include <string.h> 39 #include <strings.h> 40 #include <ctype.h> 41 #include <dirent.h> 42 #include <stddef.h> 43 #include <fcntl.h> 44 #include <errno.h> 45 #include <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 #include <math.h> 61 62 /* Not all systems have MAP_FAILED defined */ 63 #ifndef MAP_FAILED 64 #define MAP_FAILED ((void *)-1) 65 #endif 66 67 #include "xf86drm.h" 68 #include "libdrm_macros.h" 69 70 #include "util_math.h" 71 72 #ifdef __OpenBSD__ 73 #define DRM_PRIMARY_MINOR_NAME "drm" 74 #define DRM_CONTROL_MINOR_NAME "drmC" 75 #define DRM_RENDER_MINOR_NAME "drmR" 76 #else 77 #define DRM_PRIMARY_MINOR_NAME "card" 78 #define DRM_CONTROL_MINOR_NAME "controlD" 79 #define DRM_RENDER_MINOR_NAME "renderD" 80 #endif 81 82 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) 83 #define DRM_MAJOR 145 84 #endif 85 86 #ifdef __NetBSD__ 87 #define DRM_MAJOR 34 88 #endif 89 90 #ifdef __OpenBSD__ 91 #ifdef __i386__ 92 #define DRM_MAJOR 88 93 #else 94 #define DRM_MAJOR 87 95 #endif 96 #endif /* __OpenBSD__ */ 97 98 #ifndef DRM_MAJOR 99 #define DRM_MAJOR 226 /* Linux */ 100 #endif 101 102 #ifdef __OpenBSD__ 103 struct drm_pciinfo { 104 uint16_t domain; 105 uint8_t bus; 106 uint8_t dev; 107 uint8_t func; 108 uint16_t vendor_id; 109 uint16_t device_id; 110 uint16_t subvendor_id; 111 uint16_t subdevice_id; 112 uint8_t revision_id; 113 }; 114 115 #define DRM_IOCTL_GET_PCIINFO DRM_IOR(0x15, struct drm_pciinfo) 116 #endif 117 118 #define DRM_MSG_VERBOSITY 3 119 120 #define memclear(s) memset(&s, 0, sizeof(s)) 121 122 static drmServerInfoPtr drm_server_info; 123 124 void drmSetServerInfo(drmServerInfoPtr info) 125 { 126 drm_server_info = info; 127 } 128 129 /** 130 * Output a message to stderr. 131 * 132 * \param format printf() like format string. 133 * 134 * \internal 135 * This function is a wrapper around vfprintf(). 136 */ 137 138 static int DRM_PRINTFLIKE(1, 0) 139 drmDebugPrint(const char *format, va_list ap) 140 { 141 return vfprintf(stderr, format, ap); 142 } 143 144 void 145 drmMsg(const char *format, ...) 146 { 147 va_list ap; 148 const char *env; 149 if (((env = getenv("LIBGL_DEBUG")) && strstr(env, "verbose")) || 150 (drm_server_info && drm_server_info->debug_print)) 151 { 152 va_start(ap, format); 153 if (drm_server_info) { 154 drm_server_info->debug_print(format,ap); 155 } else { 156 drmDebugPrint(format, ap); 157 } 158 va_end(ap); 159 } 160 } 161 162 static void *drmHashTable = NULL; /* Context switch callbacks */ 163 164 void *drmGetHashTable(void) 165 { 166 return drmHashTable; 167 } 168 169 void *drmMalloc(int size) 170 { 171 return calloc(1, size); 172 } 173 174 void drmFree(void *pt) 175 { 176 free(pt); 177 } 178 179 /** 180 * Call ioctl, restarting if it is interupted 181 */ 182 int 183 drmIoctl(int fd, unsigned long request, void *arg) 184 { 185 int ret; 186 187 do { 188 ret = ioctl(fd, request, arg); 189 } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); 190 return ret; 191 } 192 193 static unsigned long drmGetKeyFromFd(int fd) 194 { 195 stat_t st; 196 197 st.st_rdev = 0; 198 fstat(fd, &st); 199 return st.st_rdev; 200 } 201 202 drmHashEntry *drmGetEntry(int fd) 203 { 204 unsigned long key = drmGetKeyFromFd(fd); 205 void *value; 206 drmHashEntry *entry; 207 208 if (!drmHashTable) 209 drmHashTable = drmHashCreate(); 210 211 if (drmHashLookup(drmHashTable, key, &value)) { 212 entry = drmMalloc(sizeof(*entry)); 213 entry->fd = fd; 214 entry->f = NULL; 215 entry->tagTable = drmHashCreate(); 216 drmHashInsert(drmHashTable, key, entry); 217 } else { 218 entry = value; 219 } 220 return entry; 221 } 222 223 /** 224 * Compare two busid strings 225 * 226 * \param first 227 * \param second 228 * 229 * \return 1 if matched. 230 * 231 * \internal 232 * This function compares two bus ID strings. It understands the older 233 * PCI:b:d:f format and the newer pci:oooo:bb:dd.f format. In the format, o is 234 * domain, b is bus, d is device, f is function. 235 */ 236 static int drmMatchBusID(const char *id1, const char *id2, int pci_domain_ok) 237 { 238 /* First, check if the IDs are exactly the same */ 239 if (strcasecmp(id1, id2) == 0) 240 return 1; 241 242 /* Try to match old/new-style PCI bus IDs. */ 243 if (strncasecmp(id1, "pci", 3) == 0) { 244 unsigned int o1, b1, d1, f1; 245 unsigned int o2, b2, d2, f2; 246 int ret; 247 248 ret = sscanf(id1, "pci:%04x:%02x:%02x.%u", &o1, &b1, &d1, &f1); 249 if (ret != 4) { 250 o1 = 0; 251 ret = sscanf(id1, "PCI:%u:%u:%u", &b1, &d1, &f1); 252 if (ret != 3) 253 return 0; 254 } 255 256 ret = sscanf(id2, "pci:%04x:%02x:%02x.%u", &o2, &b2, &d2, &f2); 257 if (ret != 4) { 258 o2 = 0; 259 ret = sscanf(id2, "PCI:%u:%u:%u", &b2, &d2, &f2); 260 if (ret != 3) 261 return 0; 262 } 263 264 /* If domains aren't properly supported by the kernel interface, 265 * just ignore them, which sucks less than picking a totally random 266 * card with "open by name" 267 */ 268 if (!pci_domain_ok) 269 o1 = o2 = 0; 270 271 if ((o1 != o2) || (b1 != b2) || (d1 != d2) || (f1 != f2)) 272 return 0; 273 else 274 return 1; 275 } 276 return 0; 277 } 278 279 /** 280 * Handles error checking for chown call. 281 * 282 * \param path to file. 283 * \param id of the new owner. 284 * \param id of the new group. 285 * 286 * \return zero if success or -1 if failure. 287 * 288 * \internal 289 * Checks for failure. If failure was caused by signal call chown again. 290 * If any other failure happened then it will output error mesage using 291 * drmMsg() call. 292 */ 293 #if !UDEV 294 static int chown_check_return(const char *path, uid_t owner, gid_t group) 295 { 296 int rv; 297 298 do { 299 rv = chown(path, owner, group); 300 } while (rv != 0 && errno == EINTR); 301 302 if (rv == 0) 303 return 0; 304 305 drmMsg("Failed to change owner or group for file %s! %d: %s\n", 306 path, errno, strerror(errno)); 307 return -1; 308 } 309 #endif 310 311 /** 312 * Open the DRM device, creating it if necessary. 313 * 314 * \param dev major and minor numbers of the device. 315 * \param minor minor number of the device. 316 * 317 * \return a file descriptor on success, or a negative value on error. 318 * 319 * \internal 320 * Assembles the device name from \p minor and opens it, creating the device 321 * special file node with the major and minor numbers specified by \p dev and 322 * parent directory if necessary and was called by root. 323 */ 324 static int drmOpenDevice(dev_t dev, int minor, int type) 325 { 326 stat_t st; 327 const char *dev_name; 328 char buf[64]; 329 int fd; 330 mode_t devmode = DRM_DEV_MODE, serv_mode; 331 gid_t serv_group; 332 #if !UDEV 333 int isroot = !geteuid(); 334 uid_t user = DRM_DEV_UID; 335 gid_t group = DRM_DEV_GID; 336 #endif 337 338 switch (type) { 339 case DRM_NODE_PRIMARY: 340 dev_name = DRM_DEV_NAME; 341 break; 342 case DRM_NODE_CONTROL: 343 dev_name = DRM_CONTROL_DEV_NAME; 344 break; 345 case DRM_NODE_RENDER: 346 dev_name = DRM_RENDER_DEV_NAME; 347 break; 348 default: 349 return -EINVAL; 350 }; 351 352 sprintf(buf, dev_name, DRM_DIR_NAME, minor); 353 drmMsg("drmOpenDevice: node name is %s\n", buf); 354 355 if (drm_server_info && drm_server_info->get_perms) { 356 drm_server_info->get_perms(&serv_group, &serv_mode); 357 devmode = serv_mode ? serv_mode : DRM_DEV_MODE; 358 devmode &= ~(S_IXUSR|S_IXGRP|S_IXOTH); 359 } 360 361 #if !UDEV 362 if (stat(DRM_DIR_NAME, &st)) { 363 if (!isroot) 364 return DRM_ERR_NOT_ROOT; 365 mkdir(DRM_DIR_NAME, DRM_DEV_DIRMODE); 366 chown_check_return(DRM_DIR_NAME, 0, 0); /* root:root */ 367 chmod(DRM_DIR_NAME, DRM_DEV_DIRMODE); 368 } 369 370 /* Check if the device node exists and create it if necessary. */ 371 if (stat(buf, &st)) { 372 if (!isroot) 373 return DRM_ERR_NOT_ROOT; 374 remove(buf); 375 mknod(buf, S_IFCHR | devmode, dev); 376 } 377 378 if (drm_server_info && drm_server_info->get_perms) { 379 group = ((int)serv_group >= 0) ? serv_group : DRM_DEV_GID; 380 chown_check_return(buf, user, group); 381 chmod(buf, devmode); 382 } 383 #else 384 /* if we modprobed then wait for udev */ 385 { 386 int udev_count = 0; 387 wait_for_udev: 388 if (stat(DRM_DIR_NAME, &st)) { 389 usleep(20); 390 udev_count++; 391 392 if (udev_count == 50) 393 return -1; 394 goto wait_for_udev; 395 } 396 397 if (stat(buf, &st)) { 398 usleep(20); 399 udev_count++; 400 401 if (udev_count == 50) 402 return -1; 403 goto wait_for_udev; 404 } 405 } 406 #endif 407 408 fd = open(buf, O_RDWR, 0); 409 drmMsg("drmOpenDevice: open result is %d, (%s)\n", 410 fd, fd < 0 ? strerror(errno) : "OK"); 411 if (fd >= 0) 412 return fd; 413 414 #if !UDEV 415 /* Check if the device node is not what we expect it to be, and recreate it 416 * and try again if so. 417 */ 418 if (st.st_rdev != dev) { 419 if (!isroot) 420 return DRM_ERR_NOT_ROOT; 421 remove(buf); 422 mknod(buf, S_IFCHR | devmode, dev); 423 if (drm_server_info && drm_server_info->get_perms) { 424 chown_check_return(buf, user, group); 425 chmod(buf, devmode); 426 } 427 } 428 fd = open(buf, O_RDWR, 0); 429 drmMsg("drmOpenDevice: open result is %d, (%s)\n", 430 fd, fd < 0 ? strerror(errno) : "OK"); 431 if (fd >= 0) 432 return fd; 433 434 drmMsg("drmOpenDevice: Open failed\n"); 435 remove(buf); 436 #endif 437 return -errno; 438 } 439 440 441 /** 442 * Open the DRM device 443 * 444 * \param minor device minor number. 445 * \param create allow to create the device if set. 446 * 447 * \return a file descriptor on success, or a negative value on error. 448 * 449 * \internal 450 * Calls drmOpenDevice() if \p create is set, otherwise assembles the device 451 * name from \p minor and opens it. 452 */ 453 static int drmOpenMinor(int minor, int create, int type) 454 { 455 int fd; 456 char buf[64]; 457 const char *dev_name; 458 459 if (create) 460 return drmOpenDevice(makedev(DRM_MAJOR, minor), minor, type); 461 462 switch (type) { 463 case DRM_NODE_PRIMARY: 464 dev_name = DRM_DEV_NAME; 465 break; 466 case DRM_NODE_CONTROL: 467 dev_name = DRM_CONTROL_DEV_NAME; 468 break; 469 case DRM_NODE_RENDER: 470 dev_name = DRM_RENDER_DEV_NAME; 471 break; 472 default: 473 return -EINVAL; 474 }; 475 476 sprintf(buf, dev_name, DRM_DIR_NAME, minor); 477 if ((fd = open(buf, O_RDWR, 0)) >= 0) 478 return fd; 479 return -errno; 480 } 481 482 483 /** 484 * Determine whether the DRM kernel driver has been loaded. 485 * 486 * \return 1 if the DRM driver is loaded, 0 otherwise. 487 * 488 * \internal 489 * Determine the presence of the kernel driver by attempting to open the 0 490 * minor and get version information. For backward compatibility with older 491 * Linux implementations, /proc/dri is also checked. 492 */ 493 int drmAvailable(void) 494 { 495 drmVersionPtr version; 496 int retval = 0; 497 int fd; 498 499 if ((fd = drmOpenMinor(0, 1, DRM_NODE_PRIMARY)) < 0) { 500 #ifdef __linux__ 501 /* Try proc for backward Linux compatibility */ 502 if (!access("/proc/dri/0", R_OK)) 503 return 1; 504 #endif 505 return 0; 506 } 507 508 if ((version = drmGetVersion(fd))) { 509 retval = 1; 510 drmFreeVersion(version); 511 } 512 close(fd); 513 514 return retval; 515 } 516 517 static int drmGetMinorBase(int type) 518 { 519 switch (type) { 520 case DRM_NODE_PRIMARY: 521 return 0; 522 case DRM_NODE_CONTROL: 523 return 64; 524 case DRM_NODE_RENDER: 525 return 128; 526 default: 527 return -1; 528 }; 529 } 530 531 static int drmGetMinorType(int minor) 532 { 533 int type = minor >> 6; 534 535 if (minor < 0) 536 return -1; 537 538 switch (type) { 539 case DRM_NODE_PRIMARY: 540 case DRM_NODE_CONTROL: 541 case DRM_NODE_RENDER: 542 return type; 543 default: 544 return -1; 545 } 546 } 547 548 static const char *drmGetMinorName(int type) 549 { 550 switch (type) { 551 case DRM_NODE_PRIMARY: 552 return DRM_PRIMARY_MINOR_NAME; 553 case DRM_NODE_CONTROL: 554 return DRM_CONTROL_MINOR_NAME; 555 case DRM_NODE_RENDER: 556 return DRM_RENDER_MINOR_NAME; 557 default: 558 return NULL; 559 } 560 } 561 562 /** 563 * Open the device by bus ID. 564 * 565 * \param busid bus ID. 566 * \param type device node type. 567 * 568 * \return a file descriptor on success, or a negative value on error. 569 * 570 * \internal 571 * This function attempts to open every possible minor (up to DRM_MAX_MINOR), 572 * comparing the device bus ID with the one supplied. 573 * 574 * \sa drmOpenMinor() and drmGetBusid(). 575 */ 576 static int drmOpenByBusid(const char *busid, int type) 577 { 578 int i, pci_domain_ok = 1; 579 int fd; 580 const char *buf; 581 drmSetVersion sv; 582 int base = drmGetMinorBase(type); 583 584 if (base < 0) 585 return -1; 586 587 drmMsg("drmOpenByBusid: Searching for BusID %s\n", busid); 588 for (i = base; i < base + DRM_MAX_MINOR; i++) { 589 fd = drmOpenMinor(i, 1, type); 590 drmMsg("drmOpenByBusid: drmOpenMinor returns %d\n", fd); 591 if (fd >= 0) { 592 /* We need to try for 1.4 first for proper PCI domain support 593 * and if that fails, we know the kernel is busted 594 */ 595 sv.drm_di_major = 1; 596 sv.drm_di_minor = 4; 597 sv.drm_dd_major = -1; /* Don't care */ 598 sv.drm_dd_minor = -1; /* Don't care */ 599 if (drmSetInterfaceVersion(fd, &sv)) { 600 #ifndef __alpha__ 601 pci_domain_ok = 0; 602 #endif 603 sv.drm_di_major = 1; 604 sv.drm_di_minor = 1; 605 sv.drm_dd_major = -1; /* Don't care */ 606 sv.drm_dd_minor = -1; /* Don't care */ 607 drmMsg("drmOpenByBusid: Interface 1.4 failed, trying 1.1\n"); 608 drmSetInterfaceVersion(fd, &sv); 609 } 610 buf = drmGetBusid(fd); 611 drmMsg("drmOpenByBusid: drmGetBusid reports %s\n", buf); 612 if (buf && drmMatchBusID(buf, busid, pci_domain_ok)) { 613 drmFreeBusid(buf); 614 return fd; 615 } 616 if (buf) 617 drmFreeBusid(buf); 618 close(fd); 619 } 620 } 621 return -1; 622 } 623 624 625 /** 626 * Open the device by name. 627 * 628 * \param name driver name. 629 * \param type the device node type. 630 * 631 * \return a file descriptor on success, or a negative value on error. 632 * 633 * \internal 634 * This function opens the first minor number that matches the driver name and 635 * isn't already in use. If it's in use it then it will already have a bus ID 636 * assigned. 637 * 638 * \sa drmOpenMinor(), drmGetVersion() and drmGetBusid(). 639 */ 640 static int drmOpenByName(const char *name, int type) 641 { 642 int i; 643 int fd; 644 drmVersionPtr version; 645 char * id; 646 int base = drmGetMinorBase(type); 647 648 if (base < 0) 649 return -1; 650 651 /* 652 * Open the first minor number that matches the driver name and isn't 653 * already in use. If it's in use it will have a busid assigned already. 654 */ 655 for (i = base; i < base + DRM_MAX_MINOR; i++) { 656 if ((fd = drmOpenMinor(i, 1, type)) >= 0) { 657 if ((version = drmGetVersion(fd))) { 658 if (!strcmp(version->name, name)) { 659 drmFreeVersion(version); 660 id = drmGetBusid(fd); 661 drmMsg("drmGetBusid returned '%s'\n", id ? id : "NULL"); 662 if (!id || !*id) { 663 if (id) 664 drmFreeBusid(id); 665 return fd; 666 } else { 667 drmFreeBusid(id); 668 } 669 } else { 670 drmFreeVersion(version); 671 } 672 } 673 close(fd); 674 } 675 } 676 677 #ifdef __linux__ 678 /* Backward-compatibility /proc support */ 679 for (i = 0; i < 8; i++) { 680 char proc_name[64], buf[512]; 681 char *driver, *pt, *devstring; 682 int retcode; 683 684 sprintf(proc_name, "/proc/dri/%d/name", i); 685 if ((fd = open(proc_name, 0, 0)) >= 0) { 686 retcode = read(fd, buf, sizeof(buf)-1); 687 close(fd); 688 if (retcode) { 689 buf[retcode-1] = '\0'; 690 for (driver = pt = buf; *pt && *pt != ' '; ++pt) 691 ; 692 if (*pt) { /* Device is next */ 693 *pt = '\0'; 694 if (!strcmp(driver, name)) { /* Match */ 695 for (devstring = ++pt; *pt && *pt != ' '; ++pt) 696 ; 697 if (*pt) { /* Found busid */ 698 return drmOpenByBusid(++pt, type); 699 } else { /* No busid */ 700 return drmOpenDevice(strtol(devstring, NULL, 0),i, type); 701 } 702 } 703 } 704 } 705 } 706 } 707 #endif 708 709 return -1; 710 } 711 712 713 /** 714 * Open the DRM device. 715 * 716 * Looks up the specified name and bus ID, and opens the device found. The 717 * entry in /dev/dri is created if necessary and if called by root. 718 * 719 * \param name driver name. Not referenced if bus ID is supplied. 720 * \param busid bus ID. Zero if not known. 721 * 722 * \return a file descriptor on success, or a negative value on error. 723 * 724 * \internal 725 * It calls drmOpenByBusid() if \p busid is specified or drmOpenByName() 726 * otherwise. 727 */ 728 int drmOpen(const char *name, const char *busid) 729 { 730 return drmOpenWithType(name, busid, DRM_NODE_PRIMARY); 731 } 732 733 /** 734 * Open the DRM device with specified type. 735 * 736 * Looks up the specified name and bus ID, and opens the device found. The 737 * entry in /dev/dri is created if necessary and if called by root. 738 * 739 * \param name driver name. Not referenced if bus ID is supplied. 740 * \param busid bus ID. Zero if not known. 741 * \param type the device node type to open, PRIMARY, CONTROL or RENDER 742 * 743 * \return a file descriptor on success, or a negative value on error. 744 * 745 * \internal 746 * It calls drmOpenByBusid() if \p busid is specified or drmOpenByName() 747 * otherwise. 748 */ 749 int drmOpenWithType(const char *name, const char *busid, int type) 750 { 751 if (name != NULL && drm_server_info && 752 drm_server_info->load_module && !drmAvailable()) { 753 /* try to load the kernel module */ 754 if (!drm_server_info->load_module(name)) { 755 drmMsg("[drm] failed to load kernel module \"%s\"\n", name); 756 return -1; 757 } 758 } 759 760 if (busid) { 761 int fd = drmOpenByBusid(busid, type); 762 if (fd >= 0) 763 return fd; 764 } 765 766 if (name) 767 return drmOpenByName(name, type); 768 769 return -1; 770 } 771 772 int drmOpenControl(int minor) 773 { 774 return drmOpenMinor(minor, 0, DRM_NODE_CONTROL); 775 } 776 777 int drmOpenRender(int minor) 778 { 779 return drmOpenMinor(minor, 0, DRM_NODE_RENDER); 780 } 781 782 /** 783 * Free the version information returned by drmGetVersion(). 784 * 785 * \param v pointer to the version information. 786 * 787 * \internal 788 * It frees the memory pointed by \p %v as well as all the non-null strings 789 * pointers in it. 790 */ 791 void drmFreeVersion(drmVersionPtr v) 792 { 793 if (!v) 794 return; 795 drmFree(v->name); 796 drmFree(v->date); 797 drmFree(v->desc); 798 drmFree(v); 799 } 800 801 802 /** 803 * Free the non-public version information returned by the kernel. 804 * 805 * \param v pointer to the version information. 806 * 807 * \internal 808 * Used by drmGetVersion() to free the memory pointed by \p %v as well as all 809 * the non-null strings pointers in it. 810 */ 811 static void drmFreeKernelVersion(drm_version_t *v) 812 { 813 if (!v) 814 return; 815 drmFree(v->name); 816 drmFree(v->date); 817 drmFree(v->desc); 818 drmFree(v); 819 } 820 821 822 /** 823 * Copy version information. 824 * 825 * \param d destination pointer. 826 * \param s source pointer. 827 * 828 * \internal 829 * Used by drmGetVersion() to translate the information returned by the ioctl 830 * interface in a private structure into the public structure counterpart. 831 */ 832 static void drmCopyVersion(drmVersionPtr d, const drm_version_t *s) 833 { 834 d->version_major = s->version_major; 835 d->version_minor = s->version_minor; 836 d->version_patchlevel = s->version_patchlevel; 837 d->name_len = s->name_len; 838 d->name = strdup(s->name); 839 d->date_len = s->date_len; 840 d->date = strdup(s->date); 841 d->desc_len = s->desc_len; 842 d->desc = strdup(s->desc); 843 } 844 845 846 /** 847 * Query the driver version information. 848 * 849 * \param fd file descriptor. 850 * 851 * \return pointer to a drmVersion structure which should be freed with 852 * drmFreeVersion(). 853 * 854 * \note Similar information is available via /proc/dri. 855 * 856 * \internal 857 * It gets the version information via successive DRM_IOCTL_VERSION ioctls, 858 * first with zeros to get the string lengths, and then the actually strings. 859 * It also null-terminates them since they might not be already. 860 */ 861 drmVersionPtr drmGetVersion(int fd) 862 { 863 drmVersionPtr retval; 864 drm_version_t *version = drmMalloc(sizeof(*version)); 865 866 if (drmIoctl(fd, DRM_IOCTL_VERSION, version)) { 867 drmFreeKernelVersion(version); 868 return NULL; 869 } 870 871 if (version->name_len) 872 version->name = drmMalloc(version->name_len + 1); 873 if (version->date_len) 874 version->date = drmMalloc(version->date_len + 1); 875 if (version->desc_len) 876 version->desc = drmMalloc(version->desc_len + 1); 877 878 if (drmIoctl(fd, DRM_IOCTL_VERSION, version)) { 879 drmMsg("DRM_IOCTL_VERSION: %s\n", strerror(errno)); 880 drmFreeKernelVersion(version); 881 return NULL; 882 } 883 884 /* The results might not be null-terminated strings, so terminate them. */ 885 if (version->name_len) version->name[version->name_len] = '\0'; 886 if (version->date_len) version->date[version->date_len] = '\0'; 887 if (version->desc_len) version->desc[version->desc_len] = '\0'; 888 889 retval = drmMalloc(sizeof(*retval)); 890 drmCopyVersion(retval, version); 891 drmFreeKernelVersion(version); 892 return retval; 893 } 894 895 896 /** 897 * Get version information for the DRM user space library. 898 * 899 * This version number is driver independent. 900 * 901 * \param fd file descriptor. 902 * 903 * \return version information. 904 * 905 * \internal 906 * This function allocates and fills a drm_version structure with a hard coded 907 * version number. 908 */ 909 drmVersionPtr drmGetLibVersion(int fd) 910 { 911 drm_version_t *version = drmMalloc(sizeof(*version)); 912 913 /* Version history: 914 * NOTE THIS MUST NOT GO ABOVE VERSION 1.X due to drivers needing it 915 * revision 1.0.x = original DRM interface with no drmGetLibVersion 916 * entry point and many drm<Device> extensions 917 * revision 1.1.x = added drmCommand entry points for device extensions 918 * added drmGetLibVersion to identify libdrm.a version 919 * revision 1.2.x = added drmSetInterfaceVersion 920 * modified drmOpen to handle both busid and name 921 * revision 1.3.x = added server + memory manager 922 */ 923 version->version_major = 1; 924 version->version_minor = 3; 925 version->version_patchlevel = 0; 926 927 return (drmVersionPtr)version; 928 } 929 930 int drmGetCap(int fd, uint64_t capability, uint64_t *value) 931 { 932 struct drm_get_cap cap; 933 int ret; 934 935 memclear(cap); 936 cap.capability = capability; 937 938 ret = drmIoctl(fd, DRM_IOCTL_GET_CAP, &cap); 939 if (ret) 940 return ret; 941 942 *value = cap.value; 943 return 0; 944 } 945 946 int drmSetClientCap(int fd, uint64_t capability, uint64_t value) 947 { 948 struct drm_set_client_cap cap; 949 950 memclear(cap); 951 cap.capability = capability; 952 cap.value = value; 953 954 return drmIoctl(fd, DRM_IOCTL_SET_CLIENT_CAP, &cap); 955 } 956 957 /** 958 * Free the bus ID information. 959 * 960 * \param busid bus ID information string as given by drmGetBusid(). 961 * 962 * \internal 963 * This function is just frees the memory pointed by \p busid. 964 */ 965 void drmFreeBusid(const char *busid) 966 { 967 drmFree((void *)busid); 968 } 969 970 971 /** 972 * Get the bus ID of the device. 973 * 974 * \param fd file descriptor. 975 * 976 * \return bus ID string. 977 * 978 * \internal 979 * This function gets the bus ID via successive DRM_IOCTL_GET_UNIQUE ioctls to 980 * get the string length and data, passing the arguments in a drm_unique 981 * structure. 982 */ 983 char *drmGetBusid(int fd) 984 { 985 drm_unique_t u; 986 987 memclear(u); 988 989 if (drmIoctl(fd, DRM_IOCTL_GET_UNIQUE, &u)) 990 return NULL; 991 u.unique = drmMalloc(u.unique_len + 1); 992 if (drmIoctl(fd, DRM_IOCTL_GET_UNIQUE, &u)) { 993 drmFree(u.unique); 994 return NULL; 995 } 996 u.unique[u.unique_len] = '\0'; 997 998 return u.unique; 999 } 1000 1001 1002 /** 1003 * Set the bus ID of the device. 1004 * 1005 * \param fd file descriptor. 1006 * \param busid bus ID string. 1007 * 1008 * \return zero on success, negative on failure. 1009 * 1010 * \internal 1011 * This function is a wrapper around the DRM_IOCTL_SET_UNIQUE ioctl, passing 1012 * the arguments in a drm_unique structure. 1013 */ 1014 int drmSetBusid(int fd, const char *busid) 1015 { 1016 drm_unique_t u; 1017 1018 memclear(u); 1019 u.unique = (char *)busid; 1020 u.unique_len = strlen(busid); 1021 1022 if (drmIoctl(fd, DRM_IOCTL_SET_UNIQUE, &u)) { 1023 return -errno; 1024 } 1025 return 0; 1026 } 1027 1028 int drmGetMagic(int fd, drm_magic_t * magic) 1029 { 1030 drm_auth_t auth; 1031 1032 memclear(auth); 1033 1034 *magic = 0; 1035 if (drmIoctl(fd, DRM_IOCTL_GET_MAGIC, &auth)) 1036 return -errno; 1037 *magic = auth.magic; 1038 return 0; 1039 } 1040 1041 int drmAuthMagic(int fd, drm_magic_t magic) 1042 { 1043 drm_auth_t auth; 1044 1045 memclear(auth); 1046 auth.magic = magic; 1047 if (drmIoctl(fd, DRM_IOCTL_AUTH_MAGIC, &auth)) 1048 return -errno; 1049 return 0; 1050 } 1051 1052 /** 1053 * Specifies a range of memory that is available for mapping by a 1054 * non-root process. 1055 * 1056 * \param fd file descriptor. 1057 * \param offset usually the physical address. The actual meaning depends of 1058 * the \p type parameter. See below. 1059 * \param size of the memory in bytes. 1060 * \param type type of the memory to be mapped. 1061 * \param flags combination of several flags to modify the function actions. 1062 * \param handle will be set to a value that may be used as the offset 1063 * parameter for mmap(). 1064 * 1065 * \return zero on success or a negative value on error. 1066 * 1067 * \par Mapping the frame buffer 1068 * For the frame buffer 1069 * - \p offset will be the physical address of the start of the frame buffer, 1070 * - \p size will be the size of the frame buffer in bytes, and 1071 * - \p type will be DRM_FRAME_BUFFER. 1072 * 1073 * \par 1074 * The area mapped will be uncached. If MTRR support is available in the 1075 * kernel, the frame buffer area will be set to write combining. 1076 * 1077 * \par Mapping the MMIO register area 1078 * For the MMIO register area, 1079 * - \p offset will be the physical address of the start of the register area, 1080 * - \p size will be the size of the register area bytes, and 1081 * - \p type will be DRM_REGISTERS. 1082 * \par 1083 * The area mapped will be uncached. 1084 * 1085 * \par Mapping the SAREA 1086 * For the SAREA, 1087 * - \p offset will be ignored and should be set to zero, 1088 * - \p size will be the desired size of the SAREA in bytes, 1089 * - \p type will be DRM_SHM. 1090 * 1091 * \par 1092 * A shared memory area of the requested size will be created and locked in 1093 * kernel memory. This area may be mapped into client-space by using the handle 1094 * returned. 1095 * 1096 * \note May only be called by root. 1097 * 1098 * \internal 1099 * This function is a wrapper around the DRM_IOCTL_ADD_MAP ioctl, passing 1100 * the arguments in a drm_map structure. 1101 */ 1102 int drmAddMap(int fd, drm_handle_t offset, drmSize size, drmMapType type, 1103 drmMapFlags flags, drm_handle_t *handle) 1104 { 1105 drm_map_t map; 1106 1107 memclear(map); 1108 map.offset = offset; 1109 map.size = size; 1110 map.type = type; 1111 map.flags = flags; 1112 if (drmIoctl(fd, DRM_IOCTL_ADD_MAP, &map)) 1113 return -errno; 1114 if (handle) 1115 *handle = (drm_handle_t)(uintptr_t)map.handle; 1116 return 0; 1117 } 1118 1119 int drmRmMap(int fd, drm_handle_t handle) 1120 { 1121 drm_map_t map; 1122 1123 memclear(map); 1124 map.handle = (void *)(uintptr_t)handle; 1125 1126 if(drmIoctl(fd, DRM_IOCTL_RM_MAP, &map)) 1127 return -errno; 1128 return 0; 1129 } 1130 1131 /** 1132 * Make buffers available for DMA transfers. 1133 * 1134 * \param fd file descriptor. 1135 * \param count number of buffers. 1136 * \param size size of each buffer. 1137 * \param flags buffer allocation flags. 1138 * \param agp_offset offset in the AGP aperture 1139 * 1140 * \return number of buffers allocated, negative on error. 1141 * 1142 * \internal 1143 * This function is a wrapper around DRM_IOCTL_ADD_BUFS ioctl. 1144 * 1145 * \sa drm_buf_desc. 1146 */ 1147 int drmAddBufs(int fd, int count, int size, drmBufDescFlags flags, 1148 int agp_offset) 1149 { 1150 drm_buf_desc_t request; 1151 1152 memclear(request); 1153 request.count = count; 1154 request.size = size; 1155 request.flags = flags; 1156 request.agp_start = agp_offset; 1157 1158 if (drmIoctl(fd, DRM_IOCTL_ADD_BUFS, &request)) 1159 return -errno; 1160 return request.count; 1161 } 1162 1163 int drmMarkBufs(int fd, double low, double high) 1164 { 1165 drm_buf_info_t info; 1166 int i; 1167 1168 memclear(info); 1169 1170 if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info)) 1171 return -EINVAL; 1172 1173 if (!info.count) 1174 return -EINVAL; 1175 1176 if (!(info.list = drmMalloc(info.count * sizeof(*info.list)))) 1177 return -ENOMEM; 1178 1179 if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info)) { 1180 int retval = -errno; 1181 drmFree(info.list); 1182 return retval; 1183 } 1184 1185 for (i = 0; i < info.count; i++) { 1186 info.list[i].low_mark = low * info.list[i].count; 1187 info.list[i].high_mark = high * info.list[i].count; 1188 if (drmIoctl(fd, DRM_IOCTL_MARK_BUFS, &info.list[i])) { 1189 int retval = -errno; 1190 drmFree(info.list); 1191 return retval; 1192 } 1193 } 1194 drmFree(info.list); 1195 1196 return 0; 1197 } 1198 1199 /** 1200 * Free buffers. 1201 * 1202 * \param fd file descriptor. 1203 * \param count number of buffers to free. 1204 * \param list list of buffers to be freed. 1205 * 1206 * \return zero on success, or a negative value on failure. 1207 * 1208 * \note This function is primarily used for debugging. 1209 * 1210 * \internal 1211 * This function is a wrapper around the DRM_IOCTL_FREE_BUFS ioctl, passing 1212 * the arguments in a drm_buf_free structure. 1213 */ 1214 int drmFreeBufs(int fd, int count, int *list) 1215 { 1216 drm_buf_free_t request; 1217 1218 memclear(request); 1219 request.count = count; 1220 request.list = list; 1221 if (drmIoctl(fd, DRM_IOCTL_FREE_BUFS, &request)) 1222 return -errno; 1223 return 0; 1224 } 1225 1226 1227 /** 1228 * Close the device. 1229 * 1230 * \param fd file descriptor. 1231 * 1232 * \internal 1233 * This function closes the file descriptor. 1234 */ 1235 int drmClose(int fd) 1236 { 1237 unsigned long key = drmGetKeyFromFd(fd); 1238 drmHashEntry *entry = drmGetEntry(fd); 1239 1240 drmHashDestroy(entry->tagTable); 1241 entry->fd = 0; 1242 entry->f = NULL; 1243 entry->tagTable = NULL; 1244 1245 drmHashDelete(drmHashTable, key); 1246 drmFree(entry); 1247 1248 return close(fd); 1249 } 1250 1251 1252 /** 1253 * Map a region of memory. 1254 * 1255 * \param fd file descriptor. 1256 * \param handle handle returned by drmAddMap(). 1257 * \param size size in bytes. Must match the size used by drmAddMap(). 1258 * \param address will contain the user-space virtual address where the mapping 1259 * begins. 1260 * 1261 * \return zero on success, or a negative value on failure. 1262 * 1263 * \internal 1264 * This function is a wrapper for mmap(). 1265 */ 1266 int drmMap(int fd, drm_handle_t handle, drmSize size, drmAddressPtr address) 1267 { 1268 static unsigned long pagesize_mask = 0; 1269 1270 if (fd < 0) 1271 return -EINVAL; 1272 1273 if (!pagesize_mask) 1274 pagesize_mask = getpagesize() - 1; 1275 1276 size = (size + pagesize_mask) & ~pagesize_mask; 1277 1278 *address = drm_mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, handle); 1279 if (*address == MAP_FAILED) 1280 return -errno; 1281 return 0; 1282 } 1283 1284 1285 /** 1286 * Unmap mappings obtained with drmMap(). 1287 * 1288 * \param address address as given by drmMap(). 1289 * \param size size in bytes. Must match the size used by drmMap(). 1290 * 1291 * \return zero on success, or a negative value on failure. 1292 * 1293 * \internal 1294 * This function is a wrapper for munmap(). 1295 */ 1296 int drmUnmap(drmAddress address, drmSize size) 1297 { 1298 return drm_munmap(address, size); 1299 } 1300 1301 drmBufInfoPtr drmGetBufInfo(int fd) 1302 { 1303 drm_buf_info_t info; 1304 drmBufInfoPtr retval; 1305 int i; 1306 1307 memclear(info); 1308 1309 if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info)) 1310 return NULL; 1311 1312 if (info.count) { 1313 if (!(info.list = drmMalloc(info.count * sizeof(*info.list)))) 1314 return NULL; 1315 1316 if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info)) { 1317 drmFree(info.list); 1318 return NULL; 1319 } 1320 1321 retval = drmMalloc(sizeof(*retval)); 1322 retval->count = info.count; 1323 retval->list = drmMalloc(info.count * sizeof(*retval->list)); 1324 for (i = 0; i < info.count; i++) { 1325 retval->list[i].count = info.list[i].count; 1326 retval->list[i].size = info.list[i].size; 1327 retval->list[i].low_mark = info.list[i].low_mark; 1328 retval->list[i].high_mark = info.list[i].high_mark; 1329 } 1330 drmFree(info.list); 1331 return retval; 1332 } 1333 return NULL; 1334 } 1335 1336 /** 1337 * Map all DMA buffers into client-virtual space. 1338 * 1339 * \param fd file descriptor. 1340 * 1341 * \return a pointer to a ::drmBufMap structure. 1342 * 1343 * \note The client may not use these buffers until obtaining buffer indices 1344 * with drmDMA(). 1345 * 1346 * \internal 1347 * This function calls the DRM_IOCTL_MAP_BUFS ioctl and copies the returned 1348 * information about the buffers in a drm_buf_map structure into the 1349 * client-visible data structures. 1350 */ 1351 drmBufMapPtr drmMapBufs(int fd) 1352 { 1353 drm_buf_map_t bufs; 1354 drmBufMapPtr retval; 1355 int i; 1356 1357 memclear(bufs); 1358 if (drmIoctl(fd, DRM_IOCTL_MAP_BUFS, &bufs)) 1359 return NULL; 1360 1361 if (!bufs.count) 1362 return NULL; 1363 1364 if (!(bufs.list = drmMalloc(bufs.count * sizeof(*bufs.list)))) 1365 return NULL; 1366 1367 if (drmIoctl(fd, DRM_IOCTL_MAP_BUFS, &bufs)) { 1368 drmFree(bufs.list); 1369 return NULL; 1370 } 1371 1372 retval = drmMalloc(sizeof(*retval)); 1373 retval->count = bufs.count; 1374 retval->list = drmMalloc(bufs.count * sizeof(*retval->list)); 1375 for (i = 0; i < bufs.count; i++) { 1376 retval->list[i].idx = bufs.list[i].idx; 1377 retval->list[i].total = bufs.list[i].total; 1378 retval->list[i].used = 0; 1379 retval->list[i].address = bufs.list[i].address; 1380 } 1381 1382 drmFree(bufs.list); 1383 return retval; 1384 } 1385 1386 1387 /** 1388 * Unmap buffers allocated with drmMapBufs(). 1389 * 1390 * \return zero on success, or negative value on failure. 1391 * 1392 * \internal 1393 * Calls munmap() for every buffer stored in \p bufs and frees the 1394 * memory allocated by drmMapBufs(). 1395 */ 1396 int drmUnmapBufs(drmBufMapPtr bufs) 1397 { 1398 int i; 1399 1400 for (i = 0; i < bufs->count; i++) { 1401 drm_munmap(bufs->list[i].address, bufs->list[i].total); 1402 } 1403 1404 drmFree(bufs->list); 1405 drmFree(bufs); 1406 return 0; 1407 } 1408 1409 1410 #define DRM_DMA_RETRY 16 1411 1412 /** 1413 * Reserve DMA buffers. 1414 * 1415 * \param fd file descriptor. 1416 * \param request 1417 * 1418 * \return zero on success, or a negative value on failure. 1419 * 1420 * \internal 1421 * Assemble the arguments into a drm_dma structure and keeps issuing the 1422 * DRM_IOCTL_DMA ioctl until success or until maximum number of retries. 1423 */ 1424 int drmDMA(int fd, drmDMAReqPtr request) 1425 { 1426 drm_dma_t dma; 1427 int ret, i = 0; 1428 1429 dma.context = request->context; 1430 dma.send_count = request->send_count; 1431 dma.send_indices = request->send_list; 1432 dma.send_sizes = request->send_sizes; 1433 dma.flags = request->flags; 1434 dma.request_count = request->request_count; 1435 dma.request_size = request->request_size; 1436 dma.request_indices = request->request_list; 1437 dma.request_sizes = request->request_sizes; 1438 dma.granted_count = 0; 1439 1440 do { 1441 ret = ioctl( fd, DRM_IOCTL_DMA, &dma ); 1442 } while ( ret && errno == EAGAIN && i++ < DRM_DMA_RETRY ); 1443 1444 if ( ret == 0 ) { 1445 request->granted_count = dma.granted_count; 1446 return 0; 1447 } else { 1448 return -errno; 1449 } 1450 } 1451 1452 1453 /** 1454 * Obtain heavyweight hardware lock. 1455 * 1456 * \param fd file descriptor. 1457 * \param context context. 1458 * \param flags flags that determine the sate of the hardware when the function 1459 * returns. 1460 * 1461 * \return always zero. 1462 * 1463 * \internal 1464 * This function translates the arguments into a drm_lock structure and issue 1465 * the DRM_IOCTL_LOCK ioctl until the lock is successfully acquired. 1466 */ 1467 int drmGetLock(int fd, drm_context_t context, drmLockFlags flags) 1468 { 1469 drm_lock_t lock; 1470 1471 memclear(lock); 1472 lock.context = context; 1473 lock.flags = 0; 1474 if (flags & DRM_LOCK_READY) lock.flags |= _DRM_LOCK_READY; 1475 if (flags & DRM_LOCK_QUIESCENT) lock.flags |= _DRM_LOCK_QUIESCENT; 1476 if (flags & DRM_LOCK_FLUSH) lock.flags |= _DRM_LOCK_FLUSH; 1477 if (flags & DRM_LOCK_FLUSH_ALL) lock.flags |= _DRM_LOCK_FLUSH_ALL; 1478 if (flags & DRM_HALT_ALL_QUEUES) lock.flags |= _DRM_HALT_ALL_QUEUES; 1479 if (flags & DRM_HALT_CUR_QUEUES) lock.flags |= _DRM_HALT_CUR_QUEUES; 1480 1481 while (drmIoctl(fd, DRM_IOCTL_LOCK, &lock)) 1482 ; 1483 return 0; 1484 } 1485 1486 /** 1487 * Release the hardware lock. 1488 * 1489 * \param fd file descriptor. 1490 * \param context context. 1491 * 1492 * \return zero on success, or a negative value on failure. 1493 * 1494 * \internal 1495 * This function is a wrapper around the DRM_IOCTL_UNLOCK ioctl, passing the 1496 * argument in a drm_lock structure. 1497 */ 1498 int drmUnlock(int fd, drm_context_t context) 1499 { 1500 drm_lock_t lock; 1501 1502 memclear(lock); 1503 lock.context = context; 1504 return drmIoctl(fd, DRM_IOCTL_UNLOCK, &lock); 1505 } 1506 1507 drm_context_t *drmGetReservedContextList(int fd, int *count) 1508 { 1509 drm_ctx_res_t res; 1510 drm_ctx_t *list; 1511 drm_context_t * retval; 1512 int i; 1513 1514 memclear(res); 1515 if (drmIoctl(fd, DRM_IOCTL_RES_CTX, &res)) 1516 return NULL; 1517 1518 if (!res.count) 1519 return NULL; 1520 1521 if (!(list = drmMalloc(res.count * sizeof(*list)))) 1522 return NULL; 1523 if (!(retval = drmMalloc(res.count * sizeof(*retval)))) 1524 goto err_free_list; 1525 1526 res.contexts = list; 1527 if (drmIoctl(fd, DRM_IOCTL_RES_CTX, &res)) 1528 goto err_free_context; 1529 1530 for (i = 0; i < res.count; i++) 1531 retval[i] = list[i].handle; 1532 drmFree(list); 1533 1534 *count = res.count; 1535 return retval; 1536 1537 err_free_list: 1538 drmFree(list); 1539 err_free_context: 1540 drmFree(retval); 1541 return NULL; 1542 } 1543 1544 void drmFreeReservedContextList(drm_context_t *pt) 1545 { 1546 drmFree(pt); 1547 } 1548 1549 /** 1550 * Create context. 1551 * 1552 * Used by the X server during GLXContext initialization. This causes 1553 * per-context kernel-level resources to be allocated. 1554 * 1555 * \param fd file descriptor. 1556 * \param handle is set on success. To be used by the client when requesting DMA 1557 * dispatch with drmDMA(). 1558 * 1559 * \return zero on success, or a negative value on failure. 1560 * 1561 * \note May only be called by root. 1562 * 1563 * \internal 1564 * This function is a wrapper around the DRM_IOCTL_ADD_CTX ioctl, passing the 1565 * argument in a drm_ctx structure. 1566 */ 1567 int drmCreateContext(int fd, drm_context_t *handle) 1568 { 1569 drm_ctx_t ctx; 1570 1571 memclear(ctx); 1572 if (drmIoctl(fd, DRM_IOCTL_ADD_CTX, &ctx)) 1573 return -errno; 1574 *handle = ctx.handle; 1575 return 0; 1576 } 1577 1578 int drmSwitchToContext(int fd, drm_context_t context) 1579 { 1580 drm_ctx_t ctx; 1581 1582 memclear(ctx); 1583 ctx.handle = context; 1584 if (drmIoctl(fd, DRM_IOCTL_SWITCH_CTX, &ctx)) 1585 return -errno; 1586 return 0; 1587 } 1588 1589 int drmSetContextFlags(int fd, drm_context_t context, drm_context_tFlags flags) 1590 { 1591 drm_ctx_t ctx; 1592 1593 /* 1594 * Context preserving means that no context switches are done between DMA 1595 * buffers from one context and the next. This is suitable for use in the 1596 * X server (which promises to maintain hardware context), or in the 1597 * client-side library when buffers are swapped on behalf of two threads. 1598 */ 1599 memclear(ctx); 1600 ctx.handle = context; 1601 if (flags & DRM_CONTEXT_PRESERVED) 1602 ctx.flags |= _DRM_CONTEXT_PRESERVED; 1603 if (flags & DRM_CONTEXT_2DONLY) 1604 ctx.flags |= _DRM_CONTEXT_2DONLY; 1605 if (drmIoctl(fd, DRM_IOCTL_MOD_CTX, &ctx)) 1606 return -errno; 1607 return 0; 1608 } 1609 1610 int drmGetContextFlags(int fd, drm_context_t context, 1611 drm_context_tFlagsPtr flags) 1612 { 1613 drm_ctx_t ctx; 1614 1615 memclear(ctx); 1616 ctx.handle = context; 1617 if (drmIoctl(fd, DRM_IOCTL_GET_CTX, &ctx)) 1618 return -errno; 1619 *flags = 0; 1620 if (ctx.flags & _DRM_CONTEXT_PRESERVED) 1621 *flags |= DRM_CONTEXT_PRESERVED; 1622 if (ctx.flags & _DRM_CONTEXT_2DONLY) 1623 *flags |= DRM_CONTEXT_2DONLY; 1624 return 0; 1625 } 1626 1627 /** 1628 * Destroy context. 1629 * 1630 * Free any kernel-level resources allocated with drmCreateContext() associated 1631 * with the context. 1632 * 1633 * \param fd file descriptor. 1634 * \param handle handle given by drmCreateContext(). 1635 * 1636 * \return zero on success, or a negative value on failure. 1637 * 1638 * \note May only be called by root. 1639 * 1640 * \internal 1641 * This function is a wrapper around the DRM_IOCTL_RM_CTX ioctl, passing the 1642 * argument in a drm_ctx structure. 1643 */ 1644 int drmDestroyContext(int fd, drm_context_t handle) 1645 { 1646 drm_ctx_t ctx; 1647 1648 memclear(ctx); 1649 ctx.handle = handle; 1650 if (drmIoctl(fd, DRM_IOCTL_RM_CTX, &ctx)) 1651 return -errno; 1652 return 0; 1653 } 1654 1655 int drmCreateDrawable(int fd, drm_drawable_t *handle) 1656 { 1657 drm_draw_t draw; 1658 1659 memclear(draw); 1660 if (drmIoctl(fd, DRM_IOCTL_ADD_DRAW, &draw)) 1661 return -errno; 1662 *handle = draw.handle; 1663 return 0; 1664 } 1665 1666 int drmDestroyDrawable(int fd, drm_drawable_t handle) 1667 { 1668 drm_draw_t draw; 1669 1670 memclear(draw); 1671 draw.handle = handle; 1672 if (drmIoctl(fd, DRM_IOCTL_RM_DRAW, &draw)) 1673 return -errno; 1674 return 0; 1675 } 1676 1677 int drmUpdateDrawableInfo(int fd, drm_drawable_t handle, 1678 drm_drawable_info_type_t type, unsigned int num, 1679 void *data) 1680 { 1681 drm_update_draw_t update; 1682 1683 memclear(update); 1684 update.handle = handle; 1685 update.type = type; 1686 update.num = num; 1687 update.data = (unsigned long long)(unsigned long)data; 1688 1689 if (drmIoctl(fd, DRM_IOCTL_UPDATE_DRAW, &update)) 1690 return -errno; 1691 1692 return 0; 1693 } 1694 1695 int drmCrtcGetSequence(int fd, uint32_t crtcId, uint64_t *sequence, uint64_t *ns) 1696 { 1697 struct drm_crtc_get_sequence get_seq; 1698 int ret; 1699 1700 memclear(get_seq); 1701 get_seq.crtc_id = crtcId; 1702 ret = drmIoctl(fd, DRM_IOCTL_CRTC_GET_SEQUENCE, &get_seq); 1703 if (ret) 1704 return ret; 1705 1706 if (sequence) 1707 *sequence = get_seq.sequence; 1708 if (ns) 1709 *ns = get_seq.sequence_ns; 1710 return 0; 1711 } 1712 1713 int drmCrtcQueueSequence(int fd, uint32_t crtcId, uint32_t flags, uint64_t sequence, 1714 uint64_t *sequence_queued, uint64_t user_data) 1715 { 1716 struct drm_crtc_queue_sequence queue_seq; 1717 int ret; 1718 1719 memclear(queue_seq); 1720 queue_seq.crtc_id = crtcId; 1721 queue_seq.flags = flags; 1722 queue_seq.sequence = sequence; 1723 queue_seq.user_data = user_data; 1724 1725 ret = drmIoctl(fd, DRM_IOCTL_CRTC_QUEUE_SEQUENCE, &queue_seq); 1726 if (ret == 0 && sequence_queued) 1727 *sequence_queued = queue_seq.sequence; 1728 1729 return ret; 1730 } 1731 1732 /** 1733 * Acquire the AGP device. 1734 * 1735 * Must be called before any of the other AGP related calls. 1736 * 1737 * \param fd file descriptor. 1738 * 1739 * \return zero on success, or a negative value on failure. 1740 * 1741 * \internal 1742 * This function is a wrapper around the DRM_IOCTL_AGP_ACQUIRE ioctl. 1743 */ 1744 int drmAgpAcquire(int fd) 1745 { 1746 if (drmIoctl(fd, DRM_IOCTL_AGP_ACQUIRE, NULL)) 1747 return -errno; 1748 return 0; 1749 } 1750 1751 1752 /** 1753 * Release the AGP device. 1754 * 1755 * \param fd file descriptor. 1756 * 1757 * \return zero on success, or a negative value on failure. 1758 * 1759 * \internal 1760 * This function is a wrapper around the DRM_IOCTL_AGP_RELEASE ioctl. 1761 */ 1762 int drmAgpRelease(int fd) 1763 { 1764 if (drmIoctl(fd, DRM_IOCTL_AGP_RELEASE, NULL)) 1765 return -errno; 1766 return 0; 1767 } 1768 1769 1770 /** 1771 * Set the AGP mode. 1772 * 1773 * \param fd file descriptor. 1774 * \param mode AGP mode. 1775 * 1776 * \return zero on success, or a negative value on failure. 1777 * 1778 * \internal 1779 * This function is a wrapper around the DRM_IOCTL_AGP_ENABLE ioctl, passing the 1780 * argument in a drm_agp_mode structure. 1781 */ 1782 int drmAgpEnable(int fd, unsigned long mode) 1783 { 1784 drm_agp_mode_t m; 1785 1786 memclear(m); 1787 m.mode = mode; 1788 if (drmIoctl(fd, DRM_IOCTL_AGP_ENABLE, &m)) 1789 return -errno; 1790 return 0; 1791 } 1792 1793 1794 /** 1795 * Allocate a chunk of AGP memory. 1796 * 1797 * \param fd file descriptor. 1798 * \param size requested memory size in bytes. Will be rounded to page boundary. 1799 * \param type type of memory to allocate. 1800 * \param address if not zero, will be set to the physical address of the 1801 * allocated memory. 1802 * \param handle on success will be set to a handle of the allocated memory. 1803 * 1804 * \return zero on success, or a negative value on failure. 1805 * 1806 * \internal 1807 * This function is a wrapper around the DRM_IOCTL_AGP_ALLOC ioctl, passing the 1808 * arguments in a drm_agp_buffer structure. 1809 */ 1810 int drmAgpAlloc(int fd, unsigned long size, unsigned long type, 1811 unsigned long *address, drm_handle_t *handle) 1812 { 1813 drm_agp_buffer_t b; 1814 1815 memclear(b); 1816 *handle = DRM_AGP_NO_HANDLE; 1817 b.size = size; 1818 b.type = type; 1819 if (drmIoctl(fd, DRM_IOCTL_AGP_ALLOC, &b)) 1820 return -errno; 1821 if (address != 0UL) 1822 *address = b.physical; 1823 *handle = b.handle; 1824 return 0; 1825 } 1826 1827 1828 /** 1829 * Free a chunk of AGP memory. 1830 * 1831 * \param fd file descriptor. 1832 * \param handle handle to the allocated memory, as given by drmAgpAllocate(). 1833 * 1834 * \return zero on success, or a negative value on failure. 1835 * 1836 * \internal 1837 * This function is a wrapper around the DRM_IOCTL_AGP_FREE ioctl, passing the 1838 * argument in a drm_agp_buffer structure. 1839 */ 1840 int drmAgpFree(int fd, drm_handle_t handle) 1841 { 1842 drm_agp_buffer_t b; 1843 1844 memclear(b); 1845 b.handle = handle; 1846 if (drmIoctl(fd, DRM_IOCTL_AGP_FREE, &b)) 1847 return -errno; 1848 return 0; 1849 } 1850 1851 1852 /** 1853 * Bind a chunk of AGP memory. 1854 * 1855 * \param fd file descriptor. 1856 * \param handle handle to the allocated memory, as given by drmAgpAllocate(). 1857 * \param offset offset in bytes. It will round to page boundary. 1858 * 1859 * \return zero on success, or a negative value on failure. 1860 * 1861 * \internal 1862 * This function is a wrapper around the DRM_IOCTL_AGP_BIND ioctl, passing the 1863 * argument in a drm_agp_binding structure. 1864 */ 1865 int drmAgpBind(int fd, drm_handle_t handle, unsigned long offset) 1866 { 1867 drm_agp_binding_t b; 1868 1869 memclear(b); 1870 b.handle = handle; 1871 b.offset = offset; 1872 if (drmIoctl(fd, DRM_IOCTL_AGP_BIND, &b)) 1873 return -errno; 1874 return 0; 1875 } 1876 1877 1878 /** 1879 * Unbind a chunk of AGP memory. 1880 * 1881 * \param fd file descriptor. 1882 * \param handle handle to the allocated memory, as given by drmAgpAllocate(). 1883 * 1884 * \return zero on success, or a negative value on failure. 1885 * 1886 * \internal 1887 * This function is a wrapper around the DRM_IOCTL_AGP_UNBIND ioctl, passing 1888 * the argument in a drm_agp_binding structure. 1889 */ 1890 int drmAgpUnbind(int fd, drm_handle_t handle) 1891 { 1892 drm_agp_binding_t b; 1893 1894 memclear(b); 1895 b.handle = handle; 1896 if (drmIoctl(fd, DRM_IOCTL_AGP_UNBIND, &b)) 1897 return -errno; 1898 return 0; 1899 } 1900 1901 1902 /** 1903 * Get AGP driver major version number. 1904 * 1905 * \param fd file descriptor. 1906 * 1907 * \return major version number on success, or a negative value on failure.. 1908 * 1909 * \internal 1910 * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the 1911 * necessary information in a drm_agp_info structure. 1912 */ 1913 int drmAgpVersionMajor(int fd) 1914 { 1915 drm_agp_info_t i; 1916 1917 memclear(i); 1918 1919 if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i)) 1920 return -errno; 1921 return i.agp_version_major; 1922 } 1923 1924 1925 /** 1926 * Get AGP driver minor version number. 1927 * 1928 * \param fd file descriptor. 1929 * 1930 * \return minor version number on success, or a negative value on failure. 1931 * 1932 * \internal 1933 * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the 1934 * necessary information in a drm_agp_info structure. 1935 */ 1936 int drmAgpVersionMinor(int fd) 1937 { 1938 drm_agp_info_t i; 1939 1940 memclear(i); 1941 1942 if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i)) 1943 return -errno; 1944 return i.agp_version_minor; 1945 } 1946 1947 1948 /** 1949 * Get AGP mode. 1950 * 1951 * \param fd file descriptor. 1952 * 1953 * \return mode on success, or zero on failure. 1954 * 1955 * \internal 1956 * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the 1957 * necessary information in a drm_agp_info structure. 1958 */ 1959 unsigned long drmAgpGetMode(int fd) 1960 { 1961 drm_agp_info_t i; 1962 1963 memclear(i); 1964 1965 if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i)) 1966 return 0; 1967 return i.mode; 1968 } 1969 1970 1971 /** 1972 * Get AGP aperture base. 1973 * 1974 * \param fd file descriptor. 1975 * 1976 * \return aperture base on success, zero on failure. 1977 * 1978 * \internal 1979 * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the 1980 * necessary information in a drm_agp_info structure. 1981 */ 1982 unsigned long drmAgpBase(int fd) 1983 { 1984 drm_agp_info_t i; 1985 1986 memclear(i); 1987 1988 if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i)) 1989 return 0; 1990 return i.aperture_base; 1991 } 1992 1993 1994 /** 1995 * Get AGP aperture size. 1996 * 1997 * \param fd file descriptor. 1998 * 1999 * \return aperture size on success, zero on failure. 2000 * 2001 * \internal 2002 * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the 2003 * necessary information in a drm_agp_info structure. 2004 */ 2005 unsigned long drmAgpSize(int fd) 2006 { 2007 drm_agp_info_t i; 2008 2009 memclear(i); 2010 2011 if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i)) 2012 return 0; 2013 return i.aperture_size; 2014 } 2015 2016 2017 /** 2018 * Get used AGP memory. 2019 * 2020 * \param fd file descriptor. 2021 * 2022 * \return memory used on success, or zero on failure. 2023 * 2024 * \internal 2025 * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the 2026 * necessary information in a drm_agp_info structure. 2027 */ 2028 unsigned long drmAgpMemoryUsed(int fd) 2029 { 2030 drm_agp_info_t i; 2031 2032 memclear(i); 2033 2034 if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i)) 2035 return 0; 2036 return i.memory_used; 2037 } 2038 2039 2040 /** 2041 * Get available AGP memory. 2042 * 2043 * \param fd file descriptor. 2044 * 2045 * \return memory available on success, or zero on failure. 2046 * 2047 * \internal 2048 * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the 2049 * necessary information in a drm_agp_info structure. 2050 */ 2051 unsigned long drmAgpMemoryAvail(int fd) 2052 { 2053 drm_agp_info_t i; 2054 2055 memclear(i); 2056 2057 if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i)) 2058 return 0; 2059 return i.memory_allowed; 2060 } 2061 2062 2063 /** 2064 * Get hardware vendor ID. 2065 * 2066 * \param fd file descriptor. 2067 * 2068 * \return vendor ID on success, or zero on failure. 2069 * 2070 * \internal 2071 * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the 2072 * necessary information in a drm_agp_info structure. 2073 */ 2074 unsigned int drmAgpVendorId(int fd) 2075 { 2076 drm_agp_info_t i; 2077 2078 memclear(i); 2079 2080 if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i)) 2081 return 0; 2082 return i.id_vendor; 2083 } 2084 2085 2086 /** 2087 * Get hardware device ID. 2088 * 2089 * \param fd file descriptor. 2090 * 2091 * \return zero on success, or zero on failure. 2092 * 2093 * \internal 2094 * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the 2095 * necessary information in a drm_agp_info structure. 2096 */ 2097 unsigned int drmAgpDeviceId(int fd) 2098 { 2099 drm_agp_info_t i; 2100 2101 memclear(i); 2102 2103 if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i)) 2104 return 0; 2105 return i.id_device; 2106 } 2107 2108 int drmScatterGatherAlloc(int fd, unsigned long size, drm_handle_t *handle) 2109 { 2110 drm_scatter_gather_t sg; 2111 2112 memclear(sg); 2113 2114 *handle = 0; 2115 sg.size = size; 2116 if (drmIoctl(fd, DRM_IOCTL_SG_ALLOC, &sg)) 2117 return -errno; 2118 *handle = sg.handle; 2119 return 0; 2120 } 2121 2122 int drmScatterGatherFree(int fd, drm_handle_t handle) 2123 { 2124 drm_scatter_gather_t sg; 2125 2126 memclear(sg); 2127 sg.handle = handle; 2128 if (drmIoctl(fd, DRM_IOCTL_SG_FREE, &sg)) 2129 return -errno; 2130 return 0; 2131 } 2132 2133 /** 2134 * Wait for VBLANK. 2135 * 2136 * \param fd file descriptor. 2137 * \param vbl pointer to a drmVBlank structure. 2138 * 2139 * \return zero on success, or a negative value on failure. 2140 * 2141 * \internal 2142 * This function is a wrapper around the DRM_IOCTL_WAIT_VBLANK ioctl. 2143 */ 2144 int drmWaitVBlank(int fd, drmVBlankPtr vbl) 2145 { 2146 struct timespec timeout, cur; 2147 int ret; 2148 2149 ret = clock_gettime(CLOCK_MONOTONIC, &timeout); 2150 if (ret < 0) { 2151 fprintf(stderr, "clock_gettime failed: %s\n", strerror(errno)); 2152 goto out; 2153 } 2154 timeout.tv_sec++; 2155 2156 do { 2157 ret = ioctl(fd, DRM_IOCTL_WAIT_VBLANK, vbl); 2158 vbl->request.type &= ~DRM_VBLANK_RELATIVE; 2159 if (ret && errno == EINTR) { 2160 clock_gettime(CLOCK_MONOTONIC, &cur); 2161 /* Timeout after 1s */ 2162 if (cur.tv_sec > timeout.tv_sec + 1 || 2163 (cur.tv_sec == timeout.tv_sec && cur.tv_nsec >= 2164 timeout.tv_nsec)) { 2165 errno = EBUSY; 2166 ret = -1; 2167 break; 2168 } 2169 } 2170 } while (ret && errno == EINTR); 2171 2172 out: 2173 return ret; 2174 } 2175 2176 int drmError(int err, const char *label) 2177 { 2178 switch (err) { 2179 case DRM_ERR_NO_DEVICE: 2180 fprintf(stderr, "%s: no device\n", label); 2181 break; 2182 case DRM_ERR_NO_ACCESS: 2183 fprintf(stderr, "%s: no access\n", label); 2184 break; 2185 case DRM_ERR_NOT_ROOT: 2186 fprintf(stderr, "%s: not root\n", label); 2187 break; 2188 case DRM_ERR_INVALID: 2189 fprintf(stderr, "%s: invalid args\n", label); 2190 break; 2191 default: 2192 if (err < 0) 2193 err = -err; 2194 fprintf( stderr, "%s: error %d (%s)\n", label, err, strerror(err) ); 2195 break; 2196 } 2197 2198 return 1; 2199 } 2200 2201 /** 2202 * Install IRQ handler. 2203 * 2204 * \param fd file descriptor. 2205 * \param irq IRQ number. 2206 * 2207 * \return zero on success, or a negative value on failure. 2208 * 2209 * \internal 2210 * This function is a wrapper around the DRM_IOCTL_CONTROL ioctl, passing the 2211 * argument in a drm_control structure. 2212 */ 2213 int drmCtlInstHandler(int fd, int irq) 2214 { 2215 drm_control_t ctl; 2216 2217 memclear(ctl); 2218 ctl.func = DRM_INST_HANDLER; 2219 ctl.irq = irq; 2220 if (drmIoctl(fd, DRM_IOCTL_CONTROL, &ctl)) 2221 return -errno; 2222 return 0; 2223 } 2224 2225 2226 /** 2227 * Uninstall IRQ handler. 2228 * 2229 * \param fd file descriptor. 2230 * 2231 * \return zero on success, or a negative value on failure. 2232 * 2233 * \internal 2234 * This function is a wrapper around the DRM_IOCTL_CONTROL ioctl, passing the 2235 * argument in a drm_control structure. 2236 */ 2237 int drmCtlUninstHandler(int fd) 2238 { 2239 drm_control_t ctl; 2240 2241 memclear(ctl); 2242 ctl.func = DRM_UNINST_HANDLER; 2243 ctl.irq = 0; 2244 if (drmIoctl(fd, DRM_IOCTL_CONTROL, &ctl)) 2245 return -errno; 2246 return 0; 2247 } 2248 2249 int drmFinish(int fd, int context, drmLockFlags flags) 2250 { 2251 drm_lock_t lock; 2252 2253 memclear(lock); 2254 lock.context = context; 2255 if (flags & DRM_LOCK_READY) lock.flags |= _DRM_LOCK_READY; 2256 if (flags & DRM_LOCK_QUIESCENT) lock.flags |= _DRM_LOCK_QUIESCENT; 2257 if (flags & DRM_LOCK_FLUSH) lock.flags |= _DRM_LOCK_FLUSH; 2258 if (flags & DRM_LOCK_FLUSH_ALL) lock.flags |= _DRM_LOCK_FLUSH_ALL; 2259 if (flags & DRM_HALT_ALL_QUEUES) lock.flags |= _DRM_HALT_ALL_QUEUES; 2260 if (flags & DRM_HALT_CUR_QUEUES) lock.flags |= _DRM_HALT_CUR_QUEUES; 2261 if (drmIoctl(fd, DRM_IOCTL_FINISH, &lock)) 2262 return -errno; 2263 return 0; 2264 } 2265 2266 /** 2267 * Get IRQ from bus ID. 2268 * 2269 * \param fd file descriptor. 2270 * \param busnum bus number. 2271 * \param devnum device number. 2272 * \param funcnum function number. 2273 * 2274 * \return IRQ number on success, or a negative value on failure. 2275 * 2276 * \internal 2277 * This function is a wrapper around the DRM_IOCTL_IRQ_BUSID ioctl, passing the 2278 * arguments in a drm_irq_busid structure. 2279 */ 2280 int drmGetInterruptFromBusID(int fd, int busnum, int devnum, int funcnum) 2281 { 2282 drm_irq_busid_t p; 2283 2284 memclear(p); 2285 p.busnum = busnum; 2286 p.devnum = devnum; 2287 p.funcnum = funcnum; 2288 if (drmIoctl(fd, DRM_IOCTL_IRQ_BUSID, &p)) 2289 return -errno; 2290 return p.irq; 2291 } 2292 2293 int drmAddContextTag(int fd, drm_context_t context, void *tag) 2294 { 2295 drmHashEntry *entry = drmGetEntry(fd); 2296 2297 if (drmHashInsert(entry->tagTable, context, tag)) { 2298 drmHashDelete(entry->tagTable, context); 2299 drmHashInsert(entry->tagTable, context, tag); 2300 } 2301 return 0; 2302 } 2303 2304 int drmDelContextTag(int fd, drm_context_t context) 2305 { 2306 drmHashEntry *entry = drmGetEntry(fd); 2307 2308 return drmHashDelete(entry->tagTable, context); 2309 } 2310 2311 void *drmGetContextTag(int fd, drm_context_t context) 2312 { 2313 drmHashEntry *entry = drmGetEntry(fd); 2314 void *value; 2315 2316 if (drmHashLookup(entry->tagTable, context, &value)) 2317 return NULL; 2318 2319 return value; 2320 } 2321 2322 int drmAddContextPrivateMapping(int fd, drm_context_t ctx_id, 2323 drm_handle_t handle) 2324 { 2325 drm_ctx_priv_map_t map; 2326 2327 memclear(map); 2328 map.ctx_id = ctx_id; 2329 map.handle = (void *)(uintptr_t)handle; 2330 2331 if (drmIoctl(fd, DRM_IOCTL_SET_SAREA_CTX, &map)) 2332 return -errno; 2333 return 0; 2334 } 2335 2336 int drmGetContextPrivateMapping(int fd, drm_context_t ctx_id, 2337 drm_handle_t *handle) 2338 { 2339 drm_ctx_priv_map_t map; 2340 2341 memclear(map); 2342 map.ctx_id = ctx_id; 2343 2344 if (drmIoctl(fd, DRM_IOCTL_GET_SAREA_CTX, &map)) 2345 return -errno; 2346 if (handle) 2347 *handle = (drm_handle_t)(uintptr_t)map.handle; 2348 2349 return 0; 2350 } 2351 2352 int drmGetMap(int fd, int idx, drm_handle_t *offset, drmSize *size, 2353 drmMapType *type, drmMapFlags *flags, drm_handle_t *handle, 2354 int *mtrr) 2355 { 2356 drm_map_t map; 2357 2358 memclear(map); 2359 map.offset = idx; 2360 if (drmIoctl(fd, DRM_IOCTL_GET_MAP, &map)) 2361 return -errno; 2362 *offset = map.offset; 2363 *size = map.size; 2364 *type = map.type; 2365 *flags = map.flags; 2366 *handle = (unsigned long)map.handle; 2367 *mtrr = map.mtrr; 2368 return 0; 2369 } 2370 2371 int drmGetClient(int fd, int idx, int *auth, int *pid, int *uid, 2372 unsigned long *magic, unsigned long *iocs) 2373 { 2374 drm_client_t client; 2375 2376 memclear(client); 2377 client.idx = idx; 2378 if (drmIoctl(fd, DRM_IOCTL_GET_CLIENT, &client)) 2379 return -errno; 2380 *auth = client.auth; 2381 *pid = client.pid; 2382 *uid = client.uid; 2383 *magic = client.magic; 2384 *iocs = client.iocs; 2385 return 0; 2386 } 2387 2388 int drmGetStats(int fd, drmStatsT *stats) 2389 { 2390 drm_stats_t s; 2391 unsigned i; 2392 2393 memclear(s); 2394 if (drmIoctl(fd, DRM_IOCTL_GET_STATS, &s)) 2395 return -errno; 2396 2397 stats->count = 0; 2398 memset(stats, 0, sizeof(*stats)); 2399 if (s.count > sizeof(stats->data)/sizeof(stats->data[0])) 2400 return -1; 2401 2402 #define SET_VALUE \ 2403 stats->data[i].long_format = "%-20.20s"; \ 2404 stats->data[i].rate_format = "%8.8s"; \ 2405 stats->data[i].isvalue = 1; \ 2406 stats->data[i].verbose = 0 2407 2408 #define SET_COUNT \ 2409 stats->data[i].long_format = "%-20.20s"; \ 2410 stats->data[i].rate_format = "%5.5s"; \ 2411 stats->data[i].isvalue = 0; \ 2412 stats->data[i].mult_names = "kgm"; \ 2413 stats->data[i].mult = 1000; \ 2414 stats->data[i].verbose = 0 2415 2416 #define SET_BYTE \ 2417 stats->data[i].long_format = "%-20.20s"; \ 2418 stats->data[i].rate_format = "%5.5s"; \ 2419 stats->data[i].isvalue = 0; \ 2420 stats->data[i].mult_names = "KGM"; \ 2421 stats->data[i].mult = 1024; \ 2422 stats->data[i].verbose = 0 2423 2424 2425 stats->count = s.count; 2426 for (i = 0; i < s.count; i++) { 2427 stats->data[i].value = s.data[i].value; 2428 switch (s.data[i].type) { 2429 case _DRM_STAT_LOCK: 2430 stats->data[i].long_name = "Lock"; 2431 stats->data[i].rate_name = "Lock"; 2432 SET_VALUE; 2433 break; 2434 case _DRM_STAT_OPENS: 2435 stats->data[i].long_name = "Opens"; 2436 stats->data[i].rate_name = "O"; 2437 SET_COUNT; 2438 stats->data[i].verbose = 1; 2439 break; 2440 case _DRM_STAT_CLOSES: 2441 stats->data[i].long_name = "Closes"; 2442 stats->data[i].rate_name = "Lock"; 2443 SET_COUNT; 2444 stats->data[i].verbose = 1; 2445 break; 2446 case _DRM_STAT_IOCTLS: 2447 stats->data[i].long_name = "Ioctls"; 2448 stats->data[i].rate_name = "Ioc/s"; 2449 SET_COUNT; 2450 break; 2451 case _DRM_STAT_LOCKS: 2452 stats->data[i].long_name = "Locks"; 2453 stats->data[i].rate_name = "Lck/s"; 2454 SET_COUNT; 2455 break; 2456 case _DRM_STAT_UNLOCKS: 2457 stats->data[i].long_name = "Unlocks"; 2458 stats->data[i].rate_name = "Unl/s"; 2459 SET_COUNT; 2460 break; 2461 case _DRM_STAT_IRQ: 2462 stats->data[i].long_name = "IRQs"; 2463 stats->data[i].rate_name = "IRQ/s"; 2464 SET_COUNT; 2465 break; 2466 case _DRM_STAT_PRIMARY: 2467 stats->data[i].long_name = "Primary Bytes"; 2468 stats->data[i].rate_name = "PB/s"; 2469 SET_BYTE; 2470 break; 2471 case _DRM_STAT_SECONDARY: 2472 stats->data[i].long_name = "Secondary Bytes"; 2473 stats->data[i].rate_name = "SB/s"; 2474 SET_BYTE; 2475 break; 2476 case _DRM_STAT_DMA: 2477 stats->data[i].long_name = "DMA"; 2478 stats->data[i].rate_name = "DMA/s"; 2479 SET_COUNT; 2480 break; 2481 case _DRM_STAT_SPECIAL: 2482 stats->data[i].long_name = "Special DMA"; 2483 stats->data[i].rate_name = "dma/s"; 2484 SET_COUNT; 2485 break; 2486 case _DRM_STAT_MISSED: 2487 stats->data[i].long_name = "Miss"; 2488 stats->data[i].rate_name = "Ms/s"; 2489 SET_COUNT; 2490 break; 2491 case _DRM_STAT_VALUE: 2492 stats->data[i].long_name = "Value"; 2493 stats->data[i].rate_name = "Value"; 2494 SET_VALUE; 2495 break; 2496 case _DRM_STAT_BYTE: 2497 stats->data[i].long_name = "Bytes"; 2498 stats->data[i].rate_name = "B/s"; 2499 SET_BYTE; 2500 break; 2501 case _DRM_STAT_COUNT: 2502 default: 2503 stats->data[i].long_name = "Count"; 2504 stats->data[i].rate_name = "Cnt/s"; 2505 SET_COUNT; 2506 break; 2507 } 2508 } 2509 return 0; 2510 } 2511 2512 /** 2513 * Issue a set-version ioctl. 2514 * 2515 * \param fd file descriptor. 2516 * \param drmCommandIndex command index 2517 * \param data source pointer of the data to be read and written. 2518 * \param size size of the data to be read and written. 2519 * 2520 * \return zero on success, or a negative value on failure. 2521 * 2522 * \internal 2523 * It issues a read-write ioctl given by 2524 * \code DRM_COMMAND_BASE + drmCommandIndex \endcode. 2525 */ 2526 int drmSetInterfaceVersion(int fd, drmSetVersion *version) 2527 { 2528 int retcode = 0; 2529 drm_set_version_t sv; 2530 2531 memclear(sv); 2532 sv.drm_di_major = version->drm_di_major; 2533 sv.drm_di_minor = version->drm_di_minor; 2534 sv.drm_dd_major = version->drm_dd_major; 2535 sv.drm_dd_minor = version->drm_dd_minor; 2536 2537 if (drmIoctl(fd, DRM_IOCTL_SET_VERSION, &sv)) { 2538 retcode = -errno; 2539 } 2540 2541 version->drm_di_major = sv.drm_di_major; 2542 version->drm_di_minor = sv.drm_di_minor; 2543 version->drm_dd_major = sv.drm_dd_major; 2544 version->drm_dd_minor = sv.drm_dd_minor; 2545 2546 return retcode; 2547 } 2548 2549 /** 2550 * Send a device-specific command. 2551 * 2552 * \param fd file descriptor. 2553 * \param drmCommandIndex command index 2554 * 2555 * \return zero on success, or a negative value on failure. 2556 * 2557 * \internal 2558 * It issues a ioctl given by 2559 * \code DRM_COMMAND_BASE + drmCommandIndex \endcode. 2560 */ 2561 int drmCommandNone(int fd, unsigned long drmCommandIndex) 2562 { 2563 unsigned long request; 2564 2565 request = DRM_IO( DRM_COMMAND_BASE + drmCommandIndex); 2566 2567 if (drmIoctl(fd, request, NULL)) { 2568 return -errno; 2569 } 2570 return 0; 2571 } 2572 2573 2574 /** 2575 * Send a device-specific read command. 2576 * 2577 * \param fd file descriptor. 2578 * \param drmCommandIndex command index 2579 * \param data destination pointer of the data to be read. 2580 * \param size size of the data to be read. 2581 * 2582 * \return zero on success, or a negative value on failure. 2583 * 2584 * \internal 2585 * It issues a read ioctl given by 2586 * \code DRM_COMMAND_BASE + drmCommandIndex \endcode. 2587 */ 2588 int drmCommandRead(int fd, unsigned long drmCommandIndex, void *data, 2589 unsigned long size) 2590 { 2591 unsigned long request; 2592 2593 request = DRM_IOC( DRM_IOC_READ, DRM_IOCTL_BASE, 2594 DRM_COMMAND_BASE + drmCommandIndex, size); 2595 2596 if (drmIoctl(fd, request, data)) { 2597 return -errno; 2598 } 2599 return 0; 2600 } 2601 2602 2603 /** 2604 * Send a device-specific write command. 2605 * 2606 * \param fd file descriptor. 2607 * \param drmCommandIndex command index 2608 * \param data source pointer of the data to be written. 2609 * \param size size of the data to be written. 2610 * 2611 * \return zero on success, or a negative value on failure. 2612 * 2613 * \internal 2614 * It issues a write ioctl given by 2615 * \code DRM_COMMAND_BASE + drmCommandIndex \endcode. 2616 */ 2617 int drmCommandWrite(int fd, unsigned long drmCommandIndex, void *data, 2618 unsigned long size) 2619 { 2620 unsigned long request; 2621 2622 request = DRM_IOC( DRM_IOC_WRITE, DRM_IOCTL_BASE, 2623 DRM_COMMAND_BASE + drmCommandIndex, size); 2624 2625 if (drmIoctl(fd, request, data)) { 2626 return -errno; 2627 } 2628 return 0; 2629 } 2630 2631 2632 /** 2633 * Send a device-specific read-write command. 2634 * 2635 * \param fd file descriptor. 2636 * \param drmCommandIndex command index 2637 * \param data source pointer of the data to be read and written. 2638 * \param size size of the data to be read and written. 2639 * 2640 * \return zero on success, or a negative value on failure. 2641 * 2642 * \internal 2643 * It issues a read-write ioctl given by 2644 * \code DRM_COMMAND_BASE + drmCommandIndex \endcode. 2645 */ 2646 int drmCommandWriteRead(int fd, unsigned long drmCommandIndex, void *data, 2647 unsigned long size) 2648 { 2649 unsigned long request; 2650 2651 request = DRM_IOC( DRM_IOC_READ|DRM_IOC_WRITE, DRM_IOCTL_BASE, 2652 DRM_COMMAND_BASE + drmCommandIndex, size); 2653 2654 if (drmIoctl(fd, request, data)) 2655 return -errno; 2656 return 0; 2657 } 2658 2659 #define DRM_MAX_FDS 16 2660 static struct { 2661 char *BusID; 2662 int fd; 2663 int refcount; 2664 int type; 2665 } connection[DRM_MAX_FDS]; 2666 2667 static int nr_fds = 0; 2668 2669 int drmOpenOnce(void *unused, 2670 const char *BusID, 2671 int *newlyopened) 2672 { 2673 return drmOpenOnceWithType(BusID, newlyopened, DRM_NODE_PRIMARY); 2674 } 2675 2676 int drmOpenOnceWithType(const char *BusID, int *newlyopened, int type) 2677 { 2678 int i; 2679 int fd; 2680 2681 for (i = 0; i < nr_fds; i++) 2682 if ((strcmp(BusID, connection[i].BusID) == 0) && 2683 (connection[i].type == type)) { 2684 connection[i].refcount++; 2685 *newlyopened = 0; 2686 return connection[i].fd; 2687 } 2688 2689 fd = drmOpenWithType(NULL, BusID, type); 2690 if (fd < 0 || nr_fds == DRM_MAX_FDS) 2691 return fd; 2692 2693 connection[nr_fds].BusID = strdup(BusID); 2694 connection[nr_fds].fd = fd; 2695 connection[nr_fds].refcount = 1; 2696 connection[nr_fds].type = type; 2697 *newlyopened = 1; 2698 2699 if (0) 2700 fprintf(stderr, "saved connection %d for %s %d\n", 2701 nr_fds, connection[nr_fds].BusID, 2702 strcmp(BusID, connection[nr_fds].BusID)); 2703 2704 nr_fds++; 2705 2706 return fd; 2707 } 2708 2709 void drmCloseOnce(int fd) 2710 { 2711 int i; 2712 2713 for (i = 0; i < nr_fds; i++) { 2714 if (fd == connection[i].fd) { 2715 if (--connection[i].refcount == 0) { 2716 drmClose(connection[i].fd); 2717 free(connection[i].BusID); 2718 2719 if (i < --nr_fds) 2720 connection[i] = connection[nr_fds]; 2721 2722 return; 2723 } 2724 } 2725 } 2726 } 2727 2728 int drmSetMaster(int fd) 2729 { 2730 return drmIoctl(fd, DRM_IOCTL_SET_MASTER, NULL); 2731 } 2732 2733 int drmDropMaster(int fd) 2734 { 2735 return drmIoctl(fd, DRM_IOCTL_DROP_MASTER, NULL); 2736 } 2737 2738 char *drmGetDeviceNameFromFd(int fd) 2739 { 2740 char name[128]; 2741 struct stat sbuf; 2742 dev_t d; 2743 int i; 2744 2745 /* The whole drmOpen thing is a fiasco and we need to find a way 2746 * back to just using open(2). For now, however, lets just make 2747 * things worse with even more ad hoc directory walking code to 2748 * discover the device file name. */ 2749 2750 fstat(fd, &sbuf); 2751 d = sbuf.st_rdev; 2752 2753 for (i = 0; i < DRM_MAX_MINOR; i++) { 2754 snprintf(name, sizeof name, DRM_DEV_NAME, DRM_DIR_NAME, i); 2755 if (stat(name, &sbuf) == 0 && sbuf.st_rdev == d) 2756 break; 2757 } 2758 if (i == DRM_MAX_MINOR) 2759 return NULL; 2760 2761 return strdup(name); 2762 } 2763 2764 int drmGetNodeTypeFromFd(int fd) 2765 { 2766 struct stat sbuf; 2767 int maj, min, type; 2768 2769 if (fstat(fd, &sbuf)) 2770 return -1; 2771 2772 maj = major(sbuf.st_rdev); 2773 min = minor(sbuf.st_rdev); 2774 2775 if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode)) { 2776 errno = EINVAL; 2777 return -1; 2778 } 2779 2780 type = drmGetMinorType(min); 2781 if (type == -1) 2782 errno = ENODEV; 2783 return type; 2784 } 2785 2786 int drmPrimeHandleToFD(int fd, uint32_t handle, uint32_t flags, int *prime_fd) 2787 { 2788 struct drm_prime_handle args; 2789 int ret; 2790 2791 memclear(args); 2792 args.fd = -1; 2793 args.handle = handle; 2794 args.flags = flags; 2795 ret = drmIoctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &args); 2796 if (ret) 2797 return ret; 2798 2799 *prime_fd = args.fd; 2800 return 0; 2801 } 2802 2803 int drmPrimeFDToHandle(int fd, int prime_fd, uint32_t *handle) 2804 { 2805 struct drm_prime_handle args; 2806 int ret; 2807 2808 memclear(args); 2809 args.fd = prime_fd; 2810 ret = drmIoctl(fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &args); 2811 if (ret) 2812 return ret; 2813 2814 *handle = args.handle; 2815 return 0; 2816 } 2817 2818 static char *drmGetMinorNameForFD(int fd, int type) 2819 { 2820 #ifdef __linux__ 2821 DIR *sysdir; 2822 struct dirent *ent; 2823 struct stat sbuf; 2824 const char *name = drmGetMinorName(type); 2825 int len; 2826 char dev_name[64], buf[64]; 2827 int maj, min; 2828 2829 if (!name) 2830 return NULL; 2831 2832 len = strlen(name); 2833 2834 if (fstat(fd, &sbuf)) 2835 return NULL; 2836 2837 maj = major(sbuf.st_rdev); 2838 min = minor(sbuf.st_rdev); 2839 2840 if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode)) 2841 return NULL; 2842 2843 snprintf(buf, sizeof(buf), "/sys/dev/char/%d:%d/device/drm", maj, min); 2844 2845 sysdir = opendir(buf); 2846 if (!sysdir) 2847 return NULL; 2848 2849 while ((ent = readdir(sysdir))) { 2850 if (strncmp(ent->d_name, name, len) == 0) { 2851 snprintf(dev_name, sizeof(dev_name), DRM_DIR_NAME "/%s", 2852 ent->d_name); 2853 2854 closedir(sysdir); 2855 return strdup(dev_name); 2856 } 2857 } 2858 return NULL; 2859 #else 2860 struct stat sbuf; 2861 char buf[PATH_MAX + 1]; 2862 const char *dev_name; 2863 unsigned int maj, min; 2864 int n, base; 2865 2866 if (fstat(fd, &sbuf)) 2867 return NULL; 2868 2869 maj = major(sbuf.st_rdev); 2870 min = minor(sbuf.st_rdev); 2871 2872 if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode)) 2873 return NULL; 2874 2875 switch (type) { 2876 case DRM_NODE_PRIMARY: 2877 dev_name = DRM_DEV_NAME; 2878 break; 2879 case DRM_NODE_CONTROL: 2880 dev_name = DRM_CONTROL_DEV_NAME; 2881 break; 2882 case DRM_NODE_RENDER: 2883 dev_name = DRM_RENDER_DEV_NAME; 2884 break; 2885 default: 2886 return NULL; 2887 }; 2888 2889 base = drmGetMinorBase(type); 2890 if (base < 0) 2891 return NULL; 2892 2893 n = snprintf(buf, sizeof(buf), dev_name, DRM_DIR_NAME, min - base); 2894 if (n == -1 || n >= sizeof(buf)) 2895 return NULL; 2896 2897 return strdup(buf); 2898 #endif 2899 } 2900 2901 char *drmGetPrimaryDeviceNameFromFd(int fd) 2902 { 2903 return drmGetMinorNameForFD(fd, DRM_NODE_PRIMARY); 2904 } 2905 2906 char *drmGetRenderDeviceNameFromFd(int fd) 2907 { 2908 return drmGetMinorNameForFD(fd, DRM_NODE_RENDER); 2909 } 2910 2911 #ifdef __linux__ 2912 static char * DRM_PRINTFLIKE(2, 3) 2913 sysfs_uevent_get(const char *path, const char *fmt, ...) 2914 { 2915 char filename[PATH_MAX + 1], *key, *line = NULL, *value = NULL; 2916 size_t size = 0, len; 2917 ssize_t num; 2918 va_list ap; 2919 FILE *fp; 2920 2921 va_start(ap, fmt); 2922 num = vasprintf(&key, fmt, ap); 2923 va_end(ap); 2924 len = num; 2925 2926 snprintf(filename, sizeof(filename), "%s/uevent", path); 2927 2928 fp = fopen(filename, "r"); 2929 if (!fp) { 2930 free(key); 2931 return NULL; 2932 } 2933 2934 while ((num = getline(&line, &size, fp)) >= 0) { 2935 if ((strncmp(line, key, len) == 0) && (line[len] == '=')) { 2936 char *start = line + len + 1, *end = line + num - 1; 2937 2938 if (*end != '\n') 2939 end++; 2940 2941 value = strndup(start, end - start); 2942 break; 2943 } 2944 } 2945 2946 free(line); 2947 fclose(fp); 2948 2949 free(key); 2950 2951 return value; 2952 } 2953 #endif 2954 2955 static int drmParseSubsystemType(int maj, int min) 2956 { 2957 #ifdef __linux__ 2958 char path[PATH_MAX + 1]; 2959 char link[PATH_MAX + 1] = ""; 2960 char *name; 2961 2962 snprintf(path, PATH_MAX, "/sys/dev/char/%d:%d/device/subsystem", 2963 maj, min); 2964 2965 if (readlink(path, link, PATH_MAX) < 0) 2966 return -errno; 2967 2968 name = strrchr(link, '/'); 2969 if (!name) 2970 return -EINVAL; 2971 2972 if (strncmp(name, "/pci", 4) == 0) 2973 return DRM_BUS_PCI; 2974 2975 if (strncmp(name, "/usb", 4) == 0) 2976 return DRM_BUS_USB; 2977 2978 if (strncmp(name, "/platform", 9) == 0) 2979 return DRM_BUS_PLATFORM; 2980 2981 if (strncmp(name, "/host1x", 7) == 0) 2982 return DRM_BUS_HOST1X; 2983 2984 return -EINVAL; 2985 #elif defined(__OpenBSD__) 2986 return DRM_BUS_PCI; 2987 #else 2988 #warning "Missing implementation of drmParseSubsystemType" 2989 return -EINVAL; 2990 #endif 2991 } 2992 2993 static int drmParsePciBusInfo(int maj, int min, drmPciBusInfoPtr info) 2994 { 2995 #ifdef __linux__ 2996 unsigned int domain, bus, dev, func; 2997 char path[PATH_MAX + 1], *value; 2998 int num; 2999 3000 snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min); 3001 3002 value = sysfs_uevent_get(path, "PCI_SLOT_NAME"); 3003 if (!value) 3004 return -ENOENT; 3005 3006 num = sscanf(value, "%04x:%02x:%02x.%1u", &domain, &bus, &dev, &func); 3007 free(value); 3008 3009 if (num != 4) 3010 return -EINVAL; 3011 3012 info->domain = domain; 3013 info->bus = bus; 3014 info->dev = dev; 3015 info->func = func; 3016 3017 return 0; 3018 #elif defined(__OpenBSD__) 3019 struct drm_pciinfo pinfo; 3020 int fd, type; 3021 3022 type = drmGetMinorType(min); 3023 if (type == -1) 3024 return -ENODEV; 3025 3026 fd = drmOpenMinor(min, 0, type); 3027 if (fd < 0) 3028 return -errno; 3029 3030 if (drmIoctl(fd, DRM_IOCTL_GET_PCIINFO, &pinfo)) { 3031 close(fd); 3032 return -errno; 3033 } 3034 close(fd); 3035 3036 info->domain = pinfo.domain; 3037 info->bus = pinfo.bus; 3038 info->dev = pinfo.dev; 3039 info->func = pinfo.func; 3040 3041 return 0; 3042 #else 3043 #warning "Missing implementation of drmParsePciBusInfo" 3044 return -EINVAL; 3045 #endif 3046 } 3047 3048 int drmDevicesEqual(drmDevicePtr a, drmDevicePtr b) 3049 { 3050 if (a == NULL || b == NULL) 3051 return 0; 3052 3053 if (a->bustype != b->bustype) 3054 return 0; 3055 3056 switch (a->bustype) { 3057 case DRM_BUS_PCI: 3058 return memcmp(a->businfo.pci, b->businfo.pci, sizeof(drmPciBusInfo)) == 0; 3059 3060 case DRM_BUS_USB: 3061 return memcmp(a->businfo.usb, b->businfo.usb, sizeof(drmUsbBusInfo)) == 0; 3062 3063 case DRM_BUS_PLATFORM: 3064 return memcmp(a->businfo.platform, b->businfo.platform, sizeof(drmPlatformBusInfo)) == 0; 3065 3066 case DRM_BUS_HOST1X: 3067 return memcmp(a->businfo.host1x, b->businfo.host1x, sizeof(drmHost1xBusInfo)) == 0; 3068 3069 default: 3070 break; 3071 } 3072 3073 return 0; 3074 } 3075 3076 static int drmGetNodeType(const char *name) 3077 { 3078 if (strncmp(name, DRM_PRIMARY_MINOR_NAME, 3079 sizeof(DRM_PRIMARY_MINOR_NAME) - 1) == 0) 3080 return DRM_NODE_PRIMARY; 3081 3082 if (strncmp(name, DRM_CONTROL_MINOR_NAME, 3083 sizeof(DRM_CONTROL_MINOR_NAME ) - 1) == 0) 3084 return DRM_NODE_CONTROL; 3085 3086 if (strncmp(name, DRM_RENDER_MINOR_NAME, 3087 sizeof(DRM_RENDER_MINOR_NAME) - 1) == 0) 3088 return DRM_NODE_RENDER; 3089 3090 return -EINVAL; 3091 } 3092 3093 static int drmGetMaxNodeName(void) 3094 { 3095 return sizeof(DRM_DIR_NAME) + 3096 MAX3(sizeof(DRM_PRIMARY_MINOR_NAME), 3097 sizeof(DRM_CONTROL_MINOR_NAME), 3098 sizeof(DRM_RENDER_MINOR_NAME)) + 3099 3 /* length of the node number */; 3100 } 3101 3102 #ifdef __linux__ 3103 static int parse_separate_sysfs_files(int maj, int min, 3104 drmPciDeviceInfoPtr device, 3105 bool ignore_revision) 3106 { 3107 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) 3108 static const char *attrs[] = { 3109 "revision", /* Older kernels are missing the file, so check for it first */ 3110 "vendor", 3111 "device", 3112 "subsystem_vendor", 3113 "subsystem_device", 3114 }; 3115 char path[PATH_MAX + 1]; 3116 unsigned int data[ARRAY_SIZE(attrs)]; 3117 FILE *fp; 3118 int ret; 3119 3120 for (unsigned i = ignore_revision ? 1 : 0; i < ARRAY_SIZE(attrs); i++) { 3121 snprintf(path, PATH_MAX, "/sys/dev/char/%d:%d/device/%s", maj, min, 3122 attrs[i]); 3123 fp = fopen(path, "r"); 3124 if (!fp) 3125 return -errno; 3126 3127 ret = fscanf(fp, "%x", &data[i]); 3128 fclose(fp); 3129 if (ret != 1) 3130 return -errno; 3131 3132 } 3133 3134 device->revision_id = ignore_revision ? 0xff : data[0] & 0xff; 3135 device->vendor_id = data[1] & 0xffff; 3136 device->device_id = data[2] & 0xffff; 3137 device->subvendor_id = data[3] & 0xffff; 3138 device->subdevice_id = data[4] & 0xffff; 3139 3140 return 0; 3141 } 3142 3143 static int parse_config_sysfs_file(int maj, int min, 3144 drmPciDeviceInfoPtr device) 3145 { 3146 char path[PATH_MAX + 1]; 3147 unsigned char config[64]; 3148 int fd, ret; 3149 3150 snprintf(path, PATH_MAX, "/sys/dev/char/%d:%d/device/config", maj, min); 3151 fd = open(path, O_RDONLY); 3152 if (fd < 0) 3153 return -errno; 3154 3155 ret = read(fd, config, sizeof(config)); 3156 close(fd); 3157 if (ret < 0) 3158 return -errno; 3159 3160 device->vendor_id = config[0] | (config[1] << 8); 3161 device->device_id = config[2] | (config[3] << 8); 3162 device->revision_id = config[8]; 3163 device->subvendor_id = config[44] | (config[45] << 8); 3164 device->subdevice_id = config[46] | (config[47] << 8); 3165 3166 return 0; 3167 } 3168 #endif 3169 3170 static int drmParsePciDeviceInfo(int maj, int min, 3171 drmPciDeviceInfoPtr device, 3172 uint32_t flags) 3173 { 3174 #ifdef __linux__ 3175 if (!(flags & DRM_DEVICE_GET_PCI_REVISION)) 3176 return parse_separate_sysfs_files(maj, min, device, true); 3177 3178 if (parse_separate_sysfs_files(maj, min, device, false)) 3179 return parse_config_sysfs_file(maj, min, device); 3180 3181 return 0; 3182 #elif defined(__OpenBSD__) 3183 struct drm_pciinfo pinfo; 3184 int fd, type; 3185 3186 type = drmGetMinorType(min); 3187 if (type == -1) 3188 return -ENODEV; 3189 3190 fd = drmOpenMinor(min, 0, type); 3191 if (fd < 0) 3192 return -errno; 3193 3194 if (drmIoctl(fd, DRM_IOCTL_GET_PCIINFO, &pinfo)) { 3195 close(fd); 3196 return -errno; 3197 } 3198 close(fd); 3199 3200 device->vendor_id = pinfo.vendor_id; 3201 device->device_id = pinfo.device_id; 3202 device->revision_id = pinfo.revision_id; 3203 device->subvendor_id = pinfo.subvendor_id; 3204 device->subdevice_id = pinfo.subdevice_id; 3205 3206 return 0; 3207 #else 3208 #warning "Missing implementation of drmParsePciDeviceInfo" 3209 return -EINVAL; 3210 #endif 3211 } 3212 3213 static void drmFreePlatformDevice(drmDevicePtr device) 3214 { 3215 if (device->deviceinfo.platform) { 3216 if (device->deviceinfo.platform->compatible) { 3217 char **compatible = device->deviceinfo.platform->compatible; 3218 3219 while (*compatible) { 3220 free(*compatible); 3221 compatible++; 3222 } 3223 3224 free(device->deviceinfo.platform->compatible); 3225 } 3226 } 3227 } 3228 3229 static void drmFreeHost1xDevice(drmDevicePtr device) 3230 { 3231 if (device->deviceinfo.host1x) { 3232 if (device->deviceinfo.host1x->compatible) { 3233 char **compatible = device->deviceinfo.host1x->compatible; 3234 3235 while (*compatible) { 3236 free(*compatible); 3237 compatible++; 3238 } 3239 3240 free(device->deviceinfo.host1x->compatible); 3241 } 3242 } 3243 } 3244 3245 void drmFreeDevice(drmDevicePtr *device) 3246 { 3247 if (device == NULL) 3248 return; 3249 3250 if (*device) { 3251 switch ((*device)->bustype) { 3252 case DRM_BUS_PLATFORM: 3253 drmFreePlatformDevice(*device); 3254 break; 3255 3256 case DRM_BUS_HOST1X: 3257 drmFreeHost1xDevice(*device); 3258 break; 3259 } 3260 } 3261 3262 free(*device); 3263 *device = NULL; 3264 } 3265 3266 void drmFreeDevices(drmDevicePtr devices[], int count) 3267 { 3268 int i; 3269 3270 if (devices == NULL) 3271 return; 3272 3273 for (i = 0; i < count; i++) 3274 if (devices[i]) 3275 drmFreeDevice(&devices[i]); 3276 } 3277 3278 static drmDevicePtr drmDeviceAlloc(unsigned int type, const char *node, 3279 size_t bus_size, size_t device_size, 3280 char **ptrp) 3281 { 3282 size_t max_node_length, extra, size; 3283 drmDevicePtr device; 3284 unsigned int i; 3285 char *ptr; 3286 3287 max_node_length = ALIGN(drmGetMaxNodeName(), sizeof(void *)); 3288 extra = DRM_NODE_MAX * (sizeof(void *) + max_node_length); 3289 3290 size = sizeof(*device) + extra + bus_size + device_size; 3291 3292 device = calloc(1, size); 3293 if (!device) 3294 return NULL; 3295 3296 device->available_nodes = 1 << type; 3297 3298 ptr = (char *)device + sizeof(*device); 3299 device->nodes = (char **)ptr; 3300 3301 ptr += DRM_NODE_MAX * sizeof(void *); 3302 3303 for (i = 0; i < DRM_NODE_MAX; i++) { 3304 device->nodes[i] = ptr; 3305 ptr += max_node_length; 3306 } 3307 3308 memcpy(device->nodes[type], node, max_node_length); 3309 3310 *ptrp = ptr; 3311 3312 return device; 3313 } 3314 3315 static int drmProcessPciDevice(drmDevicePtr *device, 3316 const char *node, int node_type, 3317 int maj, int min, bool fetch_deviceinfo, 3318 uint32_t flags) 3319 { 3320 drmDevicePtr dev; 3321 char *addr; 3322 int ret; 3323 3324 dev = drmDeviceAlloc(node_type, node, sizeof(drmPciBusInfo), 3325 sizeof(drmPciDeviceInfo), &addr); 3326 if (!dev) 3327 return -ENOMEM; 3328 3329 dev->bustype = DRM_BUS_PCI; 3330 3331 dev->businfo.pci = (drmPciBusInfoPtr)addr; 3332 3333 ret = drmParsePciBusInfo(maj, min, dev->businfo.pci); 3334 if (ret) 3335 goto free_device; 3336 3337 // Fetch the device info if the user has requested it 3338 if (fetch_deviceinfo) { 3339 addr += sizeof(drmPciBusInfo); 3340 dev->deviceinfo.pci = (drmPciDeviceInfoPtr)addr; 3341 3342 ret = drmParsePciDeviceInfo(maj, min, dev->deviceinfo.pci, flags); 3343 if (ret) 3344 goto free_device; 3345 } 3346 3347 *device = dev; 3348 3349 return 0; 3350 3351 free_device: 3352 free(dev); 3353 return ret; 3354 } 3355 3356 static int drmParseUsbBusInfo(int maj, int min, drmUsbBusInfoPtr info) 3357 { 3358 #ifdef __linux__ 3359 char path[PATH_MAX + 1], *value; 3360 unsigned int bus, dev; 3361 int ret; 3362 3363 snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min); 3364 3365 value = sysfs_uevent_get(path, "BUSNUM"); 3366 if (!value) 3367 return -ENOENT; 3368 3369 ret = sscanf(value, "%03u", &bus); 3370 free(value); 3371 3372 if (ret <= 0) 3373 return -errno; 3374 3375 value = sysfs_uevent_get(path, "DEVNUM"); 3376 if (!value) 3377 return -ENOENT; 3378 3379 ret = sscanf(value, "%03u", &dev); 3380 free(value); 3381 3382 if (ret <= 0) 3383 return -errno; 3384 3385 info->bus = bus; 3386 info->dev = dev; 3387 3388 return 0; 3389 #else 3390 #warning "Missing implementation of drmParseUsbBusInfo" 3391 return -EINVAL; 3392 #endif 3393 } 3394 3395 static int drmParseUsbDeviceInfo(int maj, int min, drmUsbDeviceInfoPtr info) 3396 { 3397 #ifdef __linux__ 3398 char path[PATH_MAX + 1], *value; 3399 unsigned int vendor, product; 3400 int ret; 3401 3402 snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min); 3403 3404 value = sysfs_uevent_get(path, "PRODUCT"); 3405 if (!value) 3406 return -ENOENT; 3407 3408 ret = sscanf(value, "%x/%x", &vendor, &product); 3409 free(value); 3410 3411 if (ret <= 0) 3412 return -errno; 3413 3414 info->vendor = vendor; 3415 info->product = product; 3416 3417 return 0; 3418 #else 3419 #warning "Missing implementation of drmParseUsbDeviceInfo" 3420 return -EINVAL; 3421 #endif 3422 } 3423 3424 static int drmProcessUsbDevice(drmDevicePtr *device, const char *node, 3425 int node_type, int maj, int min, 3426 bool fetch_deviceinfo, uint32_t flags) 3427 { 3428 drmDevicePtr dev; 3429 char *ptr; 3430 int ret; 3431 3432 dev = drmDeviceAlloc(node_type, node, sizeof(drmUsbBusInfo), 3433 sizeof(drmUsbDeviceInfo), &ptr); 3434 if (!dev) 3435 return -ENOMEM; 3436 3437 dev->bustype = DRM_BUS_USB; 3438 3439 dev->businfo.usb = (drmUsbBusInfoPtr)ptr; 3440 3441 ret = drmParseUsbBusInfo(maj, min, dev->businfo.usb); 3442 if (ret < 0) 3443 goto free_device; 3444 3445 if (fetch_deviceinfo) { 3446 ptr += sizeof(drmUsbBusInfo); 3447 dev->deviceinfo.usb = (drmUsbDeviceInfoPtr)ptr; 3448 3449 ret = drmParseUsbDeviceInfo(maj, min, dev->deviceinfo.usb); 3450 if (ret < 0) 3451 goto free_device; 3452 } 3453 3454 *device = dev; 3455 3456 return 0; 3457 3458 free_device: 3459 free(dev); 3460 return ret; 3461 } 3462 3463 static int drmParsePlatformBusInfo(int maj, int min, drmPlatformBusInfoPtr info) 3464 { 3465 #ifdef __linux__ 3466 char path[PATH_MAX + 1], *name; 3467 3468 snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min); 3469 3470 name = sysfs_uevent_get(path, "OF_FULLNAME"); 3471 if (!name) 3472 return -ENOENT; 3473 3474 strncpy(info->fullname, name, DRM_PLATFORM_DEVICE_NAME_LEN); 3475 info->fullname[DRM_PLATFORM_DEVICE_NAME_LEN - 1] = '\0'; 3476 free(name); 3477 3478 return 0; 3479 #else 3480 #warning "Missing implementation of drmParsePlatformBusInfo" 3481 return -EINVAL; 3482 #endif 3483 } 3484 3485 static int drmParsePlatformDeviceInfo(int maj, int min, 3486 drmPlatformDeviceInfoPtr info) 3487 { 3488 #ifdef __linux__ 3489 char path[PATH_MAX + 1], *value; 3490 unsigned int count, i; 3491 int err; 3492 3493 snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min); 3494 3495 value = sysfs_uevent_get(path, "OF_COMPATIBLE_N"); 3496 if (!value) 3497 return -ENOENT; 3498 3499 sscanf(value, "%u", &count); 3500 free(value); 3501 3502 info->compatible = calloc(count + 1, sizeof(*info->compatible)); 3503 if (!info->compatible) 3504 return -ENOMEM; 3505 3506 for (i = 0; i < count; i++) { 3507 value = sysfs_uevent_get(path, "OF_COMPATIBLE_%u", i); 3508 if (!value) { 3509 err = -ENOENT; 3510 goto free; 3511 } 3512 3513 info->compatible[i] = value; 3514 } 3515 3516 return 0; 3517 3518 free: 3519 while (i--) 3520 free(info->compatible[i]); 3521 3522 free(info->compatible); 3523 return err; 3524 #else 3525 #warning "Missing implementation of drmParsePlatformDeviceInfo" 3526 return -EINVAL; 3527 #endif 3528 } 3529 3530 static int drmProcessPlatformDevice(drmDevicePtr *device, 3531 const char *node, int node_type, 3532 int maj, int min, bool fetch_deviceinfo, 3533 uint32_t flags) 3534 { 3535 drmDevicePtr dev; 3536 char *ptr; 3537 int ret; 3538 3539 dev = drmDeviceAlloc(node_type, node, sizeof(drmPlatformBusInfo), 3540 sizeof(drmPlatformDeviceInfo), &ptr); 3541 if (!dev) 3542 return -ENOMEM; 3543 3544 dev->bustype = DRM_BUS_PLATFORM; 3545 3546 dev->businfo.platform = (drmPlatformBusInfoPtr)ptr; 3547 3548 ret = drmParsePlatformBusInfo(maj, min, dev->businfo.platform); 3549 if (ret < 0) 3550 goto free_device; 3551 3552 if (fetch_deviceinfo) { 3553 ptr += sizeof(drmPlatformBusInfo); 3554 dev->deviceinfo.platform = (drmPlatformDeviceInfoPtr)ptr; 3555 3556 ret = drmParsePlatformDeviceInfo(maj, min, dev->deviceinfo.platform); 3557 if (ret < 0) 3558 goto free_device; 3559 } 3560 3561 *device = dev; 3562 3563 return 0; 3564 3565 free_device: 3566 free(dev); 3567 return ret; 3568 } 3569 3570 static int drmParseHost1xBusInfo(int maj, int min, drmHost1xBusInfoPtr info) 3571 { 3572 #ifdef __linux__ 3573 char path[PATH_MAX + 1], *name; 3574 3575 snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min); 3576 3577 name = sysfs_uevent_get(path, "OF_FULLNAME"); 3578 if (!name) 3579 return -ENOENT; 3580 3581 strncpy(info->fullname, name, DRM_HOST1X_DEVICE_NAME_LEN); 3582 info->fullname[DRM_HOST1X_DEVICE_NAME_LEN - 1] = '\0'; 3583 free(name); 3584 3585 return 0; 3586 #else 3587 #warning "Missing implementation of drmParseHost1xBusInfo" 3588 return -EINVAL; 3589 #endif 3590 } 3591 3592 static int drmParseHost1xDeviceInfo(int maj, int min, 3593 drmHost1xDeviceInfoPtr info) 3594 { 3595 #ifdef __linux__ 3596 char path[PATH_MAX + 1], *value; 3597 unsigned int count, i; 3598 int err; 3599 3600 snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min); 3601 3602 value = sysfs_uevent_get(path, "OF_COMPATIBLE_N"); 3603 if (!value) 3604 return -ENOENT; 3605 3606 sscanf(value, "%u", &count); 3607 free(value); 3608 3609 info->compatible = calloc(count + 1, sizeof(*info->compatible)); 3610 if (!info->compatible) 3611 return -ENOMEM; 3612 3613 for (i = 0; i < count; i++) { 3614 value = sysfs_uevent_get(path, "OF_COMPATIBLE_%u", i); 3615 if (!value) { 3616 err = -ENOENT; 3617 goto free; 3618 } 3619 3620 info->compatible[i] = value; 3621 } 3622 3623 return 0; 3624 3625 free: 3626 while (i--) 3627 free(info->compatible[i]); 3628 3629 free(info->compatible); 3630 return err; 3631 #else 3632 #warning "Missing implementation of drmParseHost1xDeviceInfo" 3633 return -EINVAL; 3634 #endif 3635 } 3636 3637 static int drmProcessHost1xDevice(drmDevicePtr *device, 3638 const char *node, int node_type, 3639 int maj, int min, bool fetch_deviceinfo, 3640 uint32_t flags) 3641 { 3642 drmDevicePtr dev; 3643 char *ptr; 3644 int ret; 3645 3646 dev = drmDeviceAlloc(node_type, node, sizeof(drmHost1xBusInfo), 3647 sizeof(drmHost1xDeviceInfo), &ptr); 3648 if (!dev) 3649 return -ENOMEM; 3650 3651 dev->bustype = DRM_BUS_HOST1X; 3652 3653 dev->businfo.host1x = (drmHost1xBusInfoPtr)ptr; 3654 3655 ret = drmParseHost1xBusInfo(maj, min, dev->businfo.host1x); 3656 if (ret < 0) 3657 goto free_device; 3658 3659 if (fetch_deviceinfo) { 3660 ptr += sizeof(drmHost1xBusInfo); 3661 dev->deviceinfo.host1x = (drmHost1xDeviceInfoPtr)ptr; 3662 3663 ret = drmParseHost1xDeviceInfo(maj, min, dev->deviceinfo.host1x); 3664 if (ret < 0) 3665 goto free_device; 3666 } 3667 3668 *device = dev; 3669 3670 return 0; 3671 3672 free_device: 3673 free(dev); 3674 return ret; 3675 } 3676 3677 /* Consider devices located on the same bus as duplicate and fold the respective 3678 * entries into a single one. 3679 * 3680 * Note: this leaves "gaps" in the array, while preserving the length. 3681 */ 3682 static void drmFoldDuplicatedDevices(drmDevicePtr local_devices[], int count) 3683 { 3684 int node_type, i, j; 3685 3686 for (i = 0; i < count; i++) { 3687 for (j = i + 1; j < count; j++) { 3688 if (drmDevicesEqual(local_devices[i], local_devices[j])) { 3689 local_devices[i]->available_nodes |= local_devices[j]->available_nodes; 3690 node_type = log2(local_devices[j]->available_nodes); 3691 memcpy(local_devices[i]->nodes[node_type], 3692 local_devices[j]->nodes[node_type], drmGetMaxNodeName()); 3693 drmFreeDevice(&local_devices[j]); 3694 } 3695 } 3696 } 3697 } 3698 3699 /* Check that the given flags are valid returning 0 on success */ 3700 static int 3701 drm_device_validate_flags(uint32_t flags) 3702 { 3703 return (flags & ~DRM_DEVICE_GET_PCI_REVISION); 3704 } 3705 3706 /** 3707 * Get information about the opened drm device 3708 * 3709 * \param fd file descriptor of the drm device 3710 * \param flags feature/behaviour bitmask 3711 * \param device the address of a drmDevicePtr where the information 3712 * will be allocated in stored 3713 * 3714 * \return zero on success, negative error code otherwise. 3715 * 3716 * \note Unlike drmGetDevice it does not retrieve the pci device revision field 3717 * unless the DRM_DEVICE_GET_PCI_REVISION \p flag is set. 3718 */ 3719 int drmGetDevice2(int fd, uint32_t flags, drmDevicePtr *device) 3720 { 3721 #ifdef __OpenBSD__ 3722 /* 3723 * DRI device nodes on OpenBSD are not in their own directory, they reside 3724 * in /dev along with a large number of statically generated /dev nodes. 3725 * Avoid stat'ing all of /dev needlessly by implementing this custom path. 3726 */ 3727 drmDevicePtr d; 3728 struct stat sbuf; 3729 char node[PATH_MAX + 1]; 3730 const char *dev_name; 3731 int node_type, subsystem_type; 3732 int maj, min, n, ret, base; 3733 3734 if (fd == -1 || device == NULL) 3735 return -EINVAL; 3736 3737 if (fstat(fd, &sbuf)) 3738 return -errno; 3739 3740 maj = major(sbuf.st_rdev); 3741 min = minor(sbuf.st_rdev); 3742 3743 if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode)) 3744 return -EINVAL; 3745 3746 node_type = drmGetMinorType(min); 3747 if (node_type == -1) 3748 return -ENODEV; 3749 3750 switch (node_type) { 3751 case DRM_NODE_PRIMARY: 3752 dev_name = DRM_DEV_NAME; 3753 break; 3754 case DRM_NODE_CONTROL: 3755 dev_name = DRM_CONTROL_DEV_NAME; 3756 break; 3757 case DRM_NODE_RENDER: 3758 dev_name = DRM_RENDER_DEV_NAME; 3759 break; 3760 default: 3761 return -EINVAL; 3762 }; 3763 3764 base = drmGetMinorBase(node_type); 3765 if (base < 0) 3766 return -EINVAL; 3767 3768 n = snprintf(node, PATH_MAX, dev_name, DRM_DIR_NAME, min - base); 3769 if (n == -1 || n >= PATH_MAX) 3770 return -errno; 3771 if (stat(node, &sbuf)) 3772 return -EINVAL; 3773 3774 subsystem_type = drmParseSubsystemType(maj, min); 3775 if (subsystem_type != DRM_BUS_PCI) 3776 return -ENODEV; 3777 3778 ret = drmProcessPciDevice(&d, node, node_type, maj, min, true, flags); 3779 if (ret) 3780 return ret; 3781 3782 *device = d; 3783 3784 return 0; 3785 #else 3786 drmDevicePtr *local_devices; 3787 drmDevicePtr d; 3788 DIR *sysdir; 3789 struct dirent *dent; 3790 struct stat sbuf; 3791 char node[PATH_MAX + 1]; 3792 int node_type, subsystem_type; 3793 int maj, min; 3794 int ret, i, node_count; 3795 int max_count = 16; 3796 dev_t find_rdev; 3797 3798 if (drm_device_validate_flags(flags)) 3799 return -EINVAL; 3800 3801 if (fd == -1 || device == NULL) 3802 return -EINVAL; 3803 3804 if (fstat(fd, &sbuf)) 3805 return -errno; 3806 3807 find_rdev = sbuf.st_rdev; 3808 maj = major(sbuf.st_rdev); 3809 min = minor(sbuf.st_rdev); 3810 3811 if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode)) 3812 return -EINVAL; 3813 3814 subsystem_type = drmParseSubsystemType(maj, min); 3815 3816 local_devices = calloc(max_count, sizeof(drmDevicePtr)); 3817 if (local_devices == NULL) 3818 return -ENOMEM; 3819 3820 sysdir = opendir(DRM_DIR_NAME); 3821 if (!sysdir) { 3822 ret = -errno; 3823 goto free_locals; 3824 } 3825 3826 i = 0; 3827 while ((dent = readdir(sysdir))) { 3828 node_type = drmGetNodeType(dent->d_name); 3829 if (node_type < 0) 3830 continue; 3831 3832 snprintf(node, PATH_MAX, "%s/%s", DRM_DIR_NAME, dent->d_name); 3833 if (stat(node, &sbuf)) 3834 continue; 3835 3836 maj = major(sbuf.st_rdev); 3837 min = minor(sbuf.st_rdev); 3838 3839 if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode)) 3840 continue; 3841 3842 if (drmParseSubsystemType(maj, min) != subsystem_type) 3843 continue; 3844 3845 switch (subsystem_type) { 3846 case DRM_BUS_PCI: 3847 ret = drmProcessPciDevice(&d, node, node_type, maj, min, true, flags); 3848 if (ret) 3849 continue; 3850 3851 break; 3852 3853 case DRM_BUS_USB: 3854 ret = drmProcessUsbDevice(&d, node, node_type, maj, min, true, flags); 3855 if (ret) 3856 continue; 3857 3858 break; 3859 3860 case DRM_BUS_PLATFORM: 3861 ret = drmProcessPlatformDevice(&d, node, node_type, maj, min, true, flags); 3862 if (ret) 3863 continue; 3864 3865 break; 3866 3867 case DRM_BUS_HOST1X: 3868 ret = drmProcessHost1xDevice(&d, node, node_type, maj, min, true, flags); 3869 if (ret) 3870 continue; 3871 3872 break; 3873 3874 default: 3875 continue; 3876 } 3877 3878 if (i >= max_count) { 3879 drmDevicePtr *temp; 3880 3881 max_count += 16; 3882 temp = realloc(local_devices, max_count * sizeof(drmDevicePtr)); 3883 if (!temp) 3884 goto free_devices; 3885 local_devices = temp; 3886 } 3887 3888 /* store target at local_devices[0] for ease to use below */ 3889 if (find_rdev == sbuf.st_rdev && i) { 3890 local_devices[i] = local_devices[0]; 3891 local_devices[0] = d; 3892 } 3893 else 3894 local_devices[i] = d; 3895 i++; 3896 } 3897 node_count = i; 3898 3899 drmFoldDuplicatedDevices(local_devices, node_count); 3900 3901 *device = local_devices[0]; 3902 drmFreeDevices(&local_devices[1], node_count - 1); 3903 3904 closedir(sysdir); 3905 free(local_devices); 3906 if (*device == NULL) 3907 return -ENODEV; 3908 return 0; 3909 3910 free_devices: 3911 drmFreeDevices(local_devices, i); 3912 closedir(sysdir); 3913 3914 free_locals: 3915 free(local_devices); 3916 return ret; 3917 #endif 3918 } 3919 3920 /** 3921 * Get information about the opened drm device 3922 * 3923 * \param fd file descriptor of the drm device 3924 * \param device the address of a drmDevicePtr where the information 3925 * will be allocated in stored 3926 * 3927 * \return zero on success, negative error code otherwise. 3928 */ 3929 int drmGetDevice(int fd, drmDevicePtr *device) 3930 { 3931 return drmGetDevice2(fd, DRM_DEVICE_GET_PCI_REVISION, device); 3932 } 3933 3934 /** 3935 * Get drm devices on the system 3936 * 3937 * \param flags feature/behaviour bitmask 3938 * \param devices the array of devices with drmDevicePtr elements 3939 * can be NULL to get the device number first 3940 * \param max_devices the maximum number of devices for the array 3941 * 3942 * \return on error - negative error code, 3943 * if devices is NULL - total number of devices available on the system, 3944 * alternatively the number of devices stored in devices[], which is 3945 * capped by the max_devices. 3946 * 3947 * \note Unlike drmGetDevices it does not retrieve the pci device revision field 3948 * unless the DRM_DEVICE_GET_PCI_REVISION \p flag is set. 3949 */ 3950 int drmGetDevices2(uint32_t flags, drmDevicePtr devices[], int max_devices) 3951 { 3952 drmDevicePtr *local_devices; 3953 drmDevicePtr device; 3954 DIR *sysdir; 3955 struct dirent *dent; 3956 struct stat sbuf; 3957 char node[PATH_MAX + 1]; 3958 int node_type, subsystem_type; 3959 int maj, min; 3960 int ret, i, node_count, device_count; 3961 int max_count = 16; 3962 3963 if (drm_device_validate_flags(flags)) 3964 return -EINVAL; 3965 3966 local_devices = calloc(max_count, sizeof(drmDevicePtr)); 3967 if (local_devices == NULL) 3968 return -ENOMEM; 3969 3970 sysdir = opendir(DRM_DIR_NAME); 3971 if (!sysdir) { 3972 ret = -errno; 3973 goto free_locals; 3974 } 3975 3976 i = 0; 3977 while ((dent = readdir(sysdir))) { 3978 node_type = drmGetNodeType(dent->d_name); 3979 if (node_type < 0) 3980 continue; 3981 3982 snprintf(node, PATH_MAX, "%s/%s", DRM_DIR_NAME, dent->d_name); 3983 if (stat(node, &sbuf)) 3984 continue; 3985 3986 maj = major(sbuf.st_rdev); 3987 min = minor(sbuf.st_rdev); 3988 3989 if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode)) 3990 continue; 3991 3992 subsystem_type = drmParseSubsystemType(maj, min); 3993 3994 if (subsystem_type < 0) 3995 continue; 3996 3997 switch (subsystem_type) { 3998 case DRM_BUS_PCI: 3999 ret = drmProcessPciDevice(&device, node, node_type, 4000 maj, min, devices != NULL, flags); 4001 if (ret) 4002 continue; 4003 4004 break; 4005 4006 case DRM_BUS_USB: 4007 ret = drmProcessUsbDevice(&device, node, node_type, maj, min, 4008 devices != NULL, flags); 4009 if (ret) 4010 continue; 4011 4012 break; 4013 4014 case DRM_BUS_PLATFORM: 4015 ret = drmProcessPlatformDevice(&device, node, node_type, maj, min, 4016 devices != NULL, flags); 4017 if (ret) 4018 continue; 4019 4020 break; 4021 4022 case DRM_BUS_HOST1X: 4023 ret = drmProcessHost1xDevice(&device, node, node_type, maj, min, 4024 devices != NULL, flags); 4025 if (ret) 4026 continue; 4027 4028 break; 4029 4030 default: 4031 continue; 4032 } 4033 4034 if (i >= max_count) { 4035 drmDevicePtr *temp; 4036 4037 max_count += 16; 4038 temp = realloc(local_devices, max_count * sizeof(drmDevicePtr)); 4039 if (!temp) 4040 goto free_devices; 4041 local_devices = temp; 4042 } 4043 4044 local_devices[i] = device; 4045 i++; 4046 } 4047 node_count = i; 4048 4049 drmFoldDuplicatedDevices(local_devices, node_count); 4050 4051 device_count = 0; 4052 for (i = 0; i < node_count; i++) { 4053 if (!local_devices[i]) 4054 continue; 4055 4056 if ((devices != NULL) && (device_count < max_devices)) 4057 devices[device_count] = local_devices[i]; 4058 else 4059 drmFreeDevice(&local_devices[i]); 4060 4061 device_count++; 4062 } 4063 4064 closedir(sysdir); 4065 free(local_devices); 4066 return device_count; 4067 4068 free_devices: 4069 drmFreeDevices(local_devices, i); 4070 closedir(sysdir); 4071 4072 free_locals: 4073 free(local_devices); 4074 return ret; 4075 } 4076 4077 /** 4078 * Get drm devices on the system 4079 * 4080 * \param devices the array of devices with drmDevicePtr elements 4081 * can be NULL to get the device number first 4082 * \param max_devices the maximum number of devices for the array 4083 * 4084 * \return on error - negative error code, 4085 * if devices is NULL - total number of devices available on the system, 4086 * alternatively the number of devices stored in devices[], which is 4087 * capped by the max_devices. 4088 */ 4089 int drmGetDevices(drmDevicePtr devices[], int max_devices) 4090 { 4091 return drmGetDevices2(DRM_DEVICE_GET_PCI_REVISION, devices, max_devices); 4092 } 4093 4094 char *drmGetDeviceNameFromFd2(int fd) 4095 { 4096 #ifdef __linux__ 4097 struct stat sbuf; 4098 char path[PATH_MAX + 1], *value; 4099 unsigned int maj, min; 4100 4101 if (fstat(fd, &sbuf)) 4102 return NULL; 4103 4104 maj = major(sbuf.st_rdev); 4105 min = minor(sbuf.st_rdev); 4106 4107 if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode)) 4108 return NULL; 4109 4110 snprintf(path, sizeof(path), "/sys/dev/char/%d:%d", maj, min); 4111 4112 value = sysfs_uevent_get(path, "DEVNAME"); 4113 if (!value) 4114 return NULL; 4115 4116 snprintf(path, sizeof(path), "/dev/%s", value); 4117 free(value); 4118 4119 return strdup(path); 4120 #else 4121 struct stat sbuf; 4122 char node[PATH_MAX + 1]; 4123 const char *dev_name; 4124 int node_type; 4125 int maj, min, n, base; 4126 4127 if (fstat(fd, &sbuf)) 4128 return NULL; 4129 4130 maj = major(sbuf.st_rdev); 4131 min = minor(sbuf.st_rdev); 4132 4133 if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode)) 4134 return NULL; 4135 4136 node_type = drmGetMinorType(min); 4137 if (node_type == -1) 4138 return NULL; 4139 4140 switch (node_type) { 4141 case DRM_NODE_PRIMARY: 4142 dev_name = DRM_DEV_NAME; 4143 break; 4144 case DRM_NODE_CONTROL: 4145 dev_name = DRM_CONTROL_DEV_NAME; 4146 break; 4147 case DRM_NODE_RENDER: 4148 dev_name = DRM_RENDER_DEV_NAME; 4149 break; 4150 default: 4151 return NULL; 4152 }; 4153 4154 base = drmGetMinorBase(node_type); 4155 if (base < 0) 4156 return NULL; 4157 4158 n = snprintf(node, PATH_MAX, dev_name, DRM_DIR_NAME, min - base); 4159 if (n == -1 || n >= PATH_MAX) 4160 return NULL; 4161 4162 return strdup(node); 4163 #endif 4164 } 4165 4166 int drmSyncobjCreate(int fd, uint32_t flags, uint32_t *handle) 4167 { 4168 struct drm_syncobj_create args; 4169 int ret; 4170 4171 memclear(args); 4172 args.flags = flags; 4173 args.handle = 0; 4174 ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_CREATE, &args); 4175 if (ret) 4176 return ret; 4177 *handle = args.handle; 4178 return 0; 4179 } 4180 4181 int drmSyncobjDestroy(int fd, uint32_t handle) 4182 { 4183 struct drm_syncobj_destroy args; 4184 4185 memclear(args); 4186 args.handle = handle; 4187 return drmIoctl(fd, DRM_IOCTL_SYNCOBJ_DESTROY, &args); 4188 } 4189 4190 int drmSyncobjHandleToFD(int fd, uint32_t handle, int *obj_fd) 4191 { 4192 struct drm_syncobj_handle args; 4193 int ret; 4194 4195 memclear(args); 4196 args.fd = -1; 4197 args.handle = handle; 4198 ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD, &args); 4199 if (ret) 4200 return ret; 4201 *obj_fd = args.fd; 4202 return 0; 4203 } 4204 4205 int drmSyncobjFDToHandle(int fd, int obj_fd, uint32_t *handle) 4206 { 4207 struct drm_syncobj_handle args; 4208 int ret; 4209 4210 memclear(args); 4211 args.fd = obj_fd; 4212 args.handle = 0; 4213 ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, &args); 4214 if (ret) 4215 return ret; 4216 *handle = args.handle; 4217 return 0; 4218 } 4219 4220 int drmSyncobjImportSyncFile(int fd, uint32_t handle, int sync_file_fd) 4221 { 4222 struct drm_syncobj_handle args; 4223 4224 memclear(args); 4225 args.fd = sync_file_fd; 4226 args.handle = handle; 4227 args.flags = DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE; 4228 return drmIoctl(fd, DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, &args); 4229 } 4230 4231 int drmSyncobjExportSyncFile(int fd, uint32_t handle, int *sync_file_fd) 4232 { 4233 struct drm_syncobj_handle args; 4234 int ret; 4235 4236 memclear(args); 4237 args.fd = -1; 4238 args.handle = handle; 4239 args.flags = DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE; 4240 ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD, &args); 4241 if (ret) 4242 return ret; 4243 *sync_file_fd = args.fd; 4244 return 0; 4245 } 4246 4247 int drmSyncobjWait(int fd, uint32_t *handles, unsigned num_handles, 4248 int64_t timeout_nsec, unsigned flags, 4249 uint32_t *first_signaled) 4250 { 4251 struct drm_syncobj_wait args; 4252 int ret; 4253 4254 memclear(args); 4255 args.handles = (uintptr_t)handles; 4256 args.timeout_nsec = timeout_nsec; 4257 args.count_handles = num_handles; 4258 args.flags = flags; 4259 4260 ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_WAIT, &args); 4261 if (ret < 0) 4262 return -errno; 4263 4264 if (first_signaled) 4265 *first_signaled = args.first_signaled; 4266 return ret; 4267 } 4268 4269 int drmSyncobjReset(int fd, const uint32_t *handles, uint32_t handle_count) 4270 { 4271 struct drm_syncobj_array args; 4272 int ret; 4273 4274 memclear(args); 4275 args.handles = (uintptr_t)handles; 4276 args.count_handles = handle_count; 4277 4278 ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_RESET, &args); 4279 return ret; 4280 } 4281 4282 int drmSyncobjSignal(int fd, const uint32_t *handles, uint32_t handle_count) 4283 { 4284 struct drm_syncobj_array args; 4285 int ret; 4286 4287 memclear(args); 4288 args.handles = (uintptr_t)handles; 4289 args.count_handles = handle_count; 4290 4291 ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_SIGNAL, &args); 4292 return ret; 4293 } 4294