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