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