1d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely * \file xf86drm.c
3d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * User-level interface to DRM device
4b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss *
5d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \author Rickard E. (Rik) Faith <faith@valinux.com>
6d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \author Kevin E. Martin <martin@valinux.com>
7d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
8d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
9d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/*
10569da5a42ebf10c86d6c6ba81866a888e1c708dcBrian Paul * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
11569da5a42ebf10c86d6c6ba81866a888e1c708dcBrian Paul * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
12b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss * All Rights Reserved.
13b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss *
14b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss * Permission is hereby granted, free of charge, to any person obtaining a
15b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss * copy of this software and associated documentation files (the "Software"),
16b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss * to deal in the Software without restriction, including without limitation
17b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss * the rights to use, copy, modify, merge, publish, distribute, sublicense,
18b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss * and/or sell copies of the Software, and to permit persons to whom the
19b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss * Software is furnished to do so, subject to the following conditions:
20360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes *
21b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss * The above copyright notice and this permission notice (including the next
22b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss * paragraph) shall be included in all copies or substantial portions of the
23b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss * Software.
24360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes *
25b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
28b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
29b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
30b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
31b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss * DEALINGS IN THE SOFTWARE.
32b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss */
33b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
3479038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie#ifdef HAVE_CONFIG_H
3579038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie# include <config.h>
36b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss#endif
3779038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie#include <stdio.h>
3879038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie#include <stdlib.h>
39fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov#include <stdbool.h>
4079038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie#include <unistd.h>
4179038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie#include <string.h>
42015efd1bfa72ab8b80cc45f11eb22d7f1a1085f7Ian Romanick#include <strings.h>
4379038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie#include <ctype.h>
440ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov#include <dirent.h>
450ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov#include <stddef.h>
4679038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie#include <fcntl.h>
4779038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie#include <errno.h>
484031dc17bb728850c9b079c8d5f9cc0a379b9d46Felix Janda#include <limits.h>
4979038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie#include <signal.h>
50f4f76a6894b40abd77f0ffbf52972127608b9bcaJesse Barnes#include <time.h>
5179038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie#include <sys/types.h>
5279038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie#include <sys/stat.h>
5379038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie#define stat_t struct stat
5479038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie#include <sys/ioctl.h>
5579038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie#include <sys/time.h>
5679038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie#include <stdarg.h>
578c8d5dd76fb80637031e824a48ceaa0f9f65d2ddMike Frysinger#ifdef MAJOR_IN_MKDEV
588c8d5dd76fb80637031e824a48ceaa0f9f65d2ddMike Frysinger#include <sys/mkdev.h>
598c8d5dd76fb80637031e824a48ceaa0f9f65d2ddMike Frysinger#endif
608c8d5dd76fb80637031e824a48ceaa0f9f65d2ddMike Frysinger#ifdef MAJOR_IN_SYSMACROS
618c8d5dd76fb80637031e824a48ceaa0f9f65d2ddMike Frysinger#include <sys/sysmacros.h>
620e1135de5cbb783846a4f7e9ef8a5f953f7c77aeAlan Coopersmith#endif
63b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov#include <math.h>
64b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
65b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss/* Not all systems have MAP_FAILED defined */
66b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss#ifndef MAP_FAILED
67b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss#define MAP_FAILED ((void *)-1)
68b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss#endif
69b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
70b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss#include "xf86drm.h"
7142465feb9759ef5a6d79d7e628510cd0a081f913Emil Velikov#include "libdrm_macros.h"
72b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
735f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov#include "util_math.h"
745f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov
75fc083322b0c8a58b51976adf23a582bce8bb75f1Jonathan Gray#ifdef __OpenBSD__
7650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely#define DRM_PRIMARY_MINOR_NAME  "drm"
7750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely#define DRM_CONTROL_MINOR_NAME  "drmC"
7850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely#define DRM_RENDER_MINOR_NAME   "drmR"
79fc083322b0c8a58b51976adf23a582bce8bb75f1Jonathan Gray#else
8050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely#define DRM_PRIMARY_MINOR_NAME  "card"
8150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely#define DRM_CONTROL_MINOR_NAME  "controlD"
8250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely#define DRM_RENDER_MINOR_NAME   "renderD"
83fc083322b0c8a58b51976adf23a582bce8bb75f1Jonathan Gray#endif
84fc083322b0c8a58b51976adf23a582bce8bb75f1Jonathan Gray
8527c3785d3f12743a9e160238a4d00353060ec2f2Hasso Tepper#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
86cfa778af9c70faea8c13e5cb7f80029eee0d074eEric Anholt#define DRM_MAJOR 145
87cfa778af9c70faea8c13e5cb7f80029eee0d074eEric Anholt#endif
88cfa778af9c70faea8c13e5cb7f80029eee0d074eEric Anholt
89cfa778af9c70faea8c13e5cb7f80029eee0d074eEric Anholt#ifdef __NetBSD__
90cfa778af9c70faea8c13e5cb7f80029eee0d074eEric Anholt#define DRM_MAJOR 34
9188dbee54ed400a3fd5594fab506518c171167805Rik Faith#endif
9288dbee54ed400a3fd5594fab506518c171167805Rik Faith
9366c3afb75fa993f2f8b00c2dd9c2ec37a3a9dfb6Jonathan Gray#ifdef __OpenBSD__
9466c3afb75fa993f2f8b00c2dd9c2ec37a3a9dfb6Jonathan Gray#ifdef __i386__
9566c3afb75fa993f2f8b00c2dd9c2ec37a3a9dfb6Jonathan Gray#define DRM_MAJOR 88
9666c3afb75fa993f2f8b00c2dd9c2ec37a3a9dfb6Jonathan Gray#else
9766c3afb75fa993f2f8b00c2dd9c2ec37a3a9dfb6Jonathan Gray#define DRM_MAJOR 87
9866c3afb75fa993f2f8b00c2dd9c2ec37a3a9dfb6Jonathan Gray#endif
9966c3afb75fa993f2f8b00c2dd9c2ec37a3a9dfb6Jonathan Gray#endif /* __OpenBSD__ */
100b0a928557c91fec527f41ae8b2441174889bf32cAlan Hourihane
101cfa778af9c70faea8c13e5cb7f80029eee0d074eEric Anholt#ifndef DRM_MAJOR
10250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely#define DRM_MAJOR 226 /* Linux */
10388dbee54ed400a3fd5594fab506518c171167805Rik Faith#endif
10488dbee54ed400a3fd5594fab506518c171167805Rik Faith
105c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray#ifdef __OpenBSD__
106c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Graystruct drm_pciinfo {
107c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray	uint16_t	domain;
108c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray	uint8_t		bus;
109c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray	uint8_t		dev;
110c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray	uint8_t		func;
111c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray	uint16_t	vendor_id;
112c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray	uint16_t	device_id;
113c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray	uint16_t	subvendor_id;
114c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray	uint16_t	subdevice_id;
115c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray	uint8_t		revision_id;
116c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray};
117c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray
118c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray#define DRM_IOCTL_GET_PCIINFO	DRM_IOR(0x15, struct drm_pciinfo)
119c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray#endif
120c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray
12156bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes#define DRM_MSG_VERBOSITY 3
12256bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes
123fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter#define memclear(s) memset(&s, 0, sizeof(s))
124fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter
12579038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airliestatic drmServerInfoPtr drm_server_info;
12679038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie
12779038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlievoid drmSetServerInfo(drmServerInfoPtr info)
12879038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie{
129ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    drm_server_info = info;
13079038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie}
13179038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie
132d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
133d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Output a message to stderr.
134d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
135d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param format printf() like format string.
136d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
137d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
138d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around vfprintf().
139d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
14079038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie
14144b08c0ddf7ced99a5914421f18b269a1dcaafaeThierry Redingstatic int DRM_PRINTFLIKE(1, 0)
14244b08c0ddf7ced99a5914421f18b269a1dcaafaeThierry RedingdrmDebugPrint(const char *format, va_list ap)
14379038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie{
144ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    return vfprintf(stderr, format, ap);
14579038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie}
14679038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie
147c4857429c716f35e1fa054d1990cae28055d96d7Eric Anholtvoid
14856bd9c207770d41a497f3e8237a1099dd9d4cd91David DawesdrmMsg(const char *format, ...)
14956bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes{
15050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    va_list ap;
15156bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes    const char *env;
152eb7c2d5e63e0e9d133b16880e36c14676276d412Rob Clark    if (((env = getenv("LIBGL_DEBUG")) && strstr(env, "verbose")) ||
153eb7c2d5e63e0e9d133b16880e36c14676276d412Rob Clark        (drm_server_info && drm_server_info->debug_print))
15456bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes    {
15550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        va_start(ap, format);
15650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        if (drm_server_info) {
15750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            drm_server_info->debug_print(format,ap);
15850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        } else {
15950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            drmDebugPrint(format, ap);
16050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        }
16150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        va_end(ap);
16256bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes    }
16356bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes}
16456bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes
165b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Straussstatic void *drmHashTable = NULL; /* Context switch callbacks */
166b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
16779038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlievoid *drmGetHashTable(void)
16879038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie{
169ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    return drmHashTable;
17079038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie}
171b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
172b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Straussvoid *drmMalloc(int size)
173b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
174d0e592d4e9b59d9cc185f1d63b3c1dd818e95098Emil Velikov    return calloc(1, size);
175b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
176b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
177b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Straussvoid drmFree(void *pt)
178b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
179d0e592d4e9b59d9cc185f1d63b3c1dd818e95098Emil Velikov    free(pt);
180b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
181b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1828b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard/**
1838b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard * Call ioctl, restarting if it is interupted
1848b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard */
185731cd5526e5c732d51307b26e784f454a724a699Jesse Barnesint
18641b83a99583486ad4f8760a6537d34783769bfc3Coleman KanedrmIoctl(int fd, unsigned long request, void *arg)
1878b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard{
18850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    int ret;
1898b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard
1908b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    do {
19150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        ret = ioctl(fd, request, arg);
1928b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
1938b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    return ret;
1948b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard}
195b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
196b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Straussstatic unsigned long drmGetKeyFromFd(int fd)
197b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
198fcc21069b7019a4a93e1ceacc175ccd682353861David Dawes    stat_t     st;
199b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
200b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    st.st_rdev = 0;
201b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    fstat(fd, &st);
202b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return st.st_rdev;
203b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
204b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
20579038751ffe47ed1ce82766e027d98fd2f0e2c6aDave AirliedrmHashEntry *drmGetEntry(int fd)
206b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
207b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    unsigned long key = drmGetKeyFromFd(fd);
208b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    void          *value;
209b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drmHashEntry  *entry;
210b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
211ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    if (!drmHashTable)
21250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        drmHashTable = drmHashCreate();
213b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
214b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    if (drmHashLookup(drmHashTable, key, &value)) {
21550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        entry           = drmMalloc(sizeof(*entry));
21650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        entry->fd       = fd;
21750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        entry->f        = NULL;
21850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        entry->tagTable = drmHashCreate();
21950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        drmHashInsert(drmHashTable, key, entry);
220b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    } else {
22150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        entry = value;
222b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    }
223b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return entry;
224b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
225b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
226d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
22706cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt * Compare two busid strings
22806cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt *
22906cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt * \param first
23006cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt * \param second
23106cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt *
23206cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt * \return 1 if matched.
23306cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt *
23406cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt * \internal
23506cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt * This function compares two bus ID strings.  It understands the older
23606cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt * PCI:b:d:f format and the newer pci:oooo:bb:dd.f format.  In the format, o is
23706cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt * domain, b is bus, d is device, f is function.
23806cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt */
239b04515c5d6c95f573457a94267b855cceb639105Benjamin Herrenschmidtstatic int drmMatchBusID(const char *id1, const char *id2, int pci_domain_ok)
24006cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt{
24106cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    /* First, check if the IDs are exactly the same */
24206cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    if (strcasecmp(id1, id2) == 0)
24350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return 1;
24406cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt
24506cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    /* Try to match old/new-style PCI bus IDs. */
24606cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    if (strncasecmp(id1, "pci", 3) == 0) {
24750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        unsigned int o1, b1, d1, f1;
24850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        unsigned int o2, b2, d2, f2;
24950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        int ret;
25050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely
25150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        ret = sscanf(id1, "pci:%04x:%02x:%02x.%u", &o1, &b1, &d1, &f1);
25250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        if (ret != 4) {
25350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            o1 = 0;
25450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            ret = sscanf(id1, "PCI:%u:%u:%u", &b1, &d1, &f1);
25550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            if (ret != 3)
25650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                return 0;
25750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        }
25850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely
25950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        ret = sscanf(id2, "pci:%04x:%02x:%02x.%u", &o2, &b2, &d2, &f2);
26050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        if (ret != 4) {
26150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            o2 = 0;
26250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            ret = sscanf(id2, "PCI:%u:%u:%u", &b2, &d2, &f2);
26350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            if (ret != 3)
26450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                return 0;
26550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        }
26650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely
26750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        /* If domains aren't properly supported by the kernel interface,
26850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely         * just ignore them, which sucks less than picking a totally random
26950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely         * card with "open by name"
27050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely         */
27150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        if (!pci_domain_ok)
27250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            o1 = o2 = 0;
27350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely
27450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        if ((o1 != o2) || (b1 != b2) || (d1 != d2) || (f1 != f2))
27550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            return 0;
27650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        else
27750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            return 1;
27806cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    }
27906cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    return 0;
28006cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt}
28106cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt
28206cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt/**
283c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen * Handles error checking for chown call.
284c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen *
285c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen * \param path to file.
286c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen * \param id of the new owner.
287c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen * \param id of the new group.
288c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen *
289c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen * \return zero if success or -1 if failure.
290c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen *
291c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen * \internal
292c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen * Checks for failure. If failure was caused by signal call chown again.
293c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen * If any other failure happened then it will output error mesage using
294c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen * drmMsg() call.
295c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen */
2966fc0e4ba1ea153ff949cba0002fc5ed544de0de0Jan Vesely#if !defined(UDEV)
297c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminenstatic int chown_check_return(const char *path, uid_t owner, gid_t group)
298c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen{
29950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        int rv;
300c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen
30150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        do {
30250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            rv = chown(path, owner, group);
30350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        } while (rv != 0 && errno == EINTR);
304c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen
30550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        if (rv == 0)
30650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            return 0;
307c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen
30850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        drmMsg("Failed to change owner or group for file %s! %d: %s\n",
30950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely               path, errno, strerror(errno));
31050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -1;
311c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen}
3126fc0e4ba1ea153ff949cba0002fc5ed544de0de0Jan Vesely#endif
313c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen
314c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen/**
315d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Open the DRM device, creating it if necessary.
316d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
317d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param dev major and minor numbers of the device.
318d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param minor minor number of the device.
31950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
320d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return a file descriptor on success, or a negative value on error.
321d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
322d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
323d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Assembles the device name from \p minor and opens it, creating the device
324d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * special file node with the major and minor numbers specified by \p dev and
325d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * parent directory if necessary and was called by root.
326d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
327de8532dd8359dfdaba839ff61fc9e2f05eaf57d3Jan Veselystatic int drmOpenDevice(dev_t dev, int minor, int type)
328b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
3299c775d0b2f303389c24aea5e8abc1473f0cf93e8David Dawes    stat_t          st;
3300c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns    const char      *dev_name;
33188dbee54ed400a3fd5594fab506518c171167805Rik Faith    char            buf[64];
33288dbee54ed400a3fd5594fab506518c171167805Rik Faith    int             fd;
33379038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie    mode_t          devmode = DRM_DEV_MODE, serv_mode;
3340706c14e7cc5f1d996bb1c3c526f877c4f8fc215Jan Vesely    gid_t           serv_group;
3350706c14e7cc5f1d996bb1c3c526f877c4f8fc215Jan Vesely#if !defined(UDEV)
33688dbee54ed400a3fd5594fab506518c171167805Rik Faith    int             isroot  = !geteuid();
33788dbee54ed400a3fd5594fab506518c171167805Rik Faith    uid_t           user    = DRM_DEV_UID;
3380706c14e7cc5f1d996bb1c3c526f877c4f8fc215Jan Vesely    gid_t           group   = DRM_DEV_GID;
3390706c14e7cc5f1d996bb1c3c526f877c4f8fc215Jan Vesely#endif
3400706c14e7cc5f1d996bb1c3c526f877c4f8fc215Jan Vesely
3410c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns    switch (type) {
3420c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns    case DRM_NODE_PRIMARY:
34350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        dev_name = DRM_DEV_NAME;
34450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        break;
3450c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns    case DRM_NODE_CONTROL:
34650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        dev_name = DRM_CONTROL_DEV_NAME;
34750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        break;
3480c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns    case DRM_NODE_RENDER:
34950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        dev_name = DRM_RENDER_DEV_NAME;
35050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        break;
3510c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns    default:
35250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -EINVAL;
3530c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns    };
3540c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns
3550c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns    sprintf(buf, dev_name, DRM_DIR_NAME, minor);
35606cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    drmMsg("drmOpenDevice: node name is %s\n", buf);
35756bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes
358eb7c2d5e63e0e9d133b16880e36c14676276d412Rob Clark    if (drm_server_info && drm_server_info->get_perms) {
35950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        drm_server_info->get_perms(&serv_group, &serv_mode);
36050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        devmode  = serv_mode ? serv_mode : DRM_DEV_MODE;
36150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        devmode &= ~(S_IXUSR|S_IXGRP|S_IXOTH);
36279038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie    }
363569da5a42ebf10c86d6c6ba81866a888e1c708dcBrian Paul
3649101a0205c897fea28e6a3d875111a83ad7f7732Dave Airlie#if !defined(UDEV)
36588dbee54ed400a3fd5594fab506518c171167805Rik Faith    if (stat(DRM_DIR_NAME, &st)) {
36650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        if (!isroot)
36750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            return DRM_ERR_NOT_ROOT;
36850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        mkdir(DRM_DIR_NAME, DRM_DEV_DIRMODE);
36950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        chown_check_return(DRM_DIR_NAME, 0, 0); /* root:root */
37050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        chmod(DRM_DIR_NAME, DRM_DEV_DIRMODE);
371569da5a42ebf10c86d6c6ba81866a888e1c708dcBrian Paul    }
372b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
37306cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    /* Check if the device node exists and create it if necessary. */
374d2f2b42f1d206fd248ada48ce2c498e31351ab33Eric Anholt    if (stat(buf, &st)) {
37550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        if (!isroot)
37650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            return DRM_ERR_NOT_ROOT;
37750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        remove(buf);
37850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        mknod(buf, S_IFCHR | devmode, dev);
379b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    }
38079038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie
381eb7c2d5e63e0e9d133b16880e36c14676276d412Rob Clark    if (drm_server_info && drm_server_info->get_perms) {
38250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        group = ((int)serv_group >= 0) ? serv_group : DRM_DEV_GID;
38350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        chown_check_return(buf, user, group);
38450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        chmod(buf, devmode);
38579038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie    }
3869101a0205c897fea28e6a3d875111a83ad7f7732Dave Airlie#else
3879101a0205c897fea28e6a3d875111a83ad7f7732Dave Airlie    /* if we modprobed then wait for udev */
3889101a0205c897fea28e6a3d875111a83ad7f7732Dave Airlie    {
38950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        int udev_count = 0;
3909101a0205c897fea28e6a3d875111a83ad7f7732Dave Airliewait_for_udev:
3919101a0205c897fea28e6a3d875111a83ad7f7732Dave Airlie        if (stat(DRM_DIR_NAME, &st)) {
39250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            usleep(20);
39350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            udev_count++;
39450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely
39550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            if (udev_count == 50)
39650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                return -1;
39750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            goto wait_for_udev;
39850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        }
39950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely
40050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        if (stat(buf, &st)) {
40150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            usleep(20);
40250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            udev_count++;
40350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely
40450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            if (udev_count == 50)
40550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                return -1;
40650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            goto wait_for_udev;
40750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        }
4089101a0205c897fea28e6a3d875111a83ad7f7732Dave Airlie    }
4099101a0205c897fea28e6a3d875111a83ad7f7732Dave Airlie#endif
41088dbee54ed400a3fd5594fab506518c171167805Rik Faith
41156bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes    fd = open(buf, O_RDWR, 0);
41256bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes    drmMsg("drmOpenDevice: open result is %d, (%s)\n",
41350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely           fd, fd < 0 ? strerror(errno) : "OK");
414ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    if (fd >= 0)
41550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return fd;
416d2f2b42f1d206fd248ada48ce2c498e31351ab33Eric Anholt
41739e5e982242cd2b611a9dfc1e9b63f857d52da61Dave Airlie#if !defined(UDEV)
41806cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    /* Check if the device node is not what we expect it to be, and recreate it
41906cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt     * and try again if so.
42006cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt     */
421d2f2b42f1d206fd248ada48ce2c498e31351ab33Eric Anholt    if (st.st_rdev != dev) {
42250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        if (!isroot)
42350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            return DRM_ERR_NOT_ROOT;
42450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        remove(buf);
42550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        mknod(buf, S_IFCHR | devmode, dev);
42650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        if (drm_server_info && drm_server_info->get_perms) {
42750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            chown_check_return(buf, user, group);
42850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            chmod(buf, devmode);
42950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        }
430d2f2b42f1d206fd248ada48ce2c498e31351ab33Eric Anholt    }
431d2f2b42f1d206fd248ada48ce2c498e31351ab33Eric Anholt    fd = open(buf, O_RDWR, 0);
432d2f2b42f1d206fd248ada48ce2c498e31351ab33Eric Anholt    drmMsg("drmOpenDevice: open result is %d, (%s)\n",
43350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely           fd, fd < 0 ? strerror(errno) : "OK");
434ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    if (fd >= 0)
43550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return fd;
436d2f2b42f1d206fd248ada48ce2c498e31351ab33Eric Anholt
43756bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes    drmMsg("drmOpenDevice: Open failed\n");
43888dbee54ed400a3fd5594fab506518c171167805Rik Faith    remove(buf);
43939e5e982242cd2b611a9dfc1e9b63f857d52da61Dave Airlie#endif
44088dbee54ed400a3fd5594fab506518c171167805Rik Faith    return -errno;
441b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
442b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
443d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
444d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
445d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Open the DRM device
446d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
447d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param minor device minor number.
448d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param create allow to create the device if set.
449d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
450d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return a file descriptor on success, or a negative value on error.
45150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
452d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
453d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Calls drmOpenDevice() if \p create is set, otherwise assembles the device
454d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * name from \p minor and opens it.
455d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
456731cd5526e5c732d51307b26e784f454a724a699Jesse Barnesstatic int drmOpenMinor(int minor, int create, int type)
45788dbee54ed400a3fd5594fab506518c171167805Rik Faith{
45888dbee54ed400a3fd5594fab506518c171167805Rik Faith    int  fd;
45988dbee54ed400a3fd5594fab506518c171167805Rik Faith    char buf[64];
4600c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns    const char *dev_name;
46150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely
462ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    if (create)
46350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return drmOpenDevice(makedev(DRM_MAJOR, minor), minor, type);
46450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely
4650c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns    switch (type) {
4660c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns    case DRM_NODE_PRIMARY:
46750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        dev_name = DRM_DEV_NAME;
46850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        break;
4690c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns    case DRM_NODE_CONTROL:
47050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        dev_name = DRM_CONTROL_DEV_NAME;
47150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        break;
4720c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns    case DRM_NODE_RENDER:
47350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        dev_name = DRM_RENDER_DEV_NAME;
47450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        break;
4750c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns    default:
47650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -EINVAL;
4770c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns    };
4780c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns
4790c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns    sprintf(buf, dev_name, DRM_DIR_NAME, minor);
480ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    if ((fd = open(buf, O_RDWR, 0)) >= 0)
48150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return fd;
48288dbee54ed400a3fd5594fab506518c171167805Rik Faith    return -errno;
48388dbee54ed400a3fd5594fab506518c171167805Rik Faith}
48488dbee54ed400a3fd5594fab506518c171167805Rik Faith
485569da5a42ebf10c86d6c6ba81866a888e1c708dcBrian Paul
486d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
487d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Determine whether the DRM kernel driver has been loaded.
48850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
489d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return 1 if the DRM driver is loaded, 0 otherwise.
490d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
49150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely * \internal
492d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Determine the presence of the kernel driver by attempting to open the 0
493d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * minor and get version information.  For backward compatibility with older
494d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Linux implementations, /proc/dri is also checked.
495d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
496569da5a42ebf10c86d6c6ba81866a888e1c708dcBrian Paulint drmAvailable(void)
497569da5a42ebf10c86d6c6ba81866a888e1c708dcBrian Paul{
498569da5a42ebf10c86d6c6ba81866a888e1c708dcBrian Paul    drmVersionPtr version;
499569da5a42ebf10c86d6c6ba81866a888e1c708dcBrian Paul    int           retval = 0;
500569da5a42ebf10c86d6c6ba81866a888e1c708dcBrian Paul    int           fd;
501360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes
502ad8bbfd3c74466f088be8088d2d0524bed392b71Frank Binns    if ((fd = drmOpenMinor(0, 1, DRM_NODE_PRIMARY)) < 0) {
503b0a928557c91fec527f41ae8b2441174889bf32cAlan Hourihane#ifdef __linux__
50450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        /* Try proc for backward Linux compatibility */
50550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        if (!access("/proc/dri/0", R_OK))
50650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            return 1;
507b0a928557c91fec527f41ae8b2441174889bf32cAlan Hourihane#endif
50850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return 0;
509569da5a42ebf10c86d6c6ba81866a888e1c708dcBrian Paul    }
51050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely
51188dbee54ed400a3fd5594fab506518c171167805Rik Faith    if ((version = drmGetVersion(fd))) {
51250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        retval = 1;
51350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        drmFreeVersion(version);
51488dbee54ed400a3fd5594fab506518c171167805Rik Faith    }
51588dbee54ed400a3fd5594fab506518c171167805Rik Faith    close(fd);
516569da5a42ebf10c86d6c6ba81866a888e1c708dcBrian Paul
517569da5a42ebf10c86d6c6ba81866a888e1c708dcBrian Paul    return retval;
518569da5a42ebf10c86d6c6ba81866a888e1c708dcBrian Paul}
519569da5a42ebf10c86d6c6ba81866a888e1c708dcBrian Paul
520f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhoustatic int drmGetMinorBase(int type)
521f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou{
522f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou    switch (type) {
523f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou    case DRM_NODE_PRIMARY:
524f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou        return 0;
525f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou    case DRM_NODE_CONTROL:
526f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou        return 64;
527f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou    case DRM_NODE_RENDER:
528f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou        return 128;
529f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou    default:
530f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou        return -1;
531f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou    };
532f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou}
533d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
5341f73578df32f895a678a41758f6c563f49484347Frank Binnsstatic int drmGetMinorType(int minor)
5351f73578df32f895a678a41758f6c563f49484347Frank Binns{
5361f73578df32f895a678a41758f6c563f49484347Frank Binns    int type = minor >> 6;
5371f73578df32f895a678a41758f6c563f49484347Frank Binns
5381f73578df32f895a678a41758f6c563f49484347Frank Binns    if (minor < 0)
5391f73578df32f895a678a41758f6c563f49484347Frank Binns        return -1;
5401f73578df32f895a678a41758f6c563f49484347Frank Binns
5411f73578df32f895a678a41758f6c563f49484347Frank Binns    switch (type) {
5421f73578df32f895a678a41758f6c563f49484347Frank Binns    case DRM_NODE_PRIMARY:
5431f73578df32f895a678a41758f6c563f49484347Frank Binns    case DRM_NODE_CONTROL:
5441f73578df32f895a678a41758f6c563f49484347Frank Binns    case DRM_NODE_RENDER:
5451f73578df32f895a678a41758f6c563f49484347Frank Binns        return type;
5461f73578df32f895a678a41758f6c563f49484347Frank Binns    default:
5471f73578df32f895a678a41758f6c563f49484347Frank Binns        return -1;
5481f73578df32f895a678a41758f6c563f49484347Frank Binns    }
5491f73578df32f895a678a41758f6c563f49484347Frank Binns}
5501f73578df32f895a678a41758f6c563f49484347Frank Binns
5510ca03a4087a550646de7f26b6b53a932e8546474Emil Velikovstatic const char *drmGetMinorName(int type)
5520ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov{
5530ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov    switch (type) {
5540ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov    case DRM_NODE_PRIMARY:
555fc083322b0c8a58b51976adf23a582bce8bb75f1Jonathan Gray        return DRM_PRIMARY_MINOR_NAME;
5560ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov    case DRM_NODE_CONTROL:
557fc083322b0c8a58b51976adf23a582bce8bb75f1Jonathan Gray        return DRM_CONTROL_MINOR_NAME;
5580ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov    case DRM_NODE_RENDER:
559fc083322b0c8a58b51976adf23a582bce8bb75f1Jonathan Gray        return DRM_RENDER_MINOR_NAME;
5600ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov    default:
5610ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov        return NULL;
5620ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov    }
5630ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov}
5640ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov
565d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
566d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Open the device by bus ID.
567d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
568d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param busid bus ID.
569f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou * \param type device node type.
570d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
571d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return a file descriptor on success, or a negative value on error.
572d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
573d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
574d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function attempts to open every possible minor (up to DRM_MAX_MINOR),
575d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * comparing the device bus ID with the one supplied.
576d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
577d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \sa drmOpenMinor() and drmGetBusid().
578d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
579f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhoustatic int drmOpenByBusid(const char *busid, int type)
580e1dba5c3a73078dec24f07a6d685435677db94a4Daryll Strauss{
581b04515c5d6c95f573457a94267b855cceb639105Benjamin Herrenschmidt    int        i, pci_domain_ok = 1;
58288dbee54ed400a3fd5594fab506518c171167805Rik Faith    int        fd;
58388dbee54ed400a3fd5594fab506518c171167805Rik Faith    const char *buf;
58406cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    drmSetVersion sv;
585f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou    int        base = drmGetMinorBase(type);
586f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou
587f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou    if (base < 0)
588f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou        return -1;
58906cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt
59006cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    drmMsg("drmOpenByBusid: Searching for BusID %s\n", busid);
591f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou    for (i = base; i < base + DRM_MAX_MINOR; i++) {
59250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        fd = drmOpenMinor(i, 1, type);
59350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        drmMsg("drmOpenByBusid: drmOpenMinor returns %d\n", fd);
59450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        if (fd >= 0) {
59550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            /* We need to try for 1.4 first for proper PCI domain support
59650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely             * and if that fails, we know the kernel is busted
59750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely             */
59850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            sv.drm_di_major = 1;
59950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            sv.drm_di_minor = 4;
60050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            sv.drm_dd_major = -1;        /* Don't care */
60150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            sv.drm_dd_minor = -1;        /* Don't care */
60250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            if (drmSetInterfaceVersion(fd, &sv)) {
603b04515c5d6c95f573457a94267b855cceb639105Benjamin Herrenschmidt#ifndef __alpha__
60450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                pci_domain_ok = 0;
605b04515c5d6c95f573457a94267b855cceb639105Benjamin Herrenschmidt#endif
60650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                sv.drm_di_major = 1;
60750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                sv.drm_di_minor = 1;
60850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                sv.drm_dd_major = -1;       /* Don't care */
60950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                sv.drm_dd_minor = -1;       /* Don't care */
61050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                drmMsg("drmOpenByBusid: Interface 1.4 failed, trying 1.1\n");
61150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                drmSetInterfaceVersion(fd, &sv);
61250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            }
61350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            buf = drmGetBusid(fd);
61450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            drmMsg("drmOpenByBusid: drmGetBusid reports %s\n", buf);
61550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            if (buf && drmMatchBusID(buf, busid, pci_domain_ok)) {
61650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                drmFreeBusid(buf);
61750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                return fd;
61850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            }
61950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            if (buf)
62050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                drmFreeBusid(buf);
62150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            close(fd);
62250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        }
623e1dba5c3a73078dec24f07a6d685435677db94a4Daryll Strauss    }
624e1dba5c3a73078dec24f07a6d685435677db94a4Daryll Strauss    return -1;
625e1dba5c3a73078dec24f07a6d685435677db94a4Daryll Strauss}
626e1dba5c3a73078dec24f07a6d685435677db94a4Daryll Strauss
627d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
628d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
629d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Open the device by name.
630d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
631d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param name driver name.
632f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou * \param type the device node type.
63350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
634d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return a file descriptor on success, or a negative value on error.
63550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
636d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
637d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function opens the first minor number that matches the driver name and
638d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * isn't already in use.  If it's in use it then it will already have a bus ID
639d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * assigned.
64050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
641d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \sa drmOpenMinor(), drmGetVersion() and drmGetBusid().
642d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
643f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhoustatic int drmOpenByName(const char *name, int type)
644b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strauss{
64588dbee54ed400a3fd5594fab506518c171167805Rik Faith    int           i;
64688dbee54ed400a3fd5594fab506518c171167805Rik Faith    int           fd;
64788dbee54ed400a3fd5594fab506518c171167805Rik Faith    drmVersionPtr version;
64856bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes    char *        id;
649f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou    int           base = drmGetMinorBase(type);
650f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou
651f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou    if (base < 0)
652f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou        return -1;
653db85ed25afc616acfaadb21facf6066354f9d490Dave Airlie
65456bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes    /*
65556bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes     * Open the first minor number that matches the driver name and isn't
65656bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes     * already in use.  If it's in use it will have a busid assigned already.
65756bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes     */
658f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou    for (i = base; i < base + DRM_MAX_MINOR; i++) {
65950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        if ((fd = drmOpenMinor(i, 1, type)) >= 0) {
66050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            if ((version = drmGetVersion(fd))) {
66150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                if (!strcmp(version->name, name)) {
66250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                    drmFreeVersion(version);
66350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                    id = drmGetBusid(fd);
66450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                    drmMsg("drmGetBusid returned '%s'\n", id ? id : "NULL");
66550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                    if (!id || !*id) {
66650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                        if (id)
66750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                            drmFreeBusid(id);
66850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                        return fd;
66950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                    } else {
67050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                        drmFreeBusid(id);
67150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                    }
67250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                } else {
67350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                    drmFreeVersion(version);
67450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                }
67550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            }
67650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            close(fd);
67750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        }
678b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strauss    }
679b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strauss
68088dbee54ed400a3fd5594fab506518c171167805Rik Faith#ifdef __linux__
68122e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jackson    /* Backward-compatibility /proc support */
682b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strauss    for (i = 0; i < 8; i++) {
68350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        char proc_name[64], buf[512];
68450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        char *driver, *pt, *devstring;
68550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        int  retcode;
68650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely
68750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        sprintf(proc_name, "/proc/dri/%d/name", i);
68850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        if ((fd = open(proc_name, 0, 0)) >= 0) {
68950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            retcode = read(fd, buf, sizeof(buf)-1);
69050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            close(fd);
69150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            if (retcode) {
69250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                buf[retcode-1] = '\0';
69350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                for (driver = pt = buf; *pt && *pt != ' '; ++pt)
69450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                    ;
69550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                if (*pt) { /* Device is next */
69650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                    *pt = '\0';
69750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                    if (!strcmp(driver, name)) { /* Match */
69850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                        for (devstring = ++pt; *pt && *pt != ' '; ++pt)
69950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                            ;
70050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                        if (*pt) { /* Found busid */
70150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                            return drmOpenByBusid(++pt, type);
70250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                        } else { /* No busid */
70350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                            return drmOpenDevice(strtol(devstring, NULL, 0),i, type);
70450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                        }
70550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                    }
70650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                }
70750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            }
70850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        }
709b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strauss    }
71088dbee54ed400a3fd5594fab506518c171167805Rik Faith#endif
71188dbee54ed400a3fd5594fab506518c171167805Rik Faith
712b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strauss    return -1;
713b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strauss}
714b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
715b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strauss
716d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
717d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Open the DRM device.
718d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
719d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Looks up the specified name and bus ID, and opens the device found.  The
720d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * entry in /dev/dri is created if necessary and if called by root.
721d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
722d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param name driver name. Not referenced if bus ID is supplied.
723d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param busid bus ID. Zero if not known.
72450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
725d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return a file descriptor on success, or a negative value on error.
72650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
727d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
728d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * It calls drmOpenByBusid() if \p busid is specified or drmOpenByName()
729d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * otherwise.
730d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
731b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Straussint drmOpen(const char *name, const char *busid)
732b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
733f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou    return drmOpenWithType(name, busid, DRM_NODE_PRIMARY);
734f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou}
735f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou
736f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou/**
737f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou * Open the DRM device with specified type.
738f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou *
739f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou * Looks up the specified name and bus ID, and opens the device found.  The
740f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou * entry in /dev/dri is created if necessary and if called by root.
741f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou *
742f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou * \param name driver name. Not referenced if bus ID is supplied.
743f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou * \param busid bus ID. Zero if not known.
744f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou * \param type the device node type to open, PRIMARY, CONTROL or RENDER
745f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou *
746f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou * \return a file descriptor on success, or a negative value on error.
747f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou *
748f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou * \internal
749f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou * It calls drmOpenByBusid() if \p busid is specified or drmOpenByName()
750f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou * otherwise.
751f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou */
752f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhouint drmOpenWithType(const char *name, const char *busid, int type)
753f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou{
7542f9aea0661550a43c3d2ac33a5bc286870edd34ePrabhanjan Kandula    if (name != NULL && drm_server_info &&
7552f9aea0661550a43c3d2ac33a5bc286870edd34ePrabhanjan Kandula        drm_server_info->load_module && !drmAvailable()) {
75650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        /* try to load the kernel module */
75750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        if (!drm_server_info->load_module(name)) {
75850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            drmMsg("[drm] failed to load kernel module \"%s\"\n", name);
75950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            return -1;
76050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        }
76106cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    }
76206cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt
76306cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    if (busid) {
76450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        int fd = drmOpenByBusid(busid, type);
76550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        if (fd >= 0)
76650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            return fd;
76706cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    }
76850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely
76906cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    if (name)
77050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return drmOpenByName(name, type);
77122e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jackson
77206cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    return -1;
773b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
774b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
775731cd5526e5c732d51307b26e784f454a724a699Jesse Barnesint drmOpenControl(int minor)
776731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes{
777731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes    return drmOpenMinor(minor, 0, DRM_NODE_CONTROL);
778731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes}
779d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
7800c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binnsint drmOpenRender(int minor)
7810c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns{
7820c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns    return drmOpenMinor(minor, 0, DRM_NODE_RENDER);
7830c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns}
7840c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns
785d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
786d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Free the version information returned by drmGetVersion().
787d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
788d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param v pointer to the version information.
789d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
790d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
791d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * It frees the memory pointed by \p %v as well as all the non-null strings
792d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * pointers in it.
793d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
794b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Straussvoid drmFreeVersion(drmVersionPtr v)
795b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
796ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    if (!v)
79750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return;
7989d8ba2d0d479f53b996c0a0e366acfee52daab3bJakob Bornecrantz    drmFree(v->name);
7999d8ba2d0d479f53b996c0a0e366acfee52daab3bJakob Bornecrantz    drmFree(v->date);
8009d8ba2d0d479f53b996c0a0e366acfee52daab3bJakob Bornecrantz    drmFree(v->desc);
801b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drmFree(v);
802b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
803b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
804d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
805d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
806d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Free the non-public version information returned by the kernel.
807d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
808d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param v pointer to the version information.
809d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
810d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
811d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Used by drmGetVersion() to free the memory pointed by \p %v as well as all
812d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * the non-null strings pointers in it.
813d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
814b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Straussstatic void drmFreeKernelVersion(drm_version_t *v)
815b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
816ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    if (!v)
81750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return;
8189d8ba2d0d479f53b996c0a0e366acfee52daab3bJakob Bornecrantz    drmFree(v->name);
8199d8ba2d0d479f53b996c0a0e366acfee52daab3bJakob Bornecrantz    drmFree(v->date);
8209d8ba2d0d479f53b996c0a0e366acfee52daab3bJakob Bornecrantz    drmFree(v->desc);
821b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drmFree(v);
822b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
823b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
824d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
825d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
826d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Copy version information.
82750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
828d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param d destination pointer.
829d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param s source pointer.
83050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
831d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
832d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Used by drmGetVersion() to translate the information returned by the ioctl
833d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * interface in a private structure into the public structure counterpart.
834d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
835569da5a42ebf10c86d6c6ba81866a888e1c708dcBrian Paulstatic void drmCopyVersion(drmVersionPtr d, const drm_version_t *s)
836b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
837b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    d->version_major      = s->version_major;
838b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    d->version_minor      = s->version_minor;
839b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    d->version_patchlevel = s->version_patchlevel;
840b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    d->name_len           = s->name_len;
8410a1ff35c70730160973715b82112cd97c62ac13eAdam Jackson    d->name               = strdup(s->name);
842b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    d->date_len           = s->date_len;
8430a1ff35c70730160973715b82112cd97c62ac13eAdam Jackson    d->date               = strdup(s->date);
844b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    d->desc_len           = s->desc_len;
8450a1ff35c70730160973715b82112cd97c62ac13eAdam Jackson    d->desc               = strdup(s->desc);
846b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
847b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
848b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
849d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
850d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Query the driver version information.
851d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
852d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
85350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
854d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return pointer to a drmVersion structure which should be freed with
855d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * drmFreeVersion().
85650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
857d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \note Similar information is available via /proc/dri.
85850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
859d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
860d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * It gets the version information via successive DRM_IOCTL_VERSION ioctls,
861d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * first with zeros to get the string lengths, and then the actually strings.
862d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * It also null-terminates them since they might not be already.
863d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
864b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll StraussdrmVersionPtr drmGetVersion(int fd)
865b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
866b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drmVersionPtr retval;
867b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_version_t *version = drmMalloc(sizeof(*version));
868b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
86995f23cf894757d05a6b6c980062a46968dc069b1Daniel Vetter    memclear(*version);
870360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes
8718b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_VERSION, version)) {
87250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        drmFreeKernelVersion(version);
87350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return NULL;
874b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    }
875b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
876b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    if (version->name_len)
87750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        version->name    = drmMalloc(version->name_len + 1);
878b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    if (version->date_len)
87950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        version->date    = drmMalloc(version->date_len + 1);
880b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    if (version->desc_len)
88150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        version->desc    = drmMalloc(version->desc_len + 1);
882360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes
8838b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_VERSION, version)) {
88450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        drmMsg("DRM_IOCTL_VERSION: %s\n", strerror(errno));
88550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        drmFreeKernelVersion(version);
88650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return NULL;
887b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    }
888b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
88922e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jackson    /* The results might not be null-terminated strings, so terminate them. */
890b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    if (version->name_len) version->name[version->name_len] = '\0';
891b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    if (version->date_len) version->date[version->date_len] = '\0';
892b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    if (version->desc_len) version->desc[version->desc_len] = '\0';
893b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
894b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    retval = drmMalloc(sizeof(*retval));
895b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drmCopyVersion(retval, version);
896b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drmFreeKernelVersion(version);
897b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return retval;
898b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
899b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
9003903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen
901d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
902d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Get version information for the DRM user space library.
90350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
904d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This version number is driver independent.
90550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
906d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
907d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
908d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return version information.
90950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
910d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
911d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function allocates and fills a drm_version structure with a hard coded
912d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * version number.
913d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
9143903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens OwendrmVersionPtr drmGetLibVersion(int fd)
9153903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen{
9163903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen    drm_version_t *version = drmMalloc(sizeof(*version));
9173903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen
9183903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen    /* Version history:
91979038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie     *   NOTE THIS MUST NOT GO ABOVE VERSION 1.X due to drivers needing it
9203903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen     *   revision 1.0.x = original DRM interface with no drmGetLibVersion
9213903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen     *                    entry point and many drm<Device> extensions
9223903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen     *   revision 1.1.x = added drmCommand entry points for device extensions
9233903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen     *                    added drmGetLibVersion to identify libdrm.a version
92406cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt     *   revision 1.2.x = added drmSetInterfaceVersion
92506cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt     *                    modified drmOpen to handle both busid and name
92679038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie     *   revision 1.3.x = added server + memory manager
9273903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen     */
92879038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie    version->version_major      = 1;
92979038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie    version->version_minor      = 3;
9303903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen    version->version_patchlevel = 0;
9313903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen
9323903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen    return (drmVersionPtr)version;
9333903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen}
9343903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen
9355c6c6913d1260024e5d156db7973c9e46fe1ff03Ben Skeggsint drmGetCap(int fd, uint64_t capability, uint64_t *value)
9365c6c6913d1260024e5d156db7973c9e46fe1ff03Ben Skeggs{
93750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    struct drm_get_cap cap;
93850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    int ret;
9395c6c6913d1260024e5d156db7973c9e46fe1ff03Ben Skeggs
94050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    memclear(cap);
94150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    cap.capability = capability;
942fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter
94350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    ret = drmIoctl(fd, DRM_IOCTL_GET_CAP, &cap);
94450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    if (ret)
94550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return ret;
9465c6c6913d1260024e5d156db7973c9e46fe1ff03Ben Skeggs
94750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    *value = cap.value;
94850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    return 0;
9495c6c6913d1260024e5d156db7973c9e46fe1ff03Ben Skeggs}
950d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
951ddbbdb13d80ea7f60e6f71356a444995b905366bDamien Lespiauint drmSetClientCap(int fd, uint64_t capability, uint64_t value)
952ddbbdb13d80ea7f60e6f71356a444995b905366bDamien Lespiau{
95350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    struct drm_set_client_cap cap;
954fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter
95550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    memclear(cap);
95650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    cap.capability = capability;
95750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    cap.value = value;
958ddbbdb13d80ea7f60e6f71356a444995b905366bDamien Lespiau
95950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    return drmIoctl(fd, DRM_IOCTL_SET_CLIENT_CAP, &cap);
960ddbbdb13d80ea7f60e6f71356a444995b905366bDamien Lespiau}
961ddbbdb13d80ea7f60e6f71356a444995b905366bDamien Lespiau
962d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
963d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Free the bus ID information.
964d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
965d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param busid bus ID information string as given by drmGetBusid().
966d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
967d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
968d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is just frees the memory pointed by \p busid.
969d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
970b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Straussvoid drmFreeBusid(const char *busid)
971b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
972b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strauss    drmFree((void *)busid);
973b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
974b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
975d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
976d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
977d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Get the bus ID of the device.
978d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
979d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
980d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
981d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return bus ID string.
982d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
983d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
984d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function gets the bus ID via successive DRM_IOCTL_GET_UNIQUE ioctls to
985d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * get the string length and data, passing the arguments in a drm_unique
986d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * structure.
987d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
988b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strausschar *drmGetBusid(int fd)
989b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
990b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strauss    drm_unique_t u;
991b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
992fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(u);
993b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
9948b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_GET_UNIQUE, &u))
99550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return NULL;
996b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strauss    u.unique = drmMalloc(u.unique_len + 1);
9978b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_GET_UNIQUE, &u))
99850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return NULL;
999b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strauss    u.unique[u.unique_len] = '\0';
100006cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt
1001b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strauss    return u.unique;
1002b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1003b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1004d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
1005d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1006d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Set the bus ID of the device.
1007d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1008d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
1009d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param busid bus ID string.
1010d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1011d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success, negative on failure.
1012d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1013d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1014d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_SET_UNIQUE ioctl, passing
1015d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * the arguments in a drm_unique structure.
1016d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
1017b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Straussint drmSetBusid(int fd, const char *busid)
1018b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1019b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strauss    drm_unique_t u;
1020b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1021fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(u);
1022b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strauss    u.unique     = (char *)busid;
1023b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strauss    u.unique_len = strlen(busid);
1024b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
10258b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_SET_UNIQUE, &u)) {
102650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -errno;
102756bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes    }
1028b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return 0;
1029b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1030b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
10318696e71db2d79eb318c00abde625d7b61d6800a1Jon Smirlint drmGetMagic(int fd, drm_magic_t * magic)
1032b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1033b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_auth_t auth;
1034b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1035fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(auth);
1036fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter
1037b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    *magic = 0;
10388b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_GET_MAGIC, &auth))
103950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -errno;
1040b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    *magic = auth.magic;
1041b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return 0;
1042b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1043b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
10448696e71db2d79eb318c00abde625d7b61d6800a1Jon Smirlint drmAuthMagic(int fd, drm_magic_t magic)
1045b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1046b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_auth_t auth;
1047b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1048fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(auth);
1049b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    auth.magic = magic;
10508b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_AUTH_MAGIC, &auth))
105150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -errno;
1052b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return 0;
1053b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1054b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1055d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1056d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Specifies a range of memory that is available for mapping by a
1057d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * non-root process.
1058d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1059d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
1060d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param offset usually the physical address. The actual meaning depends of
1061d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * the \p type parameter. See below.
1062d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param size of the memory in bytes.
1063d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param type type of the memory to be mapped.
1064d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param flags combination of several flags to modify the function actions.
1065d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param handle will be set to a value that may be used as the offset
1066d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * parameter for mmap().
106750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
1068d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success or a negative value on error.
1069d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1070d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \par Mapping the frame buffer
1071d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * For the frame buffer
1072d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * - \p offset will be the physical address of the start of the frame buffer,
1073d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * - \p size will be the size of the frame buffer in bytes, and
1074d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * - \p type will be DRM_FRAME_BUFFER.
1075d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1076d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \par
1077d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * The area mapped will be uncached. If MTRR support is available in the
107850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely * kernel, the frame buffer area will be set to write combining.
1079d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1080d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \par Mapping the MMIO register area
1081d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * For the MMIO register area,
1082d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * - \p offset will be the physical address of the start of the register area,
1083d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * - \p size will be the size of the register area bytes, and
1084d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * - \p type will be DRM_REGISTERS.
1085d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \par
108650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely * The area mapped will be uncached.
108750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
1088d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \par Mapping the SAREA
1089d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * For the SAREA,
1090d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * - \p offset will be ignored and should be set to zero,
1091d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * - \p size will be the desired size of the SAREA in bytes,
1092d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * - \p type will be DRM_SHM.
109350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
1094d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \par
1095d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * A shared memory area of the requested size will be created and locked in
1096d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * kernel memory. This area may be mapped into client-space by using the handle
109750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely * returned.
109850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
1099d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \note May only be called by root.
1100d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1101d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1102d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_ADD_MAP ioctl, passing
1103d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * the arguments in a drm_map structure.
1104d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
110522e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jacksonint drmAddMap(int fd, drm_handle_t offset, drmSize size, drmMapType type,
110650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely              drmMapFlags flags, drm_handle_t *handle)
1107b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1108b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_map_t map;
1109b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1110fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(map);
1111b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    map.offset  = offset;
1112b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    map.size    = size;
1113b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    map.type    = type;
1114b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    map.flags   = flags;
11158b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_ADD_MAP, &map))
111650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -errno;
1117ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    if (handle)
111850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        *handle = (drm_handle_t)(uintptr_t)map.handle;
1119b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return 0;
1120b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1121b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
11228696e71db2d79eb318c00abde625d7b61d6800a1Jon Smirlint drmRmMap(int fd, drm_handle_t handle)
112374e19a40187ac3b5907922e5dc01418135a5794bKevin E Martin{
112474e19a40187ac3b5907922e5dc01418135a5794bKevin E Martin    drm_map_t map;
112574e19a40187ac3b5907922e5dc01418135a5794bKevin E Martin
1126fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(map);
1127961bf9b5c2866ccb4fedf2b45b29fb688519d0dbJeremy Huddleston    map.handle = (void *)(uintptr_t)handle;
112874e19a40187ac3b5907922e5dc01418135a5794bKevin E Martin
11298b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if(drmIoctl(fd, DRM_IOCTL_RM_MAP, &map))
113050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -errno;
113174e19a40187ac3b5907922e5dc01418135a5794bKevin E Martin    return 0;
113274e19a40187ac3b5907922e5dc01418135a5794bKevin E Martin}
113374e19a40187ac3b5907922e5dc01418135a5794bKevin E Martin
1134d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1135d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Make buffers available for DMA transfers.
113650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
1137d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
1138d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param count number of buffers.
1139d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param size size of each buffer.
1140d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param flags buffer allocation flags.
114150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely * \param agp_offset offset in the AGP aperture
1142d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1143d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return number of buffers allocated, negative on error.
1144d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1145d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1146d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around DRM_IOCTL_ADD_BUFS ioctl.
1147d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1148d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \sa drm_buf_desc.
1149d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
1150ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmannint drmAddBufs(int fd, int count, int size, drmBufDescFlags flags,
115150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely               int agp_offset)
1152b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1153b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_buf_desc_t request;
1154360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes
1155fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(request);
1156b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    request.count     = count;
1157b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    request.size      = size;
1158b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    request.flags     = flags;
1159ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    request.agp_start = agp_offset;
1160360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes
11618b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_ADD_BUFS, &request))
116250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -errno;
1163b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return request.count;
1164b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1165b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1166b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Straussint drmMarkBufs(int fd, double low, double high)
1167b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1168b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_buf_info_t info;
1169b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    int            i;
1170b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1171fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(info);
1172b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
11738b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info))
117450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -EINVAL;
1175b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1176ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    if (!info.count)
117750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -EINVAL;
1178360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes
1179b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    if (!(info.list = drmMalloc(info.count * sizeof(*info.list))))
118050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -ENOMEM;
1181360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes
11828b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info)) {
118350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        int retval = -errno;
118450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        drmFree(info.list);
118550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return retval;
1186b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    }
1187360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes
1188b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    for (i = 0; i < info.count; i++) {
118950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        info.list[i].low_mark  = low  * info.list[i].count;
119050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        info.list[i].high_mark = high * info.list[i].count;
119150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        if (drmIoctl(fd, DRM_IOCTL_MARK_BUFS, &info.list[i])) {
119250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            int retval = -errno;
119350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            drmFree(info.list);
119450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            return retval;
119550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        }
1196b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    }
1197b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drmFree(info.list);
1198360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes
1199b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return 0;
1200b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1201b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1202d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1203d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Free buffers.
1204d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1205d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
1206d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param count number of buffers to free.
1207d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param list list of buffers to be freed.
1208d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1209d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success, or a negative value on failure.
121050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
1211d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \note This function is primarily used for debugging.
121250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
1213d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1214d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_FREE_BUFS ioctl, passing
1215d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * the arguments in a drm_buf_free structure.
1216d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
1217b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Straussint drmFreeBufs(int fd, int count, int *list)
1218b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1219b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_buf_free_t request;
1220b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1221fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(request);
1222b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    request.count = count;
1223b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    request.list  = list;
12248b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_FREE_BUFS, &request))
122550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -errno;
1226b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return 0;
1227b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1228b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1229d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
1230d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1231d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Close the device.
1232d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1233d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
1234d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1235d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1236d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function closes the file descriptor.
1237d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
1238b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Straussint drmClose(int fd)
1239b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1240b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    unsigned long key    = drmGetKeyFromFd(fd);
1241b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drmHashEntry  *entry = drmGetEntry(fd);
1242b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1243b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drmHashDestroy(entry->tagTable);
1244b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    entry->fd       = 0;
1245b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    entry->f        = NULL;
1246b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    entry->tagTable = NULL;
1247b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1248b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drmHashDelete(drmHashTable, key);
1249b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drmFree(entry);
1250b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1251b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return close(fd);
1252b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1253b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1254d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
1255d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1256d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Map a region of memory.
1257d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1258d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
1259d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param handle handle returned by drmAddMap().
1260d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param size size in bytes. Must match the size used by drmAddMap().
1261d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param address will contain the user-space virtual address where the mapping
1262d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * begins.
1263d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1264d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success, or a negative value on failure.
126550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
1266d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1267d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper for mmap().
1268d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
126922e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jacksonint drmMap(int fd, drm_handle_t handle, drmSize size, drmAddressPtr address)
1270b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1271c7558d8fa4df805b7f7ff3d631432eadac9b8a1cAlan Hourihane    static unsigned long pagesize_mask = 0;
1272c7558d8fa4df805b7f7ff3d631432eadac9b8a1cAlan Hourihane
1273ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    if (fd < 0)
127450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -EINVAL;
1275c7558d8fa4df805b7f7ff3d631432eadac9b8a1cAlan Hourihane
1276c7558d8fa4df805b7f7ff3d631432eadac9b8a1cAlan Hourihane    if (!pagesize_mask)
127750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        pagesize_mask = getpagesize() - 1;
1278c7558d8fa4df805b7f7ff3d631432eadac9b8a1cAlan Hourihane
1279c7558d8fa4df805b7f7ff3d631432eadac9b8a1cAlan Hourihane    size = (size + pagesize_mask) & ~pagesize_mask;
1280c7558d8fa4df805b7f7ff3d631432eadac9b8a1cAlan Hourihane
1281faf51d5694e3f0ec12c7fa1fd2f87fc96a300fe3Emil Velikov    *address = drm_mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, handle);
1282ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    if (*address == MAP_FAILED)
128350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -errno;
1284b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return 0;
1285b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1286b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1287d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
1288d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1289d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Unmap mappings obtained with drmMap().
1290d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1291d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param address address as given by drmMap().
1292d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param size size in bytes. Must match the size used by drmMap().
129350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
1294d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success, or a negative value on failure.
1295d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1296d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
129722e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jackson * This function is a wrapper for munmap().
1298d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
1299b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Straussint drmUnmap(drmAddress address, drmSize size)
1300b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1301faf51d5694e3f0ec12c7fa1fd2f87fc96a300fe3Emil Velikov    return drm_munmap(address, size);
1302b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1303b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1304b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll StraussdrmBufInfoPtr drmGetBufInfo(int fd)
1305b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1306b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_buf_info_t info;
1307b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drmBufInfoPtr  retval;
1308b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    int            i;
1309b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1310fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(info);
1311b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
13128b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info))
131350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return NULL;
1314b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1315b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    if (info.count) {
131650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        if (!(info.list = drmMalloc(info.count * sizeof(*info.list))))
131750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            return NULL;
131850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely
131950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info)) {
132050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            drmFree(info.list);
132150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            return NULL;
132250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        }
132350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely
132450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        retval = drmMalloc(sizeof(*retval));
132550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        retval->count = info.count;
132650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        retval->list  = drmMalloc(info.count * sizeof(*retval->list));
132750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        for (i = 0; i < info.count; i++) {
132850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            retval->list[i].count     = info.list[i].count;
132950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            retval->list[i].size      = info.list[i].size;
133050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            retval->list[i].low_mark  = info.list[i].low_mark;
133150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            retval->list[i].high_mark = info.list[i].high_mark;
133250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        }
133350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        drmFree(info.list);
133450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return retval;
1335b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    }
1336b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return NULL;
1337b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1338b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1339d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1340d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Map all DMA buffers into client-virtual space.
1341d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1342d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
1343d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1344d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return a pointer to a ::drmBufMap structure.
1345d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1346d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \note The client may not use these buffers until obtaining buffer indices
1347d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * with drmDMA().
134850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
1349d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1350d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function calls the DRM_IOCTL_MAP_BUFS ioctl and copies the returned
1351d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * information about the buffers in a drm_buf_map structure into the
1352d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * client-visible data structures.
135350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely */
1354b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll StraussdrmBufMapPtr drmMapBufs(int fd)
1355b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1356b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_buf_map_t bufs;
1357b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drmBufMapPtr  retval;
1358b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    int           i;
1359360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes
1360fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(bufs);
13618b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_MAP_BUFS, &bufs))
136250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return NULL;
1363b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1364ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    if (!bufs.count)
136550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return NULL;
13668696e71db2d79eb318c00abde625d7b61d6800a1Jon Smirl
136750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    if (!(bufs.list = drmMalloc(bufs.count * sizeof(*bufs.list))))
136850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return NULL;
1369b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
137050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    if (drmIoctl(fd, DRM_IOCTL_MAP_BUFS, &bufs)) {
137150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        drmFree(bufs.list);
137250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return NULL;
137350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    }
137422e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jackson
137550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    retval = drmMalloc(sizeof(*retval));
137650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    retval->count = bufs.count;
137750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    retval->list  = drmMalloc(bufs.count * sizeof(*retval->list));
137850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    for (i = 0; i < bufs.count; i++) {
137950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        retval->list[i].idx     = bufs.list[i].idx;
138050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        retval->list[i].total   = bufs.list[i].total;
138150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        retval->list[i].used    = 0;
138250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        retval->list[i].address = bufs.list[i].address;
138350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    }
13848696e71db2d79eb318c00abde625d7b61d6800a1Jon Smirl
138550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    drmFree(bufs.list);
138650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    return retval;
1387b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1388b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1389d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
1390d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1391d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Unmap buffers allocated with drmMapBufs().
1392d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1393d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success, or negative value on failure.
1394d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1395d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
13968696e71db2d79eb318c00abde625d7b61d6800a1Jon Smirl * Calls munmap() for every buffer stored in \p bufs and frees the
13978696e71db2d79eb318c00abde625d7b61d6800a1Jon Smirl * memory allocated by drmMapBufs().
1398d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
1399b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Straussint drmUnmapBufs(drmBufMapPtr bufs)
1400b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1401b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    int i;
1402360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes
1403b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    for (i = 0; i < bufs->count; i++) {
140450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        drm_munmap(bufs->list[i].address, bufs->list[i].total);
1405b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    }
14068696e71db2d79eb318c00abde625d7b61d6800a1Jon Smirl
14078696e71db2d79eb318c00abde625d7b61d6800a1Jon Smirl    drmFree(bufs->list);
14088696e71db2d79eb318c00abde625d7b61d6800a1Jon Smirl    drmFree(bufs);
1409b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return 0;
1410b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1411b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1412d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
141350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely#define DRM_DMA_RETRY  16
1414360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes
1415d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1416d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Reserve DMA buffers.
1417d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1418d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
141950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely * \param request
142050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
1421d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success, or a negative value on failure.
1422d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1423d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1424d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Assemble the arguments into a drm_dma structure and keeps issuing the
1425d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * DRM_IOCTL_DMA ioctl until success or until maximum number of retries.
1426d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
1427b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Straussint drmDMA(int fd, drmDMAReqPtr request)
1428b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1429b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_dma_t dma;
1430360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes    int ret, i = 0;
1431b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1432b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    dma.context         = request->context;
1433b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    dma.send_count      = request->send_count;
1434b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    dma.send_indices    = request->send_list;
1435b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    dma.send_sizes      = request->send_sizes;
1436b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    dma.flags           = request->flags;
1437b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    dma.request_count   = request->request_count;
1438b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    dma.request_size    = request->request_size;
1439b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    dma.request_indices = request->request_list;
1440b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    dma.request_sizes   = request->request_sizes;
14418696e71db2d79eb318c00abde625d7b61d6800a1Jon Smirl    dma.granted_count   = 0;
1442360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes
1443360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes    do {
144450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        ret = ioctl( fd, DRM_IOCTL_DMA, &dma );
1445360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes    } while ( ret && errno == EAGAIN && i++ < DRM_DMA_RETRY );
1446360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes
1447360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes    if ( ret == 0 ) {
144850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        request->granted_count = dma.granted_count;
144950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return 0;
1450360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes    } else {
145150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -errno;
1452360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes    }
1453b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1454b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1455d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
1456d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1457d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Obtain heavyweight hardware lock.
1458d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1459d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
1460d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param context context.
1461d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param flags flags that determine the sate of the hardware when the function
1462d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * returns.
146350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
1464d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return always zero.
146550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
1466d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1467d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function translates the arguments into a drm_lock structure and issue
1468d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * the DRM_IOCTL_LOCK ioctl until the lock is successfully acquired.
1469d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
14708696e71db2d79eb318c00abde625d7b61d6800a1Jon Smirlint drmGetLock(int fd, drm_context_t context, drmLockFlags flags)
1471b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1472b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_lock_t lock;
1473b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1474fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(lock);
1475b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    lock.context = context;
1476b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    lock.flags   = 0;
1477b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    if (flags & DRM_LOCK_READY)      lock.flags |= _DRM_LOCK_READY;
1478b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    if (flags & DRM_LOCK_QUIESCENT)  lock.flags |= _DRM_LOCK_QUIESCENT;
1479b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    if (flags & DRM_LOCK_FLUSH)      lock.flags |= _DRM_LOCK_FLUSH;
1480b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    if (flags & DRM_LOCK_FLUSH_ALL)  lock.flags |= _DRM_LOCK_FLUSH_ALL;
1481b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    if (flags & DRM_HALT_ALL_QUEUES) lock.flags |= _DRM_HALT_ALL_QUEUES;
1482b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    if (flags & DRM_HALT_CUR_QUEUES) lock.flags |= _DRM_HALT_CUR_QUEUES;
1483360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes
14848b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    while (drmIoctl(fd, DRM_IOCTL_LOCK, &lock))
148550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        ;
1486b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return 0;
1487b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1488b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1489d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1490d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Release the hardware lock.
1491d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1492d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
1493d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param context context.
149450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
1495d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success, or a negative value on failure.
149650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
1497d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1498d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_UNLOCK ioctl, passing the
1499d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * argument in a drm_lock structure.
1500d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
15018696e71db2d79eb318c00abde625d7b61d6800a1Jon Smirlint drmUnlock(int fd, drm_context_t context)
1502b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1503b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_lock_t lock;
1504b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1505fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(lock);
1506b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    lock.context = context;
15078b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    return drmIoctl(fd, DRM_IOCTL_UNLOCK, &lock);
1508b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1509b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
151022e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jacksondrm_context_t *drmGetReservedContextList(int fd, int *count)
1511b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1512b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_ctx_res_t res;
1513b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_ctx_t     *list;
15148696e71db2d79eb318c00abde625d7b61d6800a1Jon Smirl    drm_context_t * retval;
1515b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    int           i;
1516b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1517fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(res);
15188b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_RES_CTX, &res))
151950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return NULL;
1520b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1521ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    if (!res.count)
152250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return NULL;
1523b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1524ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    if (!(list   = drmMalloc(res.count * sizeof(*list))))
152550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return NULL;
1526b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    if (!(retval = drmMalloc(res.count * sizeof(*retval)))) {
152750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        drmFree(list);
152850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return NULL;
1529b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    }
1530b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1531b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    res.contexts = list;
15328b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_RES_CTX, &res))
153350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return NULL;
1534b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1535ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    for (i = 0; i < res.count; i++)
153650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        retval[i] = list[i].handle;
1537b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drmFree(list);
1538b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1539b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    *count = res.count;
1540b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return retval;
1541b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1542b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
154322e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jacksonvoid drmFreeReservedContextList(drm_context_t *pt)
1544b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1545b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drmFree(pt);
1546b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1547b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1548d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1549d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Create context.
1550d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1551d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Used by the X server during GLXContext initialization. This causes
1552d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * per-context kernel-level resources to be allocated.
1553d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1554d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
1555d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param handle is set on success. To be used by the client when requesting DMA
1556d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * dispatch with drmDMA().
155750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
1558d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success, or a negative value on failure.
155950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
1560d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \note May only be called by root.
156150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
1562d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1563d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_ADD_CTX ioctl, passing the
1564d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * argument in a drm_ctx structure.
1565d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
156622e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jacksonint drmCreateContext(int fd, drm_context_t *handle)
1567b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1568b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_ctx_t ctx;
1569b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1570fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(ctx);
15718b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_ADD_CTX, &ctx))
157250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -errno;
1573b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    *handle = ctx.handle;
1574b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return 0;
1575b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1576b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
15778696e71db2d79eb318c00abde625d7b61d6800a1Jon Smirlint drmSwitchToContext(int fd, drm_context_t context)
1578b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1579b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_ctx_t ctx;
1580b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1581fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(ctx);
1582b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    ctx.handle = context;
15838b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_SWITCH_CTX, &ctx))
158450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -errno;
1585b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return 0;
1586b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1587b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
15888696e71db2d79eb318c00abde625d7b61d6800a1Jon Smirlint drmSetContextFlags(int fd, drm_context_t context, drm_context_tFlags flags)
1589b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1590b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_ctx_t ctx;
1591b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
159222e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jackson    /*
159322e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jackson     * Context preserving means that no context switches are done between DMA
159422e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jackson     * buffers from one context and the next.  This is suitable for use in the
159522e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jackson     * X server (which promises to maintain hardware context), or in the
159622e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jackson     * client-side library when buffers are swapped on behalf of two threads.
159722e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jackson     */
1598fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(ctx);
1599b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    ctx.handle = context;
1600ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    if (flags & DRM_CONTEXT_PRESERVED)
160150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        ctx.flags |= _DRM_CONTEXT_PRESERVED;
1602ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    if (flags & DRM_CONTEXT_2DONLY)
160350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        ctx.flags |= _DRM_CONTEXT_2DONLY;
16048b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_MOD_CTX, &ctx))
160550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -errno;
1606b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return 0;
1607b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1608b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
160922e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jacksonint drmGetContextFlags(int fd, drm_context_t context,
161022e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jackson                       drm_context_tFlagsPtr flags)
1611b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1612b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_ctx_t ctx;
1613b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1614fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(ctx);
1615b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    ctx.handle = context;
16168b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_GET_CTX, &ctx))
161750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -errno;
1618b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    *flags = 0;
1619ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    if (ctx.flags & _DRM_CONTEXT_PRESERVED)
162050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        *flags |= DRM_CONTEXT_PRESERVED;
1621ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    if (ctx.flags & _DRM_CONTEXT_2DONLY)
162250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        *flags |= DRM_CONTEXT_2DONLY;
1623b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return 0;
1624b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1625360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes
1626d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1627d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Destroy context.
1628d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1629d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Free any kernel-level resources allocated with drmCreateContext() associated
1630d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * with the context.
163150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
1632d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
1633d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param handle handle given by drmCreateContext().
163450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
1635d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success, or a negative value on failure.
163650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
1637d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \note May only be called by root.
163850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
1639d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1640d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_RM_CTX ioctl, passing the
1641d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * argument in a drm_ctx structure.
1642d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
16438696e71db2d79eb318c00abde625d7b61d6800a1Jon Smirlint drmDestroyContext(int fd, drm_context_t handle)
1644b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1645b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_ctx_t ctx;
1646fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter
1647fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(ctx);
1648b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    ctx.handle = handle;
16498b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_RM_CTX, &ctx))
165050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -errno;
1651b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return 0;
1652b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1653b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
165422e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jacksonint drmCreateDrawable(int fd, drm_drawable_t *handle)
1655b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1656b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_draw_t draw;
1657fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter
1658fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(draw);
16598b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_ADD_DRAW, &draw))
166050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -errno;
1661b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    *handle = draw.handle;
1662b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return 0;
1663b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1664b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
16658696e71db2d79eb318c00abde625d7b61d6800a1Jon Smirlint drmDestroyDrawable(int fd, drm_drawable_t handle)
1666b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1667b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_draw_t draw;
1668fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter
1669fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(draw);
1670b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    draw.handle = handle;
16718b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_RM_DRAW, &draw))
167250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -errno;
1673b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return 0;
1674b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1675b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
16769810ec2737de6aa81e764225f580e4ea39de437aMichel Dänzerint drmUpdateDrawableInfo(int fd, drm_drawable_t handle,
167750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                          drm_drawable_info_type_t type, unsigned int num,
167850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                          void *data)
16799810ec2737de6aa81e764225f580e4ea39de437aMichel Dänzer{
16809810ec2737de6aa81e764225f580e4ea39de437aMichel Dänzer    drm_update_draw_t update;
16819810ec2737de6aa81e764225f580e4ea39de437aMichel Dänzer
1682fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(update);
16839810ec2737de6aa81e764225f580e4ea39de437aMichel Dänzer    update.handle = handle;
16849810ec2737de6aa81e764225f580e4ea39de437aMichel Dänzer    update.type = type;
16859810ec2737de6aa81e764225f580e4ea39de437aMichel Dänzer    update.num = num;
16869810ec2737de6aa81e764225f580e4ea39de437aMichel Dänzer    update.data = (unsigned long long)(unsigned long)data;
16879810ec2737de6aa81e764225f580e4ea39de437aMichel Dänzer
16888b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_UPDATE_DRAW, &update))
168950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -errno;
16909810ec2737de6aa81e764225f580e4ea39de437aMichel Dänzer
16919810ec2737de6aa81e764225f580e4ea39de437aMichel Dänzer    return 0;
16929810ec2737de6aa81e764225f580e4ea39de437aMichel Dänzer}
16939810ec2737de6aa81e764225f580e4ea39de437aMichel Dänzer
1694d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1695d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Acquire the AGP device.
1696d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1697d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Must be called before any of the other AGP related calls.
1698d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1699d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
170050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
1701d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success, or a negative value on failure.
170250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
1703d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1704d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_AGP_ACQUIRE ioctl.
1705d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
1706ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmannint drmAgpAcquire(int fd)
1707ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann{
17088b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_AGP_ACQUIRE, NULL))
170950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -errno;
1710ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    return 0;
1711ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann}
1712ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
1713d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
1714d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1715d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Release the AGP device.
1716d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1717d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
171850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
1719d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success, or a negative value on failure.
172050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
1721d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1722d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_AGP_RELEASE ioctl.
1723d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
1724ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmannint drmAgpRelease(int fd)
1725ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann{
17268b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_AGP_RELEASE, NULL))
172750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -errno;
1728ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    return 0;
1729ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann}
1730ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
1731d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
1732d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1733d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Set the AGP mode.
1734d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1735d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
1736d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param mode AGP mode.
173750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
1738d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success, or a negative value on failure.
173950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
1740d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1741d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_AGP_ENABLE ioctl, passing the
1742d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * argument in a drm_agp_mode structure.
1743d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
1744ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmannint drmAgpEnable(int fd, unsigned long mode)
1745ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann{
1746ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    drm_agp_mode_t m;
1747ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
17481490055bc05fa941b59d10e89ef3fccd673af477Connor Behan    memclear(m);
1749ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    m.mode = mode;
17508b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_AGP_ENABLE, &m))
175150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -errno;
1752ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    return 0;
1753ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann}
1754ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
1755d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
1756d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1757d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Allocate a chunk of AGP memory.
1758d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1759d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
1760d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param size requested memory size in bytes. Will be rounded to page boundary.
1761d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param type type of memory to allocate.
1762d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param address if not zero, will be set to the physical address of the
1763d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * allocated memory.
1764d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param handle on success will be set to a handle of the allocated memory.
176550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
1766d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success, or a negative value on failure.
176750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
1768d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1769d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_AGP_ALLOC ioctl, passing the
1770d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * arguments in a drm_agp_buffer structure.
1771d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
1772ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmannint drmAgpAlloc(int fd, unsigned long size, unsigned long type,
177350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                unsigned long *address, drm_handle_t *handle)
1774ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann{
1775ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    drm_agp_buffer_t b;
1776b0a928557c91fec527f41ae8b2441174889bf32cAlan Hourihane
1777fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(b);
1778b0a928557c91fec527f41ae8b2441174889bf32cAlan Hourihane    *handle = DRM_AGP_NO_HANDLE;
1779ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    b.size   = size;
1780ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    b.type   = type;
17818b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_AGP_ALLOC, &b))
178250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -errno;
1783ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    if (address != 0UL)
178450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        *address = b.physical;
1785ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    *handle = b.handle;
1786ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    return 0;
1787ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann}
1788ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
1789d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
1790d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1791d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Free a chunk of AGP memory.
1792d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1793d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
1794d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param handle handle to the allocated memory, as given by drmAgpAllocate().
179550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
1796d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success, or a negative value on failure.
179750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
1798d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1799d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_AGP_FREE ioctl, passing the
1800d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * argument in a drm_agp_buffer structure.
1801d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
18027ede209ce0cbbc65f79d02e2cc43cfcb3abb6e99Dave Airlieint drmAgpFree(int fd, drm_handle_t handle)
1803ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann{
1804ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    drm_agp_buffer_t b;
1805ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
1806fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(b);
1807ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    b.handle = handle;
18088b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_AGP_FREE, &b))
180950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -errno;
1810ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    return 0;
1811ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann}
1812ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
1813d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
1814d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1815d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Bind a chunk of AGP memory.
1816d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1817d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
1818d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param handle handle to the allocated memory, as given by drmAgpAllocate().
1819d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param offset offset in bytes. It will round to page boundary.
182050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
1821d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success, or a negative value on failure.
182250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
1823d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1824d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_AGP_BIND ioctl, passing the
1825d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * argument in a drm_agp_binding structure.
1826d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
18277ede209ce0cbbc65f79d02e2cc43cfcb3abb6e99Dave Airlieint drmAgpBind(int fd, drm_handle_t handle, unsigned long offset)
1828ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann{
1829ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    drm_agp_binding_t b;
1830ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
1831fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(b);
1832ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    b.handle = handle;
1833ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    b.offset = offset;
18348b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_AGP_BIND, &b))
183550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -errno;
1836ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    return 0;
1837ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann}
1838ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
1839d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
1840d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1841d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Unbind a chunk of AGP memory.
1842d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1843d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
1844d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param handle handle to the allocated memory, as given by drmAgpAllocate().
184550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
1846d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success, or a negative value on failure.
184750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
1848d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1849d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_AGP_UNBIND ioctl, passing
1850d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * the argument in a drm_agp_binding structure.
1851d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
18527ede209ce0cbbc65f79d02e2cc43cfcb3abb6e99Dave Airlieint drmAgpUnbind(int fd, drm_handle_t handle)
1853ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann{
1854ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    drm_agp_binding_t b;
1855ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
1856fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(b);
1857ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    b.handle = handle;
18588b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_AGP_UNBIND, &b))
185950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -errno;
1860ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    return 0;
1861ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann}
1862ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
1863d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
1864d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1865d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Get AGP driver major version number.
1866d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1867d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
186850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
1869d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return major version number on success, or a negative value on failure..
187050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
1871d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1872d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1873d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * necessary information in a drm_agp_info structure.
1874d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
1875ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmannint drmAgpVersionMajor(int fd)
1876ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann{
1877ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    drm_agp_info_t i;
1878ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
1879fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(i);
1880fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter
18818b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
188250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -errno;
1883ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    return i.agp_version_major;
1884ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann}
1885ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
1886d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
1887d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1888d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Get AGP driver minor version number.
1889d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1890d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
189150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
1892d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return minor version number on success, or a negative value on failure.
189350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
1894d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1895d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1896d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * necessary information in a drm_agp_info structure.
1897d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
1898ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmannint drmAgpVersionMinor(int fd)
1899ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann{
1900ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    drm_agp_info_t i;
1901ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
1902fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(i);
1903fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter
19048b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
190550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -errno;
1906ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    return i.agp_version_minor;
1907ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann}
1908ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
1909d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
1910d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1911d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Get AGP mode.
1912d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1913d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
191450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
1915d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return mode on success, or zero on failure.
191650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
1917d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1918d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1919d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * necessary information in a drm_agp_info structure.
1920d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
1921ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmannunsigned long drmAgpGetMode(int fd)
1922ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann{
1923ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    drm_agp_info_t i;
1924ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
1925fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(i);
1926fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter
19278b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
192850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return 0;
1929ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    return i.mode;
1930ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann}
1931ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
1932d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
1933d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1934d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Get AGP aperture base.
1935d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1936d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
193750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
1938d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return aperture base on success, zero on failure.
193950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
1940d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1941d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1942d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * necessary information in a drm_agp_info structure.
1943d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
1944ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmannunsigned long drmAgpBase(int fd)
1945ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann{
1946ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    drm_agp_info_t i;
1947ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
1948fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(i);
1949fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter
19508b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
195150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return 0;
1952ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    return i.aperture_base;
1953ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann}
1954ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
1955d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
1956d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1957d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Get AGP aperture size.
1958d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1959d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
196050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
1961d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return aperture size on success, zero on failure.
196250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
1963d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1964d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1965d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * necessary information in a drm_agp_info structure.
1966d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
1967ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmannunsigned long drmAgpSize(int fd)
1968ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann{
1969ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    drm_agp_info_t i;
1970ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
1971fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(i);
1972fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter
19738b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
197450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return 0;
1975ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    return i.aperture_size;
1976ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann}
1977ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
1978d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
1979d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1980d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Get used AGP memory.
1981d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1982d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
198350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
1984d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return memory used on success, or zero on failure.
198550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
1986d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1987d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1988d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * necessary information in a drm_agp_info structure.
1989d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
1990ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmannunsigned long drmAgpMemoryUsed(int fd)
1991ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann{
1992ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    drm_agp_info_t i;
1993ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
1994fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(i);
1995fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter
19968b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
199750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return 0;
1998ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    return i.memory_used;
1999ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann}
2000ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
2001d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
2002d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
2003d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Get available AGP memory.
2004d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
2005d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
200650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
2007d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return memory available on success, or zero on failure.
200850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
2009d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
2010d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
2011d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * necessary information in a drm_agp_info structure.
2012d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
2013ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmannunsigned long drmAgpMemoryAvail(int fd)
2014ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann{
2015ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    drm_agp_info_t i;
2016ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
2017fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(i);
2018fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter
20198b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
202050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return 0;
2021ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    return i.memory_allowed;
2022ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann}
2023ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
2024d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
2025d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
2026d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Get hardware vendor ID.
2027d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
2028d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
202950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
2030d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return vendor ID on success, or zero on failure.
203150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
2032d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
2033d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
2034d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * necessary information in a drm_agp_info structure.
2035d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
2036ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmannunsigned int drmAgpVendorId(int fd)
2037ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann{
2038ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    drm_agp_info_t i;
2039ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
2040fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(i);
2041fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter
20428b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
204350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return 0;
2044ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    return i.id_vendor;
2045ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann}
2046ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
2047d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
2048d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
2049d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Get hardware device ID.
2050d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
2051d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
205250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
2053d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success, or zero on failure.
205450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
2055d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
2056d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
2057d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * necessary information in a drm_agp_info structure.
2058d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
2059ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmannunsigned int drmAgpDeviceId(int fd)
2060ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann{
2061ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    drm_agp_info_t i;
2062ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
2063fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(i);
2064fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter
20658b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
206650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return 0;
2067ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    return i.id_device;
2068ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann}
2069ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
20707ede209ce0cbbc65f79d02e2cc43cfcb3abb6e99Dave Airlieint drmScatterGatherAlloc(int fd, unsigned long size, drm_handle_t *handle)
20715d6ddbca26d695561fb1d08d798a0cc254b805e7Kevin E Martin{
20725d6ddbca26d695561fb1d08d798a0cc254b805e7Kevin E Martin    drm_scatter_gather_t sg;
20735d6ddbca26d695561fb1d08d798a0cc254b805e7Kevin E Martin
2074fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(sg);
2075fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter
20765d6ddbca26d695561fb1d08d798a0cc254b805e7Kevin E Martin    *handle = 0;
20775d6ddbca26d695561fb1d08d798a0cc254b805e7Kevin E Martin    sg.size   = size;
20788b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_SG_ALLOC, &sg))
207950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -errno;
20805d6ddbca26d695561fb1d08d798a0cc254b805e7Kevin E Martin    *handle = sg.handle;
20815d6ddbca26d695561fb1d08d798a0cc254b805e7Kevin E Martin    return 0;
20825d6ddbca26d695561fb1d08d798a0cc254b805e7Kevin E Martin}
20835d6ddbca26d695561fb1d08d798a0cc254b805e7Kevin E Martin
20847ede209ce0cbbc65f79d02e2cc43cfcb3abb6e99Dave Airlieint drmScatterGatherFree(int fd, drm_handle_t handle)
20855d6ddbca26d695561fb1d08d798a0cc254b805e7Kevin E Martin{
20865d6ddbca26d695561fb1d08d798a0cc254b805e7Kevin E Martin    drm_scatter_gather_t sg;
20875d6ddbca26d695561fb1d08d798a0cc254b805e7Kevin E Martin
2088fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(sg);
20895d6ddbca26d695561fb1d08d798a0cc254b805e7Kevin E Martin    sg.handle = handle;
20908b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_SG_FREE, &sg))
209150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -errno;
20925d6ddbca26d695561fb1d08d798a0cc254b805e7Kevin E Martin    return 0;
20935d6ddbca26d695561fb1d08d798a0cc254b805e7Kevin E Martin}
20945d6ddbca26d695561fb1d08d798a0cc254b805e7Kevin E Martin
2095d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
2096d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Wait for VBLANK.
2097d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
2098d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
2099d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param vbl pointer to a drmVBlank structure.
210050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
2101d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success, or a negative value on failure.
210250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
2103d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
2104d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_WAIT_VBLANK ioctl.
2105d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
210655acd0d5a64a2ee6b0cecc75872fbf8c4bb42a0cMichel Daenzerint drmWaitVBlank(int fd, drmVBlankPtr vbl)
210755acd0d5a64a2ee6b0cecc75872fbf8c4bb42a0cMichel Daenzer{
2108f4f76a6894b40abd77f0ffbf52972127608b9bcaJesse Barnes    struct timespec timeout, cur;
210955acd0d5a64a2ee6b0cecc75872fbf8c4bb42a0cMichel Daenzer    int ret;
211055acd0d5a64a2ee6b0cecc75872fbf8c4bb42a0cMichel Daenzer
2111f4f76a6894b40abd77f0ffbf52972127608b9bcaJesse Barnes    ret = clock_gettime(CLOCK_MONOTONIC, &timeout);
2112f4f76a6894b40abd77f0ffbf52972127608b9bcaJesse Barnes    if (ret < 0) {
211350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        fprintf(stderr, "clock_gettime failed: %s\n", strerror(errno));
211450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        goto out;
2115f4f76a6894b40abd77f0ffbf52972127608b9bcaJesse Barnes    }
2116f4f76a6894b40abd77f0ffbf52972127608b9bcaJesse Barnes    timeout.tv_sec++;
2117f4f76a6894b40abd77f0ffbf52972127608b9bcaJesse Barnes
211855acd0d5a64a2ee6b0cecc75872fbf8c4bb42a0cMichel Daenzer    do {
2119f4f76a6894b40abd77f0ffbf52972127608b9bcaJesse Barnes       ret = ioctl(fd, DRM_IOCTL_WAIT_VBLANK, vbl);
2120c7d471b6ae936127311a816a8d15b4565746af48Michel Daenzer       vbl->request.type &= ~DRM_VBLANK_RELATIVE;
2121ca37077fb78b69a00500827f1db12b70affa1514Jesse Barnes       if (ret && errno == EINTR) {
212250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely           clock_gettime(CLOCK_MONOTONIC, &cur);
212350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely           /* Timeout after 1s */
212450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely           if (cur.tv_sec > timeout.tv_sec + 1 ||
212550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely               (cur.tv_sec == timeout.tv_sec && cur.tv_nsec >=
212650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                timeout.tv_nsec)) {
212750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                   errno = EBUSY;
212850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                   ret = -1;
212950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                   break;
213050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely           }
2131f4f76a6894b40abd77f0ffbf52972127608b9bcaJesse Barnes       }
213255acd0d5a64a2ee6b0cecc75872fbf8c4bb42a0cMichel Daenzer    } while (ret && errno == EINTR);
213355acd0d5a64a2ee6b0cecc75872fbf8c4bb42a0cMichel Daenzer
2134f4f76a6894b40abd77f0ffbf52972127608b9bcaJesse Barnesout:
213555acd0d5a64a2ee6b0cecc75872fbf8c4bb42a0cMichel Daenzer    return ret;
213655acd0d5a64a2ee6b0cecc75872fbf8c4bb42a0cMichel Daenzer}
213755acd0d5a64a2ee6b0cecc75872fbf8c4bb42a0cMichel Daenzer
2138b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Straussint drmError(int err, const char *label)
2139b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
2140b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    switch (err) {
2141ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    case DRM_ERR_NO_DEVICE:
214250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        fprintf(stderr, "%s: no device\n", label);
214350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        break;
2144ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    case DRM_ERR_NO_ACCESS:
214550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        fprintf(stderr, "%s: no access\n", label);
214650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        break;
2147ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    case DRM_ERR_NOT_ROOT:
214850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        fprintf(stderr, "%s: not root\n", label);
214950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        break;
2150ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    case DRM_ERR_INVALID:
215150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        fprintf(stderr, "%s: invalid args\n", label);
215250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        break;
2153b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    default:
215450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        if (err < 0)
215550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            err = -err;
215650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        fprintf( stderr, "%s: error %d (%s)\n", label, err, strerror(err) );
215750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        break;
2158b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    }
2159b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
2160b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return 1;
2161b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
2162b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
2163d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
2164d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Install IRQ handler.
2165d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
2166d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
2167d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param irq IRQ number.
216850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
2169d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success, or a negative value on failure.
217050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
2171d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
2172d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_CONTROL ioctl, passing the
2173d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * argument in a drm_control structure.
2174d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
2175b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Straussint drmCtlInstHandler(int fd, int irq)
2176b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
2177b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_control_t ctl;
2178b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
2179fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(ctl);
2180b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    ctl.func  = DRM_INST_HANDLER;
2181b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    ctl.irq   = irq;
21828b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_CONTROL, &ctl))
218350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -errno;
2184b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return 0;
2185b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
2186b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
2187d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
2188d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
2189d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Uninstall IRQ handler.
2190d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
2191d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
219250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
2193d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success, or a negative value on failure.
219450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
2195d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
2196d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_CONTROL ioctl, passing the
2197d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * argument in a drm_control structure.
2198d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
2199b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Straussint drmCtlUninstHandler(int fd)
2200b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
2201b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_control_t ctl;
2202b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
2203fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(ctl);
2204b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    ctl.func  = DRM_UNINST_HANDLER;
2205b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    ctl.irq   = 0;
22068b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_CONTROL, &ctl))
220750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -errno;
2208b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return 0;
2209b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
2210b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
2211b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Straussint drmFinish(int fd, int context, drmLockFlags flags)
2212b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
2213b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_lock_t lock;
2214b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
2215fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(lock);
2216b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    lock.context = context;
2217b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    if (flags & DRM_LOCK_READY)      lock.flags |= _DRM_LOCK_READY;
2218b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    if (flags & DRM_LOCK_QUIESCENT)  lock.flags |= _DRM_LOCK_QUIESCENT;
2219b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    if (flags & DRM_LOCK_FLUSH)      lock.flags |= _DRM_LOCK_FLUSH;
2220b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    if (flags & DRM_LOCK_FLUSH_ALL)  lock.flags |= _DRM_LOCK_FLUSH_ALL;
2221b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    if (flags & DRM_HALT_ALL_QUEUES) lock.flags |= _DRM_HALT_ALL_QUEUES;
2222b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    if (flags & DRM_HALT_CUR_QUEUES) lock.flags |= _DRM_HALT_CUR_QUEUES;
22238b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_FINISH, &lock))
222450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -errno;
2225b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return 0;
2226b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
2227b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
2228d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
2229d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Get IRQ from bus ID.
2230d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
2231d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
2232d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param busnum bus number.
2233d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param devnum device number.
2234d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param funcnum function number.
223550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
2236d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return IRQ number on success, or a negative value on failure.
223750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
2238d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
2239d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_IRQ_BUSID ioctl, passing the
2240d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * arguments in a drm_irq_busid structure.
2241d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
2242b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Straussint drmGetInterruptFromBusID(int fd, int busnum, int devnum, int funcnum)
2243b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
2244b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_irq_busid_t p;
2245b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
2246fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(p);
2247b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    p.busnum  = busnum;
2248b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    p.devnum  = devnum;
2249b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    p.funcnum = funcnum;
22508b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_IRQ_BUSID, &p))
225150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -errno;
2252b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return p.irq;
2253b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
2254b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
22558696e71db2d79eb318c00abde625d7b61d6800a1Jon Smirlint drmAddContextTag(int fd, drm_context_t context, void *tag)
2256b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
2257b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drmHashEntry  *entry = drmGetEntry(fd);
2258b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
2259b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    if (drmHashInsert(entry->tagTable, context, tag)) {
226050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        drmHashDelete(entry->tagTable, context);
226150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        drmHashInsert(entry->tagTable, context, tag);
2262b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    }
2263b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return 0;
2264b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
2265b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
22668696e71db2d79eb318c00abde625d7b61d6800a1Jon Smirlint drmDelContextTag(int fd, drm_context_t context)
2267b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
2268b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drmHashEntry  *entry = drmGetEntry(fd);
2269b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
2270b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return drmHashDelete(entry->tagTable, context);
2271b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
2272b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
22738696e71db2d79eb318c00abde625d7b61d6800a1Jon Smirlvoid *drmGetContextTag(int fd, drm_context_t context)
2274b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
2275b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drmHashEntry  *entry = drmGetEntry(fd);
2276b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    void          *value;
2277360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes
2278ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    if (drmHashLookup(entry->tagTable, context, &value))
227950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return NULL;
2280b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
2281b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return value;
2282b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
2283b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
228422e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jacksonint drmAddContextPrivateMapping(int fd, drm_context_t ctx_id,
228522e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jackson                                drm_handle_t handle)
228674e19a40187ac3b5907922e5dc01418135a5794bKevin E Martin{
228774e19a40187ac3b5907922e5dc01418135a5794bKevin E Martin    drm_ctx_priv_map_t map;
228874e19a40187ac3b5907922e5dc01418135a5794bKevin E Martin
2289fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(map);
229074e19a40187ac3b5907922e5dc01418135a5794bKevin E Martin    map.ctx_id = ctx_id;
2291961bf9b5c2866ccb4fedf2b45b29fb688519d0dbJeremy Huddleston    map.handle = (void *)(uintptr_t)handle;
229274e19a40187ac3b5907922e5dc01418135a5794bKevin E Martin
22938b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_SET_SAREA_CTX, &map))
229450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -errno;
229574e19a40187ac3b5907922e5dc01418135a5794bKevin E Martin    return 0;
229674e19a40187ac3b5907922e5dc01418135a5794bKevin E Martin}
229774e19a40187ac3b5907922e5dc01418135a5794bKevin E Martin
229822e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jacksonint drmGetContextPrivateMapping(int fd, drm_context_t ctx_id,
229922e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jackson                                drm_handle_t *handle)
230074e19a40187ac3b5907922e5dc01418135a5794bKevin E Martin{
230174e19a40187ac3b5907922e5dc01418135a5794bKevin E Martin    drm_ctx_priv_map_t map;
230274e19a40187ac3b5907922e5dc01418135a5794bKevin E Martin
2303fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(map);
230474e19a40187ac3b5907922e5dc01418135a5794bKevin E Martin    map.ctx_id = ctx_id;
230574e19a40187ac3b5907922e5dc01418135a5794bKevin E Martin
23068b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_GET_SAREA_CTX, &map))
230750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -errno;
2308ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    if (handle)
230950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        *handle = (drm_handle_t)(uintptr_t)map.handle;
231074e19a40187ac3b5907922e5dc01418135a5794bKevin E Martin
231174e19a40187ac3b5907922e5dc01418135a5794bKevin E Martin    return 0;
231274e19a40187ac3b5907922e5dc01418135a5794bKevin E Martin}
231374e19a40187ac3b5907922e5dc01418135a5794bKevin E Martin
23148696e71db2d79eb318c00abde625d7b61d6800a1Jon Smirlint drmGetMap(int fd, int idx, drm_handle_t *offset, drmSize *size,
231550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely              drmMapType *type, drmMapFlags *flags, drm_handle_t *handle,
231650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely              int *mtrr)
231788dbee54ed400a3fd5594fab506518c171167805Rik Faith{
231888dbee54ed400a3fd5594fab506518c171167805Rik Faith    drm_map_t map;
231988dbee54ed400a3fd5594fab506518c171167805Rik Faith
2320fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(map);
232188dbee54ed400a3fd5594fab506518c171167805Rik Faith    map.offset = idx;
23228b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_GET_MAP, &map))
232350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -errno;
232488dbee54ed400a3fd5594fab506518c171167805Rik Faith    *offset = map.offset;
232588dbee54ed400a3fd5594fab506518c171167805Rik Faith    *size   = map.size;
232688dbee54ed400a3fd5594fab506518c171167805Rik Faith    *type   = map.type;
232788dbee54ed400a3fd5594fab506518c171167805Rik Faith    *flags  = map.flags;
232888dbee54ed400a3fd5594fab506518c171167805Rik Faith    *handle = (unsigned long)map.handle;
232988dbee54ed400a3fd5594fab506518c171167805Rik Faith    *mtrr   = map.mtrr;
233088dbee54ed400a3fd5594fab506518c171167805Rik Faith    return 0;
233188dbee54ed400a3fd5594fab506518c171167805Rik Faith}
233288dbee54ed400a3fd5594fab506518c171167805Rik Faith
233388dbee54ed400a3fd5594fab506518c171167805Rik Faithint drmGetClient(int fd, int idx, int *auth, int *pid, int *uid,
233450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                 unsigned long *magic, unsigned long *iocs)
233588dbee54ed400a3fd5594fab506518c171167805Rik Faith{
233688dbee54ed400a3fd5594fab506518c171167805Rik Faith    drm_client_t client;
233788dbee54ed400a3fd5594fab506518c171167805Rik Faith
2338fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(client);
233988dbee54ed400a3fd5594fab506518c171167805Rik Faith    client.idx = idx;
23408b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_GET_CLIENT, &client))
234150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -errno;
234288dbee54ed400a3fd5594fab506518c171167805Rik Faith    *auth      = client.auth;
234388dbee54ed400a3fd5594fab506518c171167805Rik Faith    *pid       = client.pid;
234488dbee54ed400a3fd5594fab506518c171167805Rik Faith    *uid       = client.uid;
234588dbee54ed400a3fd5594fab506518c171167805Rik Faith    *magic     = client.magic;
234688dbee54ed400a3fd5594fab506518c171167805Rik Faith    *iocs      = client.iocs;
234788dbee54ed400a3fd5594fab506518c171167805Rik Faith    return 0;
234888dbee54ed400a3fd5594fab506518c171167805Rik Faith}
234988dbee54ed400a3fd5594fab506518c171167805Rik Faith
235088dbee54ed400a3fd5594fab506518c171167805Rik Faithint drmGetStats(int fd, drmStatsT *stats)
235188dbee54ed400a3fd5594fab506518c171167805Rik Faith{
235288dbee54ed400a3fd5594fab506518c171167805Rik Faith    drm_stats_t s;
2353de8532dd8359dfdaba839ff61fc9e2f05eaf57d3Jan Vesely    unsigned    i;
235488dbee54ed400a3fd5594fab506518c171167805Rik Faith
2355fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(s);
23568b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_GET_STATS, &s))
235750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -errno;
235888dbee54ed400a3fd5594fab506518c171167805Rik Faith
235988dbee54ed400a3fd5594fab506518c171167805Rik Faith    stats->count = 0;
236088dbee54ed400a3fd5594fab506518c171167805Rik Faith    memset(stats, 0, sizeof(*stats));
236188dbee54ed400a3fd5594fab506518c171167805Rik Faith    if (s.count > sizeof(stats->data)/sizeof(stats->data[0]))
236250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -1;
236388dbee54ed400a3fd5594fab506518c171167805Rik Faith
236488dbee54ed400a3fd5594fab506518c171167805Rik Faith#define SET_VALUE                              \
236588dbee54ed400a3fd5594fab506518c171167805Rik Faith    stats->data[i].long_format = "%-20.20s";   \
236688dbee54ed400a3fd5594fab506518c171167805Rik Faith    stats->data[i].rate_format = "%8.8s";      \
236788dbee54ed400a3fd5594fab506518c171167805Rik Faith    stats->data[i].isvalue     = 1;            \
236888dbee54ed400a3fd5594fab506518c171167805Rik Faith    stats->data[i].verbose     = 0
236988dbee54ed400a3fd5594fab506518c171167805Rik Faith
237088dbee54ed400a3fd5594fab506518c171167805Rik Faith#define SET_COUNT                              \
237188dbee54ed400a3fd5594fab506518c171167805Rik Faith    stats->data[i].long_format = "%-20.20s";   \
237288dbee54ed400a3fd5594fab506518c171167805Rik Faith    stats->data[i].rate_format = "%5.5s";      \
237388dbee54ed400a3fd5594fab506518c171167805Rik Faith    stats->data[i].isvalue     = 0;            \
237488dbee54ed400a3fd5594fab506518c171167805Rik Faith    stats->data[i].mult_names  = "kgm";        \
237588dbee54ed400a3fd5594fab506518c171167805Rik Faith    stats->data[i].mult        = 1000;         \
237688dbee54ed400a3fd5594fab506518c171167805Rik Faith    stats->data[i].verbose     = 0
237788dbee54ed400a3fd5594fab506518c171167805Rik Faith
237888dbee54ed400a3fd5594fab506518c171167805Rik Faith#define SET_BYTE                               \
237988dbee54ed400a3fd5594fab506518c171167805Rik Faith    stats->data[i].long_format = "%-20.20s";   \
238088dbee54ed400a3fd5594fab506518c171167805Rik Faith    stats->data[i].rate_format = "%5.5s";      \
238188dbee54ed400a3fd5594fab506518c171167805Rik Faith    stats->data[i].isvalue     = 0;            \
238288dbee54ed400a3fd5594fab506518c171167805Rik Faith    stats->data[i].mult_names  = "KGM";        \
238388dbee54ed400a3fd5594fab506518c171167805Rik Faith    stats->data[i].mult        = 1024;         \
238488dbee54ed400a3fd5594fab506518c171167805Rik Faith    stats->data[i].verbose     = 0
238588dbee54ed400a3fd5594fab506518c171167805Rik Faith
238688dbee54ed400a3fd5594fab506518c171167805Rik Faith
238788dbee54ed400a3fd5594fab506518c171167805Rik Faith    stats->count = s.count;
238888dbee54ed400a3fd5594fab506518c171167805Rik Faith    for (i = 0; i < s.count; i++) {
238950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        stats->data[i].value = s.data[i].value;
239050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        switch (s.data[i].type) {
239150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        case _DRM_STAT_LOCK:
239250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            stats->data[i].long_name = "Lock";
239350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            stats->data[i].rate_name = "Lock";
239450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            SET_VALUE;
239550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            break;
239650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        case _DRM_STAT_OPENS:
239750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            stats->data[i].long_name = "Opens";
239850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            stats->data[i].rate_name = "O";
239950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            SET_COUNT;
240050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            stats->data[i].verbose   = 1;
240150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            break;
240250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        case _DRM_STAT_CLOSES:
240350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            stats->data[i].long_name = "Closes";
240450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            stats->data[i].rate_name = "Lock";
240550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            SET_COUNT;
240650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            stats->data[i].verbose   = 1;
240750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            break;
240850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        case _DRM_STAT_IOCTLS:
240950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            stats->data[i].long_name = "Ioctls";
241050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            stats->data[i].rate_name = "Ioc/s";
241150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            SET_COUNT;
241250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            break;
241350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        case _DRM_STAT_LOCKS:
241450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            stats->data[i].long_name = "Locks";
241550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            stats->data[i].rate_name = "Lck/s";
241650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            SET_COUNT;
241750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            break;
241850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        case _DRM_STAT_UNLOCKS:
241950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            stats->data[i].long_name = "Unlocks";
242050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            stats->data[i].rate_name = "Unl/s";
242150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            SET_COUNT;
242250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            break;
242350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        case _DRM_STAT_IRQ:
242450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            stats->data[i].long_name = "IRQs";
242550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            stats->data[i].rate_name = "IRQ/s";
242650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            SET_COUNT;
242750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            break;
242850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        case _DRM_STAT_PRIMARY:
242950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            stats->data[i].long_name = "Primary Bytes";
243050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            stats->data[i].rate_name = "PB/s";
243150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            SET_BYTE;
243250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            break;
243350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        case _DRM_STAT_SECONDARY:
243450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            stats->data[i].long_name = "Secondary Bytes";
243550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            stats->data[i].rate_name = "SB/s";
243650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            SET_BYTE;
243750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            break;
243850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        case _DRM_STAT_DMA:
243950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            stats->data[i].long_name = "DMA";
244050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            stats->data[i].rate_name = "DMA/s";
244150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            SET_COUNT;
244250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            break;
244350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        case _DRM_STAT_SPECIAL:
244450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            stats->data[i].long_name = "Special DMA";
244550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            stats->data[i].rate_name = "dma/s";
244650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            SET_COUNT;
244750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            break;
244850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        case _DRM_STAT_MISSED:
244950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            stats->data[i].long_name = "Miss";
245050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            stats->data[i].rate_name = "Ms/s";
245150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            SET_COUNT;
245250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            break;
245350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        case _DRM_STAT_VALUE:
245450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            stats->data[i].long_name = "Value";
245550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            stats->data[i].rate_name = "Value";
245650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            SET_VALUE;
245750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            break;
245850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        case _DRM_STAT_BYTE:
245950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            stats->data[i].long_name = "Bytes";
246050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            stats->data[i].rate_name = "B/s";
246150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            SET_BYTE;
246250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            break;
246350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        case _DRM_STAT_COUNT:
246450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        default:
246550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            stats->data[i].long_name = "Count";
246650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            stats->data[i].rate_name = "Cnt/s";
246750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            SET_COUNT;
246850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            break;
246950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        }
247088dbee54ed400a3fd5594fab506518c171167805Rik Faith    }
247188dbee54ed400a3fd5594fab506518c171167805Rik Faith    return 0;
247288dbee54ed400a3fd5594fab506518c171167805Rik Faith}
247388dbee54ed400a3fd5594fab506518c171167805Rik Faith
2474d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
247506cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt * Issue a set-version ioctl.
247606cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt *
247706cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt * \param fd file descriptor.
247850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely * \param drmCommandIndex command index
247906cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt * \param data source pointer of the data to be read and written.
248006cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt * \param size size of the data to be read and written.
248150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
248206cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt * \return zero on success, or a negative value on failure.
248350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
248406cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt * \internal
248550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely * It issues a read-write ioctl given by
248606cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
248706cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt */
248822e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jacksonint drmSetInterfaceVersion(int fd, drmSetVersion *version)
248906cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt{
249006cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    int retcode = 0;
249106cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    drm_set_version_t sv;
249206cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt
2493fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(sv);
249406cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    sv.drm_di_major = version->drm_di_major;
249506cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    sv.drm_di_minor = version->drm_di_minor;
249606cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    sv.drm_dd_major = version->drm_dd_major;
249706cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    sv.drm_dd_minor = version->drm_dd_minor;
249806cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt
24998b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_SET_VERSION, &sv)) {
250050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        retcode = -errno;
250106cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    }
250206cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt
250306cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    version->drm_di_major = sv.drm_di_major;
250406cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    version->drm_di_minor = sv.drm_di_minor;
250506cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    version->drm_dd_major = sv.drm_dd_major;
250606cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    version->drm_dd_minor = sv.drm_dd_minor;
250706cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt
250806cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    return retcode;
250906cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt}
251006cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt
251106cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt/**
2512d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Send a device-specific command.
2513d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
2514d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
251550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely * \param drmCommandIndex command index
251650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
2517d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success, or a negative value on failure.
251850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
2519d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
252050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely * It issues a ioctl given by
2521d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
2522d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
25233903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owenint drmCommandNone(int fd, unsigned long drmCommandIndex)
25243903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen{
25253903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen    unsigned long request;
25263903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen
25273903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen    request = DRM_IO( DRM_COMMAND_BASE + drmCommandIndex);
25283903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen
2529fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    if (drmIoctl(fd, request, NULL)) {
253050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -errno;
25313903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen    }
25323903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen    return 0;
25333903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen}
25343903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen
2535d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
2536d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
2537d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Send a device-specific read command.
2538d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
2539d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
254050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely * \param drmCommandIndex command index
2541d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param data destination pointer of the data to be read.
2542d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param size size of the data to be read.
254350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
2544d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success, or a negative value on failure.
2545d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
2546d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
254750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely * It issues a read ioctl given by
2548d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
2549d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
255022e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jacksonint drmCommandRead(int fd, unsigned long drmCommandIndex, void *data,
255122e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jackson                   unsigned long size)
25523903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen{
25533903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen    unsigned long request;
25543903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen
255550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    request = DRM_IOC( DRM_IOC_READ, DRM_IOCTL_BASE,
255650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        DRM_COMMAND_BASE + drmCommandIndex, size);
25573903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen
25588b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, request, data)) {
255950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -errno;
25603903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen    }
25613903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen    return 0;
25623903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen}
25633903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen
2564d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
2565d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
2566d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Send a device-specific write command.
2567d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
2568d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
256950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely * \param drmCommandIndex command index
2570d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param data source pointer of the data to be written.
2571d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param size size of the data to be written.
257250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
2573d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success, or a negative value on failure.
257450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
2575d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
257650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely * It issues a write ioctl given by
2577d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
2578d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
257922e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jacksonint drmCommandWrite(int fd, unsigned long drmCommandIndex, void *data,
258022e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jackson                    unsigned long size)
25813903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen{
25823903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen    unsigned long request;
25833903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen
258450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    request = DRM_IOC( DRM_IOC_WRITE, DRM_IOCTL_BASE,
258550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        DRM_COMMAND_BASE + drmCommandIndex, size);
25863903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen
25878b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, request, data)) {
258850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -errno;
25893903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen    }
25903903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen    return 0;
25913903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen}
25923903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen
2593d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
2594d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
2595d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Send a device-specific read-write command.
2596d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
2597d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
259850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely * \param drmCommandIndex command index
2599d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param data source pointer of the data to be read and written.
2600d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param size size of the data to be read and written.
260150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
2602d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success, or a negative value on failure.
260350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely *
2604d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
260550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely * It issues a read-write ioctl given by
2606d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
2607d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
260822e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jacksonint drmCommandWriteRead(int fd, unsigned long drmCommandIndex, void *data,
260922e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jackson                        unsigned long size)
26103903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen{
26113903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen    unsigned long request;
26123903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen
261350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    request = DRM_IOC( DRM_IOC_READ|DRM_IOC_WRITE, DRM_IOCTL_BASE,
261450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        DRM_COMMAND_BASE + drmCommandIndex, size);
26153903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen
26168b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, request, data))
261750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -errno;
26183903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen    return 0;
26193903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen}
2620166da9355d95affe427a6cff3525df60e80a99dfThomas Hellstrom
2621d51e1bb56ca2f7858cdeac6f61a7b747c1e15b1eDave Airlie#define DRM_MAX_FDS 16
2622d51e1bb56ca2f7858cdeac6f61a7b747c1e15b1eDave Airliestatic struct {
2623ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    char *BusID;
2624ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    int fd;
2625ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    int refcount;
2626dbc8b11db6f3fcbe2a76487bb0b1930908226a17Jammy Zhou    int type;
2627d51e1bb56ca2f7858cdeac6f61a7b747c1e15b1eDave Airlie} connection[DRM_MAX_FDS];
2628d51e1bb56ca2f7858cdeac6f61a7b747c1e15b1eDave Airlie
2629d51e1bb56ca2f7858cdeac6f61a7b747c1e15b1eDave Airliestatic int nr_fds = 0;
2630d51e1bb56ca2f7858cdeac6f61a7b747c1e15b1eDave Airlie
263150d3c85bdb4ac0b3d546336605a722889aff7066Jan Veselyint drmOpenOnce(void *unused,
263250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                const char *BusID,
263350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                int *newlyopened)
2634d51e1bb56ca2f7858cdeac6f61a7b747c1e15b1eDave Airlie{
2635dbc8b11db6f3fcbe2a76487bb0b1930908226a17Jammy Zhou    return drmOpenOnceWithType(BusID, newlyopened, DRM_NODE_PRIMARY);
2636dbc8b11db6f3fcbe2a76487bb0b1930908226a17Jammy Zhou}
2637dbc8b11db6f3fcbe2a76487bb0b1930908226a17Jammy Zhou
2638dbc8b11db6f3fcbe2a76487bb0b1930908226a17Jammy Zhouint drmOpenOnceWithType(const char *BusID, int *newlyopened, int type)
2639dbc8b11db6f3fcbe2a76487bb0b1930908226a17Jammy Zhou{
2640ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    int i;
2641ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    int fd;
264250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely
2643ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    for (i = 0; i < nr_fds; i++)
264450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        if ((strcmp(BusID, connection[i].BusID) == 0) &&
264550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            (connection[i].type == type)) {
264650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            connection[i].refcount++;
264750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            *newlyopened = 0;
264850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            return connection[i].fd;
264950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        }
2650ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian
2651dbc8b11db6f3fcbe2a76487bb0b1930908226a17Jammy Zhou    fd = drmOpenWithType(NULL, BusID, type);
2652c1cd3d93881a9b4a27f7190393ccc7a0236d28a4Emil Velikov    if (fd < 0 || nr_fds == DRM_MAX_FDS)
265350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return fd;
265450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely
2655ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    connection[nr_fds].BusID = strdup(BusID);
2656ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    connection[nr_fds].fd = fd;
2657ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    connection[nr_fds].refcount = 1;
2658dbc8b11db6f3fcbe2a76487bb0b1930908226a17Jammy Zhou    connection[nr_fds].type = type;
2659ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    *newlyopened = 1;
2660d51e1bb56ca2f7858cdeac6f61a7b747c1e15b1eDave Airlie
2661ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    if (0)
266250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        fprintf(stderr, "saved connection %d for %s %d\n",
266350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                nr_fds, connection[nr_fds].BusID,
266450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                strcmp(BusID, connection[nr_fds].BusID));
2665d51e1bb56ca2f7858cdeac6f61a7b747c1e15b1eDave Airlie
2666ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    nr_fds++;
2667d51e1bb56ca2f7858cdeac6f61a7b747c1e15b1eDave Airlie
2668ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    return fd;
2669d51e1bb56ca2f7858cdeac6f61a7b747c1e15b1eDave Airlie}
2670d51e1bb56ca2f7858cdeac6f61a7b747c1e15b1eDave Airlie
2671d51e1bb56ca2f7858cdeac6f61a7b747c1e15b1eDave Airlievoid drmCloseOnce(int fd)
2672d51e1bb56ca2f7858cdeac6f61a7b747c1e15b1eDave Airlie{
2673ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    int i;
2674d51e1bb56ca2f7858cdeac6f61a7b747c1e15b1eDave Airlie
2675ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    for (i = 0; i < nr_fds; i++) {
267650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        if (fd == connection[i].fd) {
267750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            if (--connection[i].refcount == 0) {
267850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                drmClose(connection[i].fd);
267950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                free(connection[i].BusID);
268050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely
268150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                if (i < --nr_fds)
268250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                    connection[i] = connection[nr_fds];
268350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely
268450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                return;
268550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            }
268650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        }
2687ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    }
2688d51e1bb56ca2f7858cdeac6f61a7b747c1e15b1eDave Airlie}
2689731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
2690731cd5526e5c732d51307b26e784f454a724a699Jesse Barnesint drmSetMaster(int fd)
2691731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes{
269250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return drmIoctl(fd, DRM_IOCTL_SET_MASTER, NULL);
2693731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes}
2694731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
2695731cd5526e5c732d51307b26e784f454a724a699Jesse Barnesint drmDropMaster(int fd)
2696731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes{
269750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return drmIoctl(fd, DRM_IOCTL_DROP_MASTER, NULL);
2698731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes}
269922d46669043d38fcd16efca773f5ed5693c0fb58Kristian Høgsberg
270022d46669043d38fcd16efca773f5ed5693c0fb58Kristian Høgsbergchar *drmGetDeviceNameFromFd(int fd)
270122d46669043d38fcd16efca773f5ed5693c0fb58Kristian Høgsberg{
270250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    char name[128];
270350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    struct stat sbuf;
270450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    dev_t d;
270550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    int i;
270622d46669043d38fcd16efca773f5ed5693c0fb58Kristian Høgsberg
270750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    /* The whole drmOpen thing is a fiasco and we need to find a way
270850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely     * back to just using open(2).  For now, however, lets just make
270950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely     * things worse with even more ad hoc directory walking code to
271050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely     * discover the device file name. */
271122d46669043d38fcd16efca773f5ed5693c0fb58Kristian Høgsberg
271250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    fstat(fd, &sbuf);
271350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    d = sbuf.st_rdev;
271422d46669043d38fcd16efca773f5ed5693c0fb58Kristian Høgsberg
271550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    for (i = 0; i < DRM_MAX_MINOR; i++) {
271650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        snprintf(name, sizeof name, DRM_DEV_NAME, DRM_DIR_NAME, i);
271750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        if (stat(name, &sbuf) == 0 && sbuf.st_rdev == d)
271850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            break;
271950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    }
272050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    if (i == DRM_MAX_MINOR)
272150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return NULL;
272222d46669043d38fcd16efca773f5ed5693c0fb58Kristian Høgsberg
272350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    return strdup(name);
272422d46669043d38fcd16efca773f5ed5693c0fb58Kristian Høgsberg}
2725cc0a14575d9fd0aafe73cb4aa445eaf024436114Dave Airlie
27261f73578df32f895a678a41758f6c563f49484347Frank Binnsint drmGetNodeTypeFromFd(int fd)
27271f73578df32f895a678a41758f6c563f49484347Frank Binns{
272850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    struct stat sbuf;
272950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    int maj, min, type;
27301f73578df32f895a678a41758f6c563f49484347Frank Binns
273150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    if (fstat(fd, &sbuf))
273250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -1;
27331f73578df32f895a678a41758f6c563f49484347Frank Binns
273450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    maj = major(sbuf.st_rdev);
273550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    min = minor(sbuf.st_rdev);
27361f73578df32f895a678a41758f6c563f49484347Frank Binns
273750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode)) {
273850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        errno = EINVAL;
273950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return -1;
274050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    }
27411f73578df32f895a678a41758f6c563f49484347Frank Binns
274250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    type = drmGetMinorType(min);
274350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    if (type == -1)
274450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        errno = ENODEV;
274550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    return type;
27461f73578df32f895a678a41758f6c563f49484347Frank Binns}
27471f73578df32f895a678a41758f6c563f49484347Frank Binns
2748cc0a14575d9fd0aafe73cb4aa445eaf024436114Dave Airlieint drmPrimeHandleToFD(int fd, uint32_t handle, uint32_t flags, int *prime_fd)
2749cc0a14575d9fd0aafe73cb4aa445eaf024436114Dave Airlie{
275050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    struct drm_prime_handle args;
275150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    int ret;
2752cc0a14575d9fd0aafe73cb4aa445eaf024436114Dave Airlie
275350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    memclear(args);
275450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    args.fd = -1;
275550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    args.handle = handle;
275650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    args.flags = flags;
275750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    ret = drmIoctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &args);
275850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    if (ret)
275950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return ret;
2760cc0a14575d9fd0aafe73cb4aa445eaf024436114Dave Airlie
276150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    *prime_fd = args.fd;
276250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    return 0;
2763cc0a14575d9fd0aafe73cb4aa445eaf024436114Dave Airlie}
2764cc0a14575d9fd0aafe73cb4aa445eaf024436114Dave Airlie
2765cc0a14575d9fd0aafe73cb4aa445eaf024436114Dave Airlieint drmPrimeFDToHandle(int fd, int prime_fd, uint32_t *handle)
2766cc0a14575d9fd0aafe73cb4aa445eaf024436114Dave Airlie{
276750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    struct drm_prime_handle args;
276850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    int ret;
2769cc0a14575d9fd0aafe73cb4aa445eaf024436114Dave Airlie
277050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    memclear(args);
277150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    args.fd = prime_fd;
277250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    ret = drmIoctl(fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &args);
277350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    if (ret)
277450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return ret;
2775cc0a14575d9fd0aafe73cb4aa445eaf024436114Dave Airlie
277650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    *handle = args.handle;
277750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    return 0;
2778cc0a14575d9fd0aafe73cb4aa445eaf024436114Dave Airlie}
2779cc0a14575d9fd0aafe73cb4aa445eaf024436114Dave Airlie
27800ca03a4087a550646de7f26b6b53a932e8546474Emil Velikovstatic char *drmGetMinorNameForFD(int fd, int type)
27810ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov{
27820ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov#ifdef __linux__
278350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    DIR *sysdir;
278450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    struct dirent *pent, *ent;
278550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    struct stat sbuf;
278650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    const char *name = drmGetMinorName(type);
278750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    int len;
278850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    char dev_name[64], buf[64];
278950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    long name_max;
279050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    int maj, min;
27910ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov
279250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    if (!name)
279350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return NULL;
27940ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov
279550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    len = strlen(name);
27960ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov
279750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    if (fstat(fd, &sbuf))
279850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return NULL;
27990ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov
280050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    maj = major(sbuf.st_rdev);
280150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    min = minor(sbuf.st_rdev);
28020ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov
280350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode))
280450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return NULL;
28050ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov
280650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    snprintf(buf, sizeof(buf), "/sys/dev/char/%d:%d/device/drm", maj, min);
28070ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov
280850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    sysdir = opendir(buf);
280950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    if (!sysdir)
281050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        return NULL;
28110ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov
281250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    name_max = fpathconf(dirfd(sysdir), _PC_NAME_MAX);
281350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    if (name_max == -1)
281450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        goto out_close_dir;
28150ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov
281650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    pent = malloc(offsetof(struct dirent, d_name) + name_max + 1);
281750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    if (pent == NULL)
281850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely         goto out_close_dir;
28190ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov
282050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    while (readdir_r(sysdir, pent, &ent) == 0 && ent != NULL) {
282150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        if (strncmp(ent->d_name, name, len) == 0) {
282250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            snprintf(dev_name, sizeof(dev_name), DRM_DIR_NAME "/%s",
282350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                 ent->d_name);
28245c42b5e36a4a02e579ec5dcdc3a95ce58538224cMathias Tillman
282550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            free(pent);
282650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            closedir(sysdir);
28270ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov
282850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            return strdup(dev_name);
282950d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        }
283050d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    }
28310ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov
283250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    free(pent);
28330ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov
28340ca03a4087a550646de7f26b6b53a932e8546474Emil Velikovout_close_dir:
283550d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    closedir(sysdir);
28368415a00a3f2f5cb4827b58b86e974900d3892d29Emil Velikov#else
2837f189011b362a2dff3ab914523e546cc96f53df39Jonathan Gray    struct stat sbuf;
2838f189011b362a2dff3ab914523e546cc96f53df39Jonathan Gray    char buf[PATH_MAX + 1];
2839f189011b362a2dff3ab914523e546cc96f53df39Jonathan Gray    const char *dev_name;
2840f189011b362a2dff3ab914523e546cc96f53df39Jonathan Gray    unsigned int maj, min;
2841d5cf3f98314c1b9d87216e00c30c9fef06ff24c3Jonathan Gray    int n, base;
2842f189011b362a2dff3ab914523e546cc96f53df39Jonathan Gray
2843f189011b362a2dff3ab914523e546cc96f53df39Jonathan Gray    if (fstat(fd, &sbuf))
2844f189011b362a2dff3ab914523e546cc96f53df39Jonathan Gray        return NULL;
2845f189011b362a2dff3ab914523e546cc96f53df39Jonathan Gray
2846f189011b362a2dff3ab914523e546cc96f53df39Jonathan Gray    maj = major(sbuf.st_rdev);
2847f189011b362a2dff3ab914523e546cc96f53df39Jonathan Gray    min = minor(sbuf.st_rdev);
2848f189011b362a2dff3ab914523e546cc96f53df39Jonathan Gray
2849f189011b362a2dff3ab914523e546cc96f53df39Jonathan Gray    if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode))
2850f189011b362a2dff3ab914523e546cc96f53df39Jonathan Gray        return NULL;
2851f189011b362a2dff3ab914523e546cc96f53df39Jonathan Gray
2852f189011b362a2dff3ab914523e546cc96f53df39Jonathan Gray    switch (type) {
2853f189011b362a2dff3ab914523e546cc96f53df39Jonathan Gray    case DRM_NODE_PRIMARY:
2854f189011b362a2dff3ab914523e546cc96f53df39Jonathan Gray        dev_name = DRM_DEV_NAME;
2855f189011b362a2dff3ab914523e546cc96f53df39Jonathan Gray        break;
2856f189011b362a2dff3ab914523e546cc96f53df39Jonathan Gray    case DRM_NODE_CONTROL:
2857f189011b362a2dff3ab914523e546cc96f53df39Jonathan Gray        dev_name = DRM_CONTROL_DEV_NAME;
2858f189011b362a2dff3ab914523e546cc96f53df39Jonathan Gray        break;
2859f189011b362a2dff3ab914523e546cc96f53df39Jonathan Gray    case DRM_NODE_RENDER:
2860f189011b362a2dff3ab914523e546cc96f53df39Jonathan Gray        dev_name = DRM_RENDER_DEV_NAME;
2861f189011b362a2dff3ab914523e546cc96f53df39Jonathan Gray        break;
2862f189011b362a2dff3ab914523e546cc96f53df39Jonathan Gray    default:
2863f189011b362a2dff3ab914523e546cc96f53df39Jonathan Gray        return NULL;
2864f189011b362a2dff3ab914523e546cc96f53df39Jonathan Gray    };
2865f189011b362a2dff3ab914523e546cc96f53df39Jonathan Gray
2866d5cf3f98314c1b9d87216e00c30c9fef06ff24c3Jonathan Gray    base = drmGetMinorBase(type);
2867d5cf3f98314c1b9d87216e00c30c9fef06ff24c3Jonathan Gray    if (base < 0)
2868d5cf3f98314c1b9d87216e00c30c9fef06ff24c3Jonathan Gray        return NULL;
2869d5cf3f98314c1b9d87216e00c30c9fef06ff24c3Jonathan Gray
2870d5cf3f98314c1b9d87216e00c30c9fef06ff24c3Jonathan Gray    n = snprintf(buf, sizeof(buf), dev_name, DRM_DIR_NAME, min - base);
2871f189011b362a2dff3ab914523e546cc96f53df39Jonathan Gray    if (n == -1 || n >= sizeof(buf))
2872f189011b362a2dff3ab914523e546cc96f53df39Jonathan Gray        return NULL;
2873f189011b362a2dff3ab914523e546cc96f53df39Jonathan Gray
2874f189011b362a2dff3ab914523e546cc96f53df39Jonathan Gray    return strdup(buf);
28750ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov#endif
287650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    return NULL;
28770ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov}
28780ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov
28790ca03a4087a550646de7f26b6b53a932e8546474Emil Velikovchar *drmGetPrimaryDeviceNameFromFd(int fd)
28800ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov{
288150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    return drmGetMinorNameForFD(fd, DRM_NODE_PRIMARY);
28820ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov}
28830ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov
28840ca03a4087a550646de7f26b6b53a932e8546474Emil Velikovchar *drmGetRenderDeviceNameFromFd(int fd)
28850ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov{
288650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    return drmGetMinorNameForFD(fd, DRM_NODE_RENDER);
28870ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov}
2888b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
2889f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding#ifdef __linux__
2890f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Redingstatic char * DRM_PRINTFLIKE(2, 3)
2891f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Redingsysfs_uevent_get(const char *path, const char *fmt, ...)
2892f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding{
2893f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    char filename[PATH_MAX + 1], *key, *line = NULL, *value = NULL;
2894f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    size_t size = 0, len;
2895f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    ssize_t num;
2896f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    va_list ap;
2897f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    FILE *fp;
2898f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding
2899f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    va_start(ap, fmt);
2900f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    num = vasprintf(&key, fmt, ap);
2901f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    va_end(ap);
2902f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    len = num;
2903f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding
2904f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    snprintf(filename, sizeof(filename), "%s/uevent", path);
2905f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding
2906f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    fp = fopen(filename, "r");
2907f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    if (!fp) {
2908f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding        free(key);
2909f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding        return NULL;
2910f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    }
2911f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding
2912f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    while ((num = getline(&line, &size, fp)) >= 0) {
2913f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding        if ((strncmp(line, key, len) == 0) && (line[len] == '=')) {
2914f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding            char *start = line + len + 1, *end = line + num - 1;
2915f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding
2916f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding            if (*end != '\n')
2917f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding                end++;
2918f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding
2919f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding            value = strndup(start, end - start);
2920f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding            break;
2921f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding        }
2922f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    }
2923f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding
2924f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    free(line);
2925f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    fclose(fp);
2926f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding
2927f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    free(key);
2928f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding
2929f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    return value;
2930f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding}
2931f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding#endif
2932f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding
2933a250fceaaa150363accaf3fb71a0e42bcecc40daEmil Velikovstatic int drmParseSubsystemType(int maj, int min)
2934b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov{
2935291b2bb92c5fc90101417b80bbdc6c994be5fff2Emil Velikov#ifdef __linux__
2936a250fceaaa150363accaf3fb71a0e42bcecc40daEmil Velikov    char path[PATH_MAX + 1];
2937b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    char link[PATH_MAX + 1] = "";
2938b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    char *name;
2939b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
2940a250fceaaa150363accaf3fb71a0e42bcecc40daEmil Velikov    snprintf(path, PATH_MAX, "/sys/dev/char/%d:%d/device/subsystem",
2941a250fceaaa150363accaf3fb71a0e42bcecc40daEmil Velikov             maj, min);
2942a250fceaaa150363accaf3fb71a0e42bcecc40daEmil Velikov
2943a250fceaaa150363accaf3fb71a0e42bcecc40daEmil Velikov    if (readlink(path, link, PATH_MAX) < 0)
2944a250fceaaa150363accaf3fb71a0e42bcecc40daEmil Velikov        return -errno;
2945b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
2946b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    name = strrchr(link, '/');
2947b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    if (!name)
2948b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        return -EINVAL;
2949b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
2950a250fceaaa150363accaf3fb71a0e42bcecc40daEmil Velikov    if (strncmp(name, "/pci", 4) == 0)
2951b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        return DRM_BUS_PCI;
2952b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
2953f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    if (strncmp(name, "/usb", 4) == 0)
2954f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding        return DRM_BUS_USB;
2955f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding
29567b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    if (strncmp(name, "/platform", 9) == 0)
29577b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding        return DRM_BUS_PLATFORM;
29587b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
29597b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    if (strncmp(name, "/host1x", 7) == 0)
29607b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding        return DRM_BUS_HOST1X;
29617b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
2962b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    return -EINVAL;
2963d05b9f2dde17e60996437332219b4b568f7edefaJonathan Gray#elif defined(__OpenBSD__)
2964e17cad1994d321a8279c124e7a85ddddcdd9e4cdThierry Reding    return DRM_BUS_PCI;
2965291b2bb92c5fc90101417b80bbdc6c994be5fff2Emil Velikov#else
2966291b2bb92c5fc90101417b80bbdc6c994be5fff2Emil Velikov#warning "Missing implementation of drmParseSubsystemType"
2967291b2bb92c5fc90101417b80bbdc6c994be5fff2Emil Velikov    return -EINVAL;
2968291b2bb92c5fc90101417b80bbdc6c994be5fff2Emil Velikov#endif
2969b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov}
2970b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
2971536e0deba3829e194aafda6d9a1d9e938ba8277aEmil Velikovstatic int drmParsePciBusInfo(int maj, int min, drmPciBusInfoPtr info)
2972b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov{
2973291b2bb92c5fc90101417b80bbdc6c994be5fff2Emil Velikov#ifdef __linux__
29745403cb39c124c444babec51bd4499971cd86ccfaThierry Reding    unsigned int domain, bus, dev, func;
29755403cb39c124c444babec51bd4499971cd86ccfaThierry Reding    char path[PATH_MAX + 1], *value;
29765403cb39c124c444babec51bd4499971cd86ccfaThierry Reding    int num;
2977b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
29785403cb39c124c444babec51bd4499971cd86ccfaThierry Reding    snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min);
2979b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
29805403cb39c124c444babec51bd4499971cd86ccfaThierry Reding    value = sysfs_uevent_get(path, "PCI_SLOT_NAME");
29815403cb39c124c444babec51bd4499971cd86ccfaThierry Reding    if (!value)
29825403cb39c124c444babec51bd4499971cd86ccfaThierry Reding        return -ENOENT;
2983b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
29845403cb39c124c444babec51bd4499971cd86ccfaThierry Reding    num = sscanf(value, "%04x:%02x:%02x.%1u", &domain, &bus, &dev, &func);
29855403cb39c124c444babec51bd4499971cd86ccfaThierry Reding    free(value);
2986b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
29875403cb39c124c444babec51bd4499971cd86ccfaThierry Reding    if (num != 4)
2988b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        return -EINVAL;
2989b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
2990b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    info->domain = domain;
2991b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    info->bus = bus;
2992b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    info->dev = dev;
2993b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    info->func = func;
2994b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
2995b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    return 0;
2996fd190564daa4cd530833a94606646730a5c0ee6cJonathan Gray#elif defined(__OpenBSD__)
2997fd190564daa4cd530833a94606646730a5c0ee6cJonathan Gray    struct drm_pciinfo pinfo;
2998fd190564daa4cd530833a94606646730a5c0ee6cJonathan Gray    int fd, type;
2999fd190564daa4cd530833a94606646730a5c0ee6cJonathan Gray
3000fd190564daa4cd530833a94606646730a5c0ee6cJonathan Gray    type = drmGetMinorType(min);
3001fd190564daa4cd530833a94606646730a5c0ee6cJonathan Gray    if (type == -1)
3002fd190564daa4cd530833a94606646730a5c0ee6cJonathan Gray        return -ENODEV;
3003fd190564daa4cd530833a94606646730a5c0ee6cJonathan Gray
3004fd190564daa4cd530833a94606646730a5c0ee6cJonathan Gray    fd = drmOpenMinor(min, 0, type);
3005fd190564daa4cd530833a94606646730a5c0ee6cJonathan Gray    if (fd < 0)
3006fd190564daa4cd530833a94606646730a5c0ee6cJonathan Gray        return -errno;
3007fd190564daa4cd530833a94606646730a5c0ee6cJonathan Gray
3008fd190564daa4cd530833a94606646730a5c0ee6cJonathan Gray    if (drmIoctl(fd, DRM_IOCTL_GET_PCIINFO, &pinfo)) {
3009fd190564daa4cd530833a94606646730a5c0ee6cJonathan Gray        close(fd);
3010fd190564daa4cd530833a94606646730a5c0ee6cJonathan Gray        return -errno;
3011fd190564daa4cd530833a94606646730a5c0ee6cJonathan Gray    }
3012fd190564daa4cd530833a94606646730a5c0ee6cJonathan Gray    close(fd);
3013fd190564daa4cd530833a94606646730a5c0ee6cJonathan Gray
3014fd190564daa4cd530833a94606646730a5c0ee6cJonathan Gray    info->domain = pinfo.domain;
3015fd190564daa4cd530833a94606646730a5c0ee6cJonathan Gray    info->bus = pinfo.bus;
3016fd190564daa4cd530833a94606646730a5c0ee6cJonathan Gray    info->dev = pinfo.dev;
3017fd190564daa4cd530833a94606646730a5c0ee6cJonathan Gray    info->func = pinfo.func;
3018fd190564daa4cd530833a94606646730a5c0ee6cJonathan Gray
3019fd190564daa4cd530833a94606646730a5c0ee6cJonathan Gray    return 0;
3020291b2bb92c5fc90101417b80bbdc6c994be5fff2Emil Velikov#else
3021291b2bb92c5fc90101417b80bbdc6c994be5fff2Emil Velikov#warning "Missing implementation of drmParsePciBusInfo"
3022291b2bb92c5fc90101417b80bbdc6c994be5fff2Emil Velikov    return -EINVAL;
3023291b2bb92c5fc90101417b80bbdc6c994be5fff2Emil Velikov#endif
3024b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov}
3025b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
3026bc2aca9e22bf2cc82874f3e44568c684eec9c5e1Emil Velikovstatic int drmCompareBusInfo(drmDevicePtr a, drmDevicePtr b)
3027b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov{
3028bc2aca9e22bf2cc82874f3e44568c684eec9c5e1Emil Velikov    if (a == NULL || b == NULL)
3029bc2aca9e22bf2cc82874f3e44568c684eec9c5e1Emil Velikov        return -1;
3030bc2aca9e22bf2cc82874f3e44568c684eec9c5e1Emil Velikov
3031b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    if (a->bustype != b->bustype)
3032bc2aca9e22bf2cc82874f3e44568c684eec9c5e1Emil Velikov        return -1;
3033b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
3034b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    switch (a->bustype) {
3035b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    case DRM_BUS_PCI:
3036bc2aca9e22bf2cc82874f3e44568c684eec9c5e1Emil Velikov        return memcmp(a->businfo.pci, b->businfo.pci, sizeof(drmPciBusInfo));
3037f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding
3038f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    case DRM_BUS_USB:
3039f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding        return memcmp(a->businfo.usb, b->businfo.usb, sizeof(drmUsbBusInfo));
3040f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding
30417b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    case DRM_BUS_PLATFORM:
30427b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding        return memcmp(a->businfo.platform, b->businfo.platform, sizeof(drmPlatformBusInfo));
30437b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
30447b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    case DRM_BUS_HOST1X:
30457b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding        return memcmp(a->businfo.host1x, b->businfo.host1x, sizeof(drmHost1xBusInfo));
30467b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
3047b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    default:
3048b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        break;
3049b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    }
3050b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
3051bc2aca9e22bf2cc82874f3e44568c684eec9c5e1Emil Velikov    return -1;
3052b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov}
3053b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
3054b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikovstatic int drmGetNodeType(const char *name)
3055b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov{
3056b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    if (strncmp(name, DRM_PRIMARY_MINOR_NAME,
3057b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        sizeof(DRM_PRIMARY_MINOR_NAME) - 1) == 0)
3058b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        return DRM_NODE_PRIMARY;
3059b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
3060b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    if (strncmp(name, DRM_CONTROL_MINOR_NAME,
3061b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        sizeof(DRM_CONTROL_MINOR_NAME ) - 1) == 0)
3062b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        return DRM_NODE_CONTROL;
3063b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
3064b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    if (strncmp(name, DRM_RENDER_MINOR_NAME,
3065b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        sizeof(DRM_RENDER_MINOR_NAME) - 1) == 0)
3066b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        return DRM_NODE_RENDER;
3067b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
3068b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    return -EINVAL;
3069b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov}
3070b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
30715f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikovstatic int drmGetMaxNodeName(void)
30725f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov{
30735f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    return sizeof(DRM_DIR_NAME) +
30745f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov           MAX3(sizeof(DRM_PRIMARY_MINOR_NAME),
30755f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov                sizeof(DRM_CONTROL_MINOR_NAME),
30765f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov                sizeof(DRM_RENDER_MINOR_NAME)) +
3077ce97507cfcbdbdc520872417b5605f3b807794ffEric Engestrom           3 /* length of the node number */;
30785f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov}
30795f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov
3080291b2bb92c5fc90101417b80bbdc6c994be5fff2Emil Velikov#ifdef __linux__
3081aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikovstatic int parse_separate_sysfs_files(int maj, int min,
308211687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov                                      drmPciDeviceInfoPtr device,
308311687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov                                      bool ignore_revision)
3084aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov{
3085aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
3086aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov    static const char *attrs[] = {
3087aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov      "revision", /* Older kernels are missing the file, so check for it first */
3088aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov      "vendor",
3089aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov      "device",
3090aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov      "subsystem_vendor",
3091aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov      "subsystem_device",
3092aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov    };
3093aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov    char path[PATH_MAX + 1];
3094aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov    unsigned int data[ARRAY_SIZE(attrs)];
3095aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov    FILE *fp;
3096aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov    int ret;
3097aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov
309811687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov    for (unsigned i = ignore_revision ? 1 : 0; i < ARRAY_SIZE(attrs); i++) {
3099aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov        snprintf(path, PATH_MAX, "/sys/dev/char/%d:%d/device/%s", maj, min,
3100aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov                 attrs[i]);
3101aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov        fp = fopen(path, "r");
3102aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov        if (!fp)
3103aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov            return -errno;
3104aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov
3105aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov        ret = fscanf(fp, "%x", &data[i]);
3106aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov        fclose(fp);
3107aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov        if (ret != 1)
3108aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov            return -errno;
3109aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov
3110aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov    }
3111aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov
311211687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov    device->revision_id = ignore_revision ? 0xff : data[0] & 0xff;
3113aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov    device->vendor_id = data[1] & 0xffff;
3114aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov    device->device_id = data[2] & 0xffff;
3115aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov    device->subvendor_id = data[3] & 0xffff;
3116aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov    device->subdevice_id = data[4] & 0xffff;
3117aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov
3118aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov    return 0;
3119aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov}
3120aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov
3121aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikovstatic int parse_config_sysfs_file(int maj, int min,
3122aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov                                   drmPciDeviceInfoPtr device)
3123aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov{
3124ef5192e9c7897c82da815a2c893b2e2562997a3aEmil Velikov    char path[PATH_MAX + 1];
3125ef5192e9c7897c82da815a2c893b2e2562997a3aEmil Velikov    unsigned char config[64];
3126ef5192e9c7897c82da815a2c893b2e2562997a3aEmil Velikov    int fd, ret;
3127ef5192e9c7897c82da815a2c893b2e2562997a3aEmil Velikov
3128b40a65d44857394966b25c5587f9dc978643f9c4Emil Velikov    snprintf(path, PATH_MAX, "/sys/dev/char/%d:%d/device/config", maj, min);
3129ef5192e9c7897c82da815a2c893b2e2562997a3aEmil Velikov    fd = open(path, O_RDONLY);
3130ef5192e9c7897c82da815a2c893b2e2562997a3aEmil Velikov    if (fd < 0)
3131ef5192e9c7897c82da815a2c893b2e2562997a3aEmil Velikov        return -errno;
3132ef5192e9c7897c82da815a2c893b2e2562997a3aEmil Velikov
3133ef5192e9c7897c82da815a2c893b2e2562997a3aEmil Velikov    ret = read(fd, config, sizeof(config));
3134ef5192e9c7897c82da815a2c893b2e2562997a3aEmil Velikov    close(fd);
3135ef5192e9c7897c82da815a2c893b2e2562997a3aEmil Velikov    if (ret < 0)
3136ef5192e9c7897c82da815a2c893b2e2562997a3aEmil Velikov        return -errno;
3137b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
3138b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    device->vendor_id = config[0] | (config[1] << 8);
3139b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    device->device_id = config[2] | (config[3] << 8);
3140b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    device->revision_id = config[8];
3141b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    device->subvendor_id = config[44] | (config[45] << 8);
3142b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    device->subdevice_id = config[46] | (config[47] << 8);
3143b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
3144b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    return 0;
3145aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov}
3146aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov#endif
3147aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov
3148aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikovstatic int drmParsePciDeviceInfo(int maj, int min,
3149aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov                                 drmPciDeviceInfoPtr device,
3150aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov                                 uint32_t flags)
3151aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov{
3152aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov#ifdef __linux__
315311687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov    if (!(flags & DRM_DEVICE_GET_PCI_REVISION))
315411687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov        return parse_separate_sysfs_files(maj, min, device, true);
315511687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov
315611687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov    if (parse_separate_sysfs_files(maj, min, device, false))
3157aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov        return parse_config_sysfs_file(maj, min, device);
3158aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov
3159aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov    return 0;
3160c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray#elif defined(__OpenBSD__)
3161c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray    struct drm_pciinfo pinfo;
3162c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray    int fd, type;
3163c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray
3164c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray    type = drmGetMinorType(min);
3165c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray    if (type == -1)
3166c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray        return -ENODEV;
3167c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray
3168c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray    fd = drmOpenMinor(min, 0, type);
3169c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray    if (fd < 0)
3170c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray        return -errno;
3171c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray
3172c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray    if (drmIoctl(fd, DRM_IOCTL_GET_PCIINFO, &pinfo)) {
3173c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray        close(fd);
3174c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray        return -errno;
3175c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray    }
3176c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray    close(fd);
3177c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray
3178c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray    device->vendor_id = pinfo.vendor_id;
3179c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray    device->device_id = pinfo.device_id;
3180c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray    device->revision_id = pinfo.revision_id;
3181c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray    device->subvendor_id = pinfo.subvendor_id;
3182c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray    device->subdevice_id = pinfo.subdevice_id;
3183c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray
3184c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray    return 0;
3185291b2bb92c5fc90101417b80bbdc6c994be5fff2Emil Velikov#else
3186291b2bb92c5fc90101417b80bbdc6c994be5fff2Emil Velikov#warning "Missing implementation of drmParsePciDeviceInfo"
3187291b2bb92c5fc90101417b80bbdc6c994be5fff2Emil Velikov    return -EINVAL;
3188291b2bb92c5fc90101417b80bbdc6c994be5fff2Emil Velikov#endif
3189b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov}
3190b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
31917b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Redingstatic void drmFreePlatformDevice(drmDevicePtr device)
31927b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding{
31937b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    if (device->deviceinfo.platform) {
31947b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding        if (device->deviceinfo.platform->compatible) {
31957b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding            char **compatible = device->deviceinfo.platform->compatible;
31967b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
31977b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding            while (*compatible) {
31987b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding                free(*compatible);
31997b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding                compatible++;
32007b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding            }
32017b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
32027b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding            free(device->deviceinfo.platform->compatible);
32037b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding        }
32047b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    }
32057b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding}
32067b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
32077b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Redingstatic void drmFreeHost1xDevice(drmDevicePtr device)
32087b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding{
32097b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    if (device->deviceinfo.host1x) {
32107b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding        if (device->deviceinfo.host1x->compatible) {
32117b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding            char **compatible = device->deviceinfo.host1x->compatible;
32127b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
32137b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding            while (*compatible) {
32147b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding                free(*compatible);
32157b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding                compatible++;
32167b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding            }
32177b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
32187b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding            free(device->deviceinfo.host1x->compatible);
32197b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding        }
32207b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    }
32217b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding}
32227b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
3223ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikovvoid drmFreeDevice(drmDevicePtr *device)
3224b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov{
3225b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    if (device == NULL)
3226b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        return;
3227b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
32287b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    if (*device) {
32297b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding        switch ((*device)->bustype) {
32307b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding        case DRM_BUS_PLATFORM:
32317b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding            drmFreePlatformDevice(*device);
32327b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding            break;
32337b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
32347b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding        case DRM_BUS_HOST1X:
32357b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding            drmFreeHost1xDevice(*device);
32367b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding            break;
32377b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding        }
32387b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    }
32397b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
32405f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    free(*device);
32415f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    *device = NULL;
3242b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov}
3243b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
3244b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikovvoid drmFreeDevices(drmDevicePtr devices[], int count)
3245b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov{
3246b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    int i;
3247b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
3248b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    if (devices == NULL)
3249b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        return;
3250b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
32516c056eecd56374b069ed24c81f59b6638cde2f3aQiang Yu    for (i = 0; i < count; i++)
32526c056eecd56374b069ed24c81f59b6638cde2f3aQiang Yu        if (devices[i])
32536c056eecd56374b069ed24c81f59b6638cde2f3aQiang Yu            drmFreeDevice(&devices[i]);
3254b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov}
3255b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
32562e57bba870399926e1a0d0be3f4918a0a8432474Thierry Redingstatic drmDevicePtr drmDeviceAlloc(unsigned int type, const char *node,
32572e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding                                   size_t bus_size, size_t device_size,
32582e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding                                   char **ptrp)
32592e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding{
32602e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding    size_t max_node_length, extra, size;
32612e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding    drmDevicePtr device;
32622e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding    unsigned int i;
32632e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding    char *ptr;
32642e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding
32652e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding    max_node_length = ALIGN(drmGetMaxNodeName(), sizeof(void *));
32662e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding    extra = DRM_NODE_MAX * (sizeof(void *) + max_node_length);
32672e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding
32682e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding    size = sizeof(*device) + extra + bus_size + device_size;
32692e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding
32702e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding    device = calloc(1, size);
32712e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding    if (!device)
32722e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding        return NULL;
32732e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding
32742e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding    device->available_nodes = 1 << type;
32752e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding
32762e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding    ptr = (char *)device + sizeof(*device);
32772e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding    device->nodes = (char **)ptr;
32782e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding
32792e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding    ptr += DRM_NODE_MAX * sizeof(void *);
32802e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding
32812e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding    for (i = 0; i < DRM_NODE_MAX; i++) {
32822e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding        device->nodes[i] = ptr;
32832e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding        ptr += max_node_length;
32842e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding    }
32852e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding
32862e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding    memcpy(device->nodes[type], node, max_node_length);
32872e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding
32882e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding    *ptrp = ptr;
32892e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding
32902e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding    return device;
32912e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding}
32922e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding
3293b40a65d44857394966b25c5587f9dc978643f9c4Emil Velikovstatic int drmProcessPciDevice(drmDevicePtr *device,
3294fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov                               const char *node, int node_type,
3295138d23117c6b96f57aaa0072992e0480153cfebdEmil Velikov                               int maj, int min, bool fetch_deviceinfo,
3296138d23117c6b96f57aaa0072992e0480153cfebdEmil Velikov                               uint32_t flags)
3297fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov{
32982e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding    drmDevicePtr dev;
32993045523de214fb7df92ee3c8482e883637504bbeMichel Dänzer    char *addr;
33002e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding    int ret;
3301fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov
33022e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding    dev = drmDeviceAlloc(node_type, node, sizeof(drmPciBusInfo),
33032e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding                         sizeof(drmPciDeviceInfo), &addr);
33042e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding    if (!dev)
3305fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov        return -ENOMEM;
3306fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov
33072e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding    dev->bustype = DRM_BUS_PCI;
330850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely
33092e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding    dev->businfo.pci = (drmPciBusInfoPtr)addr;
3310fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov
33112e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding    ret = drmParsePciBusInfo(maj, min, dev->businfo.pci);
3312fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    if (ret)
3313fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov        goto free_device;
3314fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov
3315fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    // Fetch the device info if the user has requested it
3316fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    if (fetch_deviceinfo) {
3317fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov        addr += sizeof(drmPciBusInfo);
33182e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding        dev->deviceinfo.pci = (drmPciDeviceInfoPtr)addr;
3319fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov
33202e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding        ret = drmParsePciDeviceInfo(maj, min, dev->deviceinfo.pci, flags);
3321fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov        if (ret)
3322fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov            goto free_device;
3323fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    }
33242e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding
33252e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding    *device = dev;
33262e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding
3327fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    return 0;
3328fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov
3329fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikovfree_device:
33302e57bba870399926e1a0d0be3f4918a0a8432474Thierry Reding    free(dev);
3331fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    return ret;
3332fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov}
3333fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov
3334f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Redingstatic int drmParseUsbBusInfo(int maj, int min, drmUsbBusInfoPtr info)
3335f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding{
3336f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding#ifdef __linux__
3337f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    char path[PATH_MAX + 1], *value;
3338f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    unsigned int bus, dev;
3339f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    int ret;
3340f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding
3341f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min);
3342f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding
3343f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    value = sysfs_uevent_get(path, "BUSNUM");
3344f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    if (!value)
3345f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding        return -ENOENT;
3346f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding
3347f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    ret = sscanf(value, "%03u", &bus);
3348f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    free(value);
3349f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding
3350f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    if (ret <= 0)
3351f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding        return -errno;
3352f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding
3353f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    value = sysfs_uevent_get(path, "DEVNUM");
3354f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    if (!value)
3355f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding        return -ENOENT;
3356f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding
3357f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    ret = sscanf(value, "%03u", &dev);
3358f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    free(value);
3359f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding
3360f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    if (ret <= 0)
3361f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding        return -errno;
3362f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding
3363f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    info->bus = bus;
3364f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    info->dev = dev;
3365f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding
3366f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    return 0;
3367f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding#else
3368f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding#warning "Missing implementation of drmParseUsbBusInfo"
3369f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    return -EINVAL;
3370f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding#endif
3371f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding}
3372f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding
3373f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Redingstatic int drmParseUsbDeviceInfo(int maj, int min, drmUsbDeviceInfoPtr info)
3374f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding{
3375f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding#ifdef __linux__
3376f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    char path[PATH_MAX + 1], *value;
3377f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    unsigned int vendor, product;
3378f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    int ret;
3379f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding
3380f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min);
3381f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding
3382f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    value = sysfs_uevent_get(path, "PRODUCT");
3383f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    if (!value)
3384f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding        return -ENOENT;
3385f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding
3386f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    ret = sscanf(value, "%x/%x", &vendor, &product);
3387f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    free(value);
3388f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding
3389f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    if (ret <= 0)
3390f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding        return -errno;
3391f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding
3392f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    info->vendor = vendor;
3393f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    info->product = product;
3394f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding
3395f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    return 0;
3396f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding#else
3397f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding#warning "Missing implementation of drmParseUsbDeviceInfo"
3398f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    return -EINVAL;
3399f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding#endif
3400f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding}
3401f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding
3402f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Redingstatic int drmProcessUsbDevice(drmDevicePtr *device, const char *node,
3403f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding                               int node_type, int maj, int min,
3404f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding                               bool fetch_deviceinfo, uint32_t flags)
3405f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding{
3406f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    drmDevicePtr dev;
3407f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    char *ptr;
3408f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    int ret;
3409f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding
3410f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    dev = drmDeviceAlloc(node_type, node, sizeof(drmUsbBusInfo),
3411f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding                         sizeof(drmUsbDeviceInfo), &ptr);
3412f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    if (!dev)
3413f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding        return -ENOMEM;
3414f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding
3415f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    dev->bustype = DRM_BUS_USB;
3416f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding
3417f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    dev->businfo.usb = (drmUsbBusInfoPtr)ptr;
3418f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding
3419f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    ret = drmParseUsbBusInfo(maj, min, dev->businfo.usb);
3420f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    if (ret < 0)
3421f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding        goto free_device;
3422f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding
3423f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    if (fetch_deviceinfo) {
3424f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding        ptr += sizeof(drmUsbBusInfo);
3425f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding        dev->deviceinfo.usb = (drmUsbDeviceInfoPtr)ptr;
3426f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding
3427f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding        ret = drmParseUsbDeviceInfo(maj, min, dev->deviceinfo.usb);
3428f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding        if (ret < 0)
3429f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding            goto free_device;
3430f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    }
3431f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding
3432f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    *device = dev;
3433f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding
3434f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    return 0;
3435f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding
3436f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Redingfree_device:
3437f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    free(dev);
3438f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding    return ret;
3439f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding}
3440f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding
34417b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Redingstatic int drmParsePlatformBusInfo(int maj, int min, drmPlatformBusInfoPtr info)
34427b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding{
34437b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding#ifdef __linux__
34447b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    char path[PATH_MAX + 1], *name;
34457b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
34467b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min);
34477b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
34487b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    name = sysfs_uevent_get(path, "OF_FULLNAME");
34497b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    if (!name)
34507b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding        return -ENOENT;
34517b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
34527b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    strncpy(info->fullname, name, DRM_PLATFORM_DEVICE_NAME_LEN);
34537b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    info->fullname[DRM_PLATFORM_DEVICE_NAME_LEN - 1] = '\0';
34547b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    free(name);
34557b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
34567b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    return 0;
34577b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding#else
34587b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding#warning "Missing implementation of drmParsePlatformBusInfo"
34597b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    return -EINVAL;
34607b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding#endif
34617b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding}
34627b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
34637b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Redingstatic int drmParsePlatformDeviceInfo(int maj, int min,
34647b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding                                      drmPlatformDeviceInfoPtr info)
34657b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding{
34667b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding#ifdef __linux__
34677b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    char path[PATH_MAX + 1], *value;
34687b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    unsigned int count, i;
34697b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    int err;
34707b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
34717b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min);
34727b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
34737b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    value = sysfs_uevent_get(path, "OF_COMPATIBLE_N");
34747b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    if (!value)
34757b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding        return -ENOENT;
34767b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
34777b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    sscanf(value, "%u", &count);
34787b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    free(value);
34797b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
34807b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    info->compatible = calloc(count + 1, sizeof(*info->compatible));
34817b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    if (!info->compatible)
34827b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding        return -ENOMEM;
34837b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
34847b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    for (i = 0; i < count; i++) {
34857b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding        value = sysfs_uevent_get(path, "OF_COMPATIBLE_%u", i);
34867b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding        if (!value) {
34877b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding            err = -ENOENT;
34887b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding            goto free;
34897b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding        }
34907b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
34917b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding        info->compatible[i] = value;
34927b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    }
34937b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
34947b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    return 0;
34957b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
34967b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Redingfree:
34977b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    while (i--)
34987b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding        free(info->compatible[i]);
34997b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
35007b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    free(info->compatible);
35017b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    return err;
35027b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding#else
35037b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding#warning "Missing implementation of drmParsePlatformDeviceInfo"
35047b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    return -EINVAL;
35057b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding#endif
35067b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding}
35077b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
35087b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Redingstatic int drmProcessPlatformDevice(drmDevicePtr *device,
35097b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding                                    const char *node, int node_type,
35107b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding                                    int maj, int min, bool fetch_deviceinfo,
35117b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding                                    uint32_t flags)
35127b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding{
35137b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    drmDevicePtr dev;
35147b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    char *ptr;
35157b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    int ret;
35167b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
35177b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    dev = drmDeviceAlloc(node_type, node, sizeof(drmPlatformBusInfo),
35187b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding                         sizeof(drmPlatformDeviceInfo), &ptr);
35197b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    if (!dev)
35207b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding        return -ENOMEM;
35217b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
35227b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    dev->bustype = DRM_BUS_PLATFORM;
35237b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
35247b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    dev->businfo.platform = (drmPlatformBusInfoPtr)ptr;
35257b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
35267b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    ret = drmParsePlatformBusInfo(maj, min, dev->businfo.platform);
35277b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    if (ret < 0)
35287b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding        goto free_device;
35297b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
35307b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    if (fetch_deviceinfo) {
35317b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding        ptr += sizeof(drmPlatformBusInfo);
35327b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding        dev->deviceinfo.platform = (drmPlatformDeviceInfoPtr)ptr;
35337b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
35347b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding        ret = drmParsePlatformDeviceInfo(maj, min, dev->deviceinfo.platform);
35357b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding        if (ret < 0)
35367b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding            goto free_device;
35377b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    }
35387b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
35397b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    *device = dev;
35407b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
35417b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    return 0;
35427b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
35437b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Redingfree_device:
35447b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    free(dev);
35457b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    return ret;
35467b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding}
35477b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
35487b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Redingstatic int drmParseHost1xBusInfo(int maj, int min, drmHost1xBusInfoPtr info)
35497b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding{
35507b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding#ifdef __linux__
35517b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    char path[PATH_MAX + 1], *name;
35527b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
35537b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min);
35547b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
35557b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    name = sysfs_uevent_get(path, "OF_FULLNAME");
35567b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    if (!name)
35577b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding        return -ENOENT;
35587b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
35597b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    strncpy(info->fullname, name, DRM_HOST1X_DEVICE_NAME_LEN);
35607b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    info->fullname[DRM_HOST1X_DEVICE_NAME_LEN - 1] = '\0';
35617b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    free(name);
35627b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
35637b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    return 0;
35647b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding#else
35657b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding#warning "Missing implementation of drmParseHost1xBusInfo"
35667b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    return -EINVAL;
35677b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding#endif
35687b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding}
35697b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
35707b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Redingstatic int drmParseHost1xDeviceInfo(int maj, int min,
35717b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding                                    drmHost1xDeviceInfoPtr info)
35727b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding{
35737b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding#ifdef __linux__
35747b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    char path[PATH_MAX + 1], *value;
35757b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    unsigned int count, i;
35767b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    int err;
35777b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
35787b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min);
35797b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
35807b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    value = sysfs_uevent_get(path, "OF_COMPATIBLE_N");
35817b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    if (!value)
35827b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding        return -ENOENT;
35837b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
35847b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    sscanf(value, "%u", &count);
35857b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    free(value);
35867b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
35877b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    info->compatible = calloc(count + 1, sizeof(*info->compatible));
35887b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    if (!info->compatible)
35897b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding        return -ENOMEM;
35907b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
35917b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    for (i = 0; i < count; i++) {
35927b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding        value = sysfs_uevent_get(path, "OF_COMPATIBLE_%u", i);
35937b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding        if (!value) {
35947b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding            err = -ENOENT;
35957b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding            goto free;
35967b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding        }
35977b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
35987b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding        info->compatible[i] = value;
35997b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    }
36007b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
36017b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    return 0;
36027b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
36037b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Redingfree:
36047b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    while (i--)
36057b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding        free(info->compatible[i]);
36067b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
36077b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    free(info->compatible);
36087b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    return err;
36097b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding#else
36107b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding#warning "Missing implementation of drmParseHost1xDeviceInfo"
36117b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    return -EINVAL;
36127b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding#endif
36137b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding}
36147b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
36157b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Redingstatic int drmProcessHost1xDevice(drmDevicePtr *device,
36167b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding                                  const char *node, int node_type,
36177b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding                                  int maj, int min, bool fetch_deviceinfo,
36187b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding                                  uint32_t flags)
36197b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding{
36207b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    drmDevicePtr dev;
36217b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    char *ptr;
36227b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    int ret;
36237b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
36247b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    dev = drmDeviceAlloc(node_type, node, sizeof(drmHost1xBusInfo),
36257b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding                         sizeof(drmHost1xDeviceInfo), &ptr);
36267b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    if (!dev)
36277b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding        return -ENOMEM;
36287b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
36297b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    dev->bustype = DRM_BUS_HOST1X;
36307b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
36317b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    dev->businfo.host1x = (drmHost1xBusInfoPtr)ptr;
36327b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
36337b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    ret = drmParseHost1xBusInfo(maj, min, dev->businfo.host1x);
36347b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    if (ret < 0)
36357b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding        goto free_device;
36367b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
36377b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    if (fetch_deviceinfo) {
36387b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding        ptr += sizeof(drmHost1xBusInfo);
36397b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding        dev->deviceinfo.host1x = (drmHost1xDeviceInfoPtr)ptr;
36407b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
36417b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding        ret = drmParseHost1xDeviceInfo(maj, min, dev->deviceinfo.host1x);
36427b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding        if (ret < 0)
36437b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding            goto free_device;
36447b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    }
36457b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
36467b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    *device = dev;
36477b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
36487b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    return 0;
36497b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
36507b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Redingfree_device:
36517b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    free(dev);
36527b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding    return ret;
36537b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding}
36547b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
36553c20893daa0a56b91869d806ae0d3a8d5d8b4cbaQiang Yu/* Consider devices located on the same bus as duplicate and fold the respective
36563c20893daa0a56b91869d806ae0d3a8d5d8b4cbaQiang Yu * entries into a single one.
36573c20893daa0a56b91869d806ae0d3a8d5d8b4cbaQiang Yu *
36583c20893daa0a56b91869d806ae0d3a8d5d8b4cbaQiang Yu * Note: this leaves "gaps" in the array, while preserving the length.
36593c20893daa0a56b91869d806ae0d3a8d5d8b4cbaQiang Yu */
3660fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikovstatic void drmFoldDuplicatedDevices(drmDevicePtr local_devices[], int count)
3661fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov{
3662fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    int node_type, i, j;
3663fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov
3664fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    for (i = 0; i < count; i++) {
3665fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov        for (j = i + 1; j < count; j++) {
3666fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov            if (drmCompareBusInfo(local_devices[i], local_devices[j]) == 0) {
3667fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov                local_devices[i]->available_nodes |= local_devices[j]->available_nodes;
3668fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov                node_type = log2(local_devices[j]->available_nodes);
3669fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov                memcpy(local_devices[i]->nodes[node_type],
3670fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov                       local_devices[j]->nodes[node_type], drmGetMaxNodeName());
3671fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov                drmFreeDevice(&local_devices[j]);
3672fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov            }
3673fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov        }
3674fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    }
3675fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov}
3676fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov
367711687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov/* Check that the given flags are valid returning 0 on success */
367811687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikovstatic int
367911687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikovdrm_device_validate_flags(uint32_t flags)
368011687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov{
368111687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov        return (flags & ~DRM_DEVICE_GET_PCI_REVISION);
368211687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov}
368311687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov
3684b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov/**
3685ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov * Get information about the opened drm device
3686ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov *
3687ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov * \param fd file descriptor of the drm device
368811687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov * \param flags feature/behaviour bitmask
3689ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov * \param device the address of a drmDevicePtr where the information
3690ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov *               will be allocated in stored
3691ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov *
3692ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov * \return zero on success, negative error code otherwise.
369311687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov *
369411687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov * \note Unlike drmGetDevice it does not retrieve the pci device revision field
369511687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov * unless the DRM_DEVICE_GET_PCI_REVISION \p flag is set.
3696ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov */
369711687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikovint drmGetDevice2(int fd, uint32_t flags, drmDevicePtr *device)
3698ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov{
369908257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray#ifdef __OpenBSD__
370008257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray    /*
370108257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray     * DRI device nodes on OpenBSD are not in their own directory, they reside
370208257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray     * in /dev along with a large number of statically generated /dev nodes.
370308257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray     * Avoid stat'ing all of /dev needlessly by implementing this custom path.
370408257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray     */
370508257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray    drmDevicePtr     d;
370608257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray    struct stat      sbuf;
370708257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray    char             node[PATH_MAX + 1];
370808257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray    const char      *dev_name;
370908257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray    int              node_type, subsystem_type;
3710d5cf3f98314c1b9d87216e00c30c9fef06ff24c3Jonathan Gray    int              maj, min, n, ret, base;
371108257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray
371208257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray    if (fd == -1 || device == NULL)
371308257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray        return -EINVAL;
371408257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray
371508257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray    if (fstat(fd, &sbuf))
371608257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray        return -errno;
371708257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray
371808257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray    maj = major(sbuf.st_rdev);
371908257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray    min = minor(sbuf.st_rdev);
372008257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray
372108257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray    if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode))
372208257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray        return -EINVAL;
372308257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray
372408257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray    node_type = drmGetMinorType(min);
372508257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray    if (node_type == -1)
372608257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray        return -ENODEV;
372708257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray
372808257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray    switch (node_type) {
372908257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray    case DRM_NODE_PRIMARY:
373008257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray        dev_name = DRM_DEV_NAME;
373108257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray        break;
373208257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray    case DRM_NODE_CONTROL:
373308257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray        dev_name = DRM_CONTROL_DEV_NAME;
373408257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray        break;
373508257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray    case DRM_NODE_RENDER:
373608257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray        dev_name = DRM_RENDER_DEV_NAME;
373708257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray        break;
373808257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray    default:
373908257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray        return -EINVAL;
374008257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray    };
374108257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray
3742d5cf3f98314c1b9d87216e00c30c9fef06ff24c3Jonathan Gray    base = drmGetMinorBase(node_type);
3743d5cf3f98314c1b9d87216e00c30c9fef06ff24c3Jonathan Gray    if (base < 0)
3744d5cf3f98314c1b9d87216e00c30c9fef06ff24c3Jonathan Gray        return -EINVAL;
3745d5cf3f98314c1b9d87216e00c30c9fef06ff24c3Jonathan Gray
3746d5cf3f98314c1b9d87216e00c30c9fef06ff24c3Jonathan Gray    n = snprintf(node, PATH_MAX, dev_name, DRM_DIR_NAME, min - base);
374708257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray    if (n == -1 || n >= PATH_MAX)
374808257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray      return -errno;
374908257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray    if (stat(node, &sbuf))
375008257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray        return -EINVAL;
375108257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray
375208257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray    subsystem_type = drmParseSubsystemType(maj, min);
375308257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray    if (subsystem_type != DRM_BUS_PCI)
375408257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray        return -ENODEV;
375508257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray
375608257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray    ret = drmProcessPciDevice(&d, node, node_type, maj, min, true, flags);
375708257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray    if (ret)
375808257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray        return ret;
375908257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray
376008257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray    *device = d;
376108257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray
376208257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray    return 0;
376308257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray#else
3764ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    drmDevicePtr *local_devices;
3765ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    drmDevicePtr d;
3766ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    DIR *sysdir;
3767ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    struct dirent *dent;
3768ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    struct stat sbuf;
3769ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    char node[PATH_MAX + 1];
3770ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    int node_type, subsystem_type;
3771ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    int maj, min;
3772ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    int ret, i, node_count;
3773ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    int max_count = 16;
37743c20893daa0a56b91869d806ae0d3a8d5d8b4cbaQiang Yu    dev_t find_rdev;
377511687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov
377611687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov    if (drm_device_validate_flags(flags))
377711687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov        return -EINVAL;
3778ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3779ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    if (fd == -1 || device == NULL)
3780ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        return -EINVAL;
3781ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3782ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    if (fstat(fd, &sbuf))
3783ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        return -errno;
3784ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
37853c20893daa0a56b91869d806ae0d3a8d5d8b4cbaQiang Yu    find_rdev = sbuf.st_rdev;
3786ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    maj = major(sbuf.st_rdev);
3787ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    min = minor(sbuf.st_rdev);
3788ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3789ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode))
3790ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        return -EINVAL;
3791ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3792ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    subsystem_type = drmParseSubsystemType(maj, min);
3793ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3794ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    local_devices = calloc(max_count, sizeof(drmDevicePtr));
3795ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    if (local_devices == NULL)
3796ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        return -ENOMEM;
3797ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3798ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    sysdir = opendir(DRM_DIR_NAME);
3799ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    if (!sysdir) {
3800ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        ret = -errno;
3801cf0f036e3d819fb7894562bfdfea95e5e5f57219Matt Roper        goto free_locals;
3802ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    }
3803ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3804ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    i = 0;
3805ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    while ((dent = readdir(sysdir))) {
3806ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        node_type = drmGetNodeType(dent->d_name);
3807ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        if (node_type < 0)
3808ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov            continue;
3809ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3810ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        snprintf(node, PATH_MAX, "%s/%s", DRM_DIR_NAME, dent->d_name);
3811ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        if (stat(node, &sbuf))
3812ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov            continue;
3813ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3814ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        maj = major(sbuf.st_rdev);
3815ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        min = minor(sbuf.st_rdev);
3816ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3817ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode))
3818ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov            continue;
3819ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3820ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        if (drmParseSubsystemType(maj, min) != subsystem_type)
3821ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov            continue;
3822ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3823ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        switch (subsystem_type) {
3824ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        case DRM_BUS_PCI:
3825138d23117c6b96f57aaa0072992e0480153cfebdEmil Velikov            ret = drmProcessPciDevice(&d, node, node_type, maj, min, true, flags);
3826ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov            if (ret)
3827eebefaf72c55fd2116f4c983ec6724a4d66ab413Jonathan Gray                continue;
3828ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3829ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov            break;
3830f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding
3831f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding        case DRM_BUS_USB:
3832f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding            ret = drmProcessUsbDevice(&d, node, node_type, maj, min, true, flags);
3833f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding            if (ret)
3834f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding                continue;
3835f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding
3836f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding            break;
3837f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding
38387b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding        case DRM_BUS_PLATFORM:
38397b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding            ret = drmProcessPlatformDevice(&d, node, node_type, maj, min, true, flags);
38407b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding            if (ret)
38417b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding                continue;
38427b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
38437b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding            break;
38447b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
38457b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding        case DRM_BUS_HOST1X:
38467b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding            ret = drmProcessHost1xDevice(&d, node, node_type, maj, min, true, flags);
38477b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding            if (ret)
38487b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding                continue;
38497b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
38507b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding            break;
38517b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
3852ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        default:
3853ba5a6ecf81fc2e25a4c7b8c592143faadfdd63dbMatt Roper            continue;
3854ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        }
3855ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3856ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        if (i >= max_count) {
3857ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov            drmDevicePtr *temp;
3858ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3859ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov            max_count += 16;
3860ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov            temp = realloc(local_devices, max_count * sizeof(drmDevicePtr));
3861ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov            if (!temp)
3862ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov                goto free_devices;
3863ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov            local_devices = temp;
3864ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        }
3865ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
38663c20893daa0a56b91869d806ae0d3a8d5d8b4cbaQiang Yu        /* store target at local_devices[0] for ease to use below */
38673c20893daa0a56b91869d806ae0d3a8d5d8b4cbaQiang Yu        if (find_rdev == sbuf.st_rdev && i) {
38683c20893daa0a56b91869d806ae0d3a8d5d8b4cbaQiang Yu            local_devices[i] = local_devices[0];
38693c20893daa0a56b91869d806ae0d3a8d5d8b4cbaQiang Yu            local_devices[0] = d;
38703c20893daa0a56b91869d806ae0d3a8d5d8b4cbaQiang Yu        }
38713c20893daa0a56b91869d806ae0d3a8d5d8b4cbaQiang Yu        else
38723c20893daa0a56b91869d806ae0d3a8d5d8b4cbaQiang Yu            local_devices[i] = d;
3873ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        i++;
3874ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    }
3875ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    node_count = i;
3876ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3877ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    drmFoldDuplicatedDevices(local_devices, node_count);
3878ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3879ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    *device = local_devices[0];
38803c20893daa0a56b91869d806ae0d3a8d5d8b4cbaQiang Yu    drmFreeDevices(&local_devices[1], node_count - 1);
3881ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3882ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    closedir(sysdir);
3883cf0f036e3d819fb7894562bfdfea95e5e5f57219Matt Roper    free(local_devices);
3884677cd97dc4a930af508388713f5016baf664ed18Rob Herring    if (*device == NULL)
3885e17cad1994d321a8279c124e7a85ddddcdd9e4cdThierry Reding        return -ENODEV;
3886ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    return 0;
3887ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3888ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikovfree_devices:
3889ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    drmFreeDevices(local_devices, i);
3890ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    closedir(sysdir);
3891cf0f036e3d819fb7894562bfdfea95e5e5f57219Matt Roper
3892cf0f036e3d819fb7894562bfdfea95e5e5f57219Matt Roperfree_locals:
3893cf0f036e3d819fb7894562bfdfea95e5e5f57219Matt Roper    free(local_devices);
3894ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    return ret;
389508257927231e4f51c38e1d2bdbb8db0c2d4aec40Jonathan Gray#endif
3896ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov}
3897ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3898ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov/**
389911687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov * Get information about the opened drm device
390011687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov *
390111687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov * \param fd file descriptor of the drm device
390211687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov * \param device the address of a drmDevicePtr where the information
390311687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov *               will be allocated in stored
390411687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov *
390511687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov * \return zero on success, negative error code otherwise.
390611687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov */
390711687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikovint drmGetDevice(int fd, drmDevicePtr *device)
390811687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov{
390911687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov    return drmGetDevice2(fd, DRM_DEVICE_GET_PCI_REVISION, device);
391011687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov}
391111687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov
391211687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov/**
3913b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov * Get drm devices on the system
3914b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov *
391511687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov * \param flags feature/behaviour bitmask
3916b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov * \param devices the array of devices with drmDevicePtr elements
3917b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov *                can be NULL to get the device number first
3918b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov * \param max_devices the maximum number of devices for the array
3919b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov *
3920b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov * \return on error - negative error code,
3921b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov *         if devices is NULL - total number of devices available on the system,
3922b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov *         alternatively the number of devices stored in devices[], which is
3923b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov *         capped by the max_devices.
392411687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov *
392511687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov * \note Unlike drmGetDevices it does not retrieve the pci device revision field
392611687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov * unless the DRM_DEVICE_GET_PCI_REVISION \p flag is set.
3927b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov */
392811687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikovint drmGetDevices2(uint32_t flags, drmDevicePtr devices[], int max_devices)
3929b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov{
39305f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    drmDevicePtr *local_devices;
39315f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    drmDevicePtr device;
39325f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    DIR *sysdir;
39335f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    struct dirent *dent;
39345f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    struct stat sbuf;
39355f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    char node[PATH_MAX + 1];
3936b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    int node_type, subsystem_type;
3937b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    int maj, min;
3938fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    int ret, i, node_count, device_count;
3939b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    int max_count = 16;
394011687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov
394111687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov    if (drm_device_validate_flags(flags))
394211687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov        return -EINVAL;
3943b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
39445f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    local_devices = calloc(max_count, sizeof(drmDevicePtr));
39455f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    if (local_devices == NULL)
3946b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        return -ENOMEM;
3947b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
3948b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    sysdir = opendir(DRM_DIR_NAME);
3949b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    if (!sysdir) {
3950b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        ret = -errno;
39518c4a1cbd98bd8d185d489395f33302a17db643a9Matt Roper        goto free_locals;
3952b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    }
3953b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
39545f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    i = 0;
3955b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    while ((dent = readdir(sysdir))) {
3956b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        node_type = drmGetNodeType(dent->d_name);
3957b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        if (node_type < 0)
3958b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov            continue;
3959b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
3960b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        snprintf(node, PATH_MAX, "%s/%s", DRM_DIR_NAME, dent->d_name);
3961b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        if (stat(node, &sbuf))
3962b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov            continue;
3963b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
3964b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        maj = major(sbuf.st_rdev);
3965b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        min = minor(sbuf.st_rdev);
3966b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
3967b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode))
3968b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov            continue;
3969b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
3970a250fceaaa150363accaf3fb71a0e42bcecc40daEmil Velikov        subsystem_type = drmParseSubsystemType(maj, min);
3971b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
3972b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        if (subsystem_type < 0)
3973b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov            continue;
3974b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
3975b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        switch (subsystem_type) {
3976b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        case DRM_BUS_PCI:
3977b40a65d44857394966b25c5587f9dc978643f9c4Emil Velikov            ret = drmProcessPciDevice(&device, node, node_type,
3978138d23117c6b96f57aaa0072992e0480153cfebdEmil Velikov                                      maj, min, devices != NULL, flags);
39795f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov            if (ret)
3980eebefaf72c55fd2116f4c983ec6724a4d66ab413Jonathan Gray                continue;
3981b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
3982b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov            break;
3983f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding
3984f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding        case DRM_BUS_USB:
3985f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding            ret = drmProcessUsbDevice(&device, node, node_type, maj, min,
3986f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding                                      devices != NULL, flags);
3987f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding            if (ret)
3988f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding                goto free_devices;
3989f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding
3990f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding            break;
3991f8484ccbd12ba33ea5b3895efb7a39d986271be0Thierry Reding
39927b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding        case DRM_BUS_PLATFORM:
39937b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding            ret = drmProcessPlatformDevice(&device, node, node_type, maj, min,
39947b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding                                           devices != NULL, flags);
39957b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding            if (ret)
39967b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding                goto free_devices;
39977b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
39987b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding            break;
39997b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
40007b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding        case DRM_BUS_HOST1X:
40017b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding            ret = drmProcessHost1xDevice(&device, node, node_type, maj, min,
40027b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding                                         devices != NULL, flags);
40037b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding            if (ret)
40047b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding                goto free_devices;
40057b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
40067b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding            break;
40077b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74Thierry Reding
4008b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        default:
4009ba5a6ecf81fc2e25a4c7b8c592143faadfdd63dbMatt Roper            continue;
4010b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        }
4011b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
40125f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov        if (i >= max_count) {
40135f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov            drmDevicePtr *temp;
4014b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
40155f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov            max_count += 16;
40165f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov            temp = realloc(local_devices, max_count * sizeof(drmDevicePtr));
40175f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov            if (!temp)
40185f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov                goto free_devices;
40195f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov            local_devices = temp;
40205f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov        }
40215f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov
40225f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov        local_devices[i] = device;
40235f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov        i++;
4024b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    }
40255f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    node_count = i;
4026b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
4027fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    drmFoldDuplicatedDevices(local_devices, node_count);
4028b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
40295f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    device_count = 0;
403070b64073f7d1bf56a30f7a809bd984d3ad688b9fQiang Yu    for (i = 0; i < node_count; i++) {
403150d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        if (!local_devices[i])
403250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            continue;
403370b64073f7d1bf56a30f7a809bd984d3ad688b9fQiang Yu
40345f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov        if ((devices != NULL) && (device_count < max_devices))
40355f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov            devices[device_count] = local_devices[i];
40365f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov        else
40375f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov            drmFreeDevice(&local_devices[i]);
4038b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
40395f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov        device_count++;
40405f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    }
4041b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
4042b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    closedir(sysdir);
40438c4a1cbd98bd8d185d489395f33302a17db643a9Matt Roper    free(local_devices);
40445f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    return device_count;
40455f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov
40465f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikovfree_devices:
40475f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    drmFreeDevices(local_devices, i);
4048b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    closedir(sysdir);
40498c4a1cbd98bd8d185d489395f33302a17db643a9Matt Roper
40508c4a1cbd98bd8d185d489395f33302a17db643a9Matt Roperfree_locals:
40518c4a1cbd98bd8d185d489395f33302a17db643a9Matt Roper    free(local_devices);
4052b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    return ret;
4053b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov}
405437d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov
405511687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov/**
405611687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov * Get drm devices on the system
405711687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov *
405811687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov * \param devices the array of devices with drmDevicePtr elements
405911687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov *                can be NULL to get the device number first
406011687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov * \param max_devices the maximum number of devices for the array
406111687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov *
406211687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov * \return on error - negative error code,
406311687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov *         if devices is NULL - total number of devices available on the system,
406411687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov *         alternatively the number of devices stored in devices[], which is
406511687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov *         capped by the max_devices.
406611687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov */
406711687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikovint drmGetDevices(drmDevicePtr devices[], int max_devices)
406811687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov{
406911687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov    return drmGetDevices2(DRM_DEVICE_GET_PCI_REVISION, devices, max_devices);
407011687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov}
407111687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov
407237d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikovchar *drmGetDeviceNameFromFd2(int fd)
407337d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov{
407437d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov#ifdef __linux__
407537d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov    struct stat sbuf;
40765403cb39c124c444babec51bd4499971cd86ccfaThierry Reding    char path[PATH_MAX + 1], *value;
407737d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov    unsigned int maj, min;
407837d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov
407937d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov    if (fstat(fd, &sbuf))
408037d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov        return NULL;
408137d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov
408237d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov    maj = major(sbuf.st_rdev);
408337d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov    min = minor(sbuf.st_rdev);
408437d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov
408537d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov    if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode))
408637d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov        return NULL;
408737d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov
40885403cb39c124c444babec51bd4499971cd86ccfaThierry Reding    snprintf(path, sizeof(path), "/sys/dev/char/%d:%d", maj, min);
408937d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov
40905403cb39c124c444babec51bd4499971cd86ccfaThierry Reding    value = sysfs_uevent_get(path, "DEVNAME");
40915403cb39c124c444babec51bd4499971cd86ccfaThierry Reding    if (!value)
40925403cb39c124c444babec51bd4499971cd86ccfaThierry Reding        return NULL;
409337d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov
40945403cb39c124c444babec51bd4499971cd86ccfaThierry Reding    snprintf(path, sizeof(path), "/dev/%s", value);
40955403cb39c124c444babec51bd4499971cd86ccfaThierry Reding    free(value);
409637d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov
40975403cb39c124c444babec51bd4499971cd86ccfaThierry Reding    return strdup(path);
409837d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov#else
4099e2e766d5acdbb826f1cfe5643669db54ee86f456Jonathan Gray    struct stat      sbuf;
4100e2e766d5acdbb826f1cfe5643669db54ee86f456Jonathan Gray    char             node[PATH_MAX + 1];
4101e2e766d5acdbb826f1cfe5643669db54ee86f456Jonathan Gray    const char      *dev_name;
4102e2e766d5acdbb826f1cfe5643669db54ee86f456Jonathan Gray    int              node_type;
4103e2e766d5acdbb826f1cfe5643669db54ee86f456Jonathan Gray    int              maj, min, n, base;
4104e2e766d5acdbb826f1cfe5643669db54ee86f456Jonathan Gray
4105e2e766d5acdbb826f1cfe5643669db54ee86f456Jonathan Gray    if (fstat(fd, &sbuf))
4106e2e766d5acdbb826f1cfe5643669db54ee86f456Jonathan Gray        return NULL;
4107e2e766d5acdbb826f1cfe5643669db54ee86f456Jonathan Gray
4108e2e766d5acdbb826f1cfe5643669db54ee86f456Jonathan Gray    maj = major(sbuf.st_rdev);
4109e2e766d5acdbb826f1cfe5643669db54ee86f456Jonathan Gray    min = minor(sbuf.st_rdev);
4110e2e766d5acdbb826f1cfe5643669db54ee86f456Jonathan Gray
4111e2e766d5acdbb826f1cfe5643669db54ee86f456Jonathan Gray    if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode))
4112e2e766d5acdbb826f1cfe5643669db54ee86f456Jonathan Gray        return NULL;
4113e2e766d5acdbb826f1cfe5643669db54ee86f456Jonathan Gray
4114e2e766d5acdbb826f1cfe5643669db54ee86f456Jonathan Gray    node_type = drmGetMinorType(min);
4115e2e766d5acdbb826f1cfe5643669db54ee86f456Jonathan Gray    if (node_type == -1)
4116e2e766d5acdbb826f1cfe5643669db54ee86f456Jonathan Gray        return NULL;
4117e2e766d5acdbb826f1cfe5643669db54ee86f456Jonathan Gray
4118e2e766d5acdbb826f1cfe5643669db54ee86f456Jonathan Gray    switch (node_type) {
4119e2e766d5acdbb826f1cfe5643669db54ee86f456Jonathan Gray    case DRM_NODE_PRIMARY:
4120e2e766d5acdbb826f1cfe5643669db54ee86f456Jonathan Gray        dev_name = DRM_DEV_NAME;
4121e2e766d5acdbb826f1cfe5643669db54ee86f456Jonathan Gray        break;
4122e2e766d5acdbb826f1cfe5643669db54ee86f456Jonathan Gray    case DRM_NODE_CONTROL:
4123e2e766d5acdbb826f1cfe5643669db54ee86f456Jonathan Gray        dev_name = DRM_CONTROL_DEV_NAME;
4124e2e766d5acdbb826f1cfe5643669db54ee86f456Jonathan Gray        break;
4125e2e766d5acdbb826f1cfe5643669db54ee86f456Jonathan Gray    case DRM_NODE_RENDER:
4126e2e766d5acdbb826f1cfe5643669db54ee86f456Jonathan Gray        dev_name = DRM_RENDER_DEV_NAME;
4127e2e766d5acdbb826f1cfe5643669db54ee86f456Jonathan Gray        break;
4128e2e766d5acdbb826f1cfe5643669db54ee86f456Jonathan Gray    default:
4129e2e766d5acdbb826f1cfe5643669db54ee86f456Jonathan Gray        return NULL;
4130e2e766d5acdbb826f1cfe5643669db54ee86f456Jonathan Gray    };
4131e2e766d5acdbb826f1cfe5643669db54ee86f456Jonathan Gray
4132e2e766d5acdbb826f1cfe5643669db54ee86f456Jonathan Gray    base = drmGetMinorBase(node_type);
4133e2e766d5acdbb826f1cfe5643669db54ee86f456Jonathan Gray    if (base < 0)
4134e2e766d5acdbb826f1cfe5643669db54ee86f456Jonathan Gray        return NULL;
4135e2e766d5acdbb826f1cfe5643669db54ee86f456Jonathan Gray
4136e2e766d5acdbb826f1cfe5643669db54ee86f456Jonathan Gray    n = snprintf(node, PATH_MAX, dev_name, DRM_DIR_NAME, min - base);
4137e2e766d5acdbb826f1cfe5643669db54ee86f456Jonathan Gray    if (n == -1 || n >= PATH_MAX)
4138e2e766d5acdbb826f1cfe5643669db54ee86f456Jonathan Gray      return NULL;
4139e2e766d5acdbb826f1cfe5643669db54ee86f456Jonathan Gray
4140e2e766d5acdbb826f1cfe5643669db54ee86f456Jonathan Gray    return strdup(node);
414137d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov#endif
414237d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov}
4143