xf86drm.c revision 4545e80c
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 interupted 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 mesage 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 (!drmAvailable() && name != NULL && drm_server_info && 758 drm_server_info->load_module) { 759 /* try to load the kernel module */ 760 if (!drm_server_info->load_module(name)) { 761 drmMsg("[drm] failed to load kernel module \"%s\"\n", name); 762 return -1; 763 } 764 } 765 766 if (busid) { 767 int fd = drmOpenByBusid(busid, type); 768 if (fd >= 0) 769 return fd; 770 } 771 772 if (name) 773 return drmOpenByName(name, type); 774 775 return -1; 776} 777 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 sate of the hardware when the function 1466 * returns. 1467 * 1468 * \return always zero. 1469 * 1470 * \internal 1471 * This function translates the arguments into a drm_lock structure and issue 1472 * the DRM_IOCTL_LOCK ioctl until the lock is successfully acquired. 1473 */ 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 char *drmGetDeviceNameFromFd(int fd) 2751{ 2752 char name[128]; 2753 struct stat sbuf; 2754 dev_t d; 2755 int i; 2756 2757 /* The whole drmOpen thing is a fiasco and we need to find a way 2758 * back to just using open(2). For now, however, lets just make 2759 * things worse with even more ad hoc directory walking code to 2760 * discover the device file name. */ 2761 2762 fstat(fd, &sbuf); 2763 d = sbuf.st_rdev; 2764 2765 for (i = 0; i < DRM_MAX_MINOR; i++) { 2766 snprintf(name, sizeof name, DRM_DEV_NAME, DRM_DIR_NAME, i); 2767 if (stat(name, &sbuf) == 0 && sbuf.st_rdev == d) 2768 break; 2769 } 2770 if (i == DRM_MAX_MINOR) 2771 return NULL; 2772 2773 return strdup(name); 2774} 2775 2776static bool drmNodeIsDRM(int maj, int min) 2777{ 2778#ifdef __linux__ 2779 char path[64]; 2780 struct stat sbuf; 2781 2782 snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device/drm", 2783 maj, min); 2784 return stat(path, &sbuf) == 0; 2785#else 2786 return maj == DRM_MAJOR; 2787#endif 2788} 2789 2790drm_public int drmGetNodeTypeFromFd(int fd) 2791{ 2792 struct stat sbuf; 2793 int maj, min, type; 2794 2795 if (fstat(fd, &sbuf)) 2796 return -1; 2797 2798 maj = major(sbuf.st_rdev); 2799 min = minor(sbuf.st_rdev); 2800 2801 if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode)) { 2802 errno = EINVAL; 2803 return -1; 2804 } 2805 2806 type = drmGetMinorType(min); 2807 if (type == -1) 2808 errno = ENODEV; 2809 return type; 2810} 2811 2812drm_public int drmPrimeHandleToFD(int fd, uint32_t handle, uint32_t flags, 2813 int *prime_fd) 2814{ 2815 struct drm_prime_handle args; 2816 int ret; 2817 2818 memclear(args); 2819 args.fd = -1; 2820 args.handle = handle; 2821 args.flags = flags; 2822 ret = drmIoctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &args); 2823 if (ret) 2824 return ret; 2825 2826 *prime_fd = args.fd; 2827 return 0; 2828} 2829 2830drm_public int drmPrimeFDToHandle(int fd, int prime_fd, uint32_t *handle) 2831{ 2832 struct drm_prime_handle args; 2833 int ret; 2834 2835 memclear(args); 2836 args.fd = prime_fd; 2837 ret = drmIoctl(fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &args); 2838 if (ret) 2839 return ret; 2840 2841 *handle = args.handle; 2842 return 0; 2843} 2844 2845static char *drmGetMinorNameForFD(int fd, int type) 2846{ 2847#ifdef __linux__ 2848 DIR *sysdir; 2849 struct dirent *ent; 2850 struct stat sbuf; 2851 const char *name = drmGetMinorName(type); 2852 int len; 2853 char dev_name[64], buf[64]; 2854 int maj, min; 2855 2856 if (!name) 2857 return NULL; 2858 2859 len = strlen(name); 2860 2861 if (fstat(fd, &sbuf)) 2862 return NULL; 2863 2864 maj = major(sbuf.st_rdev); 2865 min = minor(sbuf.st_rdev); 2866 2867 if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode)) 2868 return NULL; 2869 2870 snprintf(buf, sizeof(buf), "/sys/dev/char/%d:%d/device/drm", maj, min); 2871 2872 sysdir = opendir(buf); 2873 if (!sysdir) 2874 return NULL; 2875 2876 while ((ent = readdir(sysdir))) { 2877 if (strncmp(ent->d_name, name, len) == 0) { 2878 snprintf(dev_name, sizeof(dev_name), DRM_DIR_NAME "/%s", 2879 ent->d_name); 2880 2881 closedir(sysdir); 2882 return strdup(dev_name); 2883 } 2884 } 2885 2886 closedir(sysdir); 2887 return NULL; 2888#else 2889 struct stat sbuf; 2890 char buf[PATH_MAX + 1]; 2891 const char *dev_name; 2892 unsigned int maj, min; 2893 int n, base; 2894 2895 if (fstat(fd, &sbuf)) 2896 return NULL; 2897 2898 maj = major(sbuf.st_rdev); 2899 min = minor(sbuf.st_rdev); 2900 2901 if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode)) 2902 return NULL; 2903 2904 switch (type) { 2905 case DRM_NODE_PRIMARY: 2906 dev_name = DRM_DEV_NAME; 2907 break; 2908 case DRM_NODE_CONTROL: 2909 dev_name = DRM_CONTROL_DEV_NAME; 2910 break; 2911 case DRM_NODE_RENDER: 2912 dev_name = DRM_RENDER_DEV_NAME; 2913 break; 2914 default: 2915 return NULL; 2916 }; 2917 2918 base = drmGetMinorBase(type); 2919 if (base < 0) 2920 return NULL; 2921 2922 n = snprintf(buf, sizeof(buf), dev_name, DRM_DIR_NAME, min - base); 2923 if (n == -1 || n >= sizeof(buf)) 2924 return NULL; 2925 2926 return strdup(buf); 2927#endif 2928} 2929 2930drm_public char *drmGetPrimaryDeviceNameFromFd(int fd) 2931{ 2932 return drmGetMinorNameForFD(fd, DRM_NODE_PRIMARY); 2933} 2934 2935drm_public char *drmGetRenderDeviceNameFromFd(int fd) 2936{ 2937 return drmGetMinorNameForFD(fd, DRM_NODE_RENDER); 2938} 2939 2940#ifdef __linux__ 2941static char * DRM_PRINTFLIKE(2, 3) 2942sysfs_uevent_get(const char *path, const char *fmt, ...) 2943{ 2944 char filename[PATH_MAX + 1], *key, *line = NULL, *value = NULL; 2945 size_t size = 0, len; 2946 ssize_t num; 2947 va_list ap; 2948 FILE *fp; 2949 2950 va_start(ap, fmt); 2951 num = vasprintf(&key, fmt, ap); 2952 va_end(ap); 2953 len = num; 2954 2955 snprintf(filename, sizeof(filename), "%s/uevent", path); 2956 2957 fp = fopen(filename, "r"); 2958 if (!fp) { 2959 free(key); 2960 return NULL; 2961 } 2962 2963 while ((num = getline(&line, &size, fp)) >= 0) { 2964 if ((strncmp(line, key, len) == 0) && (line[len] == '=')) { 2965 char *start = line + len + 1, *end = line + num - 1; 2966 2967 if (*end != '\n') 2968 end++; 2969 2970 value = strndup(start, end - start); 2971 break; 2972 } 2973 } 2974 2975 free(line); 2976 fclose(fp); 2977 2978 free(key); 2979 2980 return value; 2981} 2982#endif 2983 2984/* Little white lie to avoid major rework of the existing code */ 2985#define DRM_BUS_VIRTIO 0x10 2986 2987static int drmParseSubsystemType(int maj, int min) 2988{ 2989#ifdef __linux__ 2990 char path[PATH_MAX + 1]; 2991 char link[PATH_MAX + 1] = ""; 2992 char *name; 2993 struct { 2994 const char *name; 2995 int bus_type; 2996 } bus_types[] = { 2997 { "/pci", DRM_BUS_PCI }, 2998 { "/usb", DRM_BUS_USB }, 2999 { "/platform", DRM_BUS_PLATFORM }, 3000 { "/spi", DRM_BUS_PLATFORM }, 3001 { "/host1x", DRM_BUS_HOST1X }, 3002 { "/virtio", DRM_BUS_VIRTIO }, 3003 }; 3004 3005 snprintf(path, PATH_MAX, "/sys/dev/char/%d:%d/device/subsystem", 3006 maj, min); 3007 3008 if (readlink(path, link, PATH_MAX) < 0) 3009 return -errno; 3010 3011 name = strrchr(link, '/'); 3012 if (!name) 3013 return -EINVAL; 3014 3015 for (unsigned i = 0; i < ARRAY_SIZE(bus_types); i++) { 3016 if (strncmp(name, bus_types[i].name, strlen(bus_types[i].name)) == 0) 3017 return bus_types[i].bus_type; 3018 } 3019 3020 return -EINVAL; 3021#elif defined(__NetBSD__) 3022 int type, fd; 3023 drmSetVersion sv; 3024 char *buf; 3025 unsigned domain, bus, dev; 3026 int func; 3027 int ret; 3028 3029 /* Get the type of device we're looking for to pick the right pathname. */ 3030 type = drmGetMinorType(min); 3031 if (type == -1) 3032 return -ENODEV; 3033 3034 /* Open the device. Don't try to create it if it's not there. */ 3035 fd = drmOpenMinor(min, 0, type); 3036 if (fd < 0) 3037 return -errno; 3038 3039 /* 3040 * Set the interface version to 1.4 or 1.1, which has the effect of 3041 * populating the bus id for us. 3042 */ 3043 sv.drm_di_major = 1; 3044 sv.drm_di_minor = 4; 3045 sv.drm_dd_major = -1; 3046 sv.drm_dd_minor = -1; 3047 if (drmSetInterfaceVersion(fd, &sv)) { 3048 sv.drm_di_major = 1; 3049 sv.drm_di_minor = 1; 3050 sv.drm_dd_major = -1; 3051 sv.drm_dd_minor = -1; 3052 if (drmSetInterfaceVersion(fd, &sv)) { 3053 /* 3054 * We're probably not the master. Hope the master already 3055 * set the version to >=1.1 so that we can get the busid. 3056 */ 3057 } 3058 } 3059 3060 /* Get the bus id. */ 3061 buf = drmGetBusid(fd); 3062 3063 /* We're done with the device now. */ 3064 (void)close(fd); 3065 3066 /* If there is no bus id, fail. */ 3067 if (buf == NULL) 3068 return -ENODEV; 3069 3070 /* Find a string we know about; otherwise -EINVAL. */ 3071 ret = -EINVAL; 3072 if (strncmp(buf, "pci:", 4) == 0) 3073 ret = DRM_BUS_PCI; 3074 3075 /* We're done with the bus id. */ 3076 free(buf); 3077 3078 /* Success or not, we're done. */ 3079 return ret; 3080#elif defined(__OpenBSD__) || defined(__DragonFly__) 3081 return DRM_BUS_PCI; 3082#else 3083#warning "Missing implementation of drmParseSubsystemType" 3084 return -EINVAL; 3085#endif 3086} 3087 3088static void 3089get_pci_path(int maj, int min, char *pci_path) 3090{ 3091 char path[PATH_MAX + 1], *term; 3092 3093 snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min); 3094 if (!realpath(path, pci_path)) { 3095 strcpy(pci_path, path); 3096 return; 3097 } 3098 3099 term = strrchr(pci_path, '/'); 3100 if (term && strncmp(term, "/virtio", 7) == 0) 3101 *term = 0; 3102} 3103 3104static int drmParsePciBusInfo(int maj, int min, drmPciBusInfoPtr info) 3105{ 3106#ifdef __linux__ 3107 unsigned int domain, bus, dev, func; 3108 char pci_path[PATH_MAX + 1], *value; 3109 int num; 3110 3111 get_pci_path(maj, min, pci_path); 3112 3113 value = sysfs_uevent_get(pci_path, "PCI_SLOT_NAME"); 3114 if (!value) 3115 return -ENOENT; 3116 3117 num = sscanf(value, "%04x:%02x:%02x.%1u", &domain, &bus, &dev, &func); 3118 free(value); 3119 3120 if (num != 4) 3121 return -EINVAL; 3122 3123 info->domain = domain; 3124 info->bus = bus; 3125 info->dev = dev; 3126 info->func = func; 3127 3128 return 0; 3129#elif defined(__NetBSD__) 3130 int type, fd; 3131 drmSetVersion sv; 3132 char *buf; 3133 unsigned domain, bus, dev; 3134 int func; 3135 int ret; 3136 3137 /* Get the type of device we're looking for to pick the right pathname. */ 3138 type = drmGetMinorType(min); 3139 if (type == -1) 3140 return -ENODEV; 3141 3142 /* Open the device. Don't try to create it if it's not there. */ 3143 fd = drmOpenMinor(min, 0, type); 3144 if (fd < 0) 3145 return -errno; 3146 3147 /* 3148 * Set the interface version to 1.4 or 1.1, which has the effect of 3149 * populating the bus id for us. 3150 */ 3151 sv.drm_di_major = 1; 3152 sv.drm_di_minor = 4; 3153 sv.drm_dd_major = -1; 3154 sv.drm_dd_minor = -1; 3155 if (drmSetInterfaceVersion(fd, &sv)) { 3156 sv.drm_di_major = 1; 3157 sv.drm_di_minor = 1; 3158 sv.drm_dd_major = -1; 3159 sv.drm_dd_minor = -1; 3160 if (drmSetInterfaceVersion(fd, &sv)) { 3161 /* 3162 * We're probably not the master. Hope the master already 3163 * set the version to >=1.1 so that we can get the busid. 3164 */ 3165 } 3166 } 3167 3168 /* Get the bus id. */ 3169 buf = drmGetBusid(fd); 3170 3171 /* We're done with the device now. */ 3172 (void)close(fd); 3173 3174 /* If there is no bus id, fail. */ 3175 if (buf == NULL) 3176 return -ENODEV; 3177 3178 /* Parse the bus id. */ 3179 ret = sscanf(buf, "pci:%04x:%02x:%02x.%d", &domain, &bus, &dev, &func); 3180 3181 /* We're done with the bus id. */ 3182 free(buf); 3183 3184 /* If scanf didn't return 4 -- domain, bus, dev, func -- then fail. */ 3185 if (ret != 4) 3186 return -ENODEV; 3187 3188 /* Populate the results. */ 3189 info->domain = domain; 3190 info->bus = bus; 3191 info->dev = dev; 3192 info->func = func; 3193 3194 /* Success! */ 3195 return 0; 3196#elif defined(__OpenBSD__) || defined(__DragonFly__) 3197 struct drm_pciinfo pinfo; 3198 int fd, type; 3199 3200 type = drmGetMinorType(min); 3201 if (type == -1) 3202 return -ENODEV; 3203 3204 fd = drmOpenMinor(min, 0, type); 3205 if (fd < 0) 3206 return -errno; 3207 3208 if (drmIoctl(fd, DRM_IOCTL_GET_PCIINFO, &pinfo)) { 3209 close(fd); 3210 return -errno; 3211 } 3212 close(fd); 3213 3214 info->domain = pinfo.domain; 3215 info->bus = pinfo.bus; 3216 info->dev = pinfo.dev; 3217 info->func = pinfo.func; 3218 3219 return 0; 3220#else 3221#warning "Missing implementation of drmParsePciBusInfo" 3222 return -EINVAL; 3223#endif 3224} 3225 3226drm_public int drmDevicesEqual(drmDevicePtr a, drmDevicePtr b) 3227{ 3228 if (a == NULL || b == NULL) 3229 return 0; 3230 3231 if (a->bustype != b->bustype) 3232 return 0; 3233 3234 switch (a->bustype) { 3235 case DRM_BUS_PCI: 3236 return memcmp(a->businfo.pci, b->businfo.pci, sizeof(drmPciBusInfo)) == 0; 3237 3238 case DRM_BUS_USB: 3239 return memcmp(a->businfo.usb, b->businfo.usb, sizeof(drmUsbBusInfo)) == 0; 3240 3241 case DRM_BUS_PLATFORM: 3242 return memcmp(a->businfo.platform, b->businfo.platform, sizeof(drmPlatformBusInfo)) == 0; 3243 3244 case DRM_BUS_HOST1X: 3245 return memcmp(a->businfo.host1x, b->businfo.host1x, sizeof(drmHost1xBusInfo)) == 0; 3246 3247 default: 3248 break; 3249 } 3250 3251 return 0; 3252} 3253 3254static int drmGetNodeType(const char *name) 3255{ 3256 if (strncmp(name, DRM_PRIMARY_MINOR_NAME, 3257 sizeof(DRM_PRIMARY_MINOR_NAME) - 1) == 0) 3258 return DRM_NODE_PRIMARY; 3259 3260 if (strncmp(name, DRM_CONTROL_MINOR_NAME, 3261 sizeof(DRM_CONTROL_MINOR_NAME ) - 1) == 0) 3262 return DRM_NODE_CONTROL; 3263 3264 if (strncmp(name, DRM_RENDER_MINOR_NAME, 3265 sizeof(DRM_RENDER_MINOR_NAME) - 1) == 0) 3266 return DRM_NODE_RENDER; 3267 3268 return -EINVAL; 3269} 3270 3271static int drmGetMaxNodeName(void) 3272{ 3273 return sizeof(DRM_DIR_NAME) + 3274 MAX3(sizeof(DRM_PRIMARY_MINOR_NAME), 3275 sizeof(DRM_CONTROL_MINOR_NAME), 3276 sizeof(DRM_RENDER_MINOR_NAME)) + 3277 3 /* length of the node number */; 3278} 3279 3280#ifdef __linux__ 3281static int parse_separate_sysfs_files(int maj, int min, 3282 drmPciDeviceInfoPtr device, 3283 bool ignore_revision) 3284{ 3285 static const char *attrs[] = { 3286 "revision", /* Older kernels are missing the file, so check for it first */ 3287 "vendor", 3288 "device", 3289 "subsystem_vendor", 3290 "subsystem_device", 3291 }; 3292 char path[PATH_MAX + 1], pci_path[PATH_MAX + 1]; 3293 unsigned int data[ARRAY_SIZE(attrs)]; 3294 FILE *fp; 3295 int ret; 3296 3297 get_pci_path(maj, min, pci_path); 3298 3299 for (unsigned i = ignore_revision ? 1 : 0; i < ARRAY_SIZE(attrs); i++) { 3300 snprintf(path, PATH_MAX, "%s/%s", pci_path, attrs[i]); 3301 fp = fopen(path, "r"); 3302 if (!fp) 3303 return -errno; 3304 3305 ret = fscanf(fp, "%x", &data[i]); 3306 fclose(fp); 3307 if (ret != 1) 3308 return -errno; 3309 3310 } 3311 3312 device->revision_id = ignore_revision ? 0xff : data[0] & 0xff; 3313 device->vendor_id = data[1] & 0xffff; 3314 device->device_id = data[2] & 0xffff; 3315 device->subvendor_id = data[3] & 0xffff; 3316 device->subdevice_id = data[4] & 0xffff; 3317 3318 return 0; 3319} 3320 3321static int parse_config_sysfs_file(int maj, int min, 3322 drmPciDeviceInfoPtr device) 3323{ 3324 char path[PATH_MAX + 1], pci_path[PATH_MAX + 1]; 3325 unsigned char config[64]; 3326 int fd, ret; 3327 3328 get_pci_path(maj, min, pci_path); 3329 3330 snprintf(path, PATH_MAX, "%s/config", pci_path); 3331 fd = open(path, O_RDONLY); 3332 if (fd < 0) 3333 return -errno; 3334 3335 ret = read(fd, config, sizeof(config)); 3336 close(fd); 3337 if (ret < 0) 3338 return -errno; 3339 3340 device->vendor_id = config[0] | (config[1] << 8); 3341 device->device_id = config[2] | (config[3] << 8); 3342 device->revision_id = config[8]; 3343 device->subvendor_id = config[44] | (config[45] << 8); 3344 device->subdevice_id = config[46] | (config[47] << 8); 3345 3346 return 0; 3347} 3348#endif 3349 3350static int drmParsePciDeviceInfo(int maj, int min, 3351 drmPciDeviceInfoPtr device, 3352 uint32_t flags) 3353{ 3354#ifdef __linux__ 3355 if (!(flags & DRM_DEVICE_GET_PCI_REVISION)) 3356 return parse_separate_sysfs_files(maj, min, device, true); 3357 3358 if (parse_separate_sysfs_files(maj, min, device, false)) 3359 return parse_config_sysfs_file(maj, min, device); 3360 3361 return 0; 3362#elif defined(__NetBSD__) 3363 drmPciBusInfo businfo; 3364 char fname[PATH_MAX]; 3365 int pcifd; 3366 pcireg_t id, class, subsys; 3367 int ret; 3368 3369 /* Find where on the bus the device lives. */ 3370 ret = drmParsePciBusInfo(maj, min, &businfo); 3371 if (ret) 3372 return ret; 3373 3374 /* Open the pciN device node to get at its config registers. */ 3375 if (snprintf(fname, sizeof fname, "/dev/pci%u", businfo.domain) 3376 >= sizeof fname) 3377 return -ENODEV; 3378 if ((pcifd = open(fname, O_RDONLY)) == -1) 3379 return -errno; 3380 3381 ret = -1; 3382 /* Read the id and class pci config registers. */ 3383 if (pcibus_conf_read(pcifd, businfo.bus, businfo.dev, businfo.func, 3384 PCI_ID_REG, &id) == -1) 3385 goto out; 3386 if (pcibus_conf_read(pcifd, businfo.bus, businfo.dev, businfo.func, 3387 PCI_CLASS_REG, &class) == -1) 3388 goto out; 3389 if (pcibus_conf_read(pcifd, businfo.bus, businfo.dev, businfo.func, 3390 PCI_SUBSYS_ID_REG, &subsys) == -1) 3391 goto out; 3392 3393 ret = 0; 3394 device->vendor_id = PCI_VENDOR(id); 3395 device->device_id = PCI_PRODUCT(id); 3396 device->subvendor_id = PCI_SUBSYS_VENDOR(subsys); 3397 device->subdevice_id = PCI_SUBSYS_ID(subsys); 3398 device->revision_id = PCI_REVISION(class); 3399out: 3400 if (ret == -1) 3401 ret = -errno; 3402 close(pcifd); 3403 return ret; 3404#elif defined(__OpenBSD__) || defined(__DragonFly__) 3405 struct drm_pciinfo pinfo; 3406 int fd, type; 3407 3408 type = drmGetMinorType(min); 3409 if (type == -1) 3410 return -ENODEV; 3411 3412 fd = drmOpenMinor(min, 0, type); 3413 if (fd < 0) 3414 return -errno; 3415 3416 if (drmIoctl(fd, DRM_IOCTL_GET_PCIINFO, &pinfo)) { 3417 close(fd); 3418 return -errno; 3419 } 3420 close(fd); 3421 3422 device->vendor_id = pinfo.vendor_id; 3423 device->device_id = pinfo.device_id; 3424 device->revision_id = pinfo.revision_id; 3425 device->subvendor_id = pinfo.subvendor_id; 3426 device->subdevice_id = pinfo.subdevice_id; 3427 3428 return 0; 3429#else 3430#warning "Missing implementation of drmParsePciDeviceInfo" 3431 return -EINVAL; 3432#endif 3433} 3434 3435static void drmFreePlatformDevice(drmDevicePtr device) 3436{ 3437 if (device->deviceinfo.platform) { 3438 if (device->deviceinfo.platform->compatible) { 3439 char **compatible = device->deviceinfo.platform->compatible; 3440 3441 while (*compatible) { 3442 free(*compatible); 3443 compatible++; 3444 } 3445 3446 free(device->deviceinfo.platform->compatible); 3447 } 3448 } 3449} 3450 3451static void drmFreeHost1xDevice(drmDevicePtr device) 3452{ 3453 if (device->deviceinfo.host1x) { 3454 if (device->deviceinfo.host1x->compatible) { 3455 char **compatible = device->deviceinfo.host1x->compatible; 3456 3457 while (*compatible) { 3458 free(*compatible); 3459 compatible++; 3460 } 3461 3462 free(device->deviceinfo.host1x->compatible); 3463 } 3464 } 3465} 3466 3467drm_public void drmFreeDevice(drmDevicePtr *device) 3468{ 3469 if (device == NULL) 3470 return; 3471 3472 if (*device) { 3473 switch ((*device)->bustype) { 3474 case DRM_BUS_PLATFORM: 3475 drmFreePlatformDevice(*device); 3476 break; 3477 3478 case DRM_BUS_HOST1X: 3479 drmFreeHost1xDevice(*device); 3480 break; 3481 } 3482 } 3483 3484 free(*device); 3485 *device = NULL; 3486} 3487 3488drm_public void drmFreeDevices(drmDevicePtr devices[], int count) 3489{ 3490 int i; 3491 3492 if (devices == NULL) 3493 return; 3494 3495 for (i = 0; i < count; i++) 3496 if (devices[i]) 3497 drmFreeDevice(&devices[i]); 3498} 3499 3500static drmDevicePtr drmDeviceAlloc(unsigned int type, const char *node, 3501 size_t bus_size, size_t device_size, 3502 char **ptrp) 3503{ 3504 size_t max_node_length, extra, size; 3505 drmDevicePtr device; 3506 unsigned int i; 3507 char *ptr; 3508 3509 max_node_length = ALIGN(drmGetMaxNodeName(), sizeof(void *)); 3510 extra = DRM_NODE_MAX * (sizeof(void *) + max_node_length); 3511 3512 size = sizeof(*device) + extra + bus_size + device_size; 3513 3514 device = calloc(1, size); 3515 if (!device) 3516 return NULL; 3517 3518 device->available_nodes = 1 << type; 3519 3520 ptr = (char *)device + sizeof(*device); 3521 device->nodes = (char **)ptr; 3522 3523 ptr += DRM_NODE_MAX * sizeof(void *); 3524 3525 for (i = 0; i < DRM_NODE_MAX; i++) { 3526 device->nodes[i] = ptr; 3527 ptr += max_node_length; 3528 } 3529 3530 memcpy(device->nodes[type], node, max_node_length); 3531 3532 *ptrp = ptr; 3533 3534 return device; 3535} 3536 3537static int drmProcessPciDevice(drmDevicePtr *device, 3538 const char *node, int node_type, 3539 int maj, int min, bool fetch_deviceinfo, 3540 uint32_t flags) 3541{ 3542 drmDevicePtr dev; 3543 char *addr; 3544 int ret; 3545 3546 dev = drmDeviceAlloc(node_type, node, sizeof(drmPciBusInfo), 3547 sizeof(drmPciDeviceInfo), &addr); 3548 if (!dev) 3549 return -ENOMEM; 3550 3551 dev->bustype = DRM_BUS_PCI; 3552 3553 dev->businfo.pci = (drmPciBusInfoPtr)addr; 3554 3555 ret = drmParsePciBusInfo(maj, min, dev->businfo.pci); 3556 if (ret) 3557 goto free_device; 3558 3559 // Fetch the device info if the user has requested it 3560 if (fetch_deviceinfo) { 3561 addr += sizeof(drmPciBusInfo); 3562 dev->deviceinfo.pci = (drmPciDeviceInfoPtr)addr; 3563 3564 ret = drmParsePciDeviceInfo(maj, min, dev->deviceinfo.pci, flags); 3565 if (ret) 3566 goto free_device; 3567 } 3568 3569 *device = dev; 3570 3571 return 0; 3572 3573free_device: 3574 free(dev); 3575 return ret; 3576} 3577 3578static int drmParseUsbBusInfo(int maj, int min, drmUsbBusInfoPtr info) 3579{ 3580#ifdef __linux__ 3581 char path[PATH_MAX + 1], *value; 3582 unsigned int bus, dev; 3583 int ret; 3584 3585 snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min); 3586 3587 value = sysfs_uevent_get(path, "BUSNUM"); 3588 if (!value) 3589 return -ENOENT; 3590 3591 ret = sscanf(value, "%03u", &bus); 3592 free(value); 3593 3594 if (ret <= 0) 3595 return -errno; 3596 3597 value = sysfs_uevent_get(path, "DEVNUM"); 3598 if (!value) 3599 return -ENOENT; 3600 3601 ret = sscanf(value, "%03u", &dev); 3602 free(value); 3603 3604 if (ret <= 0) 3605 return -errno; 3606 3607 info->bus = bus; 3608 info->dev = dev; 3609 3610 return 0; 3611#else 3612#warning "Missing implementation of drmParseUsbBusInfo" 3613 return -EINVAL; 3614#endif 3615} 3616 3617static int drmParseUsbDeviceInfo(int maj, int min, drmUsbDeviceInfoPtr info) 3618{ 3619#ifdef __linux__ 3620 char path[PATH_MAX + 1], *value; 3621 unsigned int vendor, product; 3622 int ret; 3623 3624 snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min); 3625 3626 value = sysfs_uevent_get(path, "PRODUCT"); 3627 if (!value) 3628 return -ENOENT; 3629 3630 ret = sscanf(value, "%x/%x", &vendor, &product); 3631 free(value); 3632 3633 if (ret <= 0) 3634 return -errno; 3635 3636 info->vendor = vendor; 3637 info->product = product; 3638 3639 return 0; 3640#else 3641#warning "Missing implementation of drmParseUsbDeviceInfo" 3642 return -EINVAL; 3643#endif 3644} 3645 3646static int drmProcessUsbDevice(drmDevicePtr *device, const char *node, 3647 int node_type, int maj, int min, 3648 bool fetch_deviceinfo, uint32_t flags) 3649{ 3650 drmDevicePtr dev; 3651 char *ptr; 3652 int ret; 3653 3654 dev = drmDeviceAlloc(node_type, node, sizeof(drmUsbBusInfo), 3655 sizeof(drmUsbDeviceInfo), &ptr); 3656 if (!dev) 3657 return -ENOMEM; 3658 3659 dev->bustype = DRM_BUS_USB; 3660 3661 dev->businfo.usb = (drmUsbBusInfoPtr)ptr; 3662 3663 ret = drmParseUsbBusInfo(maj, min, dev->businfo.usb); 3664 if (ret < 0) 3665 goto free_device; 3666 3667 if (fetch_deviceinfo) { 3668 ptr += sizeof(drmUsbBusInfo); 3669 dev->deviceinfo.usb = (drmUsbDeviceInfoPtr)ptr; 3670 3671 ret = drmParseUsbDeviceInfo(maj, min, dev->deviceinfo.usb); 3672 if (ret < 0) 3673 goto free_device; 3674 } 3675 3676 *device = dev; 3677 3678 return 0; 3679 3680free_device: 3681 free(dev); 3682 return ret; 3683} 3684 3685static int drmParsePlatformBusInfo(int maj, int min, drmPlatformBusInfoPtr info) 3686{ 3687#ifdef __linux__ 3688 char path[PATH_MAX + 1], *name; 3689 3690 snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min); 3691 3692 name = sysfs_uevent_get(path, "OF_FULLNAME"); 3693 if (!name) 3694 return -ENOENT; 3695 3696 strncpy(info->fullname, name, DRM_PLATFORM_DEVICE_NAME_LEN); 3697 info->fullname[DRM_PLATFORM_DEVICE_NAME_LEN - 1] = '\0'; 3698 free(name); 3699 3700 return 0; 3701#else 3702#warning "Missing implementation of drmParsePlatformBusInfo" 3703 return -EINVAL; 3704#endif 3705} 3706 3707static int drmParsePlatformDeviceInfo(int maj, int min, 3708 drmPlatformDeviceInfoPtr info) 3709{ 3710#ifdef __linux__ 3711 char path[PATH_MAX + 1], *value; 3712 unsigned int count, i; 3713 int err; 3714 3715 snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min); 3716 3717 value = sysfs_uevent_get(path, "OF_COMPATIBLE_N"); 3718 if (!value) 3719 return -ENOENT; 3720 3721 sscanf(value, "%u", &count); 3722 free(value); 3723 3724 info->compatible = calloc(count + 1, sizeof(*info->compatible)); 3725 if (!info->compatible) 3726 return -ENOMEM; 3727 3728 for (i = 0; i < count; i++) { 3729 value = sysfs_uevent_get(path, "OF_COMPATIBLE_%u", i); 3730 if (!value) { 3731 err = -ENOENT; 3732 goto free; 3733 } 3734 3735 info->compatible[i] = value; 3736 } 3737 3738 return 0; 3739 3740free: 3741 while (i--) 3742 free(info->compatible[i]); 3743 3744 free(info->compatible); 3745 return err; 3746#else 3747#warning "Missing implementation of drmParsePlatformDeviceInfo" 3748 return -EINVAL; 3749#endif 3750} 3751 3752static int drmProcessPlatformDevice(drmDevicePtr *device, 3753 const char *node, int node_type, 3754 int maj, int min, bool fetch_deviceinfo, 3755 uint32_t flags) 3756{ 3757 drmDevicePtr dev; 3758 char *ptr; 3759 int ret; 3760 3761 dev = drmDeviceAlloc(node_type, node, sizeof(drmPlatformBusInfo), 3762 sizeof(drmPlatformDeviceInfo), &ptr); 3763 if (!dev) 3764 return -ENOMEM; 3765 3766 dev->bustype = DRM_BUS_PLATFORM; 3767 3768 dev->businfo.platform = (drmPlatformBusInfoPtr)ptr; 3769 3770 ret = drmParsePlatformBusInfo(maj, min, dev->businfo.platform); 3771 if (ret < 0) 3772 goto free_device; 3773 3774 if (fetch_deviceinfo) { 3775 ptr += sizeof(drmPlatformBusInfo); 3776 dev->deviceinfo.platform = (drmPlatformDeviceInfoPtr)ptr; 3777 3778 ret = drmParsePlatformDeviceInfo(maj, min, dev->deviceinfo.platform); 3779 if (ret < 0) 3780 goto free_device; 3781 } 3782 3783 *device = dev; 3784 3785 return 0; 3786 3787free_device: 3788 free(dev); 3789 return ret; 3790} 3791 3792static int drmParseHost1xBusInfo(int maj, int min, drmHost1xBusInfoPtr info) 3793{ 3794#ifdef __linux__ 3795 char path[PATH_MAX + 1], *name; 3796 3797 snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min); 3798 3799 name = sysfs_uevent_get(path, "OF_FULLNAME"); 3800 if (!name) 3801 return -ENOENT; 3802 3803 strncpy(info->fullname, name, DRM_HOST1X_DEVICE_NAME_LEN); 3804 info->fullname[DRM_HOST1X_DEVICE_NAME_LEN - 1] = '\0'; 3805 free(name); 3806 3807 return 0; 3808#else 3809#warning "Missing implementation of drmParseHost1xBusInfo" 3810 return -EINVAL; 3811#endif 3812} 3813 3814static int drmParseHost1xDeviceInfo(int maj, int min, 3815 drmHost1xDeviceInfoPtr info) 3816{ 3817#ifdef __linux__ 3818 char path[PATH_MAX + 1], *value; 3819 unsigned int count, i; 3820 int err; 3821 3822 snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min); 3823 3824 value = sysfs_uevent_get(path, "OF_COMPATIBLE_N"); 3825 if (!value) 3826 return -ENOENT; 3827 3828 sscanf(value, "%u", &count); 3829 free(value); 3830 3831 info->compatible = calloc(count + 1, sizeof(*info->compatible)); 3832 if (!info->compatible) 3833 return -ENOMEM; 3834 3835 for (i = 0; i < count; i++) { 3836 value = sysfs_uevent_get(path, "OF_COMPATIBLE_%u", i); 3837 if (!value) { 3838 err = -ENOENT; 3839 goto free; 3840 } 3841 3842 info->compatible[i] = value; 3843 } 3844 3845 return 0; 3846 3847free: 3848 while (i--) 3849 free(info->compatible[i]); 3850 3851 free(info->compatible); 3852 return err; 3853#else 3854#warning "Missing implementation of drmParseHost1xDeviceInfo" 3855 return -EINVAL; 3856#endif 3857} 3858 3859static int drmProcessHost1xDevice(drmDevicePtr *device, 3860 const char *node, int node_type, 3861 int maj, int min, bool fetch_deviceinfo, 3862 uint32_t flags) 3863{ 3864 drmDevicePtr dev; 3865 char *ptr; 3866 int ret; 3867 3868 dev = drmDeviceAlloc(node_type, node, sizeof(drmHost1xBusInfo), 3869 sizeof(drmHost1xDeviceInfo), &ptr); 3870 if (!dev) 3871 return -ENOMEM; 3872 3873 dev->bustype = DRM_BUS_HOST1X; 3874 3875 dev->businfo.host1x = (drmHost1xBusInfoPtr)ptr; 3876 3877 ret = drmParseHost1xBusInfo(maj, min, dev->businfo.host1x); 3878 if (ret < 0) 3879 goto free_device; 3880 3881 if (fetch_deviceinfo) { 3882 ptr += sizeof(drmHost1xBusInfo); 3883 dev->deviceinfo.host1x = (drmHost1xDeviceInfoPtr)ptr; 3884 3885 ret = drmParseHost1xDeviceInfo(maj, min, dev->deviceinfo.host1x); 3886 if (ret < 0) 3887 goto free_device; 3888 } 3889 3890 *device = dev; 3891 3892 return 0; 3893 3894free_device: 3895 free(dev); 3896 return ret; 3897} 3898 3899static int 3900process_device(drmDevicePtr *device, const char *d_name, 3901 int req_subsystem_type, 3902 bool fetch_deviceinfo, uint32_t flags) 3903{ 3904 struct stat sbuf; 3905 char node[PATH_MAX + 1]; 3906 int node_type, subsystem_type; 3907 unsigned int maj, min; 3908 3909 node_type = drmGetNodeType(d_name); 3910 if (node_type < 0) 3911 return -1; 3912 3913 snprintf(node, PATH_MAX, "%s/%s", DRM_DIR_NAME, d_name); 3914 if (stat(node, &sbuf)) 3915 return -1; 3916 3917 maj = major(sbuf.st_rdev); 3918 min = minor(sbuf.st_rdev); 3919 3920 if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode)) 3921 return -1; 3922 3923 subsystem_type = drmParseSubsystemType(maj, min); 3924 if (req_subsystem_type != -1 && req_subsystem_type != subsystem_type) 3925 return -1; 3926 3927 switch (subsystem_type) { 3928 case DRM_BUS_PCI: 3929 case DRM_BUS_VIRTIO: 3930 return drmProcessPciDevice(device, node, node_type, maj, min, 3931 fetch_deviceinfo, flags); 3932 case DRM_BUS_USB: 3933 return drmProcessUsbDevice(device, node, node_type, maj, min, 3934 fetch_deviceinfo, flags); 3935 case DRM_BUS_PLATFORM: 3936 return drmProcessPlatformDevice(device, node, node_type, maj, min, 3937 fetch_deviceinfo, flags); 3938 case DRM_BUS_HOST1X: 3939 return drmProcessHost1xDevice(device, node, node_type, maj, min, 3940 fetch_deviceinfo, flags); 3941 default: 3942 return -1; 3943 } 3944} 3945 3946/* Consider devices located on the same bus as duplicate and fold the respective 3947 * entries into a single one. 3948 * 3949 * Note: this leaves "gaps" in the array, while preserving the length. 3950 */ 3951static void drmFoldDuplicatedDevices(drmDevicePtr local_devices[], int count) 3952{ 3953 int node_type, i, j; 3954 3955 for (i = 0; i < count; i++) { 3956 for (j = i + 1; j < count; j++) { 3957 if (drmDevicesEqual(local_devices[i], local_devices[j])) { 3958 local_devices[i]->available_nodes |= local_devices[j]->available_nodes; 3959 node_type = log2(local_devices[j]->available_nodes); 3960 memcpy(local_devices[i]->nodes[node_type], 3961 local_devices[j]->nodes[node_type], drmGetMaxNodeName()); 3962 drmFreeDevice(&local_devices[j]); 3963 } 3964 } 3965 } 3966} 3967 3968/* Check that the given flags are valid returning 0 on success */ 3969static int 3970drm_device_validate_flags(uint32_t flags) 3971{ 3972 return (flags & ~DRM_DEVICE_GET_PCI_REVISION); 3973} 3974 3975static bool 3976drm_device_has_rdev(drmDevicePtr device, dev_t find_rdev) 3977{ 3978 struct stat sbuf; 3979 3980 for (int i = 0; i < DRM_NODE_MAX; i++) { 3981 if (device->available_nodes & 1 << i) { 3982 if (stat(device->nodes[i], &sbuf) == 0 && 3983 sbuf.st_rdev == find_rdev) 3984 return true; 3985 } 3986 } 3987 return false; 3988} 3989 3990/* 3991 * The kernel drm core has a number of places that assume maximum of 3992 * 3x64 devices nodes. That's 64 for each of primary, control and 3993 * render nodes. Rounded it up to 256 for simplicity. 3994 */ 3995#define MAX_DRM_NODES 256 3996 3997/** 3998 * Get information about the opened drm device 3999 * 4000 * \param fd file descriptor of the drm device 4001 * \param flags feature/behaviour bitmask 4002 * \param device the address of a drmDevicePtr where the information 4003 * will be allocated in stored 4004 * 4005 * \return zero on success, negative error code otherwise. 4006 * 4007 * \note Unlike drmGetDevice it does not retrieve the pci device revision field 4008 * unless the DRM_DEVICE_GET_PCI_REVISION \p flag is set. 4009 */ 4010drm_public int drmGetDevice2(int fd, uint32_t flags, drmDevicePtr *device) 4011{ 4012#ifdef __OpenBSD__ 4013 /* 4014 * DRI device nodes on OpenBSD are not in their own directory, they reside 4015 * in /dev along with a large number of statically generated /dev nodes. 4016 * Avoid stat'ing all of /dev needlessly by implementing this custom path. 4017 */ 4018 drmDevicePtr d; 4019 struct stat sbuf; 4020 char node[PATH_MAX + 1]; 4021 const char *dev_name; 4022 int node_type, subsystem_type; 4023 int maj, min, n, ret, base; 4024 4025 if (fd == -1 || device == NULL) 4026 return -EINVAL; 4027 4028 if (fstat(fd, &sbuf)) 4029 return -errno; 4030 4031 maj = major(sbuf.st_rdev); 4032 min = minor(sbuf.st_rdev); 4033 4034 if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode)) 4035 return -EINVAL; 4036 4037 node_type = drmGetMinorType(min); 4038 if (node_type == -1) 4039 return -ENODEV; 4040 4041 switch (node_type) { 4042 case DRM_NODE_PRIMARY: 4043 dev_name = DRM_DEV_NAME; 4044 break; 4045 case DRM_NODE_CONTROL: 4046 dev_name = DRM_CONTROL_DEV_NAME; 4047 break; 4048 case DRM_NODE_RENDER: 4049 dev_name = DRM_RENDER_DEV_NAME; 4050 break; 4051 default: 4052 return -EINVAL; 4053 }; 4054 4055 base = drmGetMinorBase(node_type); 4056 if (base < 0) 4057 return -EINVAL; 4058 4059 n = snprintf(node, PATH_MAX, dev_name, DRM_DIR_NAME, min - base); 4060 if (n == -1 || n >= PATH_MAX) 4061 return -errno; 4062 if (stat(node, &sbuf)) 4063 return -EINVAL; 4064 4065 subsystem_type = drmParseSubsystemType(maj, min); 4066 if (subsystem_type != DRM_BUS_PCI) 4067 return -ENODEV; 4068 4069 ret = drmProcessPciDevice(&d, node, node_type, maj, min, true, flags); 4070 if (ret) 4071 return ret; 4072 4073 *device = d; 4074 4075 return 0; 4076#else 4077 drmDevicePtr local_devices[MAX_DRM_NODES]; 4078 drmDevicePtr d; 4079 DIR *sysdir; 4080 struct dirent *dent; 4081 struct stat sbuf; 4082 int subsystem_type; 4083 int maj, min; 4084 int ret, i, node_count; 4085 dev_t find_rdev; 4086 4087 if (drm_device_validate_flags(flags)) 4088 return -EINVAL; 4089 4090 if (fd == -1 || device == NULL) 4091 return -EINVAL; 4092 4093 if (fstat(fd, &sbuf)) 4094 return -errno; 4095 4096 find_rdev = sbuf.st_rdev; 4097 maj = major(sbuf.st_rdev); 4098 min = minor(sbuf.st_rdev); 4099 4100 if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode)) 4101 return -EINVAL; 4102 4103 subsystem_type = drmParseSubsystemType(maj, min); 4104 if (subsystem_type < 0) 4105 return subsystem_type; 4106 4107 sysdir = opendir(DRM_DIR_NAME); 4108 if (!sysdir) 4109 return -errno; 4110 4111 i = 0; 4112 while ((dent = readdir(sysdir))) { 4113 ret = process_device(&d, dent->d_name, subsystem_type, true, flags); 4114 if (ret) 4115 continue; 4116 4117 if (i >= MAX_DRM_NODES) { 4118 fprintf(stderr, "More than %d drm nodes detected. " 4119 "Please report a bug - that should not happen.\n" 4120 "Skipping extra nodes\n", MAX_DRM_NODES); 4121 break; 4122 } 4123 local_devices[i] = d; 4124 i++; 4125 } 4126 node_count = i; 4127 4128 drmFoldDuplicatedDevices(local_devices, node_count); 4129 4130 *device = NULL; 4131 4132 for (i = 0; i < node_count; i++) { 4133 if (!local_devices[i]) 4134 continue; 4135 4136 if (drm_device_has_rdev(local_devices[i], find_rdev)) 4137 *device = local_devices[i]; 4138 else 4139 drmFreeDevice(&local_devices[i]); 4140 } 4141 4142 closedir(sysdir); 4143 if (*device == NULL) 4144 return -ENODEV; 4145 return 0; 4146#endif 4147} 4148 4149/** 4150 * Get information about the opened drm device 4151 * 4152 * \param fd file descriptor of the drm device 4153 * \param device the address of a drmDevicePtr where the information 4154 * will be allocated in stored 4155 * 4156 * \return zero on success, negative error code otherwise. 4157 */ 4158drm_public int drmGetDevice(int fd, drmDevicePtr *device) 4159{ 4160 return drmGetDevice2(fd, DRM_DEVICE_GET_PCI_REVISION, device); 4161} 4162 4163/** 4164 * Get drm devices on the system 4165 * 4166 * \param flags feature/behaviour bitmask 4167 * \param devices the array of devices with drmDevicePtr elements 4168 * can be NULL to get the device number first 4169 * \param max_devices the maximum number of devices for the array 4170 * 4171 * \return on error - negative error code, 4172 * if devices is NULL - total number of devices available on the system, 4173 * alternatively the number of devices stored in devices[], which is 4174 * capped by the max_devices. 4175 * 4176 * \note Unlike drmGetDevices it does not retrieve the pci device revision field 4177 * unless the DRM_DEVICE_GET_PCI_REVISION \p flag is set. 4178 */ 4179drm_public int drmGetDevices2(uint32_t flags, drmDevicePtr devices[], 4180 int max_devices) 4181{ 4182 drmDevicePtr local_devices[MAX_DRM_NODES]; 4183 drmDevicePtr device; 4184 DIR *sysdir; 4185 struct dirent *dent; 4186 int ret, i, node_count, device_count; 4187 4188 if (drm_device_validate_flags(flags)) 4189 return -EINVAL; 4190 4191 sysdir = opendir(DRM_DIR_NAME); 4192 if (!sysdir) 4193 return -errno; 4194 4195 i = 0; 4196 while ((dent = readdir(sysdir))) { 4197 ret = process_device(&device, dent->d_name, -1, devices != NULL, flags); 4198 if (ret) 4199 continue; 4200 4201 if (i >= MAX_DRM_NODES) { 4202 fprintf(stderr, "More than %d drm nodes detected. " 4203 "Please report a bug - that should not happen.\n" 4204 "Skipping extra nodes\n", MAX_DRM_NODES); 4205 break; 4206 } 4207 local_devices[i] = device; 4208 i++; 4209 } 4210 node_count = i; 4211 4212 drmFoldDuplicatedDevices(local_devices, node_count); 4213 4214 device_count = 0; 4215 for (i = 0; i < node_count; i++) { 4216 if (!local_devices[i]) 4217 continue; 4218 4219 if ((devices != NULL) && (device_count < max_devices)) 4220 devices[device_count] = local_devices[i]; 4221 else 4222 drmFreeDevice(&local_devices[i]); 4223 4224 device_count++; 4225 } 4226 4227 closedir(sysdir); 4228 return device_count; 4229} 4230 4231/** 4232 * Get drm devices on the system 4233 * 4234 * \param devices the array of devices with drmDevicePtr elements 4235 * can be NULL to get the device number first 4236 * \param max_devices the maximum number of devices for the array 4237 * 4238 * \return on error - negative error code, 4239 * if devices is NULL - total number of devices available on the system, 4240 * alternatively the number of devices stored in devices[], which is 4241 * capped by the max_devices. 4242 */ 4243drm_public int drmGetDevices(drmDevicePtr devices[], int max_devices) 4244{ 4245 return drmGetDevices2(DRM_DEVICE_GET_PCI_REVISION, devices, max_devices); 4246} 4247 4248drm_public char *drmGetDeviceNameFromFd2(int fd) 4249{ 4250#ifdef __linux__ 4251 struct stat sbuf; 4252 char path[PATH_MAX + 1], *value; 4253 unsigned int maj, min; 4254 4255 if (fstat(fd, &sbuf)) 4256 return NULL; 4257 4258 maj = major(sbuf.st_rdev); 4259 min = minor(sbuf.st_rdev); 4260 4261 if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode)) 4262 return NULL; 4263 4264 snprintf(path, sizeof(path), "/sys/dev/char/%d:%d", maj, min); 4265 4266 value = sysfs_uevent_get(path, "DEVNAME"); 4267 if (!value) 4268 return NULL; 4269 4270 snprintf(path, sizeof(path), "/dev/%s", value); 4271 free(value); 4272 4273 return strdup(path); 4274#else 4275 struct stat sbuf; 4276 char node[PATH_MAX + 1]; 4277 const char *dev_name; 4278 int node_type; 4279 int maj, min, n, base; 4280 4281 if (fstat(fd, &sbuf)) 4282 return NULL; 4283 4284 maj = major(sbuf.st_rdev); 4285 min = minor(sbuf.st_rdev); 4286 4287 if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode)) 4288 return NULL; 4289 4290 node_type = drmGetMinorType(min); 4291 if (node_type == -1) 4292 return NULL; 4293 4294 switch (node_type) { 4295 case DRM_NODE_PRIMARY: 4296 dev_name = DRM_DEV_NAME; 4297 break; 4298 case DRM_NODE_CONTROL: 4299 dev_name = DRM_CONTROL_DEV_NAME; 4300 break; 4301 case DRM_NODE_RENDER: 4302 dev_name = DRM_RENDER_DEV_NAME; 4303 break; 4304 default: 4305 return NULL; 4306 }; 4307 4308 base = drmGetMinorBase(node_type); 4309 if (base < 0) 4310 return NULL; 4311 4312 n = snprintf(node, PATH_MAX, dev_name, DRM_DIR_NAME, min - base); 4313 if (n == -1 || n >= PATH_MAX) 4314 return NULL; 4315 4316 return strdup(node); 4317#endif 4318} 4319 4320drm_public int drmSyncobjCreate(int fd, uint32_t flags, uint32_t *handle) 4321{ 4322 struct drm_syncobj_create args; 4323 int ret; 4324 4325 memclear(args); 4326 args.flags = flags; 4327 args.handle = 0; 4328 ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_CREATE, &args); 4329 if (ret) 4330 return ret; 4331 *handle = args.handle; 4332 return 0; 4333} 4334 4335drm_public int drmSyncobjDestroy(int fd, uint32_t handle) 4336{ 4337 struct drm_syncobj_destroy args; 4338 4339 memclear(args); 4340 args.handle = handle; 4341 return drmIoctl(fd, DRM_IOCTL_SYNCOBJ_DESTROY, &args); 4342} 4343 4344drm_public int drmSyncobjHandleToFD(int fd, uint32_t handle, int *obj_fd) 4345{ 4346 struct drm_syncobj_handle args; 4347 int ret; 4348 4349 memclear(args); 4350 args.fd = -1; 4351 args.handle = handle; 4352 ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD, &args); 4353 if (ret) 4354 return ret; 4355 *obj_fd = args.fd; 4356 return 0; 4357} 4358 4359drm_public int drmSyncobjFDToHandle(int fd, int obj_fd, uint32_t *handle) 4360{ 4361 struct drm_syncobj_handle args; 4362 int ret; 4363 4364 memclear(args); 4365 args.fd = obj_fd; 4366 args.handle = 0; 4367 ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, &args); 4368 if (ret) 4369 return ret; 4370 *handle = args.handle; 4371 return 0; 4372} 4373 4374drm_public int drmSyncobjImportSyncFile(int fd, uint32_t handle, 4375 int sync_file_fd) 4376{ 4377 struct drm_syncobj_handle args; 4378 4379 memclear(args); 4380 args.fd = sync_file_fd; 4381 args.handle = handle; 4382 args.flags = DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE; 4383 return drmIoctl(fd, DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, &args); 4384} 4385 4386drm_public int drmSyncobjExportSyncFile(int fd, uint32_t handle, 4387 int *sync_file_fd) 4388{ 4389 struct drm_syncobj_handle args; 4390 int ret; 4391 4392 memclear(args); 4393 args.fd = -1; 4394 args.handle = handle; 4395 args.flags = DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE; 4396 ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD, &args); 4397 if (ret) 4398 return ret; 4399 *sync_file_fd = args.fd; 4400 return 0; 4401} 4402 4403drm_public int drmSyncobjWait(int fd, uint32_t *handles, unsigned num_handles, 4404 int64_t timeout_nsec, unsigned flags, 4405 uint32_t *first_signaled) 4406{ 4407 struct drm_syncobj_wait args; 4408 int ret; 4409 4410 memclear(args); 4411 args.handles = (uintptr_t)handles; 4412 args.timeout_nsec = timeout_nsec; 4413 args.count_handles = num_handles; 4414 args.flags = flags; 4415 4416 ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_WAIT, &args); 4417 if (ret < 0) 4418 return -errno; 4419 4420 if (first_signaled) 4421 *first_signaled = args.first_signaled; 4422 return ret; 4423} 4424 4425drm_public int drmSyncobjReset(int fd, const uint32_t *handles, 4426 uint32_t handle_count) 4427{ 4428 struct drm_syncobj_array args; 4429 int ret; 4430 4431 memclear(args); 4432 args.handles = (uintptr_t)handles; 4433 args.count_handles = handle_count; 4434 4435 ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_RESET, &args); 4436 return ret; 4437} 4438 4439drm_public int drmSyncobjSignal(int fd, const uint32_t *handles, 4440 uint32_t handle_count) 4441{ 4442 struct drm_syncobj_array args; 4443 int ret; 4444 4445 memclear(args); 4446 args.handles = (uintptr_t)handles; 4447 args.count_handles = handle_count; 4448 4449 ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_SIGNAL, &args); 4450 return ret; 4451} 4452