blob: e94f2cd00c11e6b0a8e41596b4f2eba1ce964ce5 [file] [log] [blame]
Jose Fonsecad2443b22003-05-27 00:37:33 +00001/**
2 * \file xf86drm.c
3 * User-level interface to DRM device
Daryll Straussb3a57661999-12-05 01:19:48 +00004 *
Jose Fonsecad2443b22003-05-27 00:37:33 +00005 * \author Rickard E. (Rik) Faith <faith@valinux.com>
6 * \author Kevin E. Martin <martin@valinux.com>
7 */
8
9/*
Brian Paul569da5a2000-06-08 14:38:22 +000010 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
11 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
Daryll Straussb3a57661999-12-05 01:19:48 +000012 * All Rights Reserved.
13 *
14 * Permission is hereby granted, free of charge, to any person obtaining a
15 * copy of this software and associated documentation files (the "Software"),
16 * to deal in the Software without restriction, including without limitation
17 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 * and/or sell copies of the Software, and to permit persons to whom the
19 * Software is furnished to do so, subject to the following conditions:
Gareth Hughes36047532001-02-15 08:12:14 +000020 *
Daryll Straussb3a57661999-12-05 01:19:48 +000021 * The above copyright notice and this permission notice (including the next
22 * paragraph) shall be included in all copies or substantial portions of the
23 * Software.
Gareth Hughes36047532001-02-15 08:12:14 +000024 *
Daryll Straussb3a57661999-12-05 01:19:48 +000025 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
28 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
29 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
30 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
31 * DEALINGS IN THE SOFTWARE.
Daryll Straussb3a57661999-12-05 01:19:48 +000032 */
33
Dave Airlie79038752006-11-08 15:08:09 +110034#ifdef HAVE_CONFIG_H
35# include <config.h>
Daryll Straussb3a57661999-12-05 01:19:48 +000036#endif
Dave Airlie79038752006-11-08 15:08:09 +110037#include <stdio.h>
38#include <stdlib.h>
39#include <unistd.h>
40#include <string.h>
Ian Romanick015efd12009-07-06 09:23:59 -070041#include <strings.h>
Dave Airlie79038752006-11-08 15:08:09 +110042#include <ctype.h>
43#include <fcntl.h>
44#include <errno.h>
45#include <signal.h>
Jesse Barnesf4f76a62009-01-07 10:18:08 -080046#include <time.h>
Dave Airlie79038752006-11-08 15:08:09 +110047#include <sys/types.h>
48#include <sys/stat.h>
49#define stat_t struct stat
50#include <sys/ioctl.h>
51#include <sys/mman.h>
52#include <sys/time.h>
53#include <stdarg.h>
Daryll Straussb3a57661999-12-05 01:19:48 +000054
55/* Not all systems have MAP_FAILED defined */
56#ifndef MAP_FAILED
57#define MAP_FAILED ((void *)-1)
58#endif
59
Daryll Straussb3a57661999-12-05 01:19:48 +000060#include "xf86drm.h"
Daryll Straussb3a57661999-12-05 01:19:48 +000061
Hasso Tepper27c37852008-04-07 15:27:43 +030062#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
Eric Anholtcfa778a2003-02-21 23:23:09 +000063#define DRM_MAJOR 145
Rik Faith88dbee52001-02-28 09:27:44 +000064#endif
65
Eric Anholtcfa778a2003-02-21 23:23:09 +000066#ifdef __NetBSD__
67#define DRM_MAJOR 34
68#endif
69
Alan Hourihaneb0a92852003-09-24 14:39:25 +000070# ifdef __OpenBSD__
71# define DRM_MAJOR 81
72# endif
73
Eric Anholtcfa778a2003-02-21 23:23:09 +000074#ifndef DRM_MAJOR
75#define DRM_MAJOR 226 /* Linux */
Rik Faith88dbee52001-02-28 09:27:44 +000076#endif
77
Adam Jackson22e41ef2006-02-20 23:09:00 +000078/*
79 * This definition needs to be changed on some systems if dev_t is a structure.
80 * If there is a header file we can get it from, there would be best.
81 */
Brian Paul569da5a2000-06-08 14:38:22 +000082#ifndef makedev
Brian Paul569da5a2000-06-08 14:38:22 +000083#define makedev(x,y) ((dev_t)(((x) << 8) | (y)))
84#endif
85
David Dawes56bd9c22001-07-30 19:59:39 +000086#define DRM_MSG_VERBOSITY 3
87
Jesse Barnes731cd552008-12-17 10:09:49 -080088#define DRM_NODE_CONTROL 0
89#define DRM_NODE_RENDER 1
90
Dave Airlie79038752006-11-08 15:08:09 +110091static drmServerInfoPtr drm_server_info;
92
93void drmSetServerInfo(drmServerInfoPtr info)
94{
Brianccd7b6e2007-05-29 14:54:00 -060095 drm_server_info = info;
Dave Airlie79038752006-11-08 15:08:09 +110096}
97
Jose Fonsecad2443b22003-05-27 00:37:33 +000098/**
99 * Output a message to stderr.
100 *
101 * \param format printf() like format string.
102 *
103 * \internal
104 * This function is a wrapper around vfprintf().
105 */
Dave Airlie79038752006-11-08 15:08:09 +1100106
Thierry Reding44b08c02014-01-22 12:06:51 +0100107static int DRM_PRINTFLIKE(1, 0)
108drmDebugPrint(const char *format, va_list ap)
Dave Airlie79038752006-11-08 15:08:09 +1100109{
Brianccd7b6e2007-05-29 14:54:00 -0600110 return vfprintf(stderr, format, ap);
Dave Airlie79038752006-11-08 15:08:09 +1100111}
112
Thierry Reding44b08c02014-01-22 12:06:51 +0100113typedef int DRM_PRINTFLIKE(1, 0) (*debug_msg_func_t)(const char *format,
114 va_list ap);
115
116static debug_msg_func_t drm_debug_print = drmDebugPrint;
Dave Airlie79038752006-11-08 15:08:09 +1100117
Eric Anholtc4857422008-06-03 10:20:49 -0700118void
David Dawes56bd9c22001-07-30 19:59:39 +0000119drmMsg(const char *format, ...)
120{
121 va_list ap;
David Dawes56bd9c22001-07-30 19:59:39 +0000122 const char *env;
Dave Airlie79038752006-11-08 15:08:09 +1100123 if (((env = getenv("LIBGL_DEBUG")) && strstr(env, "verbose")) || drm_server_info)
David Dawes56bd9c22001-07-30 19:59:39 +0000124 {
125 va_start(ap, format);
Dave Airlie79038752006-11-08 15:08:09 +1100126 if (drm_server_info) {
127 drm_server_info->debug_print(format,ap);
128 } else {
129 drm_debug_print(format, ap);
130 }
David Dawes56bd9c22001-07-30 19:59:39 +0000131 va_end(ap);
132 }
133}
134
Dave Airlie79038752006-11-08 15:08:09 +1100135void
Thierry Reding44b08c02014-01-22 12:06:51 +0100136drmSetDebugMsgFunction(debug_msg_func_t debug_msg_ptr)
Dave Airlie79038752006-11-08 15:08:09 +1100137{
Brianccd7b6e2007-05-29 14:54:00 -0600138 drm_debug_print = debug_msg_ptr;
Dave Airlie79038752006-11-08 15:08:09 +1100139}
140
Daryll Straussb3a57661999-12-05 01:19:48 +0000141static void *drmHashTable = NULL; /* Context switch callbacks */
142
Dave Airlie79038752006-11-08 15:08:09 +1100143void *drmGetHashTable(void)
144{
Brianccd7b6e2007-05-29 14:54:00 -0600145 return drmHashTable;
Dave Airlie79038752006-11-08 15:08:09 +1100146}
Daryll Straussb3a57661999-12-05 01:19:48 +0000147
148void *drmMalloc(int size)
149{
150 void *pt;
Brianccd7b6e2007-05-29 14:54:00 -0600151 if ((pt = malloc(size)))
152 memset(pt, 0, size);
Daryll Straussb3a57661999-12-05 01:19:48 +0000153 return pt;
154}
155
156void drmFree(void *pt)
157{
Brianccd7b6e2007-05-29 14:54:00 -0600158 if (pt)
159 free(pt);
Daryll Straussb3a57661999-12-05 01:19:48 +0000160}
161
Keith Packard8b9ab102008-06-13 16:03:22 -0700162/**
163 * Call ioctl, restarting if it is interupted
164 */
Jesse Barnes731cd552008-12-17 10:09:49 -0800165int
Coleman Kane41b83a92008-08-18 17:08:21 -0400166drmIoctl(int fd, unsigned long request, void *arg)
Keith Packard8b9ab102008-06-13 16:03:22 -0700167{
168 int ret;
169
170 do {
171 ret = ioctl(fd, request, arg);
172 } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
173 return ret;
174}
Daryll Straussb3a57661999-12-05 01:19:48 +0000175
Daryll Straussb3a57661999-12-05 01:19:48 +0000176static unsigned long drmGetKeyFromFd(int fd)
177{
David Dawesfcc21062001-03-30 17:16:20 +0000178 stat_t st;
Daryll Straussb3a57661999-12-05 01:19:48 +0000179
180 st.st_rdev = 0;
181 fstat(fd, &st);
182 return st.st_rdev;
183}
184
Dave Airlie79038752006-11-08 15:08:09 +1100185drmHashEntry *drmGetEntry(int fd)
Daryll Straussb3a57661999-12-05 01:19:48 +0000186{
187 unsigned long key = drmGetKeyFromFd(fd);
188 void *value;
189 drmHashEntry *entry;
190
Brianccd7b6e2007-05-29 14:54:00 -0600191 if (!drmHashTable)
192 drmHashTable = drmHashCreate();
Daryll Straussb3a57661999-12-05 01:19:48 +0000193
194 if (drmHashLookup(drmHashTable, key, &value)) {
195 entry = drmMalloc(sizeof(*entry));
196 entry->fd = fd;
197 entry->f = NULL;
198 entry->tagTable = drmHashCreate();
199 drmHashInsert(drmHashTable, key, entry);
200 } else {
201 entry = value;
202 }
203 return entry;
204}
205
Jose Fonsecad2443b22003-05-27 00:37:33 +0000206/**
Eric Anholt06cb1322003-10-23 02:23:31 +0000207 * Compare two busid strings
208 *
209 * \param first
210 * \param second
211 *
212 * \return 1 if matched.
213 *
214 * \internal
215 * This function compares two bus ID strings. It understands the older
216 * PCI:b:d:f format and the newer pci:oooo:bb:dd.f format. In the format, o is
217 * domain, b is bus, d is device, f is function.
218 */
Benjamin Herrenschmidtb04515c2010-08-06 13:55:11 +1000219static int drmMatchBusID(const char *id1, const char *id2, int pci_domain_ok)
Eric Anholt06cb1322003-10-23 02:23:31 +0000220{
221 /* First, check if the IDs are exactly the same */
222 if (strcasecmp(id1, id2) == 0)
223 return 1;
224
225 /* Try to match old/new-style PCI bus IDs. */
226 if (strncasecmp(id1, "pci", 3) == 0) {
Pauli Nieminen90ae0f22009-07-04 02:18:51 +0300227 unsigned int o1, b1, d1, f1;
228 unsigned int o2, b2, d2, f2;
Eric Anholt06cb1322003-10-23 02:23:31 +0000229 int ret;
230
Pauli Nieminen90ae0f22009-07-04 02:18:51 +0300231 ret = sscanf(id1, "pci:%04x:%02x:%02x.%u", &o1, &b1, &d1, &f1);
Eric Anholt06cb1322003-10-23 02:23:31 +0000232 if (ret != 4) {
233 o1 = 0;
Pauli Nieminen90ae0f22009-07-04 02:18:51 +0300234 ret = sscanf(id1, "PCI:%u:%u:%u", &b1, &d1, &f1);
Eric Anholt06cb1322003-10-23 02:23:31 +0000235 if (ret != 3)
236 return 0;
237 }
238
Pauli Nieminen90ae0f22009-07-04 02:18:51 +0300239 ret = sscanf(id2, "pci:%04x:%02x:%02x.%u", &o2, &b2, &d2, &f2);
Eric Anholt06cb1322003-10-23 02:23:31 +0000240 if (ret != 4) {
241 o2 = 0;
Pauli Nieminen90ae0f22009-07-04 02:18:51 +0300242 ret = sscanf(id2, "PCI:%u:%u:%u", &b2, &d2, &f2);
Eric Anholt06cb1322003-10-23 02:23:31 +0000243 if (ret != 3)
244 return 0;
245 }
246
Benjamin Herrenschmidtb04515c2010-08-06 13:55:11 +1000247 /* If domains aren't properly supported by the kernel interface,
248 * just ignore them, which sucks less than picking a totally random
249 * card with "open by name"
250 */
251 if (!pci_domain_ok)
252 o1 = o2 = 0;
253
Eric Anholt06cb1322003-10-23 02:23:31 +0000254 if ((o1 != o2) || (b1 != b2) || (d1 != d2) || (f1 != f2))
255 return 0;
256 else
257 return 1;
258 }
259 return 0;
260}
261
262/**
Pauli Nieminenc5a5bbb2009-07-06 23:37:20 +0300263 * Handles error checking for chown call.
264 *
265 * \param path to file.
266 * \param id of the new owner.
267 * \param id of the new group.
268 *
269 * \return zero if success or -1 if failure.
270 *
271 * \internal
272 * Checks for failure. If failure was caused by signal call chown again.
273 * If any other failure happened then it will output error mesage using
274 * drmMsg() call.
275 */
276static int chown_check_return(const char *path, uid_t owner, gid_t group)
277{
278 int rv;
279
280 do {
281 rv = chown(path, owner, group);
282 } while (rv != 0 && errno == EINTR);
283
284 if (rv == 0)
285 return 0;
286
287 drmMsg("Failed to change owner or group for file %s! %d: %s\n",
288 path, errno, strerror(errno));
289 return -1;
290}
291
292/**
Jose Fonsecad2443b22003-05-27 00:37:33 +0000293 * Open the DRM device, creating it if necessary.
294 *
295 * \param dev major and minor numbers of the device.
296 * \param minor minor number of the device.
297 *
298 * \return a file descriptor on success, or a negative value on error.
299 *
300 * \internal
301 * Assembles the device name from \p minor and opens it, creating the device
302 * special file node with the major and minor numbers specified by \p dev and
303 * parent directory if necessary and was called by root.
304 */
Jesse Barnes731cd552008-12-17 10:09:49 -0800305static int drmOpenDevice(long dev, int minor, int type)
Daryll Straussb3a57661999-12-05 01:19:48 +0000306{
David Dawes9c775d02001-05-14 14:49:58 +0000307 stat_t st;
Rik Faith88dbee52001-02-28 09:27:44 +0000308 char buf[64];
309 int fd;
Dave Airlie79038752006-11-08 15:08:09 +1100310 mode_t devmode = DRM_DEV_MODE, serv_mode;
Rik Faith88dbee52001-02-28 09:27:44 +0000311 int isroot = !geteuid();
Rik Faith88dbee52001-02-28 09:27:44 +0000312 uid_t user = DRM_DEV_UID;
Dave Airlie79038752006-11-08 15:08:09 +1100313 gid_t group = DRM_DEV_GID, serv_group;
314
Jesse Barnes731cd552008-12-17 10:09:49 -0800315 sprintf(buf, type ? DRM_DEV_NAME : DRM_CONTROL_DEV_NAME, DRM_DIR_NAME, minor);
Eric Anholt06cb1322003-10-23 02:23:31 +0000316 drmMsg("drmOpenDevice: node name is %s\n", buf);
David Dawes56bd9c22001-07-30 19:59:39 +0000317
Dave Airlie79038752006-11-08 15:08:09 +1100318 if (drm_server_info) {
Brianccd7b6e2007-05-29 14:54:00 -0600319 drm_server_info->get_perms(&serv_group, &serv_mode);
320 devmode = serv_mode ? serv_mode : DRM_DEV_MODE;
321 devmode &= ~(S_IXUSR|S_IXGRP|S_IXOTH);
322 group = (serv_group >= 0) ? serv_group : DRM_DEV_GID;
Dave Airlie79038752006-11-08 15:08:09 +1100323 }
Brian Paul569da5a2000-06-08 14:38:22 +0000324
Dave Airlie9101a022008-08-24 16:54:43 +1000325#if !defined(UDEV)
Rik Faith88dbee52001-02-28 09:27:44 +0000326 if (stat(DRM_DIR_NAME, &st)) {
Brianccd7b6e2007-05-29 14:54:00 -0600327 if (!isroot)
328 return DRM_ERR_NOT_ROOT;
Alan Hourihaneb3a20ce2002-10-22 23:38:53 +0000329 mkdir(DRM_DIR_NAME, DRM_DEV_DIRMODE);
Pauli Nieminenc5a5bbb2009-07-06 23:37:20 +0300330 chown_check_return(DRM_DIR_NAME, 0, 0); /* root:root */
Alan Hourihaneb3a20ce2002-10-22 23:38:53 +0000331 chmod(DRM_DIR_NAME, DRM_DEV_DIRMODE);
Brian Paul569da5a2000-06-08 14:38:22 +0000332 }
Daryll Straussb3a57661999-12-05 01:19:48 +0000333
Eric Anholt06cb1322003-10-23 02:23:31 +0000334 /* Check if the device node exists and create it if necessary. */
Eric Anholtd2f2b422002-08-08 21:23:46 +0000335 if (stat(buf, &st)) {
Brianccd7b6e2007-05-29 14:54:00 -0600336 if (!isroot)
337 return DRM_ERR_NOT_ROOT;
Rik Faith88dbee52001-02-28 09:27:44 +0000338 remove(buf);
339 mknod(buf, S_IFCHR | devmode, dev);
Daryll Straussb3a57661999-12-05 01:19:48 +0000340 }
Dave Airlie79038752006-11-08 15:08:09 +1100341
342 if (drm_server_info) {
Pauli Nieminenc5a5bbb2009-07-06 23:37:20 +0300343 chown_check_return(buf, user, group);
Brianccd7b6e2007-05-29 14:54:00 -0600344 chmod(buf, devmode);
Dave Airlie79038752006-11-08 15:08:09 +1100345 }
Dave Airlie9101a022008-08-24 16:54:43 +1000346#else
347 /* if we modprobed then wait for udev */
348 {
349 int udev_count = 0;
350wait_for_udev:
351 if (stat(DRM_DIR_NAME, &st)) {
352 usleep(20);
353 udev_count++;
354
355 if (udev_count == 50)
356 return -1;
357 goto wait_for_udev;
358 }
359
360 if (stat(buf, &st)) {
361 usleep(20);
362 udev_count++;
363
364 if (udev_count == 50)
365 return -1;
366 goto wait_for_udev;
367 }
368 }
369#endif
Rik Faith88dbee52001-02-28 09:27:44 +0000370
David Dawes56bd9c22001-07-30 19:59:39 +0000371 fd = open(buf, O_RDWR, 0);
372 drmMsg("drmOpenDevice: open result is %d, (%s)\n",
373 fd, fd < 0 ? strerror(errno) : "OK");
Brianccd7b6e2007-05-29 14:54:00 -0600374 if (fd >= 0)
375 return fd;
Eric Anholtd2f2b422002-08-08 21:23:46 +0000376
Dave Airlie39e5e982010-12-07 14:26:09 +1000377#if !defined(UDEV)
Eric Anholt06cb1322003-10-23 02:23:31 +0000378 /* Check if the device node is not what we expect it to be, and recreate it
379 * and try again if so.
380 */
Eric Anholtd2f2b422002-08-08 21:23:46 +0000381 if (st.st_rdev != dev) {
Brianccd7b6e2007-05-29 14:54:00 -0600382 if (!isroot)
383 return DRM_ERR_NOT_ROOT;
Eric Anholtd2f2b422002-08-08 21:23:46 +0000384 remove(buf);
385 mknod(buf, S_IFCHR | devmode, dev);
Dave Airlie79038752006-11-08 15:08:09 +1100386 if (drm_server_info) {
Pauli Nieminenc5a5bbb2009-07-06 23:37:20 +0300387 chown_check_return(buf, user, group);
Brianccd7b6e2007-05-29 14:54:00 -0600388 chmod(buf, devmode);
Dave Airlie79038752006-11-08 15:08:09 +1100389 }
Eric Anholtd2f2b422002-08-08 21:23:46 +0000390 }
391 fd = open(buf, O_RDWR, 0);
392 drmMsg("drmOpenDevice: open result is %d, (%s)\n",
393 fd, fd < 0 ? strerror(errno) : "OK");
Brianccd7b6e2007-05-29 14:54:00 -0600394 if (fd >= 0)
395 return fd;
Eric Anholtd2f2b422002-08-08 21:23:46 +0000396
David Dawes56bd9c22001-07-30 19:59:39 +0000397 drmMsg("drmOpenDevice: Open failed\n");
Rik Faith88dbee52001-02-28 09:27:44 +0000398 remove(buf);
Dave Airlie39e5e982010-12-07 14:26:09 +1000399#endif
Rik Faith88dbee52001-02-28 09:27:44 +0000400 return -errno;
Daryll Straussb3a57661999-12-05 01:19:48 +0000401}
402
Jose Fonsecad2443b22003-05-27 00:37:33 +0000403
404/**
405 * Open the DRM device
406 *
407 * \param minor device minor number.
408 * \param create allow to create the device if set.
409 *
410 * \return a file descriptor on success, or a negative value on error.
411 *
412 * \internal
413 * Calls drmOpenDevice() if \p create is set, otherwise assembles the device
414 * name from \p minor and opens it.
415 */
Jesse Barnes731cd552008-12-17 10:09:49 -0800416static int drmOpenMinor(int minor, int create, int type)
Rik Faith88dbee52001-02-28 09:27:44 +0000417{
418 int fd;
419 char buf[64];
Dave Airliedb85ed22008-02-13 12:20:02 +1000420
Brianccd7b6e2007-05-29 14:54:00 -0600421 if (create)
Jesse Barnes731cd552008-12-17 10:09:49 -0800422 return drmOpenDevice(makedev(DRM_MAJOR, minor), minor, type);
Rik Faith88dbee52001-02-28 09:27:44 +0000423
Jesse Barnes731cd552008-12-17 10:09:49 -0800424 sprintf(buf, type ? DRM_DEV_NAME : DRM_CONTROL_DEV_NAME, DRM_DIR_NAME, minor);
Brianccd7b6e2007-05-29 14:54:00 -0600425 if ((fd = open(buf, O_RDWR, 0)) >= 0)
426 return fd;
Rik Faith88dbee52001-02-28 09:27:44 +0000427 return -errno;
428}
429
Brian Paul569da5a2000-06-08 14:38:22 +0000430
Jose Fonsecad2443b22003-05-27 00:37:33 +0000431/**
432 * Determine whether the DRM kernel driver has been loaded.
433 *
434 * \return 1 if the DRM driver is loaded, 0 otherwise.
435 *
436 * \internal
437 * Determine the presence of the kernel driver by attempting to open the 0
438 * minor and get version information. For backward compatibility with older
439 * Linux implementations, /proc/dri is also checked.
440 */
Brian Paul569da5a2000-06-08 14:38:22 +0000441int drmAvailable(void)
442{
Brian Paul569da5a2000-06-08 14:38:22 +0000443 drmVersionPtr version;
444 int retval = 0;
445 int fd;
Gareth Hughes36047532001-02-15 08:12:14 +0000446
Jesse Barnes731cd552008-12-17 10:09:49 -0800447 if ((fd = drmOpenMinor(0, 1, DRM_NODE_RENDER)) < 0) {
Alan Hourihaneb0a92852003-09-24 14:39:25 +0000448#ifdef __linux__
Adam Jackson22e41ef2006-02-20 23:09:00 +0000449 /* Try proc for backward Linux compatibility */
Brianccd7b6e2007-05-29 14:54:00 -0600450 if (!access("/proc/dri/0", R_OK))
451 return 1;
Alan Hourihaneb0a92852003-09-24 14:39:25 +0000452#endif
Rik Faith88dbee52001-02-28 09:27:44 +0000453 return 0;
Brian Paul569da5a2000-06-08 14:38:22 +0000454 }
Rik Faith88dbee52001-02-28 09:27:44 +0000455
456 if ((version = drmGetVersion(fd))) {
457 retval = 1;
458 drmFreeVersion(version);
459 }
460 close(fd);
Brian Paul569da5a2000-06-08 14:38:22 +0000461
462 return retval;
463}
464
Jose Fonsecad2443b22003-05-27 00:37:33 +0000465
466/**
467 * Open the device by bus ID.
468 *
469 * \param busid bus ID.
470 *
471 * \return a file descriptor on success, or a negative value on error.
472 *
473 * \internal
474 * This function attempts to open every possible minor (up to DRM_MAX_MINOR),
475 * comparing the device bus ID with the one supplied.
476 *
477 * \sa drmOpenMinor() and drmGetBusid().
478 */
Daryll Strausse1dba5c1999-12-07 03:37:16 +0000479static int drmOpenByBusid(const char *busid)
480{
Benjamin Herrenschmidtb04515c2010-08-06 13:55:11 +1000481 int i, pci_domain_ok = 1;
Rik Faith88dbee52001-02-28 09:27:44 +0000482 int fd;
483 const char *buf;
Eric Anholt06cb1322003-10-23 02:23:31 +0000484 drmSetVersion sv;
485
486 drmMsg("drmOpenByBusid: Searching for BusID %s\n", busid);
Dave Airliedb85ed22008-02-13 12:20:02 +1000487 for (i = 0; i < DRM_MAX_MINOR; i++) {
Jesse Barnes731cd552008-12-17 10:09:49 -0800488 fd = drmOpenMinor(i, 1, DRM_NODE_RENDER);
David Dawes56bd9c22001-07-30 19:59:39 +0000489 drmMsg("drmOpenByBusid: drmOpenMinor returns %d\n", fd);
490 if (fd >= 0) {
Benjamin Herrenschmidtb04515c2010-08-06 13:55:11 +1000491 /* We need to try for 1.4 first for proper PCI domain support
492 * and if that fails, we know the kernel is busted
493 */
Eric Anholt06cb1322003-10-23 02:23:31 +0000494 sv.drm_di_major = 1;
Benjamin Herrenschmidtb04515c2010-08-06 13:55:11 +1000495 sv.drm_di_minor = 4;
Eric Anholt06cb1322003-10-23 02:23:31 +0000496 sv.drm_dd_major = -1; /* Don't care */
Eric Anholt26462b92005-12-31 11:48:12 +0000497 sv.drm_dd_minor = -1; /* Don't care */
Benjamin Herrenschmidtb04515c2010-08-06 13:55:11 +1000498 if (drmSetInterfaceVersion(fd, &sv)) {
499#ifndef __alpha__
500 pci_domain_ok = 0;
501#endif
502 sv.drm_di_major = 1;
503 sv.drm_di_minor = 1;
504 sv.drm_dd_major = -1; /* Don't care */
505 sv.drm_dd_minor = -1; /* Don't care */
Thierry Reding303ff262014-04-08 22:33:04 +0200506 drmMsg("drmOpenByBusid: Interface 1.4 failed, trying 1.1\n");
Benjamin Herrenschmidtb04515c2010-08-06 13:55:11 +1000507 drmSetInterfaceVersion(fd, &sv);
508 }
Daryll Strausse1dba5c1999-12-07 03:37:16 +0000509 buf = drmGetBusid(fd);
David Dawes56bd9c22001-07-30 19:59:39 +0000510 drmMsg("drmOpenByBusid: drmGetBusid reports %s\n", buf);
Benjamin Herrenschmidtb04515c2010-08-06 13:55:11 +1000511 if (buf && drmMatchBusID(buf, busid, pci_domain_ok)) {
Rik Faith88dbee52001-02-28 09:27:44 +0000512 drmFreeBusid(buf);
513 return fd;
Daryll Strausse1dba5c1999-12-07 03:37:16 +0000514 }
Brianccd7b6e2007-05-29 14:54:00 -0600515 if (buf)
516 drmFreeBusid(buf);
Daryll Strausse1dba5c1999-12-07 03:37:16 +0000517 close(fd);
518 }
519 }
520 return -1;
521}
522
Jose Fonsecad2443b22003-05-27 00:37:33 +0000523
524/**
525 * Open the device by name.
526 *
527 * \param name driver name.
528 *
529 * \return a file descriptor on success, or a negative value on error.
530 *
531 * \internal
532 * This function opens the first minor number that matches the driver name and
533 * isn't already in use. If it's in use it then it will already have a bus ID
534 * assigned.
535 *
536 * \sa drmOpenMinor(), drmGetVersion() and drmGetBusid().
537 */
Daryll Straussb6a28bf1999-12-05 23:10:37 +0000538static int drmOpenByName(const char *name)
Daryll Straussb3a57661999-12-05 01:19:48 +0000539{
Rik Faith88dbee52001-02-28 09:27:44 +0000540 int i;
541 int fd;
542 drmVersionPtr version;
David Dawes56bd9c22001-07-30 19:59:39 +0000543 char * id;
Rik Faith88dbee52001-02-28 09:27:44 +0000544
Dave Airliedb85ed22008-02-13 12:20:02 +1000545 if (!drmAvailable()) {
546 if (!drm_server_info) {
547 return -1;
548 }
549 else {
550 /* try to load the kernel module now */
551 if (!drm_server_info->load_module(name)) {
552 drmMsg("[drm] failed to load kernel module \"%s\"\n", name);
553 return -1;
554 }
555 }
556 }
557
David Dawes56bd9c22001-07-30 19:59:39 +0000558 /*
559 * Open the first minor number that matches the driver name and isn't
560 * already in use. If it's in use it will have a busid assigned already.
561 */
Dave Airliedb85ed22008-02-13 12:20:02 +1000562 for (i = 0; i < DRM_MAX_MINOR; i++) {
Jesse Barnes731cd552008-12-17 10:09:49 -0800563 if ((fd = drmOpenMinor(i, 1, DRM_NODE_RENDER)) >= 0) {
Rik Faith88dbee52001-02-28 09:27:44 +0000564 if ((version = drmGetVersion(fd))) {
565 if (!strcmp(version->name, name)) {
566 drmFreeVersion(version);
David Dawes56bd9c22001-07-30 19:59:39 +0000567 id = drmGetBusid(fd);
568 drmMsg("drmGetBusid returned '%s'\n", id ? id : "NULL");
569 if (!id || !*id) {
Adam Jackson22e41ef2006-02-20 23:09:00 +0000570 if (id)
David Dawes56bd9c22001-07-30 19:59:39 +0000571 drmFreeBusid(id);
David Dawes56bd9c22001-07-30 19:59:39 +0000572 return fd;
573 } else {
574 drmFreeBusid(id);
575 }
576 } else {
577 drmFreeVersion(version);
Rik Faith88dbee52001-02-28 09:27:44 +0000578 }
Rik Faith88dbee52001-02-28 09:27:44 +0000579 }
David Dawes56bd9c22001-07-30 19:59:39 +0000580 close(fd);
Rik Faith88dbee52001-02-28 09:27:44 +0000581 }
582 }
583
584#ifdef __linux__
Adam Jackson22e41ef2006-02-20 23:09:00 +0000585 /* Backward-compatibility /proc support */
Daryll Straussb6a28bf1999-12-05 23:10:37 +0000586 for (i = 0; i < 8; i++) {
Rik Faith88dbee52001-02-28 09:27:44 +0000587 char proc_name[64], buf[512];
588 char *driver, *pt, *devstring;
589 int retcode;
590
Daryll Strauss0371c291999-12-18 18:34:59 +0000591 sprintf(proc_name, "/proc/dri/%d/name", i);
Daryll Straussb6a28bf1999-12-05 23:10:37 +0000592 if ((fd = open(proc_name, 0, 0)) >= 0) {
593 retcode = read(fd, buf, sizeof(buf)-1);
594 close(fd);
595 if (retcode) {
596 buf[retcode-1] = '\0';
597 for (driver = pt = buf; *pt && *pt != ' '; ++pt)
598 ;
Adam Jackson22e41ef2006-02-20 23:09:00 +0000599 if (*pt) { /* Device is next */
Daryll Straussb6a28bf1999-12-05 23:10:37 +0000600 *pt = '\0';
601 if (!strcmp(driver, name)) { /* Match */
602 for (devstring = ++pt; *pt && *pt != ' '; ++pt)
603 ;
604 if (*pt) { /* Found busid */
Rik Faith88dbee52001-02-28 09:27:44 +0000605 return drmOpenByBusid(++pt);
Adam Jackson22e41ef2006-02-20 23:09:00 +0000606 } else { /* No busid */
Jesse Barnes731cd552008-12-17 10:09:49 -0800607 return drmOpenDevice(strtol(devstring, NULL, 0),i, DRM_NODE_RENDER);
Daryll Straussb6a28bf1999-12-05 23:10:37 +0000608 }
609 }
610 }
611 }
Brian Paul569da5a2000-06-08 14:38:22 +0000612 }
Daryll Straussb6a28bf1999-12-05 23:10:37 +0000613 }
Rik Faith88dbee52001-02-28 09:27:44 +0000614#endif
615
Daryll Straussb6a28bf1999-12-05 23:10:37 +0000616 return -1;
617}
618
Daryll Straussb6a28bf1999-12-05 23:10:37 +0000619
Jose Fonsecad2443b22003-05-27 00:37:33 +0000620/**
621 * Open the DRM device.
622 *
623 * Looks up the specified name and bus ID, and opens the device found. The
624 * entry in /dev/dri is created if necessary and if called by root.
625 *
626 * \param name driver name. Not referenced if bus ID is supplied.
627 * \param busid bus ID. Zero if not known.
628 *
629 * \return a file descriptor on success, or a negative value on error.
630 *
631 * \internal
632 * It calls drmOpenByBusid() if \p busid is specified or drmOpenByName()
633 * otherwise.
634 */
Daryll Straussb6a28bf1999-12-05 23:10:37 +0000635int drmOpen(const char *name, const char *busid)
Daryll Straussb3a57661999-12-05 01:19:48 +0000636{
Dave Airlie79038752006-11-08 15:08:09 +1100637 if (!drmAvailable() && name != NULL && drm_server_info) {
Eric Anholt06cb1322003-10-23 02:23:31 +0000638 /* try to load the kernel */
Dave Airlie79038752006-11-08 15:08:09 +1100639 if (!drm_server_info->load_module(name)) {
Brianccd7b6e2007-05-29 14:54:00 -0600640 drmMsg("[drm] failed to load kernel module \"%s\"\n", name);
Eric Anholt06cb1322003-10-23 02:23:31 +0000641 return -1;
642 }
643 }
Daryll Straussb6a28bf1999-12-05 23:10:37 +0000644
Eric Anholt06cb1322003-10-23 02:23:31 +0000645 if (busid) {
Brianccd7b6e2007-05-29 14:54:00 -0600646 int fd = drmOpenByBusid(busid);
Eric Anholt06cb1322003-10-23 02:23:31 +0000647 if (fd >= 0)
648 return fd;
649 }
Adam Jackson22e41ef2006-02-20 23:09:00 +0000650
Eric Anholt06cb1322003-10-23 02:23:31 +0000651 if (name)
652 return drmOpenByName(name);
Adam Jackson22e41ef2006-02-20 23:09:00 +0000653
Eric Anholt06cb1322003-10-23 02:23:31 +0000654 return -1;
Daryll Straussb3a57661999-12-05 01:19:48 +0000655}
656
Jesse Barnes731cd552008-12-17 10:09:49 -0800657int drmOpenControl(int minor)
658{
659 return drmOpenMinor(minor, 0, DRM_NODE_CONTROL);
660}
Jose Fonsecad2443b22003-05-27 00:37:33 +0000661
662/**
663 * Free the version information returned by drmGetVersion().
664 *
665 * \param v pointer to the version information.
666 *
667 * \internal
668 * It frees the memory pointed by \p %v as well as all the non-null strings
669 * pointers in it.
670 */
Daryll Straussb3a57661999-12-05 01:19:48 +0000671void drmFreeVersion(drmVersionPtr v)
672{
Brianccd7b6e2007-05-29 14:54:00 -0600673 if (!v)
674 return;
Jakob Bornecrantz9d8ba2d2007-02-25 10:48:26 +1100675 drmFree(v->name);
676 drmFree(v->date);
677 drmFree(v->desc);
Daryll Straussb3a57661999-12-05 01:19:48 +0000678 drmFree(v);
679}
680
Jose Fonsecad2443b22003-05-27 00:37:33 +0000681
682/**
683 * Free the non-public version information returned by the kernel.
684 *
685 * \param v pointer to the version information.
686 *
687 * \internal
688 * Used by drmGetVersion() to free the memory pointed by \p %v as well as all
689 * the non-null strings pointers in it.
690 */
Daryll Straussb3a57661999-12-05 01:19:48 +0000691static void drmFreeKernelVersion(drm_version_t *v)
692{
Brianccd7b6e2007-05-29 14:54:00 -0600693 if (!v)
694 return;
Jakob Bornecrantz9d8ba2d2007-02-25 10:48:26 +1100695 drmFree(v->name);
696 drmFree(v->date);
697 drmFree(v->desc);
Daryll Straussb3a57661999-12-05 01:19:48 +0000698 drmFree(v);
699}
700
Jose Fonsecad2443b22003-05-27 00:37:33 +0000701
702/**
703 * Copy version information.
704 *
705 * \param d destination pointer.
706 * \param s source pointer.
707 *
708 * \internal
709 * Used by drmGetVersion() to translate the information returned by the ioctl
710 * interface in a private structure into the public structure counterpart.
711 */
Brian Paul569da5a2000-06-08 14:38:22 +0000712static void drmCopyVersion(drmVersionPtr d, const drm_version_t *s)
Daryll Straussb3a57661999-12-05 01:19:48 +0000713{
714 d->version_major = s->version_major;
715 d->version_minor = s->version_minor;
716 d->version_patchlevel = s->version_patchlevel;
717 d->name_len = s->name_len;
Adam Jackson0a1ff352010-10-27 18:44:53 -0400718 d->name = strdup(s->name);
Daryll Straussb3a57661999-12-05 01:19:48 +0000719 d->date_len = s->date_len;
Adam Jackson0a1ff352010-10-27 18:44:53 -0400720 d->date = strdup(s->date);
Daryll Straussb3a57661999-12-05 01:19:48 +0000721 d->desc_len = s->desc_len;
Adam Jackson0a1ff352010-10-27 18:44:53 -0400722 d->desc = strdup(s->desc);
Daryll Straussb3a57661999-12-05 01:19:48 +0000723}
724
Daryll Straussb3a57661999-12-05 01:19:48 +0000725
Jose Fonsecad2443b22003-05-27 00:37:33 +0000726/**
727 * Query the driver version information.
728 *
729 * \param fd file descriptor.
730 *
731 * \return pointer to a drmVersion structure which should be freed with
732 * drmFreeVersion().
733 *
734 * \note Similar information is available via /proc/dri.
735 *
736 * \internal
737 * It gets the version information via successive DRM_IOCTL_VERSION ioctls,
738 * first with zeros to get the string lengths, and then the actually strings.
739 * It also null-terminates them since they might not be already.
740 */
Daryll Straussb3a57661999-12-05 01:19:48 +0000741drmVersionPtr drmGetVersion(int fd)
742{
743 drmVersionPtr retval;
744 drm_version_t *version = drmMalloc(sizeof(*version));
745
Daryll Straussb3a57661999-12-05 01:19:48 +0000746 version->name_len = 0;
747 version->name = NULL;
748 version->date_len = 0;
749 version->date = NULL;
750 version->desc_len = 0;
751 version->desc = NULL;
Gareth Hughes36047532001-02-15 08:12:14 +0000752
Keith Packard8b9ab102008-06-13 16:03:22 -0700753 if (drmIoctl(fd, DRM_IOCTL_VERSION, version)) {
Daryll Straussb3a57661999-12-05 01:19:48 +0000754 drmFreeKernelVersion(version);
755 return NULL;
756 }
757
Daryll Straussb3a57661999-12-05 01:19:48 +0000758 if (version->name_len)
759 version->name = drmMalloc(version->name_len + 1);
760 if (version->date_len)
761 version->date = drmMalloc(version->date_len + 1);
762 if (version->desc_len)
763 version->desc = drmMalloc(version->desc_len + 1);
Gareth Hughes36047532001-02-15 08:12:14 +0000764
Keith Packard8b9ab102008-06-13 16:03:22 -0700765 if (drmIoctl(fd, DRM_IOCTL_VERSION, version)) {
Alan Hourihaneb0a92852003-09-24 14:39:25 +0000766 drmMsg("DRM_IOCTL_VERSION: %s\n", strerror(errno));
Daryll Straussb3a57661999-12-05 01:19:48 +0000767 drmFreeKernelVersion(version);
768 return NULL;
769 }
770
Adam Jackson22e41ef2006-02-20 23:09:00 +0000771 /* The results might not be null-terminated strings, so terminate them. */
Daryll Straussb3a57661999-12-05 01:19:48 +0000772 if (version->name_len) version->name[version->name_len] = '\0';
773 if (version->date_len) version->date[version->date_len] = '\0';
774 if (version->desc_len) version->desc[version->desc_len] = '\0';
775
Daryll Straussb3a57661999-12-05 01:19:48 +0000776 retval = drmMalloc(sizeof(*retval));
777 drmCopyVersion(retval, version);
778 drmFreeKernelVersion(version);
779 return retval;
780}
781
Jens Owen3903e5a2002-04-09 21:54:56 +0000782
Jose Fonsecad2443b22003-05-27 00:37:33 +0000783/**
784 * Get version information for the DRM user space library.
785 *
786 * This version number is driver independent.
787 *
788 * \param fd file descriptor.
789 *
790 * \return version information.
791 *
792 * \internal
793 * This function allocates and fills a drm_version structure with a hard coded
794 * version number.
795 */
Jens Owen3903e5a2002-04-09 21:54:56 +0000796drmVersionPtr drmGetLibVersion(int fd)
797{
798 drm_version_t *version = drmMalloc(sizeof(*version));
799
800 /* Version history:
Dave Airlie79038752006-11-08 15:08:09 +1100801 * NOTE THIS MUST NOT GO ABOVE VERSION 1.X due to drivers needing it
Jens Owen3903e5a2002-04-09 21:54:56 +0000802 * revision 1.0.x = original DRM interface with no drmGetLibVersion
803 * entry point and many drm<Device> extensions
804 * revision 1.1.x = added drmCommand entry points for device extensions
805 * added drmGetLibVersion to identify libdrm.a version
Eric Anholt06cb1322003-10-23 02:23:31 +0000806 * revision 1.2.x = added drmSetInterfaceVersion
807 * modified drmOpen to handle both busid and name
Dave Airlie79038752006-11-08 15:08:09 +1100808 * revision 1.3.x = added server + memory manager
Jens Owen3903e5a2002-04-09 21:54:56 +0000809 */
Dave Airlie79038752006-11-08 15:08:09 +1100810 version->version_major = 1;
811 version->version_minor = 3;
Jens Owen3903e5a2002-04-09 21:54:56 +0000812 version->version_patchlevel = 0;
813
814 return (drmVersionPtr)version;
815}
816
Ben Skeggs5c6c6912011-02-21 11:27:19 +1000817int drmGetCap(int fd, uint64_t capability, uint64_t *value)
818{
819 struct drm_get_cap cap = { capability, 0 };
820 int ret;
821
822 ret = drmIoctl(fd, DRM_IOCTL_GET_CAP, &cap);
823 if (ret)
824 return ret;
825
826 *value = cap.value;
Dave Airlie3b04c732011-03-04 15:48:31 +1000827 return 0;
Ben Skeggs5c6c6912011-02-21 11:27:19 +1000828}
Jose Fonsecad2443b22003-05-27 00:37:33 +0000829
Damien Lespiauddbbdb12013-09-03 15:34:41 +0100830int drmSetClientCap(int fd, uint64_t capability, uint64_t value)
831{
832 struct drm_set_client_cap cap = { capability, value };
833
834 return drmIoctl(fd, DRM_IOCTL_SET_CLIENT_CAP, &cap);
835}
836
Jose Fonsecad2443b22003-05-27 00:37:33 +0000837/**
838 * Free the bus ID information.
839 *
840 * \param busid bus ID information string as given by drmGetBusid().
841 *
842 * \internal
843 * This function is just frees the memory pointed by \p busid.
844 */
Daryll Straussb6a28bf1999-12-05 23:10:37 +0000845void drmFreeBusid(const char *busid)
Daryll Straussb3a57661999-12-05 01:19:48 +0000846{
Daryll Straussb6a28bf1999-12-05 23:10:37 +0000847 drmFree((void *)busid);
Daryll Straussb3a57661999-12-05 01:19:48 +0000848}
849
Jose Fonsecad2443b22003-05-27 00:37:33 +0000850
851/**
852 * Get the bus ID of the device.
853 *
854 * \param fd file descriptor.
855 *
856 * \return bus ID string.
857 *
858 * \internal
859 * This function gets the bus ID via successive DRM_IOCTL_GET_UNIQUE ioctls to
860 * get the string length and data, passing the arguments in a drm_unique
861 * structure.
862 */
Daryll Straussb6a28bf1999-12-05 23:10:37 +0000863char *drmGetBusid(int fd)
Daryll Straussb3a57661999-12-05 01:19:48 +0000864{
Daryll Straussb6a28bf1999-12-05 23:10:37 +0000865 drm_unique_t u;
866
867 u.unique_len = 0;
868 u.unique = NULL;
869
Keith Packard8b9ab102008-06-13 16:03:22 -0700870 if (drmIoctl(fd, DRM_IOCTL_GET_UNIQUE, &u))
Brianccd7b6e2007-05-29 14:54:00 -0600871 return NULL;
Daryll Straussb6a28bf1999-12-05 23:10:37 +0000872 u.unique = drmMalloc(u.unique_len + 1);
Keith Packard8b9ab102008-06-13 16:03:22 -0700873 if (drmIoctl(fd, DRM_IOCTL_GET_UNIQUE, &u))
Brianccd7b6e2007-05-29 14:54:00 -0600874 return NULL;
Daryll Straussb6a28bf1999-12-05 23:10:37 +0000875 u.unique[u.unique_len] = '\0';
Eric Anholt06cb1322003-10-23 02:23:31 +0000876
Daryll Straussb6a28bf1999-12-05 23:10:37 +0000877 return u.unique;
Daryll Straussb3a57661999-12-05 01:19:48 +0000878}
879
Jose Fonsecad2443b22003-05-27 00:37:33 +0000880
881/**
882 * Set the bus ID of the device.
883 *
884 * \param fd file descriptor.
885 * \param busid bus ID string.
886 *
887 * \return zero on success, negative on failure.
888 *
889 * \internal
890 * This function is a wrapper around the DRM_IOCTL_SET_UNIQUE ioctl, passing
891 * the arguments in a drm_unique structure.
892 */
Daryll Straussb6a28bf1999-12-05 23:10:37 +0000893int drmSetBusid(int fd, const char *busid)
Daryll Straussb3a57661999-12-05 01:19:48 +0000894{
Daryll Straussb6a28bf1999-12-05 23:10:37 +0000895 drm_unique_t u;
Daryll Straussb3a57661999-12-05 01:19:48 +0000896
Daryll Straussb6a28bf1999-12-05 23:10:37 +0000897 u.unique = (char *)busid;
898 u.unique_len = strlen(busid);
Daryll Straussb3a57661999-12-05 01:19:48 +0000899
Keith Packard8b9ab102008-06-13 16:03:22 -0700900 if (drmIoctl(fd, DRM_IOCTL_SET_UNIQUE, &u)) {
David Dawes56bd9c22001-07-30 19:59:39 +0000901 return -errno;
902 }
Daryll Straussb3a57661999-12-05 01:19:48 +0000903 return 0;
904}
905
Jon Smirl8696e712004-07-07 04:36:36 +0000906int drmGetMagic(int fd, drm_magic_t * magic)
Daryll Straussb3a57661999-12-05 01:19:48 +0000907{
908 drm_auth_t auth;
909
910 *magic = 0;
Keith Packard8b9ab102008-06-13 16:03:22 -0700911 if (drmIoctl(fd, DRM_IOCTL_GET_MAGIC, &auth))
Brianccd7b6e2007-05-29 14:54:00 -0600912 return -errno;
Daryll Straussb3a57661999-12-05 01:19:48 +0000913 *magic = auth.magic;
914 return 0;
915}
916
Jon Smirl8696e712004-07-07 04:36:36 +0000917int drmAuthMagic(int fd, drm_magic_t magic)
Daryll Straussb3a57661999-12-05 01:19:48 +0000918{
919 drm_auth_t auth;
920
921 auth.magic = magic;
Keith Packard8b9ab102008-06-13 16:03:22 -0700922 if (drmIoctl(fd, DRM_IOCTL_AUTH_MAGIC, &auth))
Brianccd7b6e2007-05-29 14:54:00 -0600923 return -errno;
Daryll Straussb3a57661999-12-05 01:19:48 +0000924 return 0;
925}
926
Jose Fonsecad2443b22003-05-27 00:37:33 +0000927/**
928 * Specifies a range of memory that is available for mapping by a
929 * non-root process.
930 *
931 * \param fd file descriptor.
932 * \param offset usually the physical address. The actual meaning depends of
933 * the \p type parameter. See below.
934 * \param size of the memory in bytes.
935 * \param type type of the memory to be mapped.
936 * \param flags combination of several flags to modify the function actions.
937 * \param handle will be set to a value that may be used as the offset
938 * parameter for mmap().
939 *
940 * \return zero on success or a negative value on error.
941 *
942 * \par Mapping the frame buffer
943 * For the frame buffer
944 * - \p offset will be the physical address of the start of the frame buffer,
945 * - \p size will be the size of the frame buffer in bytes, and
946 * - \p type will be DRM_FRAME_BUFFER.
947 *
948 * \par
949 * The area mapped will be uncached. If MTRR support is available in the
950 * kernel, the frame buffer area will be set to write combining.
951 *
952 * \par Mapping the MMIO register area
953 * For the MMIO register area,
954 * - \p offset will be the physical address of the start of the register area,
955 * - \p size will be the size of the register area bytes, and
956 * - \p type will be DRM_REGISTERS.
957 * \par
958 * The area mapped will be uncached.
959 *
960 * \par Mapping the SAREA
961 * For the SAREA,
962 * - \p offset will be ignored and should be set to zero,
963 * - \p size will be the desired size of the SAREA in bytes,
964 * - \p type will be DRM_SHM.
965 *
966 * \par
967 * A shared memory area of the requested size will be created and locked in
968 * kernel memory. This area may be mapped into client-space by using the handle
969 * returned.
970 *
971 * \note May only be called by root.
972 *
973 * \internal
974 * This function is a wrapper around the DRM_IOCTL_ADD_MAP ioctl, passing
975 * the arguments in a drm_map structure.
976 */
Adam Jackson22e41ef2006-02-20 23:09:00 +0000977int drmAddMap(int fd, drm_handle_t offset, drmSize size, drmMapType type,
978 drmMapFlags flags, drm_handle_t *handle)
Daryll Straussb3a57661999-12-05 01:19:48 +0000979{
980 drm_map_t map;
981
982 map.offset = offset;
983 map.size = size;
984 map.handle = 0;
985 map.type = type;
986 map.flags = flags;
Keith Packard8b9ab102008-06-13 16:03:22 -0700987 if (drmIoctl(fd, DRM_IOCTL_ADD_MAP, &map))
Brianccd7b6e2007-05-29 14:54:00 -0600988 return -errno;
989 if (handle)
Jeremy Huddleston961bf9b2011-11-01 14:42:13 -0700990 *handle = (drm_handle_t)(uintptr_t)map.handle;
Daryll Straussb3a57661999-12-05 01:19:48 +0000991 return 0;
992}
993
Jon Smirl8696e712004-07-07 04:36:36 +0000994int drmRmMap(int fd, drm_handle_t handle)
Kevin E Martin74e19a42001-03-14 22:22:50 +0000995{
996 drm_map_t map;
997
Jeremy Huddleston961bf9b2011-11-01 14:42:13 -0700998 map.handle = (void *)(uintptr_t)handle;
Kevin E Martin74e19a42001-03-14 22:22:50 +0000999
Keith Packard8b9ab102008-06-13 16:03:22 -07001000 if(drmIoctl(fd, DRM_IOCTL_RM_MAP, &map))
Brianccd7b6e2007-05-29 14:54:00 -06001001 return -errno;
Kevin E Martin74e19a42001-03-14 22:22:50 +00001002 return 0;
1003}
1004
Jose Fonsecad2443b22003-05-27 00:37:33 +00001005/**
1006 * Make buffers available for DMA transfers.
1007 *
1008 * \param fd file descriptor.
1009 * \param count number of buffers.
1010 * \param size size of each buffer.
1011 * \param flags buffer allocation flags.
1012 * \param agp_offset offset in the AGP aperture
1013 *
1014 * \return number of buffers allocated, negative on error.
1015 *
1016 * \internal
1017 * This function is a wrapper around DRM_IOCTL_ADD_BUFS ioctl.
1018 *
1019 * \sa drm_buf_desc.
1020 */
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001021int drmAddBufs(int fd, int count, int size, drmBufDescFlags flags,
1022 int agp_offset)
Daryll Straussb3a57661999-12-05 01:19:48 +00001023{
1024 drm_buf_desc_t request;
Gareth Hughes36047532001-02-15 08:12:14 +00001025
Daryll Straussb3a57661999-12-05 01:19:48 +00001026 request.count = count;
1027 request.size = size;
1028 request.low_mark = 0;
1029 request.high_mark = 0;
1030 request.flags = flags;
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001031 request.agp_start = agp_offset;
Gareth Hughes36047532001-02-15 08:12:14 +00001032
Keith Packard8b9ab102008-06-13 16:03:22 -07001033 if (drmIoctl(fd, DRM_IOCTL_ADD_BUFS, &request))
Brianccd7b6e2007-05-29 14:54:00 -06001034 return -errno;
Daryll Straussb3a57661999-12-05 01:19:48 +00001035 return request.count;
1036}
1037
1038int drmMarkBufs(int fd, double low, double high)
1039{
1040 drm_buf_info_t info;
1041 int i;
1042
1043 info.count = 0;
1044 info.list = NULL;
1045
Keith Packard8b9ab102008-06-13 16:03:22 -07001046 if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info))
Brianccd7b6e2007-05-29 14:54:00 -06001047 return -EINVAL;
Daryll Straussb3a57661999-12-05 01:19:48 +00001048
Brianccd7b6e2007-05-29 14:54:00 -06001049 if (!info.count)
1050 return -EINVAL;
Gareth Hughes36047532001-02-15 08:12:14 +00001051
Daryll Straussb3a57661999-12-05 01:19:48 +00001052 if (!(info.list = drmMalloc(info.count * sizeof(*info.list))))
1053 return -ENOMEM;
Gareth Hughes36047532001-02-15 08:12:14 +00001054
Keith Packard8b9ab102008-06-13 16:03:22 -07001055 if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info)) {
Daryll Straussb3a57661999-12-05 01:19:48 +00001056 int retval = -errno;
1057 drmFree(info.list);
1058 return retval;
1059 }
Gareth Hughes36047532001-02-15 08:12:14 +00001060
Daryll Straussb3a57661999-12-05 01:19:48 +00001061 for (i = 0; i < info.count; i++) {
1062 info.list[i].low_mark = low * info.list[i].count;
1063 info.list[i].high_mark = high * info.list[i].count;
Keith Packard8b9ab102008-06-13 16:03:22 -07001064 if (drmIoctl(fd, DRM_IOCTL_MARK_BUFS, &info.list[i])) {
Daryll Straussb3a57661999-12-05 01:19:48 +00001065 int retval = -errno;
1066 drmFree(info.list);
1067 return retval;
1068 }
1069 }
1070 drmFree(info.list);
Gareth Hughes36047532001-02-15 08:12:14 +00001071
Daryll Straussb3a57661999-12-05 01:19:48 +00001072 return 0;
1073}
1074
Jose Fonsecad2443b22003-05-27 00:37:33 +00001075/**
1076 * Free buffers.
1077 *
1078 * \param fd file descriptor.
1079 * \param count number of buffers to free.
1080 * \param list list of buffers to be freed.
1081 *
1082 * \return zero on success, or a negative value on failure.
1083 *
1084 * \note This function is primarily used for debugging.
1085 *
1086 * \internal
1087 * This function is a wrapper around the DRM_IOCTL_FREE_BUFS ioctl, passing
1088 * the arguments in a drm_buf_free structure.
1089 */
Daryll Straussb3a57661999-12-05 01:19:48 +00001090int drmFreeBufs(int fd, int count, int *list)
1091{
1092 drm_buf_free_t request;
1093
1094 request.count = count;
1095 request.list = list;
Keith Packard8b9ab102008-06-13 16:03:22 -07001096 if (drmIoctl(fd, DRM_IOCTL_FREE_BUFS, &request))
Brianccd7b6e2007-05-29 14:54:00 -06001097 return -errno;
Daryll Straussb3a57661999-12-05 01:19:48 +00001098 return 0;
1099}
1100
Jose Fonsecad2443b22003-05-27 00:37:33 +00001101
1102/**
1103 * Close the device.
1104 *
1105 * \param fd file descriptor.
1106 *
1107 * \internal
1108 * This function closes the file descriptor.
1109 */
Daryll Straussb6a28bf1999-12-05 23:10:37 +00001110int drmClose(int fd)
Daryll Straussb3a57661999-12-05 01:19:48 +00001111{
1112 unsigned long key = drmGetKeyFromFd(fd);
1113 drmHashEntry *entry = drmGetEntry(fd);
1114
1115 drmHashDestroy(entry->tagTable);
1116 entry->fd = 0;
1117 entry->f = NULL;
1118 entry->tagTable = NULL;
1119
1120 drmHashDelete(drmHashTable, key);
1121 drmFree(entry);
1122
1123 return close(fd);
1124}
1125
Jose Fonsecad2443b22003-05-27 00:37:33 +00001126
1127/**
1128 * Map a region of memory.
1129 *
1130 * \param fd file descriptor.
1131 * \param handle handle returned by drmAddMap().
1132 * \param size size in bytes. Must match the size used by drmAddMap().
1133 * \param address will contain the user-space virtual address where the mapping
1134 * begins.
1135 *
1136 * \return zero on success, or a negative value on failure.
1137 *
1138 * \internal
1139 * This function is a wrapper for mmap().
1140 */
Adam Jackson22e41ef2006-02-20 23:09:00 +00001141int drmMap(int fd, drm_handle_t handle, drmSize size, drmAddressPtr address)
Daryll Straussb3a57661999-12-05 01:19:48 +00001142{
Alan Hourihanec7558d82000-09-24 09:34:10 +00001143 static unsigned long pagesize_mask = 0;
1144
Brianccd7b6e2007-05-29 14:54:00 -06001145 if (fd < 0)
1146 return -EINVAL;
Alan Hourihanec7558d82000-09-24 09:34:10 +00001147
1148 if (!pagesize_mask)
1149 pagesize_mask = getpagesize() - 1;
1150
1151 size = (size + pagesize_mask) & ~pagesize_mask;
1152
Daryll Straussb3a57661999-12-05 01:19:48 +00001153 *address = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, handle);
Brianccd7b6e2007-05-29 14:54:00 -06001154 if (*address == MAP_FAILED)
1155 return -errno;
Daryll Straussb3a57661999-12-05 01:19:48 +00001156 return 0;
1157}
1158
Jose Fonsecad2443b22003-05-27 00:37:33 +00001159
1160/**
1161 * Unmap mappings obtained with drmMap().
1162 *
1163 * \param address address as given by drmMap().
1164 * \param size size in bytes. Must match the size used by drmMap().
1165 *
1166 * \return zero on success, or a negative value on failure.
1167 *
1168 * \internal
Adam Jackson22e41ef2006-02-20 23:09:00 +00001169 * This function is a wrapper for munmap().
Jose Fonsecad2443b22003-05-27 00:37:33 +00001170 */
Daryll Straussb3a57661999-12-05 01:19:48 +00001171int drmUnmap(drmAddress address, drmSize size)
1172{
1173 return munmap(address, size);
1174}
1175
1176drmBufInfoPtr drmGetBufInfo(int fd)
1177{
1178 drm_buf_info_t info;
1179 drmBufInfoPtr retval;
1180 int i;
1181
1182 info.count = 0;
1183 info.list = NULL;
1184
Keith Packard8b9ab102008-06-13 16:03:22 -07001185 if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info))
Brianccd7b6e2007-05-29 14:54:00 -06001186 return NULL;
Daryll Straussb3a57661999-12-05 01:19:48 +00001187
1188 if (info.count) {
1189 if (!(info.list = drmMalloc(info.count * sizeof(*info.list))))
1190 return NULL;
Gareth Hughes36047532001-02-15 08:12:14 +00001191
Keith Packard8b9ab102008-06-13 16:03:22 -07001192 if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info)) {
Daryll Straussb3a57661999-12-05 01:19:48 +00001193 drmFree(info.list);
1194 return NULL;
1195 }
Adam Jackson22e41ef2006-02-20 23:09:00 +00001196
Daryll Straussb3a57661999-12-05 01:19:48 +00001197 retval = drmMalloc(sizeof(*retval));
1198 retval->count = info.count;
1199 retval->list = drmMalloc(info.count * sizeof(*retval->list));
1200 for (i = 0; i < info.count; i++) {
1201 retval->list[i].count = info.list[i].count;
1202 retval->list[i].size = info.list[i].size;
1203 retval->list[i].low_mark = info.list[i].low_mark;
1204 retval->list[i].high_mark = info.list[i].high_mark;
1205 }
1206 drmFree(info.list);
1207 return retval;
1208 }
1209 return NULL;
1210}
1211
Jose Fonsecad2443b22003-05-27 00:37:33 +00001212/**
1213 * Map all DMA buffers into client-virtual space.
1214 *
1215 * \param fd file descriptor.
1216 *
1217 * \return a pointer to a ::drmBufMap structure.
1218 *
1219 * \note The client may not use these buffers until obtaining buffer indices
1220 * with drmDMA().
1221 *
1222 * \internal
1223 * This function calls the DRM_IOCTL_MAP_BUFS ioctl and copies the returned
1224 * information about the buffers in a drm_buf_map structure into the
1225 * client-visible data structures.
1226 */
Daryll Straussb3a57661999-12-05 01:19:48 +00001227drmBufMapPtr drmMapBufs(int fd)
1228{
1229 drm_buf_map_t bufs;
1230 drmBufMapPtr retval;
1231 int i;
Gareth Hughes36047532001-02-15 08:12:14 +00001232
Daryll Straussb3a57661999-12-05 01:19:48 +00001233 bufs.count = 0;
1234 bufs.list = NULL;
Jon Smirl8696e712004-07-07 04:36:36 +00001235 bufs.virtual = NULL;
Keith Packard8b9ab102008-06-13 16:03:22 -07001236 if (drmIoctl(fd, DRM_IOCTL_MAP_BUFS, &bufs))
Brianccd7b6e2007-05-29 14:54:00 -06001237 return NULL;
Daryll Straussb3a57661999-12-05 01:19:48 +00001238
Brianccd7b6e2007-05-29 14:54:00 -06001239 if (!bufs.count)
1240 return NULL;
Jon Smirl8696e712004-07-07 04:36:36 +00001241
Daryll Straussb3a57661999-12-05 01:19:48 +00001242 if (!(bufs.list = drmMalloc(bufs.count * sizeof(*bufs.list))))
1243 return NULL;
1244
Keith Packard8b9ab102008-06-13 16:03:22 -07001245 if (drmIoctl(fd, DRM_IOCTL_MAP_BUFS, &bufs)) {
Daryll Straussb3a57661999-12-05 01:19:48 +00001246 drmFree(bufs.list);
1247 return NULL;
1248 }
Adam Jackson22e41ef2006-02-20 23:09:00 +00001249
Daryll Straussb3a57661999-12-05 01:19:48 +00001250 retval = drmMalloc(sizeof(*retval));
1251 retval->count = bufs.count;
1252 retval->list = drmMalloc(bufs.count * sizeof(*retval->list));
1253 for (i = 0; i < bufs.count; i++) {
1254 retval->list[i].idx = bufs.list[i].idx;
1255 retval->list[i].total = bufs.list[i].total;
1256 retval->list[i].used = 0;
1257 retval->list[i].address = bufs.list[i].address;
1258 }
Jon Smirl8696e712004-07-07 04:36:36 +00001259
1260 drmFree(bufs.list);
1261
Daryll Straussb3a57661999-12-05 01:19:48 +00001262 return retval;
Daryll Straussb3a57661999-12-05 01:19:48 +00001263}
1264
Jose Fonsecad2443b22003-05-27 00:37:33 +00001265
1266/**
1267 * Unmap buffers allocated with drmMapBufs().
1268 *
1269 * \return zero on success, or negative value on failure.
1270 *
1271 * \internal
Jon Smirl8696e712004-07-07 04:36:36 +00001272 * Calls munmap() for every buffer stored in \p bufs and frees the
1273 * memory allocated by drmMapBufs().
Jose Fonsecad2443b22003-05-27 00:37:33 +00001274 */
Daryll Straussb3a57661999-12-05 01:19:48 +00001275int drmUnmapBufs(drmBufMapPtr bufs)
1276{
1277 int i;
Gareth Hughes36047532001-02-15 08:12:14 +00001278
Daryll Straussb3a57661999-12-05 01:19:48 +00001279 for (i = 0; i < bufs->count; i++) {
1280 munmap(bufs->list[i].address, bufs->list[i].total);
1281 }
Jon Smirl8696e712004-07-07 04:36:36 +00001282
1283 drmFree(bufs->list);
1284 drmFree(bufs);
1285
Daryll Straussb3a57661999-12-05 01:19:48 +00001286 return 0;
1287}
1288
Jose Fonsecad2443b22003-05-27 00:37:33 +00001289
Gareth Hughes36047532001-02-15 08:12:14 +00001290#define DRM_DMA_RETRY 16
1291
Jose Fonsecad2443b22003-05-27 00:37:33 +00001292/**
1293 * Reserve DMA buffers.
1294 *
1295 * \param fd file descriptor.
1296 * \param request
1297 *
1298 * \return zero on success, or a negative value on failure.
1299 *
1300 * \internal
1301 * Assemble the arguments into a drm_dma structure and keeps issuing the
1302 * DRM_IOCTL_DMA ioctl until success or until maximum number of retries.
1303 */
Daryll Straussb3a57661999-12-05 01:19:48 +00001304int drmDMA(int fd, drmDMAReqPtr request)
1305{
1306 drm_dma_t dma;
Gareth Hughes36047532001-02-15 08:12:14 +00001307 int ret, i = 0;
Daryll Straussb3a57661999-12-05 01:19:48 +00001308
Daryll Straussb3a57661999-12-05 01:19:48 +00001309 dma.context = request->context;
1310 dma.send_count = request->send_count;
1311 dma.send_indices = request->send_list;
1312 dma.send_sizes = request->send_sizes;
1313 dma.flags = request->flags;
1314 dma.request_count = request->request_count;
1315 dma.request_size = request->request_size;
1316 dma.request_indices = request->request_list;
1317 dma.request_sizes = request->request_sizes;
Jon Smirl8696e712004-07-07 04:36:36 +00001318 dma.granted_count = 0;
Gareth Hughes36047532001-02-15 08:12:14 +00001319
1320 do {
1321 ret = ioctl( fd, DRM_IOCTL_DMA, &dma );
1322 } while ( ret && errno == EAGAIN && i++ < DRM_DMA_RETRY );
1323
1324 if ( ret == 0 ) {
1325 request->granted_count = dma.granted_count;
1326 return 0;
1327 } else {
1328 return -errno;
1329 }
Daryll Straussb3a57661999-12-05 01:19:48 +00001330}
1331
Jose Fonsecad2443b22003-05-27 00:37:33 +00001332
1333/**
1334 * Obtain heavyweight hardware lock.
1335 *
1336 * \param fd file descriptor.
1337 * \param context context.
1338 * \param flags flags that determine the sate of the hardware when the function
1339 * returns.
1340 *
1341 * \return always zero.
1342 *
1343 * \internal
1344 * This function translates the arguments into a drm_lock structure and issue
1345 * the DRM_IOCTL_LOCK ioctl until the lock is successfully acquired.
1346 */
Jon Smirl8696e712004-07-07 04:36:36 +00001347int drmGetLock(int fd, drm_context_t context, drmLockFlags flags)
Daryll Straussb3a57661999-12-05 01:19:48 +00001348{
1349 drm_lock_t lock;
1350
1351 lock.context = context;
1352 lock.flags = 0;
1353 if (flags & DRM_LOCK_READY) lock.flags |= _DRM_LOCK_READY;
1354 if (flags & DRM_LOCK_QUIESCENT) lock.flags |= _DRM_LOCK_QUIESCENT;
1355 if (flags & DRM_LOCK_FLUSH) lock.flags |= _DRM_LOCK_FLUSH;
1356 if (flags & DRM_LOCK_FLUSH_ALL) lock.flags |= _DRM_LOCK_FLUSH_ALL;
1357 if (flags & DRM_HALT_ALL_QUEUES) lock.flags |= _DRM_HALT_ALL_QUEUES;
1358 if (flags & DRM_HALT_CUR_QUEUES) lock.flags |= _DRM_HALT_CUR_QUEUES;
Gareth Hughes36047532001-02-15 08:12:14 +00001359
Keith Packard8b9ab102008-06-13 16:03:22 -07001360 while (drmIoctl(fd, DRM_IOCTL_LOCK, &lock))
Daryll Straussb3a57661999-12-05 01:19:48 +00001361 ;
1362 return 0;
1363}
1364
Jose Fonsecad2443b22003-05-27 00:37:33 +00001365/**
1366 * Release the hardware lock.
1367 *
1368 * \param fd file descriptor.
1369 * \param context context.
1370 *
1371 * \return zero on success, or a negative value on failure.
1372 *
1373 * \internal
1374 * This function is a wrapper around the DRM_IOCTL_UNLOCK ioctl, passing the
1375 * argument in a drm_lock structure.
1376 */
Jon Smirl8696e712004-07-07 04:36:36 +00001377int drmUnlock(int fd, drm_context_t context)
Daryll Straussb3a57661999-12-05 01:19:48 +00001378{
1379 drm_lock_t lock;
1380
1381 lock.context = context;
1382 lock.flags = 0;
Keith Packard8b9ab102008-06-13 16:03:22 -07001383 return drmIoctl(fd, DRM_IOCTL_UNLOCK, &lock);
Daryll Straussb3a57661999-12-05 01:19:48 +00001384}
1385
Adam Jackson22e41ef2006-02-20 23:09:00 +00001386drm_context_t *drmGetReservedContextList(int fd, int *count)
Daryll Straussb3a57661999-12-05 01:19:48 +00001387{
1388 drm_ctx_res_t res;
1389 drm_ctx_t *list;
Jon Smirl8696e712004-07-07 04:36:36 +00001390 drm_context_t * retval;
Daryll Straussb3a57661999-12-05 01:19:48 +00001391 int i;
1392
1393 res.count = 0;
1394 res.contexts = NULL;
Keith Packard8b9ab102008-06-13 16:03:22 -07001395 if (drmIoctl(fd, DRM_IOCTL_RES_CTX, &res))
Brianccd7b6e2007-05-29 14:54:00 -06001396 return NULL;
Daryll Straussb3a57661999-12-05 01:19:48 +00001397
Brianccd7b6e2007-05-29 14:54:00 -06001398 if (!res.count)
1399 return NULL;
Daryll Straussb3a57661999-12-05 01:19:48 +00001400
Brianccd7b6e2007-05-29 14:54:00 -06001401 if (!(list = drmMalloc(res.count * sizeof(*list))))
1402 return NULL;
Daryll Straussb3a57661999-12-05 01:19:48 +00001403 if (!(retval = drmMalloc(res.count * sizeof(*retval)))) {
1404 drmFree(list);
1405 return NULL;
1406 }
1407
1408 res.contexts = list;
Keith Packard8b9ab102008-06-13 16:03:22 -07001409 if (drmIoctl(fd, DRM_IOCTL_RES_CTX, &res))
Brianccd7b6e2007-05-29 14:54:00 -06001410 return NULL;
Daryll Straussb3a57661999-12-05 01:19:48 +00001411
Brianccd7b6e2007-05-29 14:54:00 -06001412 for (i = 0; i < res.count; i++)
1413 retval[i] = list[i].handle;
Daryll Straussb3a57661999-12-05 01:19:48 +00001414 drmFree(list);
1415
1416 *count = res.count;
1417 return retval;
1418}
1419
Adam Jackson22e41ef2006-02-20 23:09:00 +00001420void drmFreeReservedContextList(drm_context_t *pt)
Daryll Straussb3a57661999-12-05 01:19:48 +00001421{
1422 drmFree(pt);
1423}
1424
Jose Fonsecad2443b22003-05-27 00:37:33 +00001425/**
1426 * Create context.
1427 *
1428 * Used by the X server during GLXContext initialization. This causes
1429 * per-context kernel-level resources to be allocated.
1430 *
1431 * \param fd file descriptor.
1432 * \param handle is set on success. To be used by the client when requesting DMA
1433 * dispatch with drmDMA().
1434 *
1435 * \return zero on success, or a negative value on failure.
1436 *
1437 * \note May only be called by root.
1438 *
1439 * \internal
1440 * This function is a wrapper around the DRM_IOCTL_ADD_CTX ioctl, passing the
1441 * argument in a drm_ctx structure.
1442 */
Adam Jackson22e41ef2006-02-20 23:09:00 +00001443int drmCreateContext(int fd, drm_context_t *handle)
Daryll Straussb3a57661999-12-05 01:19:48 +00001444{
1445 drm_ctx_t ctx;
1446
1447 ctx.flags = 0; /* Modified with functions below */
Keith Packard8b9ab102008-06-13 16:03:22 -07001448 if (drmIoctl(fd, DRM_IOCTL_ADD_CTX, &ctx))
Brianccd7b6e2007-05-29 14:54:00 -06001449 return -errno;
Daryll Straussb3a57661999-12-05 01:19:48 +00001450 *handle = ctx.handle;
1451 return 0;
1452}
1453
Jon Smirl8696e712004-07-07 04:36:36 +00001454int drmSwitchToContext(int fd, drm_context_t context)
Daryll Straussb3a57661999-12-05 01:19:48 +00001455{
1456 drm_ctx_t ctx;
1457
1458 ctx.handle = context;
Keith Packard8b9ab102008-06-13 16:03:22 -07001459 if (drmIoctl(fd, DRM_IOCTL_SWITCH_CTX, &ctx))
Brianccd7b6e2007-05-29 14:54:00 -06001460 return -errno;
Daryll Straussb3a57661999-12-05 01:19:48 +00001461 return 0;
1462}
1463
Jon Smirl8696e712004-07-07 04:36:36 +00001464int drmSetContextFlags(int fd, drm_context_t context, drm_context_tFlags flags)
Daryll Straussb3a57661999-12-05 01:19:48 +00001465{
1466 drm_ctx_t ctx;
1467
Adam Jackson22e41ef2006-02-20 23:09:00 +00001468 /*
1469 * Context preserving means that no context switches are done between DMA
1470 * buffers from one context and the next. This is suitable for use in the
1471 * X server (which promises to maintain hardware context), or in the
1472 * client-side library when buffers are swapped on behalf of two threads.
1473 */
Daryll Straussb3a57661999-12-05 01:19:48 +00001474 ctx.handle = context;
1475 ctx.flags = 0;
Brianccd7b6e2007-05-29 14:54:00 -06001476 if (flags & DRM_CONTEXT_PRESERVED)
1477 ctx.flags |= _DRM_CONTEXT_PRESERVED;
1478 if (flags & DRM_CONTEXT_2DONLY)
1479 ctx.flags |= _DRM_CONTEXT_2DONLY;
Keith Packard8b9ab102008-06-13 16:03:22 -07001480 if (drmIoctl(fd, DRM_IOCTL_MOD_CTX, &ctx))
Brianccd7b6e2007-05-29 14:54:00 -06001481 return -errno;
Daryll Straussb3a57661999-12-05 01:19:48 +00001482 return 0;
1483}
1484
Adam Jackson22e41ef2006-02-20 23:09:00 +00001485int drmGetContextFlags(int fd, drm_context_t context,
1486 drm_context_tFlagsPtr flags)
Daryll Straussb3a57661999-12-05 01:19:48 +00001487{
1488 drm_ctx_t ctx;
1489
1490 ctx.handle = context;
Keith Packard8b9ab102008-06-13 16:03:22 -07001491 if (drmIoctl(fd, DRM_IOCTL_GET_CTX, &ctx))
Brianccd7b6e2007-05-29 14:54:00 -06001492 return -errno;
Daryll Straussb3a57661999-12-05 01:19:48 +00001493 *flags = 0;
Brianccd7b6e2007-05-29 14:54:00 -06001494 if (ctx.flags & _DRM_CONTEXT_PRESERVED)
1495 *flags |= DRM_CONTEXT_PRESERVED;
1496 if (ctx.flags & _DRM_CONTEXT_2DONLY)
1497 *flags |= DRM_CONTEXT_2DONLY;
Daryll Straussb3a57661999-12-05 01:19:48 +00001498 return 0;
1499}
Gareth Hughes36047532001-02-15 08:12:14 +00001500
Jose Fonsecad2443b22003-05-27 00:37:33 +00001501/**
1502 * Destroy context.
1503 *
1504 * Free any kernel-level resources allocated with drmCreateContext() associated
1505 * with the context.
1506 *
1507 * \param fd file descriptor.
1508 * \param handle handle given by drmCreateContext().
1509 *
1510 * \return zero on success, or a negative value on failure.
1511 *
1512 * \note May only be called by root.
1513 *
1514 * \internal
1515 * This function is a wrapper around the DRM_IOCTL_RM_CTX ioctl, passing the
1516 * argument in a drm_ctx structure.
1517 */
Jon Smirl8696e712004-07-07 04:36:36 +00001518int drmDestroyContext(int fd, drm_context_t handle)
Daryll Straussb3a57661999-12-05 01:19:48 +00001519{
1520 drm_ctx_t ctx;
1521 ctx.handle = handle;
Keith Packard8b9ab102008-06-13 16:03:22 -07001522 if (drmIoctl(fd, DRM_IOCTL_RM_CTX, &ctx))
Brianccd7b6e2007-05-29 14:54:00 -06001523 return -errno;
Daryll Straussb3a57661999-12-05 01:19:48 +00001524 return 0;
1525}
1526
Adam Jackson22e41ef2006-02-20 23:09:00 +00001527int drmCreateDrawable(int fd, drm_drawable_t *handle)
Daryll Straussb3a57661999-12-05 01:19:48 +00001528{
1529 drm_draw_t draw;
Keith Packard8b9ab102008-06-13 16:03:22 -07001530 if (drmIoctl(fd, DRM_IOCTL_ADD_DRAW, &draw))
Brianccd7b6e2007-05-29 14:54:00 -06001531 return -errno;
Daryll Straussb3a57661999-12-05 01:19:48 +00001532 *handle = draw.handle;
1533 return 0;
1534}
1535
Jon Smirl8696e712004-07-07 04:36:36 +00001536int drmDestroyDrawable(int fd, drm_drawable_t handle)
Daryll Straussb3a57661999-12-05 01:19:48 +00001537{
1538 drm_draw_t draw;
1539 draw.handle = handle;
Keith Packard8b9ab102008-06-13 16:03:22 -07001540 if (drmIoctl(fd, DRM_IOCTL_RM_DRAW, &draw))
Brianccd7b6e2007-05-29 14:54:00 -06001541 return -errno;
Daryll Straussb3a57661999-12-05 01:19:48 +00001542 return 0;
1543}
1544
Michel Dänzer9810ec22006-08-22 16:40:07 +02001545int drmUpdateDrawableInfo(int fd, drm_drawable_t handle,
1546 drm_drawable_info_type_t type, unsigned int num,
1547 void *data)
1548{
1549 drm_update_draw_t update;
1550
1551 update.handle = handle;
1552 update.type = type;
1553 update.num = num;
1554 update.data = (unsigned long long)(unsigned long)data;
1555
Keith Packard8b9ab102008-06-13 16:03:22 -07001556 if (drmIoctl(fd, DRM_IOCTL_UPDATE_DRAW, &update))
Brianccd7b6e2007-05-29 14:54:00 -06001557 return -errno;
Michel Dänzer9810ec22006-08-22 16:40:07 +02001558
1559 return 0;
1560}
1561
Jose Fonsecad2443b22003-05-27 00:37:33 +00001562/**
1563 * Acquire the AGP device.
1564 *
1565 * Must be called before any of the other AGP related calls.
1566 *
1567 * \param fd file descriptor.
1568 *
1569 * \return zero on success, or a negative value on failure.
1570 *
1571 * \internal
1572 * This function is a wrapper around the DRM_IOCTL_AGP_ACQUIRE ioctl.
1573 */
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001574int drmAgpAcquire(int fd)
1575{
Keith Packard8b9ab102008-06-13 16:03:22 -07001576 if (drmIoctl(fd, DRM_IOCTL_AGP_ACQUIRE, NULL))
Brianccd7b6e2007-05-29 14:54:00 -06001577 return -errno;
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001578 return 0;
1579}
1580
Jose Fonsecad2443b22003-05-27 00:37:33 +00001581
1582/**
1583 * Release the AGP device.
1584 *
1585 * \param fd file descriptor.
1586 *
1587 * \return zero on success, or a negative value on failure.
1588 *
1589 * \internal
1590 * This function is a wrapper around the DRM_IOCTL_AGP_RELEASE ioctl.
1591 */
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001592int drmAgpRelease(int fd)
1593{
Keith Packard8b9ab102008-06-13 16:03:22 -07001594 if (drmIoctl(fd, DRM_IOCTL_AGP_RELEASE, NULL))
Brianccd7b6e2007-05-29 14:54:00 -06001595 return -errno;
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001596 return 0;
1597}
1598
Jose Fonsecad2443b22003-05-27 00:37:33 +00001599
1600/**
1601 * Set the AGP mode.
1602 *
1603 * \param fd file descriptor.
1604 * \param mode AGP mode.
1605 *
1606 * \return zero on success, or a negative value on failure.
1607 *
1608 * \internal
1609 * This function is a wrapper around the DRM_IOCTL_AGP_ENABLE ioctl, passing the
1610 * argument in a drm_agp_mode structure.
1611 */
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001612int drmAgpEnable(int fd, unsigned long mode)
1613{
1614 drm_agp_mode_t m;
1615
1616 m.mode = mode;
Keith Packard8b9ab102008-06-13 16:03:22 -07001617 if (drmIoctl(fd, DRM_IOCTL_AGP_ENABLE, &m))
Brianccd7b6e2007-05-29 14:54:00 -06001618 return -errno;
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001619 return 0;
1620}
1621
Jose Fonsecad2443b22003-05-27 00:37:33 +00001622
1623/**
1624 * Allocate a chunk of AGP memory.
1625 *
1626 * \param fd file descriptor.
1627 * \param size requested memory size in bytes. Will be rounded to page boundary.
1628 * \param type type of memory to allocate.
1629 * \param address if not zero, will be set to the physical address of the
1630 * allocated memory.
1631 * \param handle on success will be set to a handle of the allocated memory.
1632 *
1633 * \return zero on success, or a negative value on failure.
1634 *
1635 * \internal
1636 * This function is a wrapper around the DRM_IOCTL_AGP_ALLOC ioctl, passing the
1637 * arguments in a drm_agp_buffer structure.
1638 */
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001639int drmAgpAlloc(int fd, unsigned long size, unsigned long type,
Dave Airlie7ede2092005-11-29 09:50:47 +00001640 unsigned long *address, drm_handle_t *handle)
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001641{
1642 drm_agp_buffer_t b;
Alan Hourihaneb0a92852003-09-24 14:39:25 +00001643
1644 *handle = DRM_AGP_NO_HANDLE;
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001645 b.size = size;
1646 b.handle = 0;
1647 b.type = type;
Keith Packard8b9ab102008-06-13 16:03:22 -07001648 if (drmIoctl(fd, DRM_IOCTL_AGP_ALLOC, &b))
Brianccd7b6e2007-05-29 14:54:00 -06001649 return -errno;
1650 if (address != 0UL)
1651 *address = b.physical;
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001652 *handle = b.handle;
1653 return 0;
1654}
1655
Jose Fonsecad2443b22003-05-27 00:37:33 +00001656
1657/**
1658 * Free a chunk of AGP memory.
1659 *
1660 * \param fd file descriptor.
1661 * \param handle handle to the allocated memory, as given by drmAgpAllocate().
1662 *
1663 * \return zero on success, or a negative value on failure.
1664 *
1665 * \internal
1666 * This function is a wrapper around the DRM_IOCTL_AGP_FREE ioctl, passing the
1667 * argument in a drm_agp_buffer structure.
1668 */
Dave Airlie7ede2092005-11-29 09:50:47 +00001669int drmAgpFree(int fd, drm_handle_t handle)
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001670{
1671 drm_agp_buffer_t b;
1672
1673 b.size = 0;
1674 b.handle = handle;
Keith Packard8b9ab102008-06-13 16:03:22 -07001675 if (drmIoctl(fd, DRM_IOCTL_AGP_FREE, &b))
Brianccd7b6e2007-05-29 14:54:00 -06001676 return -errno;
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001677 return 0;
1678}
1679
Jose Fonsecad2443b22003-05-27 00:37:33 +00001680
1681/**
1682 * Bind a chunk of AGP memory.
1683 *
1684 * \param fd file descriptor.
1685 * \param handle handle to the allocated memory, as given by drmAgpAllocate().
1686 * \param offset offset in bytes. It will round to page boundary.
1687 *
1688 * \return zero on success, or a negative value on failure.
1689 *
1690 * \internal
1691 * This function is a wrapper around the DRM_IOCTL_AGP_BIND ioctl, passing the
1692 * argument in a drm_agp_binding structure.
1693 */
Dave Airlie7ede2092005-11-29 09:50:47 +00001694int drmAgpBind(int fd, drm_handle_t handle, unsigned long offset)
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001695{
1696 drm_agp_binding_t b;
1697
1698 b.handle = handle;
1699 b.offset = offset;
Keith Packard8b9ab102008-06-13 16:03:22 -07001700 if (drmIoctl(fd, DRM_IOCTL_AGP_BIND, &b))
Brianccd7b6e2007-05-29 14:54:00 -06001701 return -errno;
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001702 return 0;
1703}
1704
Jose Fonsecad2443b22003-05-27 00:37:33 +00001705
1706/**
1707 * Unbind a chunk of AGP memory.
1708 *
1709 * \param fd file descriptor.
1710 * \param handle handle to the allocated memory, as given by drmAgpAllocate().
1711 *
1712 * \return zero on success, or a negative value on failure.
1713 *
1714 * \internal
1715 * This function is a wrapper around the DRM_IOCTL_AGP_UNBIND ioctl, passing
1716 * the argument in a drm_agp_binding structure.
1717 */
Dave Airlie7ede2092005-11-29 09:50:47 +00001718int drmAgpUnbind(int fd, drm_handle_t handle)
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001719{
1720 drm_agp_binding_t b;
1721
1722 b.handle = handle;
1723 b.offset = 0;
Keith Packard8b9ab102008-06-13 16:03:22 -07001724 if (drmIoctl(fd, DRM_IOCTL_AGP_UNBIND, &b))
Brianccd7b6e2007-05-29 14:54:00 -06001725 return -errno;
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001726 return 0;
1727}
1728
Jose Fonsecad2443b22003-05-27 00:37:33 +00001729
1730/**
1731 * Get AGP driver major version number.
1732 *
1733 * \param fd file descriptor.
1734 *
1735 * \return major version number on success, or a negative value on failure..
1736 *
1737 * \internal
1738 * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1739 * necessary information in a drm_agp_info structure.
1740 */
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001741int drmAgpVersionMajor(int fd)
1742{
1743 drm_agp_info_t i;
1744
Keith Packard8b9ab102008-06-13 16:03:22 -07001745 if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
Brianccd7b6e2007-05-29 14:54:00 -06001746 return -errno;
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001747 return i.agp_version_major;
1748}
1749
Jose Fonsecad2443b22003-05-27 00:37:33 +00001750
1751/**
1752 * Get AGP driver minor version number.
1753 *
1754 * \param fd file descriptor.
1755 *
1756 * \return minor version number on success, or a negative value on failure.
1757 *
1758 * \internal
1759 * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1760 * necessary information in a drm_agp_info structure.
1761 */
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001762int drmAgpVersionMinor(int fd)
1763{
1764 drm_agp_info_t i;
1765
Keith Packard8b9ab102008-06-13 16:03:22 -07001766 if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
Brianccd7b6e2007-05-29 14:54:00 -06001767 return -errno;
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001768 return i.agp_version_minor;
1769}
1770
Jose Fonsecad2443b22003-05-27 00:37:33 +00001771
1772/**
1773 * Get AGP mode.
1774 *
1775 * \param fd file descriptor.
1776 *
1777 * \return mode on success, or zero on failure.
1778 *
1779 * \internal
1780 * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1781 * necessary information in a drm_agp_info structure.
1782 */
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001783unsigned long drmAgpGetMode(int fd)
1784{
1785 drm_agp_info_t i;
1786
Keith Packard8b9ab102008-06-13 16:03:22 -07001787 if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
Brianccd7b6e2007-05-29 14:54:00 -06001788 return 0;
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001789 return i.mode;
1790}
1791
Jose Fonsecad2443b22003-05-27 00:37:33 +00001792
1793/**
1794 * Get AGP aperture base.
1795 *
1796 * \param fd file descriptor.
1797 *
1798 * \return aperture base on success, zero on failure.
1799 *
1800 * \internal
1801 * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1802 * necessary information in a drm_agp_info structure.
1803 */
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001804unsigned long drmAgpBase(int fd)
1805{
1806 drm_agp_info_t i;
1807
Keith Packard8b9ab102008-06-13 16:03:22 -07001808 if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
Brianccd7b6e2007-05-29 14:54:00 -06001809 return 0;
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001810 return i.aperture_base;
1811}
1812
Jose Fonsecad2443b22003-05-27 00:37:33 +00001813
1814/**
1815 * Get AGP aperture size.
1816 *
1817 * \param fd file descriptor.
1818 *
1819 * \return aperture size on success, zero on failure.
1820 *
1821 * \internal
1822 * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1823 * necessary information in a drm_agp_info structure.
1824 */
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001825unsigned long drmAgpSize(int fd)
1826{
1827 drm_agp_info_t i;
1828
Keith Packard8b9ab102008-06-13 16:03:22 -07001829 if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
Brianccd7b6e2007-05-29 14:54:00 -06001830 return 0;
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001831 return i.aperture_size;
1832}
1833
Jose Fonsecad2443b22003-05-27 00:37:33 +00001834
1835/**
1836 * Get used AGP memory.
1837 *
1838 * \param fd file descriptor.
1839 *
1840 * \return memory used on success, or zero on failure.
1841 *
1842 * \internal
1843 * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1844 * necessary information in a drm_agp_info structure.
1845 */
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001846unsigned long drmAgpMemoryUsed(int fd)
1847{
1848 drm_agp_info_t i;
1849
Keith Packard8b9ab102008-06-13 16:03:22 -07001850 if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
Brianccd7b6e2007-05-29 14:54:00 -06001851 return 0;
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001852 return i.memory_used;
1853}
1854
Jose Fonsecad2443b22003-05-27 00:37:33 +00001855
1856/**
1857 * Get available AGP memory.
1858 *
1859 * \param fd file descriptor.
1860 *
1861 * \return memory available on success, or zero on failure.
1862 *
1863 * \internal
1864 * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1865 * necessary information in a drm_agp_info structure.
1866 */
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001867unsigned long drmAgpMemoryAvail(int fd)
1868{
1869 drm_agp_info_t i;
1870
Keith Packard8b9ab102008-06-13 16:03:22 -07001871 if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
Brianccd7b6e2007-05-29 14:54:00 -06001872 return 0;
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001873 return i.memory_allowed;
1874}
1875
Jose Fonsecad2443b22003-05-27 00:37:33 +00001876
1877/**
1878 * Get hardware vendor ID.
1879 *
1880 * \param fd file descriptor.
1881 *
1882 * \return vendor ID on success, or zero on failure.
1883 *
1884 * \internal
1885 * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1886 * necessary information in a drm_agp_info structure.
1887 */
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001888unsigned int drmAgpVendorId(int fd)
1889{
1890 drm_agp_info_t i;
1891
Keith Packard8b9ab102008-06-13 16:03:22 -07001892 if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
Brianccd7b6e2007-05-29 14:54:00 -06001893 return 0;
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001894 return i.id_vendor;
1895}
1896
Jose Fonsecad2443b22003-05-27 00:37:33 +00001897
1898/**
1899 * Get hardware device ID.
1900 *
1901 * \param fd file descriptor.
1902 *
1903 * \return zero on success, or zero on failure.
1904 *
1905 * \internal
1906 * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1907 * necessary information in a drm_agp_info structure.
1908 */
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001909unsigned int drmAgpDeviceId(int fd)
1910{
1911 drm_agp_info_t i;
1912
Keith Packard8b9ab102008-06-13 16:03:22 -07001913 if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
Brianccd7b6e2007-05-29 14:54:00 -06001914 return 0;
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001915 return i.id_device;
1916}
1917
Dave Airlie7ede2092005-11-29 09:50:47 +00001918int drmScatterGatherAlloc(int fd, unsigned long size, drm_handle_t *handle)
Kevin E Martin5d6ddbc2001-04-05 22:16:12 +00001919{
1920 drm_scatter_gather_t sg;
1921
1922 *handle = 0;
1923 sg.size = size;
1924 sg.handle = 0;
Keith Packard8b9ab102008-06-13 16:03:22 -07001925 if (drmIoctl(fd, DRM_IOCTL_SG_ALLOC, &sg))
Brianccd7b6e2007-05-29 14:54:00 -06001926 return -errno;
Kevin E Martin5d6ddbc2001-04-05 22:16:12 +00001927 *handle = sg.handle;
1928 return 0;
1929}
1930
Dave Airlie7ede2092005-11-29 09:50:47 +00001931int drmScatterGatherFree(int fd, drm_handle_t handle)
Kevin E Martin5d6ddbc2001-04-05 22:16:12 +00001932{
1933 drm_scatter_gather_t sg;
1934
1935 sg.size = 0;
1936 sg.handle = handle;
Keith Packard8b9ab102008-06-13 16:03:22 -07001937 if (drmIoctl(fd, DRM_IOCTL_SG_FREE, &sg))
Brianccd7b6e2007-05-29 14:54:00 -06001938 return -errno;
Kevin E Martin5d6ddbc2001-04-05 22:16:12 +00001939 return 0;
1940}
1941
Jose Fonsecad2443b22003-05-27 00:37:33 +00001942/**
1943 * Wait for VBLANK.
1944 *
1945 * \param fd file descriptor.
1946 * \param vbl pointer to a drmVBlank structure.
1947 *
1948 * \return zero on success, or a negative value on failure.
1949 *
1950 * \internal
1951 * This function is a wrapper around the DRM_IOCTL_WAIT_VBLANK ioctl.
1952 */
Michel Daenzer55acd0d2002-09-25 17:18:19 +00001953int drmWaitVBlank(int fd, drmVBlankPtr vbl)
1954{
Jesse Barnesf4f76a62009-01-07 10:18:08 -08001955 struct timespec timeout, cur;
Michel Daenzer55acd0d2002-09-25 17:18:19 +00001956 int ret;
1957
Jesse Barnesf4f76a62009-01-07 10:18:08 -08001958 ret = clock_gettime(CLOCK_MONOTONIC, &timeout);
1959 if (ret < 0) {
Daniel Kurtz1eb28602013-03-28 14:05:40 +08001960 fprintf(stderr, "clock_gettime failed: %s\n", strerror(errno));
Jesse Barnesf4f76a62009-01-07 10:18:08 -08001961 goto out;
1962 }
1963 timeout.tv_sec++;
1964
Michel Daenzer55acd0d2002-09-25 17:18:19 +00001965 do {
Jesse Barnesf4f76a62009-01-07 10:18:08 -08001966 ret = ioctl(fd, DRM_IOCTL_WAIT_VBLANK, vbl);
Michel Daenzerc7d471b2003-02-02 03:06:47 +00001967 vbl->request.type &= ~DRM_VBLANK_RELATIVE;
Jesse Barnesca370772009-01-07 10:48:26 -08001968 if (ret && errno == EINTR) {
1969 clock_gettime(CLOCK_MONOTONIC, &cur);
1970 /* Timeout after 1s */
1971 if (cur.tv_sec > timeout.tv_sec + 1 ||
1972 (cur.tv_sec == timeout.tv_sec && cur.tv_nsec >=
1973 timeout.tv_nsec)) {
1974 errno = EBUSY;
1975 ret = -1;
1976 break;
1977 }
Jesse Barnesf4f76a62009-01-07 10:18:08 -08001978 }
Michel Daenzer55acd0d2002-09-25 17:18:19 +00001979 } while (ret && errno == EINTR);
1980
Jesse Barnesf4f76a62009-01-07 10:18:08 -08001981out:
Michel Daenzer55acd0d2002-09-25 17:18:19 +00001982 return ret;
1983}
1984
Daryll Straussb3a57661999-12-05 01:19:48 +00001985int drmError(int err, const char *label)
1986{
1987 switch (err) {
Brianccd7b6e2007-05-29 14:54:00 -06001988 case DRM_ERR_NO_DEVICE:
1989 fprintf(stderr, "%s: no device\n", label);
1990 break;
1991 case DRM_ERR_NO_ACCESS:
1992 fprintf(stderr, "%s: no access\n", label);
1993 break;
1994 case DRM_ERR_NOT_ROOT:
1995 fprintf(stderr, "%s: not root\n", label);
1996 break;
1997 case DRM_ERR_INVALID:
1998 fprintf(stderr, "%s: invalid args\n", label);
1999 break;
Daryll Straussb3a57661999-12-05 01:19:48 +00002000 default:
Brianccd7b6e2007-05-29 14:54:00 -06002001 if (err < 0)
2002 err = -err;
Daryll Straussb3a57661999-12-05 01:19:48 +00002003 fprintf( stderr, "%s: error %d (%s)\n", label, err, strerror(err) );
2004 break;
2005 }
2006
2007 return 1;
2008}
2009
Jose Fonsecad2443b22003-05-27 00:37:33 +00002010/**
2011 * Install IRQ handler.
2012 *
2013 * \param fd file descriptor.
2014 * \param irq IRQ number.
2015 *
2016 * \return zero on success, or a negative value on failure.
2017 *
2018 * \internal
2019 * This function is a wrapper around the DRM_IOCTL_CONTROL ioctl, passing the
2020 * argument in a drm_control structure.
2021 */
Daryll Straussb3a57661999-12-05 01:19:48 +00002022int drmCtlInstHandler(int fd, int irq)
2023{
2024 drm_control_t ctl;
2025
2026 ctl.func = DRM_INST_HANDLER;
Daryll Straussb3a57661999-12-05 01:19:48 +00002027 ctl.irq = irq;
Keith Packard8b9ab102008-06-13 16:03:22 -07002028 if (drmIoctl(fd, DRM_IOCTL_CONTROL, &ctl))
Brianccd7b6e2007-05-29 14:54:00 -06002029 return -errno;
Daryll Straussb3a57661999-12-05 01:19:48 +00002030 return 0;
2031}
2032
Jose Fonsecad2443b22003-05-27 00:37:33 +00002033
2034/**
2035 * Uninstall IRQ handler.
2036 *
2037 * \param fd file descriptor.
2038 *
2039 * \return zero on success, or a negative value on failure.
2040 *
2041 * \internal
2042 * This function is a wrapper around the DRM_IOCTL_CONTROL ioctl, passing the
2043 * argument in a drm_control structure.
2044 */
Daryll Straussb3a57661999-12-05 01:19:48 +00002045int drmCtlUninstHandler(int fd)
2046{
2047 drm_control_t ctl;
2048
2049 ctl.func = DRM_UNINST_HANDLER;
Daryll Straussb3a57661999-12-05 01:19:48 +00002050 ctl.irq = 0;
Keith Packard8b9ab102008-06-13 16:03:22 -07002051 if (drmIoctl(fd, DRM_IOCTL_CONTROL, &ctl))
Brianccd7b6e2007-05-29 14:54:00 -06002052 return -errno;
Daryll Straussb3a57661999-12-05 01:19:48 +00002053 return 0;
2054}
2055
2056int drmFinish(int fd, int context, drmLockFlags flags)
2057{
2058 drm_lock_t lock;
2059
2060 lock.context = context;
2061 lock.flags = 0;
2062 if (flags & DRM_LOCK_READY) lock.flags |= _DRM_LOCK_READY;
2063 if (flags & DRM_LOCK_QUIESCENT) lock.flags |= _DRM_LOCK_QUIESCENT;
2064 if (flags & DRM_LOCK_FLUSH) lock.flags |= _DRM_LOCK_FLUSH;
2065 if (flags & DRM_LOCK_FLUSH_ALL) lock.flags |= _DRM_LOCK_FLUSH_ALL;
2066 if (flags & DRM_HALT_ALL_QUEUES) lock.flags |= _DRM_HALT_ALL_QUEUES;
2067 if (flags & DRM_HALT_CUR_QUEUES) lock.flags |= _DRM_HALT_CUR_QUEUES;
Keith Packard8b9ab102008-06-13 16:03:22 -07002068 if (drmIoctl(fd, DRM_IOCTL_FINISH, &lock))
Brianccd7b6e2007-05-29 14:54:00 -06002069 return -errno;
Daryll Straussb3a57661999-12-05 01:19:48 +00002070 return 0;
2071}
2072
Jose Fonsecad2443b22003-05-27 00:37:33 +00002073/**
2074 * Get IRQ from bus ID.
2075 *
2076 * \param fd file descriptor.
2077 * \param busnum bus number.
2078 * \param devnum device number.
2079 * \param funcnum function number.
2080 *
2081 * \return IRQ number on success, or a negative value on failure.
2082 *
2083 * \internal
2084 * This function is a wrapper around the DRM_IOCTL_IRQ_BUSID ioctl, passing the
2085 * arguments in a drm_irq_busid structure.
2086 */
Daryll Straussb3a57661999-12-05 01:19:48 +00002087int drmGetInterruptFromBusID(int fd, int busnum, int devnum, int funcnum)
2088{
2089 drm_irq_busid_t p;
2090
2091 p.busnum = busnum;
2092 p.devnum = devnum;
2093 p.funcnum = funcnum;
Keith Packard8b9ab102008-06-13 16:03:22 -07002094 if (drmIoctl(fd, DRM_IOCTL_IRQ_BUSID, &p))
Brianccd7b6e2007-05-29 14:54:00 -06002095 return -errno;
Daryll Straussb3a57661999-12-05 01:19:48 +00002096 return p.irq;
2097}
2098
Jon Smirl8696e712004-07-07 04:36:36 +00002099int drmAddContextTag(int fd, drm_context_t context, void *tag)
Daryll Straussb3a57661999-12-05 01:19:48 +00002100{
2101 drmHashEntry *entry = drmGetEntry(fd);
2102
2103 if (drmHashInsert(entry->tagTable, context, tag)) {
2104 drmHashDelete(entry->tagTable, context);
2105 drmHashInsert(entry->tagTable, context, tag);
2106 }
2107 return 0;
2108}
2109
Jon Smirl8696e712004-07-07 04:36:36 +00002110int drmDelContextTag(int fd, drm_context_t context)
Daryll Straussb3a57661999-12-05 01:19:48 +00002111{
2112 drmHashEntry *entry = drmGetEntry(fd);
2113
2114 return drmHashDelete(entry->tagTable, context);
2115}
2116
Jon Smirl8696e712004-07-07 04:36:36 +00002117void *drmGetContextTag(int fd, drm_context_t context)
Daryll Straussb3a57661999-12-05 01:19:48 +00002118{
2119 drmHashEntry *entry = drmGetEntry(fd);
2120 void *value;
Gareth Hughes36047532001-02-15 08:12:14 +00002121
Brianccd7b6e2007-05-29 14:54:00 -06002122 if (drmHashLookup(entry->tagTable, context, &value))
2123 return NULL;
Daryll Straussb3a57661999-12-05 01:19:48 +00002124
2125 return value;
2126}
2127
Adam Jackson22e41ef2006-02-20 23:09:00 +00002128int drmAddContextPrivateMapping(int fd, drm_context_t ctx_id,
2129 drm_handle_t handle)
Kevin E Martin74e19a42001-03-14 22:22:50 +00002130{
2131 drm_ctx_priv_map_t map;
2132
2133 map.ctx_id = ctx_id;
Jeremy Huddleston961bf9b2011-11-01 14:42:13 -07002134 map.handle = (void *)(uintptr_t)handle;
Kevin E Martin74e19a42001-03-14 22:22:50 +00002135
Keith Packard8b9ab102008-06-13 16:03:22 -07002136 if (drmIoctl(fd, DRM_IOCTL_SET_SAREA_CTX, &map))
Brianccd7b6e2007-05-29 14:54:00 -06002137 return -errno;
Kevin E Martin74e19a42001-03-14 22:22:50 +00002138 return 0;
2139}
2140
Adam Jackson22e41ef2006-02-20 23:09:00 +00002141int drmGetContextPrivateMapping(int fd, drm_context_t ctx_id,
2142 drm_handle_t *handle)
Kevin E Martin74e19a42001-03-14 22:22:50 +00002143{
2144 drm_ctx_priv_map_t map;
2145
2146 map.ctx_id = ctx_id;
2147
Keith Packard8b9ab102008-06-13 16:03:22 -07002148 if (drmIoctl(fd, DRM_IOCTL_GET_SAREA_CTX, &map))
Brianccd7b6e2007-05-29 14:54:00 -06002149 return -errno;
2150 if (handle)
Jeremy Huddleston961bf9b2011-11-01 14:42:13 -07002151 *handle = (drm_handle_t)(uintptr_t)map.handle;
Kevin E Martin74e19a42001-03-14 22:22:50 +00002152
2153 return 0;
2154}
2155
Jon Smirl8696e712004-07-07 04:36:36 +00002156int drmGetMap(int fd, int idx, drm_handle_t *offset, drmSize *size,
2157 drmMapType *type, drmMapFlags *flags, drm_handle_t *handle,
Rik Faith88dbee52001-02-28 09:27:44 +00002158 int *mtrr)
2159{
2160 drm_map_t map;
2161
2162 map.offset = idx;
Keith Packard8b9ab102008-06-13 16:03:22 -07002163 if (drmIoctl(fd, DRM_IOCTL_GET_MAP, &map))
Brianccd7b6e2007-05-29 14:54:00 -06002164 return -errno;
Rik Faith88dbee52001-02-28 09:27:44 +00002165 *offset = map.offset;
2166 *size = map.size;
2167 *type = map.type;
2168 *flags = map.flags;
2169 *handle = (unsigned long)map.handle;
2170 *mtrr = map.mtrr;
2171 return 0;
2172}
2173
2174int drmGetClient(int fd, int idx, int *auth, int *pid, int *uid,
2175 unsigned long *magic, unsigned long *iocs)
2176{
2177 drm_client_t client;
2178
2179 client.idx = idx;
Keith Packard8b9ab102008-06-13 16:03:22 -07002180 if (drmIoctl(fd, DRM_IOCTL_GET_CLIENT, &client))
Brianccd7b6e2007-05-29 14:54:00 -06002181 return -errno;
Rik Faith88dbee52001-02-28 09:27:44 +00002182 *auth = client.auth;
2183 *pid = client.pid;
2184 *uid = client.uid;
2185 *magic = client.magic;
2186 *iocs = client.iocs;
2187 return 0;
2188}
2189
2190int drmGetStats(int fd, drmStatsT *stats)
2191{
2192 drm_stats_t s;
2193 int i;
2194
Keith Packard8b9ab102008-06-13 16:03:22 -07002195 if (drmIoctl(fd, DRM_IOCTL_GET_STATS, &s))
Brianccd7b6e2007-05-29 14:54:00 -06002196 return -errno;
Rik Faith88dbee52001-02-28 09:27:44 +00002197
2198 stats->count = 0;
2199 memset(stats, 0, sizeof(*stats));
2200 if (s.count > sizeof(stats->data)/sizeof(stats->data[0]))
2201 return -1;
2202
2203#define SET_VALUE \
2204 stats->data[i].long_format = "%-20.20s"; \
2205 stats->data[i].rate_format = "%8.8s"; \
2206 stats->data[i].isvalue = 1; \
2207 stats->data[i].verbose = 0
2208
2209#define SET_COUNT \
2210 stats->data[i].long_format = "%-20.20s"; \
2211 stats->data[i].rate_format = "%5.5s"; \
2212 stats->data[i].isvalue = 0; \
2213 stats->data[i].mult_names = "kgm"; \
2214 stats->data[i].mult = 1000; \
2215 stats->data[i].verbose = 0
2216
2217#define SET_BYTE \
2218 stats->data[i].long_format = "%-20.20s"; \
2219 stats->data[i].rate_format = "%5.5s"; \
2220 stats->data[i].isvalue = 0; \
2221 stats->data[i].mult_names = "KGM"; \
2222 stats->data[i].mult = 1024; \
2223 stats->data[i].verbose = 0
2224
2225
2226 stats->count = s.count;
2227 for (i = 0; i < s.count; i++) {
2228 stats->data[i].value = s.data[i].value;
2229 switch (s.data[i].type) {
2230 case _DRM_STAT_LOCK:
2231 stats->data[i].long_name = "Lock";
2232 stats->data[i].rate_name = "Lock";
2233 SET_VALUE;
2234 break;
2235 case _DRM_STAT_OPENS:
2236 stats->data[i].long_name = "Opens";
2237 stats->data[i].rate_name = "O";
2238 SET_COUNT;
2239 stats->data[i].verbose = 1;
2240 break;
2241 case _DRM_STAT_CLOSES:
2242 stats->data[i].long_name = "Closes";
2243 stats->data[i].rate_name = "Lock";
2244 SET_COUNT;
2245 stats->data[i].verbose = 1;
2246 break;
2247 case _DRM_STAT_IOCTLS:
2248 stats->data[i].long_name = "Ioctls";
2249 stats->data[i].rate_name = "Ioc/s";
2250 SET_COUNT;
2251 break;
2252 case _DRM_STAT_LOCKS:
2253 stats->data[i].long_name = "Locks";
2254 stats->data[i].rate_name = "Lck/s";
2255 SET_COUNT;
2256 break;
2257 case _DRM_STAT_UNLOCKS:
2258 stats->data[i].long_name = "Unlocks";
2259 stats->data[i].rate_name = "Unl/s";
2260 SET_COUNT;
2261 break;
2262 case _DRM_STAT_IRQ:
2263 stats->data[i].long_name = "IRQs";
2264 stats->data[i].rate_name = "IRQ/s";
2265 SET_COUNT;
2266 break;
2267 case _DRM_STAT_PRIMARY:
2268 stats->data[i].long_name = "Primary Bytes";
2269 stats->data[i].rate_name = "PB/s";
2270 SET_BYTE;
2271 break;
2272 case _DRM_STAT_SECONDARY:
2273 stats->data[i].long_name = "Secondary Bytes";
2274 stats->data[i].rate_name = "SB/s";
2275 SET_BYTE;
2276 break;
2277 case _DRM_STAT_DMA:
2278 stats->data[i].long_name = "DMA";
2279 stats->data[i].rate_name = "DMA/s";
2280 SET_COUNT;
2281 break;
2282 case _DRM_STAT_SPECIAL:
2283 stats->data[i].long_name = "Special DMA";
2284 stats->data[i].rate_name = "dma/s";
2285 SET_COUNT;
2286 break;
2287 case _DRM_STAT_MISSED:
2288 stats->data[i].long_name = "Miss";
2289 stats->data[i].rate_name = "Ms/s";
2290 SET_COUNT;
2291 break;
2292 case _DRM_STAT_VALUE:
2293 stats->data[i].long_name = "Value";
2294 stats->data[i].rate_name = "Value";
2295 SET_VALUE;
2296 break;
2297 case _DRM_STAT_BYTE:
2298 stats->data[i].long_name = "Bytes";
2299 stats->data[i].rate_name = "B/s";
2300 SET_BYTE;
2301 break;
2302 case _DRM_STAT_COUNT:
2303 default:
2304 stats->data[i].long_name = "Count";
2305 stats->data[i].rate_name = "Cnt/s";
2306 SET_COUNT;
2307 break;
2308 }
2309 }
2310 return 0;
2311}
2312
Jose Fonsecad2443b22003-05-27 00:37:33 +00002313/**
Eric Anholt06cb1322003-10-23 02:23:31 +00002314 * Issue a set-version ioctl.
2315 *
2316 * \param fd file descriptor.
2317 * \param drmCommandIndex command index
2318 * \param data source pointer of the data to be read and written.
2319 * \param size size of the data to be read and written.
2320 *
2321 * \return zero on success, or a negative value on failure.
2322 *
2323 * \internal
2324 * It issues a read-write ioctl given by
2325 * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
2326 */
Adam Jackson22e41ef2006-02-20 23:09:00 +00002327int drmSetInterfaceVersion(int fd, drmSetVersion *version)
Eric Anholt06cb1322003-10-23 02:23:31 +00002328{
2329 int retcode = 0;
2330 drm_set_version_t sv;
2331
2332 sv.drm_di_major = version->drm_di_major;
2333 sv.drm_di_minor = version->drm_di_minor;
2334 sv.drm_dd_major = version->drm_dd_major;
2335 sv.drm_dd_minor = version->drm_dd_minor;
2336
Keith Packard8b9ab102008-06-13 16:03:22 -07002337 if (drmIoctl(fd, DRM_IOCTL_SET_VERSION, &sv)) {
Eric Anholt06cb1322003-10-23 02:23:31 +00002338 retcode = -errno;
2339 }
2340
2341 version->drm_di_major = sv.drm_di_major;
2342 version->drm_di_minor = sv.drm_di_minor;
2343 version->drm_dd_major = sv.drm_dd_major;
2344 version->drm_dd_minor = sv.drm_dd_minor;
2345
2346 return retcode;
2347}
2348
2349/**
Jose Fonsecad2443b22003-05-27 00:37:33 +00002350 * Send a device-specific command.
2351 *
2352 * \param fd file descriptor.
2353 * \param drmCommandIndex command index
2354 *
2355 * \return zero on success, or a negative value on failure.
2356 *
2357 * \internal
2358 * It issues a ioctl given by
2359 * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
2360 */
Jens Owen3903e5a2002-04-09 21:54:56 +00002361int drmCommandNone(int fd, unsigned long drmCommandIndex)
2362{
2363 void *data = NULL; /* dummy */
2364 unsigned long request;
2365
2366 request = DRM_IO( DRM_COMMAND_BASE + drmCommandIndex);
2367
Keith Packard8b9ab102008-06-13 16:03:22 -07002368 if (drmIoctl(fd, request, data)) {
Jens Owen3903e5a2002-04-09 21:54:56 +00002369 return -errno;
2370 }
2371 return 0;
2372}
2373
Jose Fonsecad2443b22003-05-27 00:37:33 +00002374
2375/**
2376 * Send a device-specific read command.
2377 *
2378 * \param fd file descriptor.
2379 * \param drmCommandIndex command index
2380 * \param data destination pointer of the data to be read.
2381 * \param size size of the data to be read.
2382 *
2383 * \return zero on success, or a negative value on failure.
2384 *
2385 * \internal
2386 * It issues a read ioctl given by
2387 * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
2388 */
Adam Jackson22e41ef2006-02-20 23:09:00 +00002389int drmCommandRead(int fd, unsigned long drmCommandIndex, void *data,
2390 unsigned long size)
Jens Owen3903e5a2002-04-09 21:54:56 +00002391{
2392 unsigned long request;
2393
Alan Hourihane74ef13f2002-07-05 08:31:11 +00002394 request = DRM_IOC( DRM_IOC_READ, DRM_IOCTL_BASE,
2395 DRM_COMMAND_BASE + drmCommandIndex, size);
Jens Owen3903e5a2002-04-09 21:54:56 +00002396
Keith Packard8b9ab102008-06-13 16:03:22 -07002397 if (drmIoctl(fd, request, data)) {
Jens Owen3903e5a2002-04-09 21:54:56 +00002398 return -errno;
2399 }
2400 return 0;
2401}
2402
Jose Fonsecad2443b22003-05-27 00:37:33 +00002403
2404/**
2405 * Send a device-specific write command.
2406 *
2407 * \param fd file descriptor.
2408 * \param drmCommandIndex command index
2409 * \param data source pointer of the data to be written.
2410 * \param size size of the data to be written.
2411 *
2412 * \return zero on success, or a negative value on failure.
2413 *
2414 * \internal
2415 * It issues a write ioctl given by
2416 * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
2417 */
Adam Jackson22e41ef2006-02-20 23:09:00 +00002418int drmCommandWrite(int fd, unsigned long drmCommandIndex, void *data,
2419 unsigned long size)
Jens Owen3903e5a2002-04-09 21:54:56 +00002420{
2421 unsigned long request;
2422
Alan Hourihane74ef13f2002-07-05 08:31:11 +00002423 request = DRM_IOC( DRM_IOC_WRITE, DRM_IOCTL_BASE,
2424 DRM_COMMAND_BASE + drmCommandIndex, size);
Jens Owen3903e5a2002-04-09 21:54:56 +00002425
Keith Packard8b9ab102008-06-13 16:03:22 -07002426 if (drmIoctl(fd, request, data)) {
Jens Owen3903e5a2002-04-09 21:54:56 +00002427 return -errno;
2428 }
2429 return 0;
2430}
2431
Jose Fonsecad2443b22003-05-27 00:37:33 +00002432
2433/**
2434 * Send a device-specific read-write command.
2435 *
2436 * \param fd file descriptor.
2437 * \param drmCommandIndex command index
2438 * \param data source pointer of the data to be read and written.
2439 * \param size size of the data to be read and written.
2440 *
2441 * \return zero on success, or a negative value on failure.
2442 *
2443 * \internal
2444 * It issues a read-write ioctl given by
2445 * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
2446 */
Adam Jackson22e41ef2006-02-20 23:09:00 +00002447int drmCommandWriteRead(int fd, unsigned long drmCommandIndex, void *data,
2448 unsigned long size)
Jens Owen3903e5a2002-04-09 21:54:56 +00002449{
2450 unsigned long request;
2451
Alan Hourihane74ef13f2002-07-05 08:31:11 +00002452 request = DRM_IOC( DRM_IOC_READ|DRM_IOC_WRITE, DRM_IOCTL_BASE,
2453 DRM_COMMAND_BASE + drmCommandIndex, size);
Jens Owen3903e5a2002-04-09 21:54:56 +00002454
Keith Packard8b9ab102008-06-13 16:03:22 -07002455 if (drmIoctl(fd, request, data))
Jens Owen3903e5a2002-04-09 21:54:56 +00002456 return -errno;
Jens Owen3903e5a2002-04-09 21:54:56 +00002457 return 0;
2458}
Thomas Hellstrom166da932006-08-21 21:02:08 +02002459
Dave Airlied51e1bb2006-11-09 08:55:58 +11002460#define DRM_MAX_FDS 16
2461static struct {
Brianccd7b6e2007-05-29 14:54:00 -06002462 char *BusID;
2463 int fd;
2464 int refcount;
Dave Airlied51e1bb2006-11-09 08:55:58 +11002465} connection[DRM_MAX_FDS];
2466
2467static int nr_fds = 0;
2468
2469int drmOpenOnce(void *unused,
2470 const char *BusID,
2471 int *newlyopened)
2472{
Brianccd7b6e2007-05-29 14:54:00 -06002473 int i;
2474 int fd;
Dave Airlied51e1bb2006-11-09 08:55:58 +11002475
Brianccd7b6e2007-05-29 14:54:00 -06002476 for (i = 0; i < nr_fds; i++)
2477 if (strcmp(BusID, connection[i].BusID) == 0) {
2478 connection[i].refcount++;
2479 *newlyopened = 0;
2480 return connection[i].fd;
2481 }
Dave Airlied51e1bb2006-11-09 08:55:58 +11002482
Brianccd7b6e2007-05-29 14:54:00 -06002483 fd = drmOpen(unused, BusID);
2484 if (fd <= 0 || nr_fds == DRM_MAX_FDS)
2485 return fd;
Dave Airlied51e1bb2006-11-09 08:55:58 +11002486
Brianccd7b6e2007-05-29 14:54:00 -06002487 connection[nr_fds].BusID = strdup(BusID);
2488 connection[nr_fds].fd = fd;
2489 connection[nr_fds].refcount = 1;
2490 *newlyopened = 1;
Dave Airlied51e1bb2006-11-09 08:55:58 +11002491
Brianccd7b6e2007-05-29 14:54:00 -06002492 if (0)
2493 fprintf(stderr, "saved connection %d for %s %d\n",
2494 nr_fds, connection[nr_fds].BusID,
2495 strcmp(BusID, connection[nr_fds].BusID));
Dave Airlied51e1bb2006-11-09 08:55:58 +11002496
Brianccd7b6e2007-05-29 14:54:00 -06002497 nr_fds++;
Dave Airlied51e1bb2006-11-09 08:55:58 +11002498
Brianccd7b6e2007-05-29 14:54:00 -06002499 return fd;
Dave Airlied51e1bb2006-11-09 08:55:58 +11002500}
2501
2502void drmCloseOnce(int fd)
2503{
Brianccd7b6e2007-05-29 14:54:00 -06002504 int i;
Dave Airlied51e1bb2006-11-09 08:55:58 +11002505
Brianccd7b6e2007-05-29 14:54:00 -06002506 for (i = 0; i < nr_fds; i++) {
2507 if (fd == connection[i].fd) {
2508 if (--connection[i].refcount == 0) {
2509 drmClose(connection[i].fd);
2510 free(connection[i].BusID);
Dave Airlied51e1bb2006-11-09 08:55:58 +11002511
Brianccd7b6e2007-05-29 14:54:00 -06002512 if (i < --nr_fds)
2513 connection[i] = connection[nr_fds];
Dave Airlied51e1bb2006-11-09 08:55:58 +11002514
Brianccd7b6e2007-05-29 14:54:00 -06002515 return;
2516 }
2517 }
2518 }
Dave Airlied51e1bb2006-11-09 08:55:58 +11002519}
Jesse Barnes731cd552008-12-17 10:09:49 -08002520
2521int drmSetMaster(int fd)
2522{
Kristian Høgsbergfbc8b2d2009-12-09 10:37:40 -05002523 return ioctl(fd, DRM_IOCTL_SET_MASTER, 0);
Jesse Barnes731cd552008-12-17 10:09:49 -08002524}
2525
2526int drmDropMaster(int fd)
2527{
Kristian Høgsbergfbc8b2d2009-12-09 10:37:40 -05002528 return ioctl(fd, DRM_IOCTL_DROP_MASTER, 0);
Jesse Barnes731cd552008-12-17 10:09:49 -08002529}
Kristian Høgsberg22d46662009-11-23 20:51:34 -05002530
2531char *drmGetDeviceNameFromFd(int fd)
2532{
2533 char name[128];
2534 struct stat sbuf;
2535 dev_t d;
2536 int i;
2537
2538 /* The whole drmOpen thing is a fiasco and we need to find a way
2539 * back to just using open(2). For now, however, lets just make
2540 * things worse with even more ad hoc directory walking code to
2541 * discover the device file name. */
2542
2543 fstat(fd, &sbuf);
2544 d = sbuf.st_rdev;
2545
2546 for (i = 0; i < DRM_MAX_MINOR; i++) {
2547 snprintf(name, sizeof name, DRM_DEV_NAME, DRM_DIR_NAME, i);
2548 if (stat(name, &sbuf) == 0 && sbuf.st_rdev == d)
2549 break;
2550 }
2551 if (i == DRM_MAX_MINOR)
2552 return NULL;
2553
Adam Jackson0a1ff352010-10-27 18:44:53 -04002554 return strdup(name);
Kristian Høgsberg22d46662009-11-23 20:51:34 -05002555}
Dave Airliecc0a1452012-07-14 09:52:17 +00002556
2557int drmPrimeHandleToFD(int fd, uint32_t handle, uint32_t flags, int *prime_fd)
2558{
2559 struct drm_prime_handle args;
2560 int ret;
2561
2562 args.handle = handle;
2563 args.flags = flags;
2564 ret = drmIoctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &args);
2565 if (ret)
2566 return ret;
2567
2568 *prime_fd = args.fd;
2569 return 0;
2570}
2571
2572int drmPrimeFDToHandle(int fd, int prime_fd, uint32_t *handle)
2573{
2574 struct drm_prime_handle args;
2575 int ret;
2576
2577 args.fd = prime_fd;
2578 args.flags = 0;
2579 ret = drmIoctl(fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &args);
2580 if (ret)
2581 return ret;
2582
2583 *handle = args.handle;
2584 return 0;
2585}
2586