OSDN Git Service

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