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