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