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