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