OSDN Git Service

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