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