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