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