OSDN Git Service

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