blob: ed385472388282b8ea9092f1b2eae97cad004203 [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>
Dave Airlie79038752006-11-08 15:08:09 +110051#include <sys/time.h>
52#include <stdarg.h>
Daryll Straussb3a57661999-12-05 01:19:48 +000053
54/* Not all systems have MAP_FAILED defined */
55#ifndef MAP_FAILED
56#define MAP_FAILED ((void *)-1)
57#endif
58
Daryll Straussb3a57661999-12-05 01:19:48 +000059#include "xf86drm.h"
Emil Velikovfaf51d52014-09-07 20:03:05 +010060#include "libdrm.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
Frank Binnsad8bbfd2015-01-14 14:07:50 +000089#define DRM_NODE_PRIMARY 1
Frank Binns0c5aaee2015-01-14 14:07:51 +000090#define DRM_NODE_RENDER 2
Jesse Barnes731cd552008-12-17 10:09:49 -080091
Daniel Vetterfd387942015-02-11 12:41:04 +010092#define memclear(s) memset(&s, 0, sizeof(s))
93
Dave Airlie79038752006-11-08 15:08:09 +110094static drmServerInfoPtr drm_server_info;
95
96void drmSetServerInfo(drmServerInfoPtr info)
97{
Brianccd7b6e2007-05-29 14:54:00 -060098 drm_server_info = info;
Dave Airlie79038752006-11-08 15:08:09 +110099}
100
Jose Fonsecad2443b22003-05-27 00:37:33 +0000101/**
102 * Output a message to stderr.
103 *
104 * \param format printf() like format string.
105 *
106 * \internal
107 * This function is a wrapper around vfprintf().
108 */
Dave Airlie79038752006-11-08 15:08:09 +1100109
Thierry Reding44b08c02014-01-22 12:06:51 +0100110static int DRM_PRINTFLIKE(1, 0)
111drmDebugPrint(const char *format, va_list ap)
Dave Airlie79038752006-11-08 15:08:09 +1100112{
Brianccd7b6e2007-05-29 14:54:00 -0600113 return vfprintf(stderr, format, ap);
Dave Airlie79038752006-11-08 15:08:09 +1100114}
115
Thierry Reding44b08c02014-01-22 12:06:51 +0100116typedef int DRM_PRINTFLIKE(1, 0) (*debug_msg_func_t)(const char *format,
117 va_list ap);
118
119static debug_msg_func_t drm_debug_print = drmDebugPrint;
Dave Airlie79038752006-11-08 15:08:09 +1100120
Eric Anholtc4857422008-06-03 10:20:49 -0700121void
David Dawes56bd9c22001-07-30 19:59:39 +0000122drmMsg(const char *format, ...)
123{
124 va_list ap;
David Dawes56bd9c22001-07-30 19:59:39 +0000125 const char *env;
Dave Airlie79038752006-11-08 15:08:09 +1100126 if (((env = getenv("LIBGL_DEBUG")) && strstr(env, "verbose")) || drm_server_info)
David Dawes56bd9c22001-07-30 19:59:39 +0000127 {
128 va_start(ap, format);
Dave Airlie79038752006-11-08 15:08:09 +1100129 if (drm_server_info) {
130 drm_server_info->debug_print(format,ap);
131 } else {
132 drm_debug_print(format, ap);
133 }
David Dawes56bd9c22001-07-30 19:59:39 +0000134 va_end(ap);
135 }
136}
137
Dave Airlie79038752006-11-08 15:08:09 +1100138void
Thierry Reding44b08c02014-01-22 12:06:51 +0100139drmSetDebugMsgFunction(debug_msg_func_t debug_msg_ptr)
Dave Airlie79038752006-11-08 15:08:09 +1100140{
Brianccd7b6e2007-05-29 14:54:00 -0600141 drm_debug_print = debug_msg_ptr;
Dave Airlie79038752006-11-08 15:08:09 +1100142}
143
Daryll Straussb3a57661999-12-05 01:19:48 +0000144static void *drmHashTable = NULL; /* Context switch callbacks */
145
Dave Airlie79038752006-11-08 15:08:09 +1100146void *drmGetHashTable(void)
147{
Brianccd7b6e2007-05-29 14:54:00 -0600148 return drmHashTable;
Dave Airlie79038752006-11-08 15:08:09 +1100149}
Daryll Straussb3a57661999-12-05 01:19:48 +0000150
151void *drmMalloc(int size)
152{
153 void *pt;
Brianccd7b6e2007-05-29 14:54:00 -0600154 if ((pt = malloc(size)))
155 memset(pt, 0, size);
Daryll Straussb3a57661999-12-05 01:19:48 +0000156 return pt;
157}
158
159void drmFree(void *pt)
160{
Brianccd7b6e2007-05-29 14:54:00 -0600161 if (pt)
162 free(pt);
Daryll Straussb3a57661999-12-05 01:19:48 +0000163}
164
Keith Packard8b9ab102008-06-13 16:03:22 -0700165/**
166 * Call ioctl, restarting if it is interupted
167 */
Jesse Barnes731cd552008-12-17 10:09:49 -0800168int
Coleman Kane41b83a92008-08-18 17:08:21 -0400169drmIoctl(int fd, unsigned long request, void *arg)
Keith Packard8b9ab102008-06-13 16:03:22 -0700170{
171 int ret;
172
173 do {
174 ret = ioctl(fd, request, arg);
175 } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
176 return ret;
177}
Daryll Straussb3a57661999-12-05 01:19:48 +0000178
Daryll Straussb3a57661999-12-05 01:19:48 +0000179static unsigned long drmGetKeyFromFd(int fd)
180{
David Dawesfcc21062001-03-30 17:16:20 +0000181 stat_t st;
Daryll Straussb3a57661999-12-05 01:19:48 +0000182
183 st.st_rdev = 0;
184 fstat(fd, &st);
185 return st.st_rdev;
186}
187
Dave Airlie79038752006-11-08 15:08:09 +1100188drmHashEntry *drmGetEntry(int fd)
Daryll Straussb3a57661999-12-05 01:19:48 +0000189{
190 unsigned long key = drmGetKeyFromFd(fd);
191 void *value;
192 drmHashEntry *entry;
193
Brianccd7b6e2007-05-29 14:54:00 -0600194 if (!drmHashTable)
195 drmHashTable = drmHashCreate();
Daryll Straussb3a57661999-12-05 01:19:48 +0000196
197 if (drmHashLookup(drmHashTable, key, &value)) {
198 entry = drmMalloc(sizeof(*entry));
199 entry->fd = fd;
200 entry->f = NULL;
201 entry->tagTable = drmHashCreate();
202 drmHashInsert(drmHashTable, key, entry);
203 } else {
204 entry = value;
205 }
206 return entry;
207}
208
Jose Fonsecad2443b22003-05-27 00:37:33 +0000209/**
Eric Anholt06cb1322003-10-23 02:23:31 +0000210 * Compare two busid strings
211 *
212 * \param first
213 * \param second
214 *
215 * \return 1 if matched.
216 *
217 * \internal
218 * This function compares two bus ID strings. It understands the older
219 * PCI:b:d:f format and the newer pci:oooo:bb:dd.f format. In the format, o is
220 * domain, b is bus, d is device, f is function.
221 */
Benjamin Herrenschmidtb04515c2010-08-06 13:55:11 +1000222static int drmMatchBusID(const char *id1, const char *id2, int pci_domain_ok)
Eric Anholt06cb1322003-10-23 02:23:31 +0000223{
224 /* First, check if the IDs are exactly the same */
225 if (strcasecmp(id1, id2) == 0)
226 return 1;
227
228 /* Try to match old/new-style PCI bus IDs. */
229 if (strncasecmp(id1, "pci", 3) == 0) {
Pauli Nieminen90ae0f22009-07-04 02:18:51 +0300230 unsigned int o1, b1, d1, f1;
231 unsigned int o2, b2, d2, f2;
Eric Anholt06cb1322003-10-23 02:23:31 +0000232 int ret;
233
Pauli Nieminen90ae0f22009-07-04 02:18:51 +0300234 ret = sscanf(id1, "pci:%04x:%02x:%02x.%u", &o1, &b1, &d1, &f1);
Eric Anholt06cb1322003-10-23 02:23:31 +0000235 if (ret != 4) {
236 o1 = 0;
Pauli Nieminen90ae0f22009-07-04 02:18:51 +0300237 ret = sscanf(id1, "PCI:%u:%u:%u", &b1, &d1, &f1);
Eric Anholt06cb1322003-10-23 02:23:31 +0000238 if (ret != 3)
239 return 0;
240 }
241
Pauli Nieminen90ae0f22009-07-04 02:18:51 +0300242 ret = sscanf(id2, "pci:%04x:%02x:%02x.%u", &o2, &b2, &d2, &f2);
Eric Anholt06cb1322003-10-23 02:23:31 +0000243 if (ret != 4) {
244 o2 = 0;
Pauli Nieminen90ae0f22009-07-04 02:18:51 +0300245 ret = sscanf(id2, "PCI:%u:%u:%u", &b2, &d2, &f2);
Eric Anholt06cb1322003-10-23 02:23:31 +0000246 if (ret != 3)
247 return 0;
248 }
249
Benjamin Herrenschmidtb04515c2010-08-06 13:55:11 +1000250 /* If domains aren't properly supported by the kernel interface,
251 * just ignore them, which sucks less than picking a totally random
252 * card with "open by name"
253 */
254 if (!pci_domain_ok)
255 o1 = o2 = 0;
256
Eric Anholt06cb1322003-10-23 02:23:31 +0000257 if ((o1 != o2) || (b1 != b2) || (d1 != d2) || (f1 != f2))
258 return 0;
259 else
260 return 1;
261 }
262 return 0;
263}
264
265/**
Pauli Nieminenc5a5bbb2009-07-06 23:37:20 +0300266 * Handles error checking for chown call.
267 *
268 * \param path to file.
269 * \param id of the new owner.
270 * \param id of the new group.
271 *
272 * \return zero if success or -1 if failure.
273 *
274 * \internal
275 * Checks for failure. If failure was caused by signal call chown again.
276 * If any other failure happened then it will output error mesage using
277 * drmMsg() call.
278 */
279static int chown_check_return(const char *path, uid_t owner, gid_t group)
280{
281 int rv;
282
283 do {
284 rv = chown(path, owner, group);
285 } while (rv != 0 && errno == EINTR);
286
287 if (rv == 0)
288 return 0;
289
290 drmMsg("Failed to change owner or group for file %s! %d: %s\n",
291 path, errno, strerror(errno));
292 return -1;
293}
294
295/**
Jose Fonsecad2443b22003-05-27 00:37:33 +0000296 * Open the DRM device, creating it if necessary.
297 *
298 * \param dev major and minor numbers of the device.
299 * \param minor minor number of the device.
300 *
301 * \return a file descriptor on success, or a negative value on error.
302 *
303 * \internal
304 * Assembles the device name from \p minor and opens it, creating the device
305 * special file node with the major and minor numbers specified by \p dev and
306 * parent directory if necessary and was called by root.
307 */
Jan Veselyde8532d2014-11-30 12:53:18 -0500308static int drmOpenDevice(dev_t dev, int minor, int type)
Daryll Straussb3a57661999-12-05 01:19:48 +0000309{
David Dawes9c775d02001-05-14 14:49:58 +0000310 stat_t st;
Frank Binns0c5aaee2015-01-14 14:07:51 +0000311 const char *dev_name;
Rik Faith88dbee52001-02-28 09:27:44 +0000312 char buf[64];
313 int fd;
Dave Airlie79038752006-11-08 15:08:09 +1100314 mode_t devmode = DRM_DEV_MODE, serv_mode;
Rik Faith88dbee52001-02-28 09:27:44 +0000315 int isroot = !geteuid();
Rik Faith88dbee52001-02-28 09:27:44 +0000316 uid_t user = DRM_DEV_UID;
Dave Airlie79038752006-11-08 15:08:09 +1100317 gid_t group = DRM_DEV_GID, serv_group;
318
Frank Binns0c5aaee2015-01-14 14:07:51 +0000319 switch (type) {
320 case DRM_NODE_PRIMARY:
321 dev_name = DRM_DEV_NAME;
322 break;
323 case DRM_NODE_CONTROL:
324 dev_name = DRM_CONTROL_DEV_NAME;
325 break;
326 case DRM_NODE_RENDER:
327 dev_name = DRM_RENDER_DEV_NAME;
328 break;
329 default:
330 return -EINVAL;
331 };
332
333 sprintf(buf, dev_name, DRM_DIR_NAME, minor);
Eric Anholt06cb1322003-10-23 02:23:31 +0000334 drmMsg("drmOpenDevice: node name is %s\n", buf);
David Dawes56bd9c22001-07-30 19:59:39 +0000335
Dave Airlie79038752006-11-08 15:08:09 +1100336 if (drm_server_info) {
Brianccd7b6e2007-05-29 14:54:00 -0600337 drm_server_info->get_perms(&serv_group, &serv_mode);
338 devmode = serv_mode ? serv_mode : DRM_DEV_MODE;
339 devmode &= ~(S_IXUSR|S_IXGRP|S_IXOTH);
340 group = (serv_group >= 0) ? serv_group : DRM_DEV_GID;
Dave Airlie79038752006-11-08 15:08:09 +1100341 }
Brian Paul569da5a2000-06-08 14:38:22 +0000342
Dave Airlie9101a022008-08-24 16:54:43 +1000343#if !defined(UDEV)
Rik Faith88dbee52001-02-28 09:27:44 +0000344 if (stat(DRM_DIR_NAME, &st)) {
Brianccd7b6e2007-05-29 14:54:00 -0600345 if (!isroot)
346 return DRM_ERR_NOT_ROOT;
Alan Hourihaneb3a20ce2002-10-22 23:38:53 +0000347 mkdir(DRM_DIR_NAME, DRM_DEV_DIRMODE);
Pauli Nieminenc5a5bbb2009-07-06 23:37:20 +0300348 chown_check_return(DRM_DIR_NAME, 0, 0); /* root:root */
Alan Hourihaneb3a20ce2002-10-22 23:38:53 +0000349 chmod(DRM_DIR_NAME, DRM_DEV_DIRMODE);
Brian Paul569da5a2000-06-08 14:38:22 +0000350 }
Daryll Straussb3a57661999-12-05 01:19:48 +0000351
Eric Anholt06cb1322003-10-23 02:23:31 +0000352 /* Check if the device node exists and create it if necessary. */
Eric Anholtd2f2b422002-08-08 21:23:46 +0000353 if (stat(buf, &st)) {
Brianccd7b6e2007-05-29 14:54:00 -0600354 if (!isroot)
355 return DRM_ERR_NOT_ROOT;
Rik Faith88dbee52001-02-28 09:27:44 +0000356 remove(buf);
357 mknod(buf, S_IFCHR | devmode, dev);
Daryll Straussb3a57661999-12-05 01:19:48 +0000358 }
Dave Airlie79038752006-11-08 15:08:09 +1100359
360 if (drm_server_info) {
Pauli Nieminenc5a5bbb2009-07-06 23:37:20 +0300361 chown_check_return(buf, user, group);
Brianccd7b6e2007-05-29 14:54:00 -0600362 chmod(buf, devmode);
Dave Airlie79038752006-11-08 15:08:09 +1100363 }
Dave Airlie9101a022008-08-24 16:54:43 +1000364#else
365 /* if we modprobed then wait for udev */
366 {
367 int udev_count = 0;
368wait_for_udev:
369 if (stat(DRM_DIR_NAME, &st)) {
370 usleep(20);
371 udev_count++;
372
373 if (udev_count == 50)
374 return -1;
375 goto wait_for_udev;
376 }
377
378 if (stat(buf, &st)) {
379 usleep(20);
380 udev_count++;
381
382 if (udev_count == 50)
383 return -1;
384 goto wait_for_udev;
385 }
386 }
387#endif
Rik Faith88dbee52001-02-28 09:27:44 +0000388
David Dawes56bd9c22001-07-30 19:59:39 +0000389 fd = open(buf, O_RDWR, 0);
390 drmMsg("drmOpenDevice: open result is %d, (%s)\n",
391 fd, fd < 0 ? strerror(errno) : "OK");
Brianccd7b6e2007-05-29 14:54:00 -0600392 if (fd >= 0)
393 return fd;
Eric Anholtd2f2b422002-08-08 21:23:46 +0000394
Dave Airlie39e5e982010-12-07 14:26:09 +1000395#if !defined(UDEV)
Eric Anholt06cb1322003-10-23 02:23:31 +0000396 /* Check if the device node is not what we expect it to be, and recreate it
397 * and try again if so.
398 */
Eric Anholtd2f2b422002-08-08 21:23:46 +0000399 if (st.st_rdev != dev) {
Brianccd7b6e2007-05-29 14:54:00 -0600400 if (!isroot)
401 return DRM_ERR_NOT_ROOT;
Eric Anholtd2f2b422002-08-08 21:23:46 +0000402 remove(buf);
403 mknod(buf, S_IFCHR | devmode, dev);
Dave Airlie79038752006-11-08 15:08:09 +1100404 if (drm_server_info) {
Pauli Nieminenc5a5bbb2009-07-06 23:37:20 +0300405 chown_check_return(buf, user, group);
Brianccd7b6e2007-05-29 14:54:00 -0600406 chmod(buf, devmode);
Dave Airlie79038752006-11-08 15:08:09 +1100407 }
Eric Anholtd2f2b422002-08-08 21:23:46 +0000408 }
409 fd = open(buf, O_RDWR, 0);
410 drmMsg("drmOpenDevice: open result is %d, (%s)\n",
411 fd, fd < 0 ? strerror(errno) : "OK");
Brianccd7b6e2007-05-29 14:54:00 -0600412 if (fd >= 0)
413 return fd;
Eric Anholtd2f2b422002-08-08 21:23:46 +0000414
David Dawes56bd9c22001-07-30 19:59:39 +0000415 drmMsg("drmOpenDevice: Open failed\n");
Rik Faith88dbee52001-02-28 09:27:44 +0000416 remove(buf);
Dave Airlie39e5e982010-12-07 14:26:09 +1000417#endif
Rik Faith88dbee52001-02-28 09:27:44 +0000418 return -errno;
Daryll Straussb3a57661999-12-05 01:19:48 +0000419}
420
Jose Fonsecad2443b22003-05-27 00:37:33 +0000421
422/**
423 * Open the DRM device
424 *
425 * \param minor device minor number.
426 * \param create allow to create the device if set.
427 *
428 * \return a file descriptor on success, or a negative value on error.
429 *
430 * \internal
431 * Calls drmOpenDevice() if \p create is set, otherwise assembles the device
432 * name from \p minor and opens it.
433 */
Jesse Barnes731cd552008-12-17 10:09:49 -0800434static int drmOpenMinor(int minor, int create, int type)
Rik Faith88dbee52001-02-28 09:27:44 +0000435{
436 int fd;
437 char buf[64];
Frank Binns0c5aaee2015-01-14 14:07:51 +0000438 const char *dev_name;
Dave Airliedb85ed22008-02-13 12:20:02 +1000439
Brianccd7b6e2007-05-29 14:54:00 -0600440 if (create)
Jesse Barnes731cd552008-12-17 10:09:49 -0800441 return drmOpenDevice(makedev(DRM_MAJOR, minor), minor, type);
Rik Faith88dbee52001-02-28 09:27:44 +0000442
Frank Binns0c5aaee2015-01-14 14:07:51 +0000443 switch (type) {
444 case DRM_NODE_PRIMARY:
445 dev_name = DRM_DEV_NAME;
446 break;
447 case DRM_NODE_CONTROL:
448 dev_name = DRM_CONTROL_DEV_NAME;
449 break;
450 case DRM_NODE_RENDER:
451 dev_name = DRM_RENDER_DEV_NAME;
452 break;
453 default:
454 return -EINVAL;
455 };
456
457 sprintf(buf, dev_name, DRM_DIR_NAME, minor);
Brianccd7b6e2007-05-29 14:54:00 -0600458 if ((fd = open(buf, O_RDWR, 0)) >= 0)
459 return fd;
Rik Faith88dbee52001-02-28 09:27:44 +0000460 return -errno;
461}
462
Brian Paul569da5a2000-06-08 14:38:22 +0000463
Jose Fonsecad2443b22003-05-27 00:37:33 +0000464/**
465 * Determine whether the DRM kernel driver has been loaded.
466 *
467 * \return 1 if the DRM driver is loaded, 0 otherwise.
468 *
469 * \internal
470 * Determine the presence of the kernel driver by attempting to open the 0
471 * minor and get version information. For backward compatibility with older
472 * Linux implementations, /proc/dri is also checked.
473 */
Brian Paul569da5a2000-06-08 14:38:22 +0000474int drmAvailable(void)
475{
Brian Paul569da5a2000-06-08 14:38:22 +0000476 drmVersionPtr version;
477 int retval = 0;
478 int fd;
Gareth Hughes36047532001-02-15 08:12:14 +0000479
Frank Binnsad8bbfd2015-01-14 14:07:50 +0000480 if ((fd = drmOpenMinor(0, 1, DRM_NODE_PRIMARY)) < 0) {
Alan Hourihaneb0a92852003-09-24 14:39:25 +0000481#ifdef __linux__
Adam Jackson22e41ef2006-02-20 23:09:00 +0000482 /* Try proc for backward Linux compatibility */
Brianccd7b6e2007-05-29 14:54:00 -0600483 if (!access("/proc/dri/0", R_OK))
484 return 1;
Alan Hourihaneb0a92852003-09-24 14:39:25 +0000485#endif
Rik Faith88dbee52001-02-28 09:27:44 +0000486 return 0;
Brian Paul569da5a2000-06-08 14:38:22 +0000487 }
Rik Faith88dbee52001-02-28 09:27:44 +0000488
489 if ((version = drmGetVersion(fd))) {
490 retval = 1;
491 drmFreeVersion(version);
492 }
493 close(fd);
Brian Paul569da5a2000-06-08 14:38:22 +0000494
495 return retval;
496}
497
Jose Fonsecad2443b22003-05-27 00:37:33 +0000498
499/**
500 * Open the device by bus ID.
501 *
502 * \param busid bus ID.
503 *
504 * \return a file descriptor on success, or a negative value on error.
505 *
506 * \internal
507 * This function attempts to open every possible minor (up to DRM_MAX_MINOR),
508 * comparing the device bus ID with the one supplied.
509 *
510 * \sa drmOpenMinor() and drmGetBusid().
511 */
Daryll Strausse1dba5c1999-12-07 03:37:16 +0000512static int drmOpenByBusid(const char *busid)
513{
Benjamin Herrenschmidtb04515c2010-08-06 13:55:11 +1000514 int i, pci_domain_ok = 1;
Rik Faith88dbee52001-02-28 09:27:44 +0000515 int fd;
516 const char *buf;
Eric Anholt06cb1322003-10-23 02:23:31 +0000517 drmSetVersion sv;
518
519 drmMsg("drmOpenByBusid: Searching for BusID %s\n", busid);
Dave Airliedb85ed22008-02-13 12:20:02 +1000520 for (i = 0; i < DRM_MAX_MINOR; i++) {
Frank Binnsad8bbfd2015-01-14 14:07:50 +0000521 fd = drmOpenMinor(i, 1, DRM_NODE_PRIMARY);
David Dawes56bd9c22001-07-30 19:59:39 +0000522 drmMsg("drmOpenByBusid: drmOpenMinor returns %d\n", fd);
523 if (fd >= 0) {
Benjamin Herrenschmidtb04515c2010-08-06 13:55:11 +1000524 /* We need to try for 1.4 first for proper PCI domain support
525 * and if that fails, we know the kernel is busted
526 */
Eric Anholt06cb1322003-10-23 02:23:31 +0000527 sv.drm_di_major = 1;
Benjamin Herrenschmidtb04515c2010-08-06 13:55:11 +1000528 sv.drm_di_minor = 4;
Eric Anholt06cb1322003-10-23 02:23:31 +0000529 sv.drm_dd_major = -1; /* Don't care */
Eric Anholt26462b92005-12-31 11:48:12 +0000530 sv.drm_dd_minor = -1; /* Don't care */
Benjamin Herrenschmidtb04515c2010-08-06 13:55:11 +1000531 if (drmSetInterfaceVersion(fd, &sv)) {
532#ifndef __alpha__
533 pci_domain_ok = 0;
534#endif
535 sv.drm_di_major = 1;
536 sv.drm_di_minor = 1;
537 sv.drm_dd_major = -1; /* Don't care */
538 sv.drm_dd_minor = -1; /* Don't care */
Thierry Reding303ff262014-04-08 22:33:04 +0200539 drmMsg("drmOpenByBusid: Interface 1.4 failed, trying 1.1\n");
Benjamin Herrenschmidtb04515c2010-08-06 13:55:11 +1000540 drmSetInterfaceVersion(fd, &sv);
541 }
Daryll Strausse1dba5c1999-12-07 03:37:16 +0000542 buf = drmGetBusid(fd);
David Dawes56bd9c22001-07-30 19:59:39 +0000543 drmMsg("drmOpenByBusid: drmGetBusid reports %s\n", buf);
Benjamin Herrenschmidtb04515c2010-08-06 13:55:11 +1000544 if (buf && drmMatchBusID(buf, busid, pci_domain_ok)) {
Rik Faith88dbee52001-02-28 09:27:44 +0000545 drmFreeBusid(buf);
546 return fd;
Daryll Strausse1dba5c1999-12-07 03:37:16 +0000547 }
Brianccd7b6e2007-05-29 14:54:00 -0600548 if (buf)
549 drmFreeBusid(buf);
Daryll Strausse1dba5c1999-12-07 03:37:16 +0000550 close(fd);
551 }
552 }
553 return -1;
554}
555
Jose Fonsecad2443b22003-05-27 00:37:33 +0000556
557/**
558 * Open the device by name.
559 *
560 * \param name driver name.
561 *
562 * \return a file descriptor on success, or a negative value on error.
563 *
564 * \internal
565 * This function opens the first minor number that matches the driver name and
566 * isn't already in use. If it's in use it then it will already have a bus ID
567 * assigned.
568 *
569 * \sa drmOpenMinor(), drmGetVersion() and drmGetBusid().
570 */
Daryll Straussb6a28bf1999-12-05 23:10:37 +0000571static int drmOpenByName(const char *name)
Daryll Straussb3a57661999-12-05 01:19:48 +0000572{
Rik Faith88dbee52001-02-28 09:27:44 +0000573 int i;
574 int fd;
575 drmVersionPtr version;
David Dawes56bd9c22001-07-30 19:59:39 +0000576 char * id;
Dave Airliedb85ed22008-02-13 12:20:02 +1000577
David Dawes56bd9c22001-07-30 19:59:39 +0000578 /*
579 * Open the first minor number that matches the driver name and isn't
580 * already in use. If it's in use it will have a busid assigned already.
581 */
Dave Airliedb85ed22008-02-13 12:20:02 +1000582 for (i = 0; i < DRM_MAX_MINOR; i++) {
Frank Binnsad8bbfd2015-01-14 14:07:50 +0000583 if ((fd = drmOpenMinor(i, 1, DRM_NODE_PRIMARY)) >= 0) {
Rik Faith88dbee52001-02-28 09:27:44 +0000584 if ((version = drmGetVersion(fd))) {
585 if (!strcmp(version->name, name)) {
586 drmFreeVersion(version);
David Dawes56bd9c22001-07-30 19:59:39 +0000587 id = drmGetBusid(fd);
588 drmMsg("drmGetBusid returned '%s'\n", id ? id : "NULL");
589 if (!id || !*id) {
Adam Jackson22e41ef2006-02-20 23:09:00 +0000590 if (id)
David Dawes56bd9c22001-07-30 19:59:39 +0000591 drmFreeBusid(id);
David Dawes56bd9c22001-07-30 19:59:39 +0000592 return fd;
593 } else {
594 drmFreeBusid(id);
595 }
596 } else {
597 drmFreeVersion(version);
Rik Faith88dbee52001-02-28 09:27:44 +0000598 }
Rik Faith88dbee52001-02-28 09:27:44 +0000599 }
David Dawes56bd9c22001-07-30 19:59:39 +0000600 close(fd);
Rik Faith88dbee52001-02-28 09:27:44 +0000601 }
602 }
603
604#ifdef __linux__
Adam Jackson22e41ef2006-02-20 23:09:00 +0000605 /* Backward-compatibility /proc support */
Daryll Straussb6a28bf1999-12-05 23:10:37 +0000606 for (i = 0; i < 8; i++) {
Rik Faith88dbee52001-02-28 09:27:44 +0000607 char proc_name[64], buf[512];
608 char *driver, *pt, *devstring;
609 int retcode;
610
Daryll Strauss0371c291999-12-18 18:34:59 +0000611 sprintf(proc_name, "/proc/dri/%d/name", i);
Daryll Straussb6a28bf1999-12-05 23:10:37 +0000612 if ((fd = open(proc_name, 0, 0)) >= 0) {
613 retcode = read(fd, buf, sizeof(buf)-1);
614 close(fd);
615 if (retcode) {
616 buf[retcode-1] = '\0';
617 for (driver = pt = buf; *pt && *pt != ' '; ++pt)
618 ;
Adam Jackson22e41ef2006-02-20 23:09:00 +0000619 if (*pt) { /* Device is next */
Daryll Straussb6a28bf1999-12-05 23:10:37 +0000620 *pt = '\0';
621 if (!strcmp(driver, name)) { /* Match */
622 for (devstring = ++pt; *pt && *pt != ' '; ++pt)
623 ;
624 if (*pt) { /* Found busid */
Rik Faith88dbee52001-02-28 09:27:44 +0000625 return drmOpenByBusid(++pt);
Adam Jackson22e41ef2006-02-20 23:09:00 +0000626 } else { /* No busid */
Frank Binnsad8bbfd2015-01-14 14:07:50 +0000627 return drmOpenDevice(strtol(devstring, NULL, 0),i, DRM_NODE_PRIMARY);
Daryll Straussb6a28bf1999-12-05 23:10:37 +0000628 }
629 }
630 }
631 }
Brian Paul569da5a2000-06-08 14:38:22 +0000632 }
Daryll Straussb6a28bf1999-12-05 23:10:37 +0000633 }
Rik Faith88dbee52001-02-28 09:27:44 +0000634#endif
635
Daryll Straussb6a28bf1999-12-05 23:10:37 +0000636 return -1;
637}
638
Daryll Straussb6a28bf1999-12-05 23:10:37 +0000639
Jose Fonsecad2443b22003-05-27 00:37:33 +0000640/**
641 * Open the DRM device.
642 *
643 * Looks up the specified name and bus ID, and opens the device found. The
644 * entry in /dev/dri is created if necessary and if called by root.
645 *
646 * \param name driver name. Not referenced if bus ID is supplied.
647 * \param busid bus ID. Zero if not known.
648 *
649 * \return a file descriptor on success, or a negative value on error.
650 *
651 * \internal
652 * It calls drmOpenByBusid() if \p busid is specified or drmOpenByName()
653 * otherwise.
654 */
Daryll Straussb6a28bf1999-12-05 23:10:37 +0000655int drmOpen(const char *name, const char *busid)
Daryll Straussb3a57661999-12-05 01:19:48 +0000656{
Dave Airlie79038752006-11-08 15:08:09 +1100657 if (!drmAvailable() && name != NULL && drm_server_info) {
Eric Anholt06cb1322003-10-23 02:23:31 +0000658 /* try to load the kernel */
Dave Airlie79038752006-11-08 15:08:09 +1100659 if (!drm_server_info->load_module(name)) {
Brianccd7b6e2007-05-29 14:54:00 -0600660 drmMsg("[drm] failed to load kernel module \"%s\"\n", name);
Eric Anholt06cb1322003-10-23 02:23:31 +0000661 return -1;
662 }
663 }
Daryll Straussb6a28bf1999-12-05 23:10:37 +0000664
Eric Anholt06cb1322003-10-23 02:23:31 +0000665 if (busid) {
Brianccd7b6e2007-05-29 14:54:00 -0600666 int fd = drmOpenByBusid(busid);
Eric Anholt06cb1322003-10-23 02:23:31 +0000667 if (fd >= 0)
668 return fd;
669 }
Adam Jackson22e41ef2006-02-20 23:09:00 +0000670
Eric Anholt06cb1322003-10-23 02:23:31 +0000671 if (name)
672 return drmOpenByName(name);
Adam Jackson22e41ef2006-02-20 23:09:00 +0000673
Eric Anholt06cb1322003-10-23 02:23:31 +0000674 return -1;
Daryll Straussb3a57661999-12-05 01:19:48 +0000675}
676
Jesse Barnes731cd552008-12-17 10:09:49 -0800677int drmOpenControl(int minor)
678{
679 return drmOpenMinor(minor, 0, DRM_NODE_CONTROL);
680}
Jose Fonsecad2443b22003-05-27 00:37:33 +0000681
Frank Binns0c5aaee2015-01-14 14:07:51 +0000682int drmOpenRender(int minor)
683{
684 return drmOpenMinor(minor, 0, DRM_NODE_RENDER);
685}
686
Jose Fonsecad2443b22003-05-27 00:37:33 +0000687/**
688 * Free the version information returned by drmGetVersion().
689 *
690 * \param v pointer to the version information.
691 *
692 * \internal
693 * It frees the memory pointed by \p %v as well as all the non-null strings
694 * pointers in it.
695 */
Daryll Straussb3a57661999-12-05 01:19:48 +0000696void drmFreeVersion(drmVersionPtr v)
697{
Brianccd7b6e2007-05-29 14:54:00 -0600698 if (!v)
699 return;
Jakob Bornecrantz9d8ba2d2007-02-25 10:48:26 +1100700 drmFree(v->name);
701 drmFree(v->date);
702 drmFree(v->desc);
Daryll Straussb3a57661999-12-05 01:19:48 +0000703 drmFree(v);
704}
705
Jose Fonsecad2443b22003-05-27 00:37:33 +0000706
707/**
708 * Free the non-public version information returned by the kernel.
709 *
710 * \param v pointer to the version information.
711 *
712 * \internal
713 * Used by drmGetVersion() to free the memory pointed by \p %v as well as all
714 * the non-null strings pointers in it.
715 */
Daryll Straussb3a57661999-12-05 01:19:48 +0000716static void drmFreeKernelVersion(drm_version_t *v)
717{
Brianccd7b6e2007-05-29 14:54:00 -0600718 if (!v)
719 return;
Jakob Bornecrantz9d8ba2d2007-02-25 10:48:26 +1100720 drmFree(v->name);
721 drmFree(v->date);
722 drmFree(v->desc);
Daryll Straussb3a57661999-12-05 01:19:48 +0000723 drmFree(v);
724}
725
Jose Fonsecad2443b22003-05-27 00:37:33 +0000726
727/**
728 * Copy version information.
729 *
730 * \param d destination pointer.
731 * \param s source pointer.
732 *
733 * \internal
734 * Used by drmGetVersion() to translate the information returned by the ioctl
735 * interface in a private structure into the public structure counterpart.
736 */
Brian Paul569da5a2000-06-08 14:38:22 +0000737static void drmCopyVersion(drmVersionPtr d, const drm_version_t *s)
Daryll Straussb3a57661999-12-05 01:19:48 +0000738{
739 d->version_major = s->version_major;
740 d->version_minor = s->version_minor;
741 d->version_patchlevel = s->version_patchlevel;
742 d->name_len = s->name_len;
Adam Jackson0a1ff352010-10-27 18:44:53 -0400743 d->name = strdup(s->name);
Daryll Straussb3a57661999-12-05 01:19:48 +0000744 d->date_len = s->date_len;
Adam Jackson0a1ff352010-10-27 18:44:53 -0400745 d->date = strdup(s->date);
Daryll Straussb3a57661999-12-05 01:19:48 +0000746 d->desc_len = s->desc_len;
Adam Jackson0a1ff352010-10-27 18:44:53 -0400747 d->desc = strdup(s->desc);
Daryll Straussb3a57661999-12-05 01:19:48 +0000748}
749
Daryll Straussb3a57661999-12-05 01:19:48 +0000750
Jose Fonsecad2443b22003-05-27 00:37:33 +0000751/**
752 * Query the driver version information.
753 *
754 * \param fd file descriptor.
755 *
756 * \return pointer to a drmVersion structure which should be freed with
757 * drmFreeVersion().
758 *
759 * \note Similar information is available via /proc/dri.
760 *
761 * \internal
762 * It gets the version information via successive DRM_IOCTL_VERSION ioctls,
763 * first with zeros to get the string lengths, and then the actually strings.
764 * It also null-terminates them since they might not be already.
765 */
Daryll Straussb3a57661999-12-05 01:19:48 +0000766drmVersionPtr drmGetVersion(int fd)
767{
768 drmVersionPtr retval;
769 drm_version_t *version = drmMalloc(sizeof(*version));
770
Daniel Vetter95f23cf2015-02-11 17:25:30 +0100771 memclear(*version);
Gareth Hughes36047532001-02-15 08:12:14 +0000772
Keith Packard8b9ab102008-06-13 16:03:22 -0700773 if (drmIoctl(fd, DRM_IOCTL_VERSION, version)) {
Daryll Straussb3a57661999-12-05 01:19:48 +0000774 drmFreeKernelVersion(version);
775 return NULL;
776 }
777
Daryll Straussb3a57661999-12-05 01:19:48 +0000778 if (version->name_len)
779 version->name = drmMalloc(version->name_len + 1);
780 if (version->date_len)
781 version->date = drmMalloc(version->date_len + 1);
782 if (version->desc_len)
783 version->desc = drmMalloc(version->desc_len + 1);
Gareth Hughes36047532001-02-15 08:12:14 +0000784
Keith Packard8b9ab102008-06-13 16:03:22 -0700785 if (drmIoctl(fd, DRM_IOCTL_VERSION, version)) {
Alan Hourihaneb0a92852003-09-24 14:39:25 +0000786 drmMsg("DRM_IOCTL_VERSION: %s\n", strerror(errno));
Daryll Straussb3a57661999-12-05 01:19:48 +0000787 drmFreeKernelVersion(version);
788 return NULL;
789 }
790
Adam Jackson22e41ef2006-02-20 23:09:00 +0000791 /* The results might not be null-terminated strings, so terminate them. */
Daryll Straussb3a57661999-12-05 01:19:48 +0000792 if (version->name_len) version->name[version->name_len] = '\0';
793 if (version->date_len) version->date[version->date_len] = '\0';
794 if (version->desc_len) version->desc[version->desc_len] = '\0';
795
Daryll Straussb3a57661999-12-05 01:19:48 +0000796 retval = drmMalloc(sizeof(*retval));
797 drmCopyVersion(retval, version);
798 drmFreeKernelVersion(version);
799 return retval;
800}
801
Jens Owen3903e5a2002-04-09 21:54:56 +0000802
Jose Fonsecad2443b22003-05-27 00:37:33 +0000803/**
804 * Get version information for the DRM user space library.
805 *
806 * This version number is driver independent.
807 *
808 * \param fd file descriptor.
809 *
810 * \return version information.
811 *
812 * \internal
813 * This function allocates and fills a drm_version structure with a hard coded
814 * version number.
815 */
Jens Owen3903e5a2002-04-09 21:54:56 +0000816drmVersionPtr drmGetLibVersion(int fd)
817{
818 drm_version_t *version = drmMalloc(sizeof(*version));
819
820 /* Version history:
Dave Airlie79038752006-11-08 15:08:09 +1100821 * NOTE THIS MUST NOT GO ABOVE VERSION 1.X due to drivers needing it
Jens Owen3903e5a2002-04-09 21:54:56 +0000822 * revision 1.0.x = original DRM interface with no drmGetLibVersion
823 * entry point and many drm<Device> extensions
824 * revision 1.1.x = added drmCommand entry points for device extensions
825 * added drmGetLibVersion to identify libdrm.a version
Eric Anholt06cb1322003-10-23 02:23:31 +0000826 * revision 1.2.x = added drmSetInterfaceVersion
827 * modified drmOpen to handle both busid and name
Dave Airlie79038752006-11-08 15:08:09 +1100828 * revision 1.3.x = added server + memory manager
Jens Owen3903e5a2002-04-09 21:54:56 +0000829 */
Dave Airlie79038752006-11-08 15:08:09 +1100830 version->version_major = 1;
831 version->version_minor = 3;
Jens Owen3903e5a2002-04-09 21:54:56 +0000832 version->version_patchlevel = 0;
833
834 return (drmVersionPtr)version;
835}
836
Ben Skeggs5c6c6912011-02-21 11:27:19 +1000837int drmGetCap(int fd, uint64_t capability, uint64_t *value)
838{
Daniel Vetterfd387942015-02-11 12:41:04 +0100839 struct drm_get_cap cap;
Ben Skeggs5c6c6912011-02-21 11:27:19 +1000840 int ret;
841
Daniel Vetterfd387942015-02-11 12:41:04 +0100842 memclear(cap);
843 cap.capability = capability;
844
Ben Skeggs5c6c6912011-02-21 11:27:19 +1000845 ret = drmIoctl(fd, DRM_IOCTL_GET_CAP, &cap);
846 if (ret)
847 return ret;
848
849 *value = cap.value;
Dave Airlie3b04c732011-03-04 15:48:31 +1000850 return 0;
Ben Skeggs5c6c6912011-02-21 11:27:19 +1000851}
Jose Fonsecad2443b22003-05-27 00:37:33 +0000852
Damien Lespiauddbbdb12013-09-03 15:34:41 +0100853int drmSetClientCap(int fd, uint64_t capability, uint64_t value)
854{
Daniel Vetterfd387942015-02-11 12:41:04 +0100855 struct drm_set_client_cap cap;
856
857 memclear(cap);
858 cap.capability = capability;
859 cap.value = value;
Damien Lespiauddbbdb12013-09-03 15:34:41 +0100860
861 return drmIoctl(fd, DRM_IOCTL_SET_CLIENT_CAP, &cap);
862}
863
Jose Fonsecad2443b22003-05-27 00:37:33 +0000864/**
865 * Free the bus ID information.
866 *
867 * \param busid bus ID information string as given by drmGetBusid().
868 *
869 * \internal
870 * This function is just frees the memory pointed by \p busid.
871 */
Daryll Straussb6a28bf1999-12-05 23:10:37 +0000872void drmFreeBusid(const char *busid)
Daryll Straussb3a57661999-12-05 01:19:48 +0000873{
Daryll Straussb6a28bf1999-12-05 23:10:37 +0000874 drmFree((void *)busid);
Daryll Straussb3a57661999-12-05 01:19:48 +0000875}
876
Jose Fonsecad2443b22003-05-27 00:37:33 +0000877
878/**
879 * Get the bus ID of the device.
880 *
881 * \param fd file descriptor.
882 *
883 * \return bus ID string.
884 *
885 * \internal
886 * This function gets the bus ID via successive DRM_IOCTL_GET_UNIQUE ioctls to
887 * get the string length and data, passing the arguments in a drm_unique
888 * structure.
889 */
Daryll Straussb6a28bf1999-12-05 23:10:37 +0000890char *drmGetBusid(int fd)
Daryll Straussb3a57661999-12-05 01:19:48 +0000891{
Daryll Straussb6a28bf1999-12-05 23:10:37 +0000892 drm_unique_t u;
893
Daniel Vetterfd387942015-02-11 12:41:04 +0100894 memclear(u);
Daryll Straussb6a28bf1999-12-05 23:10:37 +0000895
Keith Packard8b9ab102008-06-13 16:03:22 -0700896 if (drmIoctl(fd, DRM_IOCTL_GET_UNIQUE, &u))
Brianccd7b6e2007-05-29 14:54:00 -0600897 return NULL;
Daryll Straussb6a28bf1999-12-05 23:10:37 +0000898 u.unique = drmMalloc(u.unique_len + 1);
Keith Packard8b9ab102008-06-13 16:03:22 -0700899 if (drmIoctl(fd, DRM_IOCTL_GET_UNIQUE, &u))
Brianccd7b6e2007-05-29 14:54:00 -0600900 return NULL;
Daryll Straussb6a28bf1999-12-05 23:10:37 +0000901 u.unique[u.unique_len] = '\0';
Eric Anholt06cb1322003-10-23 02:23:31 +0000902
Daryll Straussb6a28bf1999-12-05 23:10:37 +0000903 return u.unique;
Daryll Straussb3a57661999-12-05 01:19:48 +0000904}
905
Jose Fonsecad2443b22003-05-27 00:37:33 +0000906
907/**
908 * Set the bus ID of the device.
909 *
910 * \param fd file descriptor.
911 * \param busid bus ID string.
912 *
913 * \return zero on success, negative on failure.
914 *
915 * \internal
916 * This function is a wrapper around the DRM_IOCTL_SET_UNIQUE ioctl, passing
917 * the arguments in a drm_unique structure.
918 */
Daryll Straussb6a28bf1999-12-05 23:10:37 +0000919int drmSetBusid(int fd, const char *busid)
Daryll Straussb3a57661999-12-05 01:19:48 +0000920{
Daryll Straussb6a28bf1999-12-05 23:10:37 +0000921 drm_unique_t u;
Daryll Straussb3a57661999-12-05 01:19:48 +0000922
Daniel Vetterfd387942015-02-11 12:41:04 +0100923 memclear(u);
Daryll Straussb6a28bf1999-12-05 23:10:37 +0000924 u.unique = (char *)busid;
925 u.unique_len = strlen(busid);
Daryll Straussb3a57661999-12-05 01:19:48 +0000926
Keith Packard8b9ab102008-06-13 16:03:22 -0700927 if (drmIoctl(fd, DRM_IOCTL_SET_UNIQUE, &u)) {
David Dawes56bd9c22001-07-30 19:59:39 +0000928 return -errno;
929 }
Daryll Straussb3a57661999-12-05 01:19:48 +0000930 return 0;
931}
932
Jon Smirl8696e712004-07-07 04:36:36 +0000933int drmGetMagic(int fd, drm_magic_t * magic)
Daryll Straussb3a57661999-12-05 01:19:48 +0000934{
935 drm_auth_t auth;
936
Daniel Vetterfd387942015-02-11 12:41:04 +0100937 memclear(auth);
938
Daryll Straussb3a57661999-12-05 01:19:48 +0000939 *magic = 0;
Keith Packard8b9ab102008-06-13 16:03:22 -0700940 if (drmIoctl(fd, DRM_IOCTL_GET_MAGIC, &auth))
Brianccd7b6e2007-05-29 14:54:00 -0600941 return -errno;
Daryll Straussb3a57661999-12-05 01:19:48 +0000942 *magic = auth.magic;
943 return 0;
944}
945
Jon Smirl8696e712004-07-07 04:36:36 +0000946int drmAuthMagic(int fd, drm_magic_t magic)
Daryll Straussb3a57661999-12-05 01:19:48 +0000947{
948 drm_auth_t auth;
949
Daniel Vetterfd387942015-02-11 12:41:04 +0100950 memclear(auth);
Daryll Straussb3a57661999-12-05 01:19:48 +0000951 auth.magic = magic;
Keith Packard8b9ab102008-06-13 16:03:22 -0700952 if (drmIoctl(fd, DRM_IOCTL_AUTH_MAGIC, &auth))
Brianccd7b6e2007-05-29 14:54:00 -0600953 return -errno;
Daryll Straussb3a57661999-12-05 01:19:48 +0000954 return 0;
955}
956
Jose Fonsecad2443b22003-05-27 00:37:33 +0000957/**
958 * Specifies a range of memory that is available for mapping by a
959 * non-root process.
960 *
961 * \param fd file descriptor.
962 * \param offset usually the physical address. The actual meaning depends of
963 * the \p type parameter. See below.
964 * \param size of the memory in bytes.
965 * \param type type of the memory to be mapped.
966 * \param flags combination of several flags to modify the function actions.
967 * \param handle will be set to a value that may be used as the offset
968 * parameter for mmap().
969 *
970 * \return zero on success or a negative value on error.
971 *
972 * \par Mapping the frame buffer
973 * For the frame buffer
974 * - \p offset will be the physical address of the start of the frame buffer,
975 * - \p size will be the size of the frame buffer in bytes, and
976 * - \p type will be DRM_FRAME_BUFFER.
977 *
978 * \par
979 * The area mapped will be uncached. If MTRR support is available in the
980 * kernel, the frame buffer area will be set to write combining.
981 *
982 * \par Mapping the MMIO register area
983 * For the MMIO register area,
984 * - \p offset will be the physical address of the start of the register area,
985 * - \p size will be the size of the register area bytes, and
986 * - \p type will be DRM_REGISTERS.
987 * \par
988 * The area mapped will be uncached.
989 *
990 * \par Mapping the SAREA
991 * For the SAREA,
992 * - \p offset will be ignored and should be set to zero,
993 * - \p size will be the desired size of the SAREA in bytes,
994 * - \p type will be DRM_SHM.
995 *
996 * \par
997 * A shared memory area of the requested size will be created and locked in
998 * kernel memory. This area may be mapped into client-space by using the handle
999 * returned.
1000 *
1001 * \note May only be called by root.
1002 *
1003 * \internal
1004 * This function is a wrapper around the DRM_IOCTL_ADD_MAP ioctl, passing
1005 * the arguments in a drm_map structure.
1006 */
Adam Jackson22e41ef2006-02-20 23:09:00 +00001007int drmAddMap(int fd, drm_handle_t offset, drmSize size, drmMapType type,
1008 drmMapFlags flags, drm_handle_t *handle)
Daryll Straussb3a57661999-12-05 01:19:48 +00001009{
1010 drm_map_t map;
1011
Daniel Vetterfd387942015-02-11 12:41:04 +01001012 memclear(map);
Daryll Straussb3a57661999-12-05 01:19:48 +00001013 map.offset = offset;
1014 map.size = size;
Daryll Straussb3a57661999-12-05 01:19:48 +00001015 map.type = type;
1016 map.flags = flags;
Keith Packard8b9ab102008-06-13 16:03:22 -07001017 if (drmIoctl(fd, DRM_IOCTL_ADD_MAP, &map))
Brianccd7b6e2007-05-29 14:54:00 -06001018 return -errno;
1019 if (handle)
Jeremy Huddleston961bf9b2011-11-01 14:42:13 -07001020 *handle = (drm_handle_t)(uintptr_t)map.handle;
Daryll Straussb3a57661999-12-05 01:19:48 +00001021 return 0;
1022}
1023
Jon Smirl8696e712004-07-07 04:36:36 +00001024int drmRmMap(int fd, drm_handle_t handle)
Kevin E Martin74e19a42001-03-14 22:22:50 +00001025{
1026 drm_map_t map;
1027
Daniel Vetterfd387942015-02-11 12:41:04 +01001028 memclear(map);
Jeremy Huddleston961bf9b2011-11-01 14:42:13 -07001029 map.handle = (void *)(uintptr_t)handle;
Kevin E Martin74e19a42001-03-14 22:22:50 +00001030
Keith Packard8b9ab102008-06-13 16:03:22 -07001031 if(drmIoctl(fd, DRM_IOCTL_RM_MAP, &map))
Brianccd7b6e2007-05-29 14:54:00 -06001032 return -errno;
Kevin E Martin74e19a42001-03-14 22:22:50 +00001033 return 0;
1034}
1035
Jose Fonsecad2443b22003-05-27 00:37:33 +00001036/**
1037 * Make buffers available for DMA transfers.
1038 *
1039 * \param fd file descriptor.
1040 * \param count number of buffers.
1041 * \param size size of each buffer.
1042 * \param flags buffer allocation flags.
1043 * \param agp_offset offset in the AGP aperture
1044 *
1045 * \return number of buffers allocated, negative on error.
1046 *
1047 * \internal
1048 * This function is a wrapper around DRM_IOCTL_ADD_BUFS ioctl.
1049 *
1050 * \sa drm_buf_desc.
1051 */
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001052int drmAddBufs(int fd, int count, int size, drmBufDescFlags flags,
1053 int agp_offset)
Daryll Straussb3a57661999-12-05 01:19:48 +00001054{
1055 drm_buf_desc_t request;
Gareth Hughes36047532001-02-15 08:12:14 +00001056
Daniel Vetterfd387942015-02-11 12:41:04 +01001057 memclear(request);
Daryll Straussb3a57661999-12-05 01:19:48 +00001058 request.count = count;
1059 request.size = size;
Daryll Straussb3a57661999-12-05 01:19:48 +00001060 request.flags = flags;
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001061 request.agp_start = agp_offset;
Gareth Hughes36047532001-02-15 08:12:14 +00001062
Keith Packard8b9ab102008-06-13 16:03:22 -07001063 if (drmIoctl(fd, DRM_IOCTL_ADD_BUFS, &request))
Brianccd7b6e2007-05-29 14:54:00 -06001064 return -errno;
Daryll Straussb3a57661999-12-05 01:19:48 +00001065 return request.count;
1066}
1067
1068int drmMarkBufs(int fd, double low, double high)
1069{
1070 drm_buf_info_t info;
1071 int i;
1072
Daniel Vetterfd387942015-02-11 12:41:04 +01001073 memclear(info);
Daryll Straussb3a57661999-12-05 01:19:48 +00001074
Keith Packard8b9ab102008-06-13 16:03:22 -07001075 if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info))
Brianccd7b6e2007-05-29 14:54:00 -06001076 return -EINVAL;
Daryll Straussb3a57661999-12-05 01:19:48 +00001077
Brianccd7b6e2007-05-29 14:54:00 -06001078 if (!info.count)
1079 return -EINVAL;
Gareth Hughes36047532001-02-15 08:12:14 +00001080
Daryll Straussb3a57661999-12-05 01:19:48 +00001081 if (!(info.list = drmMalloc(info.count * sizeof(*info.list))))
1082 return -ENOMEM;
Gareth Hughes36047532001-02-15 08:12:14 +00001083
Keith Packard8b9ab102008-06-13 16:03:22 -07001084 if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info)) {
Daryll Straussb3a57661999-12-05 01:19:48 +00001085 int retval = -errno;
1086 drmFree(info.list);
1087 return retval;
1088 }
Gareth Hughes36047532001-02-15 08:12:14 +00001089
Daryll Straussb3a57661999-12-05 01:19:48 +00001090 for (i = 0; i < info.count; i++) {
1091 info.list[i].low_mark = low * info.list[i].count;
1092 info.list[i].high_mark = high * info.list[i].count;
Keith Packard8b9ab102008-06-13 16:03:22 -07001093 if (drmIoctl(fd, DRM_IOCTL_MARK_BUFS, &info.list[i])) {
Daryll Straussb3a57661999-12-05 01:19:48 +00001094 int retval = -errno;
1095 drmFree(info.list);
1096 return retval;
1097 }
1098 }
1099 drmFree(info.list);
Gareth Hughes36047532001-02-15 08:12:14 +00001100
Daryll Straussb3a57661999-12-05 01:19:48 +00001101 return 0;
1102}
1103
Jose Fonsecad2443b22003-05-27 00:37:33 +00001104/**
1105 * Free buffers.
1106 *
1107 * \param fd file descriptor.
1108 * \param count number of buffers to free.
1109 * \param list list of buffers to be freed.
1110 *
1111 * \return zero on success, or a negative value on failure.
1112 *
1113 * \note This function is primarily used for debugging.
1114 *
1115 * \internal
1116 * This function is a wrapper around the DRM_IOCTL_FREE_BUFS ioctl, passing
1117 * the arguments in a drm_buf_free structure.
1118 */
Daryll Straussb3a57661999-12-05 01:19:48 +00001119int drmFreeBufs(int fd, int count, int *list)
1120{
1121 drm_buf_free_t request;
1122
Daniel Vetterfd387942015-02-11 12:41:04 +01001123 memclear(request);
Daryll Straussb3a57661999-12-05 01:19:48 +00001124 request.count = count;
1125 request.list = list;
Keith Packard8b9ab102008-06-13 16:03:22 -07001126 if (drmIoctl(fd, DRM_IOCTL_FREE_BUFS, &request))
Brianccd7b6e2007-05-29 14:54:00 -06001127 return -errno;
Daryll Straussb3a57661999-12-05 01:19:48 +00001128 return 0;
1129}
1130
Jose Fonsecad2443b22003-05-27 00:37:33 +00001131
1132/**
1133 * Close the device.
1134 *
1135 * \param fd file descriptor.
1136 *
1137 * \internal
1138 * This function closes the file descriptor.
1139 */
Daryll Straussb6a28bf1999-12-05 23:10:37 +00001140int drmClose(int fd)
Daryll Straussb3a57661999-12-05 01:19:48 +00001141{
1142 unsigned long key = drmGetKeyFromFd(fd);
1143 drmHashEntry *entry = drmGetEntry(fd);
1144
1145 drmHashDestroy(entry->tagTable);
1146 entry->fd = 0;
1147 entry->f = NULL;
1148 entry->tagTable = NULL;
1149
1150 drmHashDelete(drmHashTable, key);
1151 drmFree(entry);
1152
1153 return close(fd);
1154}
1155
Jose Fonsecad2443b22003-05-27 00:37:33 +00001156
1157/**
1158 * Map a region of memory.
1159 *
1160 * \param fd file descriptor.
1161 * \param handle handle returned by drmAddMap().
1162 * \param size size in bytes. Must match the size used by drmAddMap().
1163 * \param address will contain the user-space virtual address where the mapping
1164 * begins.
1165 *
1166 * \return zero on success, or a negative value on failure.
1167 *
1168 * \internal
1169 * This function is a wrapper for mmap().
1170 */
Adam Jackson22e41ef2006-02-20 23:09:00 +00001171int drmMap(int fd, drm_handle_t handle, drmSize size, drmAddressPtr address)
Daryll Straussb3a57661999-12-05 01:19:48 +00001172{
Alan Hourihanec7558d82000-09-24 09:34:10 +00001173 static unsigned long pagesize_mask = 0;
1174
Brianccd7b6e2007-05-29 14:54:00 -06001175 if (fd < 0)
1176 return -EINVAL;
Alan Hourihanec7558d82000-09-24 09:34:10 +00001177
1178 if (!pagesize_mask)
1179 pagesize_mask = getpagesize() - 1;
1180
1181 size = (size + pagesize_mask) & ~pagesize_mask;
1182
Emil Velikovfaf51d52014-09-07 20:03:05 +01001183 *address = drm_mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, handle);
Brianccd7b6e2007-05-29 14:54:00 -06001184 if (*address == MAP_FAILED)
1185 return -errno;
Daryll Straussb3a57661999-12-05 01:19:48 +00001186 return 0;
1187}
1188
Jose Fonsecad2443b22003-05-27 00:37:33 +00001189
1190/**
1191 * Unmap mappings obtained with drmMap().
1192 *
1193 * \param address address as given by drmMap().
1194 * \param size size in bytes. Must match the size used by drmMap().
1195 *
1196 * \return zero on success, or a negative value on failure.
1197 *
1198 * \internal
Adam Jackson22e41ef2006-02-20 23:09:00 +00001199 * This function is a wrapper for munmap().
Jose Fonsecad2443b22003-05-27 00:37:33 +00001200 */
Daryll Straussb3a57661999-12-05 01:19:48 +00001201int drmUnmap(drmAddress address, drmSize size)
1202{
Emil Velikovfaf51d52014-09-07 20:03:05 +01001203 return drm_munmap(address, size);
Daryll Straussb3a57661999-12-05 01:19:48 +00001204}
1205
1206drmBufInfoPtr drmGetBufInfo(int fd)
1207{
1208 drm_buf_info_t info;
1209 drmBufInfoPtr retval;
1210 int i;
1211
Daniel Vetterfd387942015-02-11 12:41:04 +01001212 memclear(info);
Daryll Straussb3a57661999-12-05 01:19:48 +00001213
Keith Packard8b9ab102008-06-13 16:03:22 -07001214 if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info))
Brianccd7b6e2007-05-29 14:54:00 -06001215 return NULL;
Daryll Straussb3a57661999-12-05 01:19:48 +00001216
1217 if (info.count) {
1218 if (!(info.list = drmMalloc(info.count * sizeof(*info.list))))
1219 return NULL;
Gareth Hughes36047532001-02-15 08:12:14 +00001220
Keith Packard8b9ab102008-06-13 16:03:22 -07001221 if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info)) {
Daryll Straussb3a57661999-12-05 01:19:48 +00001222 drmFree(info.list);
1223 return NULL;
1224 }
Adam Jackson22e41ef2006-02-20 23:09:00 +00001225
Daryll Straussb3a57661999-12-05 01:19:48 +00001226 retval = drmMalloc(sizeof(*retval));
1227 retval->count = info.count;
1228 retval->list = drmMalloc(info.count * sizeof(*retval->list));
1229 for (i = 0; i < info.count; i++) {
1230 retval->list[i].count = info.list[i].count;
1231 retval->list[i].size = info.list[i].size;
1232 retval->list[i].low_mark = info.list[i].low_mark;
1233 retval->list[i].high_mark = info.list[i].high_mark;
1234 }
1235 drmFree(info.list);
1236 return retval;
1237 }
1238 return NULL;
1239}
1240
Jose Fonsecad2443b22003-05-27 00:37:33 +00001241/**
1242 * Map all DMA buffers into client-virtual space.
1243 *
1244 * \param fd file descriptor.
1245 *
1246 * \return a pointer to a ::drmBufMap structure.
1247 *
1248 * \note The client may not use these buffers until obtaining buffer indices
1249 * with drmDMA().
1250 *
1251 * \internal
1252 * This function calls the DRM_IOCTL_MAP_BUFS ioctl and copies the returned
1253 * information about the buffers in a drm_buf_map structure into the
1254 * client-visible data structures.
1255 */
Daryll Straussb3a57661999-12-05 01:19:48 +00001256drmBufMapPtr drmMapBufs(int fd)
1257{
1258 drm_buf_map_t bufs;
1259 drmBufMapPtr retval;
1260 int i;
Gareth Hughes36047532001-02-15 08:12:14 +00001261
Daniel Vetterfd387942015-02-11 12:41:04 +01001262 memclear(bufs);
Keith Packard8b9ab102008-06-13 16:03:22 -07001263 if (drmIoctl(fd, DRM_IOCTL_MAP_BUFS, &bufs))
Brianccd7b6e2007-05-29 14:54:00 -06001264 return NULL;
Daryll Straussb3a57661999-12-05 01:19:48 +00001265
Brianccd7b6e2007-05-29 14:54:00 -06001266 if (!bufs.count)
1267 return NULL;
Jon Smirl8696e712004-07-07 04:36:36 +00001268
Daryll Straussb3a57661999-12-05 01:19:48 +00001269 if (!(bufs.list = drmMalloc(bufs.count * sizeof(*bufs.list))))
1270 return NULL;
1271
Keith Packard8b9ab102008-06-13 16:03:22 -07001272 if (drmIoctl(fd, DRM_IOCTL_MAP_BUFS, &bufs)) {
Daryll Straussb3a57661999-12-05 01:19:48 +00001273 drmFree(bufs.list);
1274 return NULL;
1275 }
Adam Jackson22e41ef2006-02-20 23:09:00 +00001276
Daryll Straussb3a57661999-12-05 01:19:48 +00001277 retval = drmMalloc(sizeof(*retval));
1278 retval->count = bufs.count;
1279 retval->list = drmMalloc(bufs.count * sizeof(*retval->list));
1280 for (i = 0; i < bufs.count; i++) {
1281 retval->list[i].idx = bufs.list[i].idx;
1282 retval->list[i].total = bufs.list[i].total;
1283 retval->list[i].used = 0;
1284 retval->list[i].address = bufs.list[i].address;
1285 }
Jon Smirl8696e712004-07-07 04:36:36 +00001286
1287 drmFree(bufs.list);
1288
Daryll Straussb3a57661999-12-05 01:19:48 +00001289 return retval;
Daryll Straussb3a57661999-12-05 01:19:48 +00001290}
1291
Jose Fonsecad2443b22003-05-27 00:37:33 +00001292
1293/**
1294 * Unmap buffers allocated with drmMapBufs().
1295 *
1296 * \return zero on success, or negative value on failure.
1297 *
1298 * \internal
Jon Smirl8696e712004-07-07 04:36:36 +00001299 * Calls munmap() for every buffer stored in \p bufs and frees the
1300 * memory allocated by drmMapBufs().
Jose Fonsecad2443b22003-05-27 00:37:33 +00001301 */
Daryll Straussb3a57661999-12-05 01:19:48 +00001302int drmUnmapBufs(drmBufMapPtr bufs)
1303{
1304 int i;
Gareth Hughes36047532001-02-15 08:12:14 +00001305
Daryll Straussb3a57661999-12-05 01:19:48 +00001306 for (i = 0; i < bufs->count; i++) {
Emil Velikovfaf51d52014-09-07 20:03:05 +01001307 drm_munmap(bufs->list[i].address, bufs->list[i].total);
Daryll Straussb3a57661999-12-05 01:19:48 +00001308 }
Jon Smirl8696e712004-07-07 04:36:36 +00001309
1310 drmFree(bufs->list);
1311 drmFree(bufs);
1312
Daryll Straussb3a57661999-12-05 01:19:48 +00001313 return 0;
1314}
1315
Jose Fonsecad2443b22003-05-27 00:37:33 +00001316
Gareth Hughes36047532001-02-15 08:12:14 +00001317#define DRM_DMA_RETRY 16
1318
Jose Fonsecad2443b22003-05-27 00:37:33 +00001319/**
1320 * Reserve DMA buffers.
1321 *
1322 * \param fd file descriptor.
1323 * \param request
1324 *
1325 * \return zero on success, or a negative value on failure.
1326 *
1327 * \internal
1328 * Assemble the arguments into a drm_dma structure and keeps issuing the
1329 * DRM_IOCTL_DMA ioctl until success or until maximum number of retries.
1330 */
Daryll Straussb3a57661999-12-05 01:19:48 +00001331int drmDMA(int fd, drmDMAReqPtr request)
1332{
1333 drm_dma_t dma;
Gareth Hughes36047532001-02-15 08:12:14 +00001334 int ret, i = 0;
Daryll Straussb3a57661999-12-05 01:19:48 +00001335
Daryll Straussb3a57661999-12-05 01:19:48 +00001336 dma.context = request->context;
1337 dma.send_count = request->send_count;
1338 dma.send_indices = request->send_list;
1339 dma.send_sizes = request->send_sizes;
1340 dma.flags = request->flags;
1341 dma.request_count = request->request_count;
1342 dma.request_size = request->request_size;
1343 dma.request_indices = request->request_list;
1344 dma.request_sizes = request->request_sizes;
Jon Smirl8696e712004-07-07 04:36:36 +00001345 dma.granted_count = 0;
Gareth Hughes36047532001-02-15 08:12:14 +00001346
1347 do {
1348 ret = ioctl( fd, DRM_IOCTL_DMA, &dma );
1349 } while ( ret && errno == EAGAIN && i++ < DRM_DMA_RETRY );
1350
1351 if ( ret == 0 ) {
1352 request->granted_count = dma.granted_count;
1353 return 0;
1354 } else {
1355 return -errno;
1356 }
Daryll Straussb3a57661999-12-05 01:19:48 +00001357}
1358
Jose Fonsecad2443b22003-05-27 00:37:33 +00001359
1360/**
1361 * Obtain heavyweight hardware lock.
1362 *
1363 * \param fd file descriptor.
1364 * \param context context.
1365 * \param flags flags that determine the sate of the hardware when the function
1366 * returns.
1367 *
1368 * \return always zero.
1369 *
1370 * \internal
1371 * This function translates the arguments into a drm_lock structure and issue
1372 * the DRM_IOCTL_LOCK ioctl until the lock is successfully acquired.
1373 */
Jon Smirl8696e712004-07-07 04:36:36 +00001374int drmGetLock(int fd, drm_context_t context, drmLockFlags flags)
Daryll Straussb3a57661999-12-05 01:19:48 +00001375{
1376 drm_lock_t lock;
1377
Daniel Vetterfd387942015-02-11 12:41:04 +01001378 memclear(lock);
Daryll Straussb3a57661999-12-05 01:19:48 +00001379 lock.context = context;
1380 lock.flags = 0;
1381 if (flags & DRM_LOCK_READY) lock.flags |= _DRM_LOCK_READY;
1382 if (flags & DRM_LOCK_QUIESCENT) lock.flags |= _DRM_LOCK_QUIESCENT;
1383 if (flags & DRM_LOCK_FLUSH) lock.flags |= _DRM_LOCK_FLUSH;
1384 if (flags & DRM_LOCK_FLUSH_ALL) lock.flags |= _DRM_LOCK_FLUSH_ALL;
1385 if (flags & DRM_HALT_ALL_QUEUES) lock.flags |= _DRM_HALT_ALL_QUEUES;
1386 if (flags & DRM_HALT_CUR_QUEUES) lock.flags |= _DRM_HALT_CUR_QUEUES;
Gareth Hughes36047532001-02-15 08:12:14 +00001387
Keith Packard8b9ab102008-06-13 16:03:22 -07001388 while (drmIoctl(fd, DRM_IOCTL_LOCK, &lock))
Daryll Straussb3a57661999-12-05 01:19:48 +00001389 ;
1390 return 0;
1391}
1392
Jose Fonsecad2443b22003-05-27 00:37:33 +00001393/**
1394 * Release the hardware lock.
1395 *
1396 * \param fd file descriptor.
1397 * \param context context.
1398 *
1399 * \return zero on success, or a negative value on failure.
1400 *
1401 * \internal
1402 * This function is a wrapper around the DRM_IOCTL_UNLOCK ioctl, passing the
1403 * argument in a drm_lock structure.
1404 */
Jon Smirl8696e712004-07-07 04:36:36 +00001405int drmUnlock(int fd, drm_context_t context)
Daryll Straussb3a57661999-12-05 01:19:48 +00001406{
1407 drm_lock_t lock;
1408
Daniel Vetterfd387942015-02-11 12:41:04 +01001409 memclear(lock);
Daryll Straussb3a57661999-12-05 01:19:48 +00001410 lock.context = context;
Keith Packard8b9ab102008-06-13 16:03:22 -07001411 return drmIoctl(fd, DRM_IOCTL_UNLOCK, &lock);
Daryll Straussb3a57661999-12-05 01:19:48 +00001412}
1413
Adam Jackson22e41ef2006-02-20 23:09:00 +00001414drm_context_t *drmGetReservedContextList(int fd, int *count)
Daryll Straussb3a57661999-12-05 01:19:48 +00001415{
1416 drm_ctx_res_t res;
1417 drm_ctx_t *list;
Jon Smirl8696e712004-07-07 04:36:36 +00001418 drm_context_t * retval;
Daryll Straussb3a57661999-12-05 01:19:48 +00001419 int i;
1420
Daniel Vetterfd387942015-02-11 12:41:04 +01001421 memclear(res);
Keith Packard8b9ab102008-06-13 16:03:22 -07001422 if (drmIoctl(fd, DRM_IOCTL_RES_CTX, &res))
Brianccd7b6e2007-05-29 14:54:00 -06001423 return NULL;
Daryll Straussb3a57661999-12-05 01:19:48 +00001424
Brianccd7b6e2007-05-29 14:54:00 -06001425 if (!res.count)
1426 return NULL;
Daryll Straussb3a57661999-12-05 01:19:48 +00001427
Brianccd7b6e2007-05-29 14:54:00 -06001428 if (!(list = drmMalloc(res.count * sizeof(*list))))
1429 return NULL;
Daryll Straussb3a57661999-12-05 01:19:48 +00001430 if (!(retval = drmMalloc(res.count * sizeof(*retval)))) {
1431 drmFree(list);
1432 return NULL;
1433 }
1434
1435 res.contexts = list;
Keith Packard8b9ab102008-06-13 16:03:22 -07001436 if (drmIoctl(fd, DRM_IOCTL_RES_CTX, &res))
Brianccd7b6e2007-05-29 14:54:00 -06001437 return NULL;
Daryll Straussb3a57661999-12-05 01:19:48 +00001438
Brianccd7b6e2007-05-29 14:54:00 -06001439 for (i = 0; i < res.count; i++)
1440 retval[i] = list[i].handle;
Daryll Straussb3a57661999-12-05 01:19:48 +00001441 drmFree(list);
1442
1443 *count = res.count;
1444 return retval;
1445}
1446
Adam Jackson22e41ef2006-02-20 23:09:00 +00001447void drmFreeReservedContextList(drm_context_t *pt)
Daryll Straussb3a57661999-12-05 01:19:48 +00001448{
1449 drmFree(pt);
1450}
1451
Jose Fonsecad2443b22003-05-27 00:37:33 +00001452/**
1453 * Create context.
1454 *
1455 * Used by the X server during GLXContext initialization. This causes
1456 * per-context kernel-level resources to be allocated.
1457 *
1458 * \param fd file descriptor.
1459 * \param handle is set on success. To be used by the client when requesting DMA
1460 * dispatch with drmDMA().
1461 *
1462 * \return zero on success, or a negative value on failure.
1463 *
1464 * \note May only be called by root.
1465 *
1466 * \internal
1467 * This function is a wrapper around the DRM_IOCTL_ADD_CTX ioctl, passing the
1468 * argument in a drm_ctx structure.
1469 */
Adam Jackson22e41ef2006-02-20 23:09:00 +00001470int drmCreateContext(int fd, drm_context_t *handle)
Daryll Straussb3a57661999-12-05 01:19:48 +00001471{
1472 drm_ctx_t ctx;
1473
Daniel Vetterfd387942015-02-11 12:41:04 +01001474 memclear(ctx);
Keith Packard8b9ab102008-06-13 16:03:22 -07001475 if (drmIoctl(fd, DRM_IOCTL_ADD_CTX, &ctx))
Brianccd7b6e2007-05-29 14:54:00 -06001476 return -errno;
Daryll Straussb3a57661999-12-05 01:19:48 +00001477 *handle = ctx.handle;
1478 return 0;
1479}
1480
Jon Smirl8696e712004-07-07 04:36:36 +00001481int drmSwitchToContext(int fd, drm_context_t context)
Daryll Straussb3a57661999-12-05 01:19:48 +00001482{
1483 drm_ctx_t ctx;
1484
Daniel Vetterfd387942015-02-11 12:41:04 +01001485 memclear(ctx);
Daryll Straussb3a57661999-12-05 01:19:48 +00001486 ctx.handle = context;
Keith Packard8b9ab102008-06-13 16:03:22 -07001487 if (drmIoctl(fd, DRM_IOCTL_SWITCH_CTX, &ctx))
Brianccd7b6e2007-05-29 14:54:00 -06001488 return -errno;
Daryll Straussb3a57661999-12-05 01:19:48 +00001489 return 0;
1490}
1491
Jon Smirl8696e712004-07-07 04:36:36 +00001492int drmSetContextFlags(int fd, drm_context_t context, drm_context_tFlags flags)
Daryll Straussb3a57661999-12-05 01:19:48 +00001493{
1494 drm_ctx_t ctx;
1495
Adam Jackson22e41ef2006-02-20 23:09:00 +00001496 /*
1497 * Context preserving means that no context switches are done between DMA
1498 * buffers from one context and the next. This is suitable for use in the
1499 * X server (which promises to maintain hardware context), or in the
1500 * client-side library when buffers are swapped on behalf of two threads.
1501 */
Daniel Vetterfd387942015-02-11 12:41:04 +01001502 memclear(ctx);
Daryll Straussb3a57661999-12-05 01:19:48 +00001503 ctx.handle = context;
Brianccd7b6e2007-05-29 14:54:00 -06001504 if (flags & DRM_CONTEXT_PRESERVED)
1505 ctx.flags |= _DRM_CONTEXT_PRESERVED;
1506 if (flags & DRM_CONTEXT_2DONLY)
1507 ctx.flags |= _DRM_CONTEXT_2DONLY;
Keith Packard8b9ab102008-06-13 16:03:22 -07001508 if (drmIoctl(fd, DRM_IOCTL_MOD_CTX, &ctx))
Brianccd7b6e2007-05-29 14:54:00 -06001509 return -errno;
Daryll Straussb3a57661999-12-05 01:19:48 +00001510 return 0;
1511}
1512
Adam Jackson22e41ef2006-02-20 23:09:00 +00001513int drmGetContextFlags(int fd, drm_context_t context,
1514 drm_context_tFlagsPtr flags)
Daryll Straussb3a57661999-12-05 01:19:48 +00001515{
1516 drm_ctx_t ctx;
1517
Daniel Vetterfd387942015-02-11 12:41:04 +01001518 memclear(ctx);
Daryll Straussb3a57661999-12-05 01:19:48 +00001519 ctx.handle = context;
Keith Packard8b9ab102008-06-13 16:03:22 -07001520 if (drmIoctl(fd, DRM_IOCTL_GET_CTX, &ctx))
Brianccd7b6e2007-05-29 14:54:00 -06001521 return -errno;
Daryll Straussb3a57661999-12-05 01:19:48 +00001522 *flags = 0;
Brianccd7b6e2007-05-29 14:54:00 -06001523 if (ctx.flags & _DRM_CONTEXT_PRESERVED)
1524 *flags |= DRM_CONTEXT_PRESERVED;
1525 if (ctx.flags & _DRM_CONTEXT_2DONLY)
1526 *flags |= DRM_CONTEXT_2DONLY;
Daryll Straussb3a57661999-12-05 01:19:48 +00001527 return 0;
1528}
Gareth Hughes36047532001-02-15 08:12:14 +00001529
Jose Fonsecad2443b22003-05-27 00:37:33 +00001530/**
1531 * Destroy context.
1532 *
1533 * Free any kernel-level resources allocated with drmCreateContext() associated
1534 * with the context.
1535 *
1536 * \param fd file descriptor.
1537 * \param handle handle given by drmCreateContext().
1538 *
1539 * \return zero on success, or a negative value on failure.
1540 *
1541 * \note May only be called by root.
1542 *
1543 * \internal
1544 * This function is a wrapper around the DRM_IOCTL_RM_CTX ioctl, passing the
1545 * argument in a drm_ctx structure.
1546 */
Jon Smirl8696e712004-07-07 04:36:36 +00001547int drmDestroyContext(int fd, drm_context_t handle)
Daryll Straussb3a57661999-12-05 01:19:48 +00001548{
1549 drm_ctx_t ctx;
Daniel Vetterfd387942015-02-11 12:41:04 +01001550
1551 memclear(ctx);
Daryll Straussb3a57661999-12-05 01:19:48 +00001552 ctx.handle = handle;
Keith Packard8b9ab102008-06-13 16:03:22 -07001553 if (drmIoctl(fd, DRM_IOCTL_RM_CTX, &ctx))
Brianccd7b6e2007-05-29 14:54:00 -06001554 return -errno;
Daryll Straussb3a57661999-12-05 01:19:48 +00001555 return 0;
1556}
1557
Adam Jackson22e41ef2006-02-20 23:09:00 +00001558int drmCreateDrawable(int fd, drm_drawable_t *handle)
Daryll Straussb3a57661999-12-05 01:19:48 +00001559{
1560 drm_draw_t draw;
Daniel Vetterfd387942015-02-11 12:41:04 +01001561
1562 memclear(draw);
Keith Packard8b9ab102008-06-13 16:03:22 -07001563 if (drmIoctl(fd, DRM_IOCTL_ADD_DRAW, &draw))
Brianccd7b6e2007-05-29 14:54:00 -06001564 return -errno;
Daryll Straussb3a57661999-12-05 01:19:48 +00001565 *handle = draw.handle;
1566 return 0;
1567}
1568
Jon Smirl8696e712004-07-07 04:36:36 +00001569int drmDestroyDrawable(int fd, drm_drawable_t handle)
Daryll Straussb3a57661999-12-05 01:19:48 +00001570{
1571 drm_draw_t draw;
Daniel Vetterfd387942015-02-11 12:41:04 +01001572
1573 memclear(draw);
Daryll Straussb3a57661999-12-05 01:19:48 +00001574 draw.handle = handle;
Keith Packard8b9ab102008-06-13 16:03:22 -07001575 if (drmIoctl(fd, DRM_IOCTL_RM_DRAW, &draw))
Brianccd7b6e2007-05-29 14:54:00 -06001576 return -errno;
Daryll Straussb3a57661999-12-05 01:19:48 +00001577 return 0;
1578}
1579
Michel Dänzer9810ec22006-08-22 16:40:07 +02001580int drmUpdateDrawableInfo(int fd, drm_drawable_t handle,
1581 drm_drawable_info_type_t type, unsigned int num,
1582 void *data)
1583{
1584 drm_update_draw_t update;
1585
Daniel Vetterfd387942015-02-11 12:41:04 +01001586 memclear(update);
Michel Dänzer9810ec22006-08-22 16:40:07 +02001587 update.handle = handle;
1588 update.type = type;
1589 update.num = num;
1590 update.data = (unsigned long long)(unsigned long)data;
1591
Keith Packard8b9ab102008-06-13 16:03:22 -07001592 if (drmIoctl(fd, DRM_IOCTL_UPDATE_DRAW, &update))
Brianccd7b6e2007-05-29 14:54:00 -06001593 return -errno;
Michel Dänzer9810ec22006-08-22 16:40:07 +02001594
1595 return 0;
1596}
1597
Jose Fonsecad2443b22003-05-27 00:37:33 +00001598/**
1599 * Acquire the AGP device.
1600 *
1601 * Must be called before any of the other AGP related calls.
1602 *
1603 * \param fd file descriptor.
1604 *
1605 * \return zero on success, or a negative value on failure.
1606 *
1607 * \internal
1608 * This function is a wrapper around the DRM_IOCTL_AGP_ACQUIRE ioctl.
1609 */
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001610int drmAgpAcquire(int fd)
1611{
Keith Packard8b9ab102008-06-13 16:03:22 -07001612 if (drmIoctl(fd, DRM_IOCTL_AGP_ACQUIRE, NULL))
Brianccd7b6e2007-05-29 14:54:00 -06001613 return -errno;
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001614 return 0;
1615}
1616
Jose Fonsecad2443b22003-05-27 00:37:33 +00001617
1618/**
1619 * Release the AGP device.
1620 *
1621 * \param fd file descriptor.
1622 *
1623 * \return zero on success, or a negative value on failure.
1624 *
1625 * \internal
1626 * This function is a wrapper around the DRM_IOCTL_AGP_RELEASE ioctl.
1627 */
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001628int drmAgpRelease(int fd)
1629{
Keith Packard8b9ab102008-06-13 16:03:22 -07001630 if (drmIoctl(fd, DRM_IOCTL_AGP_RELEASE, NULL))
Brianccd7b6e2007-05-29 14:54:00 -06001631 return -errno;
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001632 return 0;
1633}
1634
Jose Fonsecad2443b22003-05-27 00:37:33 +00001635
1636/**
1637 * Set the AGP mode.
1638 *
1639 * \param fd file descriptor.
1640 * \param mode AGP mode.
1641 *
1642 * \return zero on success, or a negative value on failure.
1643 *
1644 * \internal
1645 * This function is a wrapper around the DRM_IOCTL_AGP_ENABLE ioctl, passing the
1646 * argument in a drm_agp_mode structure.
1647 */
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001648int drmAgpEnable(int fd, unsigned long mode)
1649{
1650 drm_agp_mode_t m;
1651
Daniel Vetterfd387942015-02-11 12:41:04 +01001652 memclear(mode);
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001653 m.mode = mode;
Keith Packard8b9ab102008-06-13 16:03:22 -07001654 if (drmIoctl(fd, DRM_IOCTL_AGP_ENABLE, &m))
Brianccd7b6e2007-05-29 14:54:00 -06001655 return -errno;
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001656 return 0;
1657}
1658
Jose Fonsecad2443b22003-05-27 00:37:33 +00001659
1660/**
1661 * Allocate a chunk of AGP memory.
1662 *
1663 * \param fd file descriptor.
1664 * \param size requested memory size in bytes. Will be rounded to page boundary.
1665 * \param type type of memory to allocate.
1666 * \param address if not zero, will be set to the physical address of the
1667 * allocated memory.
1668 * \param handle on success will be set to a handle of the allocated memory.
1669 *
1670 * \return zero on success, or a negative value on failure.
1671 *
1672 * \internal
1673 * This function is a wrapper around the DRM_IOCTL_AGP_ALLOC ioctl, passing the
1674 * arguments in a drm_agp_buffer structure.
1675 */
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001676int drmAgpAlloc(int fd, unsigned long size, unsigned long type,
Dave Airlie7ede2092005-11-29 09:50:47 +00001677 unsigned long *address, drm_handle_t *handle)
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001678{
1679 drm_agp_buffer_t b;
Alan Hourihaneb0a92852003-09-24 14:39:25 +00001680
Daniel Vetterfd387942015-02-11 12:41:04 +01001681 memclear(b);
Alan Hourihaneb0a92852003-09-24 14:39:25 +00001682 *handle = DRM_AGP_NO_HANDLE;
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001683 b.size = size;
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001684 b.type = type;
Keith Packard8b9ab102008-06-13 16:03:22 -07001685 if (drmIoctl(fd, DRM_IOCTL_AGP_ALLOC, &b))
Brianccd7b6e2007-05-29 14:54:00 -06001686 return -errno;
1687 if (address != 0UL)
1688 *address = b.physical;
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001689 *handle = b.handle;
1690 return 0;
1691}
1692
Jose Fonsecad2443b22003-05-27 00:37:33 +00001693
1694/**
1695 * Free a chunk of AGP memory.
1696 *
1697 * \param fd file descriptor.
1698 * \param handle handle to the allocated memory, as given by drmAgpAllocate().
1699 *
1700 * \return zero on success, or a negative value on failure.
1701 *
1702 * \internal
1703 * This function is a wrapper around the DRM_IOCTL_AGP_FREE ioctl, passing the
1704 * argument in a drm_agp_buffer structure.
1705 */
Dave Airlie7ede2092005-11-29 09:50:47 +00001706int drmAgpFree(int fd, drm_handle_t handle)
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001707{
1708 drm_agp_buffer_t b;
1709
Daniel Vetterfd387942015-02-11 12:41:04 +01001710 memclear(b);
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001711 b.handle = handle;
Keith Packard8b9ab102008-06-13 16:03:22 -07001712 if (drmIoctl(fd, DRM_IOCTL_AGP_FREE, &b))
Brianccd7b6e2007-05-29 14:54:00 -06001713 return -errno;
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001714 return 0;
1715}
1716
Jose Fonsecad2443b22003-05-27 00:37:33 +00001717
1718/**
1719 * Bind a chunk of AGP memory.
1720 *
1721 * \param fd file descriptor.
1722 * \param handle handle to the allocated memory, as given by drmAgpAllocate().
1723 * \param offset offset in bytes. It will round to page boundary.
1724 *
1725 * \return zero on success, or a negative value on failure.
1726 *
1727 * \internal
1728 * This function is a wrapper around the DRM_IOCTL_AGP_BIND ioctl, passing the
1729 * argument in a drm_agp_binding structure.
1730 */
Dave Airlie7ede2092005-11-29 09:50:47 +00001731int drmAgpBind(int fd, drm_handle_t handle, unsigned long offset)
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001732{
1733 drm_agp_binding_t b;
1734
Daniel Vetterfd387942015-02-11 12:41:04 +01001735 memclear(b);
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001736 b.handle = handle;
1737 b.offset = offset;
Keith Packard8b9ab102008-06-13 16:03:22 -07001738 if (drmIoctl(fd, DRM_IOCTL_AGP_BIND, &b))
Brianccd7b6e2007-05-29 14:54:00 -06001739 return -errno;
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001740 return 0;
1741}
1742
Jose Fonsecad2443b22003-05-27 00:37:33 +00001743
1744/**
1745 * Unbind a chunk of AGP memory.
1746 *
1747 * \param fd file descriptor.
1748 * \param handle handle to the allocated memory, as given by drmAgpAllocate().
1749 *
1750 * \return zero on success, or a negative value on failure.
1751 *
1752 * \internal
1753 * This function is a wrapper around the DRM_IOCTL_AGP_UNBIND ioctl, passing
1754 * the argument in a drm_agp_binding structure.
1755 */
Dave Airlie7ede2092005-11-29 09:50:47 +00001756int drmAgpUnbind(int fd, drm_handle_t handle)
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001757{
1758 drm_agp_binding_t b;
1759
Daniel Vetterfd387942015-02-11 12:41:04 +01001760 memclear(b);
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001761 b.handle = handle;
Keith Packard8b9ab102008-06-13 16:03:22 -07001762 if (drmIoctl(fd, DRM_IOCTL_AGP_UNBIND, &b))
Brianccd7b6e2007-05-29 14:54:00 -06001763 return -errno;
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001764 return 0;
1765}
1766
Jose Fonsecad2443b22003-05-27 00:37:33 +00001767
1768/**
1769 * Get AGP driver major version number.
1770 *
1771 * \param fd file descriptor.
1772 *
1773 * \return major version number on success, or a negative value on failure..
1774 *
1775 * \internal
1776 * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1777 * necessary information in a drm_agp_info structure.
1778 */
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001779int drmAgpVersionMajor(int fd)
1780{
1781 drm_agp_info_t i;
1782
Daniel Vetterfd387942015-02-11 12:41:04 +01001783 memclear(i);
1784
Keith Packard8b9ab102008-06-13 16:03:22 -07001785 if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
Brianccd7b6e2007-05-29 14:54:00 -06001786 return -errno;
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001787 return i.agp_version_major;
1788}
1789
Jose Fonsecad2443b22003-05-27 00:37:33 +00001790
1791/**
1792 * Get AGP driver minor version number.
1793 *
1794 * \param fd file descriptor.
1795 *
1796 * \return minor version number on success, or a negative value on failure.
1797 *
1798 * \internal
1799 * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1800 * necessary information in a drm_agp_info structure.
1801 */
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001802int drmAgpVersionMinor(int fd)
1803{
1804 drm_agp_info_t i;
1805
Daniel Vetterfd387942015-02-11 12:41:04 +01001806 memclear(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 -errno;
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001810 return i.agp_version_minor;
1811}
1812
Jose Fonsecad2443b22003-05-27 00:37:33 +00001813
1814/**
1815 * Get AGP mode.
1816 *
1817 * \param fd file descriptor.
1818 *
1819 * \return mode on success, or 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 drmAgpGetMode(int fd)
1826{
1827 drm_agp_info_t i;
1828
Daniel Vetterfd387942015-02-11 12:41:04 +01001829 memclear(i);
1830
Keith Packard8b9ab102008-06-13 16:03:22 -07001831 if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
Brianccd7b6e2007-05-29 14:54:00 -06001832 return 0;
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001833 return i.mode;
1834}
1835
Jose Fonsecad2443b22003-05-27 00:37:33 +00001836
1837/**
1838 * Get AGP aperture base.
1839 *
1840 * \param fd file descriptor.
1841 *
1842 * \return aperture base on success, zero on failure.
1843 *
1844 * \internal
1845 * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1846 * necessary information in a drm_agp_info structure.
1847 */
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001848unsigned long drmAgpBase(int fd)
1849{
1850 drm_agp_info_t i;
1851
Daniel Vetterfd387942015-02-11 12:41:04 +01001852 memclear(i);
1853
Keith Packard8b9ab102008-06-13 16:03:22 -07001854 if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
Brianccd7b6e2007-05-29 14:54:00 -06001855 return 0;
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001856 return i.aperture_base;
1857}
1858
Jose Fonsecad2443b22003-05-27 00:37:33 +00001859
1860/**
1861 * Get AGP aperture size.
1862 *
1863 * \param fd file descriptor.
1864 *
1865 * \return aperture size on success, zero on failure.
1866 *
1867 * \internal
1868 * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1869 * necessary information in a drm_agp_info structure.
1870 */
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001871unsigned long drmAgpSize(int fd)
1872{
1873 drm_agp_info_t i;
1874
Daniel Vetterfd387942015-02-11 12:41:04 +01001875 memclear(i);
1876
Keith Packard8b9ab102008-06-13 16:03:22 -07001877 if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
Brianccd7b6e2007-05-29 14:54:00 -06001878 return 0;
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001879 return i.aperture_size;
1880}
1881
Jose Fonsecad2443b22003-05-27 00:37:33 +00001882
1883/**
1884 * Get used AGP memory.
1885 *
1886 * \param fd file descriptor.
1887 *
1888 * \return memory used on success, or zero on failure.
1889 *
1890 * \internal
1891 * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1892 * necessary information in a drm_agp_info structure.
1893 */
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001894unsigned long drmAgpMemoryUsed(int fd)
1895{
1896 drm_agp_info_t i;
1897
Daniel Vetterfd387942015-02-11 12:41:04 +01001898 memclear(i);
1899
Keith Packard8b9ab102008-06-13 16:03:22 -07001900 if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
Brianccd7b6e2007-05-29 14:54:00 -06001901 return 0;
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001902 return i.memory_used;
1903}
1904
Jose Fonsecad2443b22003-05-27 00:37:33 +00001905
1906/**
1907 * Get available AGP memory.
1908 *
1909 * \param fd file descriptor.
1910 *
1911 * \return memory available on success, or zero on failure.
1912 *
1913 * \internal
1914 * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1915 * necessary information in a drm_agp_info structure.
1916 */
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001917unsigned long drmAgpMemoryAvail(int fd)
1918{
1919 drm_agp_info_t i;
1920
Daniel Vetterfd387942015-02-11 12:41:04 +01001921 memclear(i);
1922
Keith Packard8b9ab102008-06-13 16:03:22 -07001923 if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
Brianccd7b6e2007-05-29 14:54:00 -06001924 return 0;
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001925 return i.memory_allowed;
1926}
1927
Jose Fonsecad2443b22003-05-27 00:37:33 +00001928
1929/**
1930 * Get hardware vendor ID.
1931 *
1932 * \param fd file descriptor.
1933 *
1934 * \return vendor ID on success, or zero on failure.
1935 *
1936 * \internal
1937 * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1938 * necessary information in a drm_agp_info structure.
1939 */
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001940unsigned int drmAgpVendorId(int fd)
1941{
1942 drm_agp_info_t i;
1943
Daniel Vetterfd387942015-02-11 12:41:04 +01001944 memclear(i);
1945
Keith Packard8b9ab102008-06-13 16:03:22 -07001946 if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
Brianccd7b6e2007-05-29 14:54:00 -06001947 return 0;
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001948 return i.id_vendor;
1949}
1950
Jose Fonsecad2443b22003-05-27 00:37:33 +00001951
1952/**
1953 * Get hardware device ID.
1954 *
1955 * \param fd file descriptor.
1956 *
1957 * \return zero on success, or zero on failure.
1958 *
1959 * \internal
1960 * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1961 * necessary information in a drm_agp_info structure.
1962 */
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001963unsigned int drmAgpDeviceId(int fd)
1964{
1965 drm_agp_info_t i;
1966
Daniel Vetterfd387942015-02-11 12:41:04 +01001967 memclear(i);
1968
Keith Packard8b9ab102008-06-13 16:03:22 -07001969 if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
Brianccd7b6e2007-05-29 14:54:00 -06001970 return 0;
Jeff Hartmannba1b1ae2000-04-04 22:08:14 +00001971 return i.id_device;
1972}
1973
Dave Airlie7ede2092005-11-29 09:50:47 +00001974int drmScatterGatherAlloc(int fd, unsigned long size, drm_handle_t *handle)
Kevin E Martin5d6ddbc2001-04-05 22:16:12 +00001975{
1976 drm_scatter_gather_t sg;
1977
Daniel Vetterfd387942015-02-11 12:41:04 +01001978 memclear(sg);
1979
Kevin E Martin5d6ddbc2001-04-05 22:16:12 +00001980 *handle = 0;
1981 sg.size = size;
Keith Packard8b9ab102008-06-13 16:03:22 -07001982 if (drmIoctl(fd, DRM_IOCTL_SG_ALLOC, &sg))
Brianccd7b6e2007-05-29 14:54:00 -06001983 return -errno;
Kevin E Martin5d6ddbc2001-04-05 22:16:12 +00001984 *handle = sg.handle;
1985 return 0;
1986}
1987
Dave Airlie7ede2092005-11-29 09:50:47 +00001988int drmScatterGatherFree(int fd, drm_handle_t handle)
Kevin E Martin5d6ddbc2001-04-05 22:16:12 +00001989{
1990 drm_scatter_gather_t sg;
1991
Daniel Vetterfd387942015-02-11 12:41:04 +01001992 memclear(sg);
Kevin E Martin5d6ddbc2001-04-05 22:16:12 +00001993 sg.handle = handle;
Keith Packard8b9ab102008-06-13 16:03:22 -07001994 if (drmIoctl(fd, DRM_IOCTL_SG_FREE, &sg))
Brianccd7b6e2007-05-29 14:54:00 -06001995 return -errno;
Kevin E Martin5d6ddbc2001-04-05 22:16:12 +00001996 return 0;
1997}
1998
Jose Fonsecad2443b22003-05-27 00:37:33 +00001999/**
2000 * Wait for VBLANK.
2001 *
2002 * \param fd file descriptor.
2003 * \param vbl pointer to a drmVBlank structure.
2004 *
2005 * \return zero on success, or a negative value on failure.
2006 *
2007 * \internal
2008 * This function is a wrapper around the DRM_IOCTL_WAIT_VBLANK ioctl.
2009 */
Michel Daenzer55acd0d2002-09-25 17:18:19 +00002010int drmWaitVBlank(int fd, drmVBlankPtr vbl)
2011{
Jesse Barnesf4f76a62009-01-07 10:18:08 -08002012 struct timespec timeout, cur;
Michel Daenzer55acd0d2002-09-25 17:18:19 +00002013 int ret;
2014
Jesse Barnesf4f76a62009-01-07 10:18:08 -08002015 ret = clock_gettime(CLOCK_MONOTONIC, &timeout);
2016 if (ret < 0) {
Daniel Kurtz1eb28602013-03-28 14:05:40 +08002017 fprintf(stderr, "clock_gettime failed: %s\n", strerror(errno));
Jesse Barnesf4f76a62009-01-07 10:18:08 -08002018 goto out;
2019 }
2020 timeout.tv_sec++;
2021
Michel Daenzer55acd0d2002-09-25 17:18:19 +00002022 do {
Jesse Barnesf4f76a62009-01-07 10:18:08 -08002023 ret = ioctl(fd, DRM_IOCTL_WAIT_VBLANK, vbl);
Michel Daenzerc7d471b2003-02-02 03:06:47 +00002024 vbl->request.type &= ~DRM_VBLANK_RELATIVE;
Jesse Barnesca370772009-01-07 10:48:26 -08002025 if (ret && errno == EINTR) {
2026 clock_gettime(CLOCK_MONOTONIC, &cur);
2027 /* Timeout after 1s */
2028 if (cur.tv_sec > timeout.tv_sec + 1 ||
2029 (cur.tv_sec == timeout.tv_sec && cur.tv_nsec >=
2030 timeout.tv_nsec)) {
2031 errno = EBUSY;
2032 ret = -1;
2033 break;
2034 }
Jesse Barnesf4f76a62009-01-07 10:18:08 -08002035 }
Michel Daenzer55acd0d2002-09-25 17:18:19 +00002036 } while (ret && errno == EINTR);
2037
Jesse Barnesf4f76a62009-01-07 10:18:08 -08002038out:
Michel Daenzer55acd0d2002-09-25 17:18:19 +00002039 return ret;
2040}
2041
Daryll Straussb3a57661999-12-05 01:19:48 +00002042int drmError(int err, const char *label)
2043{
2044 switch (err) {
Brianccd7b6e2007-05-29 14:54:00 -06002045 case DRM_ERR_NO_DEVICE:
2046 fprintf(stderr, "%s: no device\n", label);
2047 break;
2048 case DRM_ERR_NO_ACCESS:
2049 fprintf(stderr, "%s: no access\n", label);
2050 break;
2051 case DRM_ERR_NOT_ROOT:
2052 fprintf(stderr, "%s: not root\n", label);
2053 break;
2054 case DRM_ERR_INVALID:
2055 fprintf(stderr, "%s: invalid args\n", label);
2056 break;
Daryll Straussb3a57661999-12-05 01:19:48 +00002057 default:
Brianccd7b6e2007-05-29 14:54:00 -06002058 if (err < 0)
2059 err = -err;
Daryll Straussb3a57661999-12-05 01:19:48 +00002060 fprintf( stderr, "%s: error %d (%s)\n", label, err, strerror(err) );
2061 break;
2062 }
2063
2064 return 1;
2065}
2066
Jose Fonsecad2443b22003-05-27 00:37:33 +00002067/**
2068 * Install IRQ handler.
2069 *
2070 * \param fd file descriptor.
2071 * \param irq IRQ number.
2072 *
2073 * \return zero on success, or a negative value on failure.
2074 *
2075 * \internal
2076 * This function is a wrapper around the DRM_IOCTL_CONTROL ioctl, passing the
2077 * argument in a drm_control structure.
2078 */
Daryll Straussb3a57661999-12-05 01:19:48 +00002079int drmCtlInstHandler(int fd, int irq)
2080{
2081 drm_control_t ctl;
2082
Daniel Vetterfd387942015-02-11 12:41:04 +01002083 memclear(ctl);
Daryll Straussb3a57661999-12-05 01:19:48 +00002084 ctl.func = DRM_INST_HANDLER;
Daryll Straussb3a57661999-12-05 01:19:48 +00002085 ctl.irq = irq;
Keith Packard8b9ab102008-06-13 16:03:22 -07002086 if (drmIoctl(fd, DRM_IOCTL_CONTROL, &ctl))
Brianccd7b6e2007-05-29 14:54:00 -06002087 return -errno;
Daryll Straussb3a57661999-12-05 01:19:48 +00002088 return 0;
2089}
2090
Jose Fonsecad2443b22003-05-27 00:37:33 +00002091
2092/**
2093 * Uninstall IRQ handler.
2094 *
2095 * \param fd file descriptor.
2096 *
2097 * \return zero on success, or a negative value on failure.
2098 *
2099 * \internal
2100 * This function is a wrapper around the DRM_IOCTL_CONTROL ioctl, passing the
2101 * argument in a drm_control structure.
2102 */
Daryll Straussb3a57661999-12-05 01:19:48 +00002103int drmCtlUninstHandler(int fd)
2104{
2105 drm_control_t ctl;
2106
Daniel Vetterfd387942015-02-11 12:41:04 +01002107 memclear(ctl);
Daryll Straussb3a57661999-12-05 01:19:48 +00002108 ctl.func = DRM_UNINST_HANDLER;
Daryll Straussb3a57661999-12-05 01:19:48 +00002109 ctl.irq = 0;
Keith Packard8b9ab102008-06-13 16:03:22 -07002110 if (drmIoctl(fd, DRM_IOCTL_CONTROL, &ctl))
Brianccd7b6e2007-05-29 14:54:00 -06002111 return -errno;
Daryll Straussb3a57661999-12-05 01:19:48 +00002112 return 0;
2113}
2114
2115int drmFinish(int fd, int context, drmLockFlags flags)
2116{
2117 drm_lock_t lock;
2118
Daniel Vetterfd387942015-02-11 12:41:04 +01002119 memclear(lock);
Daryll Straussb3a57661999-12-05 01:19:48 +00002120 lock.context = context;
Daryll Straussb3a57661999-12-05 01:19:48 +00002121 if (flags & DRM_LOCK_READY) lock.flags |= _DRM_LOCK_READY;
2122 if (flags & DRM_LOCK_QUIESCENT) lock.flags |= _DRM_LOCK_QUIESCENT;
2123 if (flags & DRM_LOCK_FLUSH) lock.flags |= _DRM_LOCK_FLUSH;
2124 if (flags & DRM_LOCK_FLUSH_ALL) lock.flags |= _DRM_LOCK_FLUSH_ALL;
2125 if (flags & DRM_HALT_ALL_QUEUES) lock.flags |= _DRM_HALT_ALL_QUEUES;
2126 if (flags & DRM_HALT_CUR_QUEUES) lock.flags |= _DRM_HALT_CUR_QUEUES;
Keith Packard8b9ab102008-06-13 16:03:22 -07002127 if (drmIoctl(fd, DRM_IOCTL_FINISH, &lock))
Brianccd7b6e2007-05-29 14:54:00 -06002128 return -errno;
Daryll Straussb3a57661999-12-05 01:19:48 +00002129 return 0;
2130}
2131
Jose Fonsecad2443b22003-05-27 00:37:33 +00002132/**
2133 * Get IRQ from bus ID.
2134 *
2135 * \param fd file descriptor.
2136 * \param busnum bus number.
2137 * \param devnum device number.
2138 * \param funcnum function number.
2139 *
2140 * \return IRQ number on success, or a negative value on failure.
2141 *
2142 * \internal
2143 * This function is a wrapper around the DRM_IOCTL_IRQ_BUSID ioctl, passing the
2144 * arguments in a drm_irq_busid structure.
2145 */
Daryll Straussb3a57661999-12-05 01:19:48 +00002146int drmGetInterruptFromBusID(int fd, int busnum, int devnum, int funcnum)
2147{
2148 drm_irq_busid_t p;
2149
Daniel Vetterfd387942015-02-11 12:41:04 +01002150 memclear(p);
Daryll Straussb3a57661999-12-05 01:19:48 +00002151 p.busnum = busnum;
2152 p.devnum = devnum;
2153 p.funcnum = funcnum;
Keith Packard8b9ab102008-06-13 16:03:22 -07002154 if (drmIoctl(fd, DRM_IOCTL_IRQ_BUSID, &p))
Brianccd7b6e2007-05-29 14:54:00 -06002155 return -errno;
Daryll Straussb3a57661999-12-05 01:19:48 +00002156 return p.irq;
2157}
2158
Jon Smirl8696e712004-07-07 04:36:36 +00002159int drmAddContextTag(int fd, drm_context_t context, void *tag)
Daryll Straussb3a57661999-12-05 01:19:48 +00002160{
2161 drmHashEntry *entry = drmGetEntry(fd);
2162
2163 if (drmHashInsert(entry->tagTable, context, tag)) {
2164 drmHashDelete(entry->tagTable, context);
2165 drmHashInsert(entry->tagTable, context, tag);
2166 }
2167 return 0;
2168}
2169
Jon Smirl8696e712004-07-07 04:36:36 +00002170int drmDelContextTag(int fd, drm_context_t context)
Daryll Straussb3a57661999-12-05 01:19:48 +00002171{
2172 drmHashEntry *entry = drmGetEntry(fd);
2173
2174 return drmHashDelete(entry->tagTable, context);
2175}
2176
Jon Smirl8696e712004-07-07 04:36:36 +00002177void *drmGetContextTag(int fd, drm_context_t context)
Daryll Straussb3a57661999-12-05 01:19:48 +00002178{
2179 drmHashEntry *entry = drmGetEntry(fd);
2180 void *value;
Gareth Hughes36047532001-02-15 08:12:14 +00002181
Brianccd7b6e2007-05-29 14:54:00 -06002182 if (drmHashLookup(entry->tagTable, context, &value))
2183 return NULL;
Daryll Straussb3a57661999-12-05 01:19:48 +00002184
2185 return value;
2186}
2187
Adam Jackson22e41ef2006-02-20 23:09:00 +00002188int drmAddContextPrivateMapping(int fd, drm_context_t ctx_id,
2189 drm_handle_t handle)
Kevin E Martin74e19a42001-03-14 22:22:50 +00002190{
2191 drm_ctx_priv_map_t map;
2192
Daniel Vetterfd387942015-02-11 12:41:04 +01002193 memclear(map);
Kevin E Martin74e19a42001-03-14 22:22:50 +00002194 map.ctx_id = ctx_id;
Jeremy Huddleston961bf9b2011-11-01 14:42:13 -07002195 map.handle = (void *)(uintptr_t)handle;
Kevin E Martin74e19a42001-03-14 22:22:50 +00002196
Keith Packard8b9ab102008-06-13 16:03:22 -07002197 if (drmIoctl(fd, DRM_IOCTL_SET_SAREA_CTX, &map))
Brianccd7b6e2007-05-29 14:54:00 -06002198 return -errno;
Kevin E Martin74e19a42001-03-14 22:22:50 +00002199 return 0;
2200}
2201
Adam Jackson22e41ef2006-02-20 23:09:00 +00002202int drmGetContextPrivateMapping(int fd, drm_context_t ctx_id,
2203 drm_handle_t *handle)
Kevin E Martin74e19a42001-03-14 22:22:50 +00002204{
2205 drm_ctx_priv_map_t map;
2206
Daniel Vetterfd387942015-02-11 12:41:04 +01002207 memclear(map);
Kevin E Martin74e19a42001-03-14 22:22:50 +00002208 map.ctx_id = ctx_id;
2209
Keith Packard8b9ab102008-06-13 16:03:22 -07002210 if (drmIoctl(fd, DRM_IOCTL_GET_SAREA_CTX, &map))
Brianccd7b6e2007-05-29 14:54:00 -06002211 return -errno;
2212 if (handle)
Jeremy Huddleston961bf9b2011-11-01 14:42:13 -07002213 *handle = (drm_handle_t)(uintptr_t)map.handle;
Kevin E Martin74e19a42001-03-14 22:22:50 +00002214
2215 return 0;
2216}
2217
Jon Smirl8696e712004-07-07 04:36:36 +00002218int drmGetMap(int fd, int idx, drm_handle_t *offset, drmSize *size,
2219 drmMapType *type, drmMapFlags *flags, drm_handle_t *handle,
Rik Faith88dbee52001-02-28 09:27:44 +00002220 int *mtrr)
2221{
2222 drm_map_t map;
2223
Daniel Vetterfd387942015-02-11 12:41:04 +01002224 memclear(map);
Rik Faith88dbee52001-02-28 09:27:44 +00002225 map.offset = idx;
Keith Packard8b9ab102008-06-13 16:03:22 -07002226 if (drmIoctl(fd, DRM_IOCTL_GET_MAP, &map))
Brianccd7b6e2007-05-29 14:54:00 -06002227 return -errno;
Rik Faith88dbee52001-02-28 09:27:44 +00002228 *offset = map.offset;
2229 *size = map.size;
2230 *type = map.type;
2231 *flags = map.flags;
2232 *handle = (unsigned long)map.handle;
2233 *mtrr = map.mtrr;
2234 return 0;
2235}
2236
2237int drmGetClient(int fd, int idx, int *auth, int *pid, int *uid,
2238 unsigned long *magic, unsigned long *iocs)
2239{
2240 drm_client_t client;
2241
Daniel Vetterfd387942015-02-11 12:41:04 +01002242 memclear(client);
Rik Faith88dbee52001-02-28 09:27:44 +00002243 client.idx = idx;
Keith Packard8b9ab102008-06-13 16:03:22 -07002244 if (drmIoctl(fd, DRM_IOCTL_GET_CLIENT, &client))
Brianccd7b6e2007-05-29 14:54:00 -06002245 return -errno;
Rik Faith88dbee52001-02-28 09:27:44 +00002246 *auth = client.auth;
2247 *pid = client.pid;
2248 *uid = client.uid;
2249 *magic = client.magic;
2250 *iocs = client.iocs;
2251 return 0;
2252}
2253
2254int drmGetStats(int fd, drmStatsT *stats)
2255{
2256 drm_stats_t s;
Jan Veselyde8532d2014-11-30 12:53:18 -05002257 unsigned i;
Rik Faith88dbee52001-02-28 09:27:44 +00002258
Daniel Vetterfd387942015-02-11 12:41:04 +01002259 memclear(s);
Keith Packard8b9ab102008-06-13 16:03:22 -07002260 if (drmIoctl(fd, DRM_IOCTL_GET_STATS, &s))
Brianccd7b6e2007-05-29 14:54:00 -06002261 return -errno;
Rik Faith88dbee52001-02-28 09:27:44 +00002262
2263 stats->count = 0;
2264 memset(stats, 0, sizeof(*stats));
2265 if (s.count > sizeof(stats->data)/sizeof(stats->data[0]))
2266 return -1;
2267
2268#define SET_VALUE \
2269 stats->data[i].long_format = "%-20.20s"; \
2270 stats->data[i].rate_format = "%8.8s"; \
2271 stats->data[i].isvalue = 1; \
2272 stats->data[i].verbose = 0
2273
2274#define SET_COUNT \
2275 stats->data[i].long_format = "%-20.20s"; \
2276 stats->data[i].rate_format = "%5.5s"; \
2277 stats->data[i].isvalue = 0; \
2278 stats->data[i].mult_names = "kgm"; \
2279 stats->data[i].mult = 1000; \
2280 stats->data[i].verbose = 0
2281
2282#define SET_BYTE \
2283 stats->data[i].long_format = "%-20.20s"; \
2284 stats->data[i].rate_format = "%5.5s"; \
2285 stats->data[i].isvalue = 0; \
2286 stats->data[i].mult_names = "KGM"; \
2287 stats->data[i].mult = 1024; \
2288 stats->data[i].verbose = 0
2289
2290
2291 stats->count = s.count;
2292 for (i = 0; i < s.count; i++) {
2293 stats->data[i].value = s.data[i].value;
2294 switch (s.data[i].type) {
2295 case _DRM_STAT_LOCK:
2296 stats->data[i].long_name = "Lock";
2297 stats->data[i].rate_name = "Lock";
2298 SET_VALUE;
2299 break;
2300 case _DRM_STAT_OPENS:
2301 stats->data[i].long_name = "Opens";
2302 stats->data[i].rate_name = "O";
2303 SET_COUNT;
2304 stats->data[i].verbose = 1;
2305 break;
2306 case _DRM_STAT_CLOSES:
2307 stats->data[i].long_name = "Closes";
2308 stats->data[i].rate_name = "Lock";
2309 SET_COUNT;
2310 stats->data[i].verbose = 1;
2311 break;
2312 case _DRM_STAT_IOCTLS:
2313 stats->data[i].long_name = "Ioctls";
2314 stats->data[i].rate_name = "Ioc/s";
2315 SET_COUNT;
2316 break;
2317 case _DRM_STAT_LOCKS:
2318 stats->data[i].long_name = "Locks";
2319 stats->data[i].rate_name = "Lck/s";
2320 SET_COUNT;
2321 break;
2322 case _DRM_STAT_UNLOCKS:
2323 stats->data[i].long_name = "Unlocks";
2324 stats->data[i].rate_name = "Unl/s";
2325 SET_COUNT;
2326 break;
2327 case _DRM_STAT_IRQ:
2328 stats->data[i].long_name = "IRQs";
2329 stats->data[i].rate_name = "IRQ/s";
2330 SET_COUNT;
2331 break;
2332 case _DRM_STAT_PRIMARY:
2333 stats->data[i].long_name = "Primary Bytes";
2334 stats->data[i].rate_name = "PB/s";
2335 SET_BYTE;
2336 break;
2337 case _DRM_STAT_SECONDARY:
2338 stats->data[i].long_name = "Secondary Bytes";
2339 stats->data[i].rate_name = "SB/s";
2340 SET_BYTE;
2341 break;
2342 case _DRM_STAT_DMA:
2343 stats->data[i].long_name = "DMA";
2344 stats->data[i].rate_name = "DMA/s";
2345 SET_COUNT;
2346 break;
2347 case _DRM_STAT_SPECIAL:
2348 stats->data[i].long_name = "Special DMA";
2349 stats->data[i].rate_name = "dma/s";
2350 SET_COUNT;
2351 break;
2352 case _DRM_STAT_MISSED:
2353 stats->data[i].long_name = "Miss";
2354 stats->data[i].rate_name = "Ms/s";
2355 SET_COUNT;
2356 break;
2357 case _DRM_STAT_VALUE:
2358 stats->data[i].long_name = "Value";
2359 stats->data[i].rate_name = "Value";
2360 SET_VALUE;
2361 break;
2362 case _DRM_STAT_BYTE:
2363 stats->data[i].long_name = "Bytes";
2364 stats->data[i].rate_name = "B/s";
2365 SET_BYTE;
2366 break;
2367 case _DRM_STAT_COUNT:
2368 default:
2369 stats->data[i].long_name = "Count";
2370 stats->data[i].rate_name = "Cnt/s";
2371 SET_COUNT;
2372 break;
2373 }
2374 }
2375 return 0;
2376}
2377
Jose Fonsecad2443b22003-05-27 00:37:33 +00002378/**
Eric Anholt06cb1322003-10-23 02:23:31 +00002379 * Issue a set-version ioctl.
2380 *
2381 * \param fd file descriptor.
2382 * \param drmCommandIndex command index
2383 * \param data source pointer of the data to be read and written.
2384 * \param size size of the data to be read and written.
2385 *
2386 * \return zero on success, or a negative value on failure.
2387 *
2388 * \internal
2389 * It issues a read-write ioctl given by
2390 * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
2391 */
Adam Jackson22e41ef2006-02-20 23:09:00 +00002392int drmSetInterfaceVersion(int fd, drmSetVersion *version)
Eric Anholt06cb1322003-10-23 02:23:31 +00002393{
2394 int retcode = 0;
2395 drm_set_version_t sv;
2396
Daniel Vetterfd387942015-02-11 12:41:04 +01002397 memclear(sv);
Eric Anholt06cb1322003-10-23 02:23:31 +00002398 sv.drm_di_major = version->drm_di_major;
2399 sv.drm_di_minor = version->drm_di_minor;
2400 sv.drm_dd_major = version->drm_dd_major;
2401 sv.drm_dd_minor = version->drm_dd_minor;
2402
Keith Packard8b9ab102008-06-13 16:03:22 -07002403 if (drmIoctl(fd, DRM_IOCTL_SET_VERSION, &sv)) {
Eric Anholt06cb1322003-10-23 02:23:31 +00002404 retcode = -errno;
2405 }
2406
2407 version->drm_di_major = sv.drm_di_major;
2408 version->drm_di_minor = sv.drm_di_minor;
2409 version->drm_dd_major = sv.drm_dd_major;
2410 version->drm_dd_minor = sv.drm_dd_minor;
2411
2412 return retcode;
2413}
2414
2415/**
Jose Fonsecad2443b22003-05-27 00:37:33 +00002416 * Send a device-specific command.
2417 *
2418 * \param fd file descriptor.
2419 * \param drmCommandIndex command index
2420 *
2421 * \return zero on success, or a negative value on failure.
2422 *
2423 * \internal
2424 * It issues a ioctl given by
2425 * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
2426 */
Jens Owen3903e5a2002-04-09 21:54:56 +00002427int drmCommandNone(int fd, unsigned long drmCommandIndex)
2428{
Jens Owen3903e5a2002-04-09 21:54:56 +00002429 unsigned long request;
2430
2431 request = DRM_IO( DRM_COMMAND_BASE + drmCommandIndex);
2432
Daniel Vetterfd387942015-02-11 12:41:04 +01002433 if (drmIoctl(fd, request, NULL)) {
Jens Owen3903e5a2002-04-09 21:54:56 +00002434 return -errno;
2435 }
2436 return 0;
2437}
2438
Jose Fonsecad2443b22003-05-27 00:37:33 +00002439
2440/**
2441 * Send a device-specific read command.
2442 *
2443 * \param fd file descriptor.
2444 * \param drmCommandIndex command index
2445 * \param data destination pointer of the data to be read.
2446 * \param size size of the data to be read.
2447 *
2448 * \return zero on success, or a negative value on failure.
2449 *
2450 * \internal
2451 * It issues a read ioctl given by
2452 * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
2453 */
Adam Jackson22e41ef2006-02-20 23:09:00 +00002454int drmCommandRead(int fd, unsigned long drmCommandIndex, void *data,
2455 unsigned long size)
Jens Owen3903e5a2002-04-09 21:54:56 +00002456{
2457 unsigned long request;
2458
Alan Hourihane74ef13f2002-07-05 08:31:11 +00002459 request = DRM_IOC( DRM_IOC_READ, DRM_IOCTL_BASE,
2460 DRM_COMMAND_BASE + drmCommandIndex, size);
Jens Owen3903e5a2002-04-09 21:54:56 +00002461
Keith Packard8b9ab102008-06-13 16:03:22 -07002462 if (drmIoctl(fd, request, data)) {
Jens Owen3903e5a2002-04-09 21:54:56 +00002463 return -errno;
2464 }
2465 return 0;
2466}
2467
Jose Fonsecad2443b22003-05-27 00:37:33 +00002468
2469/**
2470 * Send a device-specific write command.
2471 *
2472 * \param fd file descriptor.
2473 * \param drmCommandIndex command index
2474 * \param data source pointer of the data to be written.
2475 * \param size size of the data to be written.
2476 *
2477 * \return zero on success, or a negative value on failure.
2478 *
2479 * \internal
2480 * It issues a write ioctl given by
2481 * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
2482 */
Adam Jackson22e41ef2006-02-20 23:09:00 +00002483int drmCommandWrite(int fd, unsigned long drmCommandIndex, void *data,
2484 unsigned long size)
Jens Owen3903e5a2002-04-09 21:54:56 +00002485{
2486 unsigned long request;
2487
Alan Hourihane74ef13f2002-07-05 08:31:11 +00002488 request = DRM_IOC( DRM_IOC_WRITE, DRM_IOCTL_BASE,
2489 DRM_COMMAND_BASE + drmCommandIndex, size);
Jens Owen3903e5a2002-04-09 21:54:56 +00002490
Keith Packard8b9ab102008-06-13 16:03:22 -07002491 if (drmIoctl(fd, request, data)) {
Jens Owen3903e5a2002-04-09 21:54:56 +00002492 return -errno;
2493 }
2494 return 0;
2495}
2496
Jose Fonsecad2443b22003-05-27 00:37:33 +00002497
2498/**
2499 * Send a device-specific read-write command.
2500 *
2501 * \param fd file descriptor.
2502 * \param drmCommandIndex command index
2503 * \param data source pointer of the data to be read and written.
2504 * \param size size of the data to be read and written.
2505 *
2506 * \return zero on success, or a negative value on failure.
2507 *
2508 * \internal
2509 * It issues a read-write ioctl given by
2510 * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
2511 */
Adam Jackson22e41ef2006-02-20 23:09:00 +00002512int drmCommandWriteRead(int fd, unsigned long drmCommandIndex, void *data,
2513 unsigned long size)
Jens Owen3903e5a2002-04-09 21:54:56 +00002514{
2515 unsigned long request;
2516
Alan Hourihane74ef13f2002-07-05 08:31:11 +00002517 request = DRM_IOC( DRM_IOC_READ|DRM_IOC_WRITE, DRM_IOCTL_BASE,
2518 DRM_COMMAND_BASE + drmCommandIndex, size);
Jens Owen3903e5a2002-04-09 21:54:56 +00002519
Keith Packard8b9ab102008-06-13 16:03:22 -07002520 if (drmIoctl(fd, request, data))
Jens Owen3903e5a2002-04-09 21:54:56 +00002521 return -errno;
Jens Owen3903e5a2002-04-09 21:54:56 +00002522 return 0;
2523}
Thomas Hellstrom166da932006-08-21 21:02:08 +02002524
Dave Airlied51e1bb2006-11-09 08:55:58 +11002525#define DRM_MAX_FDS 16
2526static struct {
Brianccd7b6e2007-05-29 14:54:00 -06002527 char *BusID;
2528 int fd;
2529 int refcount;
Dave Airlied51e1bb2006-11-09 08:55:58 +11002530} connection[DRM_MAX_FDS];
2531
2532static int nr_fds = 0;
2533
2534int drmOpenOnce(void *unused,
2535 const char *BusID,
2536 int *newlyopened)
2537{
Brianccd7b6e2007-05-29 14:54:00 -06002538 int i;
2539 int fd;
Dave Airlied51e1bb2006-11-09 08:55:58 +11002540
Brianccd7b6e2007-05-29 14:54:00 -06002541 for (i = 0; i < nr_fds; i++)
2542 if (strcmp(BusID, connection[i].BusID) == 0) {
2543 connection[i].refcount++;
2544 *newlyopened = 0;
2545 return connection[i].fd;
2546 }
Dave Airlied51e1bb2006-11-09 08:55:58 +11002547
Brianccd7b6e2007-05-29 14:54:00 -06002548 fd = drmOpen(unused, BusID);
2549 if (fd <= 0 || nr_fds == DRM_MAX_FDS)
2550 return fd;
Dave Airlied51e1bb2006-11-09 08:55:58 +11002551
Brianccd7b6e2007-05-29 14:54:00 -06002552 connection[nr_fds].BusID = strdup(BusID);
2553 connection[nr_fds].fd = fd;
2554 connection[nr_fds].refcount = 1;
2555 *newlyopened = 1;
Dave Airlied51e1bb2006-11-09 08:55:58 +11002556
Brianccd7b6e2007-05-29 14:54:00 -06002557 if (0)
2558 fprintf(stderr, "saved connection %d for %s %d\n",
2559 nr_fds, connection[nr_fds].BusID,
2560 strcmp(BusID, connection[nr_fds].BusID));
Dave Airlied51e1bb2006-11-09 08:55:58 +11002561
Brianccd7b6e2007-05-29 14:54:00 -06002562 nr_fds++;
Dave Airlied51e1bb2006-11-09 08:55:58 +11002563
Brianccd7b6e2007-05-29 14:54:00 -06002564 return fd;
Dave Airlied51e1bb2006-11-09 08:55:58 +11002565}
2566
2567void drmCloseOnce(int fd)
2568{
Brianccd7b6e2007-05-29 14:54:00 -06002569 int i;
Dave Airlied51e1bb2006-11-09 08:55:58 +11002570
Brianccd7b6e2007-05-29 14:54:00 -06002571 for (i = 0; i < nr_fds; i++) {
2572 if (fd == connection[i].fd) {
2573 if (--connection[i].refcount == 0) {
2574 drmClose(connection[i].fd);
2575 free(connection[i].BusID);
Dave Airlied51e1bb2006-11-09 08:55:58 +11002576
Brianccd7b6e2007-05-29 14:54:00 -06002577 if (i < --nr_fds)
2578 connection[i] = connection[nr_fds];
Dave Airlied51e1bb2006-11-09 08:55:58 +11002579
Brianccd7b6e2007-05-29 14:54:00 -06002580 return;
2581 }
2582 }
2583 }
Dave Airlied51e1bb2006-11-09 08:55:58 +11002584}
Jesse Barnes731cd552008-12-17 10:09:49 -08002585
2586int drmSetMaster(int fd)
2587{
Daniel Vetterfd387942015-02-11 12:41:04 +01002588 return drmIoctl(fd, DRM_IOCTL_SET_MASTER, NULL);
Jesse Barnes731cd552008-12-17 10:09:49 -08002589}
2590
2591int drmDropMaster(int fd)
2592{
Daniel Vetterfd387942015-02-11 12:41:04 +01002593 return drmIoctl(fd, DRM_IOCTL_DROP_MASTER, NULL);
Jesse Barnes731cd552008-12-17 10:09:49 -08002594}
Kristian Høgsberg22d46662009-11-23 20:51:34 -05002595
2596char *drmGetDeviceNameFromFd(int fd)
2597{
2598 char name[128];
2599 struct stat sbuf;
2600 dev_t d;
2601 int i;
2602
2603 /* The whole drmOpen thing is a fiasco and we need to find a way
2604 * back to just using open(2). For now, however, lets just make
2605 * things worse with even more ad hoc directory walking code to
2606 * discover the device file name. */
2607
2608 fstat(fd, &sbuf);
2609 d = sbuf.st_rdev;
2610
2611 for (i = 0; i < DRM_MAX_MINOR; i++) {
2612 snprintf(name, sizeof name, DRM_DEV_NAME, DRM_DIR_NAME, i);
2613 if (stat(name, &sbuf) == 0 && sbuf.st_rdev == d)
2614 break;
2615 }
2616 if (i == DRM_MAX_MINOR)
2617 return NULL;
2618
Adam Jackson0a1ff352010-10-27 18:44:53 -04002619 return strdup(name);
Kristian Høgsberg22d46662009-11-23 20:51:34 -05002620}
Dave Airliecc0a1452012-07-14 09:52:17 +00002621
2622int drmPrimeHandleToFD(int fd, uint32_t handle, uint32_t flags, int *prime_fd)
2623{
2624 struct drm_prime_handle args;
2625 int ret;
2626
2627 args.handle = handle;
2628 args.flags = flags;
2629 ret = drmIoctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &args);
2630 if (ret)
2631 return ret;
2632
2633 *prime_fd = args.fd;
2634 return 0;
2635}
2636
2637int drmPrimeFDToHandle(int fd, int prime_fd, uint32_t *handle)
2638{
2639 struct drm_prime_handle args;
2640 int ret;
2641
2642 args.fd = prime_fd;
2643 args.flags = 0;
2644 ret = drmIoctl(fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &args);
2645 if (ret)
2646 return ret;
2647
2648 *handle = args.handle;
2649 return 0;
2650}
2651