OSDN Git Service

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