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