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