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