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