OSDN Git Service

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