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