drm/ttm: cleanup mm_ioctl ioctls to be separate ioctls.
[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     arg.op = drm_fence_create;
2276     if (ioctl(fd, DRM_IOCTL_FENCE, &arg))
2277         return -errno;
2278     fence->handle = arg.handle;
2279     fence->class = arg.class;
2280     fence->type = arg.type;
2281     fence->flags = arg.flags;
2282     fence->signaled = 0;
2283     return 0;
2284 }
2285
2286 /*
2287  * Valid flags are 
2288  * DRM_FENCE_FLAG_SHAREABLE
2289  * DRM_FENCE_MASK_DRIVER
2290  */
2291
2292 int drmFenceBuffers(int fd, unsigned flags, drmFence *fence)
2293 {
2294     drm_fence_arg_t arg;
2295     
2296     memset(&arg, 0, sizeof(arg));
2297     arg.flags = flags;
2298     arg.op = drm_fence_buffers;
2299     if (ioctl(fd, DRM_IOCTL_FENCE, &arg))
2300         return -errno;
2301     fence->handle = arg.handle;
2302     fence->class = arg.class;
2303     fence->type = arg.type;
2304     fence->flags = arg.flags;
2305     fence->signaled = 0;
2306     return 0;
2307 }
2308     
2309 int drmFenceDestroy(int fd, const drmFence *fence)
2310 {
2311     drm_fence_arg_t arg;
2312    
2313     memset(&arg, 0, sizeof(arg));
2314     arg.handle = fence->handle;
2315     arg.op = drm_fence_destroy;
2316     if (ioctl(fd, DRM_IOCTL_FENCE, &arg))
2317         return -errno;
2318     return 0;
2319 }
2320
2321 int drmFenceReference(int fd, unsigned handle, drmFence *fence)
2322 {
2323     drm_fence_arg_t arg;
2324    
2325     memset(&arg, 0, sizeof(arg));
2326     arg.handle = handle;
2327     arg.op = drm_fence_reference;
2328     if (ioctl(fd, DRM_IOCTL_FENCE, &arg))
2329         return -errno;
2330     fence->handle = arg.handle;
2331     fence->class = arg.class;
2332     fence->type = arg.type;
2333     fence->flags = arg.flags;
2334     fence->signaled = arg.signaled;
2335     return 0;
2336 }
2337
2338 int drmFenceUnreference(int fd, const drmFence *fence)
2339 {
2340     drm_fence_arg_t arg;
2341    
2342     memset(&arg, 0, sizeof(arg));
2343     arg.handle = fence->handle;
2344     arg.op = drm_fence_unreference;
2345     if (ioctl(fd, DRM_IOCTL_FENCE, &arg))
2346         return -errno;
2347     return 0;
2348 }
2349
2350 int drmFenceFlush(int fd, drmFence *fence, unsigned flush_type)
2351 {
2352     drm_fence_arg_t arg;
2353    
2354     memset(&arg, 0, sizeof(arg));
2355     arg.handle = fence->handle;
2356     arg.type = flush_type;
2357     arg.op = drm_fence_flush;
2358     if (ioctl(fd, DRM_IOCTL_FENCE, &arg))
2359         return -errno;
2360     fence->class = arg.class;
2361     fence->type = arg.type;
2362     fence->signaled = arg.signaled;
2363     return 0;
2364 }
2365
2366 int drmFenceUpdate(int fd, drmFence *fence)
2367 {
2368         drm_fence_arg_t arg;
2369         
2370     memset(&arg, 0, sizeof(arg));
2371     arg.handle = fence->handle;
2372     arg.op = drm_fence_signaled;
2373     if (ioctl(fd, DRM_IOCTL_FENCE, &arg))
2374         return -errno;
2375     fence->class = arg.class;
2376     fence->type = arg.type;
2377     fence->signaled = arg.signaled;
2378     return 0;
2379 }
2380
2381 int drmFenceSignaled(int fd, drmFence *fence, unsigned fenceType, 
2382                      int *signaled)
2383 {
2384     int 
2385         ret;
2386
2387     if ((fence->flags & DRM_FENCE_FLAG_SHAREABLE) ||
2388         ((fenceType & fence->signaled) != fenceType)) {
2389
2390         ret = drmFenceFlush(fd, fence, fenceType);
2391         if (ret)
2392             return ret;
2393     }
2394
2395     *signaled = ((fenceType & fence->signaled) == fenceType);
2396
2397     return 0;
2398 }
2399
2400 /*
2401  * Valid flags are 
2402  * DRM_FENCE_FLAG_SHAREABLE
2403  * DRM_FENCE_MASK_DRIVER
2404  */
2405
2406
2407 int drmFenceEmit(int fd, unsigned flags, drmFence *fence, unsigned emit_type)
2408 {
2409     drm_fence_arg_t arg;
2410
2411     memset(&arg, 0, sizeof(arg));
2412     arg.class = fence->class;
2413     arg.flags = flags;
2414     arg.handle = fence->handle;
2415     arg.type = emit_type;
2416     arg.op = drm_fence_emit;
2417     if (ioctl(fd, DRM_IOCTL_FENCE, &arg))
2418         return -errno;
2419     fence->class = arg.class;
2420     fence->type = arg.type;
2421     fence->signaled = arg.signaled;
2422     return 0;
2423 }
2424
2425 /*
2426  * Valid flags are 
2427  * DRM_FENCE_FLAG_WAIT_LAZY
2428  * DRM_FENCE_FLAG_WAIT_IGNORE_SIGNALS
2429  */
2430     
2431 int drmFenceWait(int fd, unsigned flags, drmFence *fence, unsigned flush_type)
2432 {
2433     drm_fence_arg_t arg;
2434     int ret;
2435
2436     if (flush_type == 0) {
2437         flush_type = fence->type;
2438     }
2439
2440     if (!(fence->flags & DRM_FENCE_FLAG_SHAREABLE)) {
2441         if ((flush_type & fence->signaled) == flush_type) {
2442             return 0;
2443         }
2444     }
2445
2446     memset(&arg, 0, sizeof(arg));
2447     arg.handle = fence->handle;
2448     arg.type = flush_type;
2449     arg.flags = flags;
2450     arg.op = drm_fence_wait;
2451     do {
2452         ret = ioctl(fd, DRM_IOCTL_FENCE, &arg);
2453     } while (ret != 0 && errno == EAGAIN);
2454
2455     if (ret)
2456         return -errno;
2457
2458     fence->class = arg.class;
2459     fence->type = arg.type;
2460     fence->signaled = arg.signaled;
2461     return 0;
2462 }    
2463
2464 static int drmAdjustListNodes(drmBOList *list)
2465 {
2466     drmBONode *node;
2467     drmMMListHead *l;
2468     int ret = 0;
2469
2470     while(list->numCurrent < list->numTarget) {
2471         node = (drmBONode *) malloc(sizeof(*node));
2472         if (!node) {
2473             ret = -ENOMEM;
2474             break;
2475         }
2476         list->numCurrent++;
2477         DRMLISTADD(&node->head, &list->free);
2478     }
2479
2480     while(list->numCurrent > list->numTarget) {
2481         l = list->free.next;
2482         if (l == &list->free)
2483             break;
2484         DRMLISTDEL(l);
2485         node = DRMLISTENTRY(drmBONode, l, head);
2486         free(node);
2487         list->numCurrent--;
2488     }
2489     return ret;
2490 }
2491
2492 void drmBOFreeList(drmBOList *list)
2493 {
2494     drmBONode *node;
2495     drmMMListHead *l;
2496
2497     l = list->list.next;
2498     while(l != &list->list) {
2499         DRMLISTDEL(l);
2500         node = DRMLISTENTRY(drmBONode, l, head);
2501         free(node);
2502         l = list->list.next;
2503         list->numCurrent--;
2504         list->numOnList--;
2505     }
2506
2507     l = list->free.next;
2508     while(l != &list->free) {
2509         DRMLISTDEL(l);
2510         node = DRMLISTENTRY(drmBONode, l, head);
2511         free(node);
2512         l = list->free.next;
2513         list->numCurrent--;
2514     }
2515 }
2516         
2517 int drmBOResetList(drmBOList *list) {
2518
2519     drmMMListHead *l;
2520     int ret;
2521
2522     ret = drmAdjustListNodes(list);
2523     if (ret)
2524         return ret;
2525
2526     l = list->list.next;
2527     while(l != &list->list) {
2528         DRMLISTDEL(l);
2529         DRMLISTADD(l, &list->free);
2530         list->numOnList--;
2531         l = list->list.next;
2532     }
2533     return drmAdjustListNodes(list);
2534 }
2535         
2536 static drmBONode *drmAddListItem(drmBOList *list, drmBO *item, 
2537                                  unsigned long arg0,
2538                                  unsigned long arg1)
2539 {
2540     drmBONode *node;
2541     drmMMListHead *l;
2542
2543     l = list->free.next;
2544     if (l == &list->free) {
2545         node = (drmBONode *) malloc(sizeof(*node));
2546         if (!node) {
2547             return NULL;
2548         }
2549         list->numCurrent++;
2550     } else {
2551         DRMLISTDEL(l);
2552         node = DRMLISTENTRY(drmBONode, l, head);
2553     }
2554     node->buf = item;
2555     node->arg0 = arg0;
2556     node->arg1 = arg1;
2557     DRMLISTADD(&node->head, &list->list);
2558     list->numOnList++;
2559     return node;
2560 }
2561         
2562 void *drmBOListIterator(drmBOList *list)
2563 {
2564     void *ret = list->list.next;
2565
2566     if (ret == &list->list)
2567         return NULL;
2568     return ret;
2569 }
2570
2571 void *drmBOListNext(drmBOList *list, void *iterator)
2572 {
2573     void *ret;
2574
2575     drmMMListHead *l = (drmMMListHead *) iterator;
2576     ret = l->next;
2577     if (ret == &list->list)
2578         return NULL;
2579     return ret;
2580 }
2581
2582 drmBO *drmBOListBuf(void *iterator)
2583 {
2584     drmBONode *node;
2585     drmMMListHead *l = (drmMMListHead *) iterator;
2586     node = DRMLISTENTRY(drmBONode, l, head);
2587     
2588     return node->buf;
2589 }
2590
2591
2592 int drmBOCreateList(int numTarget, drmBOList *list)
2593 {
2594     DRMINITLISTHEAD(&list->list);
2595     DRMINITLISTHEAD(&list->free);
2596     list->numTarget = numTarget;
2597     list->numCurrent = 0;
2598     list->numOnList = 0;
2599     return drmAdjustListNodes(list);
2600 }
2601
2602 static void drmBOCopyReply(const drm_bo_arg_reply_t *rep, 
2603                            drmBO *buf)
2604 {
2605     buf->handle = rep->handle;
2606     buf->flags = rep->flags;
2607     buf->size = rep->size;
2608     buf->offset = rep->offset;
2609     buf->mapHandle = rep->arg_handle;
2610     buf->mask = rep->mask;
2611     buf->start = rep->buffer_start;
2612     buf->fenceFlags = rep->fence_flags;
2613     buf->replyFlags = rep->rep_flags;
2614     buf->pageAlignment = rep->page_alignment;
2615 }
2616     
2617     
2618
2619 int drmBOCreate(int fd, unsigned long start, unsigned long size, 
2620                 unsigned pageAlignment, void *user_buffer, drm_bo_type_t type, 
2621                 unsigned mask,
2622                 unsigned hint, drmBO *buf)
2623 {
2624     drm_bo_arg_t arg;
2625     drm_bo_arg_request_t *req = &arg.d.req;
2626     drm_bo_arg_reply_t *rep = &arg.d.rep;
2627     int ret;
2628
2629     memset(buf, 0, sizeof(*buf));
2630     memset(&arg, 0, sizeof(arg));
2631     req->mask = mask;
2632     req->hint = hint;
2633     req->size = size;
2634     req->type = type;
2635     req->page_alignment = pageAlignment;
2636
2637     buf->virtual = NULL;
2638
2639     switch(type) {
2640     case drm_bo_type_dc:
2641         req->buffer_start = start;
2642         break;
2643     case drm_bo_type_user:
2644         req->buffer_start = (unsigned long) user_buffer;
2645         buf->virtual = user_buffer;
2646         break;
2647     case drm_bo_type_fake:
2648         req->buffer_start = start;
2649         break;
2650     default:
2651         return -EINVAL;
2652     }
2653     req->op = drm_bo_create;
2654
2655     do {
2656         ret = ioctl(fd, DRM_IOCTL_BUFOBJ, &arg);
2657     } while (ret != 0 && errno == EAGAIN);
2658
2659     if (ret)
2660         return -errno;
2661     if (!arg.handled) {
2662         return -EFAULT;
2663     }
2664     if (rep->ret) {
2665         fprintf(stderr, "Error %d\n", rep->ret);
2666         return rep->ret;
2667     }
2668     
2669     drmBOCopyReply(rep, buf);
2670     buf->mapVirtual = NULL;
2671     buf->mapCount = 0;
2672
2673     return 0;
2674 }
2675
2676 int drmBODestroy(int fd, drmBO *buf)
2677 {
2678     drm_bo_arg_t arg;
2679     drm_bo_arg_request_t *req = &arg.d.req;
2680     drm_bo_arg_reply_t *rep = &arg.d.rep;
2681     
2682     if (buf->mapVirtual && (buf->type != drm_bo_type_fake)) {
2683         (void) drmUnmap(buf->mapVirtual, buf->start + buf->size);
2684         buf->mapVirtual = NULL;
2685         buf->virtual = NULL;
2686     }
2687
2688     memset(&arg, 0, sizeof(arg));
2689     req->handle = buf->handle;
2690     req->op = drm_bo_destroy;
2691
2692     if (ioctl(fd, DRM_IOCTL_BUFOBJ, &arg))
2693         return -errno;
2694     if (!arg.handled) {
2695         return -EFAULT;
2696     }
2697     if (rep->ret) {
2698         return rep->ret;
2699     }
2700
2701     buf->handle = 0;
2702     return 0;
2703 }
2704  
2705 int drmBOReference(int fd, unsigned handle, drmBO *buf)
2706 {
2707
2708     drm_bo_arg_t arg;
2709     drm_bo_arg_request_t *req = &arg.d.req;
2710     drm_bo_arg_reply_t *rep = &arg.d.rep;
2711     
2712     memset(&arg, 0, sizeof(arg));
2713     req->handle = handle;
2714     req->op = drm_bo_reference;
2715     
2716     if (ioctl(fd, DRM_IOCTL_BUFOBJ, &arg))
2717         return -errno;
2718     if (!arg.handled) {
2719         return -EFAULT;
2720     }
2721     if (rep->ret) {
2722         return rep->ret;
2723     }
2724
2725     drmBOCopyReply(rep, buf);
2726     buf->type = drm_bo_type_dc;
2727     buf->mapVirtual = NULL;
2728     buf->mapCount = 0;
2729     buf->virtual = NULL;
2730
2731     return 0;
2732 }
2733
2734 int drmBOUnReference(int fd, drmBO *buf)
2735 {
2736     drm_bo_arg_t arg;
2737     drm_bo_arg_request_t *req = &arg.d.req;
2738     drm_bo_arg_reply_t *rep = &arg.d.rep;
2739     
2740
2741     if (buf->mapVirtual && (buf->type != drm_bo_type_fake)) {
2742         (void) munmap(buf->mapVirtual, buf->start + buf->size);
2743         buf->mapVirtual = NULL;
2744         buf->virtual = NULL;
2745     }
2746
2747     memset(&arg, 0, sizeof(arg));
2748     req->handle = buf->handle;
2749     req->op = drm_bo_unreference;
2750
2751     if (ioctl(fd, DRM_IOCTL_BUFOBJ, &arg))
2752         return -errno;
2753     if (!arg.handled) {
2754         return -EFAULT;
2755     }
2756     if (rep->ret) {
2757         return rep->ret;
2758     }
2759
2760     buf->handle = 0;
2761     return 0;
2762 }   
2763
2764 /*
2765  * Flags can be  DRM_BO_FLAG_READ, DRM_BO_FLAG_WRITE or'ed together
2766  * Hint currently be DRM_BO_HINT_DONT_BLOCK, which makes the
2767  * call return an -EBUSY if it can' immediately honor the mapping request.
2768  */
2769
2770 int drmBOMap(int fd, drmBO *buf, unsigned mapFlags, unsigned mapHint,
2771              void **address)
2772 {
2773
2774     drm_bo_arg_t arg;
2775     drm_bo_arg_request_t *req = &arg.d.req;
2776     drm_bo_arg_reply_t *rep = &arg.d.rep;
2777     int ret = 0;
2778
2779     /*
2780      * Make sure we have a virtual address of the buffer.
2781      */
2782
2783     if (!buf->virtual && buf->type != drm_bo_type_fake) {
2784         drmAddress virtual;
2785         virtual = mmap(0, buf->size + buf->start, 
2786                        PROT_READ | PROT_WRITE, MAP_SHARED,
2787                        fd, buf->mapHandle);
2788         if (virtual == MAP_FAILED) {
2789             ret = -errno;
2790         }
2791         if (ret) 
2792             return ret;
2793         buf->mapVirtual = virtual;
2794         buf->virtual = ((char *) virtual) + buf->start;
2795     }
2796
2797     memset(&arg, 0, sizeof(arg));
2798     req->handle = buf->handle;
2799     req->mask = mapFlags;
2800     req->hint = mapHint;
2801     req->op = drm_bo_map;
2802
2803     /*
2804      * May hang if the buffer object is busy.
2805      * This IOCTL synchronizes the buffer.
2806      */
2807     
2808     do {
2809         ret = ioctl(fd, DRM_IOCTL_BUFOBJ, &arg);
2810     } while (ret != 0 && errno == EAGAIN);
2811
2812     if (ret) 
2813         return -errno;
2814     if (!arg.handled) 
2815         return -EFAULT;
2816     if (rep->ret)
2817         return rep->ret;
2818
2819     drmBOCopyReply(rep, buf);   
2820     buf->mapFlags = mapFlags;
2821     ++buf->mapCount;
2822     *address = buf->virtual;
2823
2824     return 0;
2825 }
2826
2827 int drmBOUnmap(int fd, drmBO *buf)
2828 {
2829     drm_bo_arg_t arg;
2830     drm_bo_arg_request_t *req = &arg.d.req;
2831     drm_bo_arg_reply_t *rep = &arg.d.rep;
2832
2833         
2834     memset(&arg, 0, sizeof(arg));
2835     req->handle = buf->handle;
2836     req->op = drm_bo_unmap;
2837
2838     if (ioctl(fd, DRM_IOCTL_BUFOBJ, &arg)) {
2839         return -errno;
2840     }
2841     if (!arg.handled) 
2842         return -EFAULT;
2843     if (rep->ret)
2844         return rep->ret;
2845
2846     return 0;
2847 }
2848     
2849 int drmBOValidate(int fd, drmBO *buf, unsigned flags, unsigned mask, 
2850                   unsigned hint)
2851 {
2852     drm_bo_arg_t arg;
2853     drm_bo_arg_request_t *req = &arg.d.req;
2854     drm_bo_arg_reply_t *rep = &arg.d.rep;
2855     int ret = 0;
2856
2857     memset(&arg, 0, sizeof(arg));
2858     req->handle = buf->handle;
2859     req->mask = flags;
2860     req->hint = hint;
2861     req->arg_handle = mask; /* Encode mask in the arg_handle field :/ */
2862     req->op = drm_bo_validate;
2863
2864     do{
2865         ret = ioctl(fd, DRM_IOCTL_BUFOBJ, &arg);
2866     } while (ret && errno == EAGAIN);
2867     
2868     if (ret) 
2869         return -errno;
2870     if (!arg.handled)
2871         return -EFAULT;
2872     if (rep->ret)
2873         return rep->ret;
2874
2875     drmBOCopyReply(rep, buf);
2876     return 0;
2877 }
2878             
2879
2880 int drmBOFence(int fd, drmBO *buf, unsigned flags, unsigned fenceHandle)
2881 {
2882     drm_bo_arg_t arg;
2883     drm_bo_arg_request_t *req = &arg.d.req;
2884     drm_bo_arg_reply_t *rep = &arg.d.rep;
2885     int ret = 0;
2886
2887     memset(&arg, 0, sizeof(arg));
2888     req->handle = buf->handle;
2889     req->mask = flags;
2890     req->arg_handle = fenceHandle;
2891     req->op = drm_bo_fence;
2892
2893     ret = ioctl(fd, DRM_IOCTL_BUFOBJ, &arg);
2894     
2895     if (ret) 
2896         return -errno;
2897     if (!arg.handled)
2898         return -EFAULT;
2899     if (rep->ret)
2900         return rep->ret;
2901     return 0;
2902 }
2903
2904 int drmBOInfo(int fd, drmBO *buf)
2905 {
2906     drm_bo_arg_t arg;
2907     drm_bo_arg_request_t *req = &arg.d.req;
2908     drm_bo_arg_reply_t *rep = &arg.d.rep;
2909     int ret = 0;
2910
2911     memset(&arg, 0, sizeof(arg));
2912     req->handle = buf->handle;
2913     req->op = drm_bo_info;
2914
2915     ret = ioctl(fd, DRM_IOCTL_BUFOBJ, &arg);
2916     
2917     if (ret) 
2918         return -errno;
2919     if (!arg.handled)
2920         return -EFAULT;
2921     if (rep->ret)
2922         return rep->ret;
2923     drmBOCopyReply(rep, buf);
2924     return 0;
2925 }
2926
2927 int drmBOWaitIdle(int fd, drmBO *buf, unsigned hint)
2928 {
2929     drm_bo_arg_t arg;
2930     drm_bo_arg_request_t *req = &arg.d.req;
2931     drm_bo_arg_reply_t *rep = &arg.d.rep;
2932     int ret = 0;
2933
2934     if ((buf->flags & DRM_BO_FLAG_SHAREABLE) ||
2935         (buf->replyFlags & DRM_BO_REP_BUSY)) {
2936         memset(&arg, 0, sizeof(arg));
2937         req->handle = buf->handle;
2938         req->op = drm_bo_wait_idle;
2939         req->hint = hint;
2940
2941         do {
2942             ret = ioctl(fd, DRM_IOCTL_BUFOBJ, &arg);
2943         } while (ret && errno == EAGAIN);
2944
2945         if (ret) 
2946             return -errno;
2947         if (!arg.handled)
2948             return -EFAULT;
2949         if (rep->ret)
2950             return rep->ret;
2951         drmBOCopyReply(rep, buf);
2952     }
2953     return 0;
2954 }
2955         
2956 int drmBOBusy(int fd, drmBO *buf, int *busy)
2957 {
2958     if (!(buf->flags & DRM_BO_FLAG_SHAREABLE) &&
2959         !(buf->replyFlags & DRM_BO_REP_BUSY)) {
2960         *busy = 0;
2961         return 0;
2962     } else {
2963         int ret = drmBOInfo(fd, buf);
2964         if (ret)
2965             return ret;
2966         *busy = (buf->replyFlags & DRM_BO_REP_BUSY);
2967         return 0;
2968     }
2969 }
2970     
2971     
2972 int drmAddValidateItem(drmBOList *list, drmBO *buf, unsigned flags, 
2973                        unsigned mask,
2974                        int *newItem)
2975 {
2976     drmBONode *node, *cur;
2977     drmMMListHead *l;
2978
2979     *newItem = 0;
2980     cur = NULL;
2981
2982     for (l = list->list.next; l != &list->list; l = l->next) {
2983         node = DRMLISTENTRY(drmBONode, l, head);
2984         if (node->buf == buf) {
2985             cur = node;
2986             break;
2987         }
2988     }
2989     if (!cur) {
2990         cur = drmAddListItem(list, buf, flags, mask);
2991         if (!cur) {
2992             drmMsg("Out of memory creating validate list node.\n");
2993             return -ENOMEM;
2994         }
2995         *newItem = 1;
2996         cur->arg0 = flags;
2997         cur->arg1 = mask;
2998     } else {
2999         unsigned memMask = (cur->arg1 | mask) & DRM_BO_MASK_MEM;
3000         unsigned memFlags = cur->arg0 & flags & memMask;
3001         
3002         if (!memFlags) {
3003             drmMsg("Incompatible memory location requests "
3004                    "on validate list.\n");
3005             drmMsg("Previous flag: 0x%08lx, mask: 0x%08lx\n",
3006                    cur->arg0, cur->arg1);
3007             drmMsg("Current flag: 0x%08lx, mask: 0x%08lx\n",
3008                    flags, mask);
3009             return -EINVAL;
3010         }
3011         if (mask & cur->arg1 & ~DRM_BO_MASK_MEM  & (cur->arg0 ^ flags)) {
3012             drmMsg("Incompatible buffer flag requests "
3013                    "on validate list.\n");
3014             drmMsg("Previous flag: 0x%08lx, mask: 0x%08lx\n",
3015                    cur->arg0, cur->arg1);
3016             drmMsg("Current flag: 0x%08lx, mask: 0x%08lx\n",
3017                    flags, mask);
3018             return -EINVAL;
3019         }
3020         cur->arg1 |= mask;
3021         cur->arg0 = memFlags | ((cur->arg0 | flags) & 
3022                                 cur->arg1 & ~DRM_BO_MASK_MEM);  
3023     }
3024     return 0;
3025 }
3026
3027
3028 int drmBOValidateList(int fd, drmBOList *list)
3029 {
3030    
3031   drmBONode *node;
3032   drmMMListHead *l;
3033   drm_bo_arg_t *arg, *first;
3034   drm_bo_arg_request_t *req;
3035   drm_bo_arg_reply_t *rep;
3036   drm_u64_t *prevNext = NULL;
3037   drmBO *buf;
3038   int ret;
3039
3040   first = NULL;
3041
3042   for (l = list->list.next; l != &list->list; l = l->next) {
3043       node = DRMLISTENTRY(drmBONode, l, head);
3044
3045       arg = &node->bo_arg;
3046       req = &arg->d.req;
3047
3048       if (!first)
3049           first = arg;
3050
3051       if (prevNext)
3052           *prevNext = (unsigned long) arg;
3053
3054       memset(arg, 0, sizeof(*arg));
3055       prevNext = &arg->next;
3056       req->handle = node->buf->handle;
3057       req->op = drm_bo_validate;
3058       req->mask = node->arg0;
3059       req->hint = 0;
3060       req->arg_handle = node->arg1;
3061   }
3062   
3063   if (!first) 
3064       return 0;
3065
3066   do{
3067       ret = ioctl(fd, DRM_IOCTL_BUFOBJ, first);
3068   } while (ret && errno == EAGAIN);
3069
3070
3071   if (ret)
3072       return -errno;
3073   
3074   for (l = list->list.next; l != &list->list; l = l->next) {
3075       node = DRMLISTENTRY(drmBONode, l, head);
3076       arg = &node->bo_arg;
3077       rep = &arg->d.rep;
3078       
3079       if (!arg->handled) {
3080           drmMsg("Unhandled request\n");
3081           return -EFAULT;
3082       }
3083       if (rep->ret)
3084           return rep->ret;
3085
3086       buf = node->buf;
3087       drmBOCopyReply(rep, buf);
3088   }
3089
3090   return 0;
3091 }
3092           
3093
3094 int drmBOFenceList(int fd, drmBOList *list, unsigned fenceHandle)
3095 {
3096    
3097   drmBONode *node;
3098   drmMMListHead *l;
3099   drm_bo_arg_t *arg, *first;
3100   drm_bo_arg_request_t *req;
3101   drm_bo_arg_reply_t *rep;
3102   drm_u64_t *prevNext = NULL;
3103   drmBO *buf;
3104   unsigned fence_flags;
3105   int ret;
3106
3107   first = NULL;
3108
3109   for (l = list->list.next; l != &list->list; l = l->next) {
3110       node = DRMLISTENTRY(drmBONode, l, head);
3111
3112       arg = &node->bo_arg;
3113       req = &arg->d.req;
3114
3115       if (!first)
3116           first = arg;
3117
3118       if (prevNext)
3119           *prevNext = (unsigned long) arg;
3120
3121       memset(arg, 0, sizeof(*arg));
3122       prevNext = &arg->next;
3123       req->handle = node->buf->handle;
3124       req->op = drm_bo_fence;
3125       req->mask = node->arg0;
3126       req->arg_handle = fenceHandle;
3127   }
3128   
3129   if (!first) 
3130       return 0;
3131
3132   ret = ioctl(fd, DRM_IOCTL_BUFOBJ, first);
3133
3134   if (ret)
3135       return -errno;
3136   
3137   for (l = list->list.next; l != &list->list; l = l->next) {
3138       node = DRMLISTENTRY(drmBONode, l, head);
3139
3140       arg = &node->bo_arg;
3141       rep = &arg->d.rep;
3142       
3143       if (!arg->handled)
3144           return -EFAULT;
3145       if (rep->ret)
3146           return rep->ret;
3147       drmBOCopyReply(rep, node->buf);
3148   }
3149
3150   return 0;
3151 }
3152
3153 int drmMMInit(int fd, unsigned long pOffset, unsigned long pSize,
3154               unsigned memType)
3155 {
3156     struct drm_mm_init_arg arg;
3157     
3158     memset(&arg, 0, sizeof(arg));
3159
3160     arg.p_offset = pOffset;
3161     arg.p_size = pSize;
3162     arg.mem_type = memType;
3163
3164     if (ioctl(fd, DRM_IOCTL_MM_INIT, &arg))
3165         return -errno;
3166     
3167     return 0;   
3168 }
3169
3170 int drmMMTakedown(int fd, unsigned memType)
3171 {
3172     struct drm_mm_type_arg arg;
3173
3174     memset(&arg, 0, sizeof(arg));
3175     arg.mem_type = memType;
3176
3177     if (ioctl(fd, DRM_IOCTL_MM_TAKEDOWN, &arg))
3178         return -errno;
3179     
3180     return 0;   
3181 }
3182
3183 int drmMMLock(int fd, unsigned memType)
3184 {
3185     struct drm_mm_type_arg arg;
3186     int ret;
3187
3188     memset(&arg, 0, sizeof(arg));
3189     arg.mem_type = memType;
3190
3191     do{
3192         ret = ioctl(fd, DRM_IOCTL_MM_LOCK, &arg);
3193     } while (ret && errno == EAGAIN);
3194     
3195     return -errno;      
3196 }
3197
3198 int drmMMUnlock(int fd, unsigned memType)
3199 {
3200     struct drm_mm_type_arg arg;
3201     int ret;
3202
3203     memset(&arg, 0, sizeof(arg));
3204     
3205     arg.mem_type = memType;
3206
3207     do{
3208         ret = ioctl(fd, DRM_IOCTL_MM_UNLOCK, &arg);
3209     } while (ret && errno == EAGAIN);
3210     
3211     return -errno;      
3212 }
3213
3214 #define DRM_MAX_FDS 16
3215 static struct {
3216    char *BusID;
3217    int fd;
3218    int refcount;
3219 } connection[DRM_MAX_FDS];
3220
3221 static int nr_fds = 0;
3222
3223 int drmOpenOnce(void *unused, 
3224                 const char *BusID,
3225                 int *newlyopened)
3226 {
3227    int i;
3228    int fd;
3229    
3230    for (i = 0; i < nr_fds; i++)
3231       if (strcmp(BusID, connection[i].BusID) == 0) {
3232          connection[i].refcount++;
3233          *newlyopened = 0;
3234          return connection[i].fd;
3235       }
3236
3237    fd = drmOpen(unused, BusID);
3238    if (fd <= 0 || nr_fds == DRM_MAX_FDS)
3239       return fd;
3240    
3241    connection[nr_fds].BusID = strdup(BusID);
3242    connection[nr_fds].fd = fd;
3243    connection[nr_fds].refcount = 1;
3244    *newlyopened = 1;
3245
3246    if (0)
3247       fprintf(stderr, "saved connection %d for %s %d\n", 
3248               nr_fds, connection[nr_fds].BusID, 
3249               strcmp(BusID, connection[nr_fds].BusID));
3250
3251    nr_fds++;
3252
3253    return fd;   
3254 }
3255
3256 void drmCloseOnce(int fd)
3257 {
3258    int i;
3259
3260    for (i = 0; i < nr_fds; i++) {
3261       if (fd == connection[i].fd) {
3262          if (--connection[i].refcount == 0) {
3263             drmClose(connection[i].fd);
3264             free(connection[i].BusID);
3265             
3266             if (i < --nr_fds) 
3267                connection[i] = connection[nr_fds];
3268
3269             return;
3270          }
3271       }
3272    }
3273 }