OSDN Git Service

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