xf86drm.c revision 424e9256
122944501Smrg/**
222944501Smrg * \file xf86drm.c
322944501Smrg * User-level interface to DRM device
422944501Smrg *
522944501Smrg * \author Rickard E. (Rik) Faith <faith@valinux.com>
622944501Smrg * \author Kevin E. Martin <martin@valinux.com>
722944501Smrg */
822944501Smrg
922944501Smrg/*
1022944501Smrg * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
1122944501Smrg * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
1222944501Smrg * All Rights Reserved.
1322944501Smrg *
1422944501Smrg * Permission is hereby granted, free of charge, to any person obtaining a
1522944501Smrg * copy of this software and associated documentation files (the "Software"),
1622944501Smrg * to deal in the Software without restriction, including without limitation
1722944501Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1822944501Smrg * and/or sell copies of the Software, and to permit persons to whom the
1922944501Smrg * Software is furnished to do so, subject to the following conditions:
2022944501Smrg *
2122944501Smrg * The above copyright notice and this permission notice (including the next
2222944501Smrg * paragraph) shall be included in all copies or substantial portions of the
2322944501Smrg * Software.
2422944501Smrg *
2522944501Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2622944501Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2722944501Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
2822944501Smrg * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
2922944501Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
3022944501Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
3122944501Smrg * DEALINGS IN THE SOFTWARE.
3222944501Smrg */
3322944501Smrg
3422944501Smrg#ifdef HAVE_CONFIG_H
3522944501Smrg# include <config.h>
3622944501Smrg#endif
3722944501Smrg#include <stdio.h>
3822944501Smrg#include <stdlib.h>
3922944501Smrg#include <unistd.h>
4022944501Smrg#include <string.h>
4122944501Smrg#include <strings.h>
4222944501Smrg#include <ctype.h>
43424e9256Smrg#include <dirent.h>
44424e9256Smrg#include <stddef.h>
4522944501Smrg#include <fcntl.h>
4622944501Smrg#include <errno.h>
4722944501Smrg#include <signal.h>
4822944501Smrg#include <time.h>
4922944501Smrg#include <sys/types.h>
5022944501Smrg#include <sys/stat.h>
5122944501Smrg#define stat_t struct stat
5222944501Smrg#include <sys/ioctl.h>
5322944501Smrg#include <sys/time.h>
5422944501Smrg#include <stdarg.h>
55424e9256Smrg#ifdef HAVE_SYS_MKDEV_H
56424e9256Smrg# include <sys/mkdev.h> /* defines major(), minor(), and makedev() on Solaris */
57424e9256Smrg#endif
5822944501Smrg
5922944501Smrg/* Not all systems have MAP_FAILED defined */
6022944501Smrg#ifndef MAP_FAILED
6122944501Smrg#define MAP_FAILED ((void *)-1)
6222944501Smrg#endif
6322944501Smrg
6422944501Smrg#include "xf86drm.h"
65424e9256Smrg#include "libdrm_macros.h"
6622944501Smrg
6722944501Smrg#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
6822944501Smrg#define DRM_MAJOR 145
6922944501Smrg#endif
7022944501Smrg
7122944501Smrg#ifdef __NetBSD__
722e6867f6Smrg#undef DRM_MAJOR
732e6867f6Smrg#define DRM_MAJOR 180
7422944501Smrg#endif
7522944501Smrg
7622944501Smrg# ifdef __OpenBSD__
7722944501Smrg#  define DRM_MAJOR 81
7822944501Smrg# endif
7922944501Smrg
8022944501Smrg#ifndef DRM_MAJOR
8122944501Smrg#define DRM_MAJOR 226		/* Linux */
8222944501Smrg#endif
8322944501Smrg
8422944501Smrg/*
8522944501Smrg * This definition needs to be changed on some systems if dev_t is a structure.
8622944501Smrg * If there is a header file we can get it from, there would be best.
8722944501Smrg */
8822944501Smrg#ifndef makedev
8922944501Smrg#define makedev(x,y)    ((dev_t)(((x) << 8) | (y)))
9022944501Smrg#endif
9122944501Smrg
9222944501Smrg#define DRM_MSG_VERBOSITY 3
9322944501Smrg
94424e9256Smrg#define memclear(s) memset(&s, 0, sizeof(s))
9522944501Smrg
9622944501Smrgstatic drmServerInfoPtr drm_server_info;
9722944501Smrg
9822944501Smrgvoid drmSetServerInfo(drmServerInfoPtr info)
9922944501Smrg{
10022944501Smrg    drm_server_info = info;
10122944501Smrg}
10222944501Smrg
10322944501Smrg/**
10422944501Smrg * Output a message to stderr.
10522944501Smrg *
10622944501Smrg * \param format printf() like format string.
10722944501Smrg *
10822944501Smrg * \internal
10922944501Smrg * This function is a wrapper around vfprintf().
11022944501Smrg */
11122944501Smrg
112a7d7de1eSmrgstatic int DRM_PRINTFLIKE(1, 0)
113a7d7de1eSmrgdrmDebugPrint(const char *format, va_list ap)
11422944501Smrg{
11522944501Smrg    return vfprintf(stderr, format, ap);
11622944501Smrg}
11722944501Smrg
11822944501Smrgvoid
11922944501SmrgdrmMsg(const char *format, ...)
12022944501Smrg{
12122944501Smrg    va_list	ap;
12222944501Smrg    const char *env;
12322944501Smrg    if (((env = getenv("LIBGL_DEBUG")) && strstr(env, "verbose")) || drm_server_info)
12422944501Smrg    {
12522944501Smrg	va_start(ap, format);
12622944501Smrg	if (drm_server_info) {
12722944501Smrg	  drm_server_info->debug_print(format,ap);
12822944501Smrg	} else {
129424e9256Smrg	  drmDebugPrint(format, ap);
13022944501Smrg	}
13122944501Smrg	va_end(ap);
13222944501Smrg    }
13322944501Smrg}
13422944501Smrg
13522944501Smrgstatic void *drmHashTable = NULL; /* Context switch callbacks */
13622944501Smrg
13722944501Smrgvoid *drmGetHashTable(void)
13822944501Smrg{
13922944501Smrg    return drmHashTable;
14022944501Smrg}
14122944501Smrg
14222944501Smrgvoid *drmMalloc(int size)
14322944501Smrg{
144424e9256Smrg    return calloc(1, size);
14522944501Smrg}
14622944501Smrg
14722944501Smrgvoid drmFree(void *pt)
14822944501Smrg{
149424e9256Smrg    free(pt);
15022944501Smrg}
15122944501Smrg
15222944501Smrg/**
15322944501Smrg * Call ioctl, restarting if it is interupted
15422944501Smrg */
15522944501Smrgint
15622944501SmrgdrmIoctl(int fd, unsigned long request, void *arg)
15722944501Smrg{
15822944501Smrg    int	ret;
15922944501Smrg
16022944501Smrg    do {
16122944501Smrg	ret = ioctl(fd, request, arg);
16222944501Smrg    } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
16322944501Smrg    return ret;
16422944501Smrg}
16522944501Smrg
16622944501Smrgstatic unsigned long drmGetKeyFromFd(int fd)
16722944501Smrg{
16822944501Smrg    stat_t     st;
16922944501Smrg
17022944501Smrg    st.st_rdev = 0;
17122944501Smrg    fstat(fd, &st);
17222944501Smrg    return st.st_rdev;
17322944501Smrg}
17422944501Smrg
17522944501SmrgdrmHashEntry *drmGetEntry(int fd)
17622944501Smrg{
17722944501Smrg    unsigned long key = drmGetKeyFromFd(fd);
17822944501Smrg    void          *value;
17922944501Smrg    drmHashEntry  *entry;
18022944501Smrg
18122944501Smrg    if (!drmHashTable)
18222944501Smrg	drmHashTable = drmHashCreate();
18322944501Smrg
18422944501Smrg    if (drmHashLookup(drmHashTable, key, &value)) {
18522944501Smrg	entry           = drmMalloc(sizeof(*entry));
18622944501Smrg	entry->fd       = fd;
18722944501Smrg	entry->f        = NULL;
18822944501Smrg	entry->tagTable = drmHashCreate();
18922944501Smrg	drmHashInsert(drmHashTable, key, entry);
19022944501Smrg    } else {
19122944501Smrg	entry = value;
19222944501Smrg    }
19322944501Smrg    return entry;
19422944501Smrg}
19522944501Smrg
19622944501Smrg/**
19722944501Smrg * Compare two busid strings
19822944501Smrg *
19922944501Smrg * \param first
20022944501Smrg * \param second
20122944501Smrg *
20222944501Smrg * \return 1 if matched.
20322944501Smrg *
20422944501Smrg * \internal
20522944501Smrg * This function compares two bus ID strings.  It understands the older
20622944501Smrg * PCI:b:d:f format and the newer pci:oooo:bb:dd.f format.  In the format, o is
20722944501Smrg * domain, b is bus, d is device, f is function.
20822944501Smrg */
2096d98c517Smrgstatic int drmMatchBusID(const char *id1, const char *id2, int pci_domain_ok)
21022944501Smrg{
21122944501Smrg    /* First, check if the IDs are exactly the same */
21222944501Smrg    if (strcasecmp(id1, id2) == 0)
21322944501Smrg	return 1;
21422944501Smrg
21522944501Smrg    /* Try to match old/new-style PCI bus IDs. */
21622944501Smrg    if (strncasecmp(id1, "pci", 3) == 0) {
21722944501Smrg	unsigned int o1, b1, d1, f1;
21822944501Smrg	unsigned int o2, b2, d2, f2;
21922944501Smrg	int ret;
22022944501Smrg
22122944501Smrg	ret = sscanf(id1, "pci:%04x:%02x:%02x.%u", &o1, &b1, &d1, &f1);
22222944501Smrg	if (ret != 4) {
22322944501Smrg	    o1 = 0;
22422944501Smrg	    ret = sscanf(id1, "PCI:%u:%u:%u", &b1, &d1, &f1);
22522944501Smrg	    if (ret != 3)
22622944501Smrg		return 0;
22722944501Smrg	}
22822944501Smrg
22922944501Smrg	ret = sscanf(id2, "pci:%04x:%02x:%02x.%u", &o2, &b2, &d2, &f2);
23022944501Smrg	if (ret != 4) {
23122944501Smrg	    o2 = 0;
23222944501Smrg	    ret = sscanf(id2, "PCI:%u:%u:%u", &b2, &d2, &f2);
23322944501Smrg	    if (ret != 3)
23422944501Smrg		return 0;
23522944501Smrg	}
23622944501Smrg
2376d98c517Smrg	/* If domains aren't properly supported by the kernel interface,
2386d98c517Smrg	 * just ignore them, which sucks less than picking a totally random
2396d98c517Smrg	 * card with "open by name"
2406d98c517Smrg	 */
2416d98c517Smrg	if (!pci_domain_ok)
2426d98c517Smrg		o1 = o2 = 0;
2436d98c517Smrg
24422944501Smrg	if ((o1 != o2) || (b1 != b2) || (d1 != d2) || (f1 != f2))
24522944501Smrg	    return 0;
24622944501Smrg	else
24722944501Smrg	    return 1;
24822944501Smrg    }
24922944501Smrg    return 0;
25022944501Smrg}
25122944501Smrg
25222944501Smrg/**
25322944501Smrg * Handles error checking for chown call.
25422944501Smrg *
25522944501Smrg * \param path to file.
25622944501Smrg * \param id of the new owner.
25722944501Smrg * \param id of the new group.
25822944501Smrg *
25922944501Smrg * \return zero if success or -1 if failure.
26022944501Smrg *
26122944501Smrg * \internal
26222944501Smrg * Checks for failure. If failure was caused by signal call chown again.
26322944501Smrg * If any other failure happened then it will output error mesage using
26422944501Smrg * drmMsg() call.
26522944501Smrg */
266424e9256Smrg#if !defined(UDEV)
26722944501Smrgstatic int chown_check_return(const char *path, uid_t owner, gid_t group)
26822944501Smrg{
26922944501Smrg	int rv;
27022944501Smrg
27122944501Smrg	do {
27222944501Smrg		rv = chown(path, owner, group);
27322944501Smrg	} while (rv != 0 && errno == EINTR);
27422944501Smrg
27522944501Smrg	if (rv == 0)
27622944501Smrg		return 0;
27722944501Smrg
27822944501Smrg	drmMsg("Failed to change owner or group for file %s! %d: %s\n",
27922944501Smrg			path, errno, strerror(errno));
28022944501Smrg	return -1;
28122944501Smrg}
282424e9256Smrg#endif
28322944501Smrg
28422944501Smrg/**
28522944501Smrg * Open the DRM device, creating it if necessary.
28622944501Smrg *
28722944501Smrg * \param dev major and minor numbers of the device.
28822944501Smrg * \param minor minor number of the device.
28922944501Smrg *
29022944501Smrg * \return a file descriptor on success, or a negative value on error.
29122944501Smrg *
29222944501Smrg * \internal
29322944501Smrg * Assembles the device name from \p minor and opens it, creating the device
29422944501Smrg * special file node with the major and minor numbers specified by \p dev and
29522944501Smrg * parent directory if necessary and was called by root.
29622944501Smrg */
297424e9256Smrgstatic int drmOpenDevice(dev_t dev, int minor, int type)
29822944501Smrg{
29922944501Smrg    stat_t          st;
300424e9256Smrg    const char      *dev_name;
30122944501Smrg    char            buf[64];
30222944501Smrg    int             fd;
30322944501Smrg    mode_t          devmode = DRM_DEV_MODE, serv_mode;
304424e9256Smrg    gid_t           serv_group;
305424e9256Smrg#if !defined(UDEV)
30622944501Smrg    int             isroot  = !geteuid();
30722944501Smrg    uid_t           user    = DRM_DEV_UID;
308424e9256Smrg    gid_t           group   = DRM_DEV_GID;
309424e9256Smrg#endif
310424e9256Smrg
311424e9256Smrg    switch (type) {
312424e9256Smrg    case DRM_NODE_PRIMARY:
313424e9256Smrg	    dev_name = DRM_DEV_NAME;
314424e9256Smrg	    break;
315424e9256Smrg    case DRM_NODE_CONTROL:
316424e9256Smrg	    dev_name = DRM_CONTROL_DEV_NAME;
317424e9256Smrg	    break;
318424e9256Smrg    case DRM_NODE_RENDER:
319424e9256Smrg	    dev_name = DRM_RENDER_DEV_NAME;
320424e9256Smrg	    break;
321424e9256Smrg    default:
322424e9256Smrg	    return -EINVAL;
323424e9256Smrg    };
324424e9256Smrg
325424e9256Smrg    sprintf(buf, dev_name, DRM_DIR_NAME, minor);
32622944501Smrg    drmMsg("drmOpenDevice: node name is %s\n", buf);
32722944501Smrg
32822944501Smrg    if (drm_server_info) {
32922944501Smrg	drm_server_info->get_perms(&serv_group, &serv_mode);
33022944501Smrg	devmode  = serv_mode ? serv_mode : DRM_DEV_MODE;
33122944501Smrg	devmode &= ~(S_IXUSR|S_IXGRP|S_IXOTH);
33222944501Smrg    }
33322944501Smrg
33422944501Smrg#if !defined(UDEV)
33522944501Smrg    if (stat(DRM_DIR_NAME, &st)) {
33622944501Smrg	if (!isroot)
33722944501Smrg	    return DRM_ERR_NOT_ROOT;
33822944501Smrg	mkdir(DRM_DIR_NAME, DRM_DEV_DIRMODE);
33922944501Smrg	chown_check_return(DRM_DIR_NAME, 0, 0); /* root:root */
34022944501Smrg	chmod(DRM_DIR_NAME, DRM_DEV_DIRMODE);
34122944501Smrg    }
34222944501Smrg
34322944501Smrg    /* Check if the device node exists and create it if necessary. */
34422944501Smrg    if (stat(buf, &st)) {
34522944501Smrg	if (!isroot)
34622944501Smrg	    return DRM_ERR_NOT_ROOT;
34722944501Smrg	remove(buf);
34822944501Smrg	mknod(buf, S_IFCHR | devmode, dev);
34922944501Smrg    }
35022944501Smrg
35122944501Smrg    if (drm_server_info) {
352424e9256Smrg	group = ((int)serv_group >= 0) ? serv_group : DRM_DEV_GID;
35322944501Smrg	chown_check_return(buf, user, group);
35422944501Smrg	chmod(buf, devmode);
35522944501Smrg    }
35622944501Smrg#else
35722944501Smrg    /* if we modprobed then wait for udev */
35822944501Smrg    {
35922944501Smrg	int udev_count = 0;
36022944501Smrgwait_for_udev:
36122944501Smrg        if (stat(DRM_DIR_NAME, &st)) {
36222944501Smrg		usleep(20);
36322944501Smrg		udev_count++;
36422944501Smrg
36522944501Smrg		if (udev_count == 50)
36622944501Smrg			return -1;
36722944501Smrg		goto wait_for_udev;
36822944501Smrg	}
36922944501Smrg
37022944501Smrg    	if (stat(buf, &st)) {
37122944501Smrg		usleep(20);
37222944501Smrg		udev_count++;
37322944501Smrg
37422944501Smrg		if (udev_count == 50)
37522944501Smrg			return -1;
37622944501Smrg		goto wait_for_udev;
37722944501Smrg    	}
37822944501Smrg    }
37922944501Smrg#endif
38022944501Smrg
38122944501Smrg    fd = open(buf, O_RDWR, 0);
38222944501Smrg    drmMsg("drmOpenDevice: open result is %d, (%s)\n",
38322944501Smrg		fd, fd < 0 ? strerror(errno) : "OK");
38422944501Smrg    if (fd >= 0)
38522944501Smrg	return fd;
38622944501Smrg
3879ce4edccSmrg#if !defined(UDEV)
38822944501Smrg    /* Check if the device node is not what we expect it to be, and recreate it
38922944501Smrg     * and try again if so.
39022944501Smrg     */
39122944501Smrg    if (st.st_rdev != dev) {
39222944501Smrg	if (!isroot)
39322944501Smrg	    return DRM_ERR_NOT_ROOT;
39422944501Smrg	remove(buf);
39522944501Smrg	mknod(buf, S_IFCHR | devmode, dev);
39622944501Smrg	if (drm_server_info) {
39722944501Smrg	    chown_check_return(buf, user, group);
39822944501Smrg	    chmod(buf, devmode);
39922944501Smrg	}
40022944501Smrg    }
40122944501Smrg    fd = open(buf, O_RDWR, 0);
40222944501Smrg    drmMsg("drmOpenDevice: open result is %d, (%s)\n",
40322944501Smrg		fd, fd < 0 ? strerror(errno) : "OK");
40422944501Smrg    if (fd >= 0)
40522944501Smrg	return fd;
40622944501Smrg
40722944501Smrg    drmMsg("drmOpenDevice: Open failed\n");
40822944501Smrg    remove(buf);
4099ce4edccSmrg#endif
41022944501Smrg    return -errno;
41122944501Smrg}
41222944501Smrg
41322944501Smrg
41422944501Smrg/**
41522944501Smrg * Open the DRM device
41622944501Smrg *
41722944501Smrg * \param minor device minor number.
41822944501Smrg * \param create allow to create the device if set.
41922944501Smrg *
42022944501Smrg * \return a file descriptor on success, or a negative value on error.
42122944501Smrg *
42222944501Smrg * \internal
42322944501Smrg * Calls drmOpenDevice() if \p create is set, otherwise assembles the device
42422944501Smrg * name from \p minor and opens it.
42522944501Smrg */
42622944501Smrgstatic int drmOpenMinor(int minor, int create, int type)
42722944501Smrg{
42822944501Smrg    int  fd;
42922944501Smrg    char buf[64];
430424e9256Smrg    const char *dev_name;
43122944501Smrg
43222944501Smrg    if (create)
43322944501Smrg	return drmOpenDevice(makedev(DRM_MAJOR, minor), minor, type);
43422944501Smrg
435424e9256Smrg    switch (type) {
436424e9256Smrg    case DRM_NODE_PRIMARY:
437424e9256Smrg	    dev_name = DRM_DEV_NAME;
438424e9256Smrg	    break;
439424e9256Smrg    case DRM_NODE_CONTROL:
440424e9256Smrg	    dev_name = DRM_CONTROL_DEV_NAME;
441424e9256Smrg	    break;
442424e9256Smrg    case DRM_NODE_RENDER:
443424e9256Smrg	    dev_name = DRM_RENDER_DEV_NAME;
444424e9256Smrg	    break;
445424e9256Smrg    default:
446424e9256Smrg	    return -EINVAL;
447424e9256Smrg    };
448424e9256Smrg
449424e9256Smrg    sprintf(buf, dev_name, DRM_DIR_NAME, minor);
45022944501Smrg    if ((fd = open(buf, O_RDWR, 0)) >= 0)
45122944501Smrg	return fd;
45222944501Smrg    return -errno;
45322944501Smrg}
45422944501Smrg
45522944501Smrg
45622944501Smrg/**
45722944501Smrg * Determine whether the DRM kernel driver has been loaded.
45822944501Smrg *
45922944501Smrg * \return 1 if the DRM driver is loaded, 0 otherwise.
46022944501Smrg *
46122944501Smrg * \internal
46222944501Smrg * Determine the presence of the kernel driver by attempting to open the 0
46322944501Smrg * minor and get version information.  For backward compatibility with older
46422944501Smrg * Linux implementations, /proc/dri is also checked.
46522944501Smrg */
46622944501Smrgint drmAvailable(void)
46722944501Smrg{
46822944501Smrg    drmVersionPtr version;
46922944501Smrg    int           retval = 0;
47022944501Smrg    int           fd;
47122944501Smrg
472424e9256Smrg    if ((fd = drmOpenMinor(0, 1, DRM_NODE_PRIMARY)) < 0) {
47322944501Smrg#ifdef __linux__
47422944501Smrg	/* Try proc for backward Linux compatibility */
47522944501Smrg	if (!access("/proc/dri/0", R_OK))
47622944501Smrg	    return 1;
47722944501Smrg#endif
47822944501Smrg	return 0;
47922944501Smrg    }
48022944501Smrg
48122944501Smrg    if ((version = drmGetVersion(fd))) {
48222944501Smrg	retval = 1;
48322944501Smrg	drmFreeVersion(version);
48422944501Smrg    }
48522944501Smrg    close(fd);
48622944501Smrg
48722944501Smrg    return retval;
48822944501Smrg}
48922944501Smrg
490424e9256Smrgstatic int drmGetMinorBase(int type)
491424e9256Smrg{
492424e9256Smrg    switch (type) {
493424e9256Smrg    case DRM_NODE_PRIMARY:
494424e9256Smrg        return 0;
495424e9256Smrg    case DRM_NODE_CONTROL:
496424e9256Smrg        return 64;
497424e9256Smrg    case DRM_NODE_RENDER:
498424e9256Smrg        return 128;
499424e9256Smrg    default:
500424e9256Smrg        return -1;
501424e9256Smrg    };
502424e9256Smrg}
503424e9256Smrg
504424e9256Smrgstatic int drmGetMinorType(int minor)
505424e9256Smrg{
506424e9256Smrg    int type = minor >> 6;
507424e9256Smrg
508424e9256Smrg    if (minor < 0)
509424e9256Smrg        return -1;
510424e9256Smrg
511424e9256Smrg    switch (type) {
512424e9256Smrg    case DRM_NODE_PRIMARY:
513424e9256Smrg    case DRM_NODE_CONTROL:
514424e9256Smrg    case DRM_NODE_RENDER:
515424e9256Smrg        return type;
516424e9256Smrg    default:
517424e9256Smrg        return -1;
518424e9256Smrg    }
519424e9256Smrg}
520424e9256Smrg
521424e9256Smrgstatic const char *drmGetMinorName(int type)
522424e9256Smrg{
523424e9256Smrg    switch (type) {
524424e9256Smrg    case DRM_NODE_PRIMARY:
525424e9256Smrg        return "card";
526424e9256Smrg    case DRM_NODE_CONTROL:
527424e9256Smrg        return "controlD";
528424e9256Smrg    case DRM_NODE_RENDER:
529424e9256Smrg        return "renderD";
530424e9256Smrg    default:
531424e9256Smrg        return NULL;
532424e9256Smrg    }
533424e9256Smrg}
53422944501Smrg
53522944501Smrg/**
53622944501Smrg * Open the device by bus ID.
53722944501Smrg *
53822944501Smrg * \param busid bus ID.
539424e9256Smrg * \param type device node type.
54022944501Smrg *
54122944501Smrg * \return a file descriptor on success, or a negative value on error.
54222944501Smrg *
54322944501Smrg * \internal
54422944501Smrg * This function attempts to open every possible minor (up to DRM_MAX_MINOR),
54522944501Smrg * comparing the device bus ID with the one supplied.
54622944501Smrg *
54722944501Smrg * \sa drmOpenMinor() and drmGetBusid().
54822944501Smrg */
549424e9256Smrgstatic int drmOpenByBusid(const char *busid, int type)
55022944501Smrg{
5516d98c517Smrg    int        i, pci_domain_ok = 1;
55222944501Smrg    int        fd;
55322944501Smrg    const char *buf;
55422944501Smrg    drmSetVersion sv;
555424e9256Smrg    int        base = drmGetMinorBase(type);
556424e9256Smrg
557424e9256Smrg    if (base < 0)
558424e9256Smrg        return -1;
55922944501Smrg
56022944501Smrg    drmMsg("drmOpenByBusid: Searching for BusID %s\n", busid);
561424e9256Smrg    for (i = base; i < base + DRM_MAX_MINOR; i++) {
562424e9256Smrg	fd = drmOpenMinor(i, 1, type);
56322944501Smrg	drmMsg("drmOpenByBusid: drmOpenMinor returns %d\n", fd);
56422944501Smrg	if (fd >= 0) {
5656d98c517Smrg	    /* We need to try for 1.4 first for proper PCI domain support
5666d98c517Smrg	     * and if that fails, we know the kernel is busted
5676d98c517Smrg	     */
56822944501Smrg	    sv.drm_di_major = 1;
5696d98c517Smrg	    sv.drm_di_minor = 4;
57022944501Smrg	    sv.drm_dd_major = -1;	/* Don't care */
57122944501Smrg	    sv.drm_dd_minor = -1;	/* Don't care */
5726d98c517Smrg	    if (drmSetInterfaceVersion(fd, &sv)) {
5736d98c517Smrg#ifndef __alpha__
5746d98c517Smrg		pci_domain_ok = 0;
5756d98c517Smrg#endif
5766d98c517Smrg		sv.drm_di_major = 1;
5776d98c517Smrg		sv.drm_di_minor = 1;
5786d98c517Smrg		sv.drm_dd_major = -1;       /* Don't care */
5796d98c517Smrg		sv.drm_dd_minor = -1;       /* Don't care */
580a7d7de1eSmrg		drmMsg("drmOpenByBusid: Interface 1.4 failed, trying 1.1\n");
5816d98c517Smrg		drmSetInterfaceVersion(fd, &sv);
5822e6867f6Smrg	    }
58322944501Smrg	    buf = drmGetBusid(fd);
58422944501Smrg	    drmMsg("drmOpenByBusid: drmGetBusid reports %s\n", buf);
5856d98c517Smrg	    if (buf && drmMatchBusID(buf, busid, pci_domain_ok)) {
58622944501Smrg		drmFreeBusid(buf);
58722944501Smrg		return fd;
58822944501Smrg	    }
58922944501Smrg	    if (buf)
59022944501Smrg		drmFreeBusid(buf);
59122944501Smrg	    close(fd);
59222944501Smrg	}
59322944501Smrg    }
59422944501Smrg    return -1;
59522944501Smrg}
59622944501Smrg
59722944501Smrg
59822944501Smrg/**
59922944501Smrg * Open the device by name.
60022944501Smrg *
60122944501Smrg * \param name driver name.
602424e9256Smrg * \param type the device node type.
60322944501Smrg *
60422944501Smrg * \return a file descriptor on success, or a negative value on error.
60522944501Smrg *
60622944501Smrg * \internal
60722944501Smrg * This function opens the first minor number that matches the driver name and
60822944501Smrg * isn't already in use.  If it's in use it then it will already have a bus ID
60922944501Smrg * assigned.
61022944501Smrg *
61122944501Smrg * \sa drmOpenMinor(), drmGetVersion() and drmGetBusid().
61222944501Smrg */
613424e9256Smrgstatic int drmOpenByName(const char *name, int type)
61422944501Smrg{
61522944501Smrg    int           i;
61622944501Smrg    int           fd;
61722944501Smrg    drmVersionPtr version;
61822944501Smrg    char *        id;
619424e9256Smrg    int           base = drmGetMinorBase(type);
620424e9256Smrg
621424e9256Smrg    if (base < 0)
622424e9256Smrg        return -1;
62322944501Smrg
62422944501Smrg    /*
62522944501Smrg     * Open the first minor number that matches the driver name and isn't
62622944501Smrg     * already in use.  If it's in use it will have a busid assigned already.
62722944501Smrg     */
628424e9256Smrg    for (i = base; i < base + DRM_MAX_MINOR; i++) {
629424e9256Smrg	if ((fd = drmOpenMinor(i, 1, type)) >= 0) {
63022944501Smrg	    if ((version = drmGetVersion(fd))) {
63122944501Smrg		if (!strcmp(version->name, name)) {
63222944501Smrg		    drmFreeVersion(version);
63322944501Smrg		    id = drmGetBusid(fd);
63422944501Smrg		    drmMsg("drmGetBusid returned '%s'\n", id ? id : "NULL");
63522944501Smrg		    if (!id || !*id) {
63622944501Smrg			if (id)
63722944501Smrg			    drmFreeBusid(id);
63822944501Smrg			return fd;
63922944501Smrg		    } else {
64022944501Smrg			drmFreeBusid(id);
64122944501Smrg		    }
64222944501Smrg		} else {
64322944501Smrg		    drmFreeVersion(version);
64422944501Smrg		}
64522944501Smrg	    }
64622944501Smrg	    close(fd);
64722944501Smrg	}
64822944501Smrg    }
64922944501Smrg
65022944501Smrg#ifdef __linux__
65122944501Smrg    /* Backward-compatibility /proc support */
65222944501Smrg    for (i = 0; i < 8; i++) {
65322944501Smrg	char proc_name[64], buf[512];
65422944501Smrg	char *driver, *pt, *devstring;
65522944501Smrg	int  retcode;
65622944501Smrg
65722944501Smrg	sprintf(proc_name, "/proc/dri/%d/name", i);
65822944501Smrg	if ((fd = open(proc_name, 0, 0)) >= 0) {
65922944501Smrg	    retcode = read(fd, buf, sizeof(buf)-1);
66022944501Smrg	    close(fd);
66122944501Smrg	    if (retcode) {
66222944501Smrg		buf[retcode-1] = '\0';
66322944501Smrg		for (driver = pt = buf; *pt && *pt != ' '; ++pt)
66422944501Smrg		    ;
66522944501Smrg		if (*pt) { /* Device is next */
66622944501Smrg		    *pt = '\0';
66722944501Smrg		    if (!strcmp(driver, name)) { /* Match */
66822944501Smrg			for (devstring = ++pt; *pt && *pt != ' '; ++pt)
66922944501Smrg			    ;
67022944501Smrg			if (*pt) { /* Found busid */
671424e9256Smrg			    return drmOpenByBusid(++pt, type);
67222944501Smrg			} else { /* No busid */
673424e9256Smrg			    return drmOpenDevice(strtol(devstring, NULL, 0),i, type);
67422944501Smrg			}
67522944501Smrg		    }
67622944501Smrg		}
67722944501Smrg	    }
67822944501Smrg	}
67922944501Smrg    }
68022944501Smrg#endif
68122944501Smrg
68222944501Smrg    return -1;
68322944501Smrg}
68422944501Smrg
68522944501Smrg
68622944501Smrg/**
68722944501Smrg * Open the DRM device.
68822944501Smrg *
68922944501Smrg * Looks up the specified name and bus ID, and opens the device found.  The
69022944501Smrg * entry in /dev/dri is created if necessary and if called by root.
69122944501Smrg *
69222944501Smrg * \param name driver name. Not referenced if bus ID is supplied.
69322944501Smrg * \param busid bus ID. Zero if not known.
69422944501Smrg *
69522944501Smrg * \return a file descriptor on success, or a negative value on error.
69622944501Smrg *
69722944501Smrg * \internal
69822944501Smrg * It calls drmOpenByBusid() if \p busid is specified or drmOpenByName()
69922944501Smrg * otherwise.
70022944501Smrg */
70122944501Smrgint drmOpen(const char *name, const char *busid)
702424e9256Smrg{
703424e9256Smrg    return drmOpenWithType(name, busid, DRM_NODE_PRIMARY);
704424e9256Smrg}
705424e9256Smrg
706424e9256Smrg/**
707424e9256Smrg * Open the DRM device with specified type.
708424e9256Smrg *
709424e9256Smrg * Looks up the specified name and bus ID, and opens the device found.  The
710424e9256Smrg * entry in /dev/dri is created if necessary and if called by root.
711424e9256Smrg *
712424e9256Smrg * \param name driver name. Not referenced if bus ID is supplied.
713424e9256Smrg * \param busid bus ID. Zero if not known.
714424e9256Smrg * \param type the device node type to open, PRIMARY, CONTROL or RENDER
715424e9256Smrg *
716424e9256Smrg * \return a file descriptor on success, or a negative value on error.
717424e9256Smrg *
718424e9256Smrg * \internal
719424e9256Smrg * It calls drmOpenByBusid() if \p busid is specified or drmOpenByName()
720424e9256Smrg * otherwise.
721424e9256Smrg */
722424e9256Smrgint drmOpenWithType(const char *name, const char *busid, int type)
72322944501Smrg{
72422944501Smrg    if (!drmAvailable() && name != NULL && drm_server_info) {
725424e9256Smrg	/* try to load the kernel module */
72622944501Smrg	if (!drm_server_info->load_module(name)) {
72722944501Smrg	    drmMsg("[drm] failed to load kernel module \"%s\"\n", name);
72822944501Smrg	    return -1;
72922944501Smrg	}
73022944501Smrg    }
73122944501Smrg
73222944501Smrg    if (busid) {
733424e9256Smrg	int fd = drmOpenByBusid(busid, type);
73422944501Smrg	if (fd >= 0)
73522944501Smrg	    return fd;
73622944501Smrg    }
73722944501Smrg
73822944501Smrg    if (name)
739424e9256Smrg	return drmOpenByName(name, type);
74022944501Smrg
74122944501Smrg    return -1;
74222944501Smrg}
74322944501Smrg
74422944501Smrgint drmOpenControl(int minor)
74522944501Smrg{
74622944501Smrg    return drmOpenMinor(minor, 0, DRM_NODE_CONTROL);
74722944501Smrg}
74822944501Smrg
749424e9256Smrgint drmOpenRender(int minor)
750424e9256Smrg{
751424e9256Smrg    return drmOpenMinor(minor, 0, DRM_NODE_RENDER);
752424e9256Smrg}
753424e9256Smrg
75422944501Smrg/**
75522944501Smrg * Free the version information returned by drmGetVersion().
75622944501Smrg *
75722944501Smrg * \param v pointer to the version information.
75822944501Smrg *
75922944501Smrg * \internal
76022944501Smrg * It frees the memory pointed by \p %v as well as all the non-null strings
76122944501Smrg * pointers in it.
76222944501Smrg */
76322944501Smrgvoid drmFreeVersion(drmVersionPtr v)
76422944501Smrg{
76522944501Smrg    if (!v)
76622944501Smrg	return;
76722944501Smrg    drmFree(v->name);
76822944501Smrg    drmFree(v->date);
76922944501Smrg    drmFree(v->desc);
77022944501Smrg    drmFree(v);
77122944501Smrg}
77222944501Smrg
77322944501Smrg
77422944501Smrg/**
77522944501Smrg * Free the non-public version information returned by the kernel.
77622944501Smrg *
77722944501Smrg * \param v pointer to the version information.
77822944501Smrg *
77922944501Smrg * \internal
78022944501Smrg * Used by drmGetVersion() to free the memory pointed by \p %v as well as all
78122944501Smrg * the non-null strings pointers in it.
78222944501Smrg */
78322944501Smrgstatic void drmFreeKernelVersion(drm_version_t *v)
78422944501Smrg{
78522944501Smrg    if (!v)
78622944501Smrg	return;
78722944501Smrg    drmFree(v->name);
78822944501Smrg    drmFree(v->date);
78922944501Smrg    drmFree(v->desc);
79022944501Smrg    drmFree(v);
79122944501Smrg}
79222944501Smrg
79322944501Smrg
79422944501Smrg/**
79522944501Smrg * Copy version information.
79622944501Smrg *
79722944501Smrg * \param d destination pointer.
79822944501Smrg * \param s source pointer.
79922944501Smrg *
80022944501Smrg * \internal
80122944501Smrg * Used by drmGetVersion() to translate the information returned by the ioctl
80222944501Smrg * interface in a private structure into the public structure counterpart.
80322944501Smrg */
80422944501Smrgstatic void drmCopyVersion(drmVersionPtr d, const drm_version_t *s)
80522944501Smrg{
80622944501Smrg    d->version_major      = s->version_major;
80722944501Smrg    d->version_minor      = s->version_minor;
80822944501Smrg    d->version_patchlevel = s->version_patchlevel;
80922944501Smrg    d->name_len           = s->name_len;
8109ce4edccSmrg    d->name               = strdup(s->name);
81122944501Smrg    d->date_len           = s->date_len;
8129ce4edccSmrg    d->date               = strdup(s->date);
81322944501Smrg    d->desc_len           = s->desc_len;
8149ce4edccSmrg    d->desc               = strdup(s->desc);
81522944501Smrg}
81622944501Smrg
81722944501Smrg
81822944501Smrg/**
81922944501Smrg * Query the driver version information.
82022944501Smrg *
82122944501Smrg * \param fd file descriptor.
82222944501Smrg *
82322944501Smrg * \return pointer to a drmVersion structure which should be freed with
82422944501Smrg * drmFreeVersion().
82522944501Smrg *
82622944501Smrg * \note Similar information is available via /proc/dri.
82722944501Smrg *
82822944501Smrg * \internal
82922944501Smrg * It gets the version information via successive DRM_IOCTL_VERSION ioctls,
83022944501Smrg * first with zeros to get the string lengths, and then the actually strings.
83122944501Smrg * It also null-terminates them since they might not be already.
83222944501Smrg */
83322944501SmrgdrmVersionPtr drmGetVersion(int fd)
83422944501Smrg{
83522944501Smrg    drmVersionPtr retval;
83622944501Smrg    drm_version_t *version = drmMalloc(sizeof(*version));
83722944501Smrg
838424e9256Smrg    memclear(*version);
83922944501Smrg
84022944501Smrg    if (drmIoctl(fd, DRM_IOCTL_VERSION, version)) {
84122944501Smrg	drmFreeKernelVersion(version);
84222944501Smrg	return NULL;
84322944501Smrg    }
84422944501Smrg
84522944501Smrg    if (version->name_len)
84622944501Smrg	version->name    = drmMalloc(version->name_len + 1);
84722944501Smrg    if (version->date_len)
84822944501Smrg	version->date    = drmMalloc(version->date_len + 1);
84922944501Smrg    if (version->desc_len)
85022944501Smrg	version->desc    = drmMalloc(version->desc_len + 1);
85122944501Smrg
85222944501Smrg    if (drmIoctl(fd, DRM_IOCTL_VERSION, version)) {
85322944501Smrg	drmMsg("DRM_IOCTL_VERSION: %s\n", strerror(errno));
85422944501Smrg	drmFreeKernelVersion(version);
85522944501Smrg	return NULL;
85622944501Smrg    }
85722944501Smrg
85822944501Smrg    /* The results might not be null-terminated strings, so terminate them. */
85922944501Smrg    if (version->name_len) version->name[version->name_len] = '\0';
86022944501Smrg    if (version->date_len) version->date[version->date_len] = '\0';
86122944501Smrg    if (version->desc_len) version->desc[version->desc_len] = '\0';
86222944501Smrg
86322944501Smrg    retval = drmMalloc(sizeof(*retval));
86422944501Smrg    drmCopyVersion(retval, version);
86522944501Smrg    drmFreeKernelVersion(version);
86622944501Smrg    return retval;
86722944501Smrg}
86822944501Smrg
86922944501Smrg
87022944501Smrg/**
87122944501Smrg * Get version information for the DRM user space library.
87222944501Smrg *
87322944501Smrg * This version number is driver independent.
87422944501Smrg *
87522944501Smrg * \param fd file descriptor.
87622944501Smrg *
87722944501Smrg * \return version information.
87822944501Smrg *
87922944501Smrg * \internal
88022944501Smrg * This function allocates and fills a drm_version structure with a hard coded
88122944501Smrg * version number.
88222944501Smrg */
88322944501SmrgdrmVersionPtr drmGetLibVersion(int fd)
88422944501Smrg{
88522944501Smrg    drm_version_t *version = drmMalloc(sizeof(*version));
88622944501Smrg
88722944501Smrg    /* Version history:
88822944501Smrg     *   NOTE THIS MUST NOT GO ABOVE VERSION 1.X due to drivers needing it
88922944501Smrg     *   revision 1.0.x = original DRM interface with no drmGetLibVersion
89022944501Smrg     *                    entry point and many drm<Device> extensions
89122944501Smrg     *   revision 1.1.x = added drmCommand entry points for device extensions
89222944501Smrg     *                    added drmGetLibVersion to identify libdrm.a version
89322944501Smrg     *   revision 1.2.x = added drmSetInterfaceVersion
89422944501Smrg     *                    modified drmOpen to handle both busid and name
89522944501Smrg     *   revision 1.3.x = added server + memory manager
89622944501Smrg     */
89722944501Smrg    version->version_major      = 1;
89822944501Smrg    version->version_minor      = 3;
89922944501Smrg    version->version_patchlevel = 0;
90022944501Smrg
90122944501Smrg    return (drmVersionPtr)version;
90222944501Smrg}
90322944501Smrg
90420131375Smrgint drmGetCap(int fd, uint64_t capability, uint64_t *value)
90520131375Smrg{
906424e9256Smrg	struct drm_get_cap cap;
90720131375Smrg	int ret;
90820131375Smrg
909424e9256Smrg	memclear(cap);
910424e9256Smrg	cap.capability = capability;
911424e9256Smrg
91220131375Smrg	ret = drmIoctl(fd, DRM_IOCTL_GET_CAP, &cap);
91320131375Smrg	if (ret)
91420131375Smrg		return ret;
91520131375Smrg
91620131375Smrg	*value = cap.value;
91720131375Smrg	return 0;
91820131375Smrg}
91920131375Smrg
92020131375Smrgint drmSetClientCap(int fd, uint64_t capability, uint64_t value)
92120131375Smrg{
922424e9256Smrg	struct drm_set_client_cap cap;
923424e9256Smrg
924424e9256Smrg	memclear(cap);
925424e9256Smrg	cap.capability = capability;
926424e9256Smrg	cap.value = value;
92720131375Smrg
92820131375Smrg	return drmIoctl(fd, DRM_IOCTL_SET_CLIENT_CAP, &cap);
92920131375Smrg}
93022944501Smrg
93122944501Smrg/**
93222944501Smrg * Free the bus ID information.
93322944501Smrg *
93422944501Smrg * \param busid bus ID information string as given by drmGetBusid().
93522944501Smrg *
93622944501Smrg * \internal
93722944501Smrg * This function is just frees the memory pointed by \p busid.
93822944501Smrg */
93922944501Smrgvoid drmFreeBusid(const char *busid)
94022944501Smrg{
94122944501Smrg    drmFree((void *)busid);
94222944501Smrg}
94322944501Smrg
94422944501Smrg
94522944501Smrg/**
94622944501Smrg * Get the bus ID of the device.
94722944501Smrg *
94822944501Smrg * \param fd file descriptor.
94922944501Smrg *
95022944501Smrg * \return bus ID string.
95122944501Smrg *
95222944501Smrg * \internal
95322944501Smrg * This function gets the bus ID via successive DRM_IOCTL_GET_UNIQUE ioctls to
95422944501Smrg * get the string length and data, passing the arguments in a drm_unique
95522944501Smrg * structure.
95622944501Smrg */
95722944501Smrgchar *drmGetBusid(int fd)
95822944501Smrg{
95922944501Smrg    drm_unique_t u;
96022944501Smrg
961424e9256Smrg    memclear(u);
96222944501Smrg
96322944501Smrg    if (drmIoctl(fd, DRM_IOCTL_GET_UNIQUE, &u))
96422944501Smrg	return NULL;
96522944501Smrg    u.unique = drmMalloc(u.unique_len + 1);
96622944501Smrg    if (drmIoctl(fd, DRM_IOCTL_GET_UNIQUE, &u))
96722944501Smrg	return NULL;
96822944501Smrg    u.unique[u.unique_len] = '\0';
96922944501Smrg
97022944501Smrg    return u.unique;
97122944501Smrg}
97222944501Smrg
97322944501Smrg
97422944501Smrg/**
97522944501Smrg * Set the bus ID of the device.
97622944501Smrg *
97722944501Smrg * \param fd file descriptor.
97822944501Smrg * \param busid bus ID string.
97922944501Smrg *
98022944501Smrg * \return zero on success, negative on failure.
98122944501Smrg *
98222944501Smrg * \internal
98322944501Smrg * This function is a wrapper around the DRM_IOCTL_SET_UNIQUE ioctl, passing
98422944501Smrg * the arguments in a drm_unique structure.
98522944501Smrg */
98622944501Smrgint drmSetBusid(int fd, const char *busid)
98722944501Smrg{
98822944501Smrg    drm_unique_t u;
98922944501Smrg
990424e9256Smrg    memclear(u);
99122944501Smrg    u.unique     = (char *)busid;
99222944501Smrg    u.unique_len = strlen(busid);
99322944501Smrg
99422944501Smrg    if (drmIoctl(fd, DRM_IOCTL_SET_UNIQUE, &u)) {
99522944501Smrg	return -errno;
99622944501Smrg    }
99722944501Smrg    return 0;
99822944501Smrg}
99922944501Smrg
100022944501Smrgint drmGetMagic(int fd, drm_magic_t * magic)
100122944501Smrg{
100222944501Smrg    drm_auth_t auth;
100322944501Smrg
1004424e9256Smrg    memclear(auth);
1005424e9256Smrg
100622944501Smrg    *magic = 0;
100722944501Smrg    if (drmIoctl(fd, DRM_IOCTL_GET_MAGIC, &auth))
100822944501Smrg	return -errno;
100922944501Smrg    *magic = auth.magic;
101022944501Smrg    return 0;
101122944501Smrg}
101222944501Smrg
101322944501Smrgint drmAuthMagic(int fd, drm_magic_t magic)
101422944501Smrg{
101522944501Smrg    drm_auth_t auth;
101622944501Smrg
1017424e9256Smrg    memclear(auth);
101822944501Smrg    auth.magic = magic;
101922944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AUTH_MAGIC, &auth))
102022944501Smrg	return -errno;
102122944501Smrg    return 0;
102222944501Smrg}
102322944501Smrg
102422944501Smrg/**
102522944501Smrg * Specifies a range of memory that is available for mapping by a
102622944501Smrg * non-root process.
102722944501Smrg *
102822944501Smrg * \param fd file descriptor.
102922944501Smrg * \param offset usually the physical address. The actual meaning depends of
103022944501Smrg * the \p type parameter. See below.
103122944501Smrg * \param size of the memory in bytes.
103222944501Smrg * \param type type of the memory to be mapped.
103322944501Smrg * \param flags combination of several flags to modify the function actions.
103422944501Smrg * \param handle will be set to a value that may be used as the offset
103522944501Smrg * parameter for mmap().
103622944501Smrg *
103722944501Smrg * \return zero on success or a negative value on error.
103822944501Smrg *
103922944501Smrg * \par Mapping the frame buffer
104022944501Smrg * For the frame buffer
104122944501Smrg * - \p offset will be the physical address of the start of the frame buffer,
104222944501Smrg * - \p size will be the size of the frame buffer in bytes, and
104322944501Smrg * - \p type will be DRM_FRAME_BUFFER.
104422944501Smrg *
104522944501Smrg * \par
104622944501Smrg * The area mapped will be uncached. If MTRR support is available in the
104722944501Smrg * kernel, the frame buffer area will be set to write combining.
104822944501Smrg *
104922944501Smrg * \par Mapping the MMIO register area
105022944501Smrg * For the MMIO register area,
105122944501Smrg * - \p offset will be the physical address of the start of the register area,
105222944501Smrg * - \p size will be the size of the register area bytes, and
105322944501Smrg * - \p type will be DRM_REGISTERS.
105422944501Smrg * \par
105522944501Smrg * The area mapped will be uncached.
105622944501Smrg *
105722944501Smrg * \par Mapping the SAREA
105822944501Smrg * For the SAREA,
105922944501Smrg * - \p offset will be ignored and should be set to zero,
106022944501Smrg * - \p size will be the desired size of the SAREA in bytes,
106122944501Smrg * - \p type will be DRM_SHM.
106222944501Smrg *
106322944501Smrg * \par
106422944501Smrg * A shared memory area of the requested size will be created and locked in
106522944501Smrg * kernel memory. This area may be mapped into client-space by using the handle
106622944501Smrg * returned.
106722944501Smrg *
106822944501Smrg * \note May only be called by root.
106922944501Smrg *
107022944501Smrg * \internal
107122944501Smrg * This function is a wrapper around the DRM_IOCTL_ADD_MAP ioctl, passing
107222944501Smrg * the arguments in a drm_map structure.
107322944501Smrg */
107422944501Smrgint drmAddMap(int fd, drm_handle_t offset, drmSize size, drmMapType type,
107522944501Smrg	      drmMapFlags flags, drm_handle_t *handle)
107622944501Smrg{
107722944501Smrg    drm_map_t map;
107822944501Smrg
1079424e9256Smrg    memclear(map);
108022944501Smrg    map.offset  = offset;
108122944501Smrg    map.size    = size;
108222944501Smrg    map.type    = type;
108322944501Smrg    map.flags   = flags;
108422944501Smrg    if (drmIoctl(fd, DRM_IOCTL_ADD_MAP, &map))
108522944501Smrg	return -errno;
108622944501Smrg    if (handle)
108720131375Smrg	*handle = (drm_handle_t)(uintptr_t)map.handle;
108822944501Smrg    return 0;
108922944501Smrg}
109022944501Smrg
109122944501Smrgint drmRmMap(int fd, drm_handle_t handle)
109222944501Smrg{
109322944501Smrg    drm_map_t map;
109422944501Smrg
1095424e9256Smrg    memclear(map);
109620131375Smrg    map.handle = (void *)(uintptr_t)handle;
109722944501Smrg
109822944501Smrg    if(drmIoctl(fd, DRM_IOCTL_RM_MAP, &map))
109922944501Smrg	return -errno;
110022944501Smrg    return 0;
110122944501Smrg}
110222944501Smrg
110322944501Smrg/**
110422944501Smrg * Make buffers available for DMA transfers.
110522944501Smrg *
110622944501Smrg * \param fd file descriptor.
110722944501Smrg * \param count number of buffers.
110822944501Smrg * \param size size of each buffer.
110922944501Smrg * \param flags buffer allocation flags.
111022944501Smrg * \param agp_offset offset in the AGP aperture
111122944501Smrg *
111222944501Smrg * \return number of buffers allocated, negative on error.
111322944501Smrg *
111422944501Smrg * \internal
111522944501Smrg * This function is a wrapper around DRM_IOCTL_ADD_BUFS ioctl.
111622944501Smrg *
111722944501Smrg * \sa drm_buf_desc.
111822944501Smrg */
111922944501Smrgint drmAddBufs(int fd, int count, int size, drmBufDescFlags flags,
112022944501Smrg	       int agp_offset)
112122944501Smrg{
112222944501Smrg    drm_buf_desc_t request;
112322944501Smrg
1124424e9256Smrg    memclear(request);
112522944501Smrg    request.count     = count;
112622944501Smrg    request.size      = size;
112722944501Smrg    request.flags     = flags;
112822944501Smrg    request.agp_start = agp_offset;
112922944501Smrg
113022944501Smrg    if (drmIoctl(fd, DRM_IOCTL_ADD_BUFS, &request))
113122944501Smrg	return -errno;
113222944501Smrg    return request.count;
113322944501Smrg}
113422944501Smrg
113522944501Smrgint drmMarkBufs(int fd, double low, double high)
113622944501Smrg{
113722944501Smrg    drm_buf_info_t info;
113822944501Smrg    int            i;
113922944501Smrg
1140424e9256Smrg    memclear(info);
114122944501Smrg
114222944501Smrg    if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info))
114322944501Smrg	return -EINVAL;
114422944501Smrg
114522944501Smrg    if (!info.count)
114622944501Smrg	return -EINVAL;
114722944501Smrg
114822944501Smrg    if (!(info.list = drmMalloc(info.count * sizeof(*info.list))))
114922944501Smrg	return -ENOMEM;
115022944501Smrg
115122944501Smrg    if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info)) {
115222944501Smrg	int retval = -errno;
115322944501Smrg	drmFree(info.list);
115422944501Smrg	return retval;
115522944501Smrg    }
115622944501Smrg
115722944501Smrg    for (i = 0; i < info.count; i++) {
115822944501Smrg	info.list[i].low_mark  = low  * info.list[i].count;
115922944501Smrg	info.list[i].high_mark = high * info.list[i].count;
116022944501Smrg	if (drmIoctl(fd, DRM_IOCTL_MARK_BUFS, &info.list[i])) {
116122944501Smrg	    int retval = -errno;
116222944501Smrg	    drmFree(info.list);
116322944501Smrg	    return retval;
116422944501Smrg	}
116522944501Smrg    }
116622944501Smrg    drmFree(info.list);
116722944501Smrg
116822944501Smrg    return 0;
116922944501Smrg}
117022944501Smrg
117122944501Smrg/**
117222944501Smrg * Free buffers.
117322944501Smrg *
117422944501Smrg * \param fd file descriptor.
117522944501Smrg * \param count number of buffers to free.
117622944501Smrg * \param list list of buffers to be freed.
117722944501Smrg *
117822944501Smrg * \return zero on success, or a negative value on failure.
117922944501Smrg *
118022944501Smrg * \note This function is primarily used for debugging.
118122944501Smrg *
118222944501Smrg * \internal
118322944501Smrg * This function is a wrapper around the DRM_IOCTL_FREE_BUFS ioctl, passing
118422944501Smrg * the arguments in a drm_buf_free structure.
118522944501Smrg */
118622944501Smrgint drmFreeBufs(int fd, int count, int *list)
118722944501Smrg{
118822944501Smrg    drm_buf_free_t request;
118922944501Smrg
1190424e9256Smrg    memclear(request);
119122944501Smrg    request.count = count;
119222944501Smrg    request.list  = list;
119322944501Smrg    if (drmIoctl(fd, DRM_IOCTL_FREE_BUFS, &request))
119422944501Smrg	return -errno;
119522944501Smrg    return 0;
119622944501Smrg}
119722944501Smrg
119822944501Smrg
119922944501Smrg/**
120022944501Smrg * Close the device.
120122944501Smrg *
120222944501Smrg * \param fd file descriptor.
120322944501Smrg *
120422944501Smrg * \internal
120522944501Smrg * This function closes the file descriptor.
120622944501Smrg */
120722944501Smrgint drmClose(int fd)
120822944501Smrg{
120922944501Smrg    unsigned long key    = drmGetKeyFromFd(fd);
121022944501Smrg    drmHashEntry  *entry = drmGetEntry(fd);
121122944501Smrg
121222944501Smrg    drmHashDestroy(entry->tagTable);
121322944501Smrg    entry->fd       = 0;
121422944501Smrg    entry->f        = NULL;
121522944501Smrg    entry->tagTable = NULL;
121622944501Smrg
121722944501Smrg    drmHashDelete(drmHashTable, key);
121822944501Smrg    drmFree(entry);
121922944501Smrg
122022944501Smrg    return close(fd);
122122944501Smrg}
122222944501Smrg
122322944501Smrg
122422944501Smrg/**
122522944501Smrg * Map a region of memory.
122622944501Smrg *
122722944501Smrg * \param fd file descriptor.
122822944501Smrg * \param handle handle returned by drmAddMap().
122922944501Smrg * \param size size in bytes. Must match the size used by drmAddMap().
123022944501Smrg * \param address will contain the user-space virtual address where the mapping
123122944501Smrg * begins.
123222944501Smrg *
123322944501Smrg * \return zero on success, or a negative value on failure.
123422944501Smrg *
123522944501Smrg * \internal
123622944501Smrg * This function is a wrapper for mmap().
123722944501Smrg */
123822944501Smrgint drmMap(int fd, drm_handle_t handle, drmSize size, drmAddressPtr address)
123922944501Smrg{
124022944501Smrg    static unsigned long pagesize_mask = 0;
124122944501Smrg
124222944501Smrg    if (fd < 0)
124322944501Smrg	return -EINVAL;
124422944501Smrg
124522944501Smrg    if (!pagesize_mask)
124622944501Smrg	pagesize_mask = getpagesize() - 1;
124722944501Smrg
124822944501Smrg    size = (size + pagesize_mask) & ~pagesize_mask;
124922944501Smrg
1250a884aba1Smrg    *address = drm_mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, handle);
125122944501Smrg    if (*address == MAP_FAILED)
125222944501Smrg	return -errno;
125322944501Smrg    return 0;
125422944501Smrg}
125522944501Smrg
125622944501Smrg
125722944501Smrg/**
125822944501Smrg * Unmap mappings obtained with drmMap().
125922944501Smrg *
126022944501Smrg * \param address address as given by drmMap().
126122944501Smrg * \param size size in bytes. Must match the size used by drmMap().
126222944501Smrg *
126322944501Smrg * \return zero on success, or a negative value on failure.
126422944501Smrg *
126522944501Smrg * \internal
126622944501Smrg * This function is a wrapper for munmap().
126722944501Smrg */
126822944501Smrgint drmUnmap(drmAddress address, drmSize size)
126922944501Smrg{
1270a884aba1Smrg    return drm_munmap(address, size);
127122944501Smrg}
127222944501Smrg
127322944501SmrgdrmBufInfoPtr drmGetBufInfo(int fd)
127422944501Smrg{
127522944501Smrg    drm_buf_info_t info;
127622944501Smrg    drmBufInfoPtr  retval;
127722944501Smrg    int            i;
127822944501Smrg
1279424e9256Smrg    memclear(info);
128022944501Smrg
128122944501Smrg    if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info))
128222944501Smrg	return NULL;
128322944501Smrg
128422944501Smrg    if (info.count) {
128522944501Smrg	if (!(info.list = drmMalloc(info.count * sizeof(*info.list))))
128622944501Smrg	    return NULL;
128722944501Smrg
128822944501Smrg	if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info)) {
128922944501Smrg	    drmFree(info.list);
129022944501Smrg	    return NULL;
129122944501Smrg	}
129222944501Smrg
129322944501Smrg	retval = drmMalloc(sizeof(*retval));
129422944501Smrg	retval->count = info.count;
129522944501Smrg	retval->list  = drmMalloc(info.count * sizeof(*retval->list));
129622944501Smrg	for (i = 0; i < info.count; i++) {
129722944501Smrg	    retval->list[i].count     = info.list[i].count;
129822944501Smrg	    retval->list[i].size      = info.list[i].size;
129922944501Smrg	    retval->list[i].low_mark  = info.list[i].low_mark;
130022944501Smrg	    retval->list[i].high_mark = info.list[i].high_mark;
130122944501Smrg	}
130222944501Smrg	drmFree(info.list);
130322944501Smrg	return retval;
130422944501Smrg    }
130522944501Smrg    return NULL;
130622944501Smrg}
130722944501Smrg
130822944501Smrg/**
130922944501Smrg * Map all DMA buffers into client-virtual space.
131022944501Smrg *
131122944501Smrg * \param fd file descriptor.
131222944501Smrg *
131322944501Smrg * \return a pointer to a ::drmBufMap structure.
131422944501Smrg *
131522944501Smrg * \note The client may not use these buffers until obtaining buffer indices
131622944501Smrg * with drmDMA().
131722944501Smrg *
131822944501Smrg * \internal
131922944501Smrg * This function calls the DRM_IOCTL_MAP_BUFS ioctl and copies the returned
132022944501Smrg * information about the buffers in a drm_buf_map structure into the
132122944501Smrg * client-visible data structures.
132222944501Smrg */
132322944501SmrgdrmBufMapPtr drmMapBufs(int fd)
132422944501Smrg{
132522944501Smrg    drm_buf_map_t bufs;
132622944501Smrg    drmBufMapPtr  retval;
132722944501Smrg    int           i;
132822944501Smrg
1329424e9256Smrg    memclear(bufs);
133022944501Smrg    if (drmIoctl(fd, DRM_IOCTL_MAP_BUFS, &bufs))
133122944501Smrg	return NULL;
133222944501Smrg
133322944501Smrg    if (!bufs.count)
133422944501Smrg	return NULL;
133522944501Smrg
133622944501Smrg	if (!(bufs.list = drmMalloc(bufs.count * sizeof(*bufs.list))))
133722944501Smrg	    return NULL;
133822944501Smrg
133922944501Smrg	if (drmIoctl(fd, DRM_IOCTL_MAP_BUFS, &bufs)) {
134022944501Smrg	    drmFree(bufs.list);
134122944501Smrg	    return NULL;
134222944501Smrg	}
134322944501Smrg
134422944501Smrg	retval = drmMalloc(sizeof(*retval));
134522944501Smrg	retval->count = bufs.count;
134622944501Smrg	retval->list  = drmMalloc(bufs.count * sizeof(*retval->list));
134722944501Smrg	for (i = 0; i < bufs.count; i++) {
134822944501Smrg	    retval->list[i].idx     = bufs.list[i].idx;
134922944501Smrg	    retval->list[i].total   = bufs.list[i].total;
135022944501Smrg	    retval->list[i].used    = 0;
135122944501Smrg	    retval->list[i].address = bufs.list[i].address;
135222944501Smrg	}
135322944501Smrg
135422944501Smrg	drmFree(bufs.list);
135522944501Smrg
135622944501Smrg	return retval;
135722944501Smrg}
135822944501Smrg
135922944501Smrg
136022944501Smrg/**
136122944501Smrg * Unmap buffers allocated with drmMapBufs().
136222944501Smrg *
136322944501Smrg * \return zero on success, or negative value on failure.
136422944501Smrg *
136522944501Smrg * \internal
136622944501Smrg * Calls munmap() for every buffer stored in \p bufs and frees the
136722944501Smrg * memory allocated by drmMapBufs().
136822944501Smrg */
136922944501Smrgint drmUnmapBufs(drmBufMapPtr bufs)
137022944501Smrg{
137122944501Smrg    int i;
137222944501Smrg
137322944501Smrg    for (i = 0; i < bufs->count; i++) {
1374a884aba1Smrg	drm_munmap(bufs->list[i].address, bufs->list[i].total);
137522944501Smrg    }
137622944501Smrg
137722944501Smrg    drmFree(bufs->list);
137822944501Smrg    drmFree(bufs);
137922944501Smrg
138022944501Smrg    return 0;
138122944501Smrg}
138222944501Smrg
138322944501Smrg
138422944501Smrg#define DRM_DMA_RETRY		16
138522944501Smrg
138622944501Smrg/**
138722944501Smrg * Reserve DMA buffers.
138822944501Smrg *
138922944501Smrg * \param fd file descriptor.
139022944501Smrg * \param request
139122944501Smrg *
139222944501Smrg * \return zero on success, or a negative value on failure.
139322944501Smrg *
139422944501Smrg * \internal
139522944501Smrg * Assemble the arguments into a drm_dma structure and keeps issuing the
139622944501Smrg * DRM_IOCTL_DMA ioctl until success or until maximum number of retries.
139722944501Smrg */
139822944501Smrgint drmDMA(int fd, drmDMAReqPtr request)
139922944501Smrg{
140022944501Smrg    drm_dma_t dma;
140122944501Smrg    int ret, i = 0;
140222944501Smrg
140322944501Smrg    dma.context         = request->context;
140422944501Smrg    dma.send_count      = request->send_count;
140522944501Smrg    dma.send_indices    = request->send_list;
140622944501Smrg    dma.send_sizes      = request->send_sizes;
140722944501Smrg    dma.flags           = request->flags;
140822944501Smrg    dma.request_count   = request->request_count;
140922944501Smrg    dma.request_size    = request->request_size;
141022944501Smrg    dma.request_indices = request->request_list;
141122944501Smrg    dma.request_sizes   = request->request_sizes;
141222944501Smrg    dma.granted_count   = 0;
141322944501Smrg
141422944501Smrg    do {
141522944501Smrg	ret = ioctl( fd, DRM_IOCTL_DMA, &dma );
141622944501Smrg    } while ( ret && errno == EAGAIN && i++ < DRM_DMA_RETRY );
141722944501Smrg
141822944501Smrg    if ( ret == 0 ) {
141922944501Smrg	request->granted_count = dma.granted_count;
142022944501Smrg	return 0;
142122944501Smrg    } else {
142222944501Smrg	return -errno;
142322944501Smrg    }
142422944501Smrg}
142522944501Smrg
142622944501Smrg
142722944501Smrg/**
142822944501Smrg * Obtain heavyweight hardware lock.
142922944501Smrg *
143022944501Smrg * \param fd file descriptor.
143122944501Smrg * \param context context.
143222944501Smrg * \param flags flags that determine the sate of the hardware when the function
143322944501Smrg * returns.
143422944501Smrg *
143522944501Smrg * \return always zero.
143622944501Smrg *
143722944501Smrg * \internal
143822944501Smrg * This function translates the arguments into a drm_lock structure and issue
143922944501Smrg * the DRM_IOCTL_LOCK ioctl until the lock is successfully acquired.
144022944501Smrg */
144122944501Smrgint drmGetLock(int fd, drm_context_t context, drmLockFlags flags)
144222944501Smrg{
144322944501Smrg    drm_lock_t lock;
144422944501Smrg
1445424e9256Smrg    memclear(lock);
144622944501Smrg    lock.context = context;
144722944501Smrg    lock.flags   = 0;
144822944501Smrg    if (flags & DRM_LOCK_READY)      lock.flags |= _DRM_LOCK_READY;
144922944501Smrg    if (flags & DRM_LOCK_QUIESCENT)  lock.flags |= _DRM_LOCK_QUIESCENT;
145022944501Smrg    if (flags & DRM_LOCK_FLUSH)      lock.flags |= _DRM_LOCK_FLUSH;
145122944501Smrg    if (flags & DRM_LOCK_FLUSH_ALL)  lock.flags |= _DRM_LOCK_FLUSH_ALL;
145222944501Smrg    if (flags & DRM_HALT_ALL_QUEUES) lock.flags |= _DRM_HALT_ALL_QUEUES;
145322944501Smrg    if (flags & DRM_HALT_CUR_QUEUES) lock.flags |= _DRM_HALT_CUR_QUEUES;
145422944501Smrg
145522944501Smrg    while (drmIoctl(fd, DRM_IOCTL_LOCK, &lock))
145622944501Smrg	;
145722944501Smrg    return 0;
145822944501Smrg}
145922944501Smrg
146022944501Smrg/**
146122944501Smrg * Release the hardware lock.
146222944501Smrg *
146322944501Smrg * \param fd file descriptor.
146422944501Smrg * \param context context.
146522944501Smrg *
146622944501Smrg * \return zero on success, or a negative value on failure.
146722944501Smrg *
146822944501Smrg * \internal
146922944501Smrg * This function is a wrapper around the DRM_IOCTL_UNLOCK ioctl, passing the
147022944501Smrg * argument in a drm_lock structure.
147122944501Smrg */
147222944501Smrgint drmUnlock(int fd, drm_context_t context)
147322944501Smrg{
147422944501Smrg    drm_lock_t lock;
147522944501Smrg
1476424e9256Smrg    memclear(lock);
147722944501Smrg    lock.context = context;
147822944501Smrg    return drmIoctl(fd, DRM_IOCTL_UNLOCK, &lock);
147922944501Smrg}
148022944501Smrg
148122944501Smrgdrm_context_t *drmGetReservedContextList(int fd, int *count)
148222944501Smrg{
148322944501Smrg    drm_ctx_res_t res;
148422944501Smrg    drm_ctx_t     *list;
148522944501Smrg    drm_context_t * retval;
148622944501Smrg    int           i;
148722944501Smrg
1488424e9256Smrg    memclear(res);
148922944501Smrg    if (drmIoctl(fd, DRM_IOCTL_RES_CTX, &res))
149022944501Smrg	return NULL;
149122944501Smrg
149222944501Smrg    if (!res.count)
149322944501Smrg	return NULL;
149422944501Smrg
149522944501Smrg    if (!(list   = drmMalloc(res.count * sizeof(*list))))
149622944501Smrg	return NULL;
149722944501Smrg    if (!(retval = drmMalloc(res.count * sizeof(*retval)))) {
149822944501Smrg	drmFree(list);
149922944501Smrg	return NULL;
150022944501Smrg    }
150122944501Smrg
150222944501Smrg    res.contexts = list;
150322944501Smrg    if (drmIoctl(fd, DRM_IOCTL_RES_CTX, &res))
150422944501Smrg	return NULL;
150522944501Smrg
150622944501Smrg    for (i = 0; i < res.count; i++)
150722944501Smrg	retval[i] = list[i].handle;
150822944501Smrg    drmFree(list);
150922944501Smrg
151022944501Smrg    *count = res.count;
151122944501Smrg    return retval;
151222944501Smrg}
151322944501Smrg
151422944501Smrgvoid drmFreeReservedContextList(drm_context_t *pt)
151522944501Smrg{
151622944501Smrg    drmFree(pt);
151722944501Smrg}
151822944501Smrg
151922944501Smrg/**
152022944501Smrg * Create context.
152122944501Smrg *
152222944501Smrg * Used by the X server during GLXContext initialization. This causes
152322944501Smrg * per-context kernel-level resources to be allocated.
152422944501Smrg *
152522944501Smrg * \param fd file descriptor.
152622944501Smrg * \param handle is set on success. To be used by the client when requesting DMA
152722944501Smrg * dispatch with drmDMA().
152822944501Smrg *
152922944501Smrg * \return zero on success, or a negative value on failure.
153022944501Smrg *
153122944501Smrg * \note May only be called by root.
153222944501Smrg *
153322944501Smrg * \internal
153422944501Smrg * This function is a wrapper around the DRM_IOCTL_ADD_CTX ioctl, passing the
153522944501Smrg * argument in a drm_ctx structure.
153622944501Smrg */
153722944501Smrgint drmCreateContext(int fd, drm_context_t *handle)
153822944501Smrg{
153922944501Smrg    drm_ctx_t ctx;
154022944501Smrg
1541424e9256Smrg    memclear(ctx);
154222944501Smrg    if (drmIoctl(fd, DRM_IOCTL_ADD_CTX, &ctx))
154322944501Smrg	return -errno;
154422944501Smrg    *handle = ctx.handle;
154522944501Smrg    return 0;
154622944501Smrg}
154722944501Smrg
154822944501Smrgint drmSwitchToContext(int fd, drm_context_t context)
154922944501Smrg{
155022944501Smrg    drm_ctx_t ctx;
155122944501Smrg
1552424e9256Smrg    memclear(ctx);
155322944501Smrg    ctx.handle = context;
155422944501Smrg    if (drmIoctl(fd, DRM_IOCTL_SWITCH_CTX, &ctx))
155522944501Smrg	return -errno;
155622944501Smrg    return 0;
155722944501Smrg}
155822944501Smrg
155922944501Smrgint drmSetContextFlags(int fd, drm_context_t context, drm_context_tFlags flags)
156022944501Smrg{
156122944501Smrg    drm_ctx_t ctx;
156222944501Smrg
156322944501Smrg    /*
156422944501Smrg     * Context preserving means that no context switches are done between DMA
156522944501Smrg     * buffers from one context and the next.  This is suitable for use in the
156622944501Smrg     * X server (which promises to maintain hardware context), or in the
156722944501Smrg     * client-side library when buffers are swapped on behalf of two threads.
156822944501Smrg     */
1569424e9256Smrg    memclear(ctx);
157022944501Smrg    ctx.handle = context;
157122944501Smrg    if (flags & DRM_CONTEXT_PRESERVED)
157222944501Smrg	ctx.flags |= _DRM_CONTEXT_PRESERVED;
157322944501Smrg    if (flags & DRM_CONTEXT_2DONLY)
157422944501Smrg	ctx.flags |= _DRM_CONTEXT_2DONLY;
157522944501Smrg    if (drmIoctl(fd, DRM_IOCTL_MOD_CTX, &ctx))
157622944501Smrg	return -errno;
157722944501Smrg    return 0;
157822944501Smrg}
157922944501Smrg
158022944501Smrgint drmGetContextFlags(int fd, drm_context_t context,
158122944501Smrg                       drm_context_tFlagsPtr flags)
158222944501Smrg{
158322944501Smrg    drm_ctx_t ctx;
158422944501Smrg
1585424e9256Smrg    memclear(ctx);
158622944501Smrg    ctx.handle = context;
158722944501Smrg    if (drmIoctl(fd, DRM_IOCTL_GET_CTX, &ctx))
158822944501Smrg	return -errno;
158922944501Smrg    *flags = 0;
159022944501Smrg    if (ctx.flags & _DRM_CONTEXT_PRESERVED)
159122944501Smrg	*flags |= DRM_CONTEXT_PRESERVED;
159222944501Smrg    if (ctx.flags & _DRM_CONTEXT_2DONLY)
159322944501Smrg	*flags |= DRM_CONTEXT_2DONLY;
159422944501Smrg    return 0;
159522944501Smrg}
159622944501Smrg
159722944501Smrg/**
159822944501Smrg * Destroy context.
159922944501Smrg *
160022944501Smrg * Free any kernel-level resources allocated with drmCreateContext() associated
160122944501Smrg * with the context.
160222944501Smrg *
160322944501Smrg * \param fd file descriptor.
160422944501Smrg * \param handle handle given by drmCreateContext().
160522944501Smrg *
160622944501Smrg * \return zero on success, or a negative value on failure.
160722944501Smrg *
160822944501Smrg * \note May only be called by root.
160922944501Smrg *
161022944501Smrg * \internal
161122944501Smrg * This function is a wrapper around the DRM_IOCTL_RM_CTX ioctl, passing the
161222944501Smrg * argument in a drm_ctx structure.
161322944501Smrg */
161422944501Smrgint drmDestroyContext(int fd, drm_context_t handle)
161522944501Smrg{
161622944501Smrg    drm_ctx_t ctx;
1617424e9256Smrg
1618424e9256Smrg    memclear(ctx);
161922944501Smrg    ctx.handle = handle;
162022944501Smrg    if (drmIoctl(fd, DRM_IOCTL_RM_CTX, &ctx))
162122944501Smrg	return -errno;
162222944501Smrg    return 0;
162322944501Smrg}
162422944501Smrg
162522944501Smrgint drmCreateDrawable(int fd, drm_drawable_t *handle)
162622944501Smrg{
162722944501Smrg    drm_draw_t draw;
1628424e9256Smrg
1629424e9256Smrg    memclear(draw);
163022944501Smrg    if (drmIoctl(fd, DRM_IOCTL_ADD_DRAW, &draw))
163122944501Smrg	return -errno;
163222944501Smrg    *handle = draw.handle;
163322944501Smrg    return 0;
163422944501Smrg}
163522944501Smrg
163622944501Smrgint drmDestroyDrawable(int fd, drm_drawable_t handle)
163722944501Smrg{
163822944501Smrg    drm_draw_t draw;
1639424e9256Smrg
1640424e9256Smrg    memclear(draw);
164122944501Smrg    draw.handle = handle;
164222944501Smrg    if (drmIoctl(fd, DRM_IOCTL_RM_DRAW, &draw))
164322944501Smrg	return -errno;
164422944501Smrg    return 0;
164522944501Smrg}
164622944501Smrg
164722944501Smrgint drmUpdateDrawableInfo(int fd, drm_drawable_t handle,
164822944501Smrg			   drm_drawable_info_type_t type, unsigned int num,
164922944501Smrg			   void *data)
165022944501Smrg{
165122944501Smrg    drm_update_draw_t update;
165222944501Smrg
1653424e9256Smrg    memclear(update);
165422944501Smrg    update.handle = handle;
165522944501Smrg    update.type = type;
165622944501Smrg    update.num = num;
165722944501Smrg    update.data = (unsigned long long)(unsigned long)data;
165822944501Smrg
165922944501Smrg    if (drmIoctl(fd, DRM_IOCTL_UPDATE_DRAW, &update))
166022944501Smrg	return -errno;
166122944501Smrg
166222944501Smrg    return 0;
166322944501Smrg}
166422944501Smrg
166522944501Smrg/**
166622944501Smrg * Acquire the AGP device.
166722944501Smrg *
166822944501Smrg * Must be called before any of the other AGP related calls.
166922944501Smrg *
167022944501Smrg * \param fd file descriptor.
167122944501Smrg *
167222944501Smrg * \return zero on success, or a negative value on failure.
167322944501Smrg *
167422944501Smrg * \internal
167522944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_ACQUIRE ioctl.
167622944501Smrg */
167722944501Smrgint drmAgpAcquire(int fd)
167822944501Smrg{
167922944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AGP_ACQUIRE, NULL))
168022944501Smrg	return -errno;
168122944501Smrg    return 0;
168222944501Smrg}
168322944501Smrg
168422944501Smrg
168522944501Smrg/**
168622944501Smrg * Release the AGP device.
168722944501Smrg *
168822944501Smrg * \param fd file descriptor.
168922944501Smrg *
169022944501Smrg * \return zero on success, or a negative value on failure.
169122944501Smrg *
169222944501Smrg * \internal
169322944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_RELEASE ioctl.
169422944501Smrg */
169522944501Smrgint drmAgpRelease(int fd)
169622944501Smrg{
169722944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AGP_RELEASE, NULL))
169822944501Smrg	return -errno;
169922944501Smrg    return 0;
170022944501Smrg}
170122944501Smrg
170222944501Smrg
170322944501Smrg/**
170422944501Smrg * Set the AGP mode.
170522944501Smrg *
170622944501Smrg * \param fd file descriptor.
170722944501Smrg * \param mode AGP mode.
170822944501Smrg *
170922944501Smrg * \return zero on success, or a negative value on failure.
171022944501Smrg *
171122944501Smrg * \internal
171222944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_ENABLE ioctl, passing the
171322944501Smrg * argument in a drm_agp_mode structure.
171422944501Smrg */
171522944501Smrgint drmAgpEnable(int fd, unsigned long mode)
171622944501Smrg{
171722944501Smrg    drm_agp_mode_t m;
171822944501Smrg
1719424e9256Smrg    memclear(m);
172022944501Smrg    m.mode = mode;
172122944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AGP_ENABLE, &m))
172222944501Smrg	return -errno;
172322944501Smrg    return 0;
172422944501Smrg}
172522944501Smrg
172622944501Smrg
172722944501Smrg/**
172822944501Smrg * Allocate a chunk of AGP memory.
172922944501Smrg *
173022944501Smrg * \param fd file descriptor.
173122944501Smrg * \param size requested memory size in bytes. Will be rounded to page boundary.
173222944501Smrg * \param type type of memory to allocate.
173322944501Smrg * \param address if not zero, will be set to the physical address of the
173422944501Smrg * allocated memory.
173522944501Smrg * \param handle on success will be set to a handle of the allocated memory.
173622944501Smrg *
173722944501Smrg * \return zero on success, or a negative value on failure.
173822944501Smrg *
173922944501Smrg * \internal
174022944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_ALLOC ioctl, passing the
174122944501Smrg * arguments in a drm_agp_buffer structure.
174222944501Smrg */
174322944501Smrgint drmAgpAlloc(int fd, unsigned long size, unsigned long type,
174422944501Smrg		unsigned long *address, drm_handle_t *handle)
174522944501Smrg{
174622944501Smrg    drm_agp_buffer_t b;
174722944501Smrg
1748424e9256Smrg    memclear(b);
174922944501Smrg    *handle = DRM_AGP_NO_HANDLE;
175022944501Smrg    b.size   = size;
175122944501Smrg    b.type   = type;
175222944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AGP_ALLOC, &b))
175322944501Smrg	return -errno;
175422944501Smrg    if (address != 0UL)
175522944501Smrg	*address = b.physical;
175622944501Smrg    *handle = b.handle;
175722944501Smrg    return 0;
175822944501Smrg}
175922944501Smrg
176022944501Smrg
176122944501Smrg/**
176222944501Smrg * Free a chunk of AGP memory.
176322944501Smrg *
176422944501Smrg * \param fd file descriptor.
176522944501Smrg * \param handle handle to the allocated memory, as given by drmAgpAllocate().
176622944501Smrg *
176722944501Smrg * \return zero on success, or a negative value on failure.
176822944501Smrg *
176922944501Smrg * \internal
177022944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_FREE ioctl, passing the
177122944501Smrg * argument in a drm_agp_buffer structure.
177222944501Smrg */
177322944501Smrgint drmAgpFree(int fd, drm_handle_t handle)
177422944501Smrg{
177522944501Smrg    drm_agp_buffer_t b;
177622944501Smrg
1777424e9256Smrg    memclear(b);
177822944501Smrg    b.handle = handle;
177922944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AGP_FREE, &b))
178022944501Smrg	return -errno;
178122944501Smrg    return 0;
178222944501Smrg}
178322944501Smrg
178422944501Smrg
178522944501Smrg/**
178622944501Smrg * Bind a chunk of AGP memory.
178722944501Smrg *
178822944501Smrg * \param fd file descriptor.
178922944501Smrg * \param handle handle to the allocated memory, as given by drmAgpAllocate().
179022944501Smrg * \param offset offset in bytes. It will round to page boundary.
179122944501Smrg *
179222944501Smrg * \return zero on success, or a negative value on failure.
179322944501Smrg *
179422944501Smrg * \internal
179522944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_BIND ioctl, passing the
179622944501Smrg * argument in a drm_agp_binding structure.
179722944501Smrg */
179822944501Smrgint drmAgpBind(int fd, drm_handle_t handle, unsigned long offset)
179922944501Smrg{
180022944501Smrg    drm_agp_binding_t b;
180122944501Smrg
1802424e9256Smrg    memclear(b);
180322944501Smrg    b.handle = handle;
180422944501Smrg    b.offset = offset;
180522944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AGP_BIND, &b))
180622944501Smrg	return -errno;
180722944501Smrg    return 0;
180822944501Smrg}
180922944501Smrg
181022944501Smrg
181122944501Smrg/**
181222944501Smrg * Unbind a chunk of AGP memory.
181322944501Smrg *
181422944501Smrg * \param fd file descriptor.
181522944501Smrg * \param handle handle to the allocated memory, as given by drmAgpAllocate().
181622944501Smrg *
181722944501Smrg * \return zero on success, or a negative value on failure.
181822944501Smrg *
181922944501Smrg * \internal
182022944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_UNBIND ioctl, passing
182122944501Smrg * the argument in a drm_agp_binding structure.
182222944501Smrg */
182322944501Smrgint drmAgpUnbind(int fd, drm_handle_t handle)
182422944501Smrg{
182522944501Smrg    drm_agp_binding_t b;
182622944501Smrg
1827424e9256Smrg    memclear(b);
182822944501Smrg    b.handle = handle;
182922944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AGP_UNBIND, &b))
183022944501Smrg	return -errno;
183122944501Smrg    return 0;
183222944501Smrg}
183322944501Smrg
183422944501Smrg
183522944501Smrg/**
183622944501Smrg * Get AGP driver major version number.
183722944501Smrg *
183822944501Smrg * \param fd file descriptor.
183922944501Smrg *
184022944501Smrg * \return major version number on success, or a negative value on failure..
184122944501Smrg *
184222944501Smrg * \internal
184322944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
184422944501Smrg * necessary information in a drm_agp_info structure.
184522944501Smrg */
184622944501Smrgint drmAgpVersionMajor(int fd)
184722944501Smrg{
184822944501Smrg    drm_agp_info_t i;
184922944501Smrg
1850424e9256Smrg    memclear(i);
1851424e9256Smrg
185222944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
185322944501Smrg	return -errno;
185422944501Smrg    return i.agp_version_major;
185522944501Smrg}
185622944501Smrg
185722944501Smrg
185822944501Smrg/**
185922944501Smrg * Get AGP driver minor version number.
186022944501Smrg *
186122944501Smrg * \param fd file descriptor.
186222944501Smrg *
186322944501Smrg * \return minor version number on success, or a negative value on failure.
186422944501Smrg *
186522944501Smrg * \internal
186622944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
186722944501Smrg * necessary information in a drm_agp_info structure.
186822944501Smrg */
186922944501Smrgint drmAgpVersionMinor(int fd)
187022944501Smrg{
187122944501Smrg    drm_agp_info_t i;
187222944501Smrg
1873424e9256Smrg    memclear(i);
1874424e9256Smrg
187522944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
187622944501Smrg	return -errno;
187722944501Smrg    return i.agp_version_minor;
187822944501Smrg}
187922944501Smrg
188022944501Smrg
188122944501Smrg/**
188222944501Smrg * Get AGP mode.
188322944501Smrg *
188422944501Smrg * \param fd file descriptor.
188522944501Smrg *
188622944501Smrg * \return mode on success, or zero on failure.
188722944501Smrg *
188822944501Smrg * \internal
188922944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
189022944501Smrg * necessary information in a drm_agp_info structure.
189122944501Smrg */
189222944501Smrgunsigned long drmAgpGetMode(int fd)
189322944501Smrg{
189422944501Smrg    drm_agp_info_t i;
189522944501Smrg
1896424e9256Smrg    memclear(i);
1897424e9256Smrg
189822944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
189922944501Smrg	return 0;
190022944501Smrg    return i.mode;
190122944501Smrg}
190222944501Smrg
190322944501Smrg
190422944501Smrg/**
190522944501Smrg * Get AGP aperture base.
190622944501Smrg *
190722944501Smrg * \param fd file descriptor.
190822944501Smrg *
190922944501Smrg * \return aperture base on success, zero on failure.
191022944501Smrg *
191122944501Smrg * \internal
191222944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
191322944501Smrg * necessary information in a drm_agp_info structure.
191422944501Smrg */
191522944501Smrgunsigned long drmAgpBase(int fd)
191622944501Smrg{
191722944501Smrg    drm_agp_info_t i;
191822944501Smrg
1919424e9256Smrg    memclear(i);
1920424e9256Smrg
192122944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
192222944501Smrg	return 0;
192322944501Smrg    return i.aperture_base;
192422944501Smrg}
192522944501Smrg
192622944501Smrg
192722944501Smrg/**
192822944501Smrg * Get AGP aperture size.
192922944501Smrg *
193022944501Smrg * \param fd file descriptor.
193122944501Smrg *
193222944501Smrg * \return aperture size on success, zero on failure.
193322944501Smrg *
193422944501Smrg * \internal
193522944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
193622944501Smrg * necessary information in a drm_agp_info structure.
193722944501Smrg */
193822944501Smrgunsigned long drmAgpSize(int fd)
193922944501Smrg{
194022944501Smrg    drm_agp_info_t i;
194122944501Smrg
1942424e9256Smrg    memclear(i);
1943424e9256Smrg
194422944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
194522944501Smrg	return 0;
194622944501Smrg    return i.aperture_size;
194722944501Smrg}
194822944501Smrg
194922944501Smrg
195022944501Smrg/**
195122944501Smrg * Get used AGP memory.
195222944501Smrg *
195322944501Smrg * \param fd file descriptor.
195422944501Smrg *
195522944501Smrg * \return memory used on success, or zero on failure.
195622944501Smrg *
195722944501Smrg * \internal
195822944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
195922944501Smrg * necessary information in a drm_agp_info structure.
196022944501Smrg */
196122944501Smrgunsigned long drmAgpMemoryUsed(int fd)
196222944501Smrg{
196322944501Smrg    drm_agp_info_t i;
196422944501Smrg
1965424e9256Smrg    memclear(i);
1966424e9256Smrg
196722944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
196822944501Smrg	return 0;
196922944501Smrg    return i.memory_used;
197022944501Smrg}
197122944501Smrg
197222944501Smrg
197322944501Smrg/**
197422944501Smrg * Get available AGP memory.
197522944501Smrg *
197622944501Smrg * \param fd file descriptor.
197722944501Smrg *
197822944501Smrg * \return memory available on success, or zero on failure.
197922944501Smrg *
198022944501Smrg * \internal
198122944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
198222944501Smrg * necessary information in a drm_agp_info structure.
198322944501Smrg */
198422944501Smrgunsigned long drmAgpMemoryAvail(int fd)
198522944501Smrg{
198622944501Smrg    drm_agp_info_t i;
198722944501Smrg
1988424e9256Smrg    memclear(i);
1989424e9256Smrg
199022944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
199122944501Smrg	return 0;
199222944501Smrg    return i.memory_allowed;
199322944501Smrg}
199422944501Smrg
199522944501Smrg
199622944501Smrg/**
199722944501Smrg * Get hardware vendor ID.
199822944501Smrg *
199922944501Smrg * \param fd file descriptor.
200022944501Smrg *
200122944501Smrg * \return vendor ID on success, or zero on failure.
200222944501Smrg *
200322944501Smrg * \internal
200422944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
200522944501Smrg * necessary information in a drm_agp_info structure.
200622944501Smrg */
200722944501Smrgunsigned int drmAgpVendorId(int fd)
200822944501Smrg{
200922944501Smrg    drm_agp_info_t i;
201022944501Smrg
2011424e9256Smrg    memclear(i);
2012424e9256Smrg
201322944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
201422944501Smrg	return 0;
201522944501Smrg    return i.id_vendor;
201622944501Smrg}
201722944501Smrg
201822944501Smrg
201922944501Smrg/**
202022944501Smrg * Get hardware device ID.
202122944501Smrg *
202222944501Smrg * \param fd file descriptor.
202322944501Smrg *
202422944501Smrg * \return zero on success, or zero on failure.
202522944501Smrg *
202622944501Smrg * \internal
202722944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
202822944501Smrg * necessary information in a drm_agp_info structure.
202922944501Smrg */
203022944501Smrgunsigned int drmAgpDeviceId(int fd)
203122944501Smrg{
203222944501Smrg    drm_agp_info_t i;
203322944501Smrg
2034424e9256Smrg    memclear(i);
2035424e9256Smrg
203622944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
203722944501Smrg	return 0;
203822944501Smrg    return i.id_device;
203922944501Smrg}
204022944501Smrg
204122944501Smrgint drmScatterGatherAlloc(int fd, unsigned long size, drm_handle_t *handle)
204222944501Smrg{
204322944501Smrg    drm_scatter_gather_t sg;
204422944501Smrg
2045424e9256Smrg    memclear(sg);
2046424e9256Smrg
204722944501Smrg    *handle = 0;
204822944501Smrg    sg.size   = size;
204922944501Smrg    if (drmIoctl(fd, DRM_IOCTL_SG_ALLOC, &sg))
205022944501Smrg	return -errno;
205122944501Smrg    *handle = sg.handle;
205222944501Smrg    return 0;
205322944501Smrg}
205422944501Smrg
205522944501Smrgint drmScatterGatherFree(int fd, drm_handle_t handle)
205622944501Smrg{
205722944501Smrg    drm_scatter_gather_t sg;
205822944501Smrg
2059424e9256Smrg    memclear(sg);
206022944501Smrg    sg.handle = handle;
206122944501Smrg    if (drmIoctl(fd, DRM_IOCTL_SG_FREE, &sg))
206222944501Smrg	return -errno;
206322944501Smrg    return 0;
206422944501Smrg}
206522944501Smrg
206622944501Smrg/**
206722944501Smrg * Wait for VBLANK.
206822944501Smrg *
206922944501Smrg * \param fd file descriptor.
207022944501Smrg * \param vbl pointer to a drmVBlank structure.
207122944501Smrg *
207222944501Smrg * \return zero on success, or a negative value on failure.
207322944501Smrg *
207422944501Smrg * \internal
207522944501Smrg * This function is a wrapper around the DRM_IOCTL_WAIT_VBLANK ioctl.
207622944501Smrg */
207722944501Smrgint drmWaitVBlank(int fd, drmVBlankPtr vbl)
207822944501Smrg{
207922944501Smrg    struct timespec timeout, cur;
208022944501Smrg    int ret;
208122944501Smrg
208222944501Smrg    ret = clock_gettime(CLOCK_MONOTONIC, &timeout);
208322944501Smrg    if (ret < 0) {
208420131375Smrg	fprintf(stderr, "clock_gettime failed: %s\n", strerror(errno));
208522944501Smrg	goto out;
208622944501Smrg    }
208722944501Smrg    timeout.tv_sec++;
208822944501Smrg
208922944501Smrg    do {
209022944501Smrg       ret = ioctl(fd, DRM_IOCTL_WAIT_VBLANK, vbl);
209122944501Smrg       vbl->request.type &= ~DRM_VBLANK_RELATIVE;
209222944501Smrg       if (ret && errno == EINTR) {
209322944501Smrg	       clock_gettime(CLOCK_MONOTONIC, &cur);
209422944501Smrg	       /* Timeout after 1s */
209522944501Smrg	       if (cur.tv_sec > timeout.tv_sec + 1 ||
209622944501Smrg		   (cur.tv_sec == timeout.tv_sec && cur.tv_nsec >=
209722944501Smrg		    timeout.tv_nsec)) {
209822944501Smrg		       errno = EBUSY;
209922944501Smrg		       ret = -1;
210022944501Smrg		       break;
210122944501Smrg	       }
210222944501Smrg       }
210322944501Smrg    } while (ret && errno == EINTR);
210422944501Smrg
210522944501Smrgout:
210622944501Smrg    return ret;
210722944501Smrg}
210822944501Smrg
210922944501Smrgint drmError(int err, const char *label)
211022944501Smrg{
211122944501Smrg    switch (err) {
211222944501Smrg    case DRM_ERR_NO_DEVICE:
211322944501Smrg	fprintf(stderr, "%s: no device\n", label);
211422944501Smrg	break;
211522944501Smrg    case DRM_ERR_NO_ACCESS:
211622944501Smrg	fprintf(stderr, "%s: no access\n", label);
211722944501Smrg	break;
211822944501Smrg    case DRM_ERR_NOT_ROOT:
211922944501Smrg	fprintf(stderr, "%s: not root\n", label);
212022944501Smrg	break;
212122944501Smrg    case DRM_ERR_INVALID:
212222944501Smrg	fprintf(stderr, "%s: invalid args\n", label);
212322944501Smrg	break;
212422944501Smrg    default:
212522944501Smrg	if (err < 0)
212622944501Smrg	    err = -err;
212722944501Smrg	fprintf( stderr, "%s: error %d (%s)\n", label, err, strerror(err) );
212822944501Smrg	break;
212922944501Smrg    }
213022944501Smrg
213122944501Smrg    return 1;
213222944501Smrg}
213322944501Smrg
213422944501Smrg/**
213522944501Smrg * Install IRQ handler.
213622944501Smrg *
213722944501Smrg * \param fd file descriptor.
213822944501Smrg * \param irq IRQ number.
213922944501Smrg *
214022944501Smrg * \return zero on success, or a negative value on failure.
214122944501Smrg *
214222944501Smrg * \internal
214322944501Smrg * This function is a wrapper around the DRM_IOCTL_CONTROL ioctl, passing the
214422944501Smrg * argument in a drm_control structure.
214522944501Smrg */
214622944501Smrgint drmCtlInstHandler(int fd, int irq)
214722944501Smrg{
214822944501Smrg    drm_control_t ctl;
214922944501Smrg
2150424e9256Smrg    memclear(ctl);
215122944501Smrg    ctl.func  = DRM_INST_HANDLER;
215222944501Smrg    ctl.irq   = irq;
215322944501Smrg    if (drmIoctl(fd, DRM_IOCTL_CONTROL, &ctl))
215422944501Smrg	return -errno;
215522944501Smrg    return 0;
215622944501Smrg}
215722944501Smrg
215822944501Smrg
215922944501Smrg/**
216022944501Smrg * Uninstall IRQ handler.
216122944501Smrg *
216222944501Smrg * \param fd file descriptor.
216322944501Smrg *
216422944501Smrg * \return zero on success, or a negative value on failure.
216522944501Smrg *
216622944501Smrg * \internal
216722944501Smrg * This function is a wrapper around the DRM_IOCTL_CONTROL ioctl, passing the
216822944501Smrg * argument in a drm_control structure.
216922944501Smrg */
217022944501Smrgint drmCtlUninstHandler(int fd)
217122944501Smrg{
217222944501Smrg    drm_control_t ctl;
217322944501Smrg
2174424e9256Smrg    memclear(ctl);
217522944501Smrg    ctl.func  = DRM_UNINST_HANDLER;
217622944501Smrg    ctl.irq   = 0;
217722944501Smrg    if (drmIoctl(fd, DRM_IOCTL_CONTROL, &ctl))
217822944501Smrg	return -errno;
217922944501Smrg    return 0;
218022944501Smrg}
218122944501Smrg
218222944501Smrgint drmFinish(int fd, int context, drmLockFlags flags)
218322944501Smrg{
218422944501Smrg    drm_lock_t lock;
218522944501Smrg
2186424e9256Smrg    memclear(lock);
218722944501Smrg    lock.context = context;
218822944501Smrg    if (flags & DRM_LOCK_READY)      lock.flags |= _DRM_LOCK_READY;
218922944501Smrg    if (flags & DRM_LOCK_QUIESCENT)  lock.flags |= _DRM_LOCK_QUIESCENT;
219022944501Smrg    if (flags & DRM_LOCK_FLUSH)      lock.flags |= _DRM_LOCK_FLUSH;
219122944501Smrg    if (flags & DRM_LOCK_FLUSH_ALL)  lock.flags |= _DRM_LOCK_FLUSH_ALL;
219222944501Smrg    if (flags & DRM_HALT_ALL_QUEUES) lock.flags |= _DRM_HALT_ALL_QUEUES;
219322944501Smrg    if (flags & DRM_HALT_CUR_QUEUES) lock.flags |= _DRM_HALT_CUR_QUEUES;
219422944501Smrg    if (drmIoctl(fd, DRM_IOCTL_FINISH, &lock))
219522944501Smrg	return -errno;
219622944501Smrg    return 0;
219722944501Smrg}
219822944501Smrg
219922944501Smrg/**
220022944501Smrg * Get IRQ from bus ID.
220122944501Smrg *
220222944501Smrg * \param fd file descriptor.
220322944501Smrg * \param busnum bus number.
220422944501Smrg * \param devnum device number.
220522944501Smrg * \param funcnum function number.
220622944501Smrg *
220722944501Smrg * \return IRQ number on success, or a negative value on failure.
220822944501Smrg *
220922944501Smrg * \internal
221022944501Smrg * This function is a wrapper around the DRM_IOCTL_IRQ_BUSID ioctl, passing the
221122944501Smrg * arguments in a drm_irq_busid structure.
221222944501Smrg */
221322944501Smrgint drmGetInterruptFromBusID(int fd, int busnum, int devnum, int funcnum)
221422944501Smrg{
221522944501Smrg    drm_irq_busid_t p;
221622944501Smrg
2217424e9256Smrg    memclear(p);
221822944501Smrg    p.busnum  = busnum;
221922944501Smrg    p.devnum  = devnum;
222022944501Smrg    p.funcnum = funcnum;
222122944501Smrg    if (drmIoctl(fd, DRM_IOCTL_IRQ_BUSID, &p))
222222944501Smrg	return -errno;
222322944501Smrg    return p.irq;
222422944501Smrg}
222522944501Smrg
222622944501Smrgint drmAddContextTag(int fd, drm_context_t context, void *tag)
222722944501Smrg{
222822944501Smrg    drmHashEntry  *entry = drmGetEntry(fd);
222922944501Smrg
223022944501Smrg    if (drmHashInsert(entry->tagTable, context, tag)) {
223122944501Smrg	drmHashDelete(entry->tagTable, context);
223222944501Smrg	drmHashInsert(entry->tagTable, context, tag);
223322944501Smrg    }
223422944501Smrg    return 0;
223522944501Smrg}
223622944501Smrg
223722944501Smrgint drmDelContextTag(int fd, drm_context_t context)
223822944501Smrg{
223922944501Smrg    drmHashEntry  *entry = drmGetEntry(fd);
224022944501Smrg
224122944501Smrg    return drmHashDelete(entry->tagTable, context);
224222944501Smrg}
224322944501Smrg
224422944501Smrgvoid *drmGetContextTag(int fd, drm_context_t context)
224522944501Smrg{
224622944501Smrg    drmHashEntry  *entry = drmGetEntry(fd);
224722944501Smrg    void          *value;
224822944501Smrg
224922944501Smrg    if (drmHashLookup(entry->tagTable, context, &value))
225022944501Smrg	return NULL;
225122944501Smrg
225222944501Smrg    return value;
225322944501Smrg}
225422944501Smrg
225522944501Smrgint drmAddContextPrivateMapping(int fd, drm_context_t ctx_id,
225622944501Smrg                                drm_handle_t handle)
225722944501Smrg{
225822944501Smrg    drm_ctx_priv_map_t map;
225922944501Smrg
2260424e9256Smrg    memclear(map);
226122944501Smrg    map.ctx_id = ctx_id;
226220131375Smrg    map.handle = (void *)(uintptr_t)handle;
226322944501Smrg
226422944501Smrg    if (drmIoctl(fd, DRM_IOCTL_SET_SAREA_CTX, &map))
226522944501Smrg	return -errno;
226622944501Smrg    return 0;
226722944501Smrg}
226822944501Smrg
226922944501Smrgint drmGetContextPrivateMapping(int fd, drm_context_t ctx_id,
227022944501Smrg                                drm_handle_t *handle)
227122944501Smrg{
227222944501Smrg    drm_ctx_priv_map_t map;
227322944501Smrg
2274424e9256Smrg    memclear(map);
227522944501Smrg    map.ctx_id = ctx_id;
227622944501Smrg
227722944501Smrg    if (drmIoctl(fd, DRM_IOCTL_GET_SAREA_CTX, &map))
227822944501Smrg	return -errno;
227922944501Smrg    if (handle)
228020131375Smrg	*handle = (drm_handle_t)(uintptr_t)map.handle;
228122944501Smrg
228222944501Smrg    return 0;
228322944501Smrg}
228422944501Smrg
228522944501Smrgint drmGetMap(int fd, int idx, drm_handle_t *offset, drmSize *size,
228622944501Smrg	      drmMapType *type, drmMapFlags *flags, drm_handle_t *handle,
228722944501Smrg	      int *mtrr)
228822944501Smrg{
228922944501Smrg    drm_map_t map;
229022944501Smrg
2291424e9256Smrg    memclear(map);
229222944501Smrg    map.offset = idx;
229322944501Smrg    if (drmIoctl(fd, DRM_IOCTL_GET_MAP, &map))
229422944501Smrg	return -errno;
229522944501Smrg    *offset = map.offset;
229622944501Smrg    *size   = map.size;
229722944501Smrg    *type   = map.type;
229822944501Smrg    *flags  = map.flags;
229922944501Smrg    *handle = (unsigned long)map.handle;
230022944501Smrg    *mtrr   = map.mtrr;
230122944501Smrg    return 0;
230222944501Smrg}
230322944501Smrg
230422944501Smrgint drmGetClient(int fd, int idx, int *auth, int *pid, int *uid,
230522944501Smrg		 unsigned long *magic, unsigned long *iocs)
230622944501Smrg{
230722944501Smrg    drm_client_t client;
230822944501Smrg
2309424e9256Smrg    memclear(client);
231022944501Smrg    client.idx = idx;
231122944501Smrg    if (drmIoctl(fd, DRM_IOCTL_GET_CLIENT, &client))
231222944501Smrg	return -errno;
231322944501Smrg    *auth      = client.auth;
231422944501Smrg    *pid       = client.pid;
231522944501Smrg    *uid       = client.uid;
231622944501Smrg    *magic     = client.magic;
231722944501Smrg    *iocs      = client.iocs;
231822944501Smrg    return 0;
231922944501Smrg}
232022944501Smrg
232122944501Smrgint drmGetStats(int fd, drmStatsT *stats)
232222944501Smrg{
232322944501Smrg    drm_stats_t s;
2324424e9256Smrg    unsigned    i;
232522944501Smrg
2326424e9256Smrg    memclear(s);
232722944501Smrg    if (drmIoctl(fd, DRM_IOCTL_GET_STATS, &s))
232822944501Smrg	return -errno;
232922944501Smrg
233022944501Smrg    stats->count = 0;
233122944501Smrg    memset(stats, 0, sizeof(*stats));
233222944501Smrg    if (s.count > sizeof(stats->data)/sizeof(stats->data[0]))
233322944501Smrg	return -1;
233422944501Smrg
233522944501Smrg#define SET_VALUE                              \
233622944501Smrg    stats->data[i].long_format = "%-20.20s";   \
233722944501Smrg    stats->data[i].rate_format = "%8.8s";      \
233822944501Smrg    stats->data[i].isvalue     = 1;            \
233922944501Smrg    stats->data[i].verbose     = 0
234022944501Smrg
234122944501Smrg#define SET_COUNT                              \
234222944501Smrg    stats->data[i].long_format = "%-20.20s";   \
234322944501Smrg    stats->data[i].rate_format = "%5.5s";      \
234422944501Smrg    stats->data[i].isvalue     = 0;            \
234522944501Smrg    stats->data[i].mult_names  = "kgm";        \
234622944501Smrg    stats->data[i].mult        = 1000;         \
234722944501Smrg    stats->data[i].verbose     = 0
234822944501Smrg
234922944501Smrg#define SET_BYTE                               \
235022944501Smrg    stats->data[i].long_format = "%-20.20s";   \
235122944501Smrg    stats->data[i].rate_format = "%5.5s";      \
235222944501Smrg    stats->data[i].isvalue     = 0;            \
235322944501Smrg    stats->data[i].mult_names  = "KGM";        \
235422944501Smrg    stats->data[i].mult        = 1024;         \
235522944501Smrg    stats->data[i].verbose     = 0
235622944501Smrg
235722944501Smrg
235822944501Smrg    stats->count = s.count;
235922944501Smrg    for (i = 0; i < s.count; i++) {
236022944501Smrg	stats->data[i].value = s.data[i].value;
236122944501Smrg	switch (s.data[i].type) {
236222944501Smrg	case _DRM_STAT_LOCK:
236322944501Smrg	    stats->data[i].long_name = "Lock";
236422944501Smrg	    stats->data[i].rate_name = "Lock";
236522944501Smrg	    SET_VALUE;
236622944501Smrg	    break;
236722944501Smrg	case _DRM_STAT_OPENS:
236822944501Smrg	    stats->data[i].long_name = "Opens";
236922944501Smrg	    stats->data[i].rate_name = "O";
237022944501Smrg	    SET_COUNT;
237122944501Smrg	    stats->data[i].verbose   = 1;
237222944501Smrg	    break;
237322944501Smrg	case _DRM_STAT_CLOSES:
237422944501Smrg	    stats->data[i].long_name = "Closes";
237522944501Smrg	    stats->data[i].rate_name = "Lock";
237622944501Smrg	    SET_COUNT;
237722944501Smrg	    stats->data[i].verbose   = 1;
237822944501Smrg	    break;
237922944501Smrg	case _DRM_STAT_IOCTLS:
238022944501Smrg	    stats->data[i].long_name = "Ioctls";
238122944501Smrg	    stats->data[i].rate_name = "Ioc/s";
238222944501Smrg	    SET_COUNT;
238322944501Smrg	    break;
238422944501Smrg	case _DRM_STAT_LOCKS:
238522944501Smrg	    stats->data[i].long_name = "Locks";
238622944501Smrg	    stats->data[i].rate_name = "Lck/s";
238722944501Smrg	    SET_COUNT;
238822944501Smrg	    break;
238922944501Smrg	case _DRM_STAT_UNLOCKS:
239022944501Smrg	    stats->data[i].long_name = "Unlocks";
239122944501Smrg	    stats->data[i].rate_name = "Unl/s";
239222944501Smrg	    SET_COUNT;
239322944501Smrg	    break;
239422944501Smrg	case _DRM_STAT_IRQ:
239522944501Smrg	    stats->data[i].long_name = "IRQs";
239622944501Smrg	    stats->data[i].rate_name = "IRQ/s";
239722944501Smrg	    SET_COUNT;
239822944501Smrg	    break;
239922944501Smrg	case _DRM_STAT_PRIMARY:
240022944501Smrg	    stats->data[i].long_name = "Primary Bytes";
240122944501Smrg	    stats->data[i].rate_name = "PB/s";
240222944501Smrg	    SET_BYTE;
240322944501Smrg	    break;
240422944501Smrg	case _DRM_STAT_SECONDARY:
240522944501Smrg	    stats->data[i].long_name = "Secondary Bytes";
240622944501Smrg	    stats->data[i].rate_name = "SB/s";
240722944501Smrg	    SET_BYTE;
240822944501Smrg	    break;
240922944501Smrg	case _DRM_STAT_DMA:
241022944501Smrg	    stats->data[i].long_name = "DMA";
241122944501Smrg	    stats->data[i].rate_name = "DMA/s";
241222944501Smrg	    SET_COUNT;
241322944501Smrg	    break;
241422944501Smrg	case _DRM_STAT_SPECIAL:
241522944501Smrg	    stats->data[i].long_name = "Special DMA";
241622944501Smrg	    stats->data[i].rate_name = "dma/s";
241722944501Smrg	    SET_COUNT;
241822944501Smrg	    break;
241922944501Smrg	case _DRM_STAT_MISSED:
242022944501Smrg	    stats->data[i].long_name = "Miss";
242122944501Smrg	    stats->data[i].rate_name = "Ms/s";
242222944501Smrg	    SET_COUNT;
242322944501Smrg	    break;
242422944501Smrg	case _DRM_STAT_VALUE:
242522944501Smrg	    stats->data[i].long_name = "Value";
242622944501Smrg	    stats->data[i].rate_name = "Value";
242722944501Smrg	    SET_VALUE;
242822944501Smrg	    break;
242922944501Smrg	case _DRM_STAT_BYTE:
243022944501Smrg	    stats->data[i].long_name = "Bytes";
243122944501Smrg	    stats->data[i].rate_name = "B/s";
243222944501Smrg	    SET_BYTE;
243322944501Smrg	    break;
243422944501Smrg	case _DRM_STAT_COUNT:
243522944501Smrg	default:
243622944501Smrg	    stats->data[i].long_name = "Count";
243722944501Smrg	    stats->data[i].rate_name = "Cnt/s";
243822944501Smrg	    SET_COUNT;
243922944501Smrg	    break;
244022944501Smrg	}
244122944501Smrg    }
244222944501Smrg    return 0;
244322944501Smrg}
244422944501Smrg
244522944501Smrg/**
244622944501Smrg * Issue a set-version ioctl.
244722944501Smrg *
244822944501Smrg * \param fd file descriptor.
244922944501Smrg * \param drmCommandIndex command index
245022944501Smrg * \param data source pointer of the data to be read and written.
245122944501Smrg * \param size size of the data to be read and written.
245222944501Smrg *
245322944501Smrg * \return zero on success, or a negative value on failure.
245422944501Smrg *
245522944501Smrg * \internal
245622944501Smrg * It issues a read-write ioctl given by
245722944501Smrg * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
245822944501Smrg */
245922944501Smrgint drmSetInterfaceVersion(int fd, drmSetVersion *version)
246022944501Smrg{
246122944501Smrg    int retcode = 0;
246222944501Smrg    drm_set_version_t sv;
246322944501Smrg
2464424e9256Smrg    memclear(sv);
246522944501Smrg    sv.drm_di_major = version->drm_di_major;
246622944501Smrg    sv.drm_di_minor = version->drm_di_minor;
246722944501Smrg    sv.drm_dd_major = version->drm_dd_major;
246822944501Smrg    sv.drm_dd_minor = version->drm_dd_minor;
246922944501Smrg
247022944501Smrg    if (drmIoctl(fd, DRM_IOCTL_SET_VERSION, &sv)) {
247122944501Smrg	retcode = -errno;
247222944501Smrg    }
247322944501Smrg
247422944501Smrg    version->drm_di_major = sv.drm_di_major;
247522944501Smrg    version->drm_di_minor = sv.drm_di_minor;
247622944501Smrg    version->drm_dd_major = sv.drm_dd_major;
247722944501Smrg    version->drm_dd_minor = sv.drm_dd_minor;
247822944501Smrg
247922944501Smrg    return retcode;
248022944501Smrg}
248122944501Smrg
248222944501Smrg/**
248322944501Smrg * Send a device-specific command.
248422944501Smrg *
248522944501Smrg * \param fd file descriptor.
248622944501Smrg * \param drmCommandIndex command index
248722944501Smrg *
248822944501Smrg * \return zero on success, or a negative value on failure.
248922944501Smrg *
249022944501Smrg * \internal
249122944501Smrg * It issues a ioctl given by
249222944501Smrg * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
249322944501Smrg */
249422944501Smrgint drmCommandNone(int fd, unsigned long drmCommandIndex)
249522944501Smrg{
249622944501Smrg    unsigned long request;
249722944501Smrg
249822944501Smrg    request = DRM_IO( DRM_COMMAND_BASE + drmCommandIndex);
249922944501Smrg
2500424e9256Smrg    if (drmIoctl(fd, request, NULL)) {
250122944501Smrg	return -errno;
250222944501Smrg    }
250322944501Smrg    return 0;
250422944501Smrg}
250522944501Smrg
250622944501Smrg
250722944501Smrg/**
250822944501Smrg * Send a device-specific read command.
250922944501Smrg *
251022944501Smrg * \param fd file descriptor.
251122944501Smrg * \param drmCommandIndex command index
251222944501Smrg * \param data destination pointer of the data to be read.
251322944501Smrg * \param size size of the data to be read.
251422944501Smrg *
251522944501Smrg * \return zero on success, or a negative value on failure.
251622944501Smrg *
251722944501Smrg * \internal
251822944501Smrg * It issues a read ioctl given by
251922944501Smrg * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
252022944501Smrg */
252122944501Smrgint drmCommandRead(int fd, unsigned long drmCommandIndex, void *data,
252222944501Smrg                   unsigned long size)
252322944501Smrg{
252422944501Smrg    unsigned long request;
252522944501Smrg
252622944501Smrg    request = DRM_IOC( DRM_IOC_READ, DRM_IOCTL_BASE,
252722944501Smrg	DRM_COMMAND_BASE + drmCommandIndex, size);
252822944501Smrg
252922944501Smrg    if (drmIoctl(fd, request, data)) {
253022944501Smrg	return -errno;
253122944501Smrg    }
253222944501Smrg    return 0;
253322944501Smrg}
253422944501Smrg
253522944501Smrg
253622944501Smrg/**
253722944501Smrg * Send a device-specific write command.
253822944501Smrg *
253922944501Smrg * \param fd file descriptor.
254022944501Smrg * \param drmCommandIndex command index
254122944501Smrg * \param data source pointer of the data to be written.
254222944501Smrg * \param size size of the data to be written.
254322944501Smrg *
254422944501Smrg * \return zero on success, or a negative value on failure.
254522944501Smrg *
254622944501Smrg * \internal
254722944501Smrg * It issues a write ioctl given by
254822944501Smrg * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
254922944501Smrg */
255022944501Smrgint drmCommandWrite(int fd, unsigned long drmCommandIndex, void *data,
255122944501Smrg                    unsigned long size)
255222944501Smrg{
255322944501Smrg    unsigned long request;
255422944501Smrg
255522944501Smrg    request = DRM_IOC( DRM_IOC_WRITE, DRM_IOCTL_BASE,
255622944501Smrg	DRM_COMMAND_BASE + drmCommandIndex, size);
255722944501Smrg
255822944501Smrg    if (drmIoctl(fd, request, data)) {
255922944501Smrg	return -errno;
256022944501Smrg    }
256122944501Smrg    return 0;
256222944501Smrg}
256322944501Smrg
256422944501Smrg
256522944501Smrg/**
256622944501Smrg * Send a device-specific read-write command.
256722944501Smrg *
256822944501Smrg * \param fd file descriptor.
256922944501Smrg * \param drmCommandIndex command index
257022944501Smrg * \param data source pointer of the data to be read and written.
257122944501Smrg * \param size size of the data to be read and written.
257222944501Smrg *
257322944501Smrg * \return zero on success, or a negative value on failure.
257422944501Smrg *
257522944501Smrg * \internal
257622944501Smrg * It issues a read-write ioctl given by
257722944501Smrg * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
257822944501Smrg */
257922944501Smrgint drmCommandWriteRead(int fd, unsigned long drmCommandIndex, void *data,
258022944501Smrg                        unsigned long size)
258122944501Smrg{
258222944501Smrg    unsigned long request;
258322944501Smrg
258422944501Smrg    request = DRM_IOC( DRM_IOC_READ|DRM_IOC_WRITE, DRM_IOCTL_BASE,
258522944501Smrg	DRM_COMMAND_BASE + drmCommandIndex, size);
258622944501Smrg
258722944501Smrg    if (drmIoctl(fd, request, data))
258822944501Smrg	return -errno;
258922944501Smrg    return 0;
259022944501Smrg}
259122944501Smrg
259222944501Smrg#define DRM_MAX_FDS 16
259322944501Smrgstatic struct {
259422944501Smrg    char *BusID;
259522944501Smrg    int fd;
259622944501Smrg    int refcount;
2597424e9256Smrg    int type;
259822944501Smrg} connection[DRM_MAX_FDS];
259922944501Smrg
260022944501Smrgstatic int nr_fds = 0;
260122944501Smrg
260222944501Smrgint drmOpenOnce(void *unused,
260322944501Smrg		const char *BusID,
260422944501Smrg		int *newlyopened)
2605424e9256Smrg{
2606424e9256Smrg    return drmOpenOnceWithType(BusID, newlyopened, DRM_NODE_PRIMARY);
2607424e9256Smrg}
2608424e9256Smrg
2609424e9256Smrgint drmOpenOnceWithType(const char *BusID, int *newlyopened, int type)
261022944501Smrg{
261122944501Smrg    int i;
261222944501Smrg    int fd;
261322944501Smrg
261422944501Smrg    for (i = 0; i < nr_fds; i++)
2615424e9256Smrg	if ((strcmp(BusID, connection[i].BusID) == 0) &&
2616424e9256Smrg	    (connection[i].type == type)) {
261722944501Smrg	    connection[i].refcount++;
261822944501Smrg	    *newlyopened = 0;
261922944501Smrg	    return connection[i].fd;
262022944501Smrg	}
262122944501Smrg
2622424e9256Smrg    fd = drmOpenWithType(NULL, BusID, type);
262322944501Smrg    if (fd <= 0 || nr_fds == DRM_MAX_FDS)
262422944501Smrg	return fd;
262522944501Smrg
262622944501Smrg    connection[nr_fds].BusID = strdup(BusID);
262722944501Smrg    connection[nr_fds].fd = fd;
262822944501Smrg    connection[nr_fds].refcount = 1;
2629424e9256Smrg    connection[nr_fds].type = type;
263022944501Smrg    *newlyopened = 1;
263122944501Smrg
263222944501Smrg    if (0)
263322944501Smrg	fprintf(stderr, "saved connection %d for %s %d\n",
263422944501Smrg		nr_fds, connection[nr_fds].BusID,
263522944501Smrg		strcmp(BusID, connection[nr_fds].BusID));
263622944501Smrg
263722944501Smrg    nr_fds++;
263822944501Smrg
263922944501Smrg    return fd;
264022944501Smrg}
264122944501Smrg
264222944501Smrgvoid drmCloseOnce(int fd)
264322944501Smrg{
264422944501Smrg    int i;
264522944501Smrg
264622944501Smrg    for (i = 0; i < nr_fds; i++) {
264722944501Smrg	if (fd == connection[i].fd) {
264822944501Smrg	    if (--connection[i].refcount == 0) {
264922944501Smrg		drmClose(connection[i].fd);
265022944501Smrg		free(connection[i].BusID);
265122944501Smrg
265222944501Smrg		if (i < --nr_fds)
265322944501Smrg		    connection[i] = connection[nr_fds];
265422944501Smrg
265522944501Smrg		return;
265622944501Smrg	    }
265722944501Smrg	}
265822944501Smrg    }
265922944501Smrg}
266022944501Smrg
266122944501Smrgint drmSetMaster(int fd)
266222944501Smrg{
2663424e9256Smrg	return drmIoctl(fd, DRM_IOCTL_SET_MASTER, NULL);
266422944501Smrg}
266522944501Smrg
266622944501Smrgint drmDropMaster(int fd)
266722944501Smrg{
2668424e9256Smrg	return drmIoctl(fd, DRM_IOCTL_DROP_MASTER, NULL);
266922944501Smrg}
267022944501Smrg
267122944501Smrgchar *drmGetDeviceNameFromFd(int fd)
267222944501Smrg{
267322944501Smrg	char name[128];
267422944501Smrg	struct stat sbuf;
267522944501Smrg	dev_t d;
267622944501Smrg	int i;
267722944501Smrg
267822944501Smrg	/* The whole drmOpen thing is a fiasco and we need to find a way
267922944501Smrg	 * back to just using open(2).  For now, however, lets just make
268022944501Smrg	 * things worse with even more ad hoc directory walking code to
268122944501Smrg	 * discover the device file name. */
268222944501Smrg
268322944501Smrg	fstat(fd, &sbuf);
268422944501Smrg	d = sbuf.st_rdev;
268522944501Smrg
268622944501Smrg	for (i = 0; i < DRM_MAX_MINOR; i++) {
268722944501Smrg		snprintf(name, sizeof name, DRM_DEV_NAME, DRM_DIR_NAME, i);
268822944501Smrg		if (stat(name, &sbuf) == 0 && sbuf.st_rdev == d)
268922944501Smrg			break;
269022944501Smrg	}
269122944501Smrg	if (i == DRM_MAX_MINOR)
269222944501Smrg		return NULL;
269322944501Smrg
26949ce4edccSmrg	return strdup(name);
269522944501Smrg}
269620131375Smrg
2697424e9256Smrgint drmGetNodeTypeFromFd(int fd)
2698424e9256Smrg{
2699424e9256Smrg	struct stat sbuf;
2700424e9256Smrg	int maj, min, type;
2701424e9256Smrg
2702424e9256Smrg	if (fstat(fd, &sbuf))
2703424e9256Smrg		return -1;
2704424e9256Smrg
2705424e9256Smrg	maj = major(sbuf.st_rdev);
2706424e9256Smrg	min = minor(sbuf.st_rdev);
2707424e9256Smrg
2708424e9256Smrg	if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode)) {
2709424e9256Smrg		errno = EINVAL;
2710424e9256Smrg		return -1;
2711424e9256Smrg	}
2712424e9256Smrg
2713424e9256Smrg	type = drmGetMinorType(min);
2714424e9256Smrg	if (type == -1)
2715424e9256Smrg		errno = ENODEV;
2716424e9256Smrg	return type;
2717424e9256Smrg}
2718424e9256Smrg
271920131375Smrgint drmPrimeHandleToFD(int fd, uint32_t handle, uint32_t flags, int *prime_fd)
272020131375Smrg{
272120131375Smrg	struct drm_prime_handle args;
272220131375Smrg	int ret;
272320131375Smrg
2724424e9256Smrg	memclear(args);
2725424e9256Smrg	args.fd = -1;
272620131375Smrg	args.handle = handle;
272720131375Smrg	args.flags = flags;
272820131375Smrg	ret = drmIoctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &args);
272920131375Smrg	if (ret)
273020131375Smrg		return ret;
273120131375Smrg
273220131375Smrg	*prime_fd = args.fd;
273320131375Smrg	return 0;
273420131375Smrg}
273520131375Smrg
273620131375Smrgint drmPrimeFDToHandle(int fd, int prime_fd, uint32_t *handle)
273720131375Smrg{
273820131375Smrg	struct drm_prime_handle args;
273920131375Smrg	int ret;
274020131375Smrg
2741424e9256Smrg	memclear(args);
274220131375Smrg	args.fd = prime_fd;
274320131375Smrg	ret = drmIoctl(fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &args);
274420131375Smrg	if (ret)
274520131375Smrg		return ret;
274620131375Smrg
274720131375Smrg	*handle = args.handle;
274820131375Smrg	return 0;
274920131375Smrg}
2750424e9256Smrg
2751424e9256Smrgstatic char *drmGetMinorNameForFD(int fd, int type)
2752424e9256Smrg{
2753424e9256Smrg#ifdef __linux__
2754424e9256Smrg	DIR *sysdir;
2755424e9256Smrg	struct dirent *pent, *ent;
2756424e9256Smrg	struct stat sbuf;
2757424e9256Smrg	const char *name = drmGetMinorName(type);
2758424e9256Smrg	int len;
2759424e9256Smrg	char dev_name[64], buf[64];
2760424e9256Smrg	long name_max;
2761424e9256Smrg	int maj, min;
2762424e9256Smrg
2763424e9256Smrg	if (!name)
2764424e9256Smrg		return NULL;
2765424e9256Smrg
2766424e9256Smrg	len = strlen(name);
2767424e9256Smrg
2768424e9256Smrg	if (fstat(fd, &sbuf))
2769424e9256Smrg		return NULL;
2770424e9256Smrg
2771424e9256Smrg	maj = major(sbuf.st_rdev);
2772424e9256Smrg	min = minor(sbuf.st_rdev);
2773424e9256Smrg
2774424e9256Smrg	if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode))
2775424e9256Smrg		return NULL;
2776424e9256Smrg
2777424e9256Smrg	snprintf(buf, sizeof(buf), "/sys/dev/char/%d:%d/device/drm", maj, min);
2778424e9256Smrg
2779424e9256Smrg	sysdir = opendir(buf);
2780424e9256Smrg	if (!sysdir)
2781424e9256Smrg		return NULL;
2782424e9256Smrg
2783424e9256Smrg	name_max = fpathconf(dirfd(sysdir), _PC_NAME_MAX);
2784424e9256Smrg	if (name_max == -1)
2785424e9256Smrg		goto out_close_dir;
2786424e9256Smrg
2787424e9256Smrg	pent = malloc(offsetof(struct dirent, d_name) + name_max + 1);
2788424e9256Smrg	if (pent == NULL)
2789424e9256Smrg		 goto out_close_dir;
2790424e9256Smrg
2791424e9256Smrg	while (readdir_r(sysdir, pent, &ent) == 0 && ent != NULL) {
2792424e9256Smrg		if (strncmp(ent->d_name, name, len) == 0) {
2793424e9256Smrg			free(pent);
2794424e9256Smrg			closedir(sysdir);
2795424e9256Smrg
2796424e9256Smrg			snprintf(dev_name, sizeof(dev_name), DRM_DIR_NAME "/%s",
2797424e9256Smrg				 ent->d_name);
2798424e9256Smrg			return strdup(dev_name);
2799424e9256Smrg		}
2800424e9256Smrg	}
2801424e9256Smrg
2802424e9256Smrg	free(pent);
2803424e9256Smrg
2804424e9256Smrgout_close_dir:
2805424e9256Smrg	closedir(sysdir);
2806424e9256Smrg#endif
2807424e9256Smrg	return NULL;
2808424e9256Smrg}
2809424e9256Smrg
2810424e9256Smrgchar *drmGetPrimaryDeviceNameFromFd(int fd)
2811424e9256Smrg{
2812424e9256Smrg	return drmGetMinorNameForFD(fd, DRM_NODE_PRIMARY);
2813424e9256Smrg}
2814424e9256Smrg
2815424e9256Smrgchar *drmGetRenderDeviceNameFromFd(int fd)
2816424e9256Smrg{
2817424e9256Smrg	return drmGetMinorNameForFD(fd, DRM_NODE_RENDER);
2818424e9256Smrg}
2819