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