xf86drm.c revision fd190564daa4cd530833a94606646730a5c0ee6c
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{
754eb7c2d5e63e0e9d133b16880e36c14676276d412Rob Clark    if (!drmAvailable() && name != NULL && drm_server_info &&
755eb7c2d5e63e0e9d133b16880e36c14676276d412Rob Clark        drm_server_info->load_module) {
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;
2841f189011b362a2dff3ab914523e546cc96f53df39Jonathan Gray    int n;
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
2866f189011b362a2dff3ab914523e546cc96f53df39Jonathan Gray    n = snprintf(buf, sizeof(buf), dev_name, DRM_DIR_NAME, min);
2867f189011b362a2dff3ab914523e546cc96f53df39Jonathan Gray    if (n == -1 || n >= sizeof(buf))
2868f189011b362a2dff3ab914523e546cc96f53df39Jonathan Gray        return NULL;
2869f189011b362a2dff3ab914523e546cc96f53df39Jonathan Gray
2870f189011b362a2dff3ab914523e546cc96f53df39Jonathan Gray    return strdup(buf);
28710ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov#endif
287250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    return NULL;
28730ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov}
28740ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov
28750ca03a4087a550646de7f26b6b53a932e8546474Emil Velikovchar *drmGetPrimaryDeviceNameFromFd(int fd)
28760ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov{
287750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    return drmGetMinorNameForFD(fd, DRM_NODE_PRIMARY);
28780ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov}
28790ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov
28800ca03a4087a550646de7f26b6b53a932e8546474Emil Velikovchar *drmGetRenderDeviceNameFromFd(int fd)
28810ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov{
288250d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely    return drmGetMinorNameForFD(fd, DRM_NODE_RENDER);
28830ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov}
2884b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
2885a250fceaaa150363accaf3fb71a0e42bcecc40daEmil Velikovstatic int drmParseSubsystemType(int maj, int min)
2886b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov{
2887291b2bb92c5fc90101417b80bbdc6c994be5fff2Emil Velikov#ifdef __linux__
2888a250fceaaa150363accaf3fb71a0e42bcecc40daEmil Velikov    char path[PATH_MAX + 1];
2889b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    char link[PATH_MAX + 1] = "";
2890b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    char *name;
2891b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
2892a250fceaaa150363accaf3fb71a0e42bcecc40daEmil Velikov    snprintf(path, PATH_MAX, "/sys/dev/char/%d:%d/device/subsystem",
2893a250fceaaa150363accaf3fb71a0e42bcecc40daEmil Velikov             maj, min);
2894a250fceaaa150363accaf3fb71a0e42bcecc40daEmil Velikov
2895a250fceaaa150363accaf3fb71a0e42bcecc40daEmil Velikov    if (readlink(path, link, PATH_MAX) < 0)
2896a250fceaaa150363accaf3fb71a0e42bcecc40daEmil Velikov        return -errno;
2897b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
2898b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    name = strrchr(link, '/');
2899b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    if (!name)
2900b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        return -EINVAL;
2901b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
2902a250fceaaa150363accaf3fb71a0e42bcecc40daEmil Velikov    if (strncmp(name, "/pci", 4) == 0)
2903b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        return DRM_BUS_PCI;
2904b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
2905b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    return -EINVAL;
2906d05b9f2dde17e60996437332219b4b568f7edefaJonathan Gray#elif defined(__OpenBSD__)
2907d05b9f2dde17e60996437332219b4b568f7edefaJonathan Gray	return DRM_BUS_PCI;
2908291b2bb92c5fc90101417b80bbdc6c994be5fff2Emil Velikov#else
2909291b2bb92c5fc90101417b80bbdc6c994be5fff2Emil Velikov#warning "Missing implementation of drmParseSubsystemType"
2910291b2bb92c5fc90101417b80bbdc6c994be5fff2Emil Velikov    return -EINVAL;
2911291b2bb92c5fc90101417b80bbdc6c994be5fff2Emil Velikov#endif
2912b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov}
2913b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
2914536e0deba3829e194aafda6d9a1d9e938ba8277aEmil Velikovstatic int drmParsePciBusInfo(int maj, int min, drmPciBusInfoPtr info)
2915b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov{
2916291b2bb92c5fc90101417b80bbdc6c994be5fff2Emil Velikov#ifdef __linux__
2917536e0deba3829e194aafda6d9a1d9e938ba8277aEmil Velikov    char path[PATH_MAX + 1];
2918f53d3542c1dfa2a1c1a5a7155d058df9a6bcce7bEmil Velikov    char data[512 + 1];
2919536e0deba3829e194aafda6d9a1d9e938ba8277aEmil Velikov    char *str;
2920b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    int domain, bus, dev, func;
2921536e0deba3829e194aafda6d9a1d9e938ba8277aEmil Velikov    int fd, ret;
2922b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
2923536e0deba3829e194aafda6d9a1d9e938ba8277aEmil Velikov    snprintf(path, PATH_MAX, "/sys/dev/char/%d:%d/device/uevent", maj, min);
2924536e0deba3829e194aafda6d9a1d9e938ba8277aEmil Velikov    fd = open(path, O_RDONLY);
2925536e0deba3829e194aafda6d9a1d9e938ba8277aEmil Velikov    if (fd < 0)
2926536e0deba3829e194aafda6d9a1d9e938ba8277aEmil Velikov        return -errno;
2927b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
2928536e0deba3829e194aafda6d9a1d9e938ba8277aEmil Velikov    ret = read(fd, data, sizeof(data));
2929f53d3542c1dfa2a1c1a5a7155d058df9a6bcce7bEmil Velikov    data[sizeof(data)-1] = '\0';
2930536e0deba3829e194aafda6d9a1d9e938ba8277aEmil Velikov    close(fd);
2931536e0deba3829e194aafda6d9a1d9e938ba8277aEmil Velikov    if (ret < 0)
2932536e0deba3829e194aafda6d9a1d9e938ba8277aEmil Velikov        return -errno;
2933b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
2934536e0deba3829e194aafda6d9a1d9e938ba8277aEmil Velikov#define TAG "PCI_SLOT_NAME="
2935536e0deba3829e194aafda6d9a1d9e938ba8277aEmil Velikov    str = strstr(data, TAG);
2936536e0deba3829e194aafda6d9a1d9e938ba8277aEmil Velikov    if (str == NULL)
2937536e0deba3829e194aafda6d9a1d9e938ba8277aEmil Velikov        return -EINVAL;
2938b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
2939536e0deba3829e194aafda6d9a1d9e938ba8277aEmil Velikov    if (sscanf(str, TAG "%04x:%02x:%02x.%1u",
2940b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov               &domain, &bus, &dev, &func) != 4)
2941b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        return -EINVAL;
2942536e0deba3829e194aafda6d9a1d9e938ba8277aEmil Velikov#undef TAG
2943b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
2944b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    info->domain = domain;
2945b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    info->bus = bus;
2946b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    info->dev = dev;
2947b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    info->func = func;
2948b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
2949b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    return 0;
2950fd190564daa4cd530833a94606646730a5c0ee6cJonathan Gray#elif defined(__OpenBSD__)
2951fd190564daa4cd530833a94606646730a5c0ee6cJonathan Gray    struct drm_pciinfo pinfo;
2952fd190564daa4cd530833a94606646730a5c0ee6cJonathan Gray    int fd, type;
2953fd190564daa4cd530833a94606646730a5c0ee6cJonathan Gray
2954fd190564daa4cd530833a94606646730a5c0ee6cJonathan Gray    type = drmGetMinorType(min);
2955fd190564daa4cd530833a94606646730a5c0ee6cJonathan Gray    if (type == -1)
2956fd190564daa4cd530833a94606646730a5c0ee6cJonathan Gray        return -ENODEV;
2957fd190564daa4cd530833a94606646730a5c0ee6cJonathan Gray
2958fd190564daa4cd530833a94606646730a5c0ee6cJonathan Gray    fd = drmOpenMinor(min, 0, type);
2959fd190564daa4cd530833a94606646730a5c0ee6cJonathan Gray    if (fd < 0)
2960fd190564daa4cd530833a94606646730a5c0ee6cJonathan Gray        return -errno;
2961fd190564daa4cd530833a94606646730a5c0ee6cJonathan Gray
2962fd190564daa4cd530833a94606646730a5c0ee6cJonathan Gray    if (drmIoctl(fd, DRM_IOCTL_GET_PCIINFO, &pinfo)) {
2963fd190564daa4cd530833a94606646730a5c0ee6cJonathan Gray        close(fd);
2964fd190564daa4cd530833a94606646730a5c0ee6cJonathan Gray        return -errno;
2965fd190564daa4cd530833a94606646730a5c0ee6cJonathan Gray    }
2966fd190564daa4cd530833a94606646730a5c0ee6cJonathan Gray    close(fd);
2967fd190564daa4cd530833a94606646730a5c0ee6cJonathan Gray
2968fd190564daa4cd530833a94606646730a5c0ee6cJonathan Gray    info->domain = pinfo.domain;
2969fd190564daa4cd530833a94606646730a5c0ee6cJonathan Gray    info->bus = pinfo.bus;
2970fd190564daa4cd530833a94606646730a5c0ee6cJonathan Gray    info->dev = pinfo.dev;
2971fd190564daa4cd530833a94606646730a5c0ee6cJonathan Gray    info->func = pinfo.func;
2972fd190564daa4cd530833a94606646730a5c0ee6cJonathan Gray
2973fd190564daa4cd530833a94606646730a5c0ee6cJonathan Gray    return 0;
2974291b2bb92c5fc90101417b80bbdc6c994be5fff2Emil Velikov#else
2975291b2bb92c5fc90101417b80bbdc6c994be5fff2Emil Velikov#warning "Missing implementation of drmParsePciBusInfo"
2976291b2bb92c5fc90101417b80bbdc6c994be5fff2Emil Velikov    return -EINVAL;
2977291b2bb92c5fc90101417b80bbdc6c994be5fff2Emil Velikov#endif
2978b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov}
2979b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
2980bc2aca9e22bf2cc82874f3e44568c684eec9c5e1Emil Velikovstatic int drmCompareBusInfo(drmDevicePtr a, drmDevicePtr b)
2981b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov{
2982bc2aca9e22bf2cc82874f3e44568c684eec9c5e1Emil Velikov    if (a == NULL || b == NULL)
2983bc2aca9e22bf2cc82874f3e44568c684eec9c5e1Emil Velikov        return -1;
2984bc2aca9e22bf2cc82874f3e44568c684eec9c5e1Emil Velikov
2985b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    if (a->bustype != b->bustype)
2986bc2aca9e22bf2cc82874f3e44568c684eec9c5e1Emil Velikov        return -1;
2987b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
2988b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    switch (a->bustype) {
2989b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    case DRM_BUS_PCI:
2990bc2aca9e22bf2cc82874f3e44568c684eec9c5e1Emil Velikov        return memcmp(a->businfo.pci, b->businfo.pci, sizeof(drmPciBusInfo));
2991b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    default:
2992b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        break;
2993b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    }
2994b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
2995bc2aca9e22bf2cc82874f3e44568c684eec9c5e1Emil Velikov    return -1;
2996b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov}
2997b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
2998b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikovstatic int drmGetNodeType(const char *name)
2999b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov{
3000b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    if (strncmp(name, DRM_PRIMARY_MINOR_NAME,
3001b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        sizeof(DRM_PRIMARY_MINOR_NAME) - 1) == 0)
3002b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        return DRM_NODE_PRIMARY;
3003b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
3004b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    if (strncmp(name, DRM_CONTROL_MINOR_NAME,
3005b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        sizeof(DRM_CONTROL_MINOR_NAME ) - 1) == 0)
3006b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        return DRM_NODE_CONTROL;
3007b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
3008b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    if (strncmp(name, DRM_RENDER_MINOR_NAME,
3009b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        sizeof(DRM_RENDER_MINOR_NAME) - 1) == 0)
3010b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        return DRM_NODE_RENDER;
3011b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
3012b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    return -EINVAL;
3013b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov}
3014b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
30155f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikovstatic int drmGetMaxNodeName(void)
30165f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov{
30175f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    return sizeof(DRM_DIR_NAME) +
30185f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov           MAX3(sizeof(DRM_PRIMARY_MINOR_NAME),
30195f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov                sizeof(DRM_CONTROL_MINOR_NAME),
30205f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov                sizeof(DRM_RENDER_MINOR_NAME)) +
3021ce97507cfcbdbdc520872417b5605f3b807794ffEric Engestrom           3 /* length of the node number */;
30225f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov}
30235f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov
3024291b2bb92c5fc90101417b80bbdc6c994be5fff2Emil Velikov#ifdef __linux__
3025aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikovstatic int parse_separate_sysfs_files(int maj, int min,
302611687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov                                      drmPciDeviceInfoPtr device,
302711687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov                                      bool ignore_revision)
3028aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov{
3029aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
3030aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov    static const char *attrs[] = {
3031aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov      "revision", /* Older kernels are missing the file, so check for it first */
3032aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov      "vendor",
3033aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov      "device",
3034aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov      "subsystem_vendor",
3035aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov      "subsystem_device",
3036aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov    };
3037aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov    char path[PATH_MAX + 1];
3038aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov    unsigned int data[ARRAY_SIZE(attrs)];
3039aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov    FILE *fp;
3040aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov    int ret;
3041aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov
304211687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov    for (unsigned i = ignore_revision ? 1 : 0; i < ARRAY_SIZE(attrs); i++) {
3043aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov        snprintf(path, PATH_MAX, "/sys/dev/char/%d:%d/device/%s", maj, min,
3044aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov                 attrs[i]);
3045aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov        fp = fopen(path, "r");
3046aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov        if (!fp)
3047aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov            return -errno;
3048aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov
3049aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov        ret = fscanf(fp, "%x", &data[i]);
3050aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov        fclose(fp);
3051aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov        if (ret != 1)
3052aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov            return -errno;
3053aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov
3054aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov    }
3055aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov
305611687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov    device->revision_id = ignore_revision ? 0xff : data[0] & 0xff;
3057aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov    device->vendor_id = data[1] & 0xffff;
3058aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov    device->device_id = data[2] & 0xffff;
3059aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov    device->subvendor_id = data[3] & 0xffff;
3060aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov    device->subdevice_id = data[4] & 0xffff;
3061aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov
3062aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov    return 0;
3063aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov}
3064aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov
3065aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikovstatic int parse_config_sysfs_file(int maj, int min,
3066aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov                                   drmPciDeviceInfoPtr device)
3067aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov{
3068ef5192e9c7897c82da815a2c893b2e2562997a3aEmil Velikov    char path[PATH_MAX + 1];
3069ef5192e9c7897c82da815a2c893b2e2562997a3aEmil Velikov    unsigned char config[64];
3070ef5192e9c7897c82da815a2c893b2e2562997a3aEmil Velikov    int fd, ret;
3071ef5192e9c7897c82da815a2c893b2e2562997a3aEmil Velikov
3072b40a65d44857394966b25c5587f9dc978643f9c4Emil Velikov    snprintf(path, PATH_MAX, "/sys/dev/char/%d:%d/device/config", maj, min);
3073ef5192e9c7897c82da815a2c893b2e2562997a3aEmil Velikov    fd = open(path, O_RDONLY);
3074ef5192e9c7897c82da815a2c893b2e2562997a3aEmil Velikov    if (fd < 0)
3075ef5192e9c7897c82da815a2c893b2e2562997a3aEmil Velikov        return -errno;
3076ef5192e9c7897c82da815a2c893b2e2562997a3aEmil Velikov
3077ef5192e9c7897c82da815a2c893b2e2562997a3aEmil Velikov    ret = read(fd, config, sizeof(config));
3078ef5192e9c7897c82da815a2c893b2e2562997a3aEmil Velikov    close(fd);
3079ef5192e9c7897c82da815a2c893b2e2562997a3aEmil Velikov    if (ret < 0)
3080ef5192e9c7897c82da815a2c893b2e2562997a3aEmil Velikov        return -errno;
3081b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
3082b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    device->vendor_id = config[0] | (config[1] << 8);
3083b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    device->device_id = config[2] | (config[3] << 8);
3084b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    device->revision_id = config[8];
3085b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    device->subvendor_id = config[44] | (config[45] << 8);
3086b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    device->subdevice_id = config[46] | (config[47] << 8);
3087b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
3088b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    return 0;
3089aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov}
3090aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov#endif
3091aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov
3092aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikovstatic int drmParsePciDeviceInfo(int maj, int min,
3093aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov                                 drmPciDeviceInfoPtr device,
3094aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov                                 uint32_t flags)
3095aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov{
3096aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov#ifdef __linux__
309711687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov    if (!(flags & DRM_DEVICE_GET_PCI_REVISION))
309811687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov        return parse_separate_sysfs_files(maj, min, device, true);
309911687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov
310011687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov    if (parse_separate_sysfs_files(maj, min, device, false))
3101aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov        return parse_config_sysfs_file(maj, min, device);
3102aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov
3103aae3f318d5aca81b87a14360116bb766a51e82efEmil Velikov    return 0;
3104c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray#elif defined(__OpenBSD__)
3105c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray    struct drm_pciinfo pinfo;
3106c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray    int fd, type;
3107c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray
3108c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray    type = drmGetMinorType(min);
3109c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray    if (type == -1)
3110c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray        return -ENODEV;
3111c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray
3112c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray    fd = drmOpenMinor(min, 0, type);
3113c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray    if (fd < 0)
3114c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray        return -errno;
3115c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray
3116c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray    if (drmIoctl(fd, DRM_IOCTL_GET_PCIINFO, &pinfo)) {
3117c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray        close(fd);
3118c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray        return -errno;
3119c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray    }
3120c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray    close(fd);
3121c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray
3122c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray    device->vendor_id = pinfo.vendor_id;
3123c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray    device->device_id = pinfo.device_id;
3124c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray    device->revision_id = pinfo.revision_id;
3125c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray    device->subvendor_id = pinfo.subvendor_id;
3126c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray    device->subdevice_id = pinfo.subdevice_id;
3127c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray
3128c0ef1d078800a43611136e65be3c9c7472ac9d3fJonathan Gray    return 0;
3129291b2bb92c5fc90101417b80bbdc6c994be5fff2Emil Velikov#else
3130291b2bb92c5fc90101417b80bbdc6c994be5fff2Emil Velikov#warning "Missing implementation of drmParsePciDeviceInfo"
3131291b2bb92c5fc90101417b80bbdc6c994be5fff2Emil Velikov    return -EINVAL;
3132291b2bb92c5fc90101417b80bbdc6c994be5fff2Emil Velikov#endif
3133b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov}
3134b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
3135ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikovvoid drmFreeDevice(drmDevicePtr *device)
3136b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov{
3137b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    if (device == NULL)
3138b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        return;
3139b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
31405f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    free(*device);
31415f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    *device = NULL;
3142b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov}
3143b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
3144b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikovvoid drmFreeDevices(drmDevicePtr devices[], int count)
3145b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov{
3146b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    int i;
3147b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
3148b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    if (devices == NULL)
3149b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        return;
3150b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
31516c056eecd56374b069ed24c81f59b6638cde2f3aQiang Yu    for (i = 0; i < count; i++)
31526c056eecd56374b069ed24c81f59b6638cde2f3aQiang Yu        if (devices[i])
31536c056eecd56374b069ed24c81f59b6638cde2f3aQiang Yu            drmFreeDevice(&devices[i]);
3154b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov}
3155b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
3156b40a65d44857394966b25c5587f9dc978643f9c4Emil Velikovstatic int drmProcessPciDevice(drmDevicePtr *device,
3157fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov                               const char *node, int node_type,
3158138d23117c6b96f57aaa0072992e0480153cfebdEmil Velikov                               int maj, int min, bool fetch_deviceinfo,
3159138d23117c6b96f57aaa0072992e0480153cfebdEmil Velikov                               uint32_t flags)
3160fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov{
31619bdec97a1991c3cc53d1601eb809e33b154a198dNicolai Hähnle    const int max_node_str = ALIGN(drmGetMaxNodeName(), sizeof(void *));
3162fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    int ret, i;
31633045523de214fb7df92ee3c8482e883637504bbeMichel Dänzer    char *addr;
3164fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov
31653045523de214fb7df92ee3c8482e883637504bbeMichel Dänzer    *device = calloc(1, sizeof(drmDevice) +
316650d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                     (DRM_NODE_MAX * (sizeof(void *) + max_node_str)) +
316750d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                     sizeof(drmPciBusInfo) +
316850d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely                     sizeof(drmPciDeviceInfo));
3169fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    if (!*device)
3170fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov        return -ENOMEM;
3171fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov
31723045523de214fb7df92ee3c8482e883637504bbeMichel Dänzer    addr = (char*)*device;
317350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely
3174fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    (*device)->bustype = DRM_BUS_PCI;
3175fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    (*device)->available_nodes = 1 << node_type;
3176fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov
3177fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    addr += sizeof(drmDevice);
31783045523de214fb7df92ee3c8482e883637504bbeMichel Dänzer    (*device)->nodes = (char**)addr;
3179fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov
3180fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    addr += DRM_NODE_MAX * sizeof(void *);
3181fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    for (i = 0; i < DRM_NODE_MAX; i++) {
3182fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov        (*device)->nodes[i] = addr;
3183fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov        addr += max_node_str;
3184fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    }
3185fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    memcpy((*device)->nodes[node_type], node, max_node_str);
3186fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov
31873045523de214fb7df92ee3c8482e883637504bbeMichel Dänzer    (*device)->businfo.pci = (drmPciBusInfoPtr)addr;
3188fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov
3189fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    ret = drmParsePciBusInfo(maj, min, (*device)->businfo.pci);
3190fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    if (ret)
3191fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov        goto free_device;
3192fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov
3193fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    // Fetch the device info if the user has requested it
3194fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    if (fetch_deviceinfo) {
3195fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov        addr += sizeof(drmPciBusInfo);
31963045523de214fb7df92ee3c8482e883637504bbeMichel Dänzer        (*device)->deviceinfo.pci = (drmPciDeviceInfoPtr)addr;
3197fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov
3198138d23117c6b96f57aaa0072992e0480153cfebdEmil Velikov        ret = drmParsePciDeviceInfo(maj, min, (*device)->deviceinfo.pci, flags);
3199fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov        if (ret)
3200fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov            goto free_device;
3201fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    }
3202fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    return 0;
3203fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov
3204fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikovfree_device:
3205fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    free(*device);
3206fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    *device = NULL;
3207fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    return ret;
3208fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov}
3209fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov
32103c20893daa0a56b91869d806ae0d3a8d5d8b4cbaQiang Yu/* Consider devices located on the same bus as duplicate and fold the respective
32113c20893daa0a56b91869d806ae0d3a8d5d8b4cbaQiang Yu * entries into a single one.
32123c20893daa0a56b91869d806ae0d3a8d5d8b4cbaQiang Yu *
32133c20893daa0a56b91869d806ae0d3a8d5d8b4cbaQiang Yu * Note: this leaves "gaps" in the array, while preserving the length.
32143c20893daa0a56b91869d806ae0d3a8d5d8b4cbaQiang Yu */
3215fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikovstatic void drmFoldDuplicatedDevices(drmDevicePtr local_devices[], int count)
3216fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov{
3217fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    int node_type, i, j;
3218fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov
3219fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    for (i = 0; i < count; i++) {
3220fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov        for (j = i + 1; j < count; j++) {
3221fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov            if (drmCompareBusInfo(local_devices[i], local_devices[j]) == 0) {
3222fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov                local_devices[i]->available_nodes |= local_devices[j]->available_nodes;
3223fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov                node_type = log2(local_devices[j]->available_nodes);
3224fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov                memcpy(local_devices[i]->nodes[node_type],
3225fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov                       local_devices[j]->nodes[node_type], drmGetMaxNodeName());
3226fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov                drmFreeDevice(&local_devices[j]);
3227fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov            }
3228fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov        }
3229fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    }
3230fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov}
3231fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov
323211687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov/* Check that the given flags are valid returning 0 on success */
323311687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikovstatic int
323411687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikovdrm_device_validate_flags(uint32_t flags)
323511687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov{
323611687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov        return (flags & ~DRM_DEVICE_GET_PCI_REVISION);
323711687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov}
323811687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov
3239b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov/**
3240ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov * Get information about the opened drm device
3241ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov *
3242ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov * \param fd file descriptor of the drm device
324311687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov * \param flags feature/behaviour bitmask
3244ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov * \param device the address of a drmDevicePtr where the information
3245ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov *               will be allocated in stored
3246ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov *
3247ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov * \return zero on success, negative error code otherwise.
324811687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov *
324911687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov * \note Unlike drmGetDevice it does not retrieve the pci device revision field
325011687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov * unless the DRM_DEVICE_GET_PCI_REVISION \p flag is set.
3251ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov */
325211687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikovint drmGetDevice2(int fd, uint32_t flags, drmDevicePtr *device)
3253ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov{
3254ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    drmDevicePtr *local_devices;
3255ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    drmDevicePtr d;
3256ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    DIR *sysdir;
3257ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    struct dirent *dent;
3258ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    struct stat sbuf;
3259ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    char node[PATH_MAX + 1];
3260ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    int node_type, subsystem_type;
3261ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    int maj, min;
3262ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    int ret, i, node_count;
3263ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    int max_count = 16;
32643c20893daa0a56b91869d806ae0d3a8d5d8b4cbaQiang Yu    dev_t find_rdev;
326511687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov
326611687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov    if (drm_device_validate_flags(flags))
326711687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov        return -EINVAL;
3268ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3269ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    if (fd == -1 || device == NULL)
3270ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        return -EINVAL;
3271ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3272ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    if (fstat(fd, &sbuf))
3273ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        return -errno;
3274ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
32753c20893daa0a56b91869d806ae0d3a8d5d8b4cbaQiang Yu    find_rdev = sbuf.st_rdev;
3276ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    maj = major(sbuf.st_rdev);
3277ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    min = minor(sbuf.st_rdev);
3278ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3279ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode))
3280ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        return -EINVAL;
3281ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3282ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    subsystem_type = drmParseSubsystemType(maj, min);
3283ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3284ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    local_devices = calloc(max_count, sizeof(drmDevicePtr));
3285ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    if (local_devices == NULL)
3286ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        return -ENOMEM;
3287ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3288ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    sysdir = opendir(DRM_DIR_NAME);
3289ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    if (!sysdir) {
3290ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        ret = -errno;
3291cf0f036e3d819fb7894562bfdfea95e5e5f57219Matt Roper        goto free_locals;
3292ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    }
3293ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3294ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    i = 0;
3295ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    while ((dent = readdir(sysdir))) {
3296ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        node_type = drmGetNodeType(dent->d_name);
3297ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        if (node_type < 0)
3298ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov            continue;
3299ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3300ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        snprintf(node, PATH_MAX, "%s/%s", DRM_DIR_NAME, dent->d_name);
3301ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        if (stat(node, &sbuf))
3302ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov            continue;
3303ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3304ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        maj = major(sbuf.st_rdev);
3305ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        min = minor(sbuf.st_rdev);
3306ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3307ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode))
3308ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov            continue;
3309ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3310ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        if (drmParseSubsystemType(maj, min) != subsystem_type)
3311ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov            continue;
3312ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3313ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        switch (subsystem_type) {
3314ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        case DRM_BUS_PCI:
3315138d23117c6b96f57aaa0072992e0480153cfebdEmil Velikov            ret = drmProcessPciDevice(&d, node, node_type, maj, min, true, flags);
3316ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov            if (ret)
3317ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov                goto free_devices;
3318ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3319ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov            break;
3320ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        default:
3321ba5a6ecf81fc2e25a4c7b8c592143faadfdd63dbMatt Roper            continue;
3322ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        }
3323ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3324ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        if (i >= max_count) {
3325ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov            drmDevicePtr *temp;
3326ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3327ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov            max_count += 16;
3328ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov            temp = realloc(local_devices, max_count * sizeof(drmDevicePtr));
3329ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov            if (!temp)
3330ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov                goto free_devices;
3331ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov            local_devices = temp;
3332ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        }
3333ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
33343c20893daa0a56b91869d806ae0d3a8d5d8b4cbaQiang Yu        /* store target at local_devices[0] for ease to use below */
33353c20893daa0a56b91869d806ae0d3a8d5d8b4cbaQiang Yu        if (find_rdev == sbuf.st_rdev && i) {
33363c20893daa0a56b91869d806ae0d3a8d5d8b4cbaQiang Yu            local_devices[i] = local_devices[0];
33373c20893daa0a56b91869d806ae0d3a8d5d8b4cbaQiang Yu            local_devices[0] = d;
33383c20893daa0a56b91869d806ae0d3a8d5d8b4cbaQiang Yu        }
33393c20893daa0a56b91869d806ae0d3a8d5d8b4cbaQiang Yu        else
33403c20893daa0a56b91869d806ae0d3a8d5d8b4cbaQiang Yu            local_devices[i] = d;
3341ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        i++;
3342ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    }
3343ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    node_count = i;
3344ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3345ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    drmFoldDuplicatedDevices(local_devices, node_count);
3346ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3347ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    *device = local_devices[0];
33483c20893daa0a56b91869d806ae0d3a8d5d8b4cbaQiang Yu    drmFreeDevices(&local_devices[1], node_count - 1);
3349ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3350ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    closedir(sysdir);
3351cf0f036e3d819fb7894562bfdfea95e5e5f57219Matt Roper    free(local_devices);
3352677cd97dc4a930af508388713f5016baf664ed18Rob Herring    if (*device == NULL)
3353677cd97dc4a930af508388713f5016baf664ed18Rob Herring	return -ENODEV;
3354ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    return 0;
3355ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3356ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikovfree_devices:
3357ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    drmFreeDevices(local_devices, i);
3358ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    closedir(sysdir);
3359cf0f036e3d819fb7894562bfdfea95e5e5f57219Matt Roper
3360cf0f036e3d819fb7894562bfdfea95e5e5f57219Matt Roperfree_locals:
3361cf0f036e3d819fb7894562bfdfea95e5e5f57219Matt Roper    free(local_devices);
3362ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    return ret;
3363ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov}
3364ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3365ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov/**
336611687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov * Get information about the opened drm device
336711687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov *
336811687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov * \param fd file descriptor of the drm device
336911687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov * \param device the address of a drmDevicePtr where the information
337011687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov *               will be allocated in stored
337111687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov *
337211687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov * \return zero on success, negative error code otherwise.
337311687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov */
337411687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikovint drmGetDevice(int fd, drmDevicePtr *device)
337511687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov{
337611687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov    return drmGetDevice2(fd, DRM_DEVICE_GET_PCI_REVISION, device);
337711687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov}
337811687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov
337911687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov/**
3380b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov * Get drm devices on the system
3381b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov *
338211687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov * \param flags feature/behaviour bitmask
3383b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov * \param devices the array of devices with drmDevicePtr elements
3384b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov *                can be NULL to get the device number first
3385b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov * \param max_devices the maximum number of devices for the array
3386b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov *
3387b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov * \return on error - negative error code,
3388b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov *         if devices is NULL - total number of devices available on the system,
3389b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov *         alternatively the number of devices stored in devices[], which is
3390b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov *         capped by the max_devices.
339111687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov *
339211687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov * \note Unlike drmGetDevices it does not retrieve the pci device revision field
339311687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov * unless the DRM_DEVICE_GET_PCI_REVISION \p flag is set.
3394b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov */
339511687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikovint drmGetDevices2(uint32_t flags, drmDevicePtr devices[], int max_devices)
3396b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov{
33975f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    drmDevicePtr *local_devices;
33985f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    drmDevicePtr device;
33995f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    DIR *sysdir;
34005f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    struct dirent *dent;
34015f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    struct stat sbuf;
34025f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    char node[PATH_MAX + 1];
3403b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    int node_type, subsystem_type;
3404b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    int maj, min;
3405fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    int ret, i, node_count, device_count;
3406b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    int max_count = 16;
340711687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov
340811687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov    if (drm_device_validate_flags(flags))
340911687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov        return -EINVAL;
3410b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
34115f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    local_devices = calloc(max_count, sizeof(drmDevicePtr));
34125f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    if (local_devices == NULL)
3413b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        return -ENOMEM;
3414b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
3415b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    sysdir = opendir(DRM_DIR_NAME);
3416b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    if (!sysdir) {
3417b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        ret = -errno;
34188c4a1cbd98bd8d185d489395f33302a17db643a9Matt Roper        goto free_locals;
3419b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    }
3420b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
34215f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    i = 0;
3422b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    while ((dent = readdir(sysdir))) {
3423b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        node_type = drmGetNodeType(dent->d_name);
3424b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        if (node_type < 0)
3425b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov            continue;
3426b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
3427b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        snprintf(node, PATH_MAX, "%s/%s", DRM_DIR_NAME, dent->d_name);
3428b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        if (stat(node, &sbuf))
3429b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov            continue;
3430b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
3431b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        maj = major(sbuf.st_rdev);
3432b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        min = minor(sbuf.st_rdev);
3433b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
3434b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode))
3435b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov            continue;
3436b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
3437a250fceaaa150363accaf3fb71a0e42bcecc40daEmil Velikov        subsystem_type = drmParseSubsystemType(maj, min);
3438b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
3439b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        if (subsystem_type < 0)
3440b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov            continue;
3441b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
3442b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        switch (subsystem_type) {
3443b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        case DRM_BUS_PCI:
3444b40a65d44857394966b25c5587f9dc978643f9c4Emil Velikov            ret = drmProcessPciDevice(&device, node, node_type,
3445138d23117c6b96f57aaa0072992e0480153cfebdEmil Velikov                                      maj, min, devices != NULL, flags);
34465f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov            if (ret)
34475f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov                goto free_devices;
3448b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
3449b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov            break;
3450b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        default:
3451ba5a6ecf81fc2e25a4c7b8c592143faadfdd63dbMatt Roper            continue;
3452b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        }
3453b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
34545f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov        if (i >= max_count) {
34555f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov            drmDevicePtr *temp;
3456b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
34575f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov            max_count += 16;
34585f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov            temp = realloc(local_devices, max_count * sizeof(drmDevicePtr));
34595f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov            if (!temp)
34605f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov                goto free_devices;
34615f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov            local_devices = temp;
34625f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov        }
34635f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov
34645f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov        local_devices[i] = device;
34655f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov        i++;
3466b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    }
34675f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    node_count = i;
3468b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
3469fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    drmFoldDuplicatedDevices(local_devices, node_count);
3470b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
34715f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    device_count = 0;
347270b64073f7d1bf56a30f7a809bd984d3ad688b9fQiang Yu    for (i = 0; i < node_count; i++) {
347350d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely        if (!local_devices[i])
347450d3c85bdb4ac0b3d546336605a722889aff7066Jan Vesely            continue;
347570b64073f7d1bf56a30f7a809bd984d3ad688b9fQiang Yu
34765f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov        if ((devices != NULL) && (device_count < max_devices))
34775f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov            devices[device_count] = local_devices[i];
34785f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov        else
34795f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov            drmFreeDevice(&local_devices[i]);
3480b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
34815f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov        device_count++;
34825f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    }
3483b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
3484b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    closedir(sysdir);
34858c4a1cbd98bd8d185d489395f33302a17db643a9Matt Roper    free(local_devices);
34865f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    return device_count;
34875f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov
34885f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikovfree_devices:
34895f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    drmFreeDevices(local_devices, i);
3490b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    closedir(sysdir);
34918c4a1cbd98bd8d185d489395f33302a17db643a9Matt Roper
34928c4a1cbd98bd8d185d489395f33302a17db643a9Matt Roperfree_locals:
34938c4a1cbd98bd8d185d489395f33302a17db643a9Matt Roper    free(local_devices);
3494b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    return ret;
3495b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov}
349637d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov
349711687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov/**
349811687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov * Get drm devices on the system
349911687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov *
350011687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov * \param devices the array of devices with drmDevicePtr elements
350111687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov *                can be NULL to get the device number first
350211687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov * \param max_devices the maximum number of devices for the array
350311687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov *
350411687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov * \return on error - negative error code,
350511687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov *         if devices is NULL - total number of devices available on the system,
350611687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov *         alternatively the number of devices stored in devices[], which is
350711687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov *         capped by the max_devices.
350811687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov */
350911687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikovint drmGetDevices(drmDevicePtr devices[], int max_devices)
351011687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov{
351111687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov    return drmGetDevices2(DRM_DEVICE_GET_PCI_REVISION, devices, max_devices);
351211687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov}
351311687bf4180f7e21045ed9c4730533c40fe01ea5Emil Velikov
351437d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikovchar *drmGetDeviceNameFromFd2(int fd)
351537d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov{
351637d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov#ifdef __linux__
351737d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov    struct stat sbuf;
351837d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov    char *device_name = NULL;
351937d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov    unsigned int maj, min;
352037d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov    FILE *f;
352137d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov    char buf[512];
352237d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov    static const char match[9] = "\nDEVNAME=";
352337d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov    int expected = 1;
352437d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov
352537d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov
352637d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov    if (fstat(fd, &sbuf))
352737d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov        return NULL;
352837d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov
352937d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov    maj = major(sbuf.st_rdev);
353037d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov    min = minor(sbuf.st_rdev);
353137d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov
353237d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov    if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode))
353337d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov        return NULL;
353437d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov
353537d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov    snprintf(buf, sizeof(buf), "/sys/dev/char/%d:%d/uevent", maj, min);
353637d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov    if (!(f = fopen(buf, "r")))
353737d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov        return NULL;
353837d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov
353937d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov    while (expected < sizeof(match)) {
354037d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov        int c = getc(f);
354137d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov
354237d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov        if (c == EOF) {
354337d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov            fclose(f);
354437d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov            return NULL;
354537d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov        } else if (c == match[expected] )
354637d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov            expected++;
354737d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov        else
354837d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov            expected = 0;
354937d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov    }
355037d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov
355137d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov    strcpy(buf, "/dev/");
355237d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov    if (fgets(buf + 5, sizeof(buf) - 5, f)) {
355337d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov        buf[strcspn(buf, "\n")] = '\0';
355437d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov        device_name = strdup(buf);
355537d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov    }
355637d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov
355737d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov    fclose(f);
355837d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov    return device_name;
355937d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov#else
356037d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov#warning "Missing implementation of drmGetDeviceNameFromFd2"
356137d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov    return NULL;
356237d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov#endif
356337d790f7d449874d0bf199d9ca9871d12b4d599aEmil Velikov}
3564