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