OSDN Git Service

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