OSDN Git Service

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