xf86drm.c revision ccedf66b65f6ab245aa6028d7fe9eb603a121b43
1d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
2d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \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>
4879038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie#include <signal.h>
49f4f76a6894b40abd77f0ffbf52972127608b9bcaJesse Barnes#include <time.h>
5079038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie#include <sys/types.h>
5179038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie#include <sys/stat.h>
5279038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie#define stat_t struct stat
5379038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie#include <sys/ioctl.h>
5479038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie#include <sys/time.h>
5579038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie#include <stdarg.h>
560e1135de5cbb783846a4f7e9ef8a5f953f7c77aeAlan Coopersmith#ifdef HAVE_SYS_MKDEV_H
570e1135de5cbb783846a4f7e9ef8a5f953f7c77aeAlan Coopersmith# include <sys/mkdev.h> /* defines major(), minor(), and makedev() on Solaris */
580e1135de5cbb783846a4f7e9ef8a5f953f7c77aeAlan Coopersmith#endif
59b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov#include <math.h>
60b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
61b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss/* Not all systems have MAP_FAILED defined */
62b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss#ifndef MAP_FAILED
63b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss#define MAP_FAILED ((void *)-1)
64b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss#endif
65b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
66b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss#include "xf86drm.h"
6742465feb9759ef5a6d79d7e628510cd0a081f913Emil Velikov#include "libdrm_macros.h"
68b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
695f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov#include "util_math.h"
705f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov
71fc083322b0c8a58b51976adf23a582bce8bb75f1Jonathan Gray#ifdef __OpenBSD__
72fc083322b0c8a58b51976adf23a582bce8bb75f1Jonathan Gray#define DRM_PRIMARY_MINOR_NAME	"drm"
73fc083322b0c8a58b51976adf23a582bce8bb75f1Jonathan Gray#define DRM_CONTROL_MINOR_NAME	"drmC"
74fc083322b0c8a58b51976adf23a582bce8bb75f1Jonathan Gray#define DRM_RENDER_MINOR_NAME	"drmR"
75fc083322b0c8a58b51976adf23a582bce8bb75f1Jonathan Gray#else
76fc083322b0c8a58b51976adf23a582bce8bb75f1Jonathan Gray#define DRM_PRIMARY_MINOR_NAME	"card"
77fc083322b0c8a58b51976adf23a582bce8bb75f1Jonathan Gray#define DRM_CONTROL_MINOR_NAME	"controlD"
78fc083322b0c8a58b51976adf23a582bce8bb75f1Jonathan Gray#define DRM_RENDER_MINOR_NAME	"renderD"
79fc083322b0c8a58b51976adf23a582bce8bb75f1Jonathan Gray#endif
80fc083322b0c8a58b51976adf23a582bce8bb75f1Jonathan Gray
8127c3785d3f12743a9e160238a4d00353060ec2f2Hasso Tepper#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
82cfa778af9c70faea8c13e5cb7f80029eee0d074eEric Anholt#define DRM_MAJOR 145
83cfa778af9c70faea8c13e5cb7f80029eee0d074eEric Anholt#endif
84cfa778af9c70faea8c13e5cb7f80029eee0d074eEric Anholt
85cfa778af9c70faea8c13e5cb7f80029eee0d074eEric Anholt#ifdef __NetBSD__
86cfa778af9c70faea8c13e5cb7f80029eee0d074eEric Anholt#define DRM_MAJOR 34
8788dbee54ed400a3fd5594fab506518c171167805Rik Faith#endif
8888dbee54ed400a3fd5594fab506518c171167805Rik Faith
8966c3afb75fa993f2f8b00c2dd9c2ec37a3a9dfb6Jonathan Gray#ifdef __OpenBSD__
9066c3afb75fa993f2f8b00c2dd9c2ec37a3a9dfb6Jonathan Gray#ifdef __i386__
9166c3afb75fa993f2f8b00c2dd9c2ec37a3a9dfb6Jonathan Gray#define DRM_MAJOR 88
9266c3afb75fa993f2f8b00c2dd9c2ec37a3a9dfb6Jonathan Gray#else
9366c3afb75fa993f2f8b00c2dd9c2ec37a3a9dfb6Jonathan Gray#define DRM_MAJOR 87
9466c3afb75fa993f2f8b00c2dd9c2ec37a3a9dfb6Jonathan Gray#endif
9566c3afb75fa993f2f8b00c2dd9c2ec37a3a9dfb6Jonathan Gray#endif /* __OpenBSD__ */
96b0a928557c91fec527f41ae8b2441174889bf32cAlan Hourihane
97cfa778af9c70faea8c13e5cb7f80029eee0d074eEric Anholt#ifndef DRM_MAJOR
98cfa778af9c70faea8c13e5cb7f80029eee0d074eEric Anholt#define DRM_MAJOR 226		/* Linux */
9988dbee54ed400a3fd5594fab506518c171167805Rik Faith#endif
10088dbee54ed400a3fd5594fab506518c171167805Rik Faith
10122e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jackson/*
10222e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jackson * This definition needs to be changed on some systems if dev_t is a structure.
10322e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jackson * If there is a header file we can get it from, there would be best.
10422e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jackson */
105569da5a42ebf10c86d6c6ba81866a888e1c708dcBrian Paul#ifndef makedev
106569da5a42ebf10c86d6c6ba81866a888e1c708dcBrian Paul#define makedev(x,y)    ((dev_t)(((x) << 8) | (y)))
107569da5a42ebf10c86d6c6ba81866a888e1c708dcBrian Paul#endif
108569da5a42ebf10c86d6c6ba81866a888e1c708dcBrian Paul
10956bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes#define DRM_MSG_VERBOSITY 3
11056bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes
111fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter#define memclear(s) memset(&s, 0, sizeof(s))
112fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter
11379038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airliestatic drmServerInfoPtr drm_server_info;
11479038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie
11579038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlievoid drmSetServerInfo(drmServerInfoPtr info)
11679038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie{
117ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    drm_server_info = info;
11879038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie}
11979038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie
120d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
121d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Output a message to stderr.
122d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
123d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param format printf() like format string.
124d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
125d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
126d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around vfprintf().
127d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
12879038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie
12944b08c0ddf7ced99a5914421f18b269a1dcaafaeThierry Redingstatic int DRM_PRINTFLIKE(1, 0)
13044b08c0ddf7ced99a5914421f18b269a1dcaafaeThierry RedingdrmDebugPrint(const char *format, va_list ap)
13179038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie{
132ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    return vfprintf(stderr, format, ap);
13379038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie}
13479038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie
135c4857429c716f35e1fa054d1990cae28055d96d7Eric Anholtvoid
13656bd9c207770d41a497f3e8237a1099dd9d4cd91David DawesdrmMsg(const char *format, ...)
13756bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes{
13856bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes    va_list	ap;
13956bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes    const char *env;
140eb7c2d5e63e0e9d133b16880e36c14676276d412Rob Clark    if (((env = getenv("LIBGL_DEBUG")) && strstr(env, "verbose")) ||
141eb7c2d5e63e0e9d133b16880e36c14676276d412Rob Clark        (drm_server_info && drm_server_info->debug_print))
14256bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes    {
14356bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes	va_start(ap, format);
14479038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie	if (drm_server_info) {
14579038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie	  drm_server_info->debug_print(format,ap);
14679038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie	} else {
147cfbe9c9807888d24a56d9b1df28db7da669dee85Jan Vesely	  drmDebugPrint(format, ap);
14879038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie	}
14956bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes	va_end(ap);
15056bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes    }
15156bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes}
15256bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes
153b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Straussstatic void *drmHashTable = NULL; /* Context switch callbacks */
154b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
15579038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlievoid *drmGetHashTable(void)
15679038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie{
157ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    return drmHashTable;
15879038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie}
159b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
160b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Straussvoid *drmMalloc(int size)
161b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
162d0e592d4e9b59d9cc185f1d63b3c1dd818e95098Emil Velikov    return calloc(1, size);
163b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
164b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
165b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Straussvoid drmFree(void *pt)
166b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
167d0e592d4e9b59d9cc185f1d63b3c1dd818e95098Emil Velikov    free(pt);
168b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
169b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1708b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard/**
1718b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard * Call ioctl, restarting if it is interupted
1728b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard */
173731cd5526e5c732d51307b26e784f454a724a699Jesse Barnesint
17441b83a99583486ad4f8760a6537d34783769bfc3Coleman KanedrmIoctl(int fd, unsigned long request, void *arg)
1758b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard{
1768b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    int	ret;
1778b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard
1788b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    do {
1798b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard	ret = ioctl(fd, request, arg);
1808b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
1818b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    return ret;
1828b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard}
183b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
184b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Straussstatic unsigned long drmGetKeyFromFd(int fd)
185b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
186fcc21069b7019a4a93e1ceacc175ccd682353861David Dawes    stat_t     st;
187b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
188b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    st.st_rdev = 0;
189b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    fstat(fd, &st);
190b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return st.st_rdev;
191b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
192b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
19379038751ffe47ed1ce82766e027d98fd2f0e2c6aDave AirliedrmHashEntry *drmGetEntry(int fd)
194b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
195b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    unsigned long key = drmGetKeyFromFd(fd);
196b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    void          *value;
197b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drmHashEntry  *entry;
198b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
199ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    if (!drmHashTable)
200ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	drmHashTable = drmHashCreate();
201b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
202b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    if (drmHashLookup(drmHashTable, key, &value)) {
203b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	entry           = drmMalloc(sizeof(*entry));
204b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	entry->fd       = fd;
205b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	entry->f        = NULL;
206b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	entry->tagTable = drmHashCreate();
207b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	drmHashInsert(drmHashTable, key, entry);
208b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    } else {
209b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	entry = value;
210b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    }
211b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return entry;
212b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
213b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
214d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
21506cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt * Compare two busid strings
21606cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt *
21706cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt * \param first
21806cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt * \param second
21906cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt *
22006cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt * \return 1 if matched.
22106cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt *
22206cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt * \internal
22306cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt * This function compares two bus ID strings.  It understands the older
22406cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt * PCI:b:d:f format and the newer pci:oooo:bb:dd.f format.  In the format, o is
22506cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt * domain, b is bus, d is device, f is function.
22606cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt */
227b04515c5d6c95f573457a94267b855cceb639105Benjamin Herrenschmidtstatic int drmMatchBusID(const char *id1, const char *id2, int pci_domain_ok)
22806cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt{
22906cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    /* First, check if the IDs are exactly the same */
23006cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    if (strcasecmp(id1, id2) == 0)
23106cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt	return 1;
23206cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt
23306cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    /* Try to match old/new-style PCI bus IDs. */
23406cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    if (strncasecmp(id1, "pci", 3) == 0) {
23590ae0f2bb8d53500f5c9d06e2dc1a18d5a5d0cf5Pauli Nieminen	unsigned int o1, b1, d1, f1;
23690ae0f2bb8d53500f5c9d06e2dc1a18d5a5d0cf5Pauli Nieminen	unsigned int o2, b2, d2, f2;
23706cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt	int ret;
23806cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt
23990ae0f2bb8d53500f5c9d06e2dc1a18d5a5d0cf5Pauli Nieminen	ret = sscanf(id1, "pci:%04x:%02x:%02x.%u", &o1, &b1, &d1, &f1);
24006cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt	if (ret != 4) {
24106cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt	    o1 = 0;
24290ae0f2bb8d53500f5c9d06e2dc1a18d5a5d0cf5Pauli Nieminen	    ret = sscanf(id1, "PCI:%u:%u:%u", &b1, &d1, &f1);
24306cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt	    if (ret != 3)
24406cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt		return 0;
24506cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt	}
24606cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt
24790ae0f2bb8d53500f5c9d06e2dc1a18d5a5d0cf5Pauli Nieminen	ret = sscanf(id2, "pci:%04x:%02x:%02x.%u", &o2, &b2, &d2, &f2);
24806cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt	if (ret != 4) {
24906cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt	    o2 = 0;
25090ae0f2bb8d53500f5c9d06e2dc1a18d5a5d0cf5Pauli Nieminen	    ret = sscanf(id2, "PCI:%u:%u:%u", &b2, &d2, &f2);
25106cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt	    if (ret != 3)
25206cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt		return 0;
25306cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt	}
25406cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt
255b04515c5d6c95f573457a94267b855cceb639105Benjamin Herrenschmidt	/* If domains aren't properly supported by the kernel interface,
256b04515c5d6c95f573457a94267b855cceb639105Benjamin Herrenschmidt	 * just ignore them, which sucks less than picking a totally random
257b04515c5d6c95f573457a94267b855cceb639105Benjamin Herrenschmidt	 * card with "open by name"
258b04515c5d6c95f573457a94267b855cceb639105Benjamin Herrenschmidt	 */
259b04515c5d6c95f573457a94267b855cceb639105Benjamin Herrenschmidt	if (!pci_domain_ok)
260b04515c5d6c95f573457a94267b855cceb639105Benjamin Herrenschmidt		o1 = o2 = 0;
261b04515c5d6c95f573457a94267b855cceb639105Benjamin Herrenschmidt
26206cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt	if ((o1 != o2) || (b1 != b2) || (d1 != d2) || (f1 != f2))
26306cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt	    return 0;
26406cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt	else
26506cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt	    return 1;
26606cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    }
26706cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    return 0;
26806cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt}
26906cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt
27006cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt/**
271c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen * Handles error checking for chown call.
272c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen *
273c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen * \param path to file.
274c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen * \param id of the new owner.
275c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen * \param id of the new group.
276c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen *
277c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen * \return zero if success or -1 if failure.
278c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen *
279c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen * \internal
280c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen * Checks for failure. If failure was caused by signal call chown again.
281c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen * If any other failure happened then it will output error mesage using
282c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen * drmMsg() call.
283c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen */
2846fc0e4ba1ea153ff949cba0002fc5ed544de0de0Jan Vesely#if !defined(UDEV)
285c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminenstatic int chown_check_return(const char *path, uid_t owner, gid_t group)
286c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen{
287c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen	int rv;
288c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen
289c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen	do {
290c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen		rv = chown(path, owner, group);
291c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen	} while (rv != 0 && errno == EINTR);
292c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen
293c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen	if (rv == 0)
294c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen		return 0;
295c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen
296c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen	drmMsg("Failed to change owner or group for file %s! %d: %s\n",
297c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen			path, errno, strerror(errno));
298c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen	return -1;
299c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen}
3006fc0e4ba1ea153ff949cba0002fc5ed544de0de0Jan Vesely#endif
301c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen
302c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen/**
303d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Open the DRM device, creating it if necessary.
304d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
305d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param dev major and minor numbers of the device.
306d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param minor minor number of the device.
307d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
308d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return a file descriptor on success, or a negative value on error.
309d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
310d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
311d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Assembles the device name from \p minor and opens it, creating the device
312d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * special file node with the major and minor numbers specified by \p dev and
313d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * parent directory if necessary and was called by root.
314d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
315de8532dd8359dfdaba839ff61fc9e2f05eaf57d3Jan Veselystatic int drmOpenDevice(dev_t dev, int minor, int type)
316b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
3179c775d0b2f303389c24aea5e8abc1473f0cf93e8David Dawes    stat_t          st;
3180c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns    const char      *dev_name;
31988dbee54ed400a3fd5594fab506518c171167805Rik Faith    char            buf[64];
32088dbee54ed400a3fd5594fab506518c171167805Rik Faith    int             fd;
32179038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie    mode_t          devmode = DRM_DEV_MODE, serv_mode;
3220706c14e7cc5f1d996bb1c3c526f877c4f8fc215Jan Vesely    gid_t           serv_group;
3230706c14e7cc5f1d996bb1c3c526f877c4f8fc215Jan Vesely#if !defined(UDEV)
32488dbee54ed400a3fd5594fab506518c171167805Rik Faith    int             isroot  = !geteuid();
32588dbee54ed400a3fd5594fab506518c171167805Rik Faith    uid_t           user    = DRM_DEV_UID;
3260706c14e7cc5f1d996bb1c3c526f877c4f8fc215Jan Vesely    gid_t           group   = DRM_DEV_GID;
3270706c14e7cc5f1d996bb1c3c526f877c4f8fc215Jan Vesely#endif
3280706c14e7cc5f1d996bb1c3c526f877c4f8fc215Jan Vesely
3290c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns    switch (type) {
3300c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns    case DRM_NODE_PRIMARY:
3310c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns	    dev_name = DRM_DEV_NAME;
3320c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns	    break;
3330c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns    case DRM_NODE_CONTROL:
3340c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns	    dev_name = DRM_CONTROL_DEV_NAME;
3350c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns	    break;
3360c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns    case DRM_NODE_RENDER:
3370c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns	    dev_name = DRM_RENDER_DEV_NAME;
3380c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns	    break;
3390c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns    default:
3400c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns	    return -EINVAL;
3410c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns    };
3420c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns
3430c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns    sprintf(buf, dev_name, DRM_DIR_NAME, minor);
34406cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    drmMsg("drmOpenDevice: node name is %s\n", buf);
34556bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes
346eb7c2d5e63e0e9d133b16880e36c14676276d412Rob Clark    if (drm_server_info && drm_server_info->get_perms) {
347ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	drm_server_info->get_perms(&serv_group, &serv_mode);
348ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	devmode  = serv_mode ? serv_mode : DRM_DEV_MODE;
349ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	devmode &= ~(S_IXUSR|S_IXGRP|S_IXOTH);
35079038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie    }
351569da5a42ebf10c86d6c6ba81866a888e1c708dcBrian Paul
3529101a0205c897fea28e6a3d875111a83ad7f7732Dave Airlie#if !defined(UDEV)
35388dbee54ed400a3fd5594fab506518c171167805Rik Faith    if (stat(DRM_DIR_NAME, &st)) {
354ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	if (!isroot)
355ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	    return DRM_ERR_NOT_ROOT;
356b3a20ce219b353aa3e2b7f3b47ffd28b279557c7Alan Hourihane	mkdir(DRM_DIR_NAME, DRM_DEV_DIRMODE);
357c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen	chown_check_return(DRM_DIR_NAME, 0, 0); /* root:root */
358b3a20ce219b353aa3e2b7f3b47ffd28b279557c7Alan Hourihane	chmod(DRM_DIR_NAME, DRM_DEV_DIRMODE);
359569da5a42ebf10c86d6c6ba81866a888e1c708dcBrian Paul    }
360b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
36106cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    /* Check if the device node exists and create it if necessary. */
362d2f2b42f1d206fd248ada48ce2c498e31351ab33Eric Anholt    if (stat(buf, &st)) {
363ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	if (!isroot)
364ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	    return DRM_ERR_NOT_ROOT;
36588dbee54ed400a3fd5594fab506518c171167805Rik Faith	remove(buf);
36688dbee54ed400a3fd5594fab506518c171167805Rik Faith	mknod(buf, S_IFCHR | devmode, dev);
367b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    }
36879038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie
369eb7c2d5e63e0e9d133b16880e36c14676276d412Rob Clark    if (drm_server_info && drm_server_info->get_perms) {
370454b14949452c4e44990a8f455bcc307306181bcJammy Zhou	group = ((int)serv_group >= 0) ? serv_group : DRM_DEV_GID;
371c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen	chown_check_return(buf, user, group);
372ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	chmod(buf, devmode);
37379038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie    }
3749101a0205c897fea28e6a3d875111a83ad7f7732Dave Airlie#else
3759101a0205c897fea28e6a3d875111a83ad7f7732Dave Airlie    /* if we modprobed then wait for udev */
3769101a0205c897fea28e6a3d875111a83ad7f7732Dave Airlie    {
3779101a0205c897fea28e6a3d875111a83ad7f7732Dave Airlie	int udev_count = 0;
3789101a0205c897fea28e6a3d875111a83ad7f7732Dave Airliewait_for_udev:
3799101a0205c897fea28e6a3d875111a83ad7f7732Dave Airlie        if (stat(DRM_DIR_NAME, &st)) {
3809101a0205c897fea28e6a3d875111a83ad7f7732Dave Airlie		usleep(20);
3819101a0205c897fea28e6a3d875111a83ad7f7732Dave Airlie		udev_count++;
3829101a0205c897fea28e6a3d875111a83ad7f7732Dave Airlie
3839101a0205c897fea28e6a3d875111a83ad7f7732Dave Airlie		if (udev_count == 50)
3849101a0205c897fea28e6a3d875111a83ad7f7732Dave Airlie			return -1;
3859101a0205c897fea28e6a3d875111a83ad7f7732Dave Airlie		goto wait_for_udev;
3869101a0205c897fea28e6a3d875111a83ad7f7732Dave Airlie	}
3879101a0205c897fea28e6a3d875111a83ad7f7732Dave Airlie
3889101a0205c897fea28e6a3d875111a83ad7f7732Dave Airlie    	if (stat(buf, &st)) {
3899101a0205c897fea28e6a3d875111a83ad7f7732Dave Airlie		usleep(20);
3909101a0205c897fea28e6a3d875111a83ad7f7732Dave Airlie		udev_count++;
3919101a0205c897fea28e6a3d875111a83ad7f7732Dave Airlie
3929101a0205c897fea28e6a3d875111a83ad7f7732Dave Airlie		if (udev_count == 50)
3939101a0205c897fea28e6a3d875111a83ad7f7732Dave Airlie			return -1;
3949101a0205c897fea28e6a3d875111a83ad7f7732Dave Airlie		goto wait_for_udev;
3959101a0205c897fea28e6a3d875111a83ad7f7732Dave Airlie    	}
3969101a0205c897fea28e6a3d875111a83ad7f7732Dave Airlie    }
3979101a0205c897fea28e6a3d875111a83ad7f7732Dave Airlie#endif
39888dbee54ed400a3fd5594fab506518c171167805Rik Faith
39956bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes    fd = open(buf, O_RDWR, 0);
40056bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes    drmMsg("drmOpenDevice: open result is %d, (%s)\n",
40156bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes		fd, fd < 0 ? strerror(errno) : "OK");
402ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    if (fd >= 0)
403ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return fd;
404d2f2b42f1d206fd248ada48ce2c498e31351ab33Eric Anholt
40539e5e982242cd2b611a9dfc1e9b63f857d52da61Dave Airlie#if !defined(UDEV)
40606cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    /* Check if the device node is not what we expect it to be, and recreate it
40706cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt     * and try again if so.
40806cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt     */
409d2f2b42f1d206fd248ada48ce2c498e31351ab33Eric Anholt    if (st.st_rdev != dev) {
410ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	if (!isroot)
411ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	    return DRM_ERR_NOT_ROOT;
412d2f2b42f1d206fd248ada48ce2c498e31351ab33Eric Anholt	remove(buf);
413d2f2b42f1d206fd248ada48ce2c498e31351ab33Eric Anholt	mknod(buf, S_IFCHR | devmode, dev);
414eb7c2d5e63e0e9d133b16880e36c14676276d412Rob Clark	if (drm_server_info && drm_server_info->get_perms) {
415c5a5bbbe899400642795c1d95aef78deade9241fPauli Nieminen	    chown_check_return(buf, user, group);
416ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	    chmod(buf, devmode);
41779038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie	}
418d2f2b42f1d206fd248ada48ce2c498e31351ab33Eric Anholt    }
419d2f2b42f1d206fd248ada48ce2c498e31351ab33Eric Anholt    fd = open(buf, O_RDWR, 0);
420d2f2b42f1d206fd248ada48ce2c498e31351ab33Eric Anholt    drmMsg("drmOpenDevice: open result is %d, (%s)\n",
421d2f2b42f1d206fd248ada48ce2c498e31351ab33Eric Anholt		fd, fd < 0 ? strerror(errno) : "OK");
422ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    if (fd >= 0)
423ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return fd;
424d2f2b42f1d206fd248ada48ce2c498e31351ab33Eric Anholt
42556bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes    drmMsg("drmOpenDevice: Open failed\n");
42688dbee54ed400a3fd5594fab506518c171167805Rik Faith    remove(buf);
42739e5e982242cd2b611a9dfc1e9b63f857d52da61Dave Airlie#endif
42888dbee54ed400a3fd5594fab506518c171167805Rik Faith    return -errno;
429b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
430b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
431d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
432d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
433d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Open the DRM device
434d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
435d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param minor device minor number.
436d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param create allow to create the device if set.
437d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
438d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return a file descriptor on success, or a negative value on error.
439d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
440d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
441d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Calls drmOpenDevice() if \p create is set, otherwise assembles the device
442d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * name from \p minor and opens it.
443d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
444731cd5526e5c732d51307b26e784f454a724a699Jesse Barnesstatic int drmOpenMinor(int minor, int create, int type)
44588dbee54ed400a3fd5594fab506518c171167805Rik Faith{
44688dbee54ed400a3fd5594fab506518c171167805Rik Faith    int  fd;
44788dbee54ed400a3fd5594fab506518c171167805Rik Faith    char buf[64];
4480c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns    const char *dev_name;
449db85ed25afc616acfaadb21facf6066354f9d490Dave Airlie
450ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    if (create)
451731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	return drmOpenDevice(makedev(DRM_MAJOR, minor), minor, type);
45288dbee54ed400a3fd5594fab506518c171167805Rik Faith
4530c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns    switch (type) {
4540c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns    case DRM_NODE_PRIMARY:
4550c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns	    dev_name = DRM_DEV_NAME;
4560c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns	    break;
4570c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns    case DRM_NODE_CONTROL:
4580c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns	    dev_name = DRM_CONTROL_DEV_NAME;
4590c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns	    break;
4600c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns    case DRM_NODE_RENDER:
4610c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns	    dev_name = DRM_RENDER_DEV_NAME;
4620c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns	    break;
4630c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns    default:
4640c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns	    return -EINVAL;
4650c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns    };
4660c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns
4670c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns    sprintf(buf, dev_name, DRM_DIR_NAME, minor);
468ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    if ((fd = open(buf, O_RDWR, 0)) >= 0)
469ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return fd;
47088dbee54ed400a3fd5594fab506518c171167805Rik Faith    return -errno;
47188dbee54ed400a3fd5594fab506518c171167805Rik Faith}
47288dbee54ed400a3fd5594fab506518c171167805Rik Faith
473569da5a42ebf10c86d6c6ba81866a888e1c708dcBrian Paul
474d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
475d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Determine whether the DRM kernel driver has been loaded.
476d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
477d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return 1 if the DRM driver is loaded, 0 otherwise.
478d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
479d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
480d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Determine the presence of the kernel driver by attempting to open the 0
481d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * minor and get version information.  For backward compatibility with older
482d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Linux implementations, /proc/dri is also checked.
483d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
484569da5a42ebf10c86d6c6ba81866a888e1c708dcBrian Paulint drmAvailable(void)
485569da5a42ebf10c86d6c6ba81866a888e1c708dcBrian Paul{
486569da5a42ebf10c86d6c6ba81866a888e1c708dcBrian Paul    drmVersionPtr version;
487569da5a42ebf10c86d6c6ba81866a888e1c708dcBrian Paul    int           retval = 0;
488569da5a42ebf10c86d6c6ba81866a888e1c708dcBrian Paul    int           fd;
489360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes
490ad8bbfd3c74466f088be8088d2d0524bed392b71Frank Binns    if ((fd = drmOpenMinor(0, 1, DRM_NODE_PRIMARY)) < 0) {
491b0a928557c91fec527f41ae8b2441174889bf32cAlan Hourihane#ifdef __linux__
49222e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jackson	/* Try proc for backward Linux compatibility */
493ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	if (!access("/proc/dri/0", R_OK))
494ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	    return 1;
495b0a928557c91fec527f41ae8b2441174889bf32cAlan Hourihane#endif
49688dbee54ed400a3fd5594fab506518c171167805Rik Faith	return 0;
497569da5a42ebf10c86d6c6ba81866a888e1c708dcBrian Paul    }
49888dbee54ed400a3fd5594fab506518c171167805Rik Faith
49988dbee54ed400a3fd5594fab506518c171167805Rik Faith    if ((version = drmGetVersion(fd))) {
50088dbee54ed400a3fd5594fab506518c171167805Rik Faith	retval = 1;
50188dbee54ed400a3fd5594fab506518c171167805Rik Faith	drmFreeVersion(version);
50288dbee54ed400a3fd5594fab506518c171167805Rik Faith    }
50388dbee54ed400a3fd5594fab506518c171167805Rik Faith    close(fd);
504569da5a42ebf10c86d6c6ba81866a888e1c708dcBrian Paul
505569da5a42ebf10c86d6c6ba81866a888e1c708dcBrian Paul    return retval;
506569da5a42ebf10c86d6c6ba81866a888e1c708dcBrian Paul}
507569da5a42ebf10c86d6c6ba81866a888e1c708dcBrian Paul
508f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhoustatic int drmGetMinorBase(int type)
509f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou{
510f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou    switch (type) {
511f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou    case DRM_NODE_PRIMARY:
512f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou        return 0;
513f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou    case DRM_NODE_CONTROL:
514f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou        return 64;
515f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou    case DRM_NODE_RENDER:
516f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou        return 128;
517f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou    default:
518f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou        return -1;
519f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou    };
520f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou}
521d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
5221f73578df32f895a678a41758f6c563f49484347Frank Binnsstatic int drmGetMinorType(int minor)
5231f73578df32f895a678a41758f6c563f49484347Frank Binns{
5241f73578df32f895a678a41758f6c563f49484347Frank Binns    int type = minor >> 6;
5251f73578df32f895a678a41758f6c563f49484347Frank Binns
5261f73578df32f895a678a41758f6c563f49484347Frank Binns    if (minor < 0)
5271f73578df32f895a678a41758f6c563f49484347Frank Binns        return -1;
5281f73578df32f895a678a41758f6c563f49484347Frank Binns
5291f73578df32f895a678a41758f6c563f49484347Frank Binns    switch (type) {
5301f73578df32f895a678a41758f6c563f49484347Frank Binns    case DRM_NODE_PRIMARY:
5311f73578df32f895a678a41758f6c563f49484347Frank Binns    case DRM_NODE_CONTROL:
5321f73578df32f895a678a41758f6c563f49484347Frank Binns    case DRM_NODE_RENDER:
5331f73578df32f895a678a41758f6c563f49484347Frank Binns        return type;
5341f73578df32f895a678a41758f6c563f49484347Frank Binns    default:
5351f73578df32f895a678a41758f6c563f49484347Frank Binns        return -1;
5361f73578df32f895a678a41758f6c563f49484347Frank Binns    }
5371f73578df32f895a678a41758f6c563f49484347Frank Binns}
5381f73578df32f895a678a41758f6c563f49484347Frank Binns
5390ca03a4087a550646de7f26b6b53a932e8546474Emil Velikovstatic const char *drmGetMinorName(int type)
5400ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov{
5410ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov    switch (type) {
5420ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov    case DRM_NODE_PRIMARY:
543fc083322b0c8a58b51976adf23a582bce8bb75f1Jonathan Gray        return DRM_PRIMARY_MINOR_NAME;
5440ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov    case DRM_NODE_CONTROL:
545fc083322b0c8a58b51976adf23a582bce8bb75f1Jonathan Gray        return DRM_CONTROL_MINOR_NAME;
5460ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov    case DRM_NODE_RENDER:
547fc083322b0c8a58b51976adf23a582bce8bb75f1Jonathan Gray        return DRM_RENDER_MINOR_NAME;
5480ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov    default:
5490ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov        return NULL;
5500ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov    }
5510ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov}
5520ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov
553d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
554d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Open the device by bus ID.
555d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
556d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param busid bus ID.
557f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou * \param type device node type.
558d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
559d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return a file descriptor on success, or a negative value on error.
560d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
561d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
562d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function attempts to open every possible minor (up to DRM_MAX_MINOR),
563d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * comparing the device bus ID with the one supplied.
564d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
565d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \sa drmOpenMinor() and drmGetBusid().
566d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
567f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhoustatic int drmOpenByBusid(const char *busid, int type)
568e1dba5c3a73078dec24f07a6d685435677db94a4Daryll Strauss{
569b04515c5d6c95f573457a94267b855cceb639105Benjamin Herrenschmidt    int        i, pci_domain_ok = 1;
57088dbee54ed400a3fd5594fab506518c171167805Rik Faith    int        fd;
57188dbee54ed400a3fd5594fab506518c171167805Rik Faith    const char *buf;
57206cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    drmSetVersion sv;
573f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou    int        base = drmGetMinorBase(type);
574f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou
575f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou    if (base < 0)
576f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou        return -1;
57706cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt
57806cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    drmMsg("drmOpenByBusid: Searching for BusID %s\n", busid);
579f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou    for (i = base; i < base + DRM_MAX_MINOR; i++) {
580f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou	fd = drmOpenMinor(i, 1, type);
58156bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes	drmMsg("drmOpenByBusid: drmOpenMinor returns %d\n", fd);
58256bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes	if (fd >= 0) {
583b04515c5d6c95f573457a94267b855cceb639105Benjamin Herrenschmidt	    /* We need to try for 1.4 first for proper PCI domain support
584b04515c5d6c95f573457a94267b855cceb639105Benjamin Herrenschmidt	     * and if that fails, we know the kernel is busted
585b04515c5d6c95f573457a94267b855cceb639105Benjamin Herrenschmidt	     */
58606cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt	    sv.drm_di_major = 1;
587b04515c5d6c95f573457a94267b855cceb639105Benjamin Herrenschmidt	    sv.drm_di_minor = 4;
58806cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt	    sv.drm_dd_major = -1;	/* Don't care */
58926462b9aa47179e724e78f0b3b1c86fd07f61d8dEric Anholt	    sv.drm_dd_minor = -1;	/* Don't care */
590b04515c5d6c95f573457a94267b855cceb639105Benjamin Herrenschmidt	    if (drmSetInterfaceVersion(fd, &sv)) {
591b04515c5d6c95f573457a94267b855cceb639105Benjamin Herrenschmidt#ifndef __alpha__
592b04515c5d6c95f573457a94267b855cceb639105Benjamin Herrenschmidt		pci_domain_ok = 0;
593b04515c5d6c95f573457a94267b855cceb639105Benjamin Herrenschmidt#endif
594b04515c5d6c95f573457a94267b855cceb639105Benjamin Herrenschmidt		sv.drm_di_major = 1;
595b04515c5d6c95f573457a94267b855cceb639105Benjamin Herrenschmidt		sv.drm_di_minor = 1;
596b04515c5d6c95f573457a94267b855cceb639105Benjamin Herrenschmidt		sv.drm_dd_major = -1;       /* Don't care */
597b04515c5d6c95f573457a94267b855cceb639105Benjamin Herrenschmidt		sv.drm_dd_minor = -1;       /* Don't care */
598303ff26311dc5efdf28676be34d86f501699acf3Thierry Reding		drmMsg("drmOpenByBusid: Interface 1.4 failed, trying 1.1\n");
599b04515c5d6c95f573457a94267b855cceb639105Benjamin Herrenschmidt		drmSetInterfaceVersion(fd, &sv);
600b04515c5d6c95f573457a94267b855cceb639105Benjamin Herrenschmidt	    }
601e1dba5c3a73078dec24f07a6d685435677db94a4Daryll Strauss	    buf = drmGetBusid(fd);
60256bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes	    drmMsg("drmOpenByBusid: drmGetBusid reports %s\n", buf);
603b04515c5d6c95f573457a94267b855cceb639105Benjamin Herrenschmidt	    if (buf && drmMatchBusID(buf, busid, pci_domain_ok)) {
60488dbee54ed400a3fd5594fab506518c171167805Rik Faith		drmFreeBusid(buf);
60588dbee54ed400a3fd5594fab506518c171167805Rik Faith		return fd;
606e1dba5c3a73078dec24f07a6d685435677db94a4Daryll Strauss	    }
607ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	    if (buf)
608ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian		drmFreeBusid(buf);
609e1dba5c3a73078dec24f07a6d685435677db94a4Daryll Strauss	    close(fd);
610e1dba5c3a73078dec24f07a6d685435677db94a4Daryll Strauss	}
611e1dba5c3a73078dec24f07a6d685435677db94a4Daryll Strauss    }
612e1dba5c3a73078dec24f07a6d685435677db94a4Daryll Strauss    return -1;
613e1dba5c3a73078dec24f07a6d685435677db94a4Daryll Strauss}
614e1dba5c3a73078dec24f07a6d685435677db94a4Daryll Strauss
615d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
616d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
617d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Open the device by name.
618d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
619d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param name driver name.
620f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou * \param type the device node type.
621d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
622d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return a file descriptor on success, or a negative value on error.
623d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
624d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
625d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function opens the first minor number that matches the driver name and
626d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * isn't already in use.  If it's in use it then it will already have a bus ID
627d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * assigned.
628d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
629d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \sa drmOpenMinor(), drmGetVersion() and drmGetBusid().
630d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
631f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhoustatic int drmOpenByName(const char *name, int type)
632b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strauss{
63388dbee54ed400a3fd5594fab506518c171167805Rik Faith    int           i;
63488dbee54ed400a3fd5594fab506518c171167805Rik Faith    int           fd;
63588dbee54ed400a3fd5594fab506518c171167805Rik Faith    drmVersionPtr version;
63656bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes    char *        id;
637f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou    int           base = drmGetMinorBase(type);
638f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou
639f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou    if (base < 0)
640f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou        return -1;
641db85ed25afc616acfaadb21facf6066354f9d490Dave Airlie
64256bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes    /*
64356bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes     * Open the first minor number that matches the driver name and isn't
64456bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes     * already in use.  If it's in use it will have a busid assigned already.
64556bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes     */
646f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou    for (i = base; i < base + DRM_MAX_MINOR; i++) {
647f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou	if ((fd = drmOpenMinor(i, 1, type)) >= 0) {
64888dbee54ed400a3fd5594fab506518c171167805Rik Faith	    if ((version = drmGetVersion(fd))) {
64988dbee54ed400a3fd5594fab506518c171167805Rik Faith		if (!strcmp(version->name, name)) {
65088dbee54ed400a3fd5594fab506518c171167805Rik Faith		    drmFreeVersion(version);
65156bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes		    id = drmGetBusid(fd);
65256bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes		    drmMsg("drmGetBusid returned '%s'\n", id ? id : "NULL");
65356bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes		    if (!id || !*id) {
65422e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jackson			if (id)
65556bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes			    drmFreeBusid(id);
65656bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes			return fd;
65756bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes		    } else {
65856bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes			drmFreeBusid(id);
65956bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes		    }
66056bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes		} else {
66156bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes		    drmFreeVersion(version);
66288dbee54ed400a3fd5594fab506518c171167805Rik Faith		}
66388dbee54ed400a3fd5594fab506518c171167805Rik Faith	    }
66456bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes	    close(fd);
66588dbee54ed400a3fd5594fab506518c171167805Rik Faith	}
666b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strauss    }
667b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strauss
66888dbee54ed400a3fd5594fab506518c171167805Rik Faith#ifdef __linux__
66922e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jackson    /* Backward-compatibility /proc support */
670b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strauss    for (i = 0; i < 8; i++) {
67188dbee54ed400a3fd5594fab506518c171167805Rik Faith	char proc_name[64], buf[512];
67288dbee54ed400a3fd5594fab506518c171167805Rik Faith	char *driver, *pt, *devstring;
67388dbee54ed400a3fd5594fab506518c171167805Rik Faith	int  retcode;
67488dbee54ed400a3fd5594fab506518c171167805Rik Faith
6750371c290a12f75d36c9c1e7c947bf98fe210908bDaryll Strauss	sprintf(proc_name, "/proc/dri/%d/name", i);
676b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strauss	if ((fd = open(proc_name, 0, 0)) >= 0) {
677b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strauss	    retcode = read(fd, buf, sizeof(buf)-1);
678b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strauss	    close(fd);
679b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strauss	    if (retcode) {
680b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strauss		buf[retcode-1] = '\0';
681b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strauss		for (driver = pt = buf; *pt && *pt != ' '; ++pt)
682b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strauss		    ;
68322e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jackson		if (*pt) { /* Device is next */
684b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strauss		    *pt = '\0';
685b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strauss		    if (!strcmp(driver, name)) { /* Match */
686b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strauss			for (devstring = ++pt; *pt && *pt != ' '; ++pt)
687b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strauss			    ;
688b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strauss			if (*pt) { /* Found busid */
689f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou			    return drmOpenByBusid(++pt, type);
69022e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jackson			} else { /* No busid */
691f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou			    return drmOpenDevice(strtol(devstring, NULL, 0),i, type);
692b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strauss			}
693b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strauss		    }
694b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strauss		}
695b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strauss	    }
696569da5a42ebf10c86d6c6ba81866a888e1c708dcBrian Paul	}
697b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strauss    }
69888dbee54ed400a3fd5594fab506518c171167805Rik Faith#endif
69988dbee54ed400a3fd5594fab506518c171167805Rik Faith
700b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strauss    return -1;
701b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strauss}
702b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
703b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strauss
704d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
705d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Open the DRM device.
706d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
707d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Looks up the specified name and bus ID, and opens the device found.  The
708d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * entry in /dev/dri is created if necessary and if called by root.
709d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
710d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param name driver name. Not referenced if bus ID is supplied.
711d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param busid bus ID. Zero if not known.
712d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
713d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return a file descriptor on success, or a negative value on error.
714d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
715d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
716d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * It calls drmOpenByBusid() if \p busid is specified or drmOpenByName()
717d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * otherwise.
718d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
719b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Straussint drmOpen(const char *name, const char *busid)
720b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
721f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou    return drmOpenWithType(name, busid, DRM_NODE_PRIMARY);
722f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou}
723f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou
724f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou/**
725f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou * Open the DRM device with specified type.
726f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou *
727f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou * Looks up the specified name and bus ID, and opens the device found.  The
728f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou * entry in /dev/dri is created if necessary and if called by root.
729f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou *
730f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou * \param name driver name. Not referenced if bus ID is supplied.
731f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou * \param busid bus ID. Zero if not known.
732f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou * \param type the device node type to open, PRIMARY, CONTROL or RENDER
733f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou *
734f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou * \return a file descriptor on success, or a negative value on error.
735f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou *
736f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou * \internal
737f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou * It calls drmOpenByBusid() if \p busid is specified or drmOpenByName()
738f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou * otherwise.
739f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou */
740f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhouint drmOpenWithType(const char *name, const char *busid, int type)
741f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou{
742eb7c2d5e63e0e9d133b16880e36c14676276d412Rob Clark    if (!drmAvailable() && name != NULL && drm_server_info &&
743eb7c2d5e63e0e9d133b16880e36c14676276d412Rob Clark        drm_server_info->load_module) {
744f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou	/* try to load the kernel module */
74579038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie	if (!drm_server_info->load_module(name)) {
746ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	    drmMsg("[drm] failed to load kernel module \"%s\"\n", name);
74706cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt	    return -1;
74806cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt	}
74906cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    }
75006cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt
75106cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    if (busid) {
752f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou	int fd = drmOpenByBusid(busid, type);
75306cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt	if (fd >= 0)
75406cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt	    return fd;
75506cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    }
75622e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jackson
75706cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    if (name)
758f1adc4b375a16b07f560b86a34e617984049c422Jammy Zhou	return drmOpenByName(name, type);
75922e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jackson
76006cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    return -1;
761b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
762b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
763731cd5526e5c732d51307b26e784f454a724a699Jesse Barnesint drmOpenControl(int minor)
764731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes{
765731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes    return drmOpenMinor(minor, 0, DRM_NODE_CONTROL);
766731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes}
767d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
7680c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binnsint drmOpenRender(int minor)
7690c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns{
7700c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns    return drmOpenMinor(minor, 0, DRM_NODE_RENDER);
7710c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns}
7720c5aaeef51233aec89ee1f43f03d457f278f8fa0Frank Binns
773d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
774d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Free the version information returned by drmGetVersion().
775d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
776d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param v pointer to the version information.
777d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
778d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
779d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * It frees the memory pointed by \p %v as well as all the non-null strings
780d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * pointers in it.
781d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
782b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Straussvoid drmFreeVersion(drmVersionPtr v)
783b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
784ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    if (!v)
785ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return;
7869d8ba2d0d479f53b996c0a0e366acfee52daab3bJakob Bornecrantz    drmFree(v->name);
7879d8ba2d0d479f53b996c0a0e366acfee52daab3bJakob Bornecrantz    drmFree(v->date);
7889d8ba2d0d479f53b996c0a0e366acfee52daab3bJakob Bornecrantz    drmFree(v->desc);
789b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drmFree(v);
790b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
791b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
792d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
793d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
794d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Free the non-public version information returned by the kernel.
795d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
796d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param v pointer to the version information.
797d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
798d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
799d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Used by drmGetVersion() to free the memory pointed by \p %v as well as all
800d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * the non-null strings pointers in it.
801d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
802b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Straussstatic void drmFreeKernelVersion(drm_version_t *v)
803b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
804ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    if (!v)
805ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return;
8069d8ba2d0d479f53b996c0a0e366acfee52daab3bJakob Bornecrantz    drmFree(v->name);
8079d8ba2d0d479f53b996c0a0e366acfee52daab3bJakob Bornecrantz    drmFree(v->date);
8089d8ba2d0d479f53b996c0a0e366acfee52daab3bJakob Bornecrantz    drmFree(v->desc);
809b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drmFree(v);
810b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
811b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
812d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
813d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
814d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Copy version information.
815d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
816d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param d destination pointer.
817d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param s source pointer.
818d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
819d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
820d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Used by drmGetVersion() to translate the information returned by the ioctl
821d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * interface in a private structure into the public structure counterpart.
822d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
823569da5a42ebf10c86d6c6ba81866a888e1c708dcBrian Paulstatic void drmCopyVersion(drmVersionPtr d, const drm_version_t *s)
824b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
825b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    d->version_major      = s->version_major;
826b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    d->version_minor      = s->version_minor;
827b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    d->version_patchlevel = s->version_patchlevel;
828b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    d->name_len           = s->name_len;
8290a1ff35c70730160973715b82112cd97c62ac13eAdam Jackson    d->name               = strdup(s->name);
830b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    d->date_len           = s->date_len;
8310a1ff35c70730160973715b82112cd97c62ac13eAdam Jackson    d->date               = strdup(s->date);
832b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    d->desc_len           = s->desc_len;
8330a1ff35c70730160973715b82112cd97c62ac13eAdam Jackson    d->desc               = strdup(s->desc);
834b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
835b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
836b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
837d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
838d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Query the driver version information.
839d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
840d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
841d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
842d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return pointer to a drmVersion structure which should be freed with
843d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * drmFreeVersion().
844d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
845d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \note Similar information is available via /proc/dri.
846d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
847d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
848d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * It gets the version information via successive DRM_IOCTL_VERSION ioctls,
849d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * first with zeros to get the string lengths, and then the actually strings.
850d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * It also null-terminates them since they might not be already.
851d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
852b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll StraussdrmVersionPtr drmGetVersion(int fd)
853b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
854b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drmVersionPtr retval;
855b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_version_t *version = drmMalloc(sizeof(*version));
856b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
85795f23cf894757d05a6b6c980062a46968dc069b1Daniel Vetter    memclear(*version);
858360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes
8598b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_VERSION, version)) {
860b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	drmFreeKernelVersion(version);
861b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	return NULL;
862b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    }
863b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
864b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    if (version->name_len)
865b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	version->name    = drmMalloc(version->name_len + 1);
866b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    if (version->date_len)
867b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	version->date    = drmMalloc(version->date_len + 1);
868b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    if (version->desc_len)
869b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	version->desc    = drmMalloc(version->desc_len + 1);
870360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes
8718b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_VERSION, version)) {
872b0a928557c91fec527f41ae8b2441174889bf32cAlan Hourihane	drmMsg("DRM_IOCTL_VERSION: %s\n", strerror(errno));
873b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	drmFreeKernelVersion(version);
874b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	return NULL;
875b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    }
876b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
87722e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jackson    /* The results might not be null-terminated strings, so terminate them. */
878b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    if (version->name_len) version->name[version->name_len] = '\0';
879b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    if (version->date_len) version->date[version->date_len] = '\0';
880b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    if (version->desc_len) version->desc[version->desc_len] = '\0';
881b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
882b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    retval = drmMalloc(sizeof(*retval));
883b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drmCopyVersion(retval, version);
884b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drmFreeKernelVersion(version);
885b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return retval;
886b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
887b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
8883903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen
889d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
890d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Get version information for the DRM user space library.
891d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
892d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This version number is driver independent.
893d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
894d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
895d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
896d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return version information.
897d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
898d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
899d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function allocates and fills a drm_version structure with a hard coded
900d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * version number.
901d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
9023903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens OwendrmVersionPtr drmGetLibVersion(int fd)
9033903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen{
9043903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen    drm_version_t *version = drmMalloc(sizeof(*version));
9053903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen
9063903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen    /* Version history:
90779038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie     *   NOTE THIS MUST NOT GO ABOVE VERSION 1.X due to drivers needing it
9083903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen     *   revision 1.0.x = original DRM interface with no drmGetLibVersion
9093903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen     *                    entry point and many drm<Device> extensions
9103903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen     *   revision 1.1.x = added drmCommand entry points for device extensions
9113903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen     *                    added drmGetLibVersion to identify libdrm.a version
91206cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt     *   revision 1.2.x = added drmSetInterfaceVersion
91306cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt     *                    modified drmOpen to handle both busid and name
91479038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie     *   revision 1.3.x = added server + memory manager
9153903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen     */
91679038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie    version->version_major      = 1;
91779038751ffe47ed1ce82766e027d98fd2f0e2c6aDave Airlie    version->version_minor      = 3;
9183903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen    version->version_patchlevel = 0;
9193903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen
9203903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen    return (drmVersionPtr)version;
9213903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen}
9223903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen
9235c6c6913d1260024e5d156db7973c9e46fe1ff03Ben Skeggsint drmGetCap(int fd, uint64_t capability, uint64_t *value)
9245c6c6913d1260024e5d156db7973c9e46fe1ff03Ben Skeggs{
925fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter	struct drm_get_cap cap;
9265c6c6913d1260024e5d156db7973c9e46fe1ff03Ben Skeggs	int ret;
9275c6c6913d1260024e5d156db7973c9e46fe1ff03Ben Skeggs
928fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter	memclear(cap);
929fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter	cap.capability = capability;
930fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter
9315c6c6913d1260024e5d156db7973c9e46fe1ff03Ben Skeggs	ret = drmIoctl(fd, DRM_IOCTL_GET_CAP, &cap);
9325c6c6913d1260024e5d156db7973c9e46fe1ff03Ben Skeggs	if (ret)
9335c6c6913d1260024e5d156db7973c9e46fe1ff03Ben Skeggs		return ret;
9345c6c6913d1260024e5d156db7973c9e46fe1ff03Ben Skeggs
9355c6c6913d1260024e5d156db7973c9e46fe1ff03Ben Skeggs	*value = cap.value;
9363b04c73650b5e9bbcb602fdb8cea0b16ad82d0c0Dave Airlie	return 0;
9375c6c6913d1260024e5d156db7973c9e46fe1ff03Ben Skeggs}
938d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
939ddbbdb13d80ea7f60e6f71356a444995b905366bDamien Lespiauint drmSetClientCap(int fd, uint64_t capability, uint64_t value)
940ddbbdb13d80ea7f60e6f71356a444995b905366bDamien Lespiau{
941fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter	struct drm_set_client_cap cap;
942fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter
943fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter	memclear(cap);
944fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter	cap.capability = capability;
945fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter	cap.value = value;
946ddbbdb13d80ea7f60e6f71356a444995b905366bDamien Lespiau
947ddbbdb13d80ea7f60e6f71356a444995b905366bDamien Lespiau	return drmIoctl(fd, DRM_IOCTL_SET_CLIENT_CAP, &cap);
948ddbbdb13d80ea7f60e6f71356a444995b905366bDamien Lespiau}
949ddbbdb13d80ea7f60e6f71356a444995b905366bDamien Lespiau
950d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
951d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Free the bus ID information.
952d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
953d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param busid bus ID information string as given by drmGetBusid().
954d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
955d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
956d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is just frees the memory pointed by \p busid.
957d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
958b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Straussvoid drmFreeBusid(const char *busid)
959b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
960b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strauss    drmFree((void *)busid);
961b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
962b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
963d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
964d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
965d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Get the bus ID of the device.
966d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
967d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
968d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
969d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return bus ID string.
970d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
971d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
972d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function gets the bus ID via successive DRM_IOCTL_GET_UNIQUE ioctls to
973d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * get the string length and data, passing the arguments in a drm_unique
974d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * structure.
975d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
976b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strausschar *drmGetBusid(int fd)
977b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
978b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strauss    drm_unique_t u;
979b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
980fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(u);
981b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
9828b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_GET_UNIQUE, &u))
983ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return NULL;
984b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strauss    u.unique = drmMalloc(u.unique_len + 1);
9858b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_GET_UNIQUE, &u))
986ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return NULL;
987b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strauss    u.unique[u.unique_len] = '\0';
98806cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt
989b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strauss    return u.unique;
990b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
991b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
992d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
993d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
994d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Set the bus ID of the device.
995d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
996d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
997d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param busid bus ID string.
998d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
999d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success, negative on failure.
1000d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1001d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1002d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_SET_UNIQUE ioctl, passing
1003d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * the arguments in a drm_unique structure.
1004d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
1005b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Straussint drmSetBusid(int fd, const char *busid)
1006b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1007b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strauss    drm_unique_t u;
1008b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1009fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(u);
1010b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strauss    u.unique     = (char *)busid;
1011b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Strauss    u.unique_len = strlen(busid);
1012b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
10138b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_SET_UNIQUE, &u)) {
101456bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes	return -errno;
101556bd9c207770d41a497f3e8237a1099dd9d4cd91David Dawes    }
1016b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return 0;
1017b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1018b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
10198696e71db2d79eb318c00abde625d7b61d6800a1Jon Smirlint drmGetMagic(int fd, drm_magic_t * magic)
1020b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1021b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_auth_t auth;
1022b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1023fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(auth);
1024fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter
1025b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    *magic = 0;
10268b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_GET_MAGIC, &auth))
1027ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return -errno;
1028b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    *magic = auth.magic;
1029b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return 0;
1030b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1031b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
10328696e71db2d79eb318c00abde625d7b61d6800a1Jon Smirlint drmAuthMagic(int fd, drm_magic_t magic)
1033b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1034b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_auth_t auth;
1035b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1036fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(auth);
1037b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    auth.magic = magic;
10388b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_AUTH_MAGIC, &auth))
1039ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return -errno;
1040b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return 0;
1041b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1042b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1043d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1044d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Specifies a range of memory that is available for mapping by a
1045d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * non-root process.
1046d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1047d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
1048d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param offset usually the physical address. The actual meaning depends of
1049d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * the \p type parameter. See below.
1050d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param size of the memory in bytes.
1051d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param type type of the memory to be mapped.
1052d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param flags combination of several flags to modify the function actions.
1053d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param handle will be set to a value that may be used as the offset
1054d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * parameter for mmap().
1055d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1056d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success or a negative value on error.
1057d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1058d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \par Mapping the frame buffer
1059d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * For the frame buffer
1060d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * - \p offset will be the physical address of the start of the frame buffer,
1061d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * - \p size will be the size of the frame buffer in bytes, and
1062d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * - \p type will be DRM_FRAME_BUFFER.
1063d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1064d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \par
1065d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * The area mapped will be uncached. If MTRR support is available in the
1066d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * kernel, the frame buffer area will be set to write combining.
1067d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1068d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \par Mapping the MMIO register area
1069d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * For the MMIO register area,
1070d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * - \p offset will be the physical address of the start of the register area,
1071d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * - \p size will be the size of the register area bytes, and
1072d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * - \p type will be DRM_REGISTERS.
1073d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \par
1074d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * The area mapped will be uncached.
1075d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1076d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \par Mapping the SAREA
1077d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * For the SAREA,
1078d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * - \p offset will be ignored and should be set to zero,
1079d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * - \p size will be the desired size of the SAREA in bytes,
1080d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * - \p type will be DRM_SHM.
1081d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1082d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \par
1083d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * A shared memory area of the requested size will be created and locked in
1084d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * kernel memory. This area may be mapped into client-space by using the handle
1085d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * returned.
1086d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1087d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \note May only be called by root.
1088d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1089d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1090d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_ADD_MAP ioctl, passing
1091d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * the arguments in a drm_map structure.
1092d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
109322e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jacksonint drmAddMap(int fd, drm_handle_t offset, drmSize size, drmMapType type,
109422e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jackson	      drmMapFlags flags, drm_handle_t *handle)
1095b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1096b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_map_t map;
1097b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1098fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(map);
1099b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    map.offset  = offset;
1100b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    map.size    = size;
1101b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    map.type    = type;
1102b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    map.flags   = flags;
11038b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_ADD_MAP, &map))
1104ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return -errno;
1105ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    if (handle)
1106961bf9b5c2866ccb4fedf2b45b29fb688519d0dbJeremy Huddleston	*handle = (drm_handle_t)(uintptr_t)map.handle;
1107b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return 0;
1108b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1109b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
11108696e71db2d79eb318c00abde625d7b61d6800a1Jon Smirlint drmRmMap(int fd, drm_handle_t handle)
111174e19a40187ac3b5907922e5dc01418135a5794bKevin E Martin{
111274e19a40187ac3b5907922e5dc01418135a5794bKevin E Martin    drm_map_t map;
111374e19a40187ac3b5907922e5dc01418135a5794bKevin E Martin
1114fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(map);
1115961bf9b5c2866ccb4fedf2b45b29fb688519d0dbJeremy Huddleston    map.handle = (void *)(uintptr_t)handle;
111674e19a40187ac3b5907922e5dc01418135a5794bKevin E Martin
11178b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if(drmIoctl(fd, DRM_IOCTL_RM_MAP, &map))
1118ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return -errno;
111974e19a40187ac3b5907922e5dc01418135a5794bKevin E Martin    return 0;
112074e19a40187ac3b5907922e5dc01418135a5794bKevin E Martin}
112174e19a40187ac3b5907922e5dc01418135a5794bKevin E Martin
1122d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1123d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Make buffers available for DMA transfers.
1124d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1125d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
1126d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param count number of buffers.
1127d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param size size of each buffer.
1128d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param flags buffer allocation flags.
1129d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param agp_offset offset in the AGP aperture
1130d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1131d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return number of buffers allocated, negative on error.
1132d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1133d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1134d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around DRM_IOCTL_ADD_BUFS ioctl.
1135d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1136d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \sa drm_buf_desc.
1137d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
1138ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmannint drmAddBufs(int fd, int count, int size, drmBufDescFlags flags,
1139ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann	       int agp_offset)
1140b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1141b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_buf_desc_t request;
1142360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes
1143fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(request);
1144b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    request.count     = count;
1145b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    request.size      = size;
1146b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    request.flags     = flags;
1147ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    request.agp_start = agp_offset;
1148360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes
11498b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_ADD_BUFS, &request))
1150ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return -errno;
1151b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return request.count;
1152b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1153b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1154b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Straussint drmMarkBufs(int fd, double low, double high)
1155b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1156b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_buf_info_t info;
1157b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    int            i;
1158b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1159fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(info);
1160b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
11618b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info))
1162ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return -EINVAL;
1163b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1164ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    if (!info.count)
1165ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return -EINVAL;
1166360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes
1167b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    if (!(info.list = drmMalloc(info.count * sizeof(*info.list))))
1168b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	return -ENOMEM;
1169360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes
11708b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info)) {
1171b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	int retval = -errno;
1172b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	drmFree(info.list);
1173b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	return retval;
1174b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    }
1175360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes
1176b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    for (i = 0; i < info.count; i++) {
1177b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	info.list[i].low_mark  = low  * info.list[i].count;
1178b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	info.list[i].high_mark = high * info.list[i].count;
11798b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard	if (drmIoctl(fd, DRM_IOCTL_MARK_BUFS, &info.list[i])) {
1180b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	    int retval = -errno;
1181b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	    drmFree(info.list);
1182b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	    return retval;
1183b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	}
1184b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    }
1185b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drmFree(info.list);
1186360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes
1187b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return 0;
1188b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1189b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1190d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1191d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Free buffers.
1192d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1193d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
1194d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param count number of buffers to free.
1195d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param list list of buffers to be freed.
1196d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1197d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success, or a negative value on failure.
1198d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1199d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \note This function is primarily used for debugging.
1200d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1201d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1202d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_FREE_BUFS ioctl, passing
1203d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * the arguments in a drm_buf_free structure.
1204d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
1205b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Straussint drmFreeBufs(int fd, int count, int *list)
1206b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1207b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_buf_free_t request;
1208b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1209fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(request);
1210b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    request.count = count;
1211b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    request.list  = list;
12128b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_FREE_BUFS, &request))
1213ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return -errno;
1214b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return 0;
1215b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1216b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1217d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
1218d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1219d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Close the device.
1220d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1221d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
1222d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1223d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1224d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function closes the file descriptor.
1225d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
1226b6a28bfe98f2c89cfb91079bd3c7b63fb0144eb1Daryll Straussint drmClose(int fd)
1227b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1228b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    unsigned long key    = drmGetKeyFromFd(fd);
1229b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drmHashEntry  *entry = drmGetEntry(fd);
1230b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1231b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drmHashDestroy(entry->tagTable);
1232b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    entry->fd       = 0;
1233b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    entry->f        = NULL;
1234b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    entry->tagTable = NULL;
1235b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1236b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drmHashDelete(drmHashTable, key);
1237b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drmFree(entry);
1238b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1239b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return close(fd);
1240b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1241b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1242d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
1243d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1244d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Map a region of memory.
1245d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1246d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
1247d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param handle handle returned by drmAddMap().
1248d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param size size in bytes. Must match the size used by drmAddMap().
1249d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param address will contain the user-space virtual address where the mapping
1250d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * begins.
1251d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1252d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success, or a negative value on failure.
1253d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1254d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1255d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper for mmap().
1256d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
125722e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jacksonint drmMap(int fd, drm_handle_t handle, drmSize size, drmAddressPtr address)
1258b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1259c7558d8fa4df805b7f7ff3d631432eadac9b8a1cAlan Hourihane    static unsigned long pagesize_mask = 0;
1260c7558d8fa4df805b7f7ff3d631432eadac9b8a1cAlan Hourihane
1261ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    if (fd < 0)
1262ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return -EINVAL;
1263c7558d8fa4df805b7f7ff3d631432eadac9b8a1cAlan Hourihane
1264c7558d8fa4df805b7f7ff3d631432eadac9b8a1cAlan Hourihane    if (!pagesize_mask)
1265c7558d8fa4df805b7f7ff3d631432eadac9b8a1cAlan Hourihane	pagesize_mask = getpagesize() - 1;
1266c7558d8fa4df805b7f7ff3d631432eadac9b8a1cAlan Hourihane
1267c7558d8fa4df805b7f7ff3d631432eadac9b8a1cAlan Hourihane    size = (size + pagesize_mask) & ~pagesize_mask;
1268c7558d8fa4df805b7f7ff3d631432eadac9b8a1cAlan Hourihane
1269faf51d5694e3f0ec12c7fa1fd2f87fc96a300fe3Emil Velikov    *address = drm_mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, handle);
1270ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    if (*address == MAP_FAILED)
1271ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return -errno;
1272b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return 0;
1273b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1274b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1275d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
1276d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1277d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Unmap mappings obtained with drmMap().
1278d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1279d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param address address as given by drmMap().
1280d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param size size in bytes. Must match the size used by drmMap().
1281d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1282d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success, or a negative value on failure.
1283d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1284d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
128522e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jackson * This function is a wrapper for munmap().
1286d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
1287b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Straussint drmUnmap(drmAddress address, drmSize size)
1288b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1289faf51d5694e3f0ec12c7fa1fd2f87fc96a300fe3Emil Velikov    return drm_munmap(address, size);
1290b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1291b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1292b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll StraussdrmBufInfoPtr drmGetBufInfo(int fd)
1293b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1294b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_buf_info_t info;
1295b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drmBufInfoPtr  retval;
1296b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    int            i;
1297b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1298fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(info);
1299b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
13008b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info))
1301ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return NULL;
1302b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1303b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    if (info.count) {
1304b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	if (!(info.list = drmMalloc(info.count * sizeof(*info.list))))
1305b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	    return NULL;
1306360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes
13078b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard	if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info)) {
1308b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	    drmFree(info.list);
1309b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	    return NULL;
1310b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	}
131122e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jackson
1312b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	retval = drmMalloc(sizeof(*retval));
1313b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	retval->count = info.count;
1314b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	retval->list  = drmMalloc(info.count * sizeof(*retval->list));
1315b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	for (i = 0; i < info.count; i++) {
1316b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	    retval->list[i].count     = info.list[i].count;
1317b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	    retval->list[i].size      = info.list[i].size;
1318b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	    retval->list[i].low_mark  = info.list[i].low_mark;
1319b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	    retval->list[i].high_mark = info.list[i].high_mark;
1320b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	}
1321b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	drmFree(info.list);
1322b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	return retval;
1323b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    }
1324b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return NULL;
1325b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1326b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1327d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1328d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Map all DMA buffers into client-virtual space.
1329d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1330d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
1331d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1332d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return a pointer to a ::drmBufMap structure.
1333d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1334d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \note The client may not use these buffers until obtaining buffer indices
1335d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * with drmDMA().
1336d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1337d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1338d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function calls the DRM_IOCTL_MAP_BUFS ioctl and copies the returned
1339d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * information about the buffers in a drm_buf_map structure into the
1340d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * client-visible data structures.
1341d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
1342b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll StraussdrmBufMapPtr drmMapBufs(int fd)
1343b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1344b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_buf_map_t bufs;
1345b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drmBufMapPtr  retval;
1346b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    int           i;
1347360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes
1348fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(bufs);
13498b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_MAP_BUFS, &bufs))
1350ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return NULL;
1351b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1352ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    if (!bufs.count)
1353ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return NULL;
13548696e71db2d79eb318c00abde625d7b61d6800a1Jon Smirl
1355b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	if (!(bufs.list = drmMalloc(bufs.count * sizeof(*bufs.list))))
1356b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	    return NULL;
1357b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
13588b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard	if (drmIoctl(fd, DRM_IOCTL_MAP_BUFS, &bufs)) {
1359b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	    drmFree(bufs.list);
1360b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	    return NULL;
1361b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	}
136222e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jackson
1363b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	retval = drmMalloc(sizeof(*retval));
1364b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	retval->count = bufs.count;
1365b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	retval->list  = drmMalloc(bufs.count * sizeof(*retval->list));
1366b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	for (i = 0; i < bufs.count; i++) {
1367b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	    retval->list[i].idx     = bufs.list[i].idx;
1368b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	    retval->list[i].total   = bufs.list[i].total;
1369b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	    retval->list[i].used    = 0;
1370b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	    retval->list[i].address = bufs.list[i].address;
1371b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	}
13728696e71db2d79eb318c00abde625d7b61d6800a1Jon Smirl
13738696e71db2d79eb318c00abde625d7b61d6800a1Jon Smirl	drmFree(bufs.list);
13748696e71db2d79eb318c00abde625d7b61d6800a1Jon Smirl
1375b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	return retval;
1376b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1377b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1378d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
1379d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1380d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Unmap buffers allocated with drmMapBufs().
1381d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1382d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success, or negative value on failure.
1383d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1384d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
13858696e71db2d79eb318c00abde625d7b61d6800a1Jon Smirl * Calls munmap() for every buffer stored in \p bufs and frees the
13868696e71db2d79eb318c00abde625d7b61d6800a1Jon Smirl * memory allocated by drmMapBufs().
1387d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
1388b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Straussint drmUnmapBufs(drmBufMapPtr bufs)
1389b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1390b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    int i;
1391360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes
1392b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    for (i = 0; i < bufs->count; i++) {
1393faf51d5694e3f0ec12c7fa1fd2f87fc96a300fe3Emil Velikov	drm_munmap(bufs->list[i].address, bufs->list[i].total);
1394b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    }
13958696e71db2d79eb318c00abde625d7b61d6800a1Jon Smirl
13968696e71db2d79eb318c00abde625d7b61d6800a1Jon Smirl    drmFree(bufs->list);
13978696e71db2d79eb318c00abde625d7b61d6800a1Jon Smirl    drmFree(bufs);
13988696e71db2d79eb318c00abde625d7b61d6800a1Jon Smirl
1399b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return 0;
1400b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1401b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1402d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
1403360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes#define DRM_DMA_RETRY		16
1404360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes
1405d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1406d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Reserve DMA buffers.
1407d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1408d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
1409d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param request
1410d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1411d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success, or a negative value on failure.
1412d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1413d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1414d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Assemble the arguments into a drm_dma structure and keeps issuing the
1415d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * DRM_IOCTL_DMA ioctl until success or until maximum number of retries.
1416d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
1417b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Straussint drmDMA(int fd, drmDMAReqPtr request)
1418b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1419b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_dma_t dma;
1420360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes    int ret, i = 0;
1421b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1422b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    dma.context         = request->context;
1423b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    dma.send_count      = request->send_count;
1424b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    dma.send_indices    = request->send_list;
1425b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    dma.send_sizes      = request->send_sizes;
1426b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    dma.flags           = request->flags;
1427b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    dma.request_count   = request->request_count;
1428b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    dma.request_size    = request->request_size;
1429b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    dma.request_indices = request->request_list;
1430b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    dma.request_sizes   = request->request_sizes;
14318696e71db2d79eb318c00abde625d7b61d6800a1Jon Smirl    dma.granted_count   = 0;
1432360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes
1433360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes    do {
1434360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes	ret = ioctl( fd, DRM_IOCTL_DMA, &dma );
1435360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes    } while ( ret && errno == EAGAIN && i++ < DRM_DMA_RETRY );
1436360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes
1437360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes    if ( ret == 0 ) {
1438360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes	request->granted_count = dma.granted_count;
1439360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes	return 0;
1440360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes    } else {
1441360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes	return -errno;
1442360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes    }
1443b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1444b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1445d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
1446d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1447d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Obtain heavyweight hardware lock.
1448d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1449d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
1450d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param context context.
1451d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param flags flags that determine the sate of the hardware when the function
1452d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * returns.
1453d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1454d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return always zero.
1455d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1456d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1457d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function translates the arguments into a drm_lock structure and issue
1458d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * the DRM_IOCTL_LOCK ioctl until the lock is successfully acquired.
1459d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
14608696e71db2d79eb318c00abde625d7b61d6800a1Jon Smirlint drmGetLock(int fd, drm_context_t context, drmLockFlags flags)
1461b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1462b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_lock_t lock;
1463b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1464fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(lock);
1465b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    lock.context = context;
1466b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    lock.flags   = 0;
1467b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    if (flags & DRM_LOCK_READY)      lock.flags |= _DRM_LOCK_READY;
1468b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    if (flags & DRM_LOCK_QUIESCENT)  lock.flags |= _DRM_LOCK_QUIESCENT;
1469b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    if (flags & DRM_LOCK_FLUSH)      lock.flags |= _DRM_LOCK_FLUSH;
1470b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    if (flags & DRM_LOCK_FLUSH_ALL)  lock.flags |= _DRM_LOCK_FLUSH_ALL;
1471b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    if (flags & DRM_HALT_ALL_QUEUES) lock.flags |= _DRM_HALT_ALL_QUEUES;
1472b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    if (flags & DRM_HALT_CUR_QUEUES) lock.flags |= _DRM_HALT_CUR_QUEUES;
1473360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes
14748b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    while (drmIoctl(fd, DRM_IOCTL_LOCK, &lock))
1475b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	;
1476b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return 0;
1477b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1478b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1479d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1480d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Release the hardware lock.
1481d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1482d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
1483d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param context context.
1484d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1485d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success, or a negative value on failure.
1486d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1487d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1488d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_UNLOCK ioctl, passing the
1489d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * argument in a drm_lock structure.
1490d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
14918696e71db2d79eb318c00abde625d7b61d6800a1Jon Smirlint drmUnlock(int fd, drm_context_t context)
1492b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1493b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_lock_t lock;
1494b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1495fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(lock);
1496b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    lock.context = context;
14978b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    return drmIoctl(fd, DRM_IOCTL_UNLOCK, &lock);
1498b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1499b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
150022e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jacksondrm_context_t *drmGetReservedContextList(int fd, int *count)
1501b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1502b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_ctx_res_t res;
1503b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_ctx_t     *list;
15048696e71db2d79eb318c00abde625d7b61d6800a1Jon Smirl    drm_context_t * retval;
1505b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    int           i;
1506b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1507fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(res);
15088b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_RES_CTX, &res))
1509ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return NULL;
1510b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1511ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    if (!res.count)
1512ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return NULL;
1513b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1514ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    if (!(list   = drmMalloc(res.count * sizeof(*list))))
1515ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return NULL;
1516b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    if (!(retval = drmMalloc(res.count * sizeof(*retval)))) {
1517b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	drmFree(list);
1518b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	return NULL;
1519b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    }
1520b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1521b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    res.contexts = list;
15228b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_RES_CTX, &res))
1523ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return NULL;
1524b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1525ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    for (i = 0; i < res.count; i++)
1526ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	retval[i] = list[i].handle;
1527b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drmFree(list);
1528b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1529b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    *count = res.count;
1530b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return retval;
1531b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1532b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
153322e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jacksonvoid drmFreeReservedContextList(drm_context_t *pt)
1534b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1535b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drmFree(pt);
1536b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1537b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1538d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1539d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Create context.
1540d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1541d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Used by the X server during GLXContext initialization. This causes
1542d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * per-context kernel-level resources to be allocated.
1543d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1544d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
1545d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param handle is set on success. To be used by the client when requesting DMA
1546d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * dispatch with drmDMA().
1547d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1548d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success, or a negative value on failure.
1549d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1550d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \note May only be called by root.
1551d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1552d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1553d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_ADD_CTX ioctl, passing the
1554d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * argument in a drm_ctx structure.
1555d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
155622e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jacksonint drmCreateContext(int fd, drm_context_t *handle)
1557b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1558b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_ctx_t ctx;
1559b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1560fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(ctx);
15618b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_ADD_CTX, &ctx))
1562ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return -errno;
1563b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    *handle = ctx.handle;
1564b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return 0;
1565b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1566b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
15678696e71db2d79eb318c00abde625d7b61d6800a1Jon Smirlint drmSwitchToContext(int fd, drm_context_t context)
1568b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1569b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_ctx_t ctx;
1570b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1571fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(ctx);
1572b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    ctx.handle = context;
15738b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_SWITCH_CTX, &ctx))
1574ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return -errno;
1575b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return 0;
1576b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1577b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
15788696e71db2d79eb318c00abde625d7b61d6800a1Jon Smirlint drmSetContextFlags(int fd, drm_context_t context, drm_context_tFlags flags)
1579b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1580b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_ctx_t ctx;
1581b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
158222e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jackson    /*
158322e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jackson     * Context preserving means that no context switches are done between DMA
158422e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jackson     * buffers from one context and the next.  This is suitable for use in the
158522e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jackson     * X server (which promises to maintain hardware context), or in the
158622e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jackson     * client-side library when buffers are swapped on behalf of two threads.
158722e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jackson     */
1588fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(ctx);
1589b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    ctx.handle = context;
1590ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    if (flags & DRM_CONTEXT_PRESERVED)
1591ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	ctx.flags |= _DRM_CONTEXT_PRESERVED;
1592ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    if (flags & DRM_CONTEXT_2DONLY)
1593ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	ctx.flags |= _DRM_CONTEXT_2DONLY;
15948b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_MOD_CTX, &ctx))
1595ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return -errno;
1596b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return 0;
1597b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1598b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
159922e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jacksonint drmGetContextFlags(int fd, drm_context_t context,
160022e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jackson                       drm_context_tFlagsPtr flags)
1601b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1602b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_ctx_t ctx;
1603b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
1604fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(ctx);
1605b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    ctx.handle = context;
16068b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_GET_CTX, &ctx))
1607ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return -errno;
1608b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    *flags = 0;
1609ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    if (ctx.flags & _DRM_CONTEXT_PRESERVED)
1610ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	*flags |= DRM_CONTEXT_PRESERVED;
1611ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    if (ctx.flags & _DRM_CONTEXT_2DONLY)
1612ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	*flags |= DRM_CONTEXT_2DONLY;
1613b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return 0;
1614b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1615360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes
1616d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1617d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Destroy context.
1618d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1619d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Free any kernel-level resources allocated with drmCreateContext() associated
1620d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * with the context.
1621d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1622d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
1623d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param handle handle given by drmCreateContext().
1624d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1625d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success, or a negative value on failure.
1626d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1627d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \note May only be called by root.
1628d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1629d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1630d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_RM_CTX ioctl, passing the
1631d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * argument in a drm_ctx structure.
1632d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
16338696e71db2d79eb318c00abde625d7b61d6800a1Jon Smirlint drmDestroyContext(int fd, drm_context_t handle)
1634b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1635b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_ctx_t ctx;
1636fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter
1637fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(ctx);
1638b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    ctx.handle = handle;
16398b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_RM_CTX, &ctx))
1640ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return -errno;
1641b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return 0;
1642b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1643b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
164422e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jacksonint drmCreateDrawable(int fd, drm_drawable_t *handle)
1645b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1646b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_draw_t draw;
1647fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter
1648fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(draw);
16498b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_ADD_DRAW, &draw))
1650ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return -errno;
1651b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    *handle = draw.handle;
1652b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return 0;
1653b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1654b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
16558696e71db2d79eb318c00abde625d7b61d6800a1Jon Smirlint drmDestroyDrawable(int fd, drm_drawable_t handle)
1656b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
1657b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_draw_t draw;
1658fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter
1659fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(draw);
1660b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    draw.handle = handle;
16618b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_RM_DRAW, &draw))
1662ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return -errno;
1663b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return 0;
1664b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
1665b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
16669810ec2737de6aa81e764225f580e4ea39de437aMichel Dänzerint drmUpdateDrawableInfo(int fd, drm_drawable_t handle,
16679810ec2737de6aa81e764225f580e4ea39de437aMichel Dänzer			   drm_drawable_info_type_t type, unsigned int num,
16689810ec2737de6aa81e764225f580e4ea39de437aMichel Dänzer			   void *data)
16699810ec2737de6aa81e764225f580e4ea39de437aMichel Dänzer{
16709810ec2737de6aa81e764225f580e4ea39de437aMichel Dänzer    drm_update_draw_t update;
16719810ec2737de6aa81e764225f580e4ea39de437aMichel Dänzer
1672fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(update);
16739810ec2737de6aa81e764225f580e4ea39de437aMichel Dänzer    update.handle = handle;
16749810ec2737de6aa81e764225f580e4ea39de437aMichel Dänzer    update.type = type;
16759810ec2737de6aa81e764225f580e4ea39de437aMichel Dänzer    update.num = num;
16769810ec2737de6aa81e764225f580e4ea39de437aMichel Dänzer    update.data = (unsigned long long)(unsigned long)data;
16779810ec2737de6aa81e764225f580e4ea39de437aMichel Dänzer
16788b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_UPDATE_DRAW, &update))
1679ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return -errno;
16809810ec2737de6aa81e764225f580e4ea39de437aMichel Dänzer
16819810ec2737de6aa81e764225f580e4ea39de437aMichel Dänzer    return 0;
16829810ec2737de6aa81e764225f580e4ea39de437aMichel Dänzer}
16839810ec2737de6aa81e764225f580e4ea39de437aMichel Dänzer
1684d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1685d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Acquire the AGP device.
1686d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1687d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Must be called before any of the other AGP related calls.
1688d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1689d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
1690d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1691d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success, or a negative value on failure.
1692d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1693d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1694d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_AGP_ACQUIRE ioctl.
1695d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
1696ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmannint drmAgpAcquire(int fd)
1697ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann{
16988b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_AGP_ACQUIRE, NULL))
1699ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return -errno;
1700ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    return 0;
1701ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann}
1702ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
1703d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
1704d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1705d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Release the AGP device.
1706d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1707d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
1708d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1709d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success, or a negative value on failure.
1710d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1711d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1712d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_AGP_RELEASE ioctl.
1713d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
1714ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmannint drmAgpRelease(int fd)
1715ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann{
17168b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_AGP_RELEASE, NULL))
1717ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return -errno;
1718ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    return 0;
1719ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann}
1720ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
1721d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
1722d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1723d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Set the AGP mode.
1724d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1725d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
1726d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param mode AGP mode.
1727d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1728d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success, or a negative value on failure.
1729d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1730d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1731d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_AGP_ENABLE ioctl, passing the
1732d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * argument in a drm_agp_mode structure.
1733d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
1734ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmannint drmAgpEnable(int fd, unsigned long mode)
1735ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann{
1736ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    drm_agp_mode_t m;
1737ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
17381490055bc05fa941b59d10e89ef3fccd673af477Connor Behan    memclear(m);
1739ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    m.mode = mode;
17408b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_AGP_ENABLE, &m))
1741ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return -errno;
1742ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    return 0;
1743ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann}
1744ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
1745d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
1746d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1747d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Allocate a chunk of AGP memory.
1748d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1749d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
1750d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param size requested memory size in bytes. Will be rounded to page boundary.
1751d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param type type of memory to allocate.
1752d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param address if not zero, will be set to the physical address of the
1753d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * allocated memory.
1754d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param handle on success will be set to a handle of the allocated memory.
1755d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1756d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success, or a negative value on failure.
1757d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1758d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1759d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_AGP_ALLOC ioctl, passing the
1760d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * arguments in a drm_agp_buffer structure.
1761d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
1762ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmannint drmAgpAlloc(int fd, unsigned long size, unsigned long type,
17637ede209ce0cbbc65f79d02e2cc43cfcb3abb6e99Dave Airlie		unsigned long *address, drm_handle_t *handle)
1764ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann{
1765ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    drm_agp_buffer_t b;
1766b0a928557c91fec527f41ae8b2441174889bf32cAlan Hourihane
1767fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(b);
1768b0a928557c91fec527f41ae8b2441174889bf32cAlan Hourihane    *handle = DRM_AGP_NO_HANDLE;
1769ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    b.size   = size;
1770ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    b.type   = type;
17718b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_AGP_ALLOC, &b))
1772ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return -errno;
1773ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    if (address != 0UL)
1774ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	*address = b.physical;
1775ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    *handle = b.handle;
1776ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    return 0;
1777ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann}
1778ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
1779d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
1780d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1781d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Free a chunk of AGP memory.
1782d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1783d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
1784d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param handle handle to the allocated memory, as given by drmAgpAllocate().
1785d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1786d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success, or a negative value on failure.
1787d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1788d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1789d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_AGP_FREE ioctl, passing the
1790d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * argument in a drm_agp_buffer structure.
1791d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
17927ede209ce0cbbc65f79d02e2cc43cfcb3abb6e99Dave Airlieint drmAgpFree(int fd, drm_handle_t handle)
1793ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann{
1794ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    drm_agp_buffer_t b;
1795ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
1796fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(b);
1797ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    b.handle = handle;
17988b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_AGP_FREE, &b))
1799ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return -errno;
1800ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    return 0;
1801ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann}
1802ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
1803d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
1804d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1805d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Bind a chunk of AGP memory.
1806d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1807d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
1808d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param handle handle to the allocated memory, as given by drmAgpAllocate().
1809d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param offset offset in bytes. It will round to page boundary.
1810d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1811d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success, or a negative value on failure.
1812d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1813d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1814d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_AGP_BIND ioctl, passing the
1815d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * argument in a drm_agp_binding structure.
1816d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
18177ede209ce0cbbc65f79d02e2cc43cfcb3abb6e99Dave Airlieint drmAgpBind(int fd, drm_handle_t handle, unsigned long offset)
1818ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann{
1819ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    drm_agp_binding_t b;
1820ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
1821fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(b);
1822ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    b.handle = handle;
1823ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    b.offset = offset;
18248b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_AGP_BIND, &b))
1825ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return -errno;
1826ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    return 0;
1827ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann}
1828ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
1829d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
1830d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1831d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Unbind a chunk of AGP memory.
1832d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1833d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
1834d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param handle handle to the allocated memory, as given by drmAgpAllocate().
1835d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1836d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success, or a negative value on failure.
1837d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1838d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1839d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_AGP_UNBIND ioctl, passing
1840d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * the argument in a drm_agp_binding structure.
1841d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
18427ede209ce0cbbc65f79d02e2cc43cfcb3abb6e99Dave Airlieint drmAgpUnbind(int fd, drm_handle_t handle)
1843ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann{
1844ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    drm_agp_binding_t b;
1845ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
1846fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(b);
1847ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    b.handle = handle;
18488b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_AGP_UNBIND, &b))
1849ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return -errno;
1850ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    return 0;
1851ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann}
1852ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
1853d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
1854d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1855d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Get AGP driver major version number.
1856d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1857d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
1858d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1859d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return major version number on success, or a negative value on failure..
1860d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1861d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1862d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1863d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * necessary information in a drm_agp_info structure.
1864d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
1865ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmannint drmAgpVersionMajor(int fd)
1866ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann{
1867ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    drm_agp_info_t i;
1868ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
1869fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(i);
1870fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter
18718b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
1872ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return -errno;
1873ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    return i.agp_version_major;
1874ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann}
1875ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
1876d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
1877d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1878d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Get AGP driver minor version number.
1879d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1880d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
1881d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1882d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return minor version number on success, or a negative value on failure.
1883d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1884d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1885d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1886d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * necessary information in a drm_agp_info structure.
1887d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
1888ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmannint drmAgpVersionMinor(int fd)
1889ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann{
1890ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    drm_agp_info_t i;
1891ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
1892fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(i);
1893fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter
18948b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
1895ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return -errno;
1896ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    return i.agp_version_minor;
1897ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann}
1898ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
1899d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
1900d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1901d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Get AGP mode.
1902d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1903d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
1904d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1905d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return mode on success, or zero on failure.
1906d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1907d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1908d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1909d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * necessary information in a drm_agp_info structure.
1910d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
1911ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmannunsigned long drmAgpGetMode(int fd)
1912ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann{
1913ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    drm_agp_info_t i;
1914ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
1915fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(i);
1916fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter
19178b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
1918ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return 0;
1919ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    return i.mode;
1920ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann}
1921ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
1922d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
1923d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1924d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Get AGP aperture base.
1925d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1926d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
1927d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1928d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return aperture base on success, zero on failure.
1929d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1930d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1931d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1932d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * necessary information in a drm_agp_info structure.
1933d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
1934ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmannunsigned long drmAgpBase(int fd)
1935ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann{
1936ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    drm_agp_info_t i;
1937ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
1938fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(i);
1939fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter
19408b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
1941ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return 0;
1942ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    return i.aperture_base;
1943ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann}
1944ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
1945d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
1946d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1947d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Get AGP aperture size.
1948d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1949d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
1950d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1951d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return aperture size on success, zero on failure.
1952d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1953d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1954d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1955d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * necessary information in a drm_agp_info structure.
1956d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
1957ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmannunsigned long drmAgpSize(int fd)
1958ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann{
1959ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    drm_agp_info_t i;
1960ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
1961fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(i);
1962fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter
19638b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
1964ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return 0;
1965ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    return i.aperture_size;
1966ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann}
1967ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
1968d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
1969d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1970d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Get used AGP memory.
1971d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1972d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
1973d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1974d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return memory used on success, or zero on failure.
1975d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1976d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
1977d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1978d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * necessary information in a drm_agp_info structure.
1979d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
1980ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmannunsigned long drmAgpMemoryUsed(int fd)
1981ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann{
1982ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    drm_agp_info_t i;
1983ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
1984fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(i);
1985fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter
19868b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
1987ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return 0;
1988ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    return i.memory_used;
1989ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann}
1990ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
1991d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
1992d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
1993d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Get available AGP memory.
1994d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1995d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
1996d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1997d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return memory available on success, or zero on failure.
1998d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
1999d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
2000d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
2001d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * necessary information in a drm_agp_info structure.
2002d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
2003ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmannunsigned long drmAgpMemoryAvail(int fd)
2004ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann{
2005ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    drm_agp_info_t i;
2006ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
2007fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(i);
2008fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter
20098b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
2010ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return 0;
2011ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    return i.memory_allowed;
2012ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann}
2013ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
2014d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
2015d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
2016d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Get hardware vendor ID.
2017d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
2018d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
2019d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
2020d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return vendor ID on success, or zero on failure.
2021d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
2022d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
2023d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
2024d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * necessary information in a drm_agp_info structure.
2025d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
2026ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmannunsigned int drmAgpVendorId(int fd)
2027ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann{
2028ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    drm_agp_info_t i;
2029ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
2030fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(i);
2031fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter
20328b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
2033ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return 0;
2034ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    return i.id_vendor;
2035ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann}
2036ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
2037d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
2038d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
2039d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Get hardware device ID.
2040d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
2041d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
2042d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
2043d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success, or zero on failure.
2044d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
2045d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
2046d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
2047d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * necessary information in a drm_agp_info structure.
2048d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
2049ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmannunsigned int drmAgpDeviceId(int fd)
2050ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann{
2051ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    drm_agp_info_t i;
2052ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
2053fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(i);
2054fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter
20558b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
2056ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return 0;
2057ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann    return i.id_device;
2058ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann}
2059ba1b1ae3806490cce16a9c8957b52cd74967f463Jeff Hartmann
20607ede209ce0cbbc65f79d02e2cc43cfcb3abb6e99Dave Airlieint drmScatterGatherAlloc(int fd, unsigned long size, drm_handle_t *handle)
20615d6ddbca26d695561fb1d08d798a0cc254b805e7Kevin E Martin{
20625d6ddbca26d695561fb1d08d798a0cc254b805e7Kevin E Martin    drm_scatter_gather_t sg;
20635d6ddbca26d695561fb1d08d798a0cc254b805e7Kevin E Martin
2064fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(sg);
2065fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter
20665d6ddbca26d695561fb1d08d798a0cc254b805e7Kevin E Martin    *handle = 0;
20675d6ddbca26d695561fb1d08d798a0cc254b805e7Kevin E Martin    sg.size   = size;
20688b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_SG_ALLOC, &sg))
2069ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return -errno;
20705d6ddbca26d695561fb1d08d798a0cc254b805e7Kevin E Martin    *handle = sg.handle;
20715d6ddbca26d695561fb1d08d798a0cc254b805e7Kevin E Martin    return 0;
20725d6ddbca26d695561fb1d08d798a0cc254b805e7Kevin E Martin}
20735d6ddbca26d695561fb1d08d798a0cc254b805e7Kevin E Martin
20747ede209ce0cbbc65f79d02e2cc43cfcb3abb6e99Dave Airlieint drmScatterGatherFree(int fd, drm_handle_t handle)
20755d6ddbca26d695561fb1d08d798a0cc254b805e7Kevin E Martin{
20765d6ddbca26d695561fb1d08d798a0cc254b805e7Kevin E Martin    drm_scatter_gather_t sg;
20775d6ddbca26d695561fb1d08d798a0cc254b805e7Kevin E Martin
2078fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(sg);
20795d6ddbca26d695561fb1d08d798a0cc254b805e7Kevin E Martin    sg.handle = handle;
20808b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_SG_FREE, &sg))
2081ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return -errno;
20825d6ddbca26d695561fb1d08d798a0cc254b805e7Kevin E Martin    return 0;
20835d6ddbca26d695561fb1d08d798a0cc254b805e7Kevin E Martin}
20845d6ddbca26d695561fb1d08d798a0cc254b805e7Kevin E Martin
2085d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
2086d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Wait for VBLANK.
2087d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
2088d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
2089d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param vbl pointer to a drmVBlank structure.
2090d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
2091d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success, or a negative value on failure.
2092d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
2093d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
2094d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_WAIT_VBLANK ioctl.
2095d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
209655acd0d5a64a2ee6b0cecc75872fbf8c4bb42a0cMichel Daenzerint drmWaitVBlank(int fd, drmVBlankPtr vbl)
209755acd0d5a64a2ee6b0cecc75872fbf8c4bb42a0cMichel Daenzer{
2098f4f76a6894b40abd77f0ffbf52972127608b9bcaJesse Barnes    struct timespec timeout, cur;
209955acd0d5a64a2ee6b0cecc75872fbf8c4bb42a0cMichel Daenzer    int ret;
210055acd0d5a64a2ee6b0cecc75872fbf8c4bb42a0cMichel Daenzer
2101f4f76a6894b40abd77f0ffbf52972127608b9bcaJesse Barnes    ret = clock_gettime(CLOCK_MONOTONIC, &timeout);
2102f4f76a6894b40abd77f0ffbf52972127608b9bcaJesse Barnes    if (ret < 0) {
21031eb2860b4bd0306dddc5b2f2dc7403aa65c5e476Daniel Kurtz	fprintf(stderr, "clock_gettime failed: %s\n", strerror(errno));
2104f4f76a6894b40abd77f0ffbf52972127608b9bcaJesse Barnes	goto out;
2105f4f76a6894b40abd77f0ffbf52972127608b9bcaJesse Barnes    }
2106f4f76a6894b40abd77f0ffbf52972127608b9bcaJesse Barnes    timeout.tv_sec++;
2107f4f76a6894b40abd77f0ffbf52972127608b9bcaJesse Barnes
210855acd0d5a64a2ee6b0cecc75872fbf8c4bb42a0cMichel Daenzer    do {
2109f4f76a6894b40abd77f0ffbf52972127608b9bcaJesse Barnes       ret = ioctl(fd, DRM_IOCTL_WAIT_VBLANK, vbl);
2110c7d471b6ae936127311a816a8d15b4565746af48Michel Daenzer       vbl->request.type &= ~DRM_VBLANK_RELATIVE;
2111ca37077fb78b69a00500827f1db12b70affa1514Jesse Barnes       if (ret && errno == EINTR) {
2112ca37077fb78b69a00500827f1db12b70affa1514Jesse Barnes	       clock_gettime(CLOCK_MONOTONIC, &cur);
2113ca37077fb78b69a00500827f1db12b70affa1514Jesse Barnes	       /* Timeout after 1s */
2114ca37077fb78b69a00500827f1db12b70affa1514Jesse Barnes	       if (cur.tv_sec > timeout.tv_sec + 1 ||
2115ca37077fb78b69a00500827f1db12b70affa1514Jesse Barnes		   (cur.tv_sec == timeout.tv_sec && cur.tv_nsec >=
2116ca37077fb78b69a00500827f1db12b70affa1514Jesse Barnes		    timeout.tv_nsec)) {
2117ca37077fb78b69a00500827f1db12b70affa1514Jesse Barnes		       errno = EBUSY;
2118ca37077fb78b69a00500827f1db12b70affa1514Jesse Barnes		       ret = -1;
2119ca37077fb78b69a00500827f1db12b70affa1514Jesse Barnes		       break;
2120ca37077fb78b69a00500827f1db12b70affa1514Jesse Barnes	       }
2121f4f76a6894b40abd77f0ffbf52972127608b9bcaJesse Barnes       }
212255acd0d5a64a2ee6b0cecc75872fbf8c4bb42a0cMichel Daenzer    } while (ret && errno == EINTR);
212355acd0d5a64a2ee6b0cecc75872fbf8c4bb42a0cMichel Daenzer
2124f4f76a6894b40abd77f0ffbf52972127608b9bcaJesse Barnesout:
212555acd0d5a64a2ee6b0cecc75872fbf8c4bb42a0cMichel Daenzer    return ret;
212655acd0d5a64a2ee6b0cecc75872fbf8c4bb42a0cMichel Daenzer}
212755acd0d5a64a2ee6b0cecc75872fbf8c4bb42a0cMichel Daenzer
2128b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Straussint drmError(int err, const char *label)
2129b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
2130b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    switch (err) {
2131ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    case DRM_ERR_NO_DEVICE:
2132ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	fprintf(stderr, "%s: no device\n", label);
2133ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	break;
2134ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    case DRM_ERR_NO_ACCESS:
2135ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	fprintf(stderr, "%s: no access\n", label);
2136ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	break;
2137ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    case DRM_ERR_NOT_ROOT:
2138ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	fprintf(stderr, "%s: not root\n", label);
2139ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	break;
2140ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    case DRM_ERR_INVALID:
2141ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	fprintf(stderr, "%s: invalid args\n", label);
2142ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	break;
2143b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    default:
2144ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	if (err < 0)
2145ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	    err = -err;
2146b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	fprintf( stderr, "%s: error %d (%s)\n", label, err, strerror(err) );
2147b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	break;
2148b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    }
2149b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
2150b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return 1;
2151b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
2152b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
2153d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
2154d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Install IRQ handler.
2155d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
2156d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
2157d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param irq IRQ number.
2158d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
2159d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success, or a negative value on failure.
2160d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
2161d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
2162d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_CONTROL ioctl, passing the
2163d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * argument in a drm_control structure.
2164d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
2165b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Straussint drmCtlInstHandler(int fd, int irq)
2166b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
2167b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_control_t ctl;
2168b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
2169fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(ctl);
2170b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    ctl.func  = DRM_INST_HANDLER;
2171b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    ctl.irq   = irq;
21728b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_CONTROL, &ctl))
2173ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return -errno;
2174b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return 0;
2175b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
2176b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
2177d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
2178d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
2179d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Uninstall IRQ handler.
2180d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
2181d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
2182d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
2183d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success, or a negative value on failure.
2184d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
2185d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
2186d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_CONTROL ioctl, passing the
2187d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * argument in a drm_control structure.
2188d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
2189b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Straussint drmCtlUninstHandler(int fd)
2190b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
2191b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_control_t ctl;
2192b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
2193fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(ctl);
2194b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    ctl.func  = DRM_UNINST_HANDLER;
2195b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    ctl.irq   = 0;
21968b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_CONTROL, &ctl))
2197ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return -errno;
2198b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return 0;
2199b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
2200b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
2201b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Straussint drmFinish(int fd, int context, drmLockFlags flags)
2202b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
2203b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_lock_t lock;
2204b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
2205fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(lock);
2206b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    lock.context = context;
2207b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    if (flags & DRM_LOCK_READY)      lock.flags |= _DRM_LOCK_READY;
2208b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    if (flags & DRM_LOCK_QUIESCENT)  lock.flags |= _DRM_LOCK_QUIESCENT;
2209b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    if (flags & DRM_LOCK_FLUSH)      lock.flags |= _DRM_LOCK_FLUSH;
2210b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    if (flags & DRM_LOCK_FLUSH_ALL)  lock.flags |= _DRM_LOCK_FLUSH_ALL;
2211b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    if (flags & DRM_HALT_ALL_QUEUES) lock.flags |= _DRM_HALT_ALL_QUEUES;
2212b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    if (flags & DRM_HALT_CUR_QUEUES) lock.flags |= _DRM_HALT_CUR_QUEUES;
22138b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_FINISH, &lock))
2214ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return -errno;
2215b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return 0;
2216b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
2217b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
2218d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
2219d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Get IRQ from bus ID.
2220d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
2221d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
2222d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param busnum bus number.
2223d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param devnum device number.
2224d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param funcnum function number.
2225d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
2226d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return IRQ number on success, or a negative value on failure.
2227d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
2228d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
2229d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * This function is a wrapper around the DRM_IOCTL_IRQ_BUSID ioctl, passing the
2230d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * arguments in a drm_irq_busid structure.
2231d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
2232b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Straussint drmGetInterruptFromBusID(int fd, int busnum, int devnum, int funcnum)
2233b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
2234b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drm_irq_busid_t p;
2235b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
2236fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(p);
2237b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    p.busnum  = busnum;
2238b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    p.devnum  = devnum;
2239b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    p.funcnum = funcnum;
22408b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_IRQ_BUSID, &p))
2241ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return -errno;
2242b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return p.irq;
2243b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
2244b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
22458696e71db2d79eb318c00abde625d7b61d6800a1Jon Smirlint drmAddContextTag(int fd, drm_context_t context, void *tag)
2246b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
2247b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drmHashEntry  *entry = drmGetEntry(fd);
2248b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
2249b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    if (drmHashInsert(entry->tagTable, context, tag)) {
2250b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	drmHashDelete(entry->tagTable, context);
2251b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss	drmHashInsert(entry->tagTable, context, tag);
2252b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    }
2253b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return 0;
2254b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
2255b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
22568696e71db2d79eb318c00abde625d7b61d6800a1Jon Smirlint drmDelContextTag(int fd, drm_context_t context)
2257b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
2258b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drmHashEntry  *entry = drmGetEntry(fd);
2259b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
2260b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return drmHashDelete(entry->tagTable, context);
2261b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
2262b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
22638696e71db2d79eb318c00abde625d7b61d6800a1Jon Smirlvoid *drmGetContextTag(int fd, drm_context_t context)
2264b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss{
2265b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    drmHashEntry  *entry = drmGetEntry(fd);
2266b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    void          *value;
2267360475376c5a597caf4a981c934a6b0d783fa94dGareth Hughes
2268ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    if (drmHashLookup(entry->tagTable, context, &value))
2269ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return NULL;
2270b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
2271b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss    return value;
2272b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss}
2273b3a5766992019fc5f44cc9afd01b2617b76f47aDaryll Strauss
227422e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jacksonint drmAddContextPrivateMapping(int fd, drm_context_t ctx_id,
227522e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jackson                                drm_handle_t handle)
227674e19a40187ac3b5907922e5dc01418135a5794bKevin E Martin{
227774e19a40187ac3b5907922e5dc01418135a5794bKevin E Martin    drm_ctx_priv_map_t map;
227874e19a40187ac3b5907922e5dc01418135a5794bKevin E Martin
2279fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(map);
228074e19a40187ac3b5907922e5dc01418135a5794bKevin E Martin    map.ctx_id = ctx_id;
2281961bf9b5c2866ccb4fedf2b45b29fb688519d0dbJeremy Huddleston    map.handle = (void *)(uintptr_t)handle;
228274e19a40187ac3b5907922e5dc01418135a5794bKevin E Martin
22838b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_SET_SAREA_CTX, &map))
2284ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return -errno;
228574e19a40187ac3b5907922e5dc01418135a5794bKevin E Martin    return 0;
228674e19a40187ac3b5907922e5dc01418135a5794bKevin E Martin}
228774e19a40187ac3b5907922e5dc01418135a5794bKevin E Martin
228822e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jacksonint drmGetContextPrivateMapping(int fd, drm_context_t ctx_id,
228922e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jackson                                drm_handle_t *handle)
229074e19a40187ac3b5907922e5dc01418135a5794bKevin E Martin{
229174e19a40187ac3b5907922e5dc01418135a5794bKevin E Martin    drm_ctx_priv_map_t map;
229274e19a40187ac3b5907922e5dc01418135a5794bKevin E Martin
2293fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(map);
229474e19a40187ac3b5907922e5dc01418135a5794bKevin E Martin    map.ctx_id = ctx_id;
229574e19a40187ac3b5907922e5dc01418135a5794bKevin E Martin
22968b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_GET_SAREA_CTX, &map))
2297ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return -errno;
2298ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    if (handle)
2299961bf9b5c2866ccb4fedf2b45b29fb688519d0dbJeremy Huddleston	*handle = (drm_handle_t)(uintptr_t)map.handle;
230074e19a40187ac3b5907922e5dc01418135a5794bKevin E Martin
230174e19a40187ac3b5907922e5dc01418135a5794bKevin E Martin    return 0;
230274e19a40187ac3b5907922e5dc01418135a5794bKevin E Martin}
230374e19a40187ac3b5907922e5dc01418135a5794bKevin E Martin
23048696e71db2d79eb318c00abde625d7b61d6800a1Jon Smirlint drmGetMap(int fd, int idx, drm_handle_t *offset, drmSize *size,
23058696e71db2d79eb318c00abde625d7b61d6800a1Jon Smirl	      drmMapType *type, drmMapFlags *flags, drm_handle_t *handle,
230688dbee54ed400a3fd5594fab506518c171167805Rik Faith	      int *mtrr)
230788dbee54ed400a3fd5594fab506518c171167805Rik Faith{
230888dbee54ed400a3fd5594fab506518c171167805Rik Faith    drm_map_t map;
230988dbee54ed400a3fd5594fab506518c171167805Rik Faith
2310fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(map);
231188dbee54ed400a3fd5594fab506518c171167805Rik Faith    map.offset = idx;
23128b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_GET_MAP, &map))
2313ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return -errno;
231488dbee54ed400a3fd5594fab506518c171167805Rik Faith    *offset = map.offset;
231588dbee54ed400a3fd5594fab506518c171167805Rik Faith    *size   = map.size;
231688dbee54ed400a3fd5594fab506518c171167805Rik Faith    *type   = map.type;
231788dbee54ed400a3fd5594fab506518c171167805Rik Faith    *flags  = map.flags;
231888dbee54ed400a3fd5594fab506518c171167805Rik Faith    *handle = (unsigned long)map.handle;
231988dbee54ed400a3fd5594fab506518c171167805Rik Faith    *mtrr   = map.mtrr;
232088dbee54ed400a3fd5594fab506518c171167805Rik Faith    return 0;
232188dbee54ed400a3fd5594fab506518c171167805Rik Faith}
232288dbee54ed400a3fd5594fab506518c171167805Rik Faith
232388dbee54ed400a3fd5594fab506518c171167805Rik Faithint drmGetClient(int fd, int idx, int *auth, int *pid, int *uid,
232488dbee54ed400a3fd5594fab506518c171167805Rik Faith		 unsigned long *magic, unsigned long *iocs)
232588dbee54ed400a3fd5594fab506518c171167805Rik Faith{
232688dbee54ed400a3fd5594fab506518c171167805Rik Faith    drm_client_t client;
232788dbee54ed400a3fd5594fab506518c171167805Rik Faith
2328fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(client);
232988dbee54ed400a3fd5594fab506518c171167805Rik Faith    client.idx = idx;
23308b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_GET_CLIENT, &client))
2331ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return -errno;
233288dbee54ed400a3fd5594fab506518c171167805Rik Faith    *auth      = client.auth;
233388dbee54ed400a3fd5594fab506518c171167805Rik Faith    *pid       = client.pid;
233488dbee54ed400a3fd5594fab506518c171167805Rik Faith    *uid       = client.uid;
233588dbee54ed400a3fd5594fab506518c171167805Rik Faith    *magic     = client.magic;
233688dbee54ed400a3fd5594fab506518c171167805Rik Faith    *iocs      = client.iocs;
233788dbee54ed400a3fd5594fab506518c171167805Rik Faith    return 0;
233888dbee54ed400a3fd5594fab506518c171167805Rik Faith}
233988dbee54ed400a3fd5594fab506518c171167805Rik Faith
234088dbee54ed400a3fd5594fab506518c171167805Rik Faithint drmGetStats(int fd, drmStatsT *stats)
234188dbee54ed400a3fd5594fab506518c171167805Rik Faith{
234288dbee54ed400a3fd5594fab506518c171167805Rik Faith    drm_stats_t s;
2343de8532dd8359dfdaba839ff61fc9e2f05eaf57d3Jan Vesely    unsigned    i;
234488dbee54ed400a3fd5594fab506518c171167805Rik Faith
2345fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(s);
23468b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_GET_STATS, &s))
2347ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return -errno;
234888dbee54ed400a3fd5594fab506518c171167805Rik Faith
234988dbee54ed400a3fd5594fab506518c171167805Rik Faith    stats->count = 0;
235088dbee54ed400a3fd5594fab506518c171167805Rik Faith    memset(stats, 0, sizeof(*stats));
235188dbee54ed400a3fd5594fab506518c171167805Rik Faith    if (s.count > sizeof(stats->data)/sizeof(stats->data[0]))
235288dbee54ed400a3fd5594fab506518c171167805Rik Faith	return -1;
235388dbee54ed400a3fd5594fab506518c171167805Rik Faith
235488dbee54ed400a3fd5594fab506518c171167805Rik Faith#define SET_VALUE                              \
235588dbee54ed400a3fd5594fab506518c171167805Rik Faith    stats->data[i].long_format = "%-20.20s";   \
235688dbee54ed400a3fd5594fab506518c171167805Rik Faith    stats->data[i].rate_format = "%8.8s";      \
235788dbee54ed400a3fd5594fab506518c171167805Rik Faith    stats->data[i].isvalue     = 1;            \
235888dbee54ed400a3fd5594fab506518c171167805Rik Faith    stats->data[i].verbose     = 0
235988dbee54ed400a3fd5594fab506518c171167805Rik Faith
236088dbee54ed400a3fd5594fab506518c171167805Rik Faith#define SET_COUNT                              \
236188dbee54ed400a3fd5594fab506518c171167805Rik Faith    stats->data[i].long_format = "%-20.20s";   \
236288dbee54ed400a3fd5594fab506518c171167805Rik Faith    stats->data[i].rate_format = "%5.5s";      \
236388dbee54ed400a3fd5594fab506518c171167805Rik Faith    stats->data[i].isvalue     = 0;            \
236488dbee54ed400a3fd5594fab506518c171167805Rik Faith    stats->data[i].mult_names  = "kgm";        \
236588dbee54ed400a3fd5594fab506518c171167805Rik Faith    stats->data[i].mult        = 1000;         \
236688dbee54ed400a3fd5594fab506518c171167805Rik Faith    stats->data[i].verbose     = 0
236788dbee54ed400a3fd5594fab506518c171167805Rik Faith
236888dbee54ed400a3fd5594fab506518c171167805Rik Faith#define SET_BYTE                               \
236988dbee54ed400a3fd5594fab506518c171167805Rik Faith    stats->data[i].long_format = "%-20.20s";   \
237088dbee54ed400a3fd5594fab506518c171167805Rik Faith    stats->data[i].rate_format = "%5.5s";      \
237188dbee54ed400a3fd5594fab506518c171167805Rik Faith    stats->data[i].isvalue     = 0;            \
237288dbee54ed400a3fd5594fab506518c171167805Rik Faith    stats->data[i].mult_names  = "KGM";        \
237388dbee54ed400a3fd5594fab506518c171167805Rik Faith    stats->data[i].mult        = 1024;         \
237488dbee54ed400a3fd5594fab506518c171167805Rik Faith    stats->data[i].verbose     = 0
237588dbee54ed400a3fd5594fab506518c171167805Rik Faith
237688dbee54ed400a3fd5594fab506518c171167805Rik Faith
237788dbee54ed400a3fd5594fab506518c171167805Rik Faith    stats->count = s.count;
237888dbee54ed400a3fd5594fab506518c171167805Rik Faith    for (i = 0; i < s.count; i++) {
237988dbee54ed400a3fd5594fab506518c171167805Rik Faith	stats->data[i].value = s.data[i].value;
238088dbee54ed400a3fd5594fab506518c171167805Rik Faith	switch (s.data[i].type) {
238188dbee54ed400a3fd5594fab506518c171167805Rik Faith	case _DRM_STAT_LOCK:
238288dbee54ed400a3fd5594fab506518c171167805Rik Faith	    stats->data[i].long_name = "Lock";
238388dbee54ed400a3fd5594fab506518c171167805Rik Faith	    stats->data[i].rate_name = "Lock";
238488dbee54ed400a3fd5594fab506518c171167805Rik Faith	    SET_VALUE;
238588dbee54ed400a3fd5594fab506518c171167805Rik Faith	    break;
238688dbee54ed400a3fd5594fab506518c171167805Rik Faith	case _DRM_STAT_OPENS:
238788dbee54ed400a3fd5594fab506518c171167805Rik Faith	    stats->data[i].long_name = "Opens";
238888dbee54ed400a3fd5594fab506518c171167805Rik Faith	    stats->data[i].rate_name = "O";
238988dbee54ed400a3fd5594fab506518c171167805Rik Faith	    SET_COUNT;
239088dbee54ed400a3fd5594fab506518c171167805Rik Faith	    stats->data[i].verbose   = 1;
239188dbee54ed400a3fd5594fab506518c171167805Rik Faith	    break;
239288dbee54ed400a3fd5594fab506518c171167805Rik Faith	case _DRM_STAT_CLOSES:
239388dbee54ed400a3fd5594fab506518c171167805Rik Faith	    stats->data[i].long_name = "Closes";
239488dbee54ed400a3fd5594fab506518c171167805Rik Faith	    stats->data[i].rate_name = "Lock";
239588dbee54ed400a3fd5594fab506518c171167805Rik Faith	    SET_COUNT;
239688dbee54ed400a3fd5594fab506518c171167805Rik Faith	    stats->data[i].verbose   = 1;
239788dbee54ed400a3fd5594fab506518c171167805Rik Faith	    break;
239888dbee54ed400a3fd5594fab506518c171167805Rik Faith	case _DRM_STAT_IOCTLS:
239988dbee54ed400a3fd5594fab506518c171167805Rik Faith	    stats->data[i].long_name = "Ioctls";
240088dbee54ed400a3fd5594fab506518c171167805Rik Faith	    stats->data[i].rate_name = "Ioc/s";
240188dbee54ed400a3fd5594fab506518c171167805Rik Faith	    SET_COUNT;
240288dbee54ed400a3fd5594fab506518c171167805Rik Faith	    break;
240388dbee54ed400a3fd5594fab506518c171167805Rik Faith	case _DRM_STAT_LOCKS:
240488dbee54ed400a3fd5594fab506518c171167805Rik Faith	    stats->data[i].long_name = "Locks";
240588dbee54ed400a3fd5594fab506518c171167805Rik Faith	    stats->data[i].rate_name = "Lck/s";
240688dbee54ed400a3fd5594fab506518c171167805Rik Faith	    SET_COUNT;
240788dbee54ed400a3fd5594fab506518c171167805Rik Faith	    break;
240888dbee54ed400a3fd5594fab506518c171167805Rik Faith	case _DRM_STAT_UNLOCKS:
240988dbee54ed400a3fd5594fab506518c171167805Rik Faith	    stats->data[i].long_name = "Unlocks";
241088dbee54ed400a3fd5594fab506518c171167805Rik Faith	    stats->data[i].rate_name = "Unl/s";
241188dbee54ed400a3fd5594fab506518c171167805Rik Faith	    SET_COUNT;
241288dbee54ed400a3fd5594fab506518c171167805Rik Faith	    break;
241388dbee54ed400a3fd5594fab506518c171167805Rik Faith	case _DRM_STAT_IRQ:
241488dbee54ed400a3fd5594fab506518c171167805Rik Faith	    stats->data[i].long_name = "IRQs";
241588dbee54ed400a3fd5594fab506518c171167805Rik Faith	    stats->data[i].rate_name = "IRQ/s";
241688dbee54ed400a3fd5594fab506518c171167805Rik Faith	    SET_COUNT;
241788dbee54ed400a3fd5594fab506518c171167805Rik Faith	    break;
241888dbee54ed400a3fd5594fab506518c171167805Rik Faith	case _DRM_STAT_PRIMARY:
241988dbee54ed400a3fd5594fab506518c171167805Rik Faith	    stats->data[i].long_name = "Primary Bytes";
242088dbee54ed400a3fd5594fab506518c171167805Rik Faith	    stats->data[i].rate_name = "PB/s";
242188dbee54ed400a3fd5594fab506518c171167805Rik Faith	    SET_BYTE;
242288dbee54ed400a3fd5594fab506518c171167805Rik Faith	    break;
242388dbee54ed400a3fd5594fab506518c171167805Rik Faith	case _DRM_STAT_SECONDARY:
242488dbee54ed400a3fd5594fab506518c171167805Rik Faith	    stats->data[i].long_name = "Secondary Bytes";
242588dbee54ed400a3fd5594fab506518c171167805Rik Faith	    stats->data[i].rate_name = "SB/s";
242688dbee54ed400a3fd5594fab506518c171167805Rik Faith	    SET_BYTE;
242788dbee54ed400a3fd5594fab506518c171167805Rik Faith	    break;
242888dbee54ed400a3fd5594fab506518c171167805Rik Faith	case _DRM_STAT_DMA:
242988dbee54ed400a3fd5594fab506518c171167805Rik Faith	    stats->data[i].long_name = "DMA";
243088dbee54ed400a3fd5594fab506518c171167805Rik Faith	    stats->data[i].rate_name = "DMA/s";
243188dbee54ed400a3fd5594fab506518c171167805Rik Faith	    SET_COUNT;
243288dbee54ed400a3fd5594fab506518c171167805Rik Faith	    break;
243388dbee54ed400a3fd5594fab506518c171167805Rik Faith	case _DRM_STAT_SPECIAL:
243488dbee54ed400a3fd5594fab506518c171167805Rik Faith	    stats->data[i].long_name = "Special DMA";
243588dbee54ed400a3fd5594fab506518c171167805Rik Faith	    stats->data[i].rate_name = "dma/s";
243688dbee54ed400a3fd5594fab506518c171167805Rik Faith	    SET_COUNT;
243788dbee54ed400a3fd5594fab506518c171167805Rik Faith	    break;
243888dbee54ed400a3fd5594fab506518c171167805Rik Faith	case _DRM_STAT_MISSED:
243988dbee54ed400a3fd5594fab506518c171167805Rik Faith	    stats->data[i].long_name = "Miss";
244088dbee54ed400a3fd5594fab506518c171167805Rik Faith	    stats->data[i].rate_name = "Ms/s";
244188dbee54ed400a3fd5594fab506518c171167805Rik Faith	    SET_COUNT;
244288dbee54ed400a3fd5594fab506518c171167805Rik Faith	    break;
244388dbee54ed400a3fd5594fab506518c171167805Rik Faith	case _DRM_STAT_VALUE:
244488dbee54ed400a3fd5594fab506518c171167805Rik Faith	    stats->data[i].long_name = "Value";
244588dbee54ed400a3fd5594fab506518c171167805Rik Faith	    stats->data[i].rate_name = "Value";
244688dbee54ed400a3fd5594fab506518c171167805Rik Faith	    SET_VALUE;
244788dbee54ed400a3fd5594fab506518c171167805Rik Faith	    break;
244888dbee54ed400a3fd5594fab506518c171167805Rik Faith	case _DRM_STAT_BYTE:
244988dbee54ed400a3fd5594fab506518c171167805Rik Faith	    stats->data[i].long_name = "Bytes";
245088dbee54ed400a3fd5594fab506518c171167805Rik Faith	    stats->data[i].rate_name = "B/s";
245188dbee54ed400a3fd5594fab506518c171167805Rik Faith	    SET_BYTE;
245288dbee54ed400a3fd5594fab506518c171167805Rik Faith	    break;
245388dbee54ed400a3fd5594fab506518c171167805Rik Faith	case _DRM_STAT_COUNT:
245488dbee54ed400a3fd5594fab506518c171167805Rik Faith	default:
245588dbee54ed400a3fd5594fab506518c171167805Rik Faith	    stats->data[i].long_name = "Count";
245688dbee54ed400a3fd5594fab506518c171167805Rik Faith	    stats->data[i].rate_name = "Cnt/s";
245788dbee54ed400a3fd5594fab506518c171167805Rik Faith	    SET_COUNT;
245888dbee54ed400a3fd5594fab506518c171167805Rik Faith	    break;
245988dbee54ed400a3fd5594fab506518c171167805Rik Faith	}
246088dbee54ed400a3fd5594fab506518c171167805Rik Faith    }
246188dbee54ed400a3fd5594fab506518c171167805Rik Faith    return 0;
246288dbee54ed400a3fd5594fab506518c171167805Rik Faith}
246388dbee54ed400a3fd5594fab506518c171167805Rik Faith
2464d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
246506cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt * Issue a set-version ioctl.
246606cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt *
246706cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt * \param fd file descriptor.
246806cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt * \param drmCommandIndex command index
246906cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt * \param data source pointer of the data to be read and written.
247006cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt * \param size size of the data to be read and written.
247106cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt *
247206cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt * \return zero on success, or a negative value on failure.
247306cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt *
247406cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt * \internal
247506cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt * It issues a read-write ioctl given by
247606cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
247706cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt */
247822e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jacksonint drmSetInterfaceVersion(int fd, drmSetVersion *version)
247906cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt{
248006cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    int retcode = 0;
248106cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    drm_set_version_t sv;
248206cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt
2483fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    memclear(sv);
248406cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    sv.drm_di_major = version->drm_di_major;
248506cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    sv.drm_di_minor = version->drm_di_minor;
248606cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    sv.drm_dd_major = version->drm_dd_major;
248706cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    sv.drm_dd_minor = version->drm_dd_minor;
248806cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt
24898b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, DRM_IOCTL_SET_VERSION, &sv)) {
249006cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt	retcode = -errno;
249106cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    }
249206cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt
249306cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    version->drm_di_major = sv.drm_di_major;
249406cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    version->drm_di_minor = sv.drm_di_minor;
249506cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    version->drm_dd_major = sv.drm_dd_major;
249606cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    version->drm_dd_minor = sv.drm_dd_minor;
249706cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt
249806cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt    return retcode;
249906cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt}
250006cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt
250106cb132e86dc4a04044c3c76725ba3037008ab34Eric Anholt/**
2502d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Send a device-specific command.
2503d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
2504d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
2505d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param drmCommandIndex command index
2506d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
2507d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success, or a negative value on failure.
2508d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
2509d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
2510d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * It issues a ioctl given by
2511d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
2512d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
25133903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owenint drmCommandNone(int fd, unsigned long drmCommandIndex)
25143903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen{
25153903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen    unsigned long request;
25163903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen
25173903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen    request = DRM_IO( DRM_COMMAND_BASE + drmCommandIndex);
25183903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen
2519fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter    if (drmIoctl(fd, request, NULL)) {
25203903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen	return -errno;
25213903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen    }
25223903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen    return 0;
25233903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen}
25243903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen
2525d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
2526d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
2527d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Send a device-specific read command.
2528d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
2529d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
2530d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param drmCommandIndex command index
2531d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param data destination pointer of the data to be read.
2532d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param size size of the data to be read.
2533d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
2534d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success, or a negative value on failure.
2535d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
2536d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
2537d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * It issues a read ioctl given by
2538d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
2539d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
254022e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jacksonint drmCommandRead(int fd, unsigned long drmCommandIndex, void *data,
254122e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jackson                   unsigned long size)
25423903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen{
25433903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen    unsigned long request;
25443903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen
254574ef13fd009b9e37956e4207d0a5ed92f4b5e39aAlan Hourihane    request = DRM_IOC( DRM_IOC_READ, DRM_IOCTL_BASE,
254674ef13fd009b9e37956e4207d0a5ed92f4b5e39aAlan Hourihane	DRM_COMMAND_BASE + drmCommandIndex, size);
25473903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen
25488b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, request, data)) {
25493903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen	return -errno;
25503903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen    }
25513903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen    return 0;
25523903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen}
25533903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen
2554d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
2555d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
2556d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Send a device-specific write command.
2557d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
2558d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
2559d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param drmCommandIndex command index
2560d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param data source pointer of the data to be written.
2561d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param size size of the data to be written.
2562d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
2563d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success, or a negative value on failure.
2564d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
2565d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
2566d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * It issues a write ioctl given by
2567d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
2568d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
256922e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jacksonint drmCommandWrite(int fd, unsigned long drmCommandIndex, void *data,
257022e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jackson                    unsigned long size)
25713903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen{
25723903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen    unsigned long request;
25733903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen
257474ef13fd009b9e37956e4207d0a5ed92f4b5e39aAlan Hourihane    request = DRM_IOC( DRM_IOC_WRITE, DRM_IOCTL_BASE,
257574ef13fd009b9e37956e4207d0a5ed92f4b5e39aAlan Hourihane	DRM_COMMAND_BASE + drmCommandIndex, size);
25763903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen
25778b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, request, data)) {
25783903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen	return -errno;
25793903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen    }
25803903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen    return 0;
25813903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen}
25823903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen
2583d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca
2584d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca/**
2585d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * Send a device-specific read-write command.
2586d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
2587d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param fd file descriptor.
2588d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param drmCommandIndex command index
2589d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param data source pointer of the data to be read and written.
2590d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \param size size of the data to be read and written.
2591d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
2592d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \return zero on success, or a negative value on failure.
2593d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca *
2594d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \internal
2595d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * It issues a read-write ioctl given by
2596d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
2597d2443b2186712dd7c977b47e06444396e1e493ffJose Fonseca */
259822e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jacksonint drmCommandWriteRead(int fd, unsigned long drmCommandIndex, void *data,
259922e41ef08338ae6dd59acbe6d4d8e50d83672816Adam Jackson                        unsigned long size)
26003903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen{
26013903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen    unsigned long request;
26023903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen
260374ef13fd009b9e37956e4207d0a5ed92f4b5e39aAlan Hourihane    request = DRM_IOC( DRM_IOC_READ|DRM_IOC_WRITE, DRM_IOCTL_BASE,
260474ef13fd009b9e37956e4207d0a5ed92f4b5e39aAlan Hourihane	DRM_COMMAND_BASE + drmCommandIndex, size);
26053903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen
26068b9ab108ec1f2ba2b503f713769c4946849b3cb2Keith Packard    if (drmIoctl(fd, request, data))
26073903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen	return -errno;
26083903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen    return 0;
26093903e5ac94c07cf31f0bc24eff5011ef8cc7afbaJens Owen}
2610166da9355d95affe427a6cff3525df60e80a99dfThomas Hellstrom
2611d51e1bb56ca2f7858cdeac6f61a7b747c1e15b1eDave Airlie#define DRM_MAX_FDS 16
2612d51e1bb56ca2f7858cdeac6f61a7b747c1e15b1eDave Airliestatic struct {
2613ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    char *BusID;
2614ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    int fd;
2615ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    int refcount;
2616dbc8b11db6f3fcbe2a76487bb0b1930908226a17Jammy Zhou    int type;
2617d51e1bb56ca2f7858cdeac6f61a7b747c1e15b1eDave Airlie} connection[DRM_MAX_FDS];
2618d51e1bb56ca2f7858cdeac6f61a7b747c1e15b1eDave Airlie
2619d51e1bb56ca2f7858cdeac6f61a7b747c1e15b1eDave Airliestatic int nr_fds = 0;
2620d51e1bb56ca2f7858cdeac6f61a7b747c1e15b1eDave Airlie
2621d51e1bb56ca2f7858cdeac6f61a7b747c1e15b1eDave Airlieint drmOpenOnce(void *unused,
2622d51e1bb56ca2f7858cdeac6f61a7b747c1e15b1eDave Airlie		const char *BusID,
2623d51e1bb56ca2f7858cdeac6f61a7b747c1e15b1eDave Airlie		int *newlyopened)
2624d51e1bb56ca2f7858cdeac6f61a7b747c1e15b1eDave Airlie{
2625dbc8b11db6f3fcbe2a76487bb0b1930908226a17Jammy Zhou    return drmOpenOnceWithType(BusID, newlyopened, DRM_NODE_PRIMARY);
2626dbc8b11db6f3fcbe2a76487bb0b1930908226a17Jammy Zhou}
2627dbc8b11db6f3fcbe2a76487bb0b1930908226a17Jammy Zhou
2628dbc8b11db6f3fcbe2a76487bb0b1930908226a17Jammy Zhouint drmOpenOnceWithType(const char *BusID, int *newlyopened, int type)
2629dbc8b11db6f3fcbe2a76487bb0b1930908226a17Jammy Zhou{
2630ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    int i;
2631ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    int fd;
2632d51e1bb56ca2f7858cdeac6f61a7b747c1e15b1eDave Airlie
2633ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    for (i = 0; i < nr_fds; i++)
2634dbc8b11db6f3fcbe2a76487bb0b1930908226a17Jammy Zhou	if ((strcmp(BusID, connection[i].BusID) == 0) &&
2635dbc8b11db6f3fcbe2a76487bb0b1930908226a17Jammy Zhou	    (connection[i].type == type)) {
2636ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	    connection[i].refcount++;
2637ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	    *newlyopened = 0;
2638ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	    return connection[i].fd;
2639ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	}
2640ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian
2641dbc8b11db6f3fcbe2a76487bb0b1930908226a17Jammy Zhou    fd = drmOpenWithType(NULL, BusID, type);
2642c1cd3d93881a9b4a27f7190393ccc7a0236d28a4Emil Velikov    if (fd < 0 || nr_fds == DRM_MAX_FDS)
2643ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	return fd;
2644d51e1bb56ca2f7858cdeac6f61a7b747c1e15b1eDave Airlie
2645ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    connection[nr_fds].BusID = strdup(BusID);
2646ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    connection[nr_fds].fd = fd;
2647ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    connection[nr_fds].refcount = 1;
2648dbc8b11db6f3fcbe2a76487bb0b1930908226a17Jammy Zhou    connection[nr_fds].type = type;
2649ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    *newlyopened = 1;
2650d51e1bb56ca2f7858cdeac6f61a7b747c1e15b1eDave Airlie
2651ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    if (0)
2652ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	fprintf(stderr, "saved connection %d for %s %d\n",
2653ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian		nr_fds, connection[nr_fds].BusID,
2654ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian		strcmp(BusID, connection[nr_fds].BusID));
2655d51e1bb56ca2f7858cdeac6f61a7b747c1e15b1eDave Airlie
2656ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    nr_fds++;
2657d51e1bb56ca2f7858cdeac6f61a7b747c1e15b1eDave Airlie
2658ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    return fd;
2659d51e1bb56ca2f7858cdeac6f61a7b747c1e15b1eDave Airlie}
2660d51e1bb56ca2f7858cdeac6f61a7b747c1e15b1eDave Airlie
2661d51e1bb56ca2f7858cdeac6f61a7b747c1e15b1eDave Airlievoid drmCloseOnce(int fd)
2662d51e1bb56ca2f7858cdeac6f61a7b747c1e15b1eDave Airlie{
2663ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    int i;
2664d51e1bb56ca2f7858cdeac6f61a7b747c1e15b1eDave Airlie
2665ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    for (i = 0; i < nr_fds; i++) {
2666ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	if (fd == connection[i].fd) {
2667ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	    if (--connection[i].refcount == 0) {
2668ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian		drmClose(connection[i].fd);
2669ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian		free(connection[i].BusID);
2670d51e1bb56ca2f7858cdeac6f61a7b747c1e15b1eDave Airlie
2671ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian		if (i < --nr_fds)
2672ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian		    connection[i] = connection[nr_fds];
2673d51e1bb56ca2f7858cdeac6f61a7b747c1e15b1eDave Airlie
2674ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian		return;
2675ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	    }
2676ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian	}
2677ccd7b6e8ddeac936518f626d2326ae439931b2bfBrian    }
2678d51e1bb56ca2f7858cdeac6f61a7b747c1e15b1eDave Airlie}
2679731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
2680731cd5526e5c732d51307b26e784f454a724a699Jesse Barnesint drmSetMaster(int fd)
2681731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes{
2682fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter	return drmIoctl(fd, DRM_IOCTL_SET_MASTER, NULL);
2683731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes}
2684731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
2685731cd5526e5c732d51307b26e784f454a724a699Jesse Barnesint drmDropMaster(int fd)
2686731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes{
2687fd38794344f7211f45cc213344d0f5b9f9f98dd8Daniel Vetter	return drmIoctl(fd, DRM_IOCTL_DROP_MASTER, NULL);
2688731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes}
268922d46669043d38fcd16efca773f5ed5693c0fb58Kristian Høgsberg
269022d46669043d38fcd16efca773f5ed5693c0fb58Kristian Høgsbergchar *drmGetDeviceNameFromFd(int fd)
269122d46669043d38fcd16efca773f5ed5693c0fb58Kristian Høgsberg{
269222d46669043d38fcd16efca773f5ed5693c0fb58Kristian Høgsberg	char name[128];
269322d46669043d38fcd16efca773f5ed5693c0fb58Kristian Høgsberg	struct stat sbuf;
269422d46669043d38fcd16efca773f5ed5693c0fb58Kristian Høgsberg	dev_t d;
269522d46669043d38fcd16efca773f5ed5693c0fb58Kristian Høgsberg	int i;
269622d46669043d38fcd16efca773f5ed5693c0fb58Kristian Høgsberg
269722d46669043d38fcd16efca773f5ed5693c0fb58Kristian Høgsberg	/* The whole drmOpen thing is a fiasco and we need to find a way
269822d46669043d38fcd16efca773f5ed5693c0fb58Kristian Høgsberg	 * back to just using open(2).  For now, however, lets just make
269922d46669043d38fcd16efca773f5ed5693c0fb58Kristian Høgsberg	 * things worse with even more ad hoc directory walking code to
270022d46669043d38fcd16efca773f5ed5693c0fb58Kristian Høgsberg	 * discover the device file name. */
270122d46669043d38fcd16efca773f5ed5693c0fb58Kristian Høgsberg
270222d46669043d38fcd16efca773f5ed5693c0fb58Kristian Høgsberg	fstat(fd, &sbuf);
270322d46669043d38fcd16efca773f5ed5693c0fb58Kristian Høgsberg	d = sbuf.st_rdev;
270422d46669043d38fcd16efca773f5ed5693c0fb58Kristian Høgsberg
270522d46669043d38fcd16efca773f5ed5693c0fb58Kristian Høgsberg	for (i = 0; i < DRM_MAX_MINOR; i++) {
270622d46669043d38fcd16efca773f5ed5693c0fb58Kristian Høgsberg		snprintf(name, sizeof name, DRM_DEV_NAME, DRM_DIR_NAME, i);
270722d46669043d38fcd16efca773f5ed5693c0fb58Kristian Høgsberg		if (stat(name, &sbuf) == 0 && sbuf.st_rdev == d)
270822d46669043d38fcd16efca773f5ed5693c0fb58Kristian Høgsberg			break;
270922d46669043d38fcd16efca773f5ed5693c0fb58Kristian Høgsberg	}
271022d46669043d38fcd16efca773f5ed5693c0fb58Kristian Høgsberg	if (i == DRM_MAX_MINOR)
271122d46669043d38fcd16efca773f5ed5693c0fb58Kristian Høgsberg		return NULL;
271222d46669043d38fcd16efca773f5ed5693c0fb58Kristian Høgsberg
27130a1ff35c70730160973715b82112cd97c62ac13eAdam Jackson	return strdup(name);
271422d46669043d38fcd16efca773f5ed5693c0fb58Kristian Høgsberg}
2715cc0a14575d9fd0aafe73cb4aa445eaf024436114Dave Airlie
27161f73578df32f895a678a41758f6c563f49484347Frank Binnsint drmGetNodeTypeFromFd(int fd)
27171f73578df32f895a678a41758f6c563f49484347Frank Binns{
27181f73578df32f895a678a41758f6c563f49484347Frank Binns	struct stat sbuf;
27191f73578df32f895a678a41758f6c563f49484347Frank Binns	int maj, min, type;
27201f73578df32f895a678a41758f6c563f49484347Frank Binns
27211f73578df32f895a678a41758f6c563f49484347Frank Binns	if (fstat(fd, &sbuf))
27221f73578df32f895a678a41758f6c563f49484347Frank Binns		return -1;
27231f73578df32f895a678a41758f6c563f49484347Frank Binns
27241f73578df32f895a678a41758f6c563f49484347Frank Binns	maj = major(sbuf.st_rdev);
27251f73578df32f895a678a41758f6c563f49484347Frank Binns	min = minor(sbuf.st_rdev);
27261f73578df32f895a678a41758f6c563f49484347Frank Binns
27271f73578df32f895a678a41758f6c563f49484347Frank Binns	if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode)) {
27281f73578df32f895a678a41758f6c563f49484347Frank Binns		errno = EINVAL;
27291f73578df32f895a678a41758f6c563f49484347Frank Binns		return -1;
27301f73578df32f895a678a41758f6c563f49484347Frank Binns	}
27311f73578df32f895a678a41758f6c563f49484347Frank Binns
27321f73578df32f895a678a41758f6c563f49484347Frank Binns	type = drmGetMinorType(min);
27331f73578df32f895a678a41758f6c563f49484347Frank Binns	if (type == -1)
27341f73578df32f895a678a41758f6c563f49484347Frank Binns		errno = ENODEV;
27351f73578df32f895a678a41758f6c563f49484347Frank Binns	return type;
27361f73578df32f895a678a41758f6c563f49484347Frank Binns}
27371f73578df32f895a678a41758f6c563f49484347Frank Binns
2738cc0a14575d9fd0aafe73cb4aa445eaf024436114Dave Airlieint drmPrimeHandleToFD(int fd, uint32_t handle, uint32_t flags, int *prime_fd)
2739cc0a14575d9fd0aafe73cb4aa445eaf024436114Dave Airlie{
2740cc0a14575d9fd0aafe73cb4aa445eaf024436114Dave Airlie	struct drm_prime_handle args;
2741cc0a14575d9fd0aafe73cb4aa445eaf024436114Dave Airlie	int ret;
2742cc0a14575d9fd0aafe73cb4aa445eaf024436114Dave Airlie
27434bca42fc504a2051964030daaa49b5ac49bb64d3Guillaume Desmottes	memclear(args);
27444bca42fc504a2051964030daaa49b5ac49bb64d3Guillaume Desmottes	args.fd = -1;
2745cc0a14575d9fd0aafe73cb4aa445eaf024436114Dave Airlie	args.handle = handle;
2746cc0a14575d9fd0aafe73cb4aa445eaf024436114Dave Airlie	args.flags = flags;
2747cc0a14575d9fd0aafe73cb4aa445eaf024436114Dave Airlie	ret = drmIoctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &args);
2748cc0a14575d9fd0aafe73cb4aa445eaf024436114Dave Airlie	if (ret)
2749cc0a14575d9fd0aafe73cb4aa445eaf024436114Dave Airlie		return ret;
2750cc0a14575d9fd0aafe73cb4aa445eaf024436114Dave Airlie
2751cc0a14575d9fd0aafe73cb4aa445eaf024436114Dave Airlie	*prime_fd = args.fd;
2752cc0a14575d9fd0aafe73cb4aa445eaf024436114Dave Airlie	return 0;
2753cc0a14575d9fd0aafe73cb4aa445eaf024436114Dave Airlie}
2754cc0a14575d9fd0aafe73cb4aa445eaf024436114Dave Airlie
2755cc0a14575d9fd0aafe73cb4aa445eaf024436114Dave Airlieint drmPrimeFDToHandle(int fd, int prime_fd, uint32_t *handle)
2756cc0a14575d9fd0aafe73cb4aa445eaf024436114Dave Airlie{
2757cc0a14575d9fd0aafe73cb4aa445eaf024436114Dave Airlie	struct drm_prime_handle args;
2758cc0a14575d9fd0aafe73cb4aa445eaf024436114Dave Airlie	int ret;
2759cc0a14575d9fd0aafe73cb4aa445eaf024436114Dave Airlie
27604bca42fc504a2051964030daaa49b5ac49bb64d3Guillaume Desmottes	memclear(args);
2761cc0a14575d9fd0aafe73cb4aa445eaf024436114Dave Airlie	args.fd = prime_fd;
2762cc0a14575d9fd0aafe73cb4aa445eaf024436114Dave Airlie	ret = drmIoctl(fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &args);
2763cc0a14575d9fd0aafe73cb4aa445eaf024436114Dave Airlie	if (ret)
2764cc0a14575d9fd0aafe73cb4aa445eaf024436114Dave Airlie		return ret;
2765cc0a14575d9fd0aafe73cb4aa445eaf024436114Dave Airlie
2766cc0a14575d9fd0aafe73cb4aa445eaf024436114Dave Airlie	*handle = args.handle;
2767cc0a14575d9fd0aafe73cb4aa445eaf024436114Dave Airlie	return 0;
2768cc0a14575d9fd0aafe73cb4aa445eaf024436114Dave Airlie}
2769cc0a14575d9fd0aafe73cb4aa445eaf024436114Dave Airlie
27700ca03a4087a550646de7f26b6b53a932e8546474Emil Velikovstatic char *drmGetMinorNameForFD(int fd, int type)
27710ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov{
27720ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov#ifdef __linux__
27730ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov	DIR *sysdir;
27740ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov	struct dirent *pent, *ent;
27750ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov	struct stat sbuf;
27760ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov	const char *name = drmGetMinorName(type);
27770ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov	int len;
27780ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov	char dev_name[64], buf[64];
27790ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov	long name_max;
27800ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov	int maj, min;
27810ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov
27820ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov	if (!name)
27830ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov		return NULL;
27840ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov
27850ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov	len = strlen(name);
27860ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov
27870ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov	if (fstat(fd, &sbuf))
27880ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov		return NULL;
27890ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov
27900ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov	maj = major(sbuf.st_rdev);
27910ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov	min = minor(sbuf.st_rdev);
27920ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov
27930ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov	if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode))
27940ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov		return NULL;
27950ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov
27960ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov	snprintf(buf, sizeof(buf), "/sys/dev/char/%d:%d/device/drm", maj, min);
27970ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov
27980ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov	sysdir = opendir(buf);
27990ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov	if (!sysdir)
28000ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov		return NULL;
28010ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov
28020ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov	name_max = fpathconf(dirfd(sysdir), _PC_NAME_MAX);
28030ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov	if (name_max == -1)
28040ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov		goto out_close_dir;
28050ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov
28060ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov	pent = malloc(offsetof(struct dirent, d_name) + name_max + 1);
28070ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov	if (pent == NULL)
28080ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov		 goto out_close_dir;
28090ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov
28100ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov	while (readdir_r(sysdir, pent, &ent) == 0 && ent != NULL) {
28110ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov		if (strncmp(ent->d_name, name, len) == 0) {
28125c42b5e36a4a02e579ec5dcdc3a95ce58538224cMathias Tillman			snprintf(dev_name, sizeof(dev_name), DRM_DIR_NAME "/%s",
28135c42b5e36a4a02e579ec5dcdc3a95ce58538224cMathias Tillman				 ent->d_name);
28145c42b5e36a4a02e579ec5dcdc3a95ce58538224cMathias Tillman
28150ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov			free(pent);
28160ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov			closedir(sysdir);
28170ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov
28180ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov			return strdup(dev_name);
28190ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov		}
28200ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov	}
28210ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov
28220ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov	free(pent);
28230ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov
28240ca03a4087a550646de7f26b6b53a932e8546474Emil Velikovout_close_dir:
28250ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov	closedir(sysdir);
28268415a00a3f2f5cb4827b58b86e974900d3892d29Emil Velikov#else
28278415a00a3f2f5cb4827b58b86e974900d3892d29Emil Velikov#warning "Missing implementation of drmGetMinorNameForFD"
28280ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov#endif
28290ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov	return NULL;
28300ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov}
28310ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov
28320ca03a4087a550646de7f26b6b53a932e8546474Emil Velikovchar *drmGetPrimaryDeviceNameFromFd(int fd)
28330ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov{
28340ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov	return drmGetMinorNameForFD(fd, DRM_NODE_PRIMARY);
28350ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov}
28360ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov
28370ca03a4087a550646de7f26b6b53a932e8546474Emil Velikovchar *drmGetRenderDeviceNameFromFd(int fd)
28380ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov{
28390ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov	return drmGetMinorNameForFD(fd, DRM_NODE_RENDER);
28400ca03a4087a550646de7f26b6b53a932e8546474Emil Velikov}
2841b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
2842a250fceaaa150363accaf3fb71a0e42bcecc40daEmil Velikovstatic int drmParseSubsystemType(int maj, int min)
2843b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov{
2844291b2bb92c5fc90101417b80bbdc6c994be5fff2Emil Velikov#ifdef __linux__
2845a250fceaaa150363accaf3fb71a0e42bcecc40daEmil Velikov    char path[PATH_MAX + 1];
2846b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    char link[PATH_MAX + 1] = "";
2847b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    char *name;
2848b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
2849a250fceaaa150363accaf3fb71a0e42bcecc40daEmil Velikov    snprintf(path, PATH_MAX, "/sys/dev/char/%d:%d/device/subsystem",
2850a250fceaaa150363accaf3fb71a0e42bcecc40daEmil Velikov             maj, min);
2851a250fceaaa150363accaf3fb71a0e42bcecc40daEmil Velikov
2852a250fceaaa150363accaf3fb71a0e42bcecc40daEmil Velikov    if (readlink(path, link, PATH_MAX) < 0)
2853a250fceaaa150363accaf3fb71a0e42bcecc40daEmil Velikov        return -errno;
2854b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
2855b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    name = strrchr(link, '/');
2856b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    if (!name)
2857b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        return -EINVAL;
2858b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
2859a250fceaaa150363accaf3fb71a0e42bcecc40daEmil Velikov    if (strncmp(name, "/pci", 4) == 0)
2860b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        return DRM_BUS_PCI;
2861b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
2862b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    return -EINVAL;
2863291b2bb92c5fc90101417b80bbdc6c994be5fff2Emil Velikov#else
2864291b2bb92c5fc90101417b80bbdc6c994be5fff2Emil Velikov#warning "Missing implementation of drmParseSubsystemType"
2865291b2bb92c5fc90101417b80bbdc6c994be5fff2Emil Velikov    return -EINVAL;
2866291b2bb92c5fc90101417b80bbdc6c994be5fff2Emil Velikov#endif
2867b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov}
2868b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
2869536e0deba3829e194aafda6d9a1d9e938ba8277aEmil Velikovstatic int drmParsePciBusInfo(int maj, int min, drmPciBusInfoPtr info)
2870b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov{
2871291b2bb92c5fc90101417b80bbdc6c994be5fff2Emil Velikov#ifdef __linux__
2872536e0deba3829e194aafda6d9a1d9e938ba8277aEmil Velikov    char path[PATH_MAX + 1];
2873536e0deba3829e194aafda6d9a1d9e938ba8277aEmil Velikov    char data[128];
2874536e0deba3829e194aafda6d9a1d9e938ba8277aEmil Velikov    char *str;
2875b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    int domain, bus, dev, func;
2876536e0deba3829e194aafda6d9a1d9e938ba8277aEmil Velikov    int fd, ret;
2877b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
2878536e0deba3829e194aafda6d9a1d9e938ba8277aEmil Velikov    snprintf(path, PATH_MAX, "/sys/dev/char/%d:%d/device/uevent", maj, min);
2879536e0deba3829e194aafda6d9a1d9e938ba8277aEmil Velikov    fd = open(path, O_RDONLY);
2880536e0deba3829e194aafda6d9a1d9e938ba8277aEmil Velikov    if (fd < 0)
2881536e0deba3829e194aafda6d9a1d9e938ba8277aEmil Velikov        return -errno;
2882b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
2883536e0deba3829e194aafda6d9a1d9e938ba8277aEmil Velikov    ret = read(fd, data, sizeof(data));
2884536e0deba3829e194aafda6d9a1d9e938ba8277aEmil Velikov    close(fd);
2885536e0deba3829e194aafda6d9a1d9e938ba8277aEmil Velikov    if (ret < 0)
2886536e0deba3829e194aafda6d9a1d9e938ba8277aEmil Velikov        return -errno;
2887b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
2888536e0deba3829e194aafda6d9a1d9e938ba8277aEmil Velikov#define TAG "PCI_SLOT_NAME="
2889536e0deba3829e194aafda6d9a1d9e938ba8277aEmil Velikov    str = strstr(data, TAG);
2890536e0deba3829e194aafda6d9a1d9e938ba8277aEmil Velikov    if (str == NULL)
2891536e0deba3829e194aafda6d9a1d9e938ba8277aEmil Velikov        return -EINVAL;
2892b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
2893536e0deba3829e194aafda6d9a1d9e938ba8277aEmil Velikov    if (sscanf(str, TAG "%04x:%02x:%02x.%1u",
2894b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov               &domain, &bus, &dev, &func) != 4)
2895b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        return -EINVAL;
2896536e0deba3829e194aafda6d9a1d9e938ba8277aEmil Velikov#undef TAG
2897b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
2898b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    info->domain = domain;
2899b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    info->bus = bus;
2900b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    info->dev = dev;
2901b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    info->func = func;
2902b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
2903b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    return 0;
2904291b2bb92c5fc90101417b80bbdc6c994be5fff2Emil Velikov#else
2905291b2bb92c5fc90101417b80bbdc6c994be5fff2Emil Velikov#warning "Missing implementation of drmParsePciBusInfo"
2906291b2bb92c5fc90101417b80bbdc6c994be5fff2Emil Velikov    return -EINVAL;
2907291b2bb92c5fc90101417b80bbdc6c994be5fff2Emil Velikov#endif
2908b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov}
2909b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
2910bc2aca9e22bf2cc82874f3e44568c684eec9c5e1Emil Velikovstatic int drmCompareBusInfo(drmDevicePtr a, drmDevicePtr b)
2911b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov{
2912bc2aca9e22bf2cc82874f3e44568c684eec9c5e1Emil Velikov    if (a == NULL || b == NULL)
2913bc2aca9e22bf2cc82874f3e44568c684eec9c5e1Emil Velikov        return -1;
2914bc2aca9e22bf2cc82874f3e44568c684eec9c5e1Emil Velikov
2915b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    if (a->bustype != b->bustype)
2916bc2aca9e22bf2cc82874f3e44568c684eec9c5e1Emil Velikov        return -1;
2917b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
2918b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    switch (a->bustype) {
2919b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    case DRM_BUS_PCI:
2920bc2aca9e22bf2cc82874f3e44568c684eec9c5e1Emil Velikov        return memcmp(a->businfo.pci, b->businfo.pci, sizeof(drmPciBusInfo));
2921b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    default:
2922b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        break;
2923b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    }
2924b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
2925bc2aca9e22bf2cc82874f3e44568c684eec9c5e1Emil Velikov    return -1;
2926b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov}
2927b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
2928b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikovstatic int drmGetNodeType(const char *name)
2929b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov{
2930b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    if (strncmp(name, DRM_PRIMARY_MINOR_NAME,
2931b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        sizeof(DRM_PRIMARY_MINOR_NAME) - 1) == 0)
2932b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        return DRM_NODE_PRIMARY;
2933b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
2934b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    if (strncmp(name, DRM_CONTROL_MINOR_NAME,
2935b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        sizeof(DRM_CONTROL_MINOR_NAME ) - 1) == 0)
2936b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        return DRM_NODE_CONTROL;
2937b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
2938b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    if (strncmp(name, DRM_RENDER_MINOR_NAME,
2939b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        sizeof(DRM_RENDER_MINOR_NAME) - 1) == 0)
2940b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        return DRM_NODE_RENDER;
2941b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
2942b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    return -EINVAL;
2943b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov}
2944b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
29455f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikovstatic int drmGetMaxNodeName(void)
29465f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov{
29475f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    return sizeof(DRM_DIR_NAME) +
29485f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov           MAX3(sizeof(DRM_PRIMARY_MINOR_NAME),
29495f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov                sizeof(DRM_CONTROL_MINOR_NAME),
29505f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov                sizeof(DRM_RENDER_MINOR_NAME)) +
29515f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov           3 /* lenght of the node number */;
29525f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov}
29535f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov
2954ef5192e9c7897c82da815a2c893b2e2562997a3aEmil Velikovstatic int drmParsePciDeviceInfo(const char *d_name,
2955b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov                                 drmPciDeviceInfoPtr device)
2956b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov{
2957291b2bb92c5fc90101417b80bbdc6c994be5fff2Emil Velikov#ifdef __linux__
2958ef5192e9c7897c82da815a2c893b2e2562997a3aEmil Velikov    char path[PATH_MAX + 1];
2959ef5192e9c7897c82da815a2c893b2e2562997a3aEmil Velikov    unsigned char config[64];
2960ef5192e9c7897c82da815a2c893b2e2562997a3aEmil Velikov    int fd, ret;
2961ef5192e9c7897c82da815a2c893b2e2562997a3aEmil Velikov
2962ef5192e9c7897c82da815a2c893b2e2562997a3aEmil Velikov    snprintf(path, PATH_MAX, "/sys/class/drm/%s/device/config", d_name);
2963ef5192e9c7897c82da815a2c893b2e2562997a3aEmil Velikov    fd = open(path, O_RDONLY);
2964ef5192e9c7897c82da815a2c893b2e2562997a3aEmil Velikov    if (fd < 0)
2965ef5192e9c7897c82da815a2c893b2e2562997a3aEmil Velikov        return -errno;
2966ef5192e9c7897c82da815a2c893b2e2562997a3aEmil Velikov
2967ef5192e9c7897c82da815a2c893b2e2562997a3aEmil Velikov    ret = read(fd, config, sizeof(config));
2968ef5192e9c7897c82da815a2c893b2e2562997a3aEmil Velikov    close(fd);
2969ef5192e9c7897c82da815a2c893b2e2562997a3aEmil Velikov    if (ret < 0)
2970ef5192e9c7897c82da815a2c893b2e2562997a3aEmil Velikov        return -errno;
2971b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
2972b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    device->vendor_id = config[0] | (config[1] << 8);
2973b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    device->device_id = config[2] | (config[3] << 8);
2974b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    device->revision_id = config[8];
2975b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    device->subvendor_id = config[44] | (config[45] << 8);
2976b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    device->subdevice_id = config[46] | (config[47] << 8);
2977b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
2978b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    return 0;
2979291b2bb92c5fc90101417b80bbdc6c994be5fff2Emil Velikov#else
2980291b2bb92c5fc90101417b80bbdc6c994be5fff2Emil Velikov#warning "Missing implementation of drmParsePciDeviceInfo"
2981291b2bb92c5fc90101417b80bbdc6c994be5fff2Emil Velikov    return -EINVAL;
2982291b2bb92c5fc90101417b80bbdc6c994be5fff2Emil Velikov#endif
2983b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov}
2984b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
2985ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikovvoid drmFreeDevice(drmDevicePtr *device)
2986b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov{
2987b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    if (device == NULL)
2988b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        return;
2989b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
29905f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    free(*device);
29915f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    *device = NULL;
2992b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov}
2993b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
2994b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikovvoid drmFreeDevices(drmDevicePtr devices[], int count)
2995b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov{
2996b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    int i;
2997b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
2998b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    if (devices == NULL)
2999b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        return;
3000b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
30015f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    for (i = 0; i < count && devices[i] != NULL; i++)
30025f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov        drmFreeDevice(&devices[i]);
3003b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov}
3004b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
3005fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikovstatic int drmProcessPciDevice(drmDevicePtr *device, const char *d_name,
3006fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov                               const char *node, int node_type,
3007fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov                               int maj, int min, bool fetch_deviceinfo)
3008fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov{
3009fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    const int max_node_str = drmGetMaxNodeName();
3010fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    int ret, i;
3011fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    void *addr;
3012fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov
3013fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    addr = *device = calloc(1, sizeof(drmDevice) +
3014fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov                               (DRM_NODE_MAX *
3015fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov                                (sizeof(void *) + max_node_str)) +
3016fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov                               sizeof(drmPciBusInfo) +
3017fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov                               sizeof(drmPciDeviceInfo));
3018fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    if (!*device)
3019fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov        return -ENOMEM;
3020fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov
3021fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    (*device)->bustype = DRM_BUS_PCI;
3022fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    (*device)->available_nodes = 1 << node_type;
3023fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov
3024fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    addr += sizeof(drmDevice);
3025fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    (*device)->nodes = addr;
3026fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov
3027fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    addr += DRM_NODE_MAX * sizeof(void *);
3028fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    for (i = 0; i < DRM_NODE_MAX; i++) {
3029fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov        (*device)->nodes[i] = addr;
3030fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov        addr += max_node_str;
3031fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    }
3032fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    memcpy((*device)->nodes[node_type], node, max_node_str);
3033fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov
3034fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    (*device)->businfo.pci = addr;
3035fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov
3036fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    ret = drmParsePciBusInfo(maj, min, (*device)->businfo.pci);
3037fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    if (ret)
3038fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov        goto free_device;
3039fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov
3040fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    // Fetch the device info if the user has requested it
3041fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    if (fetch_deviceinfo) {
3042fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov        addr += sizeof(drmPciBusInfo);
3043fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov        (*device)->deviceinfo.pci = addr;
3044fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov
3045fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov        ret = drmParsePciDeviceInfo(d_name, (*device)->deviceinfo.pci);
3046fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov        if (ret)
3047fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov            goto free_device;
3048fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    }
3049fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    return 0;
3050fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov
3051fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikovfree_device:
3052fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    free(*device);
3053fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    *device = NULL;
3054fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    return ret;
3055fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov}
3056fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov
3057fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikovstatic void drmFoldDuplicatedDevices(drmDevicePtr local_devices[], int count)
3058fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov{
3059fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    int node_type, i, j;
3060fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov
3061fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    for (i = 0; i < count; i++) {
3062fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov        for (j = i + 1; j < count; j++) {
3063fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov            if (drmCompareBusInfo(local_devices[i], local_devices[j]) == 0) {
3064fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov                local_devices[i]->available_nodes |= local_devices[j]->available_nodes;
3065fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov                node_type = log2(local_devices[j]->available_nodes);
3066fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov                memcpy(local_devices[i]->nodes[node_type],
3067fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov                       local_devices[j]->nodes[node_type], drmGetMaxNodeName());
3068fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov                drmFreeDevice(&local_devices[j]);
3069fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov            }
3070fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov        }
3071fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    }
3072fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov}
3073fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov
3074b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov/**
3075ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov * Get information about the opened drm device
3076ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov *
3077ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov * \param fd file descriptor of the drm device
3078ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov * \param device the address of a drmDevicePtr where the information
3079ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov *               will be allocated in stored
3080ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov *
3081ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov * \return zero on success, negative error code otherwise.
3082ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov */
3083ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikovint drmGetDevice(int fd, drmDevicePtr *device)
3084ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov{
3085ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    drmDevicePtr *local_devices;
3086ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    drmDevicePtr d;
3087ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    DIR *sysdir;
3088ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    struct dirent *dent;
3089ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    struct stat sbuf;
3090ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    char node[PATH_MAX + 1];
3091ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    int node_type, subsystem_type;
3092ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    int maj, min;
3093ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    int ret, i, node_count;
3094ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    int max_count = 16;
3095ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3096ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    if (fd == -1 || device == NULL)
3097ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        return -EINVAL;
3098ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3099ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    if (fstat(fd, &sbuf))
3100ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        return -errno;
3101ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3102ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    maj = major(sbuf.st_rdev);
3103ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    min = minor(sbuf.st_rdev);
3104ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3105ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode))
3106ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        return -EINVAL;
3107ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3108ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    subsystem_type = drmParseSubsystemType(maj, min);
3109ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3110ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    local_devices = calloc(max_count, sizeof(drmDevicePtr));
3111ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    if (local_devices == NULL)
3112ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        return -ENOMEM;
3113ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3114ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    sysdir = opendir(DRM_DIR_NAME);
3115ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    if (!sysdir) {
3116ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        ret = -errno;
3117ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        goto close_sysdir;
3118ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    }
3119ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3120ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    i = 0;
3121ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    while ((dent = readdir(sysdir))) {
3122ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        node_type = drmGetNodeType(dent->d_name);
3123ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        if (node_type < 0)
3124ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov            continue;
3125ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3126ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        snprintf(node, PATH_MAX, "%s/%s", DRM_DIR_NAME, dent->d_name);
3127ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        if (stat(node, &sbuf))
3128ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov            continue;
3129ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3130ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        maj = major(sbuf.st_rdev);
3131ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        min = minor(sbuf.st_rdev);
3132ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3133ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode))
3134ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov            continue;
3135ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3136ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        if (drmParseSubsystemType(maj, min) != subsystem_type)
3137ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov            continue;
3138ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3139ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        switch (subsystem_type) {
3140ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        case DRM_BUS_PCI:
3141ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov            ret = drmProcessPciDevice(&d, dent->d_name, node, node_type,
3142ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov                                      maj, min, true);
3143ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov            if (ret)
3144ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov                goto free_devices;
3145ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3146ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov            break;
3147ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        default:
3148ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov            fprintf(stderr, "The subsystem type is not supported yet\n");
3149ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov            break;
3150ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        }
3151ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3152ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        if (i >= max_count) {
3153ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov            drmDevicePtr *temp;
3154ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3155ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov            max_count += 16;
3156ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov            temp = realloc(local_devices, max_count * sizeof(drmDevicePtr));
3157ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov            if (!temp)
3158ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov                goto free_devices;
3159ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov            local_devices = temp;
3160ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        }
3161ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3162ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        local_devices[i] = d;
3163ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov        i++;
3164ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    }
3165ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    node_count = i;
3166ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3167ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    /* Fold nodes into a single device if they share the same bus info */
3168ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    drmFoldDuplicatedDevices(local_devices, node_count);
3169ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3170ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    *device = local_devices[0];
3171ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    for (i = 1; i < node_count && local_devices[i]; i++)
3172ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov            drmFreeDevice(&local_devices[i]);
3173ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3174ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    free(local_devices);
3175ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    closedir(sysdir);
3176ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    return 0;
3177ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3178ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikovfree_devices:
3179ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    drmFreeDevices(local_devices, i);
3180ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    free(local_devices);
3181ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3182ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikovclose_sysdir:
3183ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    closedir(sysdir);
3184ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov    return ret;
3185ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov}
3186ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov
3187ccedf66b65f6ab245aa6028d7fe9eb603a121b43Emil Velikov/**
3188b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov * Get drm devices on the system
3189b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov *
3190b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov * \param devices the array of devices with drmDevicePtr elements
3191b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov *                can be NULL to get the device number first
3192b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov * \param max_devices the maximum number of devices for the array
3193b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov *
3194b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov * \return on error - negative error code,
3195b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov *         if devices is NULL - total number of devices available on the system,
3196b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov *         alternatively the number of devices stored in devices[], which is
3197b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov *         capped by the max_devices.
3198b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov */
3199b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikovint drmGetDevices(drmDevicePtr devices[], int max_devices)
3200b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov{
32015f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    drmDevicePtr *local_devices;
32025f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    drmDevicePtr device;
32035f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    DIR *sysdir;
32045f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    struct dirent *dent;
32055f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    struct stat sbuf;
32065f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    char node[PATH_MAX + 1];
3207b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    int node_type, subsystem_type;
3208b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    int maj, min;
3209fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    int ret, i, node_count, device_count;
3210b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    int max_count = 16;
3211b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
32125f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    local_devices = calloc(max_count, sizeof(drmDevicePtr));
32135f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    if (local_devices == NULL)
3214b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        return -ENOMEM;
3215b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
3216b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    sysdir = opendir(DRM_DIR_NAME);
3217b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    if (!sysdir) {
3218b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        ret = -errno;
32195f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov        goto close_sysdir;
3220b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    }
3221b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
32225f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    i = 0;
3223b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    while ((dent = readdir(sysdir))) {
3224b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        node_type = drmGetNodeType(dent->d_name);
3225b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        if (node_type < 0)
3226b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov            continue;
3227b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
3228b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        snprintf(node, PATH_MAX, "%s/%s", DRM_DIR_NAME, dent->d_name);
3229b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        if (stat(node, &sbuf))
3230b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov            continue;
3231b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
3232b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        maj = major(sbuf.st_rdev);
3233b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        min = minor(sbuf.st_rdev);
3234b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
3235b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode))
3236b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov            continue;
3237b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
3238a250fceaaa150363accaf3fb71a0e42bcecc40daEmil Velikov        subsystem_type = drmParseSubsystemType(maj, min);
3239b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
3240b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        if (subsystem_type < 0)
3241b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov            continue;
3242b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
3243b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        switch (subsystem_type) {
3244b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        case DRM_BUS_PCI:
3245fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov            ret = drmProcessPciDevice(&device, dent->d_name, node, node_type,
3246fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov                                      maj, min, devices != NULL);
32475f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov            if (ret)
32485f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov                goto free_devices;
3249b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
3250b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov            break;
3251b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        default:
3252b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov            fprintf(stderr, "The subsystem type is not supported yet\n");
3253b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov            break;
3254b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov        }
3255b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
32565f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov        if (i >= max_count) {
32575f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov            drmDevicePtr *temp;
3258b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
32595f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov            max_count += 16;
32605f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov            temp = realloc(local_devices, max_count * sizeof(drmDevicePtr));
32615f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov            if (!temp)
32625f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov                goto free_devices;
32635f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov            local_devices = temp;
32645f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov        }
32655f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov
32665f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov        local_devices[i] = device;
32675f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov        i++;
3268b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    }
32695f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    node_count = i;
3270b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
32715f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    /* Fold nodes into a single device if they share the same bus info */
3272fae59d7234caf4827bf5ca74c1b706cbfb70a460Emil Velikov    drmFoldDuplicatedDevices(local_devices, node_count);
3273b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
32745f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    device_count = 0;
32755f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    for (i = 0; i < node_count && local_devices[i]; i++) {
32765f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov        if ((devices != NULL) && (device_count < max_devices))
32775f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov            devices[device_count] = local_devices[i];
32785f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov        else
32795f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov            drmFreeDevice(&local_devices[i]);
3280b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
32815f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov        device_count++;
32825f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    }
3283b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
32845f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    free(local_devices);
3285b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    closedir(sysdir);
32865f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    return device_count;
32875f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov
32885f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikovfree_devices:
32895f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    drmFreeDevices(local_devices, i);
32905f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikov    free(local_devices);
3291b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov
32925f68d31820315ebda9b49e8bd50d1ab605efd7faEmil Velikovclose_sysdir:
3293b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    closedir(sysdir);
3294b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov    return ret;
3295b556ea127e004b734b2a7bf8e67cdcf56312171dEmil Velikov}
3296