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