OSDN Git Service

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