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