add internals for opening a control node
[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
583 /**
584  * Free the version information returned by drmGetVersion().
585  *
586  * \param v pointer to the version information.
587  *
588  * \internal
589  * It frees the memory pointed by \p %v as well as all the non-null strings
590  * pointers in it.
591  */
592 void drmFreeVersion(drmVersionPtr v)
593 {
594     if (!v)
595         return;
596     drmFree(v->name);
597     drmFree(v->date);
598     drmFree(v->desc);
599     drmFree(v);
600 }
601
602
603 /**
604  * Free the non-public version information returned by the kernel.
605  *
606  * \param v pointer to the version information.
607  *
608  * \internal
609  * Used by drmGetVersion() to free the memory pointed by \p %v as well as all
610  * the non-null strings pointers in it.
611  */
612 static void drmFreeKernelVersion(drm_version_t *v)
613 {
614     if (!v)
615         return;
616     drmFree(v->name);
617     drmFree(v->date);
618     drmFree(v->desc);
619     drmFree(v);
620 }
621
622
623 /**
624  * Copy version information.
625  * 
626  * \param d destination pointer.
627  * \param s source pointer.
628  * 
629  * \internal
630  * Used by drmGetVersion() to translate the information returned by the ioctl
631  * interface in a private structure into the public structure counterpart.
632  */
633 static void drmCopyVersion(drmVersionPtr d, const drm_version_t *s)
634 {
635     d->version_major      = s->version_major;
636     d->version_minor      = s->version_minor;
637     d->version_patchlevel = s->version_patchlevel;
638     d->name_len           = s->name_len;
639     d->name               = drmStrdup(s->name);
640     d->date_len           = s->date_len;
641     d->date               = drmStrdup(s->date);
642     d->desc_len           = s->desc_len;
643     d->desc               = drmStrdup(s->desc);
644 }
645
646
647 /**
648  * Query the driver version information.
649  *
650  * \param fd file descriptor.
651  * 
652  * \return pointer to a drmVersion structure which should be freed with
653  * drmFreeVersion().
654  * 
655  * \note Similar information is available via /proc/dri.
656  * 
657  * \internal
658  * It gets the version information via successive DRM_IOCTL_VERSION ioctls,
659  * first with zeros to get the string lengths, and then the actually strings.
660  * It also null-terminates them since they might not be already.
661  */
662 drmVersionPtr drmGetVersion(int fd)
663 {
664     drmVersionPtr retval;
665     drm_version_t *version = drmMalloc(sizeof(*version));
666
667     version->name_len    = 0;
668     version->name        = NULL;
669     version->date_len    = 0;
670     version->date        = NULL;
671     version->desc_len    = 0;
672     version->desc        = NULL;
673
674     if (ioctl(fd, DRM_IOCTL_VERSION, version)) {
675         drmFreeKernelVersion(version);
676         return NULL;
677     }
678
679     if (version->name_len)
680         version->name    = drmMalloc(version->name_len + 1);
681     if (version->date_len)
682         version->date    = drmMalloc(version->date_len + 1);
683     if (version->desc_len)
684         version->desc    = drmMalloc(version->desc_len + 1);
685
686     if (ioctl(fd, DRM_IOCTL_VERSION, version)) {
687         drmMsg("DRM_IOCTL_VERSION: %s\n", strerror(errno));
688         drmFreeKernelVersion(version);
689         return NULL;
690     }
691
692     /* The results might not be null-terminated strings, so terminate them. */
693     if (version->name_len) version->name[version->name_len] = '\0';
694     if (version->date_len) version->date[version->date_len] = '\0';
695     if (version->desc_len) version->desc[version->desc_len] = '\0';
696
697     retval = drmMalloc(sizeof(*retval));
698     drmCopyVersion(retval, version);
699     drmFreeKernelVersion(version);
700     return retval;
701 }
702
703
704 /**
705  * Get version information for the DRM user space library.
706  * 
707  * This version number is driver independent.
708  * 
709  * \param fd file descriptor.
710  *
711  * \return version information.
712  * 
713  * \internal
714  * This function allocates and fills a drm_version structure with a hard coded
715  * version number.
716  */
717 drmVersionPtr drmGetLibVersion(int fd)
718 {
719     drm_version_t *version = drmMalloc(sizeof(*version));
720
721     /* Version history:
722      *   NOTE THIS MUST NOT GO ABOVE VERSION 1.X due to drivers needing it
723      *   revision 1.0.x = original DRM interface with no drmGetLibVersion
724      *                    entry point and many drm<Device> extensions
725      *   revision 1.1.x = added drmCommand entry points for device extensions
726      *                    added drmGetLibVersion to identify libdrm.a version
727      *   revision 1.2.x = added drmSetInterfaceVersion
728      *                    modified drmOpen to handle both busid and name
729      *   revision 1.3.x = added server + memory manager
730      */
731     version->version_major      = 1;
732     version->version_minor      = 3;
733     version->version_patchlevel = 0;
734
735     return (drmVersionPtr)version;
736 }
737
738
739 /**
740  * Free the bus ID information.
741  *
742  * \param busid bus ID information string as given by drmGetBusid().
743  *
744  * \internal
745  * This function is just frees the memory pointed by \p busid.
746  */
747 void drmFreeBusid(const char *busid)
748 {
749     drmFree((void *)busid);
750 }
751
752
753 /**
754  * Get the bus ID of the device.
755  *
756  * \param fd file descriptor.
757  *
758  * \return bus ID string.
759  *
760  * \internal
761  * This function gets the bus ID via successive DRM_IOCTL_GET_UNIQUE ioctls to
762  * get the string length and data, passing the arguments in a drm_unique
763  * structure.
764  */
765 char *drmGetBusid(int fd)
766 {
767     drm_unique_t u;
768
769     u.unique_len = 0;
770     u.unique     = NULL;
771
772     if (ioctl(fd, DRM_IOCTL_GET_UNIQUE, &u))
773         return NULL;
774     u.unique = drmMalloc(u.unique_len + 1);
775     if (ioctl(fd, DRM_IOCTL_GET_UNIQUE, &u))
776         return NULL;
777     u.unique[u.unique_len] = '\0';
778
779     return u.unique;
780 }
781
782
783 /**
784  * Set the bus ID of the device.
785  *
786  * \param fd file descriptor.
787  * \param busid bus ID string.
788  *
789  * \return zero on success, negative on failure.
790  *
791  * \internal
792  * This function is a wrapper around the DRM_IOCTL_SET_UNIQUE ioctl, passing
793  * the arguments in a drm_unique structure.
794  */
795 int drmSetBusid(int fd, const char *busid)
796 {
797     drm_unique_t u;
798
799     u.unique     = (char *)busid;
800     u.unique_len = strlen(busid);
801
802     if (ioctl(fd, DRM_IOCTL_SET_UNIQUE, &u)) {
803         return -errno;
804     }
805     return 0;
806 }
807
808 int drmGetMagic(int fd, drm_magic_t * magic)
809 {
810     drm_auth_t auth;
811
812     *magic = 0;
813     if (ioctl(fd, DRM_IOCTL_GET_MAGIC, &auth))
814         return -errno;
815     *magic = auth.magic;
816     return 0;
817 }
818
819 int drmAuthMagic(int fd, drm_magic_t magic)
820 {
821     drm_auth_t auth;
822
823     auth.magic = magic;
824     if (ioctl(fd, DRM_IOCTL_AUTH_MAGIC, &auth))
825         return -errno;
826     return 0;
827 }
828
829 /**
830  * Specifies a range of memory that is available for mapping by a
831  * non-root process.
832  *
833  * \param fd file descriptor.
834  * \param offset usually the physical address. The actual meaning depends of
835  * the \p type parameter. See below.
836  * \param size of the memory in bytes.
837  * \param type type of the memory to be mapped.
838  * \param flags combination of several flags to modify the function actions.
839  * \param handle will be set to a value that may be used as the offset
840  * parameter for mmap().
841  * 
842  * \return zero on success or a negative value on error.
843  *
844  * \par Mapping the frame buffer
845  * For the frame buffer
846  * - \p offset will be the physical address of the start of the frame buffer,
847  * - \p size will be the size of the frame buffer in bytes, and
848  * - \p type will be DRM_FRAME_BUFFER.
849  *
850  * \par
851  * The area mapped will be uncached. If MTRR support is available in the
852  * kernel, the frame buffer area will be set to write combining. 
853  *
854  * \par Mapping the MMIO register area
855  * For the MMIO register area,
856  * - \p offset will be the physical address of the start of the register area,
857  * - \p size will be the size of the register area bytes, and
858  * - \p type will be DRM_REGISTERS.
859  * \par
860  * The area mapped will be uncached. 
861  * 
862  * \par Mapping the SAREA
863  * For the SAREA,
864  * - \p offset will be ignored and should be set to zero,
865  * - \p size will be the desired size of the SAREA in bytes,
866  * - \p type will be DRM_SHM.
867  * 
868  * \par
869  * A shared memory area of the requested size will be created and locked in
870  * kernel memory. This area may be mapped into client-space by using the handle
871  * returned. 
872  * 
873  * \note May only be called by root.
874  *
875  * \internal
876  * This function is a wrapper around the DRM_IOCTL_ADD_MAP ioctl, passing
877  * the arguments in a drm_map structure.
878  */
879 int drmAddMap(int fd, drm_handle_t offset, drmSize size, drmMapType type,
880               drmMapFlags flags, drm_handle_t *handle)
881 {
882     drm_map_t map;
883
884     map.offset  = offset;
885     map.size    = size;
886     map.handle  = 0;
887     map.type    = type;
888     map.flags   = flags;
889     if (ioctl(fd, DRM_IOCTL_ADD_MAP, &map))
890         return -errno;
891     if (handle)
892         *handle = (drm_handle_t)map.handle;
893     return 0;
894 }
895
896 int drmRmMap(int fd, drm_handle_t handle)
897 {
898     drm_map_t map;
899
900     map.handle = (void *)handle;
901
902     if(ioctl(fd, DRM_IOCTL_RM_MAP, &map))
903         return -errno;
904     return 0;
905 }
906
907 /**
908  * Make buffers available for DMA transfers.
909  * 
910  * \param fd file descriptor.
911  * \param count number of buffers.
912  * \param size size of each buffer.
913  * \param flags buffer allocation flags.
914  * \param agp_offset offset in the AGP aperture 
915  *
916  * \return number of buffers allocated, negative on error.
917  *
918  * \internal
919  * This function is a wrapper around DRM_IOCTL_ADD_BUFS ioctl.
920  *
921  * \sa drm_buf_desc.
922  */
923 int drmAddBufs(int fd, int count, int size, drmBufDescFlags flags,
924                int agp_offset)
925 {
926     drm_buf_desc_t request;
927
928     request.count     = count;
929     request.size      = size;
930     request.low_mark  = 0;
931     request.high_mark = 0;
932     request.flags     = flags;
933     request.agp_start = agp_offset;
934
935     if (ioctl(fd, DRM_IOCTL_ADD_BUFS, &request))
936         return -errno;
937     return request.count;
938 }
939
940 int drmMarkBufs(int fd, double low, double high)
941 {
942     drm_buf_info_t info;
943     int            i;
944
945     info.count = 0;
946     info.list  = NULL;
947
948     if (ioctl(fd, DRM_IOCTL_INFO_BUFS, &info))
949         return -EINVAL;
950
951     if (!info.count)
952         return -EINVAL;
953
954     if (!(info.list = drmMalloc(info.count * sizeof(*info.list))))
955         return -ENOMEM;
956
957     if (ioctl(fd, DRM_IOCTL_INFO_BUFS, &info)) {
958         int retval = -errno;
959         drmFree(info.list);
960         return retval;
961     }
962
963     for (i = 0; i < info.count; i++) {
964         info.list[i].low_mark  = low  * info.list[i].count;
965         info.list[i].high_mark = high * info.list[i].count;
966         if (ioctl(fd, DRM_IOCTL_MARK_BUFS, &info.list[i])) {
967             int retval = -errno;
968             drmFree(info.list);
969             return retval;
970         }
971     }
972     drmFree(info.list);
973
974     return 0;
975 }
976
977 /**
978  * Free buffers.
979  *
980  * \param fd file descriptor.
981  * \param count number of buffers to free.
982  * \param list list of buffers to be freed.
983  *
984  * \return zero on success, or a negative value on failure.
985  * 
986  * \note This function is primarily used for debugging.
987  * 
988  * \internal
989  * This function is a wrapper around the DRM_IOCTL_FREE_BUFS ioctl, passing
990  * the arguments in a drm_buf_free structure.
991  */
992 int drmFreeBufs(int fd, int count, int *list)
993 {
994     drm_buf_free_t request;
995
996     request.count = count;
997     request.list  = list;
998     if (ioctl(fd, DRM_IOCTL_FREE_BUFS, &request))
999         return -errno;
1000     return 0;
1001 }
1002
1003
1004 /**
1005  * Close the device.
1006  *
1007  * \param fd file descriptor.
1008  *
1009  * \internal
1010  * This function closes the file descriptor.
1011  */
1012 int drmClose(int fd)
1013 {
1014     unsigned long key    = drmGetKeyFromFd(fd);
1015     drmHashEntry  *entry = drmGetEntry(fd);
1016
1017     drmHashDestroy(entry->tagTable);
1018     entry->fd       = 0;
1019     entry->f        = NULL;
1020     entry->tagTable = NULL;
1021
1022     drmHashDelete(drmHashTable, key);
1023     drmFree(entry);
1024
1025     return close(fd);
1026 }
1027
1028
1029 /**
1030  * Map a region of memory.
1031  *
1032  * \param fd file descriptor.
1033  * \param handle handle returned by drmAddMap().
1034  * \param size size in bytes. Must match the size used by drmAddMap().
1035  * \param address will contain the user-space virtual address where the mapping
1036  * begins.
1037  *
1038  * \return zero on success, or a negative value on failure.
1039  * 
1040  * \internal
1041  * This function is a wrapper for mmap().
1042  */
1043 int drmMap(int fd, drm_handle_t handle, drmSize size, drmAddressPtr address)
1044 {
1045     static unsigned long pagesize_mask = 0;
1046
1047     if (fd < 0)
1048         return -EINVAL;
1049
1050     if (!pagesize_mask)
1051         pagesize_mask = getpagesize() - 1;
1052
1053     size = (size + pagesize_mask) & ~pagesize_mask;
1054
1055     *address = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, handle);
1056     if (*address == MAP_FAILED)
1057         return -errno;
1058     return 0;
1059 }
1060
1061
1062 /**
1063  * Unmap mappings obtained with drmMap().
1064  *
1065  * \param address address as given by drmMap().
1066  * \param size size in bytes. Must match the size used by drmMap().
1067  * 
1068  * \return zero on success, or a negative value on failure.
1069  *
1070  * \internal
1071  * This function is a wrapper for munmap().
1072  */
1073 int drmUnmap(drmAddress address, drmSize size)
1074 {
1075     return munmap(address, size);
1076 }
1077
1078 drmBufInfoPtr drmGetBufInfo(int fd)
1079 {
1080     drm_buf_info_t info;
1081     drmBufInfoPtr  retval;
1082     int            i;
1083
1084     info.count = 0;
1085     info.list  = NULL;
1086
1087     if (ioctl(fd, DRM_IOCTL_INFO_BUFS, &info))
1088         return NULL;
1089
1090     if (info.count) {
1091         if (!(info.list = drmMalloc(info.count * sizeof(*info.list))))
1092             return NULL;
1093
1094         if (ioctl(fd, DRM_IOCTL_INFO_BUFS, &info)) {
1095             drmFree(info.list);
1096             return NULL;
1097         }
1098
1099         retval = drmMalloc(sizeof(*retval));
1100         retval->count = info.count;
1101         retval->list  = drmMalloc(info.count * sizeof(*retval->list));
1102         for (i = 0; i < info.count; i++) {
1103             retval->list[i].count     = info.list[i].count;
1104             retval->list[i].size      = info.list[i].size;
1105             retval->list[i].low_mark  = info.list[i].low_mark;
1106             retval->list[i].high_mark = info.list[i].high_mark;
1107         }
1108         drmFree(info.list);
1109         return retval;
1110     }
1111     return NULL;
1112 }
1113
1114 /**
1115  * Map all DMA buffers into client-virtual space.
1116  *
1117  * \param fd file descriptor.
1118  *
1119  * \return a pointer to a ::drmBufMap structure.
1120  *
1121  * \note The client may not use these buffers until obtaining buffer indices
1122  * with drmDMA().
1123  * 
1124  * \internal
1125  * This function calls the DRM_IOCTL_MAP_BUFS ioctl and copies the returned
1126  * information about the buffers in a drm_buf_map structure into the
1127  * client-visible data structures.
1128  */ 
1129 drmBufMapPtr drmMapBufs(int fd)
1130 {
1131     drm_buf_map_t bufs;
1132     drmBufMapPtr  retval;
1133     int           i;
1134
1135     bufs.count = 0;
1136     bufs.list  = NULL;
1137     bufs.virtual = NULL;
1138     if (ioctl(fd, DRM_IOCTL_MAP_BUFS, &bufs))
1139         return NULL;
1140
1141     if (!bufs.count)
1142         return NULL;
1143
1144         if (!(bufs.list = drmMalloc(bufs.count * sizeof(*bufs.list))))
1145             return NULL;
1146
1147         if (ioctl(fd, DRM_IOCTL_MAP_BUFS, &bufs)) {
1148             drmFree(bufs.list);
1149             return NULL;
1150         }
1151
1152         retval = drmMalloc(sizeof(*retval));
1153         retval->count = bufs.count;
1154         retval->list  = drmMalloc(bufs.count * sizeof(*retval->list));
1155         for (i = 0; i < bufs.count; i++) {
1156             retval->list[i].idx     = bufs.list[i].idx;
1157             retval->list[i].total   = bufs.list[i].total;
1158             retval->list[i].used    = 0;
1159             retval->list[i].address = bufs.list[i].address;
1160         }
1161
1162         drmFree(bufs.list);
1163         
1164         return retval;
1165 }
1166
1167
1168 /**
1169  * Unmap buffers allocated with drmMapBufs().
1170  *
1171  * \return zero on success, or negative value on failure.
1172  *
1173  * \internal
1174  * Calls munmap() for every buffer stored in \p bufs and frees the
1175  * memory allocated by drmMapBufs().
1176  */
1177 int drmUnmapBufs(drmBufMapPtr bufs)
1178 {
1179     int i;
1180
1181     for (i = 0; i < bufs->count; i++) {
1182         munmap(bufs->list[i].address, bufs->list[i].total);
1183     }
1184
1185     drmFree(bufs->list);
1186     drmFree(bufs);
1187         
1188     return 0;
1189 }
1190
1191
1192 #define DRM_DMA_RETRY           16
1193
1194 /**
1195  * Reserve DMA buffers.
1196  *
1197  * \param fd file descriptor.
1198  * \param request 
1199  * 
1200  * \return zero on success, or a negative value on failure.
1201  *
1202  * \internal
1203  * Assemble the arguments into a drm_dma structure and keeps issuing the
1204  * DRM_IOCTL_DMA ioctl until success or until maximum number of retries.
1205  */
1206 int drmDMA(int fd, drmDMAReqPtr request)
1207 {
1208     drm_dma_t dma;
1209     int ret, i = 0;
1210
1211     dma.context         = request->context;
1212     dma.send_count      = request->send_count;
1213     dma.send_indices    = request->send_list;
1214     dma.send_sizes      = request->send_sizes;
1215     dma.flags           = request->flags;
1216     dma.request_count   = request->request_count;
1217     dma.request_size    = request->request_size;
1218     dma.request_indices = request->request_list;
1219     dma.request_sizes   = request->request_sizes;
1220     dma.granted_count   = 0;
1221
1222     do {
1223         ret = ioctl( fd, DRM_IOCTL_DMA, &dma );
1224     } while ( ret && errno == EAGAIN && i++ < DRM_DMA_RETRY );
1225
1226     if ( ret == 0 ) {
1227         request->granted_count = dma.granted_count;
1228         return 0;
1229     } else {
1230         return -errno;
1231     }
1232 }
1233
1234
1235 /**
1236  * Obtain heavyweight hardware lock.
1237  *
1238  * \param fd file descriptor.
1239  * \param context context.
1240  * \param flags flags that determine the sate of the hardware when the function
1241  * returns.
1242  * 
1243  * \return always zero.
1244  * 
1245  * \internal
1246  * This function translates the arguments into a drm_lock structure and issue
1247  * the DRM_IOCTL_LOCK ioctl until the lock is successfully acquired.
1248  */
1249 int drmGetLock(int fd, drm_context_t context, drmLockFlags flags)
1250 {
1251     drm_lock_t lock;
1252
1253     lock.context = context;
1254     lock.flags   = 0;
1255     if (flags & DRM_LOCK_READY)      lock.flags |= _DRM_LOCK_READY;
1256     if (flags & DRM_LOCK_QUIESCENT)  lock.flags |= _DRM_LOCK_QUIESCENT;
1257     if (flags & DRM_LOCK_FLUSH)      lock.flags |= _DRM_LOCK_FLUSH;
1258     if (flags & DRM_LOCK_FLUSH_ALL)  lock.flags |= _DRM_LOCK_FLUSH_ALL;
1259     if (flags & DRM_HALT_ALL_QUEUES) lock.flags |= _DRM_HALT_ALL_QUEUES;
1260     if (flags & DRM_HALT_CUR_QUEUES) lock.flags |= _DRM_HALT_CUR_QUEUES;
1261
1262     while (ioctl(fd, DRM_IOCTL_LOCK, &lock))
1263         ;
1264     return 0;
1265 }
1266
1267 /**
1268  * Release the hardware lock.
1269  *
1270  * \param fd file descriptor.
1271  * \param context context.
1272  * 
1273  * \return zero on success, or a negative value on failure.
1274  * 
1275  * \internal
1276  * This function is a wrapper around the DRM_IOCTL_UNLOCK ioctl, passing the
1277  * argument in a drm_lock structure.
1278  */
1279 int drmUnlock(int fd, drm_context_t context)
1280 {
1281     drm_lock_t lock;
1282
1283     lock.context = context;
1284     lock.flags   = 0;
1285     return ioctl(fd, DRM_IOCTL_UNLOCK, &lock);
1286 }
1287
1288 drm_context_t *drmGetReservedContextList(int fd, int *count)
1289 {
1290     drm_ctx_res_t res;
1291     drm_ctx_t     *list;
1292     drm_context_t * retval;
1293     int           i;
1294
1295     res.count    = 0;
1296     res.contexts = NULL;
1297     if (ioctl(fd, DRM_IOCTL_RES_CTX, &res))
1298         return NULL;
1299
1300     if (!res.count)
1301         return NULL;
1302
1303     if (!(list   = drmMalloc(res.count * sizeof(*list))))
1304         return NULL;
1305     if (!(retval = drmMalloc(res.count * sizeof(*retval)))) {
1306         drmFree(list);
1307         return NULL;
1308     }
1309
1310     res.contexts = list;
1311     if (ioctl(fd, DRM_IOCTL_RES_CTX, &res))
1312         return NULL;
1313
1314     for (i = 0; i < res.count; i++)
1315         retval[i] = list[i].handle;
1316     drmFree(list);
1317
1318     *count = res.count;
1319     return retval;
1320 }
1321
1322 void drmFreeReservedContextList(drm_context_t *pt)
1323 {
1324     drmFree(pt);
1325 }
1326
1327 /**
1328  * Create context.
1329  *
1330  * Used by the X server during GLXContext initialization. This causes
1331  * per-context kernel-level resources to be allocated.
1332  *
1333  * \param fd file descriptor.
1334  * \param handle is set on success. To be used by the client when requesting DMA
1335  * dispatch with drmDMA().
1336  * 
1337  * \return zero on success, or a negative value on failure.
1338  * 
1339  * \note May only be called by root.
1340  * 
1341  * \internal
1342  * This function is a wrapper around the DRM_IOCTL_ADD_CTX ioctl, passing the
1343  * argument in a drm_ctx structure.
1344  */
1345 int drmCreateContext(int fd, drm_context_t *handle)
1346 {
1347     drm_ctx_t ctx;
1348
1349     ctx.flags = 0;      /* Modified with functions below */
1350     if (ioctl(fd, DRM_IOCTL_ADD_CTX, &ctx))
1351         return -errno;
1352     *handle = ctx.handle;
1353     return 0;
1354 }
1355
1356 int drmSwitchToContext(int fd, drm_context_t context)
1357 {
1358     drm_ctx_t ctx;
1359
1360     ctx.handle = context;
1361     if (ioctl(fd, DRM_IOCTL_SWITCH_CTX, &ctx))
1362         return -errno;
1363     return 0;
1364 }
1365
1366 int drmSetContextFlags(int fd, drm_context_t context, drm_context_tFlags flags)
1367 {
1368     drm_ctx_t ctx;
1369
1370     /*
1371      * Context preserving means that no context switches are done between DMA
1372      * buffers from one context and the next.  This is suitable for use in the
1373      * X server (which promises to maintain hardware context), or in the
1374      * client-side library when buffers are swapped on behalf of two threads.
1375      */
1376     ctx.handle = context;
1377     ctx.flags  = 0;
1378     if (flags & DRM_CONTEXT_PRESERVED)
1379         ctx.flags |= _DRM_CONTEXT_PRESERVED;
1380     if (flags & DRM_CONTEXT_2DONLY)
1381         ctx.flags |= _DRM_CONTEXT_2DONLY;
1382     if (ioctl(fd, DRM_IOCTL_MOD_CTX, &ctx))
1383         return -errno;
1384     return 0;
1385 }
1386
1387 int drmGetContextFlags(int fd, drm_context_t context,
1388                        drm_context_tFlagsPtr flags)
1389 {
1390     drm_ctx_t ctx;
1391
1392     ctx.handle = context;
1393     if (ioctl(fd, DRM_IOCTL_GET_CTX, &ctx))
1394         return -errno;
1395     *flags = 0;
1396     if (ctx.flags & _DRM_CONTEXT_PRESERVED)
1397         *flags |= DRM_CONTEXT_PRESERVED;
1398     if (ctx.flags & _DRM_CONTEXT_2DONLY)
1399         *flags |= DRM_CONTEXT_2DONLY;
1400     return 0;
1401 }
1402
1403 /**
1404  * Destroy context.
1405  *
1406  * Free any kernel-level resources allocated with drmCreateContext() associated
1407  * with the context.
1408  * 
1409  * \param fd file descriptor.
1410  * \param handle handle given by drmCreateContext().
1411  * 
1412  * \return zero on success, or a negative value on failure.
1413  * 
1414  * \note May only be called by root.
1415  * 
1416  * \internal
1417  * This function is a wrapper around the DRM_IOCTL_RM_CTX ioctl, passing the
1418  * argument in a drm_ctx structure.
1419  */
1420 int drmDestroyContext(int fd, drm_context_t handle)
1421 {
1422     drm_ctx_t ctx;
1423     ctx.handle = handle;
1424     if (ioctl(fd, DRM_IOCTL_RM_CTX, &ctx))
1425         return -errno;
1426     return 0;
1427 }
1428
1429 int drmCreateDrawable(int fd, drm_drawable_t *handle)
1430 {
1431     drm_draw_t draw;
1432     if (ioctl(fd, DRM_IOCTL_ADD_DRAW, &draw))
1433         return -errno;
1434     *handle = draw.handle;
1435     return 0;
1436 }
1437
1438 int drmDestroyDrawable(int fd, drm_drawable_t handle)
1439 {
1440     drm_draw_t draw;
1441     draw.handle = handle;
1442     if (ioctl(fd, DRM_IOCTL_RM_DRAW, &draw))
1443         return -errno;
1444     return 0;
1445 }
1446
1447 int drmUpdateDrawableInfo(int fd, drm_drawable_t handle,
1448                            drm_drawable_info_type_t type, unsigned int num,
1449                            void *data)
1450 {
1451     drm_update_draw_t update;
1452
1453     update.handle = handle;
1454     update.type = type;
1455     update.num = num;
1456     update.data = (unsigned long long)(unsigned long)data;
1457
1458     if (ioctl(fd, DRM_IOCTL_UPDATE_DRAW, &update))
1459         return -errno;
1460
1461     return 0;
1462 }
1463
1464 /**
1465  * Acquire the AGP device.
1466  *
1467  * Must be called before any of the other AGP related calls.
1468  *
1469  * \param fd file descriptor.
1470  * 
1471  * \return zero on success, or a negative value on failure.
1472  * 
1473  * \internal
1474  * This function is a wrapper around the DRM_IOCTL_AGP_ACQUIRE ioctl.
1475  */
1476 int drmAgpAcquire(int fd)
1477 {
1478     if (ioctl(fd, DRM_IOCTL_AGP_ACQUIRE, NULL))
1479         return -errno;
1480     return 0;
1481 }
1482
1483
1484 /**
1485  * Release the AGP device.
1486  *
1487  * \param fd file descriptor.
1488  * 
1489  * \return zero on success, or a negative value on failure.
1490  * 
1491  * \internal
1492  * This function is a wrapper around the DRM_IOCTL_AGP_RELEASE ioctl.
1493  */
1494 int drmAgpRelease(int fd)
1495 {
1496     if (ioctl(fd, DRM_IOCTL_AGP_RELEASE, NULL))
1497         return -errno;
1498     return 0;
1499 }
1500
1501
1502 /**
1503  * Set the AGP mode.
1504  *
1505  * \param fd file descriptor.
1506  * \param mode AGP mode.
1507  * 
1508  * \return zero on success, or a negative value on failure.
1509  * 
1510  * \internal
1511  * This function is a wrapper around the DRM_IOCTL_AGP_ENABLE ioctl, passing the
1512  * argument in a drm_agp_mode structure.
1513  */
1514 int drmAgpEnable(int fd, unsigned long mode)
1515 {
1516     drm_agp_mode_t m;
1517
1518     m.mode = mode;
1519     if (ioctl(fd, DRM_IOCTL_AGP_ENABLE, &m))
1520         return -errno;
1521     return 0;
1522 }
1523
1524
1525 /**
1526  * Allocate a chunk of AGP memory.
1527  *
1528  * \param fd file descriptor.
1529  * \param size requested memory size in bytes. Will be rounded to page boundary.
1530  * \param type type of memory to allocate.
1531  * \param address if not zero, will be set to the physical address of the
1532  * allocated memory.
1533  * \param handle on success will be set to a handle of the allocated memory.
1534  * 
1535  * \return zero on success, or a negative value on failure.
1536  * 
1537  * \internal
1538  * This function is a wrapper around the DRM_IOCTL_AGP_ALLOC ioctl, passing the
1539  * arguments in a drm_agp_buffer structure.
1540  */
1541 int drmAgpAlloc(int fd, unsigned long size, unsigned long type,
1542                 unsigned long *address, drm_handle_t *handle)
1543 {
1544     drm_agp_buffer_t b;
1545
1546     *handle = DRM_AGP_NO_HANDLE;
1547     b.size   = size;
1548     b.handle = 0;
1549     b.type   = type;
1550     if (ioctl(fd, DRM_IOCTL_AGP_ALLOC, &b))
1551         return -errno;
1552     if (address != 0UL)
1553         *address = b.physical;
1554     *handle = b.handle;
1555     return 0;
1556 }
1557
1558
1559 /**
1560  * Free a chunk of AGP memory.
1561  *
1562  * \param fd file descriptor.
1563  * \param handle handle to the allocated memory, as given by drmAgpAllocate().
1564  * 
1565  * \return zero on success, or a negative value on failure.
1566  * 
1567  * \internal
1568  * This function is a wrapper around the DRM_IOCTL_AGP_FREE ioctl, passing the
1569  * argument in a drm_agp_buffer structure.
1570  */
1571 int drmAgpFree(int fd, drm_handle_t handle)
1572 {
1573     drm_agp_buffer_t b;
1574
1575     b.size   = 0;
1576     b.handle = handle;
1577     if (ioctl(fd, DRM_IOCTL_AGP_FREE, &b))
1578         return -errno;
1579     return 0;
1580 }
1581
1582
1583 /**
1584  * Bind a chunk of AGP memory.
1585  *
1586  * \param fd file descriptor.
1587  * \param handle handle to the allocated memory, as given by drmAgpAllocate().
1588  * \param offset offset in bytes. It will round to page boundary.
1589  * 
1590  * \return zero on success, or a negative value on failure.
1591  * 
1592  * \internal
1593  * This function is a wrapper around the DRM_IOCTL_AGP_BIND ioctl, passing the
1594  * argument in a drm_agp_binding structure.
1595  */
1596 int drmAgpBind(int fd, drm_handle_t handle, unsigned long offset)
1597 {
1598     drm_agp_binding_t b;
1599
1600     b.handle = handle;
1601     b.offset = offset;
1602     if (ioctl(fd, DRM_IOCTL_AGP_BIND, &b))
1603         return -errno;
1604     return 0;
1605 }
1606
1607
1608 /**
1609  * Unbind a chunk of AGP memory.
1610  *
1611  * \param fd file descriptor.
1612  * \param handle handle to the allocated memory, as given by drmAgpAllocate().
1613  * 
1614  * \return zero on success, or a negative value on failure.
1615  * 
1616  * \internal
1617  * This function is a wrapper around the DRM_IOCTL_AGP_UNBIND ioctl, passing
1618  * the argument in a drm_agp_binding structure.
1619  */
1620 int drmAgpUnbind(int fd, drm_handle_t handle)
1621 {
1622     drm_agp_binding_t b;
1623
1624     b.handle = handle;
1625     b.offset = 0;
1626     if (ioctl(fd, DRM_IOCTL_AGP_UNBIND, &b))
1627         return -errno;
1628     return 0;
1629 }
1630
1631
1632 /**
1633  * Get AGP driver major version number.
1634  *
1635  * \param fd file descriptor.
1636  * 
1637  * \return major version number on success, or a negative value on failure..
1638  * 
1639  * \internal
1640  * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1641  * necessary information in a drm_agp_info structure.
1642  */
1643 int drmAgpVersionMajor(int fd)
1644 {
1645     drm_agp_info_t i;
1646
1647     if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i))
1648         return -errno;
1649     return i.agp_version_major;
1650 }
1651
1652
1653 /**
1654  * Get AGP driver minor version number.
1655  *
1656  * \param fd file descriptor.
1657  * 
1658  * \return minor version number on success, or a negative value on failure.
1659  * 
1660  * \internal
1661  * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1662  * necessary information in a drm_agp_info structure.
1663  */
1664 int drmAgpVersionMinor(int fd)
1665 {
1666     drm_agp_info_t i;
1667
1668     if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i))
1669         return -errno;
1670     return i.agp_version_minor;
1671 }
1672
1673
1674 /**
1675  * Get AGP mode.
1676  *
1677  * \param fd file descriptor.
1678  * 
1679  * \return mode on success, or zero on failure.
1680  * 
1681  * \internal
1682  * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1683  * necessary information in a drm_agp_info structure.
1684  */
1685 unsigned long drmAgpGetMode(int fd)
1686 {
1687     drm_agp_info_t i;
1688
1689     if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i))
1690         return 0;
1691     return i.mode;
1692 }
1693
1694
1695 /**
1696  * Get AGP aperture base.
1697  *
1698  * \param fd file descriptor.
1699  * 
1700  * \return aperture base on success, zero on failure.
1701  * 
1702  * \internal
1703  * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1704  * necessary information in a drm_agp_info structure.
1705  */
1706 unsigned long drmAgpBase(int fd)
1707 {
1708     drm_agp_info_t i;
1709
1710     if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i))
1711         return 0;
1712     return i.aperture_base;
1713 }
1714
1715
1716 /**
1717  * Get AGP aperture size.
1718  *
1719  * \param fd file descriptor.
1720  * 
1721  * \return aperture size on success, zero on failure.
1722  * 
1723  * \internal
1724  * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1725  * necessary information in a drm_agp_info structure.
1726  */
1727 unsigned long drmAgpSize(int fd)
1728 {
1729     drm_agp_info_t i;
1730
1731     if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i))
1732         return 0;
1733     return i.aperture_size;
1734 }
1735
1736
1737 /**
1738  * Get used AGP memory.
1739  *
1740  * \param fd file descriptor.
1741  * 
1742  * \return memory used on success, or zero on failure.
1743  * 
1744  * \internal
1745  * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1746  * necessary information in a drm_agp_info structure.
1747  */
1748 unsigned long drmAgpMemoryUsed(int fd)
1749 {
1750     drm_agp_info_t i;
1751
1752     if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i))
1753         return 0;
1754     return i.memory_used;
1755 }
1756
1757
1758 /**
1759  * Get available AGP memory.
1760  *
1761  * \param fd file descriptor.
1762  * 
1763  * \return memory available on success, or zero on failure.
1764  * 
1765  * \internal
1766  * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1767  * necessary information in a drm_agp_info structure.
1768  */
1769 unsigned long drmAgpMemoryAvail(int fd)
1770 {
1771     drm_agp_info_t i;
1772
1773     if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i))
1774         return 0;
1775     return i.memory_allowed;
1776 }
1777
1778
1779 /**
1780  * Get hardware vendor ID.
1781  *
1782  * \param fd file descriptor.
1783  * 
1784  * \return vendor ID on success, or zero on failure.
1785  * 
1786  * \internal
1787  * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1788  * necessary information in a drm_agp_info structure.
1789  */
1790 unsigned int drmAgpVendorId(int fd)
1791 {
1792     drm_agp_info_t i;
1793
1794     if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i))
1795         return 0;
1796     return i.id_vendor;
1797 }
1798
1799
1800 /**
1801  * Get hardware device ID.
1802  *
1803  * \param fd file descriptor.
1804  * 
1805  * \return zero on success, or zero on failure.
1806  * 
1807  * \internal
1808  * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1809  * necessary information in a drm_agp_info structure.
1810  */
1811 unsigned int drmAgpDeviceId(int fd)
1812 {
1813     drm_agp_info_t i;
1814
1815     if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i))
1816         return 0;
1817     return i.id_device;
1818 }
1819
1820 int drmScatterGatherAlloc(int fd, unsigned long size, drm_handle_t *handle)
1821 {
1822     drm_scatter_gather_t sg;
1823
1824     *handle = 0;
1825     sg.size   = size;
1826     sg.handle = 0;
1827     if (ioctl(fd, DRM_IOCTL_SG_ALLOC, &sg))
1828         return -errno;
1829     *handle = sg.handle;
1830     return 0;
1831 }
1832
1833 int drmScatterGatherFree(int fd, drm_handle_t handle)
1834 {
1835     drm_scatter_gather_t sg;
1836
1837     sg.size   = 0;
1838     sg.handle = handle;
1839     if (ioctl(fd, DRM_IOCTL_SG_FREE, &sg))
1840         return -errno;
1841     return 0;
1842 }
1843
1844 /**
1845  * Wait for VBLANK.
1846  *
1847  * \param fd file descriptor.
1848  * \param vbl pointer to a drmVBlank structure.
1849  * 
1850  * \return zero on success, or a negative value on failure.
1851  * 
1852  * \internal
1853  * This function is a wrapper around the DRM_IOCTL_WAIT_VBLANK ioctl.
1854  */
1855 int drmWaitVBlank(int fd, drmVBlankPtr vbl)
1856 {
1857     int ret;
1858
1859     do {
1860        ret = ioctl(fd, DRM_IOCTL_WAIT_VBLANK, vbl);
1861        vbl->request.type &= ~DRM_VBLANK_RELATIVE;
1862     } while (ret && errno == EINTR);
1863
1864     return ret;
1865 }
1866
1867 int drmError(int err, const char *label)
1868 {
1869     switch (err) {
1870     case DRM_ERR_NO_DEVICE:
1871         fprintf(stderr, "%s: no device\n", label);
1872         break;
1873     case DRM_ERR_NO_ACCESS:
1874         fprintf(stderr, "%s: no access\n", label);
1875         break;
1876     case DRM_ERR_NOT_ROOT:
1877         fprintf(stderr, "%s: not root\n", label);
1878         break;
1879     case DRM_ERR_INVALID:
1880         fprintf(stderr, "%s: invalid args\n", label);
1881         break;
1882     default:
1883         if (err < 0)
1884             err = -err;
1885         fprintf( stderr, "%s: error %d (%s)\n", label, err, strerror(err) );
1886         break;
1887     }
1888
1889     return 1;
1890 }
1891
1892 /**
1893  * Install IRQ handler.
1894  *
1895  * \param fd file descriptor.
1896  * \param irq IRQ number.
1897  * 
1898  * \return zero on success, or a negative value on failure.
1899  * 
1900  * \internal
1901  * This function is a wrapper around the DRM_IOCTL_CONTROL ioctl, passing the
1902  * argument in a drm_control structure.
1903  */
1904 int drmCtlInstHandler(int fd, int irq)
1905 {
1906     drm_control_t ctl;
1907
1908     ctl.func  = DRM_INST_HANDLER;
1909     ctl.irq   = irq;
1910     if (ioctl(fd, DRM_IOCTL_CONTROL, &ctl))
1911         return -errno;
1912     return 0;
1913 }
1914
1915
1916 /**
1917  * Uninstall IRQ handler.
1918  *
1919  * \param fd file descriptor.
1920  * 
1921  * \return zero on success, or a negative value on failure.
1922  * 
1923  * \internal
1924  * This function is a wrapper around the DRM_IOCTL_CONTROL ioctl, passing the
1925  * argument in a drm_control structure.
1926  */
1927 int drmCtlUninstHandler(int fd)
1928 {
1929     drm_control_t ctl;
1930
1931     ctl.func  = DRM_UNINST_HANDLER;
1932     ctl.irq   = 0;
1933     if (ioctl(fd, DRM_IOCTL_CONTROL, &ctl))
1934         return -errno;
1935     return 0;
1936 }
1937
1938 int drmFinish(int fd, int context, drmLockFlags flags)
1939 {
1940     drm_lock_t lock;
1941
1942     lock.context = context;
1943     lock.flags   = 0;
1944     if (flags & DRM_LOCK_READY)      lock.flags |= _DRM_LOCK_READY;
1945     if (flags & DRM_LOCK_QUIESCENT)  lock.flags |= _DRM_LOCK_QUIESCENT;
1946     if (flags & DRM_LOCK_FLUSH)      lock.flags |= _DRM_LOCK_FLUSH;
1947     if (flags & DRM_LOCK_FLUSH_ALL)  lock.flags |= _DRM_LOCK_FLUSH_ALL;
1948     if (flags & DRM_HALT_ALL_QUEUES) lock.flags |= _DRM_HALT_ALL_QUEUES;
1949     if (flags & DRM_HALT_CUR_QUEUES) lock.flags |= _DRM_HALT_CUR_QUEUES;
1950     if (ioctl(fd, DRM_IOCTL_FINISH, &lock))
1951         return -errno;
1952     return 0;
1953 }
1954
1955 /**
1956  * Get IRQ from bus ID.
1957  *
1958  * \param fd file descriptor.
1959  * \param busnum bus number.
1960  * \param devnum device number.
1961  * \param funcnum function number.
1962  * 
1963  * \return IRQ number on success, or a negative value on failure.
1964  * 
1965  * \internal
1966  * This function is a wrapper around the DRM_IOCTL_IRQ_BUSID ioctl, passing the
1967  * arguments in a drm_irq_busid structure.
1968  */
1969 int drmGetInterruptFromBusID(int fd, int busnum, int devnum, int funcnum)
1970 {
1971     drm_irq_busid_t p;
1972
1973     p.busnum  = busnum;
1974     p.devnum  = devnum;
1975     p.funcnum = funcnum;
1976     if (ioctl(fd, DRM_IOCTL_IRQ_BUSID, &p))
1977         return -errno;
1978     return p.irq;
1979 }
1980
1981 int drmAddContextTag(int fd, drm_context_t context, void *tag)
1982 {
1983     drmHashEntry  *entry = drmGetEntry(fd);
1984
1985     if (drmHashInsert(entry->tagTable, context, tag)) {
1986         drmHashDelete(entry->tagTable, context);
1987         drmHashInsert(entry->tagTable, context, tag);
1988     }
1989     return 0;
1990 }
1991
1992 int drmDelContextTag(int fd, drm_context_t context)
1993 {
1994     drmHashEntry  *entry = drmGetEntry(fd);
1995
1996     return drmHashDelete(entry->tagTable, context);
1997 }
1998
1999 void *drmGetContextTag(int fd, drm_context_t context)
2000 {
2001     drmHashEntry  *entry = drmGetEntry(fd);
2002     void          *value;
2003
2004     if (drmHashLookup(entry->tagTable, context, &value))
2005         return NULL;
2006
2007     return value;
2008 }
2009
2010 int drmAddContextPrivateMapping(int fd, drm_context_t ctx_id,
2011                                 drm_handle_t handle)
2012 {
2013     drm_ctx_priv_map_t map;
2014
2015     map.ctx_id = ctx_id;
2016     map.handle = (void *)handle;
2017
2018     if (ioctl(fd, DRM_IOCTL_SET_SAREA_CTX, &map))
2019         return -errno;
2020     return 0;
2021 }
2022
2023 int drmGetContextPrivateMapping(int fd, drm_context_t ctx_id,
2024                                 drm_handle_t *handle)
2025 {
2026     drm_ctx_priv_map_t map;
2027
2028     map.ctx_id = ctx_id;
2029
2030     if (ioctl(fd, DRM_IOCTL_GET_SAREA_CTX, &map))
2031         return -errno;
2032     if (handle)
2033         *handle = (drm_handle_t)map.handle;
2034
2035     return 0;
2036 }
2037
2038 int drmGetMap(int fd, int idx, drm_handle_t *offset, drmSize *size,
2039               drmMapType *type, drmMapFlags *flags, drm_handle_t *handle,
2040               int *mtrr)
2041 {
2042     drm_map_t map;
2043
2044     map.offset = idx;
2045     if (ioctl(fd, DRM_IOCTL_GET_MAP, &map))
2046         return -errno;
2047     *offset = map.offset;
2048     *size   = map.size;
2049     *type   = map.type;
2050     *flags  = map.flags;
2051     *handle = (unsigned long)map.handle;
2052     *mtrr   = map.mtrr;
2053     return 0;
2054 }
2055
2056 int drmGetClient(int fd, int idx, int *auth, int *pid, int *uid,
2057                  unsigned long *magic, unsigned long *iocs)
2058 {
2059     drm_client_t client;
2060
2061     client.idx = idx;
2062     if (ioctl(fd, DRM_IOCTL_GET_CLIENT, &client))
2063         return -errno;
2064     *auth      = client.auth;
2065     *pid       = client.pid;
2066     *uid       = client.uid;
2067     *magic     = client.magic;
2068     *iocs      = client.iocs;
2069     return 0;
2070 }
2071
2072 int drmGetStats(int fd, drmStatsT *stats)
2073 {
2074     drm_stats_t s;
2075     int         i;
2076
2077     if (ioctl(fd, DRM_IOCTL_GET_STATS, &s))
2078         return -errno;
2079
2080     stats->count = 0;
2081     memset(stats, 0, sizeof(*stats));
2082     if (s.count > sizeof(stats->data)/sizeof(stats->data[0]))
2083         return -1;
2084
2085 #define SET_VALUE                              \
2086     stats->data[i].long_format = "%-20.20s";   \
2087     stats->data[i].rate_format = "%8.8s";      \
2088     stats->data[i].isvalue     = 1;            \
2089     stats->data[i].verbose     = 0
2090
2091 #define SET_COUNT                              \
2092     stats->data[i].long_format = "%-20.20s";   \
2093     stats->data[i].rate_format = "%5.5s";      \
2094     stats->data[i].isvalue     = 0;            \
2095     stats->data[i].mult_names  = "kgm";        \
2096     stats->data[i].mult        = 1000;         \
2097     stats->data[i].verbose     = 0
2098
2099 #define SET_BYTE                               \
2100     stats->data[i].long_format = "%-20.20s";   \
2101     stats->data[i].rate_format = "%5.5s";      \
2102     stats->data[i].isvalue     = 0;            \
2103     stats->data[i].mult_names  = "KGM";        \
2104     stats->data[i].mult        = 1024;         \
2105     stats->data[i].verbose     = 0
2106
2107
2108     stats->count = s.count;
2109     for (i = 0; i < s.count; i++) {
2110         stats->data[i].value = s.data[i].value;
2111         switch (s.data[i].type) {
2112         case _DRM_STAT_LOCK:
2113             stats->data[i].long_name = "Lock";
2114             stats->data[i].rate_name = "Lock";
2115             SET_VALUE;
2116             break;
2117         case _DRM_STAT_OPENS:
2118             stats->data[i].long_name = "Opens";
2119             stats->data[i].rate_name = "O";
2120             SET_COUNT;
2121             stats->data[i].verbose   = 1;
2122             break;
2123         case _DRM_STAT_CLOSES:
2124             stats->data[i].long_name = "Closes";
2125             stats->data[i].rate_name = "Lock";
2126             SET_COUNT;
2127             stats->data[i].verbose   = 1;
2128             break;
2129         case _DRM_STAT_IOCTLS:
2130             stats->data[i].long_name = "Ioctls";
2131             stats->data[i].rate_name = "Ioc/s";
2132             SET_COUNT;
2133             break;
2134         case _DRM_STAT_LOCKS:
2135             stats->data[i].long_name = "Locks";
2136             stats->data[i].rate_name = "Lck/s";
2137             SET_COUNT;
2138             break;
2139         case _DRM_STAT_UNLOCKS:
2140             stats->data[i].long_name = "Unlocks";
2141             stats->data[i].rate_name = "Unl/s";
2142             SET_COUNT;
2143             break;
2144         case _DRM_STAT_IRQ:
2145             stats->data[i].long_name = "IRQs";
2146             stats->data[i].rate_name = "IRQ/s";
2147             SET_COUNT;
2148             break;
2149         case _DRM_STAT_PRIMARY:
2150             stats->data[i].long_name = "Primary Bytes";
2151             stats->data[i].rate_name = "PB/s";
2152             SET_BYTE;
2153             break;
2154         case _DRM_STAT_SECONDARY:
2155             stats->data[i].long_name = "Secondary Bytes";
2156             stats->data[i].rate_name = "SB/s";
2157             SET_BYTE;
2158             break;
2159         case _DRM_STAT_DMA:
2160             stats->data[i].long_name = "DMA";
2161             stats->data[i].rate_name = "DMA/s";
2162             SET_COUNT;
2163             break;
2164         case _DRM_STAT_SPECIAL:
2165             stats->data[i].long_name = "Special DMA";
2166             stats->data[i].rate_name = "dma/s";
2167             SET_COUNT;
2168             break;
2169         case _DRM_STAT_MISSED:
2170             stats->data[i].long_name = "Miss";
2171             stats->data[i].rate_name = "Ms/s";
2172             SET_COUNT;
2173             break;
2174         case _DRM_STAT_VALUE:
2175             stats->data[i].long_name = "Value";
2176             stats->data[i].rate_name = "Value";
2177             SET_VALUE;
2178             break;
2179         case _DRM_STAT_BYTE:
2180             stats->data[i].long_name = "Bytes";
2181             stats->data[i].rate_name = "B/s";
2182             SET_BYTE;
2183             break;
2184         case _DRM_STAT_COUNT:
2185         default:
2186             stats->data[i].long_name = "Count";
2187             stats->data[i].rate_name = "Cnt/s";
2188             SET_COUNT;
2189             break;
2190         }
2191     }
2192     return 0;
2193 }
2194
2195 /**
2196  * Issue a set-version ioctl.
2197  *
2198  * \param fd file descriptor.
2199  * \param drmCommandIndex command index 
2200  * \param data source pointer of the data to be read and written.
2201  * \param size size of the data to be read and written.
2202  * 
2203  * \return zero on success, or a negative value on failure.
2204  * 
2205  * \internal
2206  * It issues a read-write ioctl given by 
2207  * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
2208  */
2209 int drmSetInterfaceVersion(int fd, drmSetVersion *version)
2210 {
2211     int retcode = 0;
2212     drm_set_version_t sv;
2213
2214     sv.drm_di_major = version->drm_di_major;
2215     sv.drm_di_minor = version->drm_di_minor;
2216     sv.drm_dd_major = version->drm_dd_major;
2217     sv.drm_dd_minor = version->drm_dd_minor;
2218
2219     if (ioctl(fd, DRM_IOCTL_SET_VERSION, &sv)) {
2220         retcode = -errno;
2221     }
2222
2223     version->drm_di_major = sv.drm_di_major;
2224     version->drm_di_minor = sv.drm_di_minor;
2225     version->drm_dd_major = sv.drm_dd_major;
2226     version->drm_dd_minor = sv.drm_dd_minor;
2227
2228     return retcode;
2229 }
2230
2231 /**
2232  * Send a device-specific command.
2233  *
2234  * \param fd file descriptor.
2235  * \param drmCommandIndex command index 
2236  * 
2237  * \return zero on success, or a negative value on failure.
2238  * 
2239  * \internal
2240  * It issues a ioctl given by 
2241  * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
2242  */
2243 int drmCommandNone(int fd, unsigned long drmCommandIndex)
2244 {
2245     void *data = NULL; /* dummy */
2246     unsigned long request;
2247
2248     request = DRM_IO( DRM_COMMAND_BASE + drmCommandIndex);
2249
2250     if (ioctl(fd, request, data)) {
2251         return -errno;
2252     }
2253     return 0;
2254 }
2255
2256
2257 /**
2258  * Send a device-specific read command.
2259  *
2260  * \param fd file descriptor.
2261  * \param drmCommandIndex command index 
2262  * \param data destination pointer of the data to be read.
2263  * \param size size of the data to be read.
2264  * 
2265  * \return zero on success, or a negative value on failure.
2266  *
2267  * \internal
2268  * It issues a read ioctl given by 
2269  * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
2270  */
2271 int drmCommandRead(int fd, unsigned long drmCommandIndex, void *data,
2272                    unsigned long size)
2273 {
2274     unsigned long request;
2275
2276     request = DRM_IOC( DRM_IOC_READ, DRM_IOCTL_BASE, 
2277         DRM_COMMAND_BASE + drmCommandIndex, size);
2278
2279     if (ioctl(fd, request, data)) {
2280         return -errno;
2281     }
2282     return 0;
2283 }
2284
2285
2286 /**
2287  * Send a device-specific write command.
2288  *
2289  * \param fd file descriptor.
2290  * \param drmCommandIndex command index 
2291  * \param data source pointer of the data to be written.
2292  * \param size size of the data to be written.
2293  * 
2294  * \return zero on success, or a negative value on failure.
2295  * 
2296  * \internal
2297  * It issues a write ioctl given by 
2298  * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
2299  */
2300 int drmCommandWrite(int fd, unsigned long drmCommandIndex, void *data,
2301                     unsigned long size)
2302 {
2303     unsigned long request;
2304
2305     request = DRM_IOC( DRM_IOC_WRITE, DRM_IOCTL_BASE, 
2306         DRM_COMMAND_BASE + drmCommandIndex, size);
2307
2308     if (ioctl(fd, request, data)) {
2309         return -errno;
2310     }
2311     return 0;
2312 }
2313
2314
2315 /**
2316  * Send a device-specific read-write command.
2317  *
2318  * \param fd file descriptor.
2319  * \param drmCommandIndex command index 
2320  * \param data source pointer of the data to be read and written.
2321  * \param size size of the data to be read and written.
2322  * 
2323  * \return zero on success, or a negative value on failure.
2324  * 
2325  * \internal
2326  * It issues a read-write ioctl given by 
2327  * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
2328  */
2329 int drmCommandWriteRead(int fd, unsigned long drmCommandIndex, void *data,
2330                         unsigned long size)
2331 {
2332     unsigned long request;
2333
2334     request = DRM_IOC( DRM_IOC_READ|DRM_IOC_WRITE, DRM_IOCTL_BASE, 
2335         DRM_COMMAND_BASE + drmCommandIndex, size);
2336
2337     if (ioctl(fd, request, data)) {
2338         return -errno;
2339     }
2340     return 0;
2341 }
2342
2343
2344 /*
2345  * Valid flags are 
2346  * DRM_FENCE_FLAG_EMIT
2347  * DRM_FENCE_FLAG_SHAREABLE
2348  * DRM_FENCE_MASK_DRIVER
2349  */
2350
2351 int drmFenceCreate(int fd, unsigned flags, int fence_class, unsigned type,
2352                    drmFence *fence)
2353 {
2354     drm_fence_arg_t arg;
2355
2356     memset(&arg, 0, sizeof(arg));
2357     arg.flags = flags;
2358     arg.type = type;
2359     arg.fence_class = fence_class;
2360
2361     if (ioctl(fd, DRM_IOCTL_FENCE_CREATE, &arg))
2362         return -errno;
2363     fence->handle = arg.handle;
2364     fence->fence_class = arg.fence_class;
2365     fence->type = arg.type;
2366     fence->flags = arg.flags;
2367     fence->signaled = 0;
2368     return 0;
2369 }
2370
2371 /*
2372  * Valid flags are 
2373  * DRM_FENCE_FLAG_SHAREABLE
2374  * DRM_FENCE_MASK_DRIVER
2375  */
2376
2377 int drmFenceBuffers(int fd, unsigned flags, uint32_t fence_class, drmFence *fence)
2378 {
2379     drm_fence_arg_t arg;
2380
2381     memset(&arg, 0, sizeof(arg));
2382     arg.flags = flags;
2383     arg.fence_class = fence_class;
2384
2385     if (ioctl(fd, DRM_IOCTL_FENCE_BUFFERS, &arg))
2386         return -errno;
2387     fence->handle = arg.handle;
2388     fence->fence_class = arg.fence_class;
2389     fence->type = arg.type;
2390     fence->flags = arg.flags;
2391     fence->sequence = arg.sequence;
2392     fence->signaled = 0;
2393     return 0;
2394 }
2395
2396 int drmFenceReference(int fd, unsigned handle, drmFence *fence)
2397 {
2398     drm_fence_arg_t arg;
2399
2400     memset(&arg, 0, sizeof(arg));
2401     arg.handle = handle;
2402
2403     if (ioctl(fd, DRM_IOCTL_FENCE_REFERENCE, &arg))
2404         return -errno;
2405     fence->handle = arg.handle;
2406     fence->fence_class = arg.fence_class;
2407     fence->type = arg.type;
2408     fence->flags = arg.flags;
2409     fence->signaled = arg.signaled;
2410     return 0;
2411 }
2412
2413 int drmFenceUnreference(int fd, const drmFence *fence)
2414 {
2415     drm_fence_arg_t arg;
2416
2417     memset(&arg, 0, sizeof(arg));
2418     arg.handle = fence->handle;
2419
2420     if (ioctl(fd, DRM_IOCTL_FENCE_UNREFERENCE, &arg))
2421         return -errno;
2422     return 0;
2423 }
2424
2425 int drmFenceFlush(int fd, drmFence *fence, unsigned flush_type)
2426 {
2427     drm_fence_arg_t arg;
2428
2429     memset(&arg, 0, sizeof(arg));
2430     arg.handle = fence->handle;
2431     arg.type = flush_type;
2432
2433     if (ioctl(fd, DRM_IOCTL_FENCE_FLUSH, &arg))
2434         return -errno;
2435     fence->fence_class = arg.fence_class;
2436     fence->type = arg.type;
2437     fence->signaled = arg.signaled;
2438     return arg.error;
2439 }
2440
2441 int drmFenceUpdate(int fd, drmFence *fence)
2442 {
2443     drm_fence_arg_t arg;
2444
2445     memset(&arg, 0, sizeof(arg));
2446     arg.handle = fence->handle;
2447
2448     if (ioctl(fd, DRM_IOCTL_FENCE_SIGNALED, &arg))
2449         return -errno;
2450     fence->fence_class = arg.fence_class;
2451     fence->type = arg.type;
2452     fence->signaled = arg.signaled;
2453     return 0;
2454 }
2455
2456 int drmFenceSignaled(int fd, drmFence *fence, unsigned fenceType, 
2457                      int *signaled)
2458 {
2459     if ((fence->flags & DRM_FENCE_FLAG_SHAREABLE) ||
2460         ((fenceType & fence->signaled) != fenceType)) {
2461         int ret = drmFenceFlush(fd, fence, fenceType);
2462         if (ret)
2463             return ret;
2464     }
2465
2466     *signaled = ((fenceType & fence->signaled) == fenceType);
2467
2468     return 0;
2469 }
2470
2471 /*
2472  * Valid flags are 
2473  * DRM_FENCE_FLAG_SHAREABLE
2474  * DRM_FENCE_MASK_DRIVER
2475  */
2476
2477
2478 int drmFenceEmit(int fd, unsigned flags, drmFence *fence, unsigned emit_type)
2479 {
2480     drm_fence_arg_t arg;
2481
2482     memset(&arg, 0, sizeof(arg));
2483     arg.fence_class = fence->fence_class;
2484     arg.flags = flags;
2485     arg.handle = fence->handle;
2486     arg.type = emit_type;
2487
2488     if (ioctl(fd, DRM_IOCTL_FENCE_EMIT, &arg))
2489         return -errno;
2490     fence->fence_class = arg.fence_class;
2491     fence->type = arg.type;
2492     fence->signaled = arg.signaled;
2493     fence->sequence = arg.sequence;
2494     return 0;
2495 }
2496
2497 /*
2498  * Valid flags are 
2499  * DRM_FENCE_FLAG_WAIT_LAZY
2500  * DRM_FENCE_FLAG_WAIT_IGNORE_SIGNALS
2501  */
2502
2503 #define DRM_IOCTL_TIMEOUT_USEC 3000000UL
2504
2505 static unsigned long
2506 drmTimeDiff(struct timeval *now, struct timeval *then)
2507 {
2508     uint64_t val;
2509
2510     val = now->tv_sec - then->tv_sec;
2511     val *= 1000000LL;
2512     val += now->tv_usec;
2513     val -= then->tv_usec;
2514
2515     return (unsigned long) val;
2516 }
2517
2518 static int
2519 drmIoctlTimeout(int fd, unsigned long request, void *argp)
2520 {
2521     int haveThen = 0;
2522     struct timeval then, now;
2523     int ret;
2524
2525     do {
2526         ret = ioctl(fd, request, argp);
2527         if (ret != 0 && errno == EAGAIN) {
2528             if (!haveThen) {
2529                 gettimeofday(&then, NULL);
2530                 haveThen = 1;
2531             }
2532             gettimeofday(&now, NULL);
2533         }
2534     } while (ret != 0 && errno == EAGAIN && 
2535              drmTimeDiff(&now, &then) < DRM_IOCTL_TIMEOUT_USEC);
2536     
2537     if (ret != 0)
2538         return ((errno == EAGAIN) ? -EBUSY : -errno);
2539
2540     return 0;
2541 }
2542     
2543         
2544
2545
2546 int drmFenceWait(int fd, unsigned flags, drmFence *fence, unsigned flush_type)
2547 {
2548     drm_fence_arg_t arg;
2549     int ret;
2550
2551     if (flush_type == 0) {
2552         flush_type = fence->type;
2553     }
2554
2555     if (!(fence->flags & DRM_FENCE_FLAG_SHAREABLE)) {
2556         if ((flush_type & fence->signaled) == flush_type) {
2557             return 0;
2558         }
2559     }
2560
2561     memset(&arg, 0, sizeof(arg));
2562     arg.handle = fence->handle;
2563     arg.type = flush_type;
2564     arg.flags = flags;
2565
2566
2567     ret = drmIoctlTimeout(fd, DRM_IOCTL_FENCE_WAIT, &arg);
2568     if (ret)
2569         return ret;
2570
2571     fence->fence_class = arg.fence_class;
2572     fence->type = arg.type;
2573     fence->signaled = arg.signaled;
2574     return arg.error;
2575 }    
2576
2577 static void drmBOCopyReply(const struct drm_bo_info_rep *rep, drmBO *buf)
2578 {
2579     buf->handle = rep->handle;
2580     buf->flags = rep->flags;
2581     buf->size = rep->size;
2582     buf->offset = rep->offset;
2583     buf->mapHandle = rep->arg_handle;
2584     buf->mask = rep->mask;
2585     buf->start = rep->buffer_start;
2586     buf->fenceFlags = rep->fence_flags;
2587     buf->replyFlags = rep->rep_flags;
2588     buf->pageAlignment = rep->page_alignment;
2589     buf->tileInfo = rep->tile_info;
2590     buf->hwTileStride = rep->hw_tile_stride;
2591     buf->desiredTileStride = rep->desired_tile_stride;
2592 }
2593
2594
2595
2596 int drmBOCreate(int fd, unsigned long size,
2597                 unsigned pageAlignment, void *user_buffer,
2598                 uint64_t mask,
2599                 unsigned hint, drmBO *buf)
2600 {
2601     struct drm_bo_create_arg arg;
2602     struct drm_bo_create_req *req = &arg.d.req;
2603     struct drm_bo_info_rep *rep = &arg.d.rep;
2604     int ret;
2605
2606     memset(buf, 0, sizeof(*buf));
2607     memset(&arg, 0, sizeof(arg));
2608     req->mask = mask;
2609     req->hint = hint;
2610     req->size = size;
2611     req->page_alignment = pageAlignment;
2612     req->buffer_start = (unsigned long) user_buffer;
2613
2614     buf->virtual = NULL;
2615
2616     ret = drmIoctlTimeout(fd, DRM_IOCTL_BO_CREATE, &arg);
2617     if (ret)
2618         return ret;
2619
2620     drmBOCopyReply(rep, buf);
2621     buf->virtual = user_buffer;
2622     buf->mapCount = 0;
2623
2624     return 0;
2625 }
2626
2627 int drmBOReference(int fd, unsigned handle, drmBO *buf)
2628 {
2629     struct drm_bo_reference_info_arg arg;
2630     struct drm_bo_handle_arg *req = &arg.d.req;
2631     struct drm_bo_info_rep *rep = &arg.d.rep;
2632     
2633     memset(&arg, 0, sizeof(arg));
2634     req->handle = handle;
2635     
2636     if (ioctl(fd, DRM_IOCTL_BO_REFERENCE, &arg))
2637         return -errno;
2638
2639     drmBOCopyReply(rep, buf);
2640     buf->mapVirtual = NULL;
2641     buf->mapCount = 0;
2642     buf->virtual = NULL;
2643
2644     return 0;
2645 }
2646
2647 int drmBOUnreference(int fd, drmBO *buf)
2648 {
2649     struct drm_bo_handle_arg arg;
2650
2651     if (buf->mapVirtual && buf->mapHandle) {
2652         (void) munmap(buf->mapVirtual, buf->start + buf->size);
2653         buf->mapVirtual = NULL;
2654         buf->virtual = NULL;
2655     }
2656
2657     memset(&arg, 0, sizeof(arg));
2658     arg.handle = buf->handle;
2659
2660     if (ioctl(fd, DRM_IOCTL_BO_UNREFERENCE, &arg))
2661         return -errno;
2662
2663     buf->handle = 0;
2664     return 0;
2665 }   
2666
2667
2668 /*
2669  * Flags can be  DRM_BO_FLAG_READ, DRM_BO_FLAG_WRITE or'ed together
2670  * Hint currently be DRM_BO_HINT_DONT_BLOCK, which makes the
2671  * call return an -EBUSY if it can' immediately honor the mapping request.
2672  */
2673
2674 int drmBOMap(int fd, drmBO *buf, unsigned mapFlags, unsigned mapHint,
2675              void **address)
2676 {
2677     struct drm_bo_map_wait_idle_arg arg;
2678     struct drm_bo_info_req *req = &arg.d.req;
2679     struct drm_bo_info_rep *rep = &arg.d.rep;
2680     int ret = 0;
2681
2682     /*
2683      * Make sure we have a virtual address of the buffer.
2684      */
2685
2686     if (!buf->virtual) {
2687         drmAddress virtual;
2688         virtual = mmap(0, buf->size + buf->start, 
2689                        PROT_READ | PROT_WRITE, MAP_SHARED,
2690                        fd, buf->mapHandle);
2691         if (virtual == MAP_FAILED) {
2692             ret = -errno;
2693         }
2694         if (ret) 
2695             return ret;
2696         buf->mapVirtual = virtual;
2697         buf->virtual = ((char *) virtual) + buf->start;
2698     }
2699
2700     memset(&arg, 0, sizeof(arg));
2701     req->handle = buf->handle;
2702     req->mask = mapFlags;
2703     req->hint = mapHint;
2704
2705     /*
2706      * May hang if the buffer object is busy.
2707      * This IOCTL synchronizes the buffer.
2708      */
2709     
2710     ret = drmIoctlTimeout(fd, DRM_IOCTL_BO_MAP, &arg);
2711     if (ret)
2712         return ret;
2713
2714     drmBOCopyReply(rep, buf);   
2715     buf->mapFlags = mapFlags;
2716     ++buf->mapCount;
2717     *address = buf->virtual;
2718
2719     return 0;
2720 }
2721
2722
2723 int drmBOUnmap(int fd, drmBO *buf)
2724 {
2725     struct drm_bo_handle_arg arg;
2726
2727     memset(&arg, 0, sizeof(arg));
2728     arg.handle = buf->handle;
2729
2730     if (ioctl(fd, DRM_IOCTL_BO_UNMAP, &arg)) {
2731         return -errno;
2732     }
2733     buf->mapCount--;
2734     return 0;
2735 }
2736
2737 int drmBOSetStatus(int fd, drmBO *buf, 
2738                    uint64_t flags, uint64_t mask,
2739                    unsigned int hint, 
2740                    unsigned int desired_tile_stride,
2741                    unsigned int tile_info)
2742 {
2743
2744     struct drm_bo_map_wait_idle_arg arg;
2745     struct drm_bo_info_req *req = &arg.d.req;
2746     struct drm_bo_info_rep *rep = &arg.d.rep;
2747     int ret = 0;
2748
2749     memset(&arg, 0, sizeof(arg));
2750     req->mask = mask;
2751     req->flags = flags;
2752     req->handle = buf->handle;
2753     req->hint = hint;
2754     req->desired_tile_stride = desired_tile_stride;
2755     req->tile_info = tile_info;
2756     
2757     ret = drmIoctlTimeout(fd, DRM_IOCTL_BO_SETSTATUS, &arg);
2758     if (ret) 
2759             return ret;
2760
2761     drmBOCopyReply(rep, buf);
2762     return 0;
2763 }
2764             
2765
2766 int drmBOInfo(int fd, drmBO *buf)
2767 {
2768     struct drm_bo_reference_info_arg arg;
2769     struct drm_bo_handle_arg *req = &arg.d.req;
2770     struct drm_bo_info_rep *rep = &arg.d.rep;
2771     int ret = 0;
2772
2773     memset(&arg, 0, sizeof(arg));
2774     req->handle = buf->handle;
2775
2776     ret = ioctl(fd, DRM_IOCTL_BO_INFO, &arg);
2777     if (ret) 
2778         return -errno;
2779
2780     drmBOCopyReply(rep, buf);
2781     return 0;
2782 }
2783
2784 int drmBOWaitIdle(int fd, drmBO *buf, unsigned hint)
2785 {
2786     struct drm_bo_map_wait_idle_arg arg;
2787     struct drm_bo_info_req *req = &arg.d.req;
2788     struct drm_bo_info_rep *rep = &arg.d.rep;
2789     int ret = 0;
2790
2791     if ((buf->flags & DRM_BO_FLAG_SHAREABLE) ||
2792         (buf->replyFlags & DRM_BO_REP_BUSY)) {
2793         memset(&arg, 0, sizeof(arg));
2794         req->handle = buf->handle;
2795         req->hint = hint;
2796
2797         ret = drmIoctlTimeout(fd, DRM_IOCTL_BO_WAIT_IDLE, &arg);
2798         if (ret) 
2799             return ret;
2800
2801         drmBOCopyReply(rep, buf);
2802     }
2803     return 0;
2804 }
2805         
2806 int drmBOBusy(int fd, drmBO *buf, int *busy)
2807 {
2808     if (!(buf->flags & DRM_BO_FLAG_SHAREABLE) &&
2809         !(buf->replyFlags & DRM_BO_REP_BUSY)) {
2810         *busy = 0;
2811         return 0;
2812     }
2813     else {
2814         int ret = drmBOInfo(fd, buf);
2815         if (ret)
2816             return ret;
2817         *busy = (buf->replyFlags & DRM_BO_REP_BUSY);
2818         return 0;
2819     }
2820 }
2821     
2822 int drmMMInit(int fd, unsigned long pOffset, unsigned long pSize,
2823               unsigned memType)
2824 {
2825     struct drm_mm_init_arg arg;
2826
2827     memset(&arg, 0, sizeof(arg));
2828
2829     arg.magic = DRM_BO_INIT_MAGIC;
2830     arg.major = DRM_BO_INIT_MAJOR;
2831     arg.minor = DRM_BO_INIT_MINOR;
2832     arg.p_offset = pOffset;
2833     arg.p_size = pSize;
2834     arg.mem_type = memType;
2835
2836     if (ioctl(fd, DRM_IOCTL_MM_INIT, &arg))
2837         return -errno;
2838     return 0;   
2839 }
2840
2841 int drmMMTakedown(int fd, unsigned memType)
2842 {
2843     struct drm_mm_type_arg arg;
2844
2845     memset(&arg, 0, sizeof(arg));
2846     arg.mem_type = memType;
2847
2848     if (ioctl(fd, DRM_IOCTL_MM_TAKEDOWN, &arg))
2849         return -errno;
2850     return 0;   
2851 }
2852
2853 /*
2854  * If this function returns an error, and lockBM was set to 1,
2855  * the buffer manager is NOT locked.
2856  */
2857
2858 int drmMMLock(int fd, unsigned memType, int lockBM, int ignoreNoEvict)
2859 {
2860     struct drm_mm_type_arg arg;
2861
2862     memset(&arg, 0, sizeof(arg));
2863     arg.mem_type = memType;
2864     arg.lock_flags |= (lockBM) ? DRM_BO_LOCK_UNLOCK_BM : 0;
2865     arg.lock_flags |= (ignoreNoEvict) ? DRM_BO_LOCK_IGNORE_NO_EVICT : 0;
2866
2867     return drmIoctlTimeout(fd, DRM_IOCTL_MM_LOCK, &arg);
2868 }
2869
2870 int drmMMUnlock(int fd, unsigned memType, int unlockBM)
2871 {
2872     struct drm_mm_type_arg arg;
2873
2874     memset(&arg, 0, sizeof(arg));
2875     
2876     arg.mem_type = memType;
2877     arg.lock_flags |= (unlockBM) ? DRM_BO_LOCK_UNLOCK_BM : 0;
2878
2879     return drmIoctlTimeout(fd, DRM_IOCTL_MM_UNLOCK, &arg);
2880 }
2881
2882 int drmBOVersion(int fd, unsigned int *major,
2883                  unsigned int *minor,
2884                  unsigned int *patchlevel)
2885 {
2886     struct drm_bo_version_arg arg;
2887     int ret;
2888
2889     memset(&arg, 0, sizeof(arg));
2890     ret = ioctl(fd, DRM_IOCTL_BO_VERSION, &arg);
2891     if (ret)
2892         return -errno;
2893
2894     if (major)
2895         *major = arg.major;
2896     if (minor)
2897         *minor = arg.minor;
2898     if (patchlevel)
2899         *patchlevel = arg.patchlevel;
2900
2901     return 0;
2902 }
2903
2904
2905
2906 #define DRM_MAX_FDS 16
2907 static struct {
2908     char *BusID;
2909     int fd;
2910     int refcount;
2911 } connection[DRM_MAX_FDS];
2912
2913 static int nr_fds = 0;
2914
2915 int drmOpenOnce(void *unused, 
2916                 const char *BusID,
2917                 int *newlyopened)
2918 {
2919     int i;
2920     int fd;
2921    
2922     for (i = 0; i < nr_fds; i++)
2923         if (strcmp(BusID, connection[i].BusID) == 0) {
2924             connection[i].refcount++;
2925             *newlyopened = 0;
2926             return connection[i].fd;
2927         }
2928
2929     fd = drmOpen(unused, BusID);
2930     if (fd <= 0 || nr_fds == DRM_MAX_FDS)
2931         return fd;
2932    
2933     connection[nr_fds].BusID = strdup(BusID);
2934     connection[nr_fds].fd = fd;
2935     connection[nr_fds].refcount = 1;
2936     *newlyopened = 1;
2937
2938     if (0)
2939         fprintf(stderr, "saved connection %d for %s %d\n", 
2940                 nr_fds, connection[nr_fds].BusID, 
2941                 strcmp(BusID, connection[nr_fds].BusID));
2942
2943     nr_fds++;
2944
2945     return fd;
2946 }
2947
2948 void drmCloseOnce(int fd)
2949 {
2950     int i;
2951
2952     for (i = 0; i < nr_fds; i++) {
2953         if (fd == connection[i].fd) {
2954             if (--connection[i].refcount == 0) {
2955                 drmClose(connection[i].fd);
2956                 free(connection[i].BusID);
2957             
2958                 if (i < --nr_fds) 
2959                     connection[i] = connection[nr_fds];
2960
2961                 return;
2962             }
2963         }
2964     }
2965 }