OSDN Git Service

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