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