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