OSDN Git Service

d873ebb1259768a0b8638b59778d36a9f6aa7536
[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 #include <stdio.h>
35 #include <stdlib.h>
36 #include <stdbool.h>
37 #include <unistd.h>
38 #include <string.h>
39 #include <strings.h>
40 #include <ctype.h>
41 #include <dirent.h>
42 #include <stddef.h>
43 #include <fcntl.h>
44 #include <errno.h>
45 #include <limits.h>
46 #include <signal.h>
47 #include <time.h>
48 #include <sys/types.h>
49 #include <sys/stat.h>
50 #define stat_t struct stat
51 #include <sys/ioctl.h>
52 #include <sys/time.h>
53 #include <stdarg.h>
54 #ifdef MAJOR_IN_MKDEV
55 #include <sys/mkdev.h>
56 #endif
57 #ifdef MAJOR_IN_SYSMACROS
58 #include <sys/sysmacros.h>
59 #endif
60 #include <math.h>
61
62 #if defined(__FreeBSD__)
63 #include <sys/param.h>
64 #endif
65
66 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
67
68 /* Not all systems have MAP_FAILED defined */
69 #ifndef MAP_FAILED
70 #define MAP_FAILED ((void *)-1)
71 #endif
72
73 #include "xf86drm.h"
74 #include "libdrm_macros.h"
75
76 #include "util_math.h"
77
78 #ifdef __DragonFly__
79 #define DRM_MAJOR 145
80 #endif
81
82 #ifdef __NetBSD__
83 #define DRM_MAJOR 34
84 #endif
85
86 #ifdef __OpenBSD__
87 #ifdef __i386__
88 #define DRM_MAJOR 88
89 #else
90 #define DRM_MAJOR 87
91 #endif
92 #endif /* __OpenBSD__ */
93
94 #ifndef DRM_MAJOR
95 #define DRM_MAJOR 226 /* Linux */
96 #endif
97
98 #if defined(__OpenBSD__) || defined(__DragonFly__)
99 struct drm_pciinfo {
100         uint16_t        domain;
101         uint8_t         bus;
102         uint8_t         dev;
103         uint8_t         func;
104         uint16_t        vendor_id;
105         uint16_t        device_id;
106         uint16_t        subvendor_id;
107         uint16_t        subdevice_id;
108         uint8_t         revision_id;
109 };
110
111 #define DRM_IOCTL_GET_PCIINFO   DRM_IOR(0x15, struct drm_pciinfo)
112 #endif
113
114 #define DRM_MSG_VERBOSITY 3
115
116 #define memclear(s) memset(&s, 0, sizeof(s))
117
118 static drmServerInfoPtr drm_server_info;
119
120 static bool drmNodeIsDRM(int maj, int min);
121
122 drm_public void drmSetServerInfo(drmServerInfoPtr info)
123 {
124     drm_server_info = info;
125 }
126
127 /**
128  * Output a message to stderr.
129  *
130  * \param format printf() like format string.
131  *
132  * \internal
133  * This function is a wrapper around vfprintf().
134  */
135
136 static int DRM_PRINTFLIKE(1, 0)
137 drmDebugPrint(const char *format, va_list ap)
138 {
139     return vfprintf(stderr, format, ap);
140 }
141
142 drm_public void
143 drmMsg(const char *format, ...)
144 {
145     va_list ap;
146     const char *env;
147     if (((env = getenv("LIBGL_DEBUG")) && strstr(env, "verbose")) ||
148         (drm_server_info && drm_server_info->debug_print))
149     {
150         va_start(ap, format);
151         if (drm_server_info) {
152             drm_server_info->debug_print(format,ap);
153         } else {
154             drmDebugPrint(format, ap);
155         }
156         va_end(ap);
157     }
158 }
159
160 static void *drmHashTable = NULL; /* Context switch callbacks */
161
162 drm_public void *drmGetHashTable(void)
163 {
164     return drmHashTable;
165 }
166
167 drm_public void *drmMalloc(int size)
168 {
169     return calloc(1, size);
170 }
171
172 drm_public void drmFree(void *pt)
173 {
174     free(pt);
175 }
176
177 /**
178  * Call ioctl, restarting if it is interrupted
179  */
180 drm_public int
181 drmIoctl(int fd, unsigned long request, void *arg)
182 {
183     int ret;
184
185     do {
186         ret = ioctl(fd, request, arg);
187     } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
188     return ret;
189 }
190
191 static unsigned long drmGetKeyFromFd(int fd)
192 {
193     stat_t     st;
194
195     st.st_rdev = 0;
196     fstat(fd, &st);
197     return st.st_rdev;
198 }
199
200 drm_public drmHashEntry *drmGetEntry(int fd)
201 {
202     unsigned long key = drmGetKeyFromFd(fd);
203     void          *value;
204     drmHashEntry  *entry;
205
206     if (!drmHashTable)
207         drmHashTable = drmHashCreate();
208
209     if (drmHashLookup(drmHashTable, key, &value)) {
210         entry           = drmMalloc(sizeof(*entry));
211         entry->fd       = fd;
212         entry->f        = NULL;
213         entry->tagTable = drmHashCreate();
214         drmHashInsert(drmHashTable, key, entry);
215     } else {
216         entry = value;
217     }
218     return entry;
219 }
220
221 /**
222  * Compare two busid strings
223  *
224  * \param first
225  * \param second
226  *
227  * \return 1 if matched.
228  *
229  * \internal
230  * This function compares two bus ID strings.  It understands the older
231  * PCI:b:d:f format and the newer pci:oooo:bb:dd.f format.  In the format, o is
232  * domain, b is bus, d is device, f is function.
233  */
234 static int drmMatchBusID(const char *id1, const char *id2, int pci_domain_ok)
235 {
236     /* First, check if the IDs are exactly the same */
237     if (strcasecmp(id1, id2) == 0)
238         return 1;
239
240     /* Try to match old/new-style PCI bus IDs. */
241     if (strncasecmp(id1, "pci", 3) == 0) {
242         unsigned int o1, b1, d1, f1;
243         unsigned int o2, b2, d2, f2;
244         int ret;
245
246         ret = sscanf(id1, "pci:%04x:%02x:%02x.%u", &o1, &b1, &d1, &f1);
247         if (ret != 4) {
248             o1 = 0;
249             ret = sscanf(id1, "PCI:%u:%u:%u", &b1, &d1, &f1);
250             if (ret != 3)
251                 return 0;
252         }
253
254         ret = sscanf(id2, "pci:%04x:%02x:%02x.%u", &o2, &b2, &d2, &f2);
255         if (ret != 4) {
256             o2 = 0;
257             ret = sscanf(id2, "PCI:%u:%u:%u", &b2, &d2, &f2);
258             if (ret != 3)
259                 return 0;
260         }
261
262         /* If domains aren't properly supported by the kernel interface,
263          * just ignore them, which sucks less than picking a totally random
264          * card with "open by name"
265          */
266         if (!pci_domain_ok)
267             o1 = o2 = 0;
268
269         if ((o1 != o2) || (b1 != b2) || (d1 != d2) || (f1 != f2))
270             return 0;
271         else
272             return 1;
273     }
274     return 0;
275 }
276
277 /**
278  * Handles error checking for chown call.
279  *
280  * \param path to file.
281  * \param id of the new owner.
282  * \param id of the new group.
283  *
284  * \return zero if success or -1 if failure.
285  *
286  * \internal
287  * Checks for failure. If failure was caused by signal call chown again.
288  * If any other failure happened then it will output error message using
289  * drmMsg() call.
290  */
291 #if !UDEV
292 static int chown_check_return(const char *path, uid_t owner, gid_t group)
293 {
294         int rv;
295
296         do {
297             rv = chown(path, owner, group);
298         } while (rv != 0 && errno == EINTR);
299
300         if (rv == 0)
301             return 0;
302
303         drmMsg("Failed to change owner or group for file %s! %d: %s\n",
304                path, errno, strerror(errno));
305         return -1;
306 }
307 #endif
308
309 static const char *drmGetDeviceName(int type)
310 {
311     switch (type) {
312     case DRM_NODE_PRIMARY:
313         return DRM_DEV_NAME;
314     case DRM_NODE_CONTROL:
315         return DRM_CONTROL_DEV_NAME;
316     case DRM_NODE_RENDER:
317         return DRM_RENDER_DEV_NAME;
318     }
319     return NULL;
320 }
321
322 /**
323  * Open the DRM device, creating it if necessary.
324  *
325  * \param dev major and minor numbers of the device.
326  * \param minor minor number of the device.
327  *
328  * \return a file descriptor on success, or a negative value on error.
329  *
330  * \internal
331  * Assembles the device name from \p minor and opens it, creating the device
332  * special file node with the major and minor numbers specified by \p dev and
333  * parent directory if necessary and was called by root.
334  */
335 static int drmOpenDevice(dev_t dev, int minor, int type)
336 {
337     stat_t          st;
338     const char      *dev_name = drmGetDeviceName(type);
339     char            buf[DRM_NODE_NAME_MAX];
340     int             fd;
341     mode_t          devmode = DRM_DEV_MODE, serv_mode;
342     gid_t           serv_group;
343 #if !UDEV
344     int             isroot  = !geteuid();
345     uid_t           user    = DRM_DEV_UID;
346     gid_t           group   = DRM_DEV_GID;
347 #endif
348
349     if (!dev_name)
350         return -EINVAL;
351
352     sprintf(buf, dev_name, DRM_DIR_NAME, minor);
353     drmMsg("drmOpenDevice: node name is %s\n", buf);
354
355     if (drm_server_info && drm_server_info->get_perms) {
356         drm_server_info->get_perms(&serv_group, &serv_mode);
357         devmode  = serv_mode ? serv_mode : DRM_DEV_MODE;
358         devmode &= ~(S_IXUSR|S_IXGRP|S_IXOTH);
359     }
360
361 #if !UDEV
362     if (stat(DRM_DIR_NAME, &st)) {
363         if (!isroot)
364             return DRM_ERR_NOT_ROOT;
365         mkdir(DRM_DIR_NAME, DRM_DEV_DIRMODE);
366         chown_check_return(DRM_DIR_NAME, 0, 0); /* root:root */
367         chmod(DRM_DIR_NAME, DRM_DEV_DIRMODE);
368     }
369
370     /* Check if the device node exists and create it if necessary. */
371     if (stat(buf, &st)) {
372         if (!isroot)
373             return DRM_ERR_NOT_ROOT;
374         remove(buf);
375         mknod(buf, S_IFCHR | devmode, dev);
376     }
377
378     if (drm_server_info && drm_server_info->get_perms) {
379         group = ((int)serv_group >= 0) ? serv_group : DRM_DEV_GID;
380         chown_check_return(buf, user, group);
381         chmod(buf, devmode);
382     }
383 #else
384     /* if we modprobed then wait for udev */
385     {
386         int udev_count = 0;
387 wait_for_udev:
388         if (stat(DRM_DIR_NAME, &st)) {
389             usleep(20);
390             udev_count++;
391
392             if (udev_count == 50)
393                 return -1;
394             goto wait_for_udev;
395         }
396
397         if (stat(buf, &st)) {
398             usleep(20);
399             udev_count++;
400
401             if (udev_count == 50)
402                 return -1;
403             goto wait_for_udev;
404         }
405     }
406 #endif
407
408     fd = open(buf, O_RDWR | O_CLOEXEC, 0);
409     drmMsg("drmOpenDevice: open result is %d, (%s)\n",
410            fd, fd < 0 ? strerror(errno) : "OK");
411     if (fd >= 0)
412         return fd;
413
414 #if !UDEV
415     /* Check if the device node is not what we expect it to be, and recreate it
416      * and try again if so.
417      */
418     if (st.st_rdev != dev) {
419         if (!isroot)
420             return DRM_ERR_NOT_ROOT;
421         remove(buf);
422         mknod(buf, S_IFCHR | devmode, dev);
423         if (drm_server_info && drm_server_info->get_perms) {
424             chown_check_return(buf, user, group);
425             chmod(buf, devmode);
426         }
427     }
428     fd = open(buf, O_RDWR | O_CLOEXEC, 0);
429     drmMsg("drmOpenDevice: open result is %d, (%s)\n",
430            fd, fd < 0 ? strerror(errno) : "OK");
431     if (fd >= 0)
432         return fd;
433
434     drmMsg("drmOpenDevice: Open failed\n");
435     remove(buf);
436 #endif
437     return -errno;
438 }
439
440
441 /**
442  * Open the DRM device
443  *
444  * \param minor device minor number.
445  * \param create allow to create the device if set.
446  *
447  * \return a file descriptor on success, or a negative value on error.
448  *
449  * \internal
450  * Calls drmOpenDevice() if \p create is set, otherwise assembles the device
451  * name from \p minor and opens it.
452  */
453 static int drmOpenMinor(int minor, int create, int type)
454 {
455     int  fd;
456     char buf[DRM_NODE_NAME_MAX];
457     const char *dev_name = drmGetDeviceName(type);
458
459     if (create)
460         return drmOpenDevice(makedev(DRM_MAJOR, minor), minor, type);
461
462     if (!dev_name)
463         return -EINVAL;
464
465     sprintf(buf, dev_name, DRM_DIR_NAME, minor);
466     if ((fd = open(buf, O_RDWR | O_CLOEXEC, 0)) >= 0)
467         return fd;
468     return -errno;
469 }
470
471
472 /**
473  * Determine whether the DRM kernel driver has been loaded.
474  *
475  * \return 1 if the DRM driver is loaded, 0 otherwise.
476  *
477  * \internal
478  * Determine the presence of the kernel driver by attempting to open the 0
479  * minor and get version information.  For backward compatibility with older
480  * Linux implementations, /proc/dri is also checked.
481  */
482 drm_public int drmAvailable(void)
483 {
484     drmVersionPtr version;
485     int           retval = 0;
486     int           fd;
487
488     if ((fd = drmOpenMinor(0, 1, DRM_NODE_PRIMARY)) < 0) {
489 #ifdef __linux__
490         /* Try proc for backward Linux compatibility */
491         if (!access("/proc/dri/0", R_OK))
492             return 1;
493 #endif
494         return 0;
495     }
496
497     if ((version = drmGetVersion(fd))) {
498         retval = 1;
499         drmFreeVersion(version);
500     }
501     close(fd);
502
503     return retval;
504 }
505
506 static int drmGetMinorBase(int type)
507 {
508     switch (type) {
509     case DRM_NODE_PRIMARY:
510         return 0;
511     case DRM_NODE_CONTROL:
512         return 64;
513     case DRM_NODE_RENDER:
514         return 128;
515     default:
516         return -1;
517     };
518 }
519
520 static int drmGetMinorType(int major, int minor)
521 {
522 #ifdef __FreeBSD__
523     char name[SPECNAMELEN];
524     int id;
525
526     if (!devname_r(makedev(major, minor), S_IFCHR, name, sizeof(name)))
527         return -1;
528
529     if (sscanf(name, "drm/%d", &id) != 1) {
530         // If not in /dev/drm/ we have the type in the name
531         if (sscanf(name, "dri/card%d\n", &id) >= 1)
532            return DRM_NODE_PRIMARY;
533         else if (sscanf(name, "dri/control%d\n", &id) >= 1)
534            return DRM_NODE_CONTROL;
535         else if (sscanf(name, "dri/renderD%d\n", &id) >= 1)
536            return DRM_NODE_RENDER;
537         return -1;
538     }
539
540     minor = id;
541 #endif
542     int type = minor >> 6;
543
544     if (minor < 0)
545         return -1;
546
547     switch (type) {
548     case DRM_NODE_PRIMARY:
549     case DRM_NODE_CONTROL:
550     case DRM_NODE_RENDER:
551         return type;
552     default:
553         return -1;
554     }
555 }
556
557 static const char *drmGetMinorName(int type)
558 {
559     switch (type) {
560     case DRM_NODE_PRIMARY:
561         return DRM_PRIMARY_MINOR_NAME;
562     case DRM_NODE_CONTROL:
563         return DRM_CONTROL_MINOR_NAME;
564     case DRM_NODE_RENDER:
565         return DRM_RENDER_MINOR_NAME;
566     default:
567         return NULL;
568     }
569 }
570
571 /**
572  * Open the device by bus ID.
573  *
574  * \param busid bus ID.
575  * \param type device node type.
576  *
577  * \return a file descriptor on success, or a negative value on error.
578  *
579  * \internal
580  * This function attempts to open every possible minor (up to DRM_MAX_MINOR),
581  * comparing the device bus ID with the one supplied.
582  *
583  * \sa drmOpenMinor() and drmGetBusid().
584  */
585 static int drmOpenByBusid(const char *busid, int type)
586 {
587     int        i, pci_domain_ok = 1;
588     int        fd;
589     const char *buf;
590     drmSetVersion sv;
591     int        base = drmGetMinorBase(type);
592
593     if (base < 0)
594         return -1;
595
596     drmMsg("drmOpenByBusid: Searching for BusID %s\n", busid);
597     for (i = base; i < base + DRM_MAX_MINOR; i++) {
598         fd = drmOpenMinor(i, 1, type);
599         drmMsg("drmOpenByBusid: drmOpenMinor returns %d\n", fd);
600         if (fd >= 0) {
601             /* We need to try for 1.4 first for proper PCI domain support
602              * and if that fails, we know the kernel is busted
603              */
604             sv.drm_di_major = 1;
605             sv.drm_di_minor = 4;
606             sv.drm_dd_major = -1;        /* Don't care */
607             sv.drm_dd_minor = -1;        /* Don't care */
608             if (drmSetInterfaceVersion(fd, &sv)) {
609 #ifndef __alpha__
610                 pci_domain_ok = 0;
611 #endif
612                 sv.drm_di_major = 1;
613                 sv.drm_di_minor = 1;
614                 sv.drm_dd_major = -1;       /* Don't care */
615                 sv.drm_dd_minor = -1;       /* Don't care */
616                 drmMsg("drmOpenByBusid: Interface 1.4 failed, trying 1.1\n");
617                 drmSetInterfaceVersion(fd, &sv);
618             }
619             buf = drmGetBusid(fd);
620             drmMsg("drmOpenByBusid: drmGetBusid reports %s\n", buf);
621             if (buf && drmMatchBusID(buf, busid, pci_domain_ok)) {
622                 drmFreeBusid(buf);
623                 return fd;
624             }
625             if (buf)
626                 drmFreeBusid(buf);
627             close(fd);
628         }
629     }
630     return -1;
631 }
632
633
634 /**
635  * Open the device by name.
636  *
637  * \param name driver name.
638  * \param type the device node type.
639  *
640  * \return a file descriptor on success, or a negative value on error.
641  *
642  * \internal
643  * This function opens the first minor number that matches the driver name and
644  * isn't already in use.  If it's in use it then it will already have a bus ID
645  * assigned.
646  *
647  * \sa drmOpenMinor(), drmGetVersion() and drmGetBusid().
648  */
649 static int drmOpenByName(const char *name, int type)
650 {
651     int           i;
652     int           fd;
653     drmVersionPtr version;
654     char *        id;
655     int           base = drmGetMinorBase(type);
656
657     if (base < 0)
658         return -1;
659
660     /*
661      * Open the first minor number that matches the driver name and isn't
662      * already in use.  If it's in use it will have a busid assigned already.
663      */
664     for (i = base; i < base + DRM_MAX_MINOR; i++) {
665         if ((fd = drmOpenMinor(i, 1, type)) >= 0) {
666             if ((version = drmGetVersion(fd))) {
667                 if (!strcmp(version->name, name)) {
668                     drmFreeVersion(version);
669                     id = drmGetBusid(fd);
670                     drmMsg("drmGetBusid returned '%s'\n", id ? id : "NULL");
671                     if (!id || !*id) {
672                         if (id)
673                             drmFreeBusid(id);
674                         return fd;
675                     } else {
676                         drmFreeBusid(id);
677                     }
678                 } else {
679                     drmFreeVersion(version);
680                 }
681             }
682             close(fd);
683         }
684     }
685
686 #ifdef __linux__
687     /* Backward-compatibility /proc support */
688     for (i = 0; i < 8; i++) {
689         char proc_name[64], buf[512];
690         char *driver, *pt, *devstring;
691         int  retcode;
692
693         sprintf(proc_name, "/proc/dri/%d/name", i);
694         if ((fd = open(proc_name, 0, 0)) >= 0) {
695             retcode = read(fd, buf, sizeof(buf)-1);
696             close(fd);
697             if (retcode) {
698                 buf[retcode-1] = '\0';
699                 for (driver = pt = buf; *pt && *pt != ' '; ++pt)
700                     ;
701                 if (*pt) { /* Device is next */
702                     *pt = '\0';
703                     if (!strcmp(driver, name)) { /* Match */
704                         for (devstring = ++pt; *pt && *pt != ' '; ++pt)
705                             ;
706                         if (*pt) { /* Found busid */
707                             return drmOpenByBusid(++pt, type);
708                         } else { /* No busid */
709                             return drmOpenDevice(strtol(devstring, NULL, 0),i, type);
710                         }
711                     }
712                 }
713             }
714         }
715     }
716 #endif
717
718     return -1;
719 }
720
721
722 /**
723  * Open the DRM device.
724  *
725  * Looks up the specified name and bus ID, and opens the device found.  The
726  * entry in /dev/dri is created if necessary and if called by root.
727  *
728  * \param name driver name. Not referenced if bus ID is supplied.
729  * \param busid bus ID. Zero if not known.
730  *
731  * \return a file descriptor on success, or a negative value on error.
732  *
733  * \internal
734  * It calls drmOpenByBusid() if \p busid is specified or drmOpenByName()
735  * otherwise.
736  */
737 drm_public int drmOpen(const char *name, const char *busid)
738 {
739     return drmOpenWithType(name, busid, DRM_NODE_PRIMARY);
740 }
741
742 /**
743  * Open the DRM device with specified type.
744  *
745  * Looks up the specified name and bus ID, and opens the device found.  The
746  * entry in /dev/dri is created if necessary and if called by root.
747  *
748  * \param name driver name. Not referenced if bus ID is supplied.
749  * \param busid bus ID. Zero if not known.
750  * \param type the device node type to open, PRIMARY, CONTROL or RENDER
751  *
752  * \return a file descriptor on success, or a negative value on error.
753  *
754  * \internal
755  * It calls drmOpenByBusid() if \p busid is specified or drmOpenByName()
756  * otherwise.
757  */
758 drm_public int drmOpenWithType(const char *name, const char *busid, int type)
759 {
760     if (name != NULL && drm_server_info &&
761         drm_server_info->load_module && !drmAvailable()) {
762         /* try to load the kernel module */
763         if (!drm_server_info->load_module(name)) {
764             drmMsg("[drm] failed to load kernel module \"%s\"\n", name);
765             return -1;
766         }
767     }
768
769     if (busid) {
770         int fd = drmOpenByBusid(busid, type);
771         if (fd >= 0)
772             return fd;
773     }
774
775     if (name)
776         return drmOpenByName(name, type);
777
778     return -1;
779 }
780
781 drm_public int drmOpenControl(int minor)
782 {
783     return drmOpenMinor(minor, 0, DRM_NODE_CONTROL);
784 }
785
786 drm_public int drmOpenRender(int minor)
787 {
788     return drmOpenMinor(minor, 0, DRM_NODE_RENDER);
789 }
790
791 /**
792  * Free the version information returned by drmGetVersion().
793  *
794  * \param v pointer to the version information.
795  *
796  * \internal
797  * It frees the memory pointed by \p %v as well as all the non-null strings
798  * pointers in it.
799  */
800 drm_public void drmFreeVersion(drmVersionPtr v)
801 {
802     if (!v)
803         return;
804     drmFree(v->name);
805     drmFree(v->date);
806     drmFree(v->desc);
807     drmFree(v);
808 }
809
810
811 /**
812  * Free the non-public version information returned by the kernel.
813  *
814  * \param v pointer to the version information.
815  *
816  * \internal
817  * Used by drmGetVersion() to free the memory pointed by \p %v as well as all
818  * the non-null strings pointers in it.
819  */
820 static void drmFreeKernelVersion(drm_version_t *v)
821 {
822     if (!v)
823         return;
824     drmFree(v->name);
825     drmFree(v->date);
826     drmFree(v->desc);
827     drmFree(v);
828 }
829
830
831 /**
832  * Copy version information.
833  *
834  * \param d destination pointer.
835  * \param s source pointer.
836  *
837  * \internal
838  * Used by drmGetVersion() to translate the information returned by the ioctl
839  * interface in a private structure into the public structure counterpart.
840  */
841 static void drmCopyVersion(drmVersionPtr d, const drm_version_t *s)
842 {
843     d->version_major      = s->version_major;
844     d->version_minor      = s->version_minor;
845     d->version_patchlevel = s->version_patchlevel;
846     d->name_len           = s->name_len;
847     d->name               = strdup(s->name);
848     d->date_len           = s->date_len;
849     d->date               = strdup(s->date);
850     d->desc_len           = s->desc_len;
851     d->desc               = strdup(s->desc);
852 }
853
854
855 /**
856  * Query the driver version information.
857  *
858  * \param fd file descriptor.
859  *
860  * \return pointer to a drmVersion structure which should be freed with
861  * drmFreeVersion().
862  *
863  * \note Similar information is available via /proc/dri.
864  *
865  * \internal
866  * It gets the version information via successive DRM_IOCTL_VERSION ioctls,
867  * first with zeros to get the string lengths, and then the actually strings.
868  * It also null-terminates them since they might not be already.
869  */
870 drm_public drmVersionPtr drmGetVersion(int fd)
871 {
872     drmVersionPtr retval;
873     drm_version_t *version = drmMalloc(sizeof(*version));
874
875     if (drmIoctl(fd, DRM_IOCTL_VERSION, version)) {
876         drmFreeKernelVersion(version);
877         return NULL;
878     }
879
880     if (version->name_len)
881         version->name    = drmMalloc(version->name_len + 1);
882     if (version->date_len)
883         version->date    = drmMalloc(version->date_len + 1);
884     if (version->desc_len)
885         version->desc    = drmMalloc(version->desc_len + 1);
886
887     if (drmIoctl(fd, DRM_IOCTL_VERSION, version)) {
888         drmMsg("DRM_IOCTL_VERSION: %s\n", strerror(errno));
889         drmFreeKernelVersion(version);
890         return NULL;
891     }
892
893     /* The results might not be null-terminated strings, so terminate them. */
894     if (version->name_len) version->name[version->name_len] = '\0';
895     if (version->date_len) version->date[version->date_len] = '\0';
896     if (version->desc_len) version->desc[version->desc_len] = '\0';
897
898     retval = drmMalloc(sizeof(*retval));
899     drmCopyVersion(retval, version);
900     drmFreeKernelVersion(version);
901     return retval;
902 }
903
904
905 /**
906  * Get version information for the DRM user space library.
907  *
908  * This version number is driver independent.
909  *
910  * \param fd file descriptor.
911  *
912  * \return version information.
913  *
914  * \internal
915  * This function allocates and fills a drm_version structure with a hard coded
916  * version number.
917  */
918 drm_public drmVersionPtr drmGetLibVersion(int fd)
919 {
920     drm_version_t *version = drmMalloc(sizeof(*version));
921
922     /* Version history:
923      *   NOTE THIS MUST NOT GO ABOVE VERSION 1.X due to drivers needing it
924      *   revision 1.0.x = original DRM interface with no drmGetLibVersion
925      *                    entry point and many drm<Device> extensions
926      *   revision 1.1.x = added drmCommand entry points for device extensions
927      *                    added drmGetLibVersion to identify libdrm.a version
928      *   revision 1.2.x = added drmSetInterfaceVersion
929      *                    modified drmOpen to handle both busid and name
930      *   revision 1.3.x = added server + memory manager
931      */
932     version->version_major      = 1;
933     version->version_minor      = 3;
934     version->version_patchlevel = 0;
935
936     return (drmVersionPtr)version;
937 }
938
939 drm_public int drmGetCap(int fd, uint64_t capability, uint64_t *value)
940 {
941     struct drm_get_cap cap;
942     int ret;
943
944     memclear(cap);
945     cap.capability = capability;
946
947     ret = drmIoctl(fd, DRM_IOCTL_GET_CAP, &cap);
948     if (ret)
949         return ret;
950
951     *value = cap.value;
952     return 0;
953 }
954
955 drm_public int drmSetClientCap(int fd, uint64_t capability, uint64_t value)
956 {
957     struct drm_set_client_cap cap;
958
959     memclear(cap);
960     cap.capability = capability;
961     cap.value = value;
962
963     return drmIoctl(fd, DRM_IOCTL_SET_CLIENT_CAP, &cap);
964 }
965
966 /**
967  * Free the bus ID information.
968  *
969  * \param busid bus ID information string as given by drmGetBusid().
970  *
971  * \internal
972  * This function is just frees the memory pointed by \p busid.
973  */
974 drm_public void drmFreeBusid(const char *busid)
975 {
976     drmFree((void *)busid);
977 }
978
979
980 /**
981  * Get the bus ID of the device.
982  *
983  * \param fd file descriptor.
984  *
985  * \return bus ID string.
986  *
987  * \internal
988  * This function gets the bus ID via successive DRM_IOCTL_GET_UNIQUE ioctls to
989  * get the string length and data, passing the arguments in a drm_unique
990  * structure.
991  */
992 drm_public char *drmGetBusid(int fd)
993 {
994     drm_unique_t u;
995
996     memclear(u);
997
998     if (drmIoctl(fd, DRM_IOCTL_GET_UNIQUE, &u))
999         return NULL;
1000     u.unique = drmMalloc(u.unique_len + 1);
1001     if (drmIoctl(fd, DRM_IOCTL_GET_UNIQUE, &u)) {
1002         drmFree(u.unique);
1003         return NULL;
1004     }
1005     u.unique[u.unique_len] = '\0';
1006
1007     return u.unique;
1008 }
1009
1010
1011 /**
1012  * Set the bus ID of the device.
1013  *
1014  * \param fd file descriptor.
1015  * \param busid bus ID string.
1016  *
1017  * \return zero on success, negative on failure.
1018  *
1019  * \internal
1020  * This function is a wrapper around the DRM_IOCTL_SET_UNIQUE ioctl, passing
1021  * the arguments in a drm_unique structure.
1022  */
1023 drm_public int drmSetBusid(int fd, const char *busid)
1024 {
1025     drm_unique_t u;
1026
1027     memclear(u);
1028     u.unique     = (char *)busid;
1029     u.unique_len = strlen(busid);
1030
1031     if (drmIoctl(fd, DRM_IOCTL_SET_UNIQUE, &u)) {
1032         return -errno;
1033     }
1034     return 0;
1035 }
1036
1037 drm_public int drmGetMagic(int fd, drm_magic_t * magic)
1038 {
1039     drm_auth_t auth;
1040
1041     memclear(auth);
1042
1043     *magic = 0;
1044     if (drmIoctl(fd, DRM_IOCTL_GET_MAGIC, &auth))
1045         return -errno;
1046     *magic = auth.magic;
1047     return 0;
1048 }
1049
1050 drm_public int drmAuthMagic(int fd, drm_magic_t magic)
1051 {
1052     drm_auth_t auth;
1053
1054     memclear(auth);
1055     auth.magic = magic;
1056     if (drmIoctl(fd, DRM_IOCTL_AUTH_MAGIC, &auth))
1057         return -errno;
1058     return 0;
1059 }
1060
1061 /**
1062  * Specifies a range of memory that is available for mapping by a
1063  * non-root process.
1064  *
1065  * \param fd file descriptor.
1066  * \param offset usually the physical address. The actual meaning depends of
1067  * the \p type parameter. See below.
1068  * \param size of the memory in bytes.
1069  * \param type type of the memory to be mapped.
1070  * \param flags combination of several flags to modify the function actions.
1071  * \param handle will be set to a value that may be used as the offset
1072  * parameter for mmap().
1073  *
1074  * \return zero on success or a negative value on error.
1075  *
1076  * \par Mapping the frame buffer
1077  * For the frame buffer
1078  * - \p offset will be the physical address of the start of the frame buffer,
1079  * - \p size will be the size of the frame buffer in bytes, and
1080  * - \p type will be DRM_FRAME_BUFFER.
1081  *
1082  * \par
1083  * The area mapped will be uncached. If MTRR support is available in the
1084  * kernel, the frame buffer area will be set to write combining.
1085  *
1086  * \par Mapping the MMIO register area
1087  * For the MMIO register area,
1088  * - \p offset will be the physical address of the start of the register area,
1089  * - \p size will be the size of the register area bytes, and
1090  * - \p type will be DRM_REGISTERS.
1091  * \par
1092  * The area mapped will be uncached.
1093  *
1094  * \par Mapping the SAREA
1095  * For the SAREA,
1096  * - \p offset will be ignored and should be set to zero,
1097  * - \p size will be the desired size of the SAREA in bytes,
1098  * - \p type will be DRM_SHM.
1099  *
1100  * \par
1101  * A shared memory area of the requested size will be created and locked in
1102  * kernel memory. This area may be mapped into client-space by using the handle
1103  * returned.
1104  *
1105  * \note May only be called by root.
1106  *
1107  * \internal
1108  * This function is a wrapper around the DRM_IOCTL_ADD_MAP ioctl, passing
1109  * the arguments in a drm_map structure.
1110  */
1111 drm_public int drmAddMap(int fd, drm_handle_t offset, drmSize size, drmMapType type,
1112                          drmMapFlags flags, drm_handle_t *handle)
1113 {
1114     drm_map_t map;
1115
1116     memclear(map);
1117     map.offset  = offset;
1118     map.size    = size;
1119     map.type    = type;
1120     map.flags   = flags;
1121     if (drmIoctl(fd, DRM_IOCTL_ADD_MAP, &map))
1122         return -errno;
1123     if (handle)
1124         *handle = (drm_handle_t)(uintptr_t)map.handle;
1125     return 0;
1126 }
1127
1128 drm_public int drmRmMap(int fd, drm_handle_t handle)
1129 {
1130     drm_map_t map;
1131
1132     memclear(map);
1133     map.handle = (void *)(uintptr_t)handle;
1134
1135     if(drmIoctl(fd, DRM_IOCTL_RM_MAP, &map))
1136         return -errno;
1137     return 0;
1138 }
1139
1140 /**
1141  * Make buffers available for DMA transfers.
1142  *
1143  * \param fd file descriptor.
1144  * \param count number of buffers.
1145  * \param size size of each buffer.
1146  * \param flags buffer allocation flags.
1147  * \param agp_offset offset in the AGP aperture
1148  *
1149  * \return number of buffers allocated, negative on error.
1150  *
1151  * \internal
1152  * This function is a wrapper around DRM_IOCTL_ADD_BUFS ioctl.
1153  *
1154  * \sa drm_buf_desc.
1155  */
1156 drm_public int drmAddBufs(int fd, int count, int size, drmBufDescFlags flags,
1157                           int agp_offset)
1158 {
1159     drm_buf_desc_t request;
1160
1161     memclear(request);
1162     request.count     = count;
1163     request.size      = size;
1164     request.flags     = flags;
1165     request.agp_start = agp_offset;
1166
1167     if (drmIoctl(fd, DRM_IOCTL_ADD_BUFS, &request))
1168         return -errno;
1169     return request.count;
1170 }
1171
1172 drm_public int drmMarkBufs(int fd, double low, double high)
1173 {
1174     drm_buf_info_t info;
1175     int            i;
1176
1177     memclear(info);
1178
1179     if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info))
1180         return -EINVAL;
1181
1182     if (!info.count)
1183         return -EINVAL;
1184
1185     if (!(info.list = drmMalloc(info.count * sizeof(*info.list))))
1186         return -ENOMEM;
1187
1188     if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info)) {
1189         int retval = -errno;
1190         drmFree(info.list);
1191         return retval;
1192     }
1193
1194     for (i = 0; i < info.count; i++) {
1195         info.list[i].low_mark  = low  * info.list[i].count;
1196         info.list[i].high_mark = high * info.list[i].count;
1197         if (drmIoctl(fd, DRM_IOCTL_MARK_BUFS, &info.list[i])) {
1198             int retval = -errno;
1199             drmFree(info.list);
1200             return retval;
1201         }
1202     }
1203     drmFree(info.list);
1204
1205     return 0;
1206 }
1207
1208 /**
1209  * Free buffers.
1210  *
1211  * \param fd file descriptor.
1212  * \param count number of buffers to free.
1213  * \param list list of buffers to be freed.
1214  *
1215  * \return zero on success, or a negative value on failure.
1216  *
1217  * \note This function is primarily used for debugging.
1218  *
1219  * \internal
1220  * This function is a wrapper around the DRM_IOCTL_FREE_BUFS ioctl, passing
1221  * the arguments in a drm_buf_free structure.
1222  */
1223 drm_public int drmFreeBufs(int fd, int count, int *list)
1224 {
1225     drm_buf_free_t request;
1226
1227     memclear(request);
1228     request.count = count;
1229     request.list  = list;
1230     if (drmIoctl(fd, DRM_IOCTL_FREE_BUFS, &request))
1231         return -errno;
1232     return 0;
1233 }
1234
1235
1236 /**
1237  * Close the device.
1238  *
1239  * \param fd file descriptor.
1240  *
1241  * \internal
1242  * This function closes the file descriptor.
1243  */
1244 drm_public int drmClose(int fd)
1245 {
1246     unsigned long key    = drmGetKeyFromFd(fd);
1247     drmHashEntry  *entry = drmGetEntry(fd);
1248
1249     drmHashDestroy(entry->tagTable);
1250     entry->fd       = 0;
1251     entry->f        = NULL;
1252     entry->tagTable = NULL;
1253
1254     drmHashDelete(drmHashTable, key);
1255     drmFree(entry);
1256
1257     return close(fd);
1258 }
1259
1260
1261 /**
1262  * Map a region of memory.
1263  *
1264  * \param fd file descriptor.
1265  * \param handle handle returned by drmAddMap().
1266  * \param size size in bytes. Must match the size used by drmAddMap().
1267  * \param address will contain the user-space virtual address where the mapping
1268  * begins.
1269  *
1270  * \return zero on success, or a negative value on failure.
1271  *
1272  * \internal
1273  * This function is a wrapper for mmap().
1274  */
1275 drm_public int drmMap(int fd, drm_handle_t handle, drmSize size,
1276                       drmAddressPtr address)
1277 {
1278     static unsigned long pagesize_mask = 0;
1279
1280     if (fd < 0)
1281         return -EINVAL;
1282
1283     if (!pagesize_mask)
1284         pagesize_mask = getpagesize() - 1;
1285
1286     size = (size + pagesize_mask) & ~pagesize_mask;
1287
1288     *address = drm_mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, handle);
1289     if (*address == MAP_FAILED)
1290         return -errno;
1291     return 0;
1292 }
1293
1294
1295 /**
1296  * Unmap mappings obtained with drmMap().
1297  *
1298  * \param address address as given by drmMap().
1299  * \param size size in bytes. Must match the size used by drmMap().
1300  *
1301  * \return zero on success, or a negative value on failure.
1302  *
1303  * \internal
1304  * This function is a wrapper for munmap().
1305  */
1306 drm_public int drmUnmap(drmAddress address, drmSize size)
1307 {
1308     return drm_munmap(address, size);
1309 }
1310
1311 drm_public drmBufInfoPtr drmGetBufInfo(int fd)
1312 {
1313     drm_buf_info_t info;
1314     drmBufInfoPtr  retval;
1315     int            i;
1316
1317     memclear(info);
1318
1319     if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info))
1320         return NULL;
1321
1322     if (info.count) {
1323         if (!(info.list = drmMalloc(info.count * sizeof(*info.list))))
1324             return NULL;
1325
1326         if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info)) {
1327             drmFree(info.list);
1328             return NULL;
1329         }
1330
1331         retval = drmMalloc(sizeof(*retval));
1332         retval->count = info.count;
1333         retval->list  = drmMalloc(info.count * sizeof(*retval->list));
1334         for (i = 0; i < info.count; i++) {
1335             retval->list[i].count     = info.list[i].count;
1336             retval->list[i].size      = info.list[i].size;
1337             retval->list[i].low_mark  = info.list[i].low_mark;
1338             retval->list[i].high_mark = info.list[i].high_mark;
1339         }
1340         drmFree(info.list);
1341         return retval;
1342     }
1343     return NULL;
1344 }
1345
1346 /**
1347  * Map all DMA buffers into client-virtual space.
1348  *
1349  * \param fd file descriptor.
1350  *
1351  * \return a pointer to a ::drmBufMap structure.
1352  *
1353  * \note The client may not use these buffers until obtaining buffer indices
1354  * with drmDMA().
1355  *
1356  * \internal
1357  * This function calls the DRM_IOCTL_MAP_BUFS ioctl and copies the returned
1358  * information about the buffers in a drm_buf_map structure into the
1359  * client-visible data structures.
1360  */
1361 drm_public drmBufMapPtr drmMapBufs(int fd)
1362 {
1363     drm_buf_map_t bufs;
1364     drmBufMapPtr  retval;
1365     int           i;
1366
1367     memclear(bufs);
1368     if (drmIoctl(fd, DRM_IOCTL_MAP_BUFS, &bufs))
1369         return NULL;
1370
1371     if (!bufs.count)
1372         return NULL;
1373
1374     if (!(bufs.list = drmMalloc(bufs.count * sizeof(*bufs.list))))
1375         return NULL;
1376
1377     if (drmIoctl(fd, DRM_IOCTL_MAP_BUFS, &bufs)) {
1378         drmFree(bufs.list);
1379         return NULL;
1380     }
1381
1382     retval = drmMalloc(sizeof(*retval));
1383     retval->count = bufs.count;
1384     retval->list  = drmMalloc(bufs.count * sizeof(*retval->list));
1385     for (i = 0; i < bufs.count; i++) {
1386         retval->list[i].idx     = bufs.list[i].idx;
1387         retval->list[i].total   = bufs.list[i].total;
1388         retval->list[i].used    = 0;
1389         retval->list[i].address = bufs.list[i].address;
1390     }
1391
1392     drmFree(bufs.list);
1393     return retval;
1394 }
1395
1396
1397 /**
1398  * Unmap buffers allocated with drmMapBufs().
1399  *
1400  * \return zero on success, or negative value on failure.
1401  *
1402  * \internal
1403  * Calls munmap() for every buffer stored in \p bufs and frees the
1404  * memory allocated by drmMapBufs().
1405  */
1406 drm_public int drmUnmapBufs(drmBufMapPtr bufs)
1407 {
1408     int i;
1409
1410     for (i = 0; i < bufs->count; i++) {
1411         drm_munmap(bufs->list[i].address, bufs->list[i].total);
1412     }
1413
1414     drmFree(bufs->list);
1415     drmFree(bufs);
1416     return 0;
1417 }
1418
1419
1420 #define DRM_DMA_RETRY  16
1421
1422 /**
1423  * Reserve DMA buffers.
1424  *
1425  * \param fd file descriptor.
1426  * \param request
1427  *
1428  * \return zero on success, or a negative value on failure.
1429  *
1430  * \internal
1431  * Assemble the arguments into a drm_dma structure and keeps issuing the
1432  * DRM_IOCTL_DMA ioctl until success or until maximum number of retries.
1433  */
1434 drm_public int drmDMA(int fd, drmDMAReqPtr request)
1435 {
1436     drm_dma_t dma;
1437     int ret, i = 0;
1438
1439     dma.context         = request->context;
1440     dma.send_count      = request->send_count;
1441     dma.send_indices    = request->send_list;
1442     dma.send_sizes      = request->send_sizes;
1443     dma.flags           = request->flags;
1444     dma.request_count   = request->request_count;
1445     dma.request_size    = request->request_size;
1446     dma.request_indices = request->request_list;
1447     dma.request_sizes   = request->request_sizes;
1448     dma.granted_count   = 0;
1449
1450     do {
1451         ret = ioctl( fd, DRM_IOCTL_DMA, &dma );
1452     } while ( ret && errno == EAGAIN && i++ < DRM_DMA_RETRY );
1453
1454     if ( ret == 0 ) {
1455         request->granted_count = dma.granted_count;
1456         return 0;
1457     } else {
1458         return -errno;
1459     }
1460 }
1461
1462
1463 /**
1464  * Obtain heavyweight hardware lock.
1465  *
1466  * \param fd file descriptor.
1467  * \param context context.
1468  * \param flags flags that determine the state of the hardware when the function
1469  * returns.
1470  *
1471  * \return always zero.
1472  *
1473  * \internal
1474  * This function translates the arguments into a drm_lock structure and issue
1475  * the DRM_IOCTL_LOCK ioctl until the lock is successfully acquired.
1476  */
1477 drm_public int drmGetLock(int fd, drm_context_t context, drmLockFlags flags)
1478 {
1479     drm_lock_t lock;
1480
1481     memclear(lock);
1482     lock.context = context;
1483     lock.flags   = 0;
1484     if (flags & DRM_LOCK_READY)      lock.flags |= _DRM_LOCK_READY;
1485     if (flags & DRM_LOCK_QUIESCENT)  lock.flags |= _DRM_LOCK_QUIESCENT;
1486     if (flags & DRM_LOCK_FLUSH)      lock.flags |= _DRM_LOCK_FLUSH;
1487     if (flags & DRM_LOCK_FLUSH_ALL)  lock.flags |= _DRM_LOCK_FLUSH_ALL;
1488     if (flags & DRM_HALT_ALL_QUEUES) lock.flags |= _DRM_HALT_ALL_QUEUES;
1489     if (flags & DRM_HALT_CUR_QUEUES) lock.flags |= _DRM_HALT_CUR_QUEUES;
1490
1491     while (drmIoctl(fd, DRM_IOCTL_LOCK, &lock))
1492         ;
1493     return 0;
1494 }
1495
1496 /**
1497  * Release the hardware lock.
1498  *
1499  * \param fd file descriptor.
1500  * \param context context.
1501  *
1502  * \return zero on success, or a negative value on failure.
1503  *
1504  * \internal
1505  * This function is a wrapper around the DRM_IOCTL_UNLOCK ioctl, passing the
1506  * argument in a drm_lock structure.
1507  */
1508 drm_public int drmUnlock(int fd, drm_context_t context)
1509 {
1510     drm_lock_t lock;
1511
1512     memclear(lock);
1513     lock.context = context;
1514     return drmIoctl(fd, DRM_IOCTL_UNLOCK, &lock);
1515 }
1516
1517 drm_public drm_context_t *drmGetReservedContextList(int fd, int *count)
1518 {
1519     drm_ctx_res_t res;
1520     drm_ctx_t     *list;
1521     drm_context_t * retval;
1522     int           i;
1523
1524     memclear(res);
1525     if (drmIoctl(fd, DRM_IOCTL_RES_CTX, &res))
1526         return NULL;
1527
1528     if (!res.count)
1529         return NULL;
1530
1531     if (!(list   = drmMalloc(res.count * sizeof(*list))))
1532         return NULL;
1533     if (!(retval = drmMalloc(res.count * sizeof(*retval))))
1534         goto err_free_list;
1535
1536     res.contexts = list;
1537     if (drmIoctl(fd, DRM_IOCTL_RES_CTX, &res))
1538         goto err_free_context;
1539
1540     for (i = 0; i < res.count; i++)
1541         retval[i] = list[i].handle;
1542     drmFree(list);
1543
1544     *count = res.count;
1545     return retval;
1546
1547 err_free_list:
1548     drmFree(list);
1549 err_free_context:
1550     drmFree(retval);
1551     return NULL;
1552 }
1553
1554 drm_public void drmFreeReservedContextList(drm_context_t *pt)
1555 {
1556     drmFree(pt);
1557 }
1558
1559 /**
1560  * Create context.
1561  *
1562  * Used by the X server during GLXContext initialization. This causes
1563  * per-context kernel-level resources to be allocated.
1564  *
1565  * \param fd file descriptor.
1566  * \param handle is set on success. To be used by the client when requesting DMA
1567  * dispatch with drmDMA().
1568  *
1569  * \return zero on success, or a negative value on failure.
1570  *
1571  * \note May only be called by root.
1572  *
1573  * \internal
1574  * This function is a wrapper around the DRM_IOCTL_ADD_CTX ioctl, passing the
1575  * argument in a drm_ctx structure.
1576  */
1577 drm_public int drmCreateContext(int fd, drm_context_t *handle)
1578 {
1579     drm_ctx_t ctx;
1580
1581     memclear(ctx);
1582     if (drmIoctl(fd, DRM_IOCTL_ADD_CTX, &ctx))
1583         return -errno;
1584     *handle = ctx.handle;
1585     return 0;
1586 }
1587
1588 drm_public int drmSwitchToContext(int fd, drm_context_t context)
1589 {
1590     drm_ctx_t ctx;
1591
1592     memclear(ctx);
1593     ctx.handle = context;
1594     if (drmIoctl(fd, DRM_IOCTL_SWITCH_CTX, &ctx))
1595         return -errno;
1596     return 0;
1597 }
1598
1599 drm_public int drmSetContextFlags(int fd, drm_context_t context,
1600                                   drm_context_tFlags flags)
1601 {
1602     drm_ctx_t ctx;
1603
1604     /*
1605      * Context preserving means that no context switches are done between DMA
1606      * buffers from one context and the next.  This is suitable for use in the
1607      * X server (which promises to maintain hardware context), or in the
1608      * client-side library when buffers are swapped on behalf of two threads.
1609      */
1610     memclear(ctx);
1611     ctx.handle = context;
1612     if (flags & DRM_CONTEXT_PRESERVED)
1613         ctx.flags |= _DRM_CONTEXT_PRESERVED;
1614     if (flags & DRM_CONTEXT_2DONLY)
1615         ctx.flags |= _DRM_CONTEXT_2DONLY;
1616     if (drmIoctl(fd, DRM_IOCTL_MOD_CTX, &ctx))
1617         return -errno;
1618     return 0;
1619 }
1620
1621 drm_public int drmGetContextFlags(int fd, drm_context_t context,
1622                                   drm_context_tFlagsPtr flags)
1623 {
1624     drm_ctx_t ctx;
1625
1626     memclear(ctx);
1627     ctx.handle = context;
1628     if (drmIoctl(fd, DRM_IOCTL_GET_CTX, &ctx))
1629         return -errno;
1630     *flags = 0;
1631     if (ctx.flags & _DRM_CONTEXT_PRESERVED)
1632         *flags |= DRM_CONTEXT_PRESERVED;
1633     if (ctx.flags & _DRM_CONTEXT_2DONLY)
1634         *flags |= DRM_CONTEXT_2DONLY;
1635     return 0;
1636 }
1637
1638 /**
1639  * Destroy context.
1640  *
1641  * Free any kernel-level resources allocated with drmCreateContext() associated
1642  * with the context.
1643  *
1644  * \param fd file descriptor.
1645  * \param handle handle given by drmCreateContext().
1646  *
1647  * \return zero on success, or a negative value on failure.
1648  *
1649  * \note May only be called by root.
1650  *
1651  * \internal
1652  * This function is a wrapper around the DRM_IOCTL_RM_CTX ioctl, passing the
1653  * argument in a drm_ctx structure.
1654  */
1655 drm_public int drmDestroyContext(int fd, drm_context_t handle)
1656 {
1657     drm_ctx_t ctx;
1658
1659     memclear(ctx);
1660     ctx.handle = handle;
1661     if (drmIoctl(fd, DRM_IOCTL_RM_CTX, &ctx))
1662         return -errno;
1663     return 0;
1664 }
1665
1666 drm_public int drmCreateDrawable(int fd, drm_drawable_t *handle)
1667 {
1668     drm_draw_t draw;
1669
1670     memclear(draw);
1671     if (drmIoctl(fd, DRM_IOCTL_ADD_DRAW, &draw))
1672         return -errno;
1673     *handle = draw.handle;
1674     return 0;
1675 }
1676
1677 drm_public int drmDestroyDrawable(int fd, drm_drawable_t handle)
1678 {
1679     drm_draw_t draw;
1680
1681     memclear(draw);
1682     draw.handle = handle;
1683     if (drmIoctl(fd, DRM_IOCTL_RM_DRAW, &draw))
1684         return -errno;
1685     return 0;
1686 }
1687
1688 drm_public int drmUpdateDrawableInfo(int fd, drm_drawable_t handle,
1689                                      drm_drawable_info_type_t type,
1690                                      unsigned int num, void *data)
1691 {
1692     drm_update_draw_t update;
1693
1694     memclear(update);
1695     update.handle = handle;
1696     update.type = type;
1697     update.num = num;
1698     update.data = (unsigned long long)(unsigned long)data;
1699
1700     if (drmIoctl(fd, DRM_IOCTL_UPDATE_DRAW, &update))
1701         return -errno;
1702
1703     return 0;
1704 }
1705
1706 drm_public int drmCrtcGetSequence(int fd, uint32_t crtcId, uint64_t *sequence,
1707                                   uint64_t *ns)
1708 {
1709     struct drm_crtc_get_sequence get_seq;
1710     int ret;
1711
1712     memclear(get_seq);
1713     get_seq.crtc_id = crtcId;
1714     ret = drmIoctl(fd, DRM_IOCTL_CRTC_GET_SEQUENCE, &get_seq);
1715     if (ret)
1716         return ret;
1717
1718     if (sequence)
1719         *sequence = get_seq.sequence;
1720     if (ns)
1721         *ns = get_seq.sequence_ns;
1722     return 0;
1723 }
1724
1725 drm_public int drmCrtcQueueSequence(int fd, uint32_t crtcId, uint32_t flags,
1726                                     uint64_t sequence,
1727                                     uint64_t *sequence_queued,
1728                                     uint64_t user_data)
1729 {
1730     struct drm_crtc_queue_sequence queue_seq;
1731     int ret;
1732
1733     memclear(queue_seq);
1734     queue_seq.crtc_id = crtcId;
1735     queue_seq.flags = flags;
1736     queue_seq.sequence = sequence;
1737     queue_seq.user_data = user_data;
1738
1739     ret = drmIoctl(fd, DRM_IOCTL_CRTC_QUEUE_SEQUENCE, &queue_seq);
1740     if (ret == 0 && sequence_queued)
1741         *sequence_queued = queue_seq.sequence;
1742
1743     return ret;
1744 }
1745
1746 /**
1747  * Acquire the AGP device.
1748  *
1749  * Must be called before any of the other AGP related calls.
1750  *
1751  * \param fd file descriptor.
1752  *
1753  * \return zero on success, or a negative value on failure.
1754  *
1755  * \internal
1756  * This function is a wrapper around the DRM_IOCTL_AGP_ACQUIRE ioctl.
1757  */
1758 drm_public int drmAgpAcquire(int fd)
1759 {
1760     if (drmIoctl(fd, DRM_IOCTL_AGP_ACQUIRE, NULL))
1761         return -errno;
1762     return 0;
1763 }
1764
1765
1766 /**
1767  * Release the AGP device.
1768  *
1769  * \param fd file descriptor.
1770  *
1771  * \return zero on success, or a negative value on failure.
1772  *
1773  * \internal
1774  * This function is a wrapper around the DRM_IOCTL_AGP_RELEASE ioctl.
1775  */
1776 drm_public int drmAgpRelease(int fd)
1777 {
1778     if (drmIoctl(fd, DRM_IOCTL_AGP_RELEASE, NULL))
1779         return -errno;
1780     return 0;
1781 }
1782
1783
1784 /**
1785  * Set the AGP mode.
1786  *
1787  * \param fd file descriptor.
1788  * \param mode AGP mode.
1789  *
1790  * \return zero on success, or a negative value on failure.
1791  *
1792  * \internal
1793  * This function is a wrapper around the DRM_IOCTL_AGP_ENABLE ioctl, passing the
1794  * argument in a drm_agp_mode structure.
1795  */
1796 drm_public int drmAgpEnable(int fd, unsigned long mode)
1797 {
1798     drm_agp_mode_t m;
1799
1800     memclear(m);
1801     m.mode = mode;
1802     if (drmIoctl(fd, DRM_IOCTL_AGP_ENABLE, &m))
1803         return -errno;
1804     return 0;
1805 }
1806
1807
1808 /**
1809  * Allocate a chunk of AGP memory.
1810  *
1811  * \param fd file descriptor.
1812  * \param size requested memory size in bytes. Will be rounded to page boundary.
1813  * \param type type of memory to allocate.
1814  * \param address if not zero, will be set to the physical address of the
1815  * allocated memory.
1816  * \param handle on success will be set to a handle of the allocated memory.
1817  *
1818  * \return zero on success, or a negative value on failure.
1819  *
1820  * \internal
1821  * This function is a wrapper around the DRM_IOCTL_AGP_ALLOC ioctl, passing the
1822  * arguments in a drm_agp_buffer structure.
1823  */
1824 drm_public int drmAgpAlloc(int fd, unsigned long size, unsigned long type,
1825                            unsigned long *address, drm_handle_t *handle)
1826 {
1827     drm_agp_buffer_t b;
1828
1829     memclear(b);
1830     *handle = DRM_AGP_NO_HANDLE;
1831     b.size   = size;
1832     b.type   = type;
1833     if (drmIoctl(fd, DRM_IOCTL_AGP_ALLOC, &b))
1834         return -errno;
1835     if (address != 0UL)
1836         *address = b.physical;
1837     *handle = b.handle;
1838     return 0;
1839 }
1840
1841
1842 /**
1843  * Free a chunk of AGP memory.
1844  *
1845  * \param fd file descriptor.
1846  * \param handle handle to the allocated memory, as given by drmAgpAllocate().
1847  *
1848  * \return zero on success, or a negative value on failure.
1849  *
1850  * \internal
1851  * This function is a wrapper around the DRM_IOCTL_AGP_FREE ioctl, passing the
1852  * argument in a drm_agp_buffer structure.
1853  */
1854 drm_public int drmAgpFree(int fd, drm_handle_t handle)
1855 {
1856     drm_agp_buffer_t b;
1857
1858     memclear(b);
1859     b.handle = handle;
1860     if (drmIoctl(fd, DRM_IOCTL_AGP_FREE, &b))
1861         return -errno;
1862     return 0;
1863 }
1864
1865
1866 /**
1867  * Bind a chunk of AGP memory.
1868  *
1869  * \param fd file descriptor.
1870  * \param handle handle to the allocated memory, as given by drmAgpAllocate().
1871  * \param offset offset in bytes. It will round to page boundary.
1872  *
1873  * \return zero on success, or a negative value on failure.
1874  *
1875  * \internal
1876  * This function is a wrapper around the DRM_IOCTL_AGP_BIND ioctl, passing the
1877  * argument in a drm_agp_binding structure.
1878  */
1879 drm_public int drmAgpBind(int fd, drm_handle_t handle, unsigned long offset)
1880 {
1881     drm_agp_binding_t b;
1882
1883     memclear(b);
1884     b.handle = handle;
1885     b.offset = offset;
1886     if (drmIoctl(fd, DRM_IOCTL_AGP_BIND, &b))
1887         return -errno;
1888     return 0;
1889 }
1890
1891
1892 /**
1893  * Unbind a chunk of AGP memory.
1894  *
1895  * \param fd file descriptor.
1896  * \param handle handle to the allocated memory, as given by drmAgpAllocate().
1897  *
1898  * \return zero on success, or a negative value on failure.
1899  *
1900  * \internal
1901  * This function is a wrapper around the DRM_IOCTL_AGP_UNBIND ioctl, passing
1902  * the argument in a drm_agp_binding structure.
1903  */
1904 drm_public int drmAgpUnbind(int fd, drm_handle_t handle)
1905 {
1906     drm_agp_binding_t b;
1907
1908     memclear(b);
1909     b.handle = handle;
1910     if (drmIoctl(fd, DRM_IOCTL_AGP_UNBIND, &b))
1911         return -errno;
1912     return 0;
1913 }
1914
1915
1916 /**
1917  * Get AGP driver major version number.
1918  *
1919  * \param fd file descriptor.
1920  *
1921  * \return major version number on success, or a negative value on failure..
1922  *
1923  * \internal
1924  * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1925  * necessary information in a drm_agp_info structure.
1926  */
1927 drm_public int drmAgpVersionMajor(int fd)
1928 {
1929     drm_agp_info_t i;
1930
1931     memclear(i);
1932
1933     if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
1934         return -errno;
1935     return i.agp_version_major;
1936 }
1937
1938
1939 /**
1940  * Get AGP driver minor version number.
1941  *
1942  * \param fd file descriptor.
1943  *
1944  * \return minor version number on success, or a negative value on failure.
1945  *
1946  * \internal
1947  * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1948  * necessary information in a drm_agp_info structure.
1949  */
1950 drm_public int drmAgpVersionMinor(int fd)
1951 {
1952     drm_agp_info_t i;
1953
1954     memclear(i);
1955
1956     if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
1957         return -errno;
1958     return i.agp_version_minor;
1959 }
1960
1961
1962 /**
1963  * Get AGP mode.
1964  *
1965  * \param fd file descriptor.
1966  *
1967  * \return mode on success, or zero on failure.
1968  *
1969  * \internal
1970  * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1971  * necessary information in a drm_agp_info structure.
1972  */
1973 drm_public unsigned long drmAgpGetMode(int fd)
1974 {
1975     drm_agp_info_t i;
1976
1977     memclear(i);
1978
1979     if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
1980         return 0;
1981     return i.mode;
1982 }
1983
1984
1985 /**
1986  * Get AGP aperture base.
1987  *
1988  * \param fd file descriptor.
1989  *
1990  * \return aperture base on success, zero on failure.
1991  *
1992  * \internal
1993  * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1994  * necessary information in a drm_agp_info structure.
1995  */
1996 drm_public unsigned long drmAgpBase(int fd)
1997 {
1998     drm_agp_info_t i;
1999
2000     memclear(i);
2001
2002     if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
2003         return 0;
2004     return i.aperture_base;
2005 }
2006
2007
2008 /**
2009  * Get AGP aperture size.
2010  *
2011  * \param fd file descriptor.
2012  *
2013  * \return aperture size on success, zero on failure.
2014  *
2015  * \internal
2016  * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
2017  * necessary information in a drm_agp_info structure.
2018  */
2019 drm_public unsigned long drmAgpSize(int fd)
2020 {
2021     drm_agp_info_t i;
2022
2023     memclear(i);
2024
2025     if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
2026         return 0;
2027     return i.aperture_size;
2028 }
2029
2030
2031 /**
2032  * Get used AGP memory.
2033  *
2034  * \param fd file descriptor.
2035  *
2036  * \return memory used on success, or zero on failure.
2037  *
2038  * \internal
2039  * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
2040  * necessary information in a drm_agp_info structure.
2041  */
2042 drm_public unsigned long drmAgpMemoryUsed(int fd)
2043 {
2044     drm_agp_info_t i;
2045
2046     memclear(i);
2047
2048     if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
2049         return 0;
2050     return i.memory_used;
2051 }
2052
2053
2054 /**
2055  * Get available AGP memory.
2056  *
2057  * \param fd file descriptor.
2058  *
2059  * \return memory available on success, or zero on failure.
2060  *
2061  * \internal
2062  * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
2063  * necessary information in a drm_agp_info structure.
2064  */
2065 drm_public unsigned long drmAgpMemoryAvail(int fd)
2066 {
2067     drm_agp_info_t i;
2068
2069     memclear(i);
2070
2071     if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
2072         return 0;
2073     return i.memory_allowed;
2074 }
2075
2076
2077 /**
2078  * Get hardware vendor ID.
2079  *
2080  * \param fd file descriptor.
2081  *
2082  * \return vendor ID on success, or zero on failure.
2083  *
2084  * \internal
2085  * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
2086  * necessary information in a drm_agp_info structure.
2087  */
2088 drm_public unsigned int drmAgpVendorId(int fd)
2089 {
2090     drm_agp_info_t i;
2091
2092     memclear(i);
2093
2094     if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
2095         return 0;
2096     return i.id_vendor;
2097 }
2098
2099
2100 /**
2101  * Get hardware device ID.
2102  *
2103  * \param fd file descriptor.
2104  *
2105  * \return zero on success, or zero on failure.
2106  *
2107  * \internal
2108  * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
2109  * necessary information in a drm_agp_info structure.
2110  */
2111 drm_public unsigned int drmAgpDeviceId(int fd)
2112 {
2113     drm_agp_info_t i;
2114
2115     memclear(i);
2116
2117     if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
2118         return 0;
2119     return i.id_device;
2120 }
2121
2122 drm_public int drmScatterGatherAlloc(int fd, unsigned long size,
2123                                      drm_handle_t *handle)
2124 {
2125     drm_scatter_gather_t sg;
2126
2127     memclear(sg);
2128
2129     *handle = 0;
2130     sg.size   = size;
2131     if (drmIoctl(fd, DRM_IOCTL_SG_ALLOC, &sg))
2132         return -errno;
2133     *handle = sg.handle;
2134     return 0;
2135 }
2136
2137 drm_public int drmScatterGatherFree(int fd, drm_handle_t handle)
2138 {
2139     drm_scatter_gather_t sg;
2140
2141     memclear(sg);
2142     sg.handle = handle;
2143     if (drmIoctl(fd, DRM_IOCTL_SG_FREE, &sg))
2144         return -errno;
2145     return 0;
2146 }
2147
2148 /**
2149  * Wait for VBLANK.
2150  *
2151  * \param fd file descriptor.
2152  * \param vbl pointer to a drmVBlank structure.
2153  *
2154  * \return zero on success, or a negative value on failure.
2155  *
2156  * \internal
2157  * This function is a wrapper around the DRM_IOCTL_WAIT_VBLANK ioctl.
2158  */
2159 drm_public int drmWaitVBlank(int fd, drmVBlankPtr vbl)
2160 {
2161     struct timespec timeout, cur;
2162     int ret;
2163
2164     ret = clock_gettime(CLOCK_MONOTONIC, &timeout);
2165     if (ret < 0) {
2166         fprintf(stderr, "clock_gettime failed: %s\n", strerror(errno));
2167         goto out;
2168     }
2169     timeout.tv_sec++;
2170
2171     do {
2172        ret = ioctl(fd, DRM_IOCTL_WAIT_VBLANK, vbl);
2173        vbl->request.type &= ~DRM_VBLANK_RELATIVE;
2174        if (ret && errno == EINTR) {
2175            clock_gettime(CLOCK_MONOTONIC, &cur);
2176            /* Timeout after 1s */
2177            if (cur.tv_sec > timeout.tv_sec + 1 ||
2178                (cur.tv_sec == timeout.tv_sec && cur.tv_nsec >=
2179                 timeout.tv_nsec)) {
2180                    errno = EBUSY;
2181                    ret = -1;
2182                    break;
2183            }
2184        }
2185     } while (ret && errno == EINTR);
2186
2187 out:
2188     return ret;
2189 }
2190
2191 drm_public int drmError(int err, const char *label)
2192 {
2193     switch (err) {
2194     case DRM_ERR_NO_DEVICE:
2195         fprintf(stderr, "%s: no device\n", label);
2196         break;
2197     case DRM_ERR_NO_ACCESS:
2198         fprintf(stderr, "%s: no access\n", label);
2199         break;
2200     case DRM_ERR_NOT_ROOT:
2201         fprintf(stderr, "%s: not root\n", label);
2202         break;
2203     case DRM_ERR_INVALID:
2204         fprintf(stderr, "%s: invalid args\n", label);
2205         break;
2206     default:
2207         if (err < 0)
2208             err = -err;
2209         fprintf( stderr, "%s: error %d (%s)\n", label, err, strerror(err) );
2210         break;
2211     }
2212
2213     return 1;
2214 }
2215
2216 /**
2217  * Install IRQ handler.
2218  *
2219  * \param fd file descriptor.
2220  * \param irq IRQ number.
2221  *
2222  * \return zero on success, or a negative value on failure.
2223  *
2224  * \internal
2225  * This function is a wrapper around the DRM_IOCTL_CONTROL ioctl, passing the
2226  * argument in a drm_control structure.
2227  */
2228 drm_public int drmCtlInstHandler(int fd, int irq)
2229 {
2230     drm_control_t ctl;
2231
2232     memclear(ctl);
2233     ctl.func  = DRM_INST_HANDLER;
2234     ctl.irq   = irq;
2235     if (drmIoctl(fd, DRM_IOCTL_CONTROL, &ctl))
2236         return -errno;
2237     return 0;
2238 }
2239
2240
2241 /**
2242  * Uninstall IRQ handler.
2243  *
2244  * \param fd file descriptor.
2245  *
2246  * \return zero on success, or a negative value on failure.
2247  *
2248  * \internal
2249  * This function is a wrapper around the DRM_IOCTL_CONTROL ioctl, passing the
2250  * argument in a drm_control structure.
2251  */
2252 drm_public int drmCtlUninstHandler(int fd)
2253 {
2254     drm_control_t ctl;
2255
2256     memclear(ctl);
2257     ctl.func  = DRM_UNINST_HANDLER;
2258     ctl.irq   = 0;
2259     if (drmIoctl(fd, DRM_IOCTL_CONTROL, &ctl))
2260         return -errno;
2261     return 0;
2262 }
2263
2264 drm_public int drmFinish(int fd, int context, drmLockFlags flags)
2265 {
2266     drm_lock_t lock;
2267
2268     memclear(lock);
2269     lock.context = context;
2270     if (flags & DRM_LOCK_READY)      lock.flags |= _DRM_LOCK_READY;
2271     if (flags & DRM_LOCK_QUIESCENT)  lock.flags |= _DRM_LOCK_QUIESCENT;
2272     if (flags & DRM_LOCK_FLUSH)      lock.flags |= _DRM_LOCK_FLUSH;
2273     if (flags & DRM_LOCK_FLUSH_ALL)  lock.flags |= _DRM_LOCK_FLUSH_ALL;
2274     if (flags & DRM_HALT_ALL_QUEUES) lock.flags |= _DRM_HALT_ALL_QUEUES;
2275     if (flags & DRM_HALT_CUR_QUEUES) lock.flags |= _DRM_HALT_CUR_QUEUES;
2276     if (drmIoctl(fd, DRM_IOCTL_FINISH, &lock))
2277         return -errno;
2278     return 0;
2279 }
2280
2281 /**
2282  * Get IRQ from bus ID.
2283  *
2284  * \param fd file descriptor.
2285  * \param busnum bus number.
2286  * \param devnum device number.
2287  * \param funcnum function number.
2288  *
2289  * \return IRQ number on success, or a negative value on failure.
2290  *
2291  * \internal
2292  * This function is a wrapper around the DRM_IOCTL_IRQ_BUSID ioctl, passing the
2293  * arguments in a drm_irq_busid structure.
2294  */
2295 drm_public int drmGetInterruptFromBusID(int fd, int busnum, int devnum,
2296                                         int funcnum)
2297 {
2298     drm_irq_busid_t p;
2299
2300     memclear(p);
2301     p.busnum  = busnum;
2302     p.devnum  = devnum;
2303     p.funcnum = funcnum;
2304     if (drmIoctl(fd, DRM_IOCTL_IRQ_BUSID, &p))
2305         return -errno;
2306     return p.irq;
2307 }
2308
2309 drm_public int drmAddContextTag(int fd, drm_context_t context, void *tag)
2310 {
2311     drmHashEntry  *entry = drmGetEntry(fd);
2312
2313     if (drmHashInsert(entry->tagTable, context, tag)) {
2314         drmHashDelete(entry->tagTable, context);
2315         drmHashInsert(entry->tagTable, context, tag);
2316     }
2317     return 0;
2318 }
2319
2320 drm_public int drmDelContextTag(int fd, drm_context_t context)
2321 {
2322     drmHashEntry  *entry = drmGetEntry(fd);
2323
2324     return drmHashDelete(entry->tagTable, context);
2325 }
2326
2327 drm_public void *drmGetContextTag(int fd, drm_context_t context)
2328 {
2329     drmHashEntry  *entry = drmGetEntry(fd);
2330     void          *value;
2331
2332     if (drmHashLookup(entry->tagTable, context, &value))
2333         return NULL;
2334
2335     return value;
2336 }
2337
2338 drm_public int drmAddContextPrivateMapping(int fd, drm_context_t ctx_id,
2339                                            drm_handle_t handle)
2340 {
2341     drm_ctx_priv_map_t map;
2342
2343     memclear(map);
2344     map.ctx_id = ctx_id;
2345     map.handle = (void *)(uintptr_t)handle;
2346
2347     if (drmIoctl(fd, DRM_IOCTL_SET_SAREA_CTX, &map))
2348         return -errno;
2349     return 0;
2350 }
2351
2352 drm_public int drmGetContextPrivateMapping(int fd, drm_context_t ctx_id,
2353                                            drm_handle_t *handle)
2354 {
2355     drm_ctx_priv_map_t map;
2356
2357     memclear(map);
2358     map.ctx_id = ctx_id;
2359
2360     if (drmIoctl(fd, DRM_IOCTL_GET_SAREA_CTX, &map))
2361         return -errno;
2362     if (handle)
2363         *handle = (drm_handle_t)(uintptr_t)map.handle;
2364
2365     return 0;
2366 }
2367
2368 drm_public int drmGetMap(int fd, int idx, drm_handle_t *offset, drmSize *size,
2369                          drmMapType *type, drmMapFlags *flags,
2370                          drm_handle_t *handle, int *mtrr)
2371 {
2372     drm_map_t map;
2373
2374     memclear(map);
2375     map.offset = idx;
2376     if (drmIoctl(fd, DRM_IOCTL_GET_MAP, &map))
2377         return -errno;
2378     *offset = map.offset;
2379     *size   = map.size;
2380     *type   = map.type;
2381     *flags  = map.flags;
2382     *handle = (unsigned long)map.handle;
2383     *mtrr   = map.mtrr;
2384     return 0;
2385 }
2386
2387 drm_public int drmGetClient(int fd, int idx, int *auth, int *pid, int *uid,
2388                             unsigned long *magic, unsigned long *iocs)
2389 {
2390     drm_client_t client;
2391
2392     memclear(client);
2393     client.idx = idx;
2394     if (drmIoctl(fd, DRM_IOCTL_GET_CLIENT, &client))
2395         return -errno;
2396     *auth      = client.auth;
2397     *pid       = client.pid;
2398     *uid       = client.uid;
2399     *magic     = client.magic;
2400     *iocs      = client.iocs;
2401     return 0;
2402 }
2403
2404 drm_public int drmGetStats(int fd, drmStatsT *stats)
2405 {
2406     drm_stats_t s;
2407     unsigned    i;
2408
2409     memclear(s);
2410     if (drmIoctl(fd, DRM_IOCTL_GET_STATS, &s))
2411         return -errno;
2412
2413     stats->count = 0;
2414     memset(stats, 0, sizeof(*stats));
2415     if (s.count > sizeof(stats->data)/sizeof(stats->data[0]))
2416         return -1;
2417
2418 #define SET_VALUE                              \
2419     stats->data[i].long_format = "%-20.20s";   \
2420     stats->data[i].rate_format = "%8.8s";      \
2421     stats->data[i].isvalue     = 1;            \
2422     stats->data[i].verbose     = 0
2423
2424 #define SET_COUNT                              \
2425     stats->data[i].long_format = "%-20.20s";   \
2426     stats->data[i].rate_format = "%5.5s";      \
2427     stats->data[i].isvalue     = 0;            \
2428     stats->data[i].mult_names  = "kgm";        \
2429     stats->data[i].mult        = 1000;         \
2430     stats->data[i].verbose     = 0
2431
2432 #define SET_BYTE                               \
2433     stats->data[i].long_format = "%-20.20s";   \
2434     stats->data[i].rate_format = "%5.5s";      \
2435     stats->data[i].isvalue     = 0;            \
2436     stats->data[i].mult_names  = "KGM";        \
2437     stats->data[i].mult        = 1024;         \
2438     stats->data[i].verbose     = 0
2439
2440
2441     stats->count = s.count;
2442     for (i = 0; i < s.count; i++) {
2443         stats->data[i].value = s.data[i].value;
2444         switch (s.data[i].type) {
2445         case _DRM_STAT_LOCK:
2446             stats->data[i].long_name = "Lock";
2447             stats->data[i].rate_name = "Lock";
2448             SET_VALUE;
2449             break;
2450         case _DRM_STAT_OPENS:
2451             stats->data[i].long_name = "Opens";
2452             stats->data[i].rate_name = "O";
2453             SET_COUNT;
2454             stats->data[i].verbose   = 1;
2455             break;
2456         case _DRM_STAT_CLOSES:
2457             stats->data[i].long_name = "Closes";
2458             stats->data[i].rate_name = "Lock";
2459             SET_COUNT;
2460             stats->data[i].verbose   = 1;
2461             break;
2462         case _DRM_STAT_IOCTLS:
2463             stats->data[i].long_name = "Ioctls";
2464             stats->data[i].rate_name = "Ioc/s";
2465             SET_COUNT;
2466             break;
2467         case _DRM_STAT_LOCKS:
2468             stats->data[i].long_name = "Locks";
2469             stats->data[i].rate_name = "Lck/s";
2470             SET_COUNT;
2471             break;
2472         case _DRM_STAT_UNLOCKS:
2473             stats->data[i].long_name = "Unlocks";
2474             stats->data[i].rate_name = "Unl/s";
2475             SET_COUNT;
2476             break;
2477         case _DRM_STAT_IRQ:
2478             stats->data[i].long_name = "IRQs";
2479             stats->data[i].rate_name = "IRQ/s";
2480             SET_COUNT;
2481             break;
2482         case _DRM_STAT_PRIMARY:
2483             stats->data[i].long_name = "Primary Bytes";
2484             stats->data[i].rate_name = "PB/s";
2485             SET_BYTE;
2486             break;
2487         case _DRM_STAT_SECONDARY:
2488             stats->data[i].long_name = "Secondary Bytes";
2489             stats->data[i].rate_name = "SB/s";
2490             SET_BYTE;
2491             break;
2492         case _DRM_STAT_DMA:
2493             stats->data[i].long_name = "DMA";
2494             stats->data[i].rate_name = "DMA/s";
2495             SET_COUNT;
2496             break;
2497         case _DRM_STAT_SPECIAL:
2498             stats->data[i].long_name = "Special DMA";
2499             stats->data[i].rate_name = "dma/s";
2500             SET_COUNT;
2501             break;
2502         case _DRM_STAT_MISSED:
2503             stats->data[i].long_name = "Miss";
2504             stats->data[i].rate_name = "Ms/s";
2505             SET_COUNT;
2506             break;
2507         case _DRM_STAT_VALUE:
2508             stats->data[i].long_name = "Value";
2509             stats->data[i].rate_name = "Value";
2510             SET_VALUE;
2511             break;
2512         case _DRM_STAT_BYTE:
2513             stats->data[i].long_name = "Bytes";
2514             stats->data[i].rate_name = "B/s";
2515             SET_BYTE;
2516             break;
2517         case _DRM_STAT_COUNT:
2518         default:
2519             stats->data[i].long_name = "Count";
2520             stats->data[i].rate_name = "Cnt/s";
2521             SET_COUNT;
2522             break;
2523         }
2524     }
2525     return 0;
2526 }
2527
2528 /**
2529  * Issue a set-version ioctl.
2530  *
2531  * \param fd file descriptor.
2532  * \param drmCommandIndex command index
2533  * \param data source pointer of the data to be read and written.
2534  * \param size size of the data to be read and written.
2535  *
2536  * \return zero on success, or a negative value on failure.
2537  *
2538  * \internal
2539  * It issues a read-write ioctl given by
2540  * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
2541  */
2542 drm_public int drmSetInterfaceVersion(int fd, drmSetVersion *version)
2543 {
2544     int retcode = 0;
2545     drm_set_version_t sv;
2546
2547     memclear(sv);
2548     sv.drm_di_major = version->drm_di_major;
2549     sv.drm_di_minor = version->drm_di_minor;
2550     sv.drm_dd_major = version->drm_dd_major;
2551     sv.drm_dd_minor = version->drm_dd_minor;
2552
2553     if (drmIoctl(fd, DRM_IOCTL_SET_VERSION, &sv)) {
2554         retcode = -errno;
2555     }
2556
2557     version->drm_di_major = sv.drm_di_major;
2558     version->drm_di_minor = sv.drm_di_minor;
2559     version->drm_dd_major = sv.drm_dd_major;
2560     version->drm_dd_minor = sv.drm_dd_minor;
2561
2562     return retcode;
2563 }
2564
2565 /**
2566  * Send a device-specific command.
2567  *
2568  * \param fd file descriptor.
2569  * \param drmCommandIndex command index
2570  *
2571  * \return zero on success, or a negative value on failure.
2572  *
2573  * \internal
2574  * It issues a ioctl given by
2575  * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
2576  */
2577 drm_public int drmCommandNone(int fd, unsigned long drmCommandIndex)
2578 {
2579     unsigned long request;
2580
2581     request = DRM_IO( DRM_COMMAND_BASE + drmCommandIndex);
2582
2583     if (drmIoctl(fd, request, NULL)) {
2584         return -errno;
2585     }
2586     return 0;
2587 }
2588
2589
2590 /**
2591  * Send a device-specific read command.
2592  *
2593  * \param fd file descriptor.
2594  * \param drmCommandIndex command index
2595  * \param data destination pointer of the data to be read.
2596  * \param size size of the data to be read.
2597  *
2598  * \return zero on success, or a negative value on failure.
2599  *
2600  * \internal
2601  * It issues a read ioctl given by
2602  * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
2603  */
2604 drm_public int drmCommandRead(int fd, unsigned long drmCommandIndex,
2605                               void *data, unsigned long size)
2606 {
2607     unsigned long request;
2608
2609     request = DRM_IOC( DRM_IOC_READ, DRM_IOCTL_BASE,
2610         DRM_COMMAND_BASE + drmCommandIndex, size);
2611
2612     if (drmIoctl(fd, request, data)) {
2613         return -errno;
2614     }
2615     return 0;
2616 }
2617
2618
2619 /**
2620  * Send a device-specific write command.
2621  *
2622  * \param fd file descriptor.
2623  * \param drmCommandIndex command index
2624  * \param data source pointer of the data to be written.
2625  * \param size size of the data to be written.
2626  *
2627  * \return zero on success, or a negative value on failure.
2628  *
2629  * \internal
2630  * It issues a write ioctl given by
2631  * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
2632  */
2633 drm_public int drmCommandWrite(int fd, unsigned long drmCommandIndex,
2634                                void *data, unsigned long size)
2635 {
2636     unsigned long request;
2637
2638     request = DRM_IOC( DRM_IOC_WRITE, DRM_IOCTL_BASE,
2639         DRM_COMMAND_BASE + drmCommandIndex, size);
2640
2641     if (drmIoctl(fd, request, data)) {
2642         return -errno;
2643     }
2644     return 0;
2645 }
2646
2647
2648 /**
2649  * Send a device-specific read-write command.
2650  *
2651  * \param fd file descriptor.
2652  * \param drmCommandIndex command index
2653  * \param data source pointer of the data to be read and written.
2654  * \param size size of the data to be read and written.
2655  *
2656  * \return zero on success, or a negative value on failure.
2657  *
2658  * \internal
2659  * It issues a read-write ioctl given by
2660  * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
2661  */
2662 drm_public int drmCommandWriteRead(int fd, unsigned long drmCommandIndex,
2663                                    void *data, unsigned long size)
2664 {
2665     unsigned long request;
2666
2667     request = DRM_IOC( DRM_IOC_READ|DRM_IOC_WRITE, DRM_IOCTL_BASE,
2668         DRM_COMMAND_BASE + drmCommandIndex, size);
2669
2670     if (drmIoctl(fd, request, data))
2671         return -errno;
2672     return 0;
2673 }
2674
2675 #define DRM_MAX_FDS 16
2676 static struct {
2677     char *BusID;
2678     int fd;
2679     int refcount;
2680     int type;
2681 } connection[DRM_MAX_FDS];
2682
2683 static int nr_fds = 0;
2684
2685 drm_public int drmOpenOnce(void *unused, const char *BusID, int *newlyopened)
2686 {
2687     return drmOpenOnceWithType(BusID, newlyopened, DRM_NODE_PRIMARY);
2688 }
2689
2690 drm_public int drmOpenOnceWithType(const char *BusID, int *newlyopened,
2691                                    int type)
2692 {
2693     int i;
2694     int fd;
2695
2696     for (i = 0; i < nr_fds; i++)
2697         if ((strcmp(BusID, connection[i].BusID) == 0) &&
2698             (connection[i].type == type)) {
2699             connection[i].refcount++;
2700             *newlyopened = 0;
2701             return connection[i].fd;
2702         }
2703
2704     fd = drmOpenWithType(NULL, BusID, type);
2705     if (fd < 0 || nr_fds == DRM_MAX_FDS)
2706         return fd;
2707
2708     connection[nr_fds].BusID = strdup(BusID);
2709     connection[nr_fds].fd = fd;
2710     connection[nr_fds].refcount = 1;
2711     connection[nr_fds].type = type;
2712     *newlyopened = 1;
2713
2714     if (0)
2715         fprintf(stderr, "saved connection %d for %s %d\n",
2716                 nr_fds, connection[nr_fds].BusID,
2717                 strcmp(BusID, connection[nr_fds].BusID));
2718
2719     nr_fds++;
2720
2721     return fd;
2722 }
2723
2724 drm_public void drmCloseOnce(int fd)
2725 {
2726     int i;
2727
2728     for (i = 0; i < nr_fds; i++) {
2729         if (fd == connection[i].fd) {
2730             if (--connection[i].refcount == 0) {
2731                 drmClose(connection[i].fd);
2732                 free(connection[i].BusID);
2733
2734                 if (i < --nr_fds)
2735                     connection[i] = connection[nr_fds];
2736
2737                 return;
2738             }
2739         }
2740     }
2741 }
2742
2743 drm_public int drmSetMaster(int fd)
2744 {
2745         return drmIoctl(fd, DRM_IOCTL_SET_MASTER, NULL);
2746 }
2747
2748 drm_public int drmDropMaster(int fd)
2749 {
2750         return drmIoctl(fd, DRM_IOCTL_DROP_MASTER, NULL);
2751 }
2752
2753 drm_public int drmIsMaster(int fd)
2754 {
2755         /* Detect master by attempting something that requires master.
2756          *
2757          * Authenticating magic tokens requires master and 0 is an
2758          * internal kernel detail which we could use. Attempting this on
2759          * a master fd would fail therefore fail with EINVAL because 0
2760          * is invalid.
2761          *
2762          * A non-master fd will fail with EACCES, as the kernel checks
2763          * for master before attempting to do anything else.
2764          *
2765          * Since we don't want to leak implementation details, use
2766          * EACCES.
2767          */
2768         return drmAuthMagic(fd, 0) != -EACCES;
2769 }
2770
2771 drm_public char *drmGetDeviceNameFromFd(int fd)
2772 {
2773 #ifdef __FreeBSD__
2774     struct stat sbuf;
2775     char dname[SPECNAMELEN];
2776     char name[SPECNAMELEN];
2777     int maj, min;
2778
2779     if (fstat(fd, &sbuf))
2780         return NULL;
2781
2782     maj = major(sbuf.st_rdev);
2783     min = minor(sbuf.st_rdev);
2784
2785     if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode))
2786         return NULL;
2787
2788     if (!devname_r(sbuf.st_rdev, S_IFCHR, dname, sizeof(dname)))
2789         return NULL;
2790
2791     snprintf(name, sizeof(name), "/dev/%s", dname);
2792     return strdup(name);
2793 #else
2794     char name[128];
2795     struct stat sbuf;
2796     dev_t d;
2797     int i;
2798
2799     /* The whole drmOpen thing is a fiasco and we need to find a way
2800      * back to just using open(2).  For now, however, lets just make
2801      * things worse with even more ad hoc directory walking code to
2802      * discover the device file name. */
2803
2804     fstat(fd, &sbuf);
2805     d = sbuf.st_rdev;
2806
2807     for (i = 0; i < DRM_MAX_MINOR; i++) {
2808         snprintf(name, sizeof name, DRM_DEV_NAME, DRM_DIR_NAME, i);
2809         if (stat(name, &sbuf) == 0 && sbuf.st_rdev == d)
2810             break;
2811     }
2812     if (i == DRM_MAX_MINOR)
2813         return NULL;
2814
2815     return strdup(name);
2816 #endif
2817 }
2818
2819 static bool drmNodeIsDRM(int maj, int min)
2820 {
2821 #ifdef __linux__
2822     char path[64];
2823     struct stat sbuf;
2824
2825     snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device/drm",
2826              maj, min);
2827     return stat(path, &sbuf) == 0;
2828 #elif __FreeBSD__
2829     char name[SPECNAMELEN];
2830
2831     if (!devname_r(makedev(maj, min), S_IFCHR, name, sizeof(name)))
2832       return 0;
2833     /* Handle drm/ and dri/ as both are present in different FreeBSD version
2834      * FreeBSD on amd64/i386/powerpc external kernel modules create node in
2835      * in /dev/drm/ and links in /dev/dri while a WIP in kernel driver creates
2836      * only device nodes in /dev/dri/ */
2837     return (!strncmp(name, "drm/", 4) || !strncmp(name, "dri/", 4));
2838 #else
2839     return maj == DRM_MAJOR;
2840 #endif
2841 }
2842
2843 drm_public int drmGetNodeTypeFromFd(int fd)
2844 {
2845     struct stat sbuf;
2846     int maj, min, type;
2847
2848     if (fstat(fd, &sbuf))
2849         return -1;
2850
2851     maj = major(sbuf.st_rdev);
2852     min = minor(sbuf.st_rdev);
2853
2854     if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode)) {
2855         errno = EINVAL;
2856         return -1;
2857     }
2858
2859     type = drmGetMinorType(maj, min);
2860     if (type == -1)
2861         errno = ENODEV;
2862     return type;
2863 }
2864
2865 drm_public int drmPrimeHandleToFD(int fd, uint32_t handle, uint32_t flags,
2866                                   int *prime_fd)
2867 {
2868     struct drm_prime_handle args;
2869     int ret;
2870
2871     memclear(args);
2872     args.fd = -1;
2873     args.handle = handle;
2874     args.flags = flags;
2875     ret = drmIoctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &args);
2876     if (ret)
2877         return ret;
2878
2879     *prime_fd = args.fd;
2880     return 0;
2881 }
2882
2883 drm_public int drmPrimeFDToHandle(int fd, int prime_fd, uint32_t *handle)
2884 {
2885     struct drm_prime_handle args;
2886     int ret;
2887
2888     memclear(args);
2889     args.fd = prime_fd;
2890     ret = drmIoctl(fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &args);
2891     if (ret)
2892         return ret;
2893
2894     *handle = args.handle;
2895     return 0;
2896 }
2897
2898 static char *drmGetMinorNameForFD(int fd, int type)
2899 {
2900 #ifdef __linux__
2901     DIR *sysdir;
2902     struct dirent *ent;
2903     struct stat sbuf;
2904     const char *name = drmGetMinorName(type);
2905     int len;
2906     char dev_name[64], buf[64];
2907     int maj, min;
2908
2909     if (!name)
2910         return NULL;
2911
2912     len = strlen(name);
2913
2914     if (fstat(fd, &sbuf))
2915         return NULL;
2916
2917     maj = major(sbuf.st_rdev);
2918     min = minor(sbuf.st_rdev);
2919
2920     if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode))
2921         return NULL;
2922
2923     snprintf(buf, sizeof(buf), "/sys/dev/char/%d:%d/device/drm", maj, min);
2924
2925     sysdir = opendir(buf);
2926     if (!sysdir)
2927         return NULL;
2928
2929     while ((ent = readdir(sysdir))) {
2930         if (strncmp(ent->d_name, name, len) == 0) {
2931             snprintf(dev_name, sizeof(dev_name), DRM_DIR_NAME "/%s",
2932                  ent->d_name);
2933
2934             closedir(sysdir);
2935             return strdup(dev_name);
2936         }
2937     }
2938
2939     closedir(sysdir);
2940     return NULL;
2941 #elif __FreeBSD__
2942     struct stat sbuf;
2943     char dname[SPECNAMELEN];
2944     const char *mname;
2945     char name[SPECNAMELEN];
2946     int id, maj, min;
2947
2948     if (fstat(fd, &sbuf))
2949         return NULL;
2950
2951     maj = major(sbuf.st_rdev);
2952     min = minor(sbuf.st_rdev);
2953
2954     if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode))
2955         return NULL;
2956
2957     if (!devname_r(sbuf.st_rdev, S_IFCHR, dname, sizeof(dname)))
2958         return NULL;
2959
2960     /* Handle both /dev/drm and /dev/dri
2961      * FreeBSD on amd64/i386/powerpc external kernel modules create node in
2962      * in /dev/drm/ and links in /dev/dri while a WIP in kernel driver creates
2963      * only device nodes in /dev/dri/ */
2964     mname = drmGetMinorName(type);
2965     if (sscanf(dname, "drm/%d", &id) != 1) {
2966         snprintf(name, sizeof(name), "dri/%s", mname);
2967         if (strncmp(name, dname, strlen(name)) != 0)
2968             return NULL;
2969         snprintf(name, sizeof(name), "/dev/%s", dname);
2970     } else
2971         snprintf(name, sizeof(name), DRM_DIR_NAME "/%s%d", mname, id);
2972     return strdup(name);
2973 #else
2974     struct stat sbuf;
2975     char buf[PATH_MAX + 1];
2976     const char *dev_name = drmGetDeviceName(type);
2977     unsigned int maj, min;
2978     int n;
2979
2980     if (fstat(fd, &sbuf))
2981         return NULL;
2982
2983     maj = major(sbuf.st_rdev);
2984     min = minor(sbuf.st_rdev);
2985
2986     if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode))
2987         return NULL;
2988
2989     if (!dev_name)
2990         return NULL;
2991
2992     n = snprintf(buf, sizeof(buf), dev_name, DRM_DIR_NAME, min);
2993     if (n == -1 || n >= sizeof(buf))
2994         return NULL;
2995
2996     return strdup(buf);
2997 #endif
2998 }
2999
3000 drm_public char *drmGetPrimaryDeviceNameFromFd(int fd)
3001 {
3002     return drmGetMinorNameForFD(fd, DRM_NODE_PRIMARY);
3003 }
3004
3005 drm_public char *drmGetRenderDeviceNameFromFd(int fd)
3006 {
3007     return drmGetMinorNameForFD(fd, DRM_NODE_RENDER);
3008 }
3009
3010 #ifdef __linux__
3011 static char * DRM_PRINTFLIKE(2, 3)
3012 sysfs_uevent_get(const char *path, const char *fmt, ...)
3013 {
3014     char filename[PATH_MAX + 1], *key, *line = NULL, *value = NULL;
3015     size_t size = 0, len;
3016     ssize_t num;
3017     va_list ap;
3018     FILE *fp;
3019
3020     va_start(ap, fmt);
3021     num = vasprintf(&key, fmt, ap);
3022     va_end(ap);
3023     len = num;
3024
3025     snprintf(filename, sizeof(filename), "%s/uevent", path);
3026
3027     fp = fopen(filename, "r");
3028     if (!fp) {
3029         free(key);
3030         return NULL;
3031     }
3032
3033     while ((num = getline(&line, &size, fp)) >= 0) {
3034         if ((strncmp(line, key, len) == 0) && (line[len] == '=')) {
3035             char *start = line + len + 1, *end = line + num - 1;
3036
3037             if (*end != '\n')
3038                 end++;
3039
3040             value = strndup(start, end - start);
3041             break;
3042         }
3043     }
3044
3045     free(line);
3046     fclose(fp);
3047
3048     free(key);
3049
3050     return value;
3051 }
3052 #endif
3053
3054 /* Little white lie to avoid major rework of the existing code */
3055 #define DRM_BUS_VIRTIO 0x10
3056
3057 #ifdef __linux__
3058 static int get_subsystem_type(const char *device_path)
3059 {
3060     char path[PATH_MAX + 1] = "";
3061     char link[PATH_MAX + 1] = "";
3062     char *name;
3063     struct {
3064         const char *name;
3065         int bus_type;
3066     } bus_types[] = {
3067         { "/pci", DRM_BUS_PCI },
3068         { "/usb", DRM_BUS_USB },
3069         { "/platform", DRM_BUS_PLATFORM },
3070         { "/spi", DRM_BUS_PLATFORM },
3071         { "/host1x", DRM_BUS_HOST1X },
3072         { "/virtio", DRM_BUS_VIRTIO },
3073     };
3074
3075     strncpy(path, device_path, PATH_MAX);
3076     strncat(path, "/subsystem", PATH_MAX);
3077
3078     if (readlink(path, link, PATH_MAX) < 0)
3079         return -errno;
3080
3081     name = strrchr(link, '/');
3082     if (!name)
3083         return -EINVAL;
3084
3085     for (unsigned i = 0; i < ARRAY_SIZE(bus_types); i++) {
3086         if (strncmp(name, bus_types[i].name, strlen(bus_types[i].name)) == 0)
3087             return bus_types[i].bus_type;
3088     }
3089
3090     return -EINVAL;
3091 }
3092 #endif
3093
3094 static int drmParseSubsystemType(int maj, int min)
3095 {
3096 #ifdef __linux__
3097     char path[PATH_MAX + 1] = "";
3098     char real_path[PATH_MAX + 1] = "";
3099     int subsystem_type;
3100
3101     snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min);
3102     if (!realpath(path, real_path))
3103         return -errno;
3104     snprintf(path, sizeof(path), "%s", real_path);
3105
3106     subsystem_type = get_subsystem_type(path);
3107     if (subsystem_type == DRM_BUS_VIRTIO) {
3108         strncat(path, "/..", PATH_MAX);
3109         subsystem_type = get_subsystem_type(path);
3110     }
3111     return subsystem_type;
3112 #elif defined(__OpenBSD__) || defined(__DragonFly__) || defined(__FreeBSD__)
3113     return DRM_BUS_PCI;
3114 #else
3115 #warning "Missing implementation of drmParseSubsystemType"
3116     return -EINVAL;
3117 #endif
3118 }
3119
3120 static void
3121 get_pci_path(int maj, int min, char *pci_path)
3122 {
3123     char path[PATH_MAX + 1], *term;
3124
3125     snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min);
3126     if (!realpath(path, pci_path)) {
3127         strcpy(pci_path, path);
3128         return;
3129     }
3130
3131     term = strrchr(pci_path, '/');
3132     if (term && strncmp(term, "/virtio", 7) == 0)
3133         *term = 0;
3134 }
3135
3136 static int drmParsePciBusInfo(int maj, int min, drmPciBusInfoPtr info)
3137 {
3138 #ifdef __linux__
3139     unsigned int domain, bus, dev, func;
3140     char pci_path[PATH_MAX + 1], *value;
3141     int num;
3142
3143     get_pci_path(maj, min, pci_path);
3144
3145     value = sysfs_uevent_get(pci_path, "PCI_SLOT_NAME");
3146     if (!value)
3147         return -ENOENT;
3148
3149     num = sscanf(value, "%04x:%02x:%02x.%1u", &domain, &bus, &dev, &func);
3150     free(value);
3151
3152     if (num != 4)
3153         return -EINVAL;
3154
3155     info->domain = domain;
3156     info->bus = bus;
3157     info->dev = dev;
3158     info->func = func;
3159
3160     return 0;
3161 #elif defined(__OpenBSD__) || defined(__DragonFly__)
3162     struct drm_pciinfo pinfo;
3163     int fd, type;
3164
3165     type = drmGetMinorType(maj, min);
3166     if (type == -1)
3167         return -ENODEV;
3168
3169     fd = drmOpenMinor(min, 0, type);
3170     if (fd < 0)
3171         return -errno;
3172
3173     if (drmIoctl(fd, DRM_IOCTL_GET_PCIINFO, &pinfo)) {
3174         close(fd);
3175         return -errno;
3176     }
3177     close(fd);
3178
3179     info->domain = pinfo.domain;
3180     info->bus = pinfo.bus;
3181     info->dev = pinfo.dev;
3182     info->func = pinfo.func;
3183
3184     return 0;
3185 #else
3186 #warning "Missing implementation of drmParsePciBusInfo"
3187     return -EINVAL;
3188 #endif
3189 }
3190
3191 drm_public int drmDevicesEqual(drmDevicePtr a, drmDevicePtr b)
3192 {
3193     if (a == NULL || b == NULL)
3194         return 0;
3195
3196     if (a->bustype != b->bustype)
3197         return 0;
3198
3199     switch (a->bustype) {
3200     case DRM_BUS_PCI:
3201         return memcmp(a->businfo.pci, b->businfo.pci, sizeof(drmPciBusInfo)) == 0;
3202
3203     case DRM_BUS_USB:
3204         return memcmp(a->businfo.usb, b->businfo.usb, sizeof(drmUsbBusInfo)) == 0;
3205
3206     case DRM_BUS_PLATFORM:
3207         return memcmp(a->businfo.platform, b->businfo.platform, sizeof(drmPlatformBusInfo)) == 0;
3208
3209     case DRM_BUS_HOST1X:
3210         return memcmp(a->businfo.host1x, b->businfo.host1x, sizeof(drmHost1xBusInfo)) == 0;
3211
3212     default:
3213         break;
3214     }
3215
3216     return 0;
3217 }
3218
3219 static int drmGetNodeType(const char *name)
3220 {
3221     if (strncmp(name, DRM_CONTROL_MINOR_NAME,
3222         sizeof(DRM_CONTROL_MINOR_NAME ) - 1) == 0)
3223         return DRM_NODE_CONTROL;
3224
3225     if (strncmp(name, DRM_RENDER_MINOR_NAME,
3226         sizeof(DRM_RENDER_MINOR_NAME) - 1) == 0)
3227         return DRM_NODE_RENDER;
3228
3229     if (strncmp(name, DRM_PRIMARY_MINOR_NAME,
3230         sizeof(DRM_PRIMARY_MINOR_NAME) - 1) == 0)
3231         return DRM_NODE_PRIMARY;
3232
3233     return -EINVAL;
3234 }
3235
3236 static int drmGetMaxNodeName(void)
3237 {
3238     return sizeof(DRM_DIR_NAME) +
3239            MAX3(sizeof(DRM_PRIMARY_MINOR_NAME),
3240                 sizeof(DRM_CONTROL_MINOR_NAME),
3241                 sizeof(DRM_RENDER_MINOR_NAME)) +
3242            3 /* length of the node number */;
3243 }
3244
3245 #ifdef __linux__
3246 static int parse_separate_sysfs_files(int maj, int min,
3247                                       drmPciDeviceInfoPtr device,
3248                                       bool ignore_revision)
3249 {
3250     static const char *attrs[] = {
3251       "revision", /* Older kernels are missing the file, so check for it first */
3252       "vendor",
3253       "device",
3254       "subsystem_vendor",
3255       "subsystem_device",
3256     };
3257     char path[PATH_MAX + 1], pci_path[PATH_MAX + 1];
3258     unsigned int data[ARRAY_SIZE(attrs)];
3259     FILE *fp;
3260     int ret;
3261
3262     get_pci_path(maj, min, pci_path);
3263
3264     for (unsigned i = ignore_revision ? 1 : 0; i < ARRAY_SIZE(attrs); i++) {
3265         snprintf(path, PATH_MAX, "%s/%s", pci_path, attrs[i]);
3266         fp = fopen(path, "r");
3267         if (!fp)
3268             return -errno;
3269
3270         ret = fscanf(fp, "%x", &data[i]);
3271         fclose(fp);
3272         if (ret != 1)
3273             return -errno;
3274
3275     }
3276
3277     device->revision_id = ignore_revision ? 0xff : data[0] & 0xff;
3278     device->vendor_id = data[1] & 0xffff;
3279     device->device_id = data[2] & 0xffff;
3280     device->subvendor_id = data[3] & 0xffff;
3281     device->subdevice_id = data[4] & 0xffff;
3282
3283     return 0;
3284 }
3285
3286 static int parse_config_sysfs_file(int maj, int min,
3287                                    drmPciDeviceInfoPtr device)
3288 {
3289     char path[PATH_MAX + 1], pci_path[PATH_MAX + 1];
3290     unsigned char config[64];
3291     int fd, ret;
3292
3293     get_pci_path(maj, min, pci_path);
3294
3295     snprintf(path, PATH_MAX, "%s/config", pci_path);
3296     fd = open(path, O_RDONLY);
3297     if (fd < 0)
3298         return -errno;
3299
3300     ret = read(fd, config, sizeof(config));
3301     close(fd);
3302     if (ret < 0)
3303         return -errno;
3304
3305     device->vendor_id = config[0] | (config[1] << 8);
3306     device->device_id = config[2] | (config[3] << 8);
3307     device->revision_id = config[8];
3308     device->subvendor_id = config[44] | (config[45] << 8);
3309     device->subdevice_id = config[46] | (config[47] << 8);
3310
3311     return 0;
3312 }
3313 #endif
3314
3315 static int drmParsePciDeviceInfo(int maj, int min,
3316                                  drmPciDeviceInfoPtr device,
3317                                  uint32_t flags)
3318 {
3319 #ifdef __linux__
3320     if (!(flags & DRM_DEVICE_GET_PCI_REVISION))
3321         return parse_separate_sysfs_files(maj, min, device, true);
3322
3323     if (parse_separate_sysfs_files(maj, min, device, false))
3324         return parse_config_sysfs_file(maj, min, device);
3325
3326     return 0;
3327 #elif defined(__OpenBSD__) || defined(__DragonFly__)
3328     struct drm_pciinfo pinfo;
3329     int fd, type;
3330
3331     type = drmGetMinorType(maj, min);
3332     if (type == -1)
3333         return -ENODEV;
3334
3335     fd = drmOpenMinor(min, 0, type);
3336     if (fd < 0)
3337         return -errno;
3338
3339     if (drmIoctl(fd, DRM_IOCTL_GET_PCIINFO, &pinfo)) {
3340         close(fd);
3341         return -errno;
3342     }
3343     close(fd);
3344
3345     device->vendor_id = pinfo.vendor_id;
3346     device->device_id = pinfo.device_id;
3347     device->revision_id = pinfo.revision_id;
3348     device->subvendor_id = pinfo.subvendor_id;
3349     device->subdevice_id = pinfo.subdevice_id;
3350
3351     return 0;
3352 #else
3353 #warning "Missing implementation of drmParsePciDeviceInfo"
3354     return -EINVAL;
3355 #endif
3356 }
3357
3358 static void drmFreePlatformDevice(drmDevicePtr device)
3359 {
3360     if (device->deviceinfo.platform) {
3361         if (device->deviceinfo.platform->compatible) {
3362             char **compatible = device->deviceinfo.platform->compatible;
3363
3364             while (*compatible) {
3365                 free(*compatible);
3366                 compatible++;
3367             }
3368
3369             free(device->deviceinfo.platform->compatible);
3370         }
3371     }
3372 }
3373
3374 static void drmFreeHost1xDevice(drmDevicePtr device)
3375 {
3376     if (device->deviceinfo.host1x) {
3377         if (device->deviceinfo.host1x->compatible) {
3378             char **compatible = device->deviceinfo.host1x->compatible;
3379
3380             while (*compatible) {
3381                 free(*compatible);
3382                 compatible++;
3383             }
3384
3385             free(device->deviceinfo.host1x->compatible);
3386         }
3387     }
3388 }
3389
3390 drm_public void drmFreeDevice(drmDevicePtr *device)
3391 {
3392     if (device == NULL)
3393         return;
3394
3395     if (*device) {
3396         switch ((*device)->bustype) {
3397         case DRM_BUS_PLATFORM:
3398             drmFreePlatformDevice(*device);
3399             break;
3400
3401         case DRM_BUS_HOST1X:
3402             drmFreeHost1xDevice(*device);
3403             break;
3404         }
3405     }
3406
3407     free(*device);
3408     *device = NULL;
3409 }
3410
3411 drm_public void drmFreeDevices(drmDevicePtr devices[], int count)
3412 {
3413     int i;
3414
3415     if (devices == NULL)
3416         return;
3417
3418     for (i = 0; i < count; i++)
3419         if (devices[i])
3420             drmFreeDevice(&devices[i]);
3421 }
3422
3423 static drmDevicePtr drmDeviceAlloc(unsigned int type, const char *node,
3424                                    size_t bus_size, size_t device_size,
3425                                    char **ptrp)
3426 {
3427     size_t max_node_length, extra, size;
3428     drmDevicePtr device;
3429     unsigned int i;
3430     char *ptr;
3431
3432     max_node_length = ALIGN(drmGetMaxNodeName(), sizeof(void *));
3433     extra = DRM_NODE_MAX * (sizeof(void *) + max_node_length);
3434
3435     size = sizeof(*device) + extra + bus_size + device_size;
3436
3437     device = calloc(1, size);
3438     if (!device)
3439         return NULL;
3440
3441     device->available_nodes = 1 << type;
3442
3443     ptr = (char *)device + sizeof(*device);
3444     device->nodes = (char **)ptr;
3445
3446     ptr += DRM_NODE_MAX * sizeof(void *);
3447
3448     for (i = 0; i < DRM_NODE_MAX; i++) {
3449         device->nodes[i] = ptr;
3450         ptr += max_node_length;
3451     }
3452
3453     memcpy(device->nodes[type], node, max_node_length);
3454
3455     *ptrp = ptr;
3456
3457     return device;
3458 }
3459
3460 static int drmProcessPciDevice(drmDevicePtr *device,
3461                                const char *node, int node_type,
3462                                int maj, int min, bool fetch_deviceinfo,
3463                                uint32_t flags)
3464 {
3465     drmDevicePtr dev;
3466     char *addr;
3467     int ret;
3468
3469     dev = drmDeviceAlloc(node_type, node, sizeof(drmPciBusInfo),
3470                          sizeof(drmPciDeviceInfo), &addr);
3471     if (!dev)
3472         return -ENOMEM;
3473
3474     dev->bustype = DRM_BUS_PCI;
3475
3476     dev->businfo.pci = (drmPciBusInfoPtr)addr;
3477
3478     ret = drmParsePciBusInfo(maj, min, dev->businfo.pci);
3479     if (ret)
3480         goto free_device;
3481
3482     // Fetch the device info if the user has requested it
3483     if (fetch_deviceinfo) {
3484         addr += sizeof(drmPciBusInfo);
3485         dev->deviceinfo.pci = (drmPciDeviceInfoPtr)addr;
3486
3487         ret = drmParsePciDeviceInfo(maj, min, dev->deviceinfo.pci, flags);
3488         if (ret)
3489             goto free_device;
3490     }
3491
3492     *device = dev;
3493
3494     return 0;
3495
3496 free_device:
3497     free(dev);
3498     return ret;
3499 }
3500
3501 static int drmParseUsbBusInfo(int maj, int min, drmUsbBusInfoPtr info)
3502 {
3503 #ifdef __linux__
3504     char path[PATH_MAX + 1], *value;
3505     unsigned int bus, dev;
3506     int ret;
3507
3508     snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min);
3509
3510     value = sysfs_uevent_get(path, "BUSNUM");
3511     if (!value)
3512         return -ENOENT;
3513
3514     ret = sscanf(value, "%03u", &bus);
3515     free(value);
3516
3517     if (ret <= 0)
3518         return -errno;
3519
3520     value = sysfs_uevent_get(path, "DEVNUM");
3521     if (!value)
3522         return -ENOENT;
3523
3524     ret = sscanf(value, "%03u", &dev);
3525     free(value);
3526
3527     if (ret <= 0)
3528         return -errno;
3529
3530     info->bus = bus;
3531     info->dev = dev;
3532
3533     return 0;
3534 #else
3535 #warning "Missing implementation of drmParseUsbBusInfo"
3536     return -EINVAL;
3537 #endif
3538 }
3539
3540 static int drmParseUsbDeviceInfo(int maj, int min, drmUsbDeviceInfoPtr info)
3541 {
3542 #ifdef __linux__
3543     char path[PATH_MAX + 1], *value;
3544     unsigned int vendor, product;
3545     int ret;
3546
3547     snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min);
3548
3549     value = sysfs_uevent_get(path, "PRODUCT");
3550     if (!value)
3551         return -ENOENT;
3552
3553     ret = sscanf(value, "%x/%x", &vendor, &product);
3554     free(value);
3555
3556     if (ret <= 0)
3557         return -errno;
3558
3559     info->vendor = vendor;
3560     info->product = product;
3561
3562     return 0;
3563 #else
3564 #warning "Missing implementation of drmParseUsbDeviceInfo"
3565     return -EINVAL;
3566 #endif
3567 }
3568
3569 static int drmProcessUsbDevice(drmDevicePtr *device, const char *node,
3570                                int node_type, int maj, int min,
3571                                bool fetch_deviceinfo, uint32_t flags)
3572 {
3573     drmDevicePtr dev;
3574     char *ptr;
3575     int ret;
3576
3577     dev = drmDeviceAlloc(node_type, node, sizeof(drmUsbBusInfo),
3578                          sizeof(drmUsbDeviceInfo), &ptr);
3579     if (!dev)
3580         return -ENOMEM;
3581
3582     dev->bustype = DRM_BUS_USB;
3583
3584     dev->businfo.usb = (drmUsbBusInfoPtr)ptr;
3585
3586     ret = drmParseUsbBusInfo(maj, min, dev->businfo.usb);
3587     if (ret < 0)
3588         goto free_device;
3589
3590     if (fetch_deviceinfo) {
3591         ptr += sizeof(drmUsbBusInfo);
3592         dev->deviceinfo.usb = (drmUsbDeviceInfoPtr)ptr;
3593
3594         ret = drmParseUsbDeviceInfo(maj, min, dev->deviceinfo.usb);
3595         if (ret < 0)
3596             goto free_device;
3597     }
3598
3599     *device = dev;
3600
3601     return 0;
3602
3603 free_device:
3604     free(dev);
3605     return ret;
3606 }
3607
3608 static int drmParseOFBusInfo(int maj, int min, char *fullname)
3609 {
3610 #ifdef __linux__
3611     char path[PATH_MAX + 1], *name, *tmp_name;
3612
3613     snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min);
3614
3615     name = sysfs_uevent_get(path, "OF_FULLNAME");
3616     tmp_name = name;
3617     if (!name) {
3618         /* If the device lacks OF data, pick the MODALIAS info */
3619         name = sysfs_uevent_get(path, "MODALIAS");
3620         if (!name)
3621             return -ENOENT;
3622
3623         /* .. and strip the MODALIAS=[platform,usb...]: part. */
3624         tmp_name = strrchr(name, ':');
3625         if (!tmp_name) {
3626             free(name);
3627             return -ENOENT;
3628         }
3629         tmp_name++;
3630     }
3631
3632     strncpy(fullname, tmp_name, DRM_PLATFORM_DEVICE_NAME_LEN);
3633     fullname[DRM_PLATFORM_DEVICE_NAME_LEN - 1] = '\0';
3634     free(name);
3635
3636     return 0;
3637 #else
3638 #warning "Missing implementation of drmParseOFBusInfo"
3639     return -EINVAL;
3640 #endif
3641 }
3642
3643 static int drmParseOFDeviceInfo(int maj, int min, char ***compatible)
3644 {
3645 #ifdef __linux__
3646     char path[PATH_MAX + 1], *value, *tmp_name;
3647     unsigned int count, i;
3648     int err;
3649
3650     snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min);
3651
3652     value = sysfs_uevent_get(path, "OF_COMPATIBLE_N");
3653     if (value) {
3654         sscanf(value, "%u", &count);
3655         free(value);
3656     } else {
3657         /* Assume one entry if the device lack OF data */
3658         count = 1;
3659     }
3660
3661     *compatible = calloc(count + 1, sizeof(char *));
3662     if (!*compatible)
3663         return -ENOMEM;
3664
3665     for (i = 0; i < count; i++) {
3666         value = sysfs_uevent_get(path, "OF_COMPATIBLE_%u", i);
3667         tmp_name = value;
3668         if (!value) {
3669             /* If the device lacks OF data, pick the MODALIAS info */
3670             value = sysfs_uevent_get(path, "MODALIAS");
3671             if (!value) {
3672                 err = -ENOENT;
3673                 goto free;
3674             }
3675
3676             /* .. and strip the MODALIAS=[platform,usb...]: part. */
3677             tmp_name = strrchr(value, ':');
3678             if (!tmp_name) {
3679                 free(value);
3680                 return -ENOENT;
3681             }
3682             tmp_name = strdup(tmp_name + 1);
3683             free(value);
3684         }
3685
3686         (*compatible)[i] = tmp_name;
3687     }
3688
3689     return 0;
3690
3691 free:
3692     while (i--)
3693         free((*compatible)[i]);
3694
3695     free(*compatible);
3696     return err;
3697 #else
3698 #warning "Missing implementation of drmParseOFDeviceInfo"
3699     return -EINVAL;
3700 #endif
3701 }
3702
3703 static int drmProcessPlatformDevice(drmDevicePtr *device,
3704                                     const char *node, int node_type,
3705                                     int maj, int min, bool fetch_deviceinfo,
3706                                     uint32_t flags)
3707 {
3708     drmDevicePtr dev;
3709     char *ptr;
3710     int ret;
3711
3712     dev = drmDeviceAlloc(node_type, node, sizeof(drmPlatformBusInfo),
3713                          sizeof(drmPlatformDeviceInfo), &ptr);
3714     if (!dev)
3715         return -ENOMEM;
3716
3717     dev->bustype = DRM_BUS_PLATFORM;
3718
3719     dev->businfo.platform = (drmPlatformBusInfoPtr)ptr;
3720
3721     ret = drmParseOFBusInfo(maj, min, dev->businfo.platform->fullname);
3722     if (ret < 0)
3723         goto free_device;
3724
3725     if (fetch_deviceinfo) {
3726         ptr += sizeof(drmPlatformBusInfo);
3727         dev->deviceinfo.platform = (drmPlatformDeviceInfoPtr)ptr;
3728
3729         ret = drmParseOFDeviceInfo(maj, min, &dev->deviceinfo.platform->compatible);
3730         if (ret < 0)
3731             goto free_device;
3732     }
3733
3734     *device = dev;
3735
3736     return 0;
3737
3738 free_device:
3739     free(dev);
3740     return ret;
3741 }
3742
3743 static int drmProcessHost1xDevice(drmDevicePtr *device,
3744                                   const char *node, int node_type,
3745                                   int maj, int min, bool fetch_deviceinfo,
3746                                   uint32_t flags)
3747 {
3748     drmDevicePtr dev;
3749     char *ptr;
3750     int ret;
3751
3752     dev = drmDeviceAlloc(node_type, node, sizeof(drmHost1xBusInfo),
3753                          sizeof(drmHost1xDeviceInfo), &ptr);
3754     if (!dev)
3755         return -ENOMEM;
3756
3757     dev->bustype = DRM_BUS_HOST1X;
3758
3759     dev->businfo.host1x = (drmHost1xBusInfoPtr)ptr;
3760
3761     ret = drmParseOFBusInfo(maj, min, dev->businfo.host1x->fullname);
3762     if (ret < 0)
3763         goto free_device;
3764
3765     if (fetch_deviceinfo) {
3766         ptr += sizeof(drmHost1xBusInfo);
3767         dev->deviceinfo.host1x = (drmHost1xDeviceInfoPtr)ptr;
3768
3769         ret = drmParseOFDeviceInfo(maj, min, &dev->deviceinfo.host1x->compatible);
3770         if (ret < 0)
3771             goto free_device;
3772     }
3773
3774     *device = dev;
3775
3776     return 0;
3777
3778 free_device:
3779     free(dev);
3780     return ret;
3781 }
3782
3783 static int
3784 process_device(drmDevicePtr *device, const char *d_name,
3785                int req_subsystem_type,
3786                bool fetch_deviceinfo, uint32_t flags)
3787 {
3788     struct stat sbuf;
3789     char node[PATH_MAX + 1];
3790     int node_type, subsystem_type;
3791     unsigned int maj, min;
3792
3793     node_type = drmGetNodeType(d_name);
3794     if (node_type < 0)
3795         return -1;
3796
3797     snprintf(node, PATH_MAX, "%s/%s", DRM_DIR_NAME, d_name);
3798     if (stat(node, &sbuf))
3799         return -1;
3800
3801     maj = major(sbuf.st_rdev);
3802     min = minor(sbuf.st_rdev);
3803
3804     if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode))
3805         return -1;
3806
3807     subsystem_type = drmParseSubsystemType(maj, min);
3808     if (req_subsystem_type != -1 && req_subsystem_type != subsystem_type)
3809         return -1;
3810
3811     switch (subsystem_type) {
3812     case DRM_BUS_PCI:
3813         return drmProcessPciDevice(device, node, node_type, maj, min,
3814                                    fetch_deviceinfo, flags);
3815     case DRM_BUS_USB:
3816         return drmProcessUsbDevice(device, node, node_type, maj, min,
3817                                    fetch_deviceinfo, flags);
3818     case DRM_BUS_PLATFORM:
3819         return drmProcessPlatformDevice(device, node, node_type, maj, min,
3820                                         fetch_deviceinfo, flags);
3821     case DRM_BUS_HOST1X:
3822         return drmProcessHost1xDevice(device, node, node_type, maj, min,
3823                                       fetch_deviceinfo, flags);
3824     default:
3825         return -1;
3826    }
3827 }
3828
3829 /* Consider devices located on the same bus as duplicate and fold the respective
3830  * entries into a single one.
3831  *
3832  * Note: this leaves "gaps" in the array, while preserving the length.
3833  */
3834 static void drmFoldDuplicatedDevices(drmDevicePtr local_devices[], int count)
3835 {
3836     int node_type, i, j;
3837
3838     for (i = 0; i < count; i++) {
3839         for (j = i + 1; j < count; j++) {
3840             if (drmDevicesEqual(local_devices[i], local_devices[j])) {
3841                 local_devices[i]->available_nodes |= local_devices[j]->available_nodes;
3842                 node_type = log2(local_devices[j]->available_nodes);
3843                 memcpy(local_devices[i]->nodes[node_type],
3844                        local_devices[j]->nodes[node_type], drmGetMaxNodeName());
3845                 drmFreeDevice(&local_devices[j]);
3846             }
3847         }
3848     }
3849 }
3850
3851 /* Check that the given flags are valid returning 0 on success */
3852 static int
3853 drm_device_validate_flags(uint32_t flags)
3854 {
3855         return (flags & ~DRM_DEVICE_GET_PCI_REVISION);
3856 }
3857
3858 static bool
3859 drm_device_has_rdev(drmDevicePtr device, dev_t find_rdev)
3860 {
3861     struct stat sbuf;
3862
3863     for (int i = 0; i < DRM_NODE_MAX; i++) {
3864         if (device->available_nodes & 1 << i) {
3865             if (stat(device->nodes[i], &sbuf) == 0 &&
3866                 sbuf.st_rdev == find_rdev)
3867                 return true;
3868         }
3869     }
3870     return false;
3871 }
3872
3873 /*
3874  * The kernel drm core has a number of places that assume maximum of
3875  * 3x64 devices nodes. That's 64 for each of primary, control and
3876  * render nodes. Rounded it up to 256 for simplicity.
3877  */
3878 #define MAX_DRM_NODES 256
3879
3880 /**
3881  * Get information about the opened drm device
3882  *
3883  * \param fd file descriptor of the drm device
3884  * \param flags feature/behaviour bitmask
3885  * \param device the address of a drmDevicePtr where the information
3886  *               will be allocated in stored
3887  *
3888  * \return zero on success, negative error code otherwise.
3889  *
3890  * \note Unlike drmGetDevice it does not retrieve the pci device revision field
3891  * unless the DRM_DEVICE_GET_PCI_REVISION \p flag is set.
3892  */
3893 drm_public int drmGetDevice2(int fd, uint32_t flags, drmDevicePtr *device)
3894 {
3895 #ifdef __OpenBSD__
3896     /*
3897      * DRI device nodes on OpenBSD are not in their own directory, they reside
3898      * in /dev along with a large number of statically generated /dev nodes.
3899      * Avoid stat'ing all of /dev needlessly by implementing this custom path.
3900      */
3901     drmDevicePtr     d;
3902     struct stat      sbuf;
3903     char             node[PATH_MAX + 1];
3904     const char      *dev_name;
3905     int              node_type, subsystem_type;
3906     int              maj, min, n, ret;
3907
3908     if (fd == -1 || device == NULL)
3909         return -EINVAL;
3910
3911     if (fstat(fd, &sbuf))
3912         return -errno;
3913
3914     maj = major(sbuf.st_rdev);
3915     min = minor(sbuf.st_rdev);
3916
3917     if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode))
3918         return -EINVAL;
3919
3920     node_type = drmGetMinorType(maj, min);
3921     if (node_type == -1)
3922         return -ENODEV;
3923
3924     dev_name = drmGetDeviceName(node_type);
3925     if (!dev_name)
3926         return -EINVAL;
3927
3928     n = snprintf(node, PATH_MAX, dev_name, DRM_DIR_NAME, min);
3929     if (n == -1 || n >= PATH_MAX)
3930       return -errno;
3931     if (stat(node, &sbuf))
3932         return -EINVAL;
3933
3934     subsystem_type = drmParseSubsystemType(maj, min);
3935     if (subsystem_type != DRM_BUS_PCI)
3936         return -ENODEV;
3937
3938     ret = drmProcessPciDevice(&d, node, node_type, maj, min, true, flags);
3939     if (ret)
3940         return ret;
3941
3942     *device = d;
3943
3944     return 0;
3945 #else
3946     drmDevicePtr local_devices[MAX_DRM_NODES];
3947     drmDevicePtr d;
3948     DIR *sysdir;
3949     struct dirent *dent;
3950     struct stat sbuf;
3951     int subsystem_type;
3952     int maj, min;
3953     int ret, i, node_count;
3954     dev_t find_rdev;
3955
3956     if (drm_device_validate_flags(flags))
3957         return -EINVAL;
3958
3959     if (fd == -1 || device == NULL)
3960         return -EINVAL;
3961
3962     if (fstat(fd, &sbuf))
3963         return -errno;
3964
3965     find_rdev = sbuf.st_rdev;
3966     maj = major(sbuf.st_rdev);
3967     min = minor(sbuf.st_rdev);
3968
3969     if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode))
3970         return -EINVAL;
3971
3972     subsystem_type = drmParseSubsystemType(maj, min);
3973     if (subsystem_type < 0)
3974         return subsystem_type;
3975
3976     sysdir = opendir(DRM_DIR_NAME);
3977     if (!sysdir)
3978         return -errno;
3979
3980     i = 0;
3981     while ((dent = readdir(sysdir))) {
3982         ret = process_device(&d, dent->d_name, subsystem_type, true, flags);
3983         if (ret)
3984             continue;
3985
3986         if (i >= MAX_DRM_NODES) {
3987             fprintf(stderr, "More than %d drm nodes detected. "
3988                     "Please report a bug - that should not happen.\n"
3989                     "Skipping extra nodes\n", MAX_DRM_NODES);
3990             break;
3991         }
3992         local_devices[i] = d;
3993         i++;
3994     }
3995     node_count = i;
3996
3997     drmFoldDuplicatedDevices(local_devices, node_count);
3998
3999     *device = NULL;
4000
4001     for (i = 0; i < node_count; i++) {
4002         if (!local_devices[i])
4003             continue;
4004
4005         if (drm_device_has_rdev(local_devices[i], find_rdev))
4006             *device = local_devices[i];
4007         else
4008             drmFreeDevice(&local_devices[i]);
4009     }
4010
4011     closedir(sysdir);
4012     if (*device == NULL)
4013         return -ENODEV;
4014     return 0;
4015 #endif
4016 }
4017
4018 /**
4019  * Get information about the opened drm device
4020  *
4021  * \param fd file descriptor of the drm device
4022  * \param device the address of a drmDevicePtr where the information
4023  *               will be allocated in stored
4024  *
4025  * \return zero on success, negative error code otherwise.
4026  */
4027 drm_public int drmGetDevice(int fd, drmDevicePtr *device)
4028 {
4029     return drmGetDevice2(fd, DRM_DEVICE_GET_PCI_REVISION, device);
4030 }
4031
4032 /**
4033  * Get drm devices on the system
4034  *
4035  * \param flags feature/behaviour bitmask
4036  * \param devices the array of devices with drmDevicePtr elements
4037  *                can be NULL to get the device number first
4038  * \param max_devices the maximum number of devices for the array
4039  *
4040  * \return on error - negative error code,
4041  *         if devices is NULL - total number of devices available on the system,
4042  *         alternatively the number of devices stored in devices[], which is
4043  *         capped by the max_devices.
4044  *
4045  * \note Unlike drmGetDevices it does not retrieve the pci device revision field
4046  * unless the DRM_DEVICE_GET_PCI_REVISION \p flag is set.
4047  */
4048 drm_public int drmGetDevices2(uint32_t flags, drmDevicePtr devices[],
4049                               int max_devices)
4050 {
4051     drmDevicePtr local_devices[MAX_DRM_NODES];
4052     drmDevicePtr device;
4053     DIR *sysdir;
4054     struct dirent *dent;
4055     int ret, i, node_count, device_count;
4056
4057     if (drm_device_validate_flags(flags))
4058         return -EINVAL;
4059
4060     sysdir = opendir(DRM_DIR_NAME);
4061     if (!sysdir)
4062         return -errno;
4063
4064     i = 0;
4065     while ((dent = readdir(sysdir))) {
4066         ret = process_device(&device, dent->d_name, -1, devices != NULL, flags);
4067         if (ret)
4068             continue;
4069
4070         if (i >= MAX_DRM_NODES) {
4071             fprintf(stderr, "More than %d drm nodes detected. "
4072                     "Please report a bug - that should not happen.\n"
4073                     "Skipping extra nodes\n", MAX_DRM_NODES);
4074             break;
4075         }
4076         local_devices[i] = device;
4077         i++;
4078     }
4079     node_count = i;
4080
4081     drmFoldDuplicatedDevices(local_devices, node_count);
4082
4083     device_count = 0;
4084     for (i = 0; i < node_count; i++) {
4085         if (!local_devices[i])
4086             continue;
4087
4088         if ((devices != NULL) && (device_count < max_devices))
4089             devices[device_count] = local_devices[i];
4090         else
4091             drmFreeDevice(&local_devices[i]);
4092
4093         device_count++;
4094     }
4095
4096     closedir(sysdir);
4097     return device_count;
4098 }
4099
4100 /**
4101  * Get drm devices on the system
4102  *
4103  * \param devices the array of devices with drmDevicePtr elements
4104  *                can be NULL to get the device number first
4105  * \param max_devices the maximum number of devices for the array
4106  *
4107  * \return on error - negative error code,
4108  *         if devices is NULL - total number of devices available on the system,
4109  *         alternatively the number of devices stored in devices[], which is
4110  *         capped by the max_devices.
4111  */
4112 drm_public int drmGetDevices(drmDevicePtr devices[], int max_devices)
4113 {
4114     return drmGetDevices2(DRM_DEVICE_GET_PCI_REVISION, devices, max_devices);
4115 }
4116
4117 drm_public char *drmGetDeviceNameFromFd2(int fd)
4118 {
4119 #ifdef __linux__
4120     struct stat sbuf;
4121     char path[PATH_MAX + 1], *value;
4122     unsigned int maj, min;
4123
4124     if (fstat(fd, &sbuf))
4125         return NULL;
4126
4127     maj = major(sbuf.st_rdev);
4128     min = minor(sbuf.st_rdev);
4129
4130     if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode))
4131         return NULL;
4132
4133     snprintf(path, sizeof(path), "/sys/dev/char/%d:%d", maj, min);
4134
4135     value = sysfs_uevent_get(path, "DEVNAME");
4136     if (!value)
4137         return NULL;
4138
4139     snprintf(path, sizeof(path), "/dev/%s", value);
4140     free(value);
4141
4142     return strdup(path);
4143 #else
4144     struct stat      sbuf;
4145     char             node[PATH_MAX + 1];
4146     const char      *dev_name;
4147     int              node_type;
4148     int              maj, min, n;
4149
4150     if (fstat(fd, &sbuf))
4151         return NULL;
4152
4153     maj = major(sbuf.st_rdev);
4154     min = minor(sbuf.st_rdev);
4155
4156     if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode))
4157         return NULL;
4158
4159     node_type = drmGetMinorType(maj, min);
4160     if (node_type == -1)
4161         return NULL;
4162
4163     dev_name = drmGetDeviceName(node_type);
4164     if (!dev_name)
4165         return NULL;
4166
4167     n = snprintf(node, PATH_MAX, dev_name, DRM_DIR_NAME, min);
4168     if (n == -1 || n >= PATH_MAX)
4169       return NULL;
4170
4171     return strdup(node);
4172 #endif
4173 }
4174
4175 drm_public int drmSyncobjCreate(int fd, uint32_t flags, uint32_t *handle)
4176 {
4177     struct drm_syncobj_create args;
4178     int ret;
4179
4180     memclear(args);
4181     args.flags = flags;
4182     args.handle = 0;
4183     ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_CREATE, &args);
4184     if (ret)
4185         return ret;
4186     *handle = args.handle;
4187     return 0;
4188 }
4189
4190 drm_public int drmSyncobjDestroy(int fd, uint32_t handle)
4191 {
4192     struct drm_syncobj_destroy args;
4193
4194     memclear(args);
4195     args.handle = handle;
4196     return drmIoctl(fd, DRM_IOCTL_SYNCOBJ_DESTROY, &args);
4197 }
4198
4199 drm_public int drmSyncobjHandleToFD(int fd, uint32_t handle, int *obj_fd)
4200 {
4201     struct drm_syncobj_handle args;
4202     int ret;
4203
4204     memclear(args);
4205     args.fd = -1;
4206     args.handle = handle;
4207     ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD, &args);
4208     if (ret)
4209         return ret;
4210     *obj_fd = args.fd;
4211     return 0;
4212 }
4213
4214 drm_public int drmSyncobjFDToHandle(int fd, int obj_fd, uint32_t *handle)
4215 {
4216     struct drm_syncobj_handle args;
4217     int ret;
4218
4219     memclear(args);
4220     args.fd = obj_fd;
4221     args.handle = 0;
4222     ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, &args);
4223     if (ret)
4224         return ret;
4225     *handle = args.handle;
4226     return 0;
4227 }
4228
4229 drm_public int drmSyncobjImportSyncFile(int fd, uint32_t handle,
4230                                         int sync_file_fd)
4231 {
4232     struct drm_syncobj_handle args;
4233
4234     memclear(args);
4235     args.fd = sync_file_fd;
4236     args.handle = handle;
4237     args.flags = DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE;
4238     return drmIoctl(fd, DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, &args);
4239 }
4240
4241 drm_public int drmSyncobjExportSyncFile(int fd, uint32_t handle,
4242                                         int *sync_file_fd)
4243 {
4244     struct drm_syncobj_handle args;
4245     int ret;
4246
4247     memclear(args);
4248     args.fd = -1;
4249     args.handle = handle;
4250     args.flags = DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE;
4251     ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD, &args);
4252     if (ret)
4253         return ret;
4254     *sync_file_fd = args.fd;
4255     return 0;
4256 }
4257
4258 drm_public int drmSyncobjWait(int fd, uint32_t *handles, unsigned num_handles,
4259                               int64_t timeout_nsec, unsigned flags,
4260                               uint32_t *first_signaled)
4261 {
4262     struct drm_syncobj_wait args;
4263     int ret;
4264
4265     memclear(args);
4266     args.handles = (uintptr_t)handles;
4267     args.timeout_nsec = timeout_nsec;
4268     args.count_handles = num_handles;
4269     args.flags = flags;
4270
4271     ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_WAIT, &args);
4272     if (ret < 0)
4273         return -errno;
4274
4275     if (first_signaled)
4276         *first_signaled = args.first_signaled;
4277     return ret;
4278 }
4279
4280 drm_public int drmSyncobjReset(int fd, const uint32_t *handles,
4281                                uint32_t handle_count)
4282 {
4283     struct drm_syncobj_array args;
4284     int ret;
4285
4286     memclear(args);
4287     args.handles = (uintptr_t)handles;
4288     args.count_handles = handle_count;
4289
4290     ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_RESET, &args);
4291     return ret;
4292 }
4293
4294 drm_public int drmSyncobjSignal(int fd, const uint32_t *handles,
4295                                 uint32_t handle_count)
4296 {
4297     struct drm_syncobj_array args;
4298     int ret;
4299
4300     memclear(args);
4301     args.handles = (uintptr_t)handles;
4302     args.count_handles = handle_count;
4303
4304     ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_SIGNAL, &args);
4305     return ret;
4306 }
4307
4308 drm_public int drmSyncobjTimelineSignal(int fd, const uint32_t *handles,
4309                                         uint64_t *points, uint32_t handle_count)
4310 {
4311     struct drm_syncobj_timeline_array args;
4312     int ret;
4313
4314     memclear(args);
4315     args.handles = (uintptr_t)handles;
4316     args.points = (uintptr_t)points;
4317     args.count_handles = handle_count;
4318
4319     ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL, &args);
4320     return ret;
4321 }
4322
4323 drm_public int drmSyncobjTimelineWait(int fd, uint32_t *handles, uint64_t *points,
4324                                       unsigned num_handles,
4325                                       int64_t timeout_nsec, unsigned flags,
4326                                       uint32_t *first_signaled)
4327 {
4328     struct drm_syncobj_timeline_wait args;
4329     int ret;
4330
4331     memclear(args);
4332     args.handles = (uintptr_t)handles;
4333     args.points = (uintptr_t)points;
4334     args.timeout_nsec = timeout_nsec;
4335     args.count_handles = num_handles;
4336     args.flags = flags;
4337
4338     ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT, &args);
4339     if (ret < 0)
4340         return -errno;
4341
4342     if (first_signaled)
4343         *first_signaled = args.first_signaled;
4344     return ret;
4345 }
4346
4347
4348 drm_public int drmSyncobjQuery(int fd, uint32_t *handles, uint64_t *points,
4349                                uint32_t handle_count)
4350 {
4351     struct drm_syncobj_timeline_array args;
4352     int ret;
4353
4354     memclear(args);
4355     args.handles = (uintptr_t)handles;
4356     args.points = (uintptr_t)points;
4357     args.count_handles = handle_count;
4358
4359     ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_QUERY, &args);
4360     if (ret)
4361         return ret;
4362     return 0;
4363 }
4364
4365 drm_public int drmSyncobjQuery2(int fd, uint32_t *handles, uint64_t *points,
4366                                 uint32_t handle_count, uint32_t flags)
4367 {
4368     struct drm_syncobj_timeline_array args;
4369
4370     memclear(args);
4371     args.handles = (uintptr_t)handles;
4372     args.points = (uintptr_t)points;
4373     args.count_handles = handle_count;
4374     args.flags = flags;
4375
4376     return drmIoctl(fd, DRM_IOCTL_SYNCOBJ_QUERY, &args);
4377 }
4378
4379
4380 drm_public int drmSyncobjTransfer(int fd,
4381                                   uint32_t dst_handle, uint64_t dst_point,
4382                                   uint32_t src_handle, uint64_t src_point,
4383                                   uint32_t flags)
4384 {
4385     struct drm_syncobj_transfer args;
4386     int ret;
4387
4388     memclear(args);
4389     args.src_handle = src_handle;
4390     args.dst_handle = dst_handle;
4391     args.src_point = src_point;
4392     args.dst_point = dst_point;
4393     args.flags = flags;
4394
4395     ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_TRANSFER, &args);
4396
4397     return ret;
4398 }