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