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