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