xf86drm.c revision 20131375
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>
4322944501Smrg#include <fcntl.h>
4422944501Smrg#include <errno.h>
4522944501Smrg#include <signal.h>
4622944501Smrg#include <time.h>
4722944501Smrg#include <sys/types.h>
4822944501Smrg#include <sys/stat.h>
4922944501Smrg#define stat_t struct stat
5022944501Smrg#include <sys/ioctl.h>
5122944501Smrg#include <sys/mman.h>
5222944501Smrg#include <sys/time.h>
5322944501Smrg#include <stdarg.h>
5422944501Smrg
5522944501Smrg/* Not all systems have MAP_FAILED defined */
5622944501Smrg#ifndef MAP_FAILED
5722944501Smrg#define MAP_FAILED ((void *)-1)
5822944501Smrg#endif
5922944501Smrg
6022944501Smrg#include "xf86drm.h"
6122944501Smrg
6222944501Smrg#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
6322944501Smrg#define DRM_MAJOR 145
6422944501Smrg#endif
6522944501Smrg
6622944501Smrg#ifdef __NetBSD__
672e6867f6Smrg#undef DRM_MAJOR
682e6867f6Smrg#define DRM_MAJOR 180
6922944501Smrg#endif
7022944501Smrg
7122944501Smrg# ifdef __OpenBSD__
7222944501Smrg#  define DRM_MAJOR 81
7322944501Smrg# endif
7422944501Smrg
7522944501Smrg#ifndef DRM_MAJOR
7622944501Smrg#define DRM_MAJOR 226		/* Linux */
7722944501Smrg#endif
7822944501Smrg
7922944501Smrg/*
8022944501Smrg * This definition needs to be changed on some systems if dev_t is a structure.
8122944501Smrg * If there is a header file we can get it from, there would be best.
8222944501Smrg */
8322944501Smrg#ifndef makedev
8422944501Smrg#define makedev(x,y)    ((dev_t)(((x) << 8) | (y)))
8522944501Smrg#endif
8622944501Smrg
8722944501Smrg#define DRM_MSG_VERBOSITY 3
8822944501Smrg
8922944501Smrg#define DRM_NODE_CONTROL 0
9022944501Smrg#define DRM_NODE_RENDER 1
9122944501Smrg
9222944501Smrgstatic drmServerInfoPtr drm_server_info;
9322944501Smrg
9422944501Smrgvoid drmSetServerInfo(drmServerInfoPtr info)
9522944501Smrg{
9622944501Smrg    drm_server_info = info;
9722944501Smrg}
9822944501Smrg
9922944501Smrg/**
10022944501Smrg * Output a message to stderr.
10122944501Smrg *
10222944501Smrg * \param format printf() like format string.
10322944501Smrg *
10422944501Smrg * \internal
10522944501Smrg * This function is a wrapper around vfprintf().
10622944501Smrg */
10722944501Smrg
10822944501Smrgstatic int drmDebugPrint(const char *format, va_list ap)
10922944501Smrg{
11022944501Smrg    return vfprintf(stderr, format, ap);
11122944501Smrg}
11222944501Smrg
11322944501Smrgstatic int (*drm_debug_print)(const char *format, va_list ap) = drmDebugPrint;
11422944501Smrg
11522944501Smrgvoid
11622944501SmrgdrmMsg(const char *format, ...)
11722944501Smrg{
11822944501Smrg    va_list	ap;
11922944501Smrg    const char *env;
12022944501Smrg    if (((env = getenv("LIBGL_DEBUG")) && strstr(env, "verbose")) || drm_server_info)
12122944501Smrg    {
12222944501Smrg	va_start(ap, format);
12322944501Smrg	if (drm_server_info) {
12422944501Smrg	  drm_server_info->debug_print(format,ap);
12522944501Smrg	} else {
12622944501Smrg	  drm_debug_print(format, ap);
12722944501Smrg	}
12822944501Smrg	va_end(ap);
12922944501Smrg    }
13022944501Smrg}
13122944501Smrg
13222944501Smrgvoid
13322944501SmrgdrmSetDebugMsgFunction(int (*debug_msg_ptr)(const char *format, va_list ap))
13422944501Smrg{
13522944501Smrg    drm_debug_print = debug_msg_ptr;
13622944501Smrg}
13722944501Smrg
13822944501Smrgstatic void *drmHashTable = NULL; /* Context switch callbacks */
13922944501Smrg
14022944501Smrgvoid *drmGetHashTable(void)
14122944501Smrg{
14222944501Smrg    return drmHashTable;
14322944501Smrg}
14422944501Smrg
14522944501Smrgvoid *drmMalloc(int size)
14622944501Smrg{
14722944501Smrg    void *pt;
14822944501Smrg    if ((pt = malloc(size)))
14922944501Smrg	memset(pt, 0, size);
15022944501Smrg    return pt;
15122944501Smrg}
15222944501Smrg
15322944501Smrgvoid drmFree(void *pt)
15422944501Smrg{
15522944501Smrg    if (pt)
15622944501Smrg	free(pt);
15722944501Smrg}
15822944501Smrg
15922944501Smrg/**
16022944501Smrg * Call ioctl, restarting if it is interupted
16122944501Smrg */
16222944501Smrgint
16322944501SmrgdrmIoctl(int fd, unsigned long request, void *arg)
16422944501Smrg{
16522944501Smrg    int	ret;
16622944501Smrg
16722944501Smrg    do {
16822944501Smrg	ret = ioctl(fd, request, arg);
16922944501Smrg    } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
17022944501Smrg    return ret;
17122944501Smrg}
17222944501Smrg
17322944501Smrgstatic unsigned long drmGetKeyFromFd(int fd)
17422944501Smrg{
17522944501Smrg    stat_t     st;
17622944501Smrg
17722944501Smrg    st.st_rdev = 0;
17822944501Smrg    fstat(fd, &st);
17922944501Smrg    return st.st_rdev;
18022944501Smrg}
18122944501Smrg
18222944501SmrgdrmHashEntry *drmGetEntry(int fd)
18322944501Smrg{
18422944501Smrg    unsigned long key = drmGetKeyFromFd(fd);
18522944501Smrg    void          *value;
18622944501Smrg    drmHashEntry  *entry;
18722944501Smrg
18822944501Smrg    if (!drmHashTable)
18922944501Smrg	drmHashTable = drmHashCreate();
19022944501Smrg
19122944501Smrg    if (drmHashLookup(drmHashTable, key, &value)) {
19222944501Smrg	entry           = drmMalloc(sizeof(*entry));
19322944501Smrg	entry->fd       = fd;
19422944501Smrg	entry->f        = NULL;
19522944501Smrg	entry->tagTable = drmHashCreate();
19622944501Smrg	drmHashInsert(drmHashTable, key, entry);
19722944501Smrg    } else {
19822944501Smrg	entry = value;
19922944501Smrg    }
20022944501Smrg    return entry;
20122944501Smrg}
20222944501Smrg
20322944501Smrg/**
20422944501Smrg * Compare two busid strings
20522944501Smrg *
20622944501Smrg * \param first
20722944501Smrg * \param second
20822944501Smrg *
20922944501Smrg * \return 1 if matched.
21022944501Smrg *
21122944501Smrg * \internal
21222944501Smrg * This function compares two bus ID strings.  It understands the older
21322944501Smrg * PCI:b:d:f format and the newer pci:oooo:bb:dd.f format.  In the format, o is
21422944501Smrg * domain, b is bus, d is device, f is function.
21522944501Smrg */
2166d98c517Smrgstatic int drmMatchBusID(const char *id1, const char *id2, int pci_domain_ok)
21722944501Smrg{
21822944501Smrg    /* First, check if the IDs are exactly the same */
21922944501Smrg    if (strcasecmp(id1, id2) == 0)
22022944501Smrg	return 1;
22122944501Smrg
22222944501Smrg    /* Try to match old/new-style PCI bus IDs. */
22322944501Smrg    if (strncasecmp(id1, "pci", 3) == 0) {
22422944501Smrg	unsigned int o1, b1, d1, f1;
22522944501Smrg	unsigned int o2, b2, d2, f2;
22622944501Smrg	int ret;
22722944501Smrg
22822944501Smrg	ret = sscanf(id1, "pci:%04x:%02x:%02x.%u", &o1, &b1, &d1, &f1);
22922944501Smrg	if (ret != 4) {
23022944501Smrg	    o1 = 0;
23122944501Smrg	    ret = sscanf(id1, "PCI:%u:%u:%u", &b1, &d1, &f1);
23222944501Smrg	    if (ret != 3)
23322944501Smrg		return 0;
23422944501Smrg	}
23522944501Smrg
23622944501Smrg	ret = sscanf(id2, "pci:%04x:%02x:%02x.%u", &o2, &b2, &d2, &f2);
23722944501Smrg	if (ret != 4) {
23822944501Smrg	    o2 = 0;
23922944501Smrg	    ret = sscanf(id2, "PCI:%u:%u:%u", &b2, &d2, &f2);
24022944501Smrg	    if (ret != 3)
24122944501Smrg		return 0;
24222944501Smrg	}
24322944501Smrg
2446d98c517Smrg	/* If domains aren't properly supported by the kernel interface,
2456d98c517Smrg	 * just ignore them, which sucks less than picking a totally random
2466d98c517Smrg	 * card with "open by name"
2476d98c517Smrg	 */
2486d98c517Smrg	if (!pci_domain_ok)
2496d98c517Smrg		o1 = o2 = 0;
2506d98c517Smrg
25122944501Smrg	if ((o1 != o2) || (b1 != b2) || (d1 != d2) || (f1 != f2))
25222944501Smrg	    return 0;
25322944501Smrg	else
25422944501Smrg	    return 1;
25522944501Smrg    }
25622944501Smrg    return 0;
25722944501Smrg}
25822944501Smrg
25922944501Smrg/**
26022944501Smrg * Handles error checking for chown call.
26122944501Smrg *
26222944501Smrg * \param path to file.
26322944501Smrg * \param id of the new owner.
26422944501Smrg * \param id of the new group.
26522944501Smrg *
26622944501Smrg * \return zero if success or -1 if failure.
26722944501Smrg *
26822944501Smrg * \internal
26922944501Smrg * Checks for failure. If failure was caused by signal call chown again.
27022944501Smrg * If any other failure happened then it will output error mesage using
27122944501Smrg * drmMsg() call.
27222944501Smrg */
27322944501Smrgstatic int chown_check_return(const char *path, uid_t owner, gid_t group)
27422944501Smrg{
27522944501Smrg	int rv;
27622944501Smrg
27722944501Smrg	do {
27822944501Smrg		rv = chown(path, owner, group);
27922944501Smrg	} while (rv != 0 && errno == EINTR);
28022944501Smrg
28122944501Smrg	if (rv == 0)
28222944501Smrg		return 0;
28322944501Smrg
28422944501Smrg	drmMsg("Failed to change owner or group for file %s! %d: %s\n",
28522944501Smrg			path, errno, strerror(errno));
28622944501Smrg	return -1;
28722944501Smrg}
28822944501Smrg
28922944501Smrg/**
29022944501Smrg * Open the DRM device, creating it if necessary.
29122944501Smrg *
29222944501Smrg * \param dev major and minor numbers of the device.
29322944501Smrg * \param minor minor number of the device.
29422944501Smrg *
29522944501Smrg * \return a file descriptor on success, or a negative value on error.
29622944501Smrg *
29722944501Smrg * \internal
29822944501Smrg * Assembles the device name from \p minor and opens it, creating the device
29922944501Smrg * special file node with the major and minor numbers specified by \p dev and
30022944501Smrg * parent directory if necessary and was called by root.
30122944501Smrg */
30222944501Smrgstatic int drmOpenDevice(long dev, int minor, int type)
30322944501Smrg{
30422944501Smrg    stat_t          st;
30522944501Smrg    char            buf[64];
30622944501Smrg    int             fd;
30722944501Smrg    mode_t          devmode = DRM_DEV_MODE, serv_mode;
30822944501Smrg    int             isroot  = !geteuid();
30922944501Smrg    uid_t           user    = DRM_DEV_UID;
31022944501Smrg    gid_t           group   = DRM_DEV_GID, serv_group;
31122944501Smrg
31222944501Smrg    sprintf(buf, type ? DRM_DEV_NAME : DRM_CONTROL_DEV_NAME, DRM_DIR_NAME, minor);
31322944501Smrg    drmMsg("drmOpenDevice: node name is %s\n", buf);
31422944501Smrg
31522944501Smrg    if (drm_server_info) {
31622944501Smrg	drm_server_info->get_perms(&serv_group, &serv_mode);
31722944501Smrg	devmode  = serv_mode ? serv_mode : DRM_DEV_MODE;
31822944501Smrg	devmode &= ~(S_IXUSR|S_IXGRP|S_IXOTH);
31922944501Smrg	group = (serv_group >= 0) ? serv_group : DRM_DEV_GID;
32022944501Smrg    }
32122944501Smrg
32222944501Smrg#if !defined(UDEV)
32322944501Smrg    if (stat(DRM_DIR_NAME, &st)) {
32422944501Smrg	if (!isroot)
32522944501Smrg	    return DRM_ERR_NOT_ROOT;
32622944501Smrg	mkdir(DRM_DIR_NAME, DRM_DEV_DIRMODE);
32722944501Smrg	chown_check_return(DRM_DIR_NAME, 0, 0); /* root:root */
32822944501Smrg	chmod(DRM_DIR_NAME, DRM_DEV_DIRMODE);
32922944501Smrg    }
33022944501Smrg
33122944501Smrg    /* Check if the device node exists and create it if necessary. */
33222944501Smrg    if (stat(buf, &st)) {
33322944501Smrg	if (!isroot)
33422944501Smrg	    return DRM_ERR_NOT_ROOT;
33522944501Smrg	remove(buf);
33622944501Smrg	mknod(buf, S_IFCHR | devmode, dev);
33722944501Smrg    }
33822944501Smrg
33922944501Smrg    if (drm_server_info) {
34022944501Smrg	chown_check_return(buf, user, group);
34122944501Smrg	chmod(buf, devmode);
34222944501Smrg    }
34322944501Smrg#else
34422944501Smrg    /* if we modprobed then wait for udev */
34522944501Smrg    {
34622944501Smrg	int udev_count = 0;
34722944501Smrgwait_for_udev:
34822944501Smrg        if (stat(DRM_DIR_NAME, &st)) {
34922944501Smrg		usleep(20);
35022944501Smrg		udev_count++;
35122944501Smrg
35222944501Smrg		if (udev_count == 50)
35322944501Smrg			return -1;
35422944501Smrg		goto wait_for_udev;
35522944501Smrg	}
35622944501Smrg
35722944501Smrg    	if (stat(buf, &st)) {
35822944501Smrg		usleep(20);
35922944501Smrg		udev_count++;
36022944501Smrg
36122944501Smrg		if (udev_count == 50)
36222944501Smrg			return -1;
36322944501Smrg		goto wait_for_udev;
36422944501Smrg    	}
36522944501Smrg    }
36622944501Smrg#endif
36722944501Smrg
36822944501Smrg    fd = open(buf, O_RDWR, 0);
36922944501Smrg    drmMsg("drmOpenDevice: open result is %d, (%s)\n",
37022944501Smrg		fd, fd < 0 ? strerror(errno) : "OK");
37122944501Smrg    if (fd >= 0)
37222944501Smrg	return fd;
37322944501Smrg
3749ce4edccSmrg#if !defined(UDEV)
37522944501Smrg    /* Check if the device node is not what we expect it to be, and recreate it
37622944501Smrg     * and try again if so.
37722944501Smrg     */
37822944501Smrg    if (st.st_rdev != dev) {
37922944501Smrg	if (!isroot)
38022944501Smrg	    return DRM_ERR_NOT_ROOT;
38122944501Smrg	remove(buf);
38222944501Smrg	mknod(buf, S_IFCHR | devmode, dev);
38322944501Smrg	if (drm_server_info) {
38422944501Smrg	    chown_check_return(buf, user, group);
38522944501Smrg	    chmod(buf, devmode);
38622944501Smrg	}
38722944501Smrg    }
38822944501Smrg    fd = open(buf, O_RDWR, 0);
38922944501Smrg    drmMsg("drmOpenDevice: open result is %d, (%s)\n",
39022944501Smrg		fd, fd < 0 ? strerror(errno) : "OK");
39122944501Smrg    if (fd >= 0)
39222944501Smrg	return fd;
39322944501Smrg
39422944501Smrg    drmMsg("drmOpenDevice: Open failed\n");
39522944501Smrg    remove(buf);
3969ce4edccSmrg#endif
39722944501Smrg    return -errno;
39822944501Smrg}
39922944501Smrg
40022944501Smrg
40122944501Smrg/**
40222944501Smrg * Open the DRM device
40322944501Smrg *
40422944501Smrg * \param minor device minor number.
40522944501Smrg * \param create allow to create the device if set.
40622944501Smrg *
40722944501Smrg * \return a file descriptor on success, or a negative value on error.
40822944501Smrg *
40922944501Smrg * \internal
41022944501Smrg * Calls drmOpenDevice() if \p create is set, otherwise assembles the device
41122944501Smrg * name from \p minor and opens it.
41222944501Smrg */
41322944501Smrgstatic int drmOpenMinor(int minor, int create, int type)
41422944501Smrg{
41522944501Smrg    int  fd;
41622944501Smrg    char buf[64];
41722944501Smrg
41822944501Smrg    if (create)
41922944501Smrg	return drmOpenDevice(makedev(DRM_MAJOR, minor), minor, type);
42022944501Smrg
42122944501Smrg    sprintf(buf, type ? DRM_DEV_NAME : DRM_CONTROL_DEV_NAME, DRM_DIR_NAME, minor);
42222944501Smrg    if ((fd = open(buf, O_RDWR, 0)) >= 0)
42322944501Smrg	return fd;
42422944501Smrg    return -errno;
42522944501Smrg}
42622944501Smrg
42722944501Smrg
42822944501Smrg/**
42922944501Smrg * Determine whether the DRM kernel driver has been loaded.
43022944501Smrg *
43122944501Smrg * \return 1 if the DRM driver is loaded, 0 otherwise.
43222944501Smrg *
43322944501Smrg * \internal
43422944501Smrg * Determine the presence of the kernel driver by attempting to open the 0
43522944501Smrg * minor and get version information.  For backward compatibility with older
43622944501Smrg * Linux implementations, /proc/dri is also checked.
43722944501Smrg */
43822944501Smrgint drmAvailable(void)
43922944501Smrg{
44022944501Smrg    drmVersionPtr version;
44122944501Smrg    int           retval = 0;
44222944501Smrg    int           fd;
44322944501Smrg
44422944501Smrg    if ((fd = drmOpenMinor(0, 1, DRM_NODE_RENDER)) < 0) {
44522944501Smrg#ifdef __linux__
44622944501Smrg	/* Try proc for backward Linux compatibility */
44722944501Smrg	if (!access("/proc/dri/0", R_OK))
44822944501Smrg	    return 1;
44922944501Smrg#endif
45022944501Smrg	return 0;
45122944501Smrg    }
45222944501Smrg
45322944501Smrg    if ((version = drmGetVersion(fd))) {
45422944501Smrg	retval = 1;
45522944501Smrg	drmFreeVersion(version);
45622944501Smrg    }
45722944501Smrg    close(fd);
45822944501Smrg
45922944501Smrg    return retval;
46022944501Smrg}
46122944501Smrg
46222944501Smrg
46322944501Smrg/**
46422944501Smrg * Open the device by bus ID.
46522944501Smrg *
46622944501Smrg * \param busid bus ID.
46722944501Smrg *
46822944501Smrg * \return a file descriptor on success, or a negative value on error.
46922944501Smrg *
47022944501Smrg * \internal
47122944501Smrg * This function attempts to open every possible minor (up to DRM_MAX_MINOR),
47222944501Smrg * comparing the device bus ID with the one supplied.
47322944501Smrg *
47422944501Smrg * \sa drmOpenMinor() and drmGetBusid().
47522944501Smrg */
47622944501Smrgstatic int drmOpenByBusid(const char *busid)
47722944501Smrg{
4786d98c517Smrg    int        i, pci_domain_ok = 1;
47922944501Smrg    int        fd;
48022944501Smrg    const char *buf;
48122944501Smrg    drmSetVersion sv;
48222944501Smrg
48322944501Smrg    drmMsg("drmOpenByBusid: Searching for BusID %s\n", busid);
48422944501Smrg    for (i = 0; i < DRM_MAX_MINOR; i++) {
48522944501Smrg	fd = drmOpenMinor(i, 1, DRM_NODE_RENDER);
48622944501Smrg	drmMsg("drmOpenByBusid: drmOpenMinor returns %d\n", fd);
48722944501Smrg	if (fd >= 0) {
4886d98c517Smrg	    /* We need to try for 1.4 first for proper PCI domain support
4896d98c517Smrg	     * and if that fails, we know the kernel is busted
4906d98c517Smrg	     */
49122944501Smrg	    sv.drm_di_major = 1;
4926d98c517Smrg	    sv.drm_di_minor = 4;
49322944501Smrg	    sv.drm_dd_major = -1;	/* Don't care */
49422944501Smrg	    sv.drm_dd_minor = -1;	/* Don't care */
4956d98c517Smrg	    if (drmSetInterfaceVersion(fd, &sv)) {
4966d98c517Smrg#ifndef __alpha__
4976d98c517Smrg		pci_domain_ok = 0;
4986d98c517Smrg#endif
4996d98c517Smrg		sv.drm_di_major = 1;
5006d98c517Smrg		sv.drm_di_minor = 1;
5016d98c517Smrg		sv.drm_dd_major = -1;       /* Don't care */
5026d98c517Smrg		sv.drm_dd_minor = -1;       /* Don't care */
5036d98c517Smrg		drmMsg("drmOpenByBusid: Interface 1.4 failed, trying 1.1\n",fd);
5046d98c517Smrg		drmSetInterfaceVersion(fd, &sv);
5052e6867f6Smrg	    }
50622944501Smrg	    buf = drmGetBusid(fd);
50722944501Smrg	    drmMsg("drmOpenByBusid: drmGetBusid reports %s\n", buf);
5086d98c517Smrg	    if (buf && drmMatchBusID(buf, busid, pci_domain_ok)) {
50922944501Smrg		drmFreeBusid(buf);
51022944501Smrg		return fd;
51122944501Smrg	    }
51222944501Smrg	    if (buf)
51322944501Smrg		drmFreeBusid(buf);
51422944501Smrg	    close(fd);
51522944501Smrg	}
51622944501Smrg    }
51722944501Smrg    return -1;
51822944501Smrg}
51922944501Smrg
52022944501Smrg
52122944501Smrg/**
52222944501Smrg * Open the device by name.
52322944501Smrg *
52422944501Smrg * \param name driver name.
52522944501Smrg *
52622944501Smrg * \return a file descriptor on success, or a negative value on error.
52722944501Smrg *
52822944501Smrg * \internal
52922944501Smrg * This function opens the first minor number that matches the driver name and
53022944501Smrg * isn't already in use.  If it's in use it then it will already have a bus ID
53122944501Smrg * assigned.
53222944501Smrg *
53322944501Smrg * \sa drmOpenMinor(), drmGetVersion() and drmGetBusid().
53422944501Smrg */
53522944501Smrgstatic int drmOpenByName(const char *name)
53622944501Smrg{
53722944501Smrg    int           i;
53822944501Smrg    int           fd;
53922944501Smrg    drmVersionPtr version;
54022944501Smrg    char *        id;
54122944501Smrg
54222944501Smrg    if (!drmAvailable()) {
54322944501Smrg	if (!drm_server_info) {
54422944501Smrg	    return -1;
54522944501Smrg	}
54622944501Smrg	else {
54722944501Smrg	    /* try to load the kernel module now */
54822944501Smrg	    if (!drm_server_info->load_module(name)) {
54922944501Smrg		drmMsg("[drm] failed to load kernel module \"%s\"\n", name);
55022944501Smrg		return -1;
55122944501Smrg	    }
55222944501Smrg	}
55322944501Smrg    }
55422944501Smrg
55522944501Smrg    /*
55622944501Smrg     * Open the first minor number that matches the driver name and isn't
55722944501Smrg     * already in use.  If it's in use it will have a busid assigned already.
55822944501Smrg     */
55922944501Smrg    for (i = 0; i < DRM_MAX_MINOR; i++) {
56022944501Smrg	if ((fd = drmOpenMinor(i, 1, DRM_NODE_RENDER)) >= 0) {
56122944501Smrg	    if ((version = drmGetVersion(fd))) {
56222944501Smrg		if (!strcmp(version->name, name)) {
56322944501Smrg		    drmFreeVersion(version);
56422944501Smrg		    id = drmGetBusid(fd);
56522944501Smrg		    drmMsg("drmGetBusid returned '%s'\n", id ? id : "NULL");
56622944501Smrg		    if (!id || !*id) {
56722944501Smrg			if (id)
56822944501Smrg			    drmFreeBusid(id);
56922944501Smrg			return fd;
57022944501Smrg		    } else {
57122944501Smrg			drmFreeBusid(id);
57222944501Smrg		    }
57322944501Smrg		} else {
57422944501Smrg		    drmFreeVersion(version);
57522944501Smrg		}
57622944501Smrg	    }
57722944501Smrg	    close(fd);
57822944501Smrg	}
57922944501Smrg    }
58022944501Smrg
58122944501Smrg#ifdef __linux__
58222944501Smrg    /* Backward-compatibility /proc support */
58322944501Smrg    for (i = 0; i < 8; i++) {
58422944501Smrg	char proc_name[64], buf[512];
58522944501Smrg	char *driver, *pt, *devstring;
58622944501Smrg	int  retcode;
58722944501Smrg
58822944501Smrg	sprintf(proc_name, "/proc/dri/%d/name", i);
58922944501Smrg	if ((fd = open(proc_name, 0, 0)) >= 0) {
59022944501Smrg	    retcode = read(fd, buf, sizeof(buf)-1);
59122944501Smrg	    close(fd);
59222944501Smrg	    if (retcode) {
59322944501Smrg		buf[retcode-1] = '\0';
59422944501Smrg		for (driver = pt = buf; *pt && *pt != ' '; ++pt)
59522944501Smrg		    ;
59622944501Smrg		if (*pt) { /* Device is next */
59722944501Smrg		    *pt = '\0';
59822944501Smrg		    if (!strcmp(driver, name)) { /* Match */
59922944501Smrg			for (devstring = ++pt; *pt && *pt != ' '; ++pt)
60022944501Smrg			    ;
60122944501Smrg			if (*pt) { /* Found busid */
60222944501Smrg			    return drmOpenByBusid(++pt);
60322944501Smrg			} else { /* No busid */
60422944501Smrg			    return drmOpenDevice(strtol(devstring, NULL, 0),i, DRM_NODE_RENDER);
60522944501Smrg			}
60622944501Smrg		    }
60722944501Smrg		}
60822944501Smrg	    }
60922944501Smrg	}
61022944501Smrg    }
61122944501Smrg#endif
61222944501Smrg
61322944501Smrg    return -1;
61422944501Smrg}
61522944501Smrg
61622944501Smrg
61722944501Smrg/**
61822944501Smrg * Open the DRM device.
61922944501Smrg *
62022944501Smrg * Looks up the specified name and bus ID, and opens the device found.  The
62122944501Smrg * entry in /dev/dri is created if necessary and if called by root.
62222944501Smrg *
62322944501Smrg * \param name driver name. Not referenced if bus ID is supplied.
62422944501Smrg * \param busid bus ID. Zero if not known.
62522944501Smrg *
62622944501Smrg * \return a file descriptor on success, or a negative value on error.
62722944501Smrg *
62822944501Smrg * \internal
62922944501Smrg * It calls drmOpenByBusid() if \p busid is specified or drmOpenByName()
63022944501Smrg * otherwise.
63122944501Smrg */
63222944501Smrgint drmOpen(const char *name, const char *busid)
63322944501Smrg{
63422944501Smrg    if (!drmAvailable() && name != NULL && drm_server_info) {
63522944501Smrg	/* try to load the kernel */
63622944501Smrg	if (!drm_server_info->load_module(name)) {
63722944501Smrg	    drmMsg("[drm] failed to load kernel module \"%s\"\n", name);
63822944501Smrg	    return -1;
63922944501Smrg	}
64022944501Smrg    }
64122944501Smrg
64222944501Smrg    if (busid) {
64322944501Smrg	int fd = drmOpenByBusid(busid);
64422944501Smrg	if (fd >= 0)
64522944501Smrg	    return fd;
64622944501Smrg    }
64722944501Smrg
64822944501Smrg    if (name)
64922944501Smrg	return drmOpenByName(name);
65022944501Smrg
65122944501Smrg    return -1;
65222944501Smrg}
65322944501Smrg
65422944501Smrgint drmOpenControl(int minor)
65522944501Smrg{
65622944501Smrg    return drmOpenMinor(minor, 0, DRM_NODE_CONTROL);
65722944501Smrg}
65822944501Smrg
65922944501Smrg/**
66022944501Smrg * Free the version information returned by drmGetVersion().
66122944501Smrg *
66222944501Smrg * \param v pointer to the version information.
66322944501Smrg *
66422944501Smrg * \internal
66522944501Smrg * It frees the memory pointed by \p %v as well as all the non-null strings
66622944501Smrg * pointers in it.
66722944501Smrg */
66822944501Smrgvoid drmFreeVersion(drmVersionPtr v)
66922944501Smrg{
67022944501Smrg    if (!v)
67122944501Smrg	return;
67222944501Smrg    drmFree(v->name);
67322944501Smrg    drmFree(v->date);
67422944501Smrg    drmFree(v->desc);
67522944501Smrg    drmFree(v);
67622944501Smrg}
67722944501Smrg
67822944501Smrg
67922944501Smrg/**
68022944501Smrg * Free the non-public version information returned by the kernel.
68122944501Smrg *
68222944501Smrg * \param v pointer to the version information.
68322944501Smrg *
68422944501Smrg * \internal
68522944501Smrg * Used by drmGetVersion() to free the memory pointed by \p %v as well as all
68622944501Smrg * the non-null strings pointers in it.
68722944501Smrg */
68822944501Smrgstatic void drmFreeKernelVersion(drm_version_t *v)
68922944501Smrg{
69022944501Smrg    if (!v)
69122944501Smrg	return;
69222944501Smrg    drmFree(v->name);
69322944501Smrg    drmFree(v->date);
69422944501Smrg    drmFree(v->desc);
69522944501Smrg    drmFree(v);
69622944501Smrg}
69722944501Smrg
69822944501Smrg
69922944501Smrg/**
70022944501Smrg * Copy version information.
70122944501Smrg *
70222944501Smrg * \param d destination pointer.
70322944501Smrg * \param s source pointer.
70422944501Smrg *
70522944501Smrg * \internal
70622944501Smrg * Used by drmGetVersion() to translate the information returned by the ioctl
70722944501Smrg * interface in a private structure into the public structure counterpart.
70822944501Smrg */
70922944501Smrgstatic void drmCopyVersion(drmVersionPtr d, const drm_version_t *s)
71022944501Smrg{
71122944501Smrg    d->version_major      = s->version_major;
71222944501Smrg    d->version_minor      = s->version_minor;
71322944501Smrg    d->version_patchlevel = s->version_patchlevel;
71422944501Smrg    d->name_len           = s->name_len;
7159ce4edccSmrg    d->name               = strdup(s->name);
71622944501Smrg    d->date_len           = s->date_len;
7179ce4edccSmrg    d->date               = strdup(s->date);
71822944501Smrg    d->desc_len           = s->desc_len;
7199ce4edccSmrg    d->desc               = strdup(s->desc);
72022944501Smrg}
72122944501Smrg
72222944501Smrg
72322944501Smrg/**
72422944501Smrg * Query the driver version information.
72522944501Smrg *
72622944501Smrg * \param fd file descriptor.
72722944501Smrg *
72822944501Smrg * \return pointer to a drmVersion structure which should be freed with
72922944501Smrg * drmFreeVersion().
73022944501Smrg *
73122944501Smrg * \note Similar information is available via /proc/dri.
73222944501Smrg *
73322944501Smrg * \internal
73422944501Smrg * It gets the version information via successive DRM_IOCTL_VERSION ioctls,
73522944501Smrg * first with zeros to get the string lengths, and then the actually strings.
73622944501Smrg * It also null-terminates them since they might not be already.
73722944501Smrg */
73822944501SmrgdrmVersionPtr drmGetVersion(int fd)
73922944501Smrg{
74022944501Smrg    drmVersionPtr retval;
74122944501Smrg    drm_version_t *version = drmMalloc(sizeof(*version));
74222944501Smrg
74322944501Smrg    version->name_len    = 0;
74422944501Smrg    version->name        = NULL;
74522944501Smrg    version->date_len    = 0;
74622944501Smrg    version->date        = NULL;
74722944501Smrg    version->desc_len    = 0;
74822944501Smrg    version->desc        = NULL;
74922944501Smrg
75022944501Smrg    if (drmIoctl(fd, DRM_IOCTL_VERSION, version)) {
75122944501Smrg	drmFreeKernelVersion(version);
75222944501Smrg	return NULL;
75322944501Smrg    }
75422944501Smrg
75522944501Smrg    if (version->name_len)
75622944501Smrg	version->name    = drmMalloc(version->name_len + 1);
75722944501Smrg    if (version->date_len)
75822944501Smrg	version->date    = drmMalloc(version->date_len + 1);
75922944501Smrg    if (version->desc_len)
76022944501Smrg	version->desc    = drmMalloc(version->desc_len + 1);
76122944501Smrg
76222944501Smrg    if (drmIoctl(fd, DRM_IOCTL_VERSION, version)) {
76322944501Smrg	drmMsg("DRM_IOCTL_VERSION: %s\n", strerror(errno));
76422944501Smrg	drmFreeKernelVersion(version);
76522944501Smrg	return NULL;
76622944501Smrg    }
76722944501Smrg
76822944501Smrg    /* The results might not be null-terminated strings, so terminate them. */
76922944501Smrg    if (version->name_len) version->name[version->name_len] = '\0';
77022944501Smrg    if (version->date_len) version->date[version->date_len] = '\0';
77122944501Smrg    if (version->desc_len) version->desc[version->desc_len] = '\0';
77222944501Smrg
77322944501Smrg    retval = drmMalloc(sizeof(*retval));
77422944501Smrg    drmCopyVersion(retval, version);
77522944501Smrg    drmFreeKernelVersion(version);
77622944501Smrg    return retval;
77722944501Smrg}
77822944501Smrg
77922944501Smrg
78022944501Smrg/**
78122944501Smrg * Get version information for the DRM user space library.
78222944501Smrg *
78322944501Smrg * This version number is driver independent.
78422944501Smrg *
78522944501Smrg * \param fd file descriptor.
78622944501Smrg *
78722944501Smrg * \return version information.
78822944501Smrg *
78922944501Smrg * \internal
79022944501Smrg * This function allocates and fills a drm_version structure with a hard coded
79122944501Smrg * version number.
79222944501Smrg */
79322944501SmrgdrmVersionPtr drmGetLibVersion(int fd)
79422944501Smrg{
79522944501Smrg    drm_version_t *version = drmMalloc(sizeof(*version));
79622944501Smrg
79722944501Smrg    /* Version history:
79822944501Smrg     *   NOTE THIS MUST NOT GO ABOVE VERSION 1.X due to drivers needing it
79922944501Smrg     *   revision 1.0.x = original DRM interface with no drmGetLibVersion
80022944501Smrg     *                    entry point and many drm<Device> extensions
80122944501Smrg     *   revision 1.1.x = added drmCommand entry points for device extensions
80222944501Smrg     *                    added drmGetLibVersion to identify libdrm.a version
80322944501Smrg     *   revision 1.2.x = added drmSetInterfaceVersion
80422944501Smrg     *                    modified drmOpen to handle both busid and name
80522944501Smrg     *   revision 1.3.x = added server + memory manager
80622944501Smrg     */
80722944501Smrg    version->version_major      = 1;
80822944501Smrg    version->version_minor      = 3;
80922944501Smrg    version->version_patchlevel = 0;
81022944501Smrg
81122944501Smrg    return (drmVersionPtr)version;
81222944501Smrg}
81322944501Smrg
81420131375Smrgint drmGetCap(int fd, uint64_t capability, uint64_t *value)
81520131375Smrg{
81620131375Smrg	struct drm_get_cap cap = { capability, 0 };
81720131375Smrg	int ret;
81820131375Smrg
81920131375Smrg	ret = drmIoctl(fd, DRM_IOCTL_GET_CAP, &cap);
82020131375Smrg	if (ret)
82120131375Smrg		return ret;
82220131375Smrg
82320131375Smrg	*value = cap.value;
82420131375Smrg	return 0;
82520131375Smrg}
82620131375Smrg
82720131375Smrgint drmSetClientCap(int fd, uint64_t capability, uint64_t value)
82820131375Smrg{
82920131375Smrg	struct drm_set_client_cap cap  = { capability, value };
83020131375Smrg
83120131375Smrg	return drmIoctl(fd, DRM_IOCTL_SET_CLIENT_CAP, &cap);
83220131375Smrg}
83322944501Smrg
83422944501Smrg/**
83522944501Smrg * Free the bus ID information.
83622944501Smrg *
83722944501Smrg * \param busid bus ID information string as given by drmGetBusid().
83822944501Smrg *
83922944501Smrg * \internal
84022944501Smrg * This function is just frees the memory pointed by \p busid.
84122944501Smrg */
84222944501Smrgvoid drmFreeBusid(const char *busid)
84322944501Smrg{
84422944501Smrg    drmFree((void *)busid);
84522944501Smrg}
84622944501Smrg
84722944501Smrg
84822944501Smrg/**
84922944501Smrg * Get the bus ID of the device.
85022944501Smrg *
85122944501Smrg * \param fd file descriptor.
85222944501Smrg *
85322944501Smrg * \return bus ID string.
85422944501Smrg *
85522944501Smrg * \internal
85622944501Smrg * This function gets the bus ID via successive DRM_IOCTL_GET_UNIQUE ioctls to
85722944501Smrg * get the string length and data, passing the arguments in a drm_unique
85822944501Smrg * structure.
85922944501Smrg */
86022944501Smrgchar *drmGetBusid(int fd)
86122944501Smrg{
86222944501Smrg    drm_unique_t u;
86322944501Smrg
86422944501Smrg    u.unique_len = 0;
86522944501Smrg    u.unique     = NULL;
86622944501Smrg
86722944501Smrg    if (drmIoctl(fd, DRM_IOCTL_GET_UNIQUE, &u))
86822944501Smrg	return NULL;
86922944501Smrg    u.unique = drmMalloc(u.unique_len + 1);
87022944501Smrg    if (drmIoctl(fd, DRM_IOCTL_GET_UNIQUE, &u))
87122944501Smrg	return NULL;
87222944501Smrg    u.unique[u.unique_len] = '\0';
87322944501Smrg
87422944501Smrg    return u.unique;
87522944501Smrg}
87622944501Smrg
87722944501Smrg
87822944501Smrg/**
87922944501Smrg * Set the bus ID of the device.
88022944501Smrg *
88122944501Smrg * \param fd file descriptor.
88222944501Smrg * \param busid bus ID string.
88322944501Smrg *
88422944501Smrg * \return zero on success, negative on failure.
88522944501Smrg *
88622944501Smrg * \internal
88722944501Smrg * This function is a wrapper around the DRM_IOCTL_SET_UNIQUE ioctl, passing
88822944501Smrg * the arguments in a drm_unique structure.
88922944501Smrg */
89022944501Smrgint drmSetBusid(int fd, const char *busid)
89122944501Smrg{
89222944501Smrg    drm_unique_t u;
89322944501Smrg
89422944501Smrg    u.unique     = (char *)busid;
89522944501Smrg    u.unique_len = strlen(busid);
89622944501Smrg
89722944501Smrg    if (drmIoctl(fd, DRM_IOCTL_SET_UNIQUE, &u)) {
89822944501Smrg	return -errno;
89922944501Smrg    }
90022944501Smrg    return 0;
90122944501Smrg}
90222944501Smrg
90322944501Smrgint drmGetMagic(int fd, drm_magic_t * magic)
90422944501Smrg{
90522944501Smrg    drm_auth_t auth;
90622944501Smrg
90722944501Smrg    *magic = 0;
90822944501Smrg    if (drmIoctl(fd, DRM_IOCTL_GET_MAGIC, &auth))
90922944501Smrg	return -errno;
91022944501Smrg    *magic = auth.magic;
91122944501Smrg    return 0;
91222944501Smrg}
91322944501Smrg
91422944501Smrgint drmAuthMagic(int fd, drm_magic_t magic)
91522944501Smrg{
91622944501Smrg    drm_auth_t auth;
91722944501Smrg
91822944501Smrg    auth.magic = magic;
91922944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AUTH_MAGIC, &auth))
92022944501Smrg	return -errno;
92122944501Smrg    return 0;
92222944501Smrg}
92322944501Smrg
92422944501Smrg/**
92522944501Smrg * Specifies a range of memory that is available for mapping by a
92622944501Smrg * non-root process.
92722944501Smrg *
92822944501Smrg * \param fd file descriptor.
92922944501Smrg * \param offset usually the physical address. The actual meaning depends of
93022944501Smrg * the \p type parameter. See below.
93122944501Smrg * \param size of the memory in bytes.
93222944501Smrg * \param type type of the memory to be mapped.
93322944501Smrg * \param flags combination of several flags to modify the function actions.
93422944501Smrg * \param handle will be set to a value that may be used as the offset
93522944501Smrg * parameter for mmap().
93622944501Smrg *
93722944501Smrg * \return zero on success or a negative value on error.
93822944501Smrg *
93922944501Smrg * \par Mapping the frame buffer
94022944501Smrg * For the frame buffer
94122944501Smrg * - \p offset will be the physical address of the start of the frame buffer,
94222944501Smrg * - \p size will be the size of the frame buffer in bytes, and
94322944501Smrg * - \p type will be DRM_FRAME_BUFFER.
94422944501Smrg *
94522944501Smrg * \par
94622944501Smrg * The area mapped will be uncached. If MTRR support is available in the
94722944501Smrg * kernel, the frame buffer area will be set to write combining.
94822944501Smrg *
94922944501Smrg * \par Mapping the MMIO register area
95022944501Smrg * For the MMIO register area,
95122944501Smrg * - \p offset will be the physical address of the start of the register area,
95222944501Smrg * - \p size will be the size of the register area bytes, and
95322944501Smrg * - \p type will be DRM_REGISTERS.
95422944501Smrg * \par
95522944501Smrg * The area mapped will be uncached.
95622944501Smrg *
95722944501Smrg * \par Mapping the SAREA
95822944501Smrg * For the SAREA,
95922944501Smrg * - \p offset will be ignored and should be set to zero,
96022944501Smrg * - \p size will be the desired size of the SAREA in bytes,
96122944501Smrg * - \p type will be DRM_SHM.
96222944501Smrg *
96322944501Smrg * \par
96422944501Smrg * A shared memory area of the requested size will be created and locked in
96522944501Smrg * kernel memory. This area may be mapped into client-space by using the handle
96622944501Smrg * returned.
96722944501Smrg *
96822944501Smrg * \note May only be called by root.
96922944501Smrg *
97022944501Smrg * \internal
97122944501Smrg * This function is a wrapper around the DRM_IOCTL_ADD_MAP ioctl, passing
97222944501Smrg * the arguments in a drm_map structure.
97322944501Smrg */
97422944501Smrgint drmAddMap(int fd, drm_handle_t offset, drmSize size, drmMapType type,
97522944501Smrg	      drmMapFlags flags, drm_handle_t *handle)
97622944501Smrg{
97722944501Smrg    drm_map_t map;
97822944501Smrg
97922944501Smrg    map.offset  = offset;
98022944501Smrg    map.size    = size;
98122944501Smrg    map.handle  = 0;
98222944501Smrg    map.type    = type;
98322944501Smrg    map.flags   = flags;
98422944501Smrg    if (drmIoctl(fd, DRM_IOCTL_ADD_MAP, &map))
98522944501Smrg	return -errno;
98622944501Smrg    if (handle)
98720131375Smrg	*handle = (drm_handle_t)(uintptr_t)map.handle;
98822944501Smrg    return 0;
98922944501Smrg}
99022944501Smrg
99122944501Smrgint drmRmMap(int fd, drm_handle_t handle)
99222944501Smrg{
99322944501Smrg    drm_map_t map;
99422944501Smrg
99520131375Smrg    map.handle = (void *)(uintptr_t)handle;
99622944501Smrg
99722944501Smrg    if(drmIoctl(fd, DRM_IOCTL_RM_MAP, &map))
99822944501Smrg	return -errno;
99922944501Smrg    return 0;
100022944501Smrg}
100122944501Smrg
100222944501Smrg/**
100322944501Smrg * Make buffers available for DMA transfers.
100422944501Smrg *
100522944501Smrg * \param fd file descriptor.
100622944501Smrg * \param count number of buffers.
100722944501Smrg * \param size size of each buffer.
100822944501Smrg * \param flags buffer allocation flags.
100922944501Smrg * \param agp_offset offset in the AGP aperture
101022944501Smrg *
101122944501Smrg * \return number of buffers allocated, negative on error.
101222944501Smrg *
101322944501Smrg * \internal
101422944501Smrg * This function is a wrapper around DRM_IOCTL_ADD_BUFS ioctl.
101522944501Smrg *
101622944501Smrg * \sa drm_buf_desc.
101722944501Smrg */
101822944501Smrgint drmAddBufs(int fd, int count, int size, drmBufDescFlags flags,
101922944501Smrg	       int agp_offset)
102022944501Smrg{
102122944501Smrg    drm_buf_desc_t request;
102222944501Smrg
102322944501Smrg    request.count     = count;
102422944501Smrg    request.size      = size;
102522944501Smrg    request.low_mark  = 0;
102622944501Smrg    request.high_mark = 0;
102722944501Smrg    request.flags     = flags;
102822944501Smrg    request.agp_start = agp_offset;
102922944501Smrg
103022944501Smrg    if (drmIoctl(fd, DRM_IOCTL_ADD_BUFS, &request))
103122944501Smrg	return -errno;
103222944501Smrg    return request.count;
103322944501Smrg}
103422944501Smrg
103522944501Smrgint drmMarkBufs(int fd, double low, double high)
103622944501Smrg{
103722944501Smrg    drm_buf_info_t info;
103822944501Smrg    int            i;
103922944501Smrg
104022944501Smrg    info.count = 0;
104122944501Smrg    info.list  = NULL;
104222944501Smrg
104322944501Smrg    if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info))
104422944501Smrg	return -EINVAL;
104522944501Smrg
104622944501Smrg    if (!info.count)
104722944501Smrg	return -EINVAL;
104822944501Smrg
104922944501Smrg    if (!(info.list = drmMalloc(info.count * sizeof(*info.list))))
105022944501Smrg	return -ENOMEM;
105122944501Smrg
105222944501Smrg    if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info)) {
105322944501Smrg	int retval = -errno;
105422944501Smrg	drmFree(info.list);
105522944501Smrg	return retval;
105622944501Smrg    }
105722944501Smrg
105822944501Smrg    for (i = 0; i < info.count; i++) {
105922944501Smrg	info.list[i].low_mark  = low  * info.list[i].count;
106022944501Smrg	info.list[i].high_mark = high * info.list[i].count;
106122944501Smrg	if (drmIoctl(fd, DRM_IOCTL_MARK_BUFS, &info.list[i])) {
106222944501Smrg	    int retval = -errno;
106322944501Smrg	    drmFree(info.list);
106422944501Smrg	    return retval;
106522944501Smrg	}
106622944501Smrg    }
106722944501Smrg    drmFree(info.list);
106822944501Smrg
106922944501Smrg    return 0;
107022944501Smrg}
107122944501Smrg
107222944501Smrg/**
107322944501Smrg * Free buffers.
107422944501Smrg *
107522944501Smrg * \param fd file descriptor.
107622944501Smrg * \param count number of buffers to free.
107722944501Smrg * \param list list of buffers to be freed.
107822944501Smrg *
107922944501Smrg * \return zero on success, or a negative value on failure.
108022944501Smrg *
108122944501Smrg * \note This function is primarily used for debugging.
108222944501Smrg *
108322944501Smrg * \internal
108422944501Smrg * This function is a wrapper around the DRM_IOCTL_FREE_BUFS ioctl, passing
108522944501Smrg * the arguments in a drm_buf_free structure.
108622944501Smrg */
108722944501Smrgint drmFreeBufs(int fd, int count, int *list)
108822944501Smrg{
108922944501Smrg    drm_buf_free_t request;
109022944501Smrg
109122944501Smrg    request.count = count;
109222944501Smrg    request.list  = list;
109322944501Smrg    if (drmIoctl(fd, DRM_IOCTL_FREE_BUFS, &request))
109422944501Smrg	return -errno;
109522944501Smrg    return 0;
109622944501Smrg}
109722944501Smrg
109822944501Smrg
109922944501Smrg/**
110022944501Smrg * Close the device.
110122944501Smrg *
110222944501Smrg * \param fd file descriptor.
110322944501Smrg *
110422944501Smrg * \internal
110522944501Smrg * This function closes the file descriptor.
110622944501Smrg */
110722944501Smrgint drmClose(int fd)
110822944501Smrg{
110922944501Smrg    unsigned long key    = drmGetKeyFromFd(fd);
111022944501Smrg    drmHashEntry  *entry = drmGetEntry(fd);
111122944501Smrg
111222944501Smrg    drmHashDestroy(entry->tagTable);
111322944501Smrg    entry->fd       = 0;
111422944501Smrg    entry->f        = NULL;
111522944501Smrg    entry->tagTable = NULL;
111622944501Smrg
111722944501Smrg    drmHashDelete(drmHashTable, key);
111822944501Smrg    drmFree(entry);
111922944501Smrg
112022944501Smrg    return close(fd);
112122944501Smrg}
112222944501Smrg
112322944501Smrg
112422944501Smrg/**
112522944501Smrg * Map a region of memory.
112622944501Smrg *
112722944501Smrg * \param fd file descriptor.
112822944501Smrg * \param handle handle returned by drmAddMap().
112922944501Smrg * \param size size in bytes. Must match the size used by drmAddMap().
113022944501Smrg * \param address will contain the user-space virtual address where the mapping
113122944501Smrg * begins.
113222944501Smrg *
113322944501Smrg * \return zero on success, or a negative value on failure.
113422944501Smrg *
113522944501Smrg * \internal
113622944501Smrg * This function is a wrapper for mmap().
113722944501Smrg */
113822944501Smrgint drmMap(int fd, drm_handle_t handle, drmSize size, drmAddressPtr address)
113922944501Smrg{
114022944501Smrg    static unsigned long pagesize_mask = 0;
114122944501Smrg
114222944501Smrg    if (fd < 0)
114322944501Smrg	return -EINVAL;
114422944501Smrg
114522944501Smrg    if (!pagesize_mask)
114622944501Smrg	pagesize_mask = getpagesize() - 1;
114722944501Smrg
114822944501Smrg    size = (size + pagesize_mask) & ~pagesize_mask;
114922944501Smrg
115022944501Smrg    *address = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, handle);
115122944501Smrg    if (*address == MAP_FAILED)
115222944501Smrg	return -errno;
115322944501Smrg    return 0;
115422944501Smrg}
115522944501Smrg
115622944501Smrg
115722944501Smrg/**
115822944501Smrg * Unmap mappings obtained with drmMap().
115922944501Smrg *
116022944501Smrg * \param address address as given by drmMap().
116122944501Smrg * \param size size in bytes. Must match the size used by drmMap().
116222944501Smrg *
116322944501Smrg * \return zero on success, or a negative value on failure.
116422944501Smrg *
116522944501Smrg * \internal
116622944501Smrg * This function is a wrapper for munmap().
116722944501Smrg */
116822944501Smrgint drmUnmap(drmAddress address, drmSize size)
116922944501Smrg{
117022944501Smrg    return munmap(address, size);
117122944501Smrg}
117222944501Smrg
117322944501SmrgdrmBufInfoPtr drmGetBufInfo(int fd)
117422944501Smrg{
117522944501Smrg    drm_buf_info_t info;
117622944501Smrg    drmBufInfoPtr  retval;
117722944501Smrg    int            i;
117822944501Smrg
117922944501Smrg    info.count = 0;
118022944501Smrg    info.list  = NULL;
118122944501Smrg
118222944501Smrg    if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info))
118322944501Smrg	return NULL;
118422944501Smrg
118522944501Smrg    if (info.count) {
118622944501Smrg	if (!(info.list = drmMalloc(info.count * sizeof(*info.list))))
118722944501Smrg	    return NULL;
118822944501Smrg
118922944501Smrg	if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info)) {
119022944501Smrg	    drmFree(info.list);
119122944501Smrg	    return NULL;
119222944501Smrg	}
119322944501Smrg
119422944501Smrg	retval = drmMalloc(sizeof(*retval));
119522944501Smrg	retval->count = info.count;
119622944501Smrg	retval->list  = drmMalloc(info.count * sizeof(*retval->list));
119722944501Smrg	for (i = 0; i < info.count; i++) {
119822944501Smrg	    retval->list[i].count     = info.list[i].count;
119922944501Smrg	    retval->list[i].size      = info.list[i].size;
120022944501Smrg	    retval->list[i].low_mark  = info.list[i].low_mark;
120122944501Smrg	    retval->list[i].high_mark = info.list[i].high_mark;
120222944501Smrg	}
120322944501Smrg	drmFree(info.list);
120422944501Smrg	return retval;
120522944501Smrg    }
120622944501Smrg    return NULL;
120722944501Smrg}
120822944501Smrg
120922944501Smrg/**
121022944501Smrg * Map all DMA buffers into client-virtual space.
121122944501Smrg *
121222944501Smrg * \param fd file descriptor.
121322944501Smrg *
121422944501Smrg * \return a pointer to a ::drmBufMap structure.
121522944501Smrg *
121622944501Smrg * \note The client may not use these buffers until obtaining buffer indices
121722944501Smrg * with drmDMA().
121822944501Smrg *
121922944501Smrg * \internal
122022944501Smrg * This function calls the DRM_IOCTL_MAP_BUFS ioctl and copies the returned
122122944501Smrg * information about the buffers in a drm_buf_map structure into the
122222944501Smrg * client-visible data structures.
122322944501Smrg */
122422944501SmrgdrmBufMapPtr drmMapBufs(int fd)
122522944501Smrg{
122622944501Smrg    drm_buf_map_t bufs;
122722944501Smrg    drmBufMapPtr  retval;
122822944501Smrg    int           i;
122922944501Smrg
123022944501Smrg    bufs.count = 0;
123122944501Smrg    bufs.list  = NULL;
123222944501Smrg    bufs.virtual = NULL;
123322944501Smrg    if (drmIoctl(fd, DRM_IOCTL_MAP_BUFS, &bufs))
123422944501Smrg	return NULL;
123522944501Smrg
123622944501Smrg    if (!bufs.count)
123722944501Smrg	return NULL;
123822944501Smrg
123922944501Smrg	if (!(bufs.list = drmMalloc(bufs.count * sizeof(*bufs.list))))
124022944501Smrg	    return NULL;
124122944501Smrg
124222944501Smrg	if (drmIoctl(fd, DRM_IOCTL_MAP_BUFS, &bufs)) {
124322944501Smrg	    drmFree(bufs.list);
124422944501Smrg	    return NULL;
124522944501Smrg	}
124622944501Smrg
124722944501Smrg	retval = drmMalloc(sizeof(*retval));
124822944501Smrg	retval->count = bufs.count;
124922944501Smrg	retval->list  = drmMalloc(bufs.count * sizeof(*retval->list));
125022944501Smrg	for (i = 0; i < bufs.count; i++) {
125122944501Smrg	    retval->list[i].idx     = bufs.list[i].idx;
125222944501Smrg	    retval->list[i].total   = bufs.list[i].total;
125322944501Smrg	    retval->list[i].used    = 0;
125422944501Smrg	    retval->list[i].address = bufs.list[i].address;
125522944501Smrg	}
125622944501Smrg
125722944501Smrg	drmFree(bufs.list);
125822944501Smrg
125922944501Smrg	return retval;
126022944501Smrg}
126122944501Smrg
126222944501Smrg
126322944501Smrg/**
126422944501Smrg * Unmap buffers allocated with drmMapBufs().
126522944501Smrg *
126622944501Smrg * \return zero on success, or negative value on failure.
126722944501Smrg *
126822944501Smrg * \internal
126922944501Smrg * Calls munmap() for every buffer stored in \p bufs and frees the
127022944501Smrg * memory allocated by drmMapBufs().
127122944501Smrg */
127222944501Smrgint drmUnmapBufs(drmBufMapPtr bufs)
127322944501Smrg{
127422944501Smrg    int i;
127522944501Smrg
127622944501Smrg    for (i = 0; i < bufs->count; i++) {
127722944501Smrg	munmap(bufs->list[i].address, bufs->list[i].total);
127822944501Smrg    }
127922944501Smrg
128022944501Smrg    drmFree(bufs->list);
128122944501Smrg    drmFree(bufs);
128222944501Smrg
128322944501Smrg    return 0;
128422944501Smrg}
128522944501Smrg
128622944501Smrg
128722944501Smrg#define DRM_DMA_RETRY		16
128822944501Smrg
128922944501Smrg/**
129022944501Smrg * Reserve DMA buffers.
129122944501Smrg *
129222944501Smrg * \param fd file descriptor.
129322944501Smrg * \param request
129422944501Smrg *
129522944501Smrg * \return zero on success, or a negative value on failure.
129622944501Smrg *
129722944501Smrg * \internal
129822944501Smrg * Assemble the arguments into a drm_dma structure and keeps issuing the
129922944501Smrg * DRM_IOCTL_DMA ioctl until success or until maximum number of retries.
130022944501Smrg */
130122944501Smrgint drmDMA(int fd, drmDMAReqPtr request)
130222944501Smrg{
130322944501Smrg    drm_dma_t dma;
130422944501Smrg    int ret, i = 0;
130522944501Smrg
130622944501Smrg    dma.context         = request->context;
130722944501Smrg    dma.send_count      = request->send_count;
130822944501Smrg    dma.send_indices    = request->send_list;
130922944501Smrg    dma.send_sizes      = request->send_sizes;
131022944501Smrg    dma.flags           = request->flags;
131122944501Smrg    dma.request_count   = request->request_count;
131222944501Smrg    dma.request_size    = request->request_size;
131322944501Smrg    dma.request_indices = request->request_list;
131422944501Smrg    dma.request_sizes   = request->request_sizes;
131522944501Smrg    dma.granted_count   = 0;
131622944501Smrg
131722944501Smrg    do {
131822944501Smrg	ret = ioctl( fd, DRM_IOCTL_DMA, &dma );
131922944501Smrg    } while ( ret && errno == EAGAIN && i++ < DRM_DMA_RETRY );
132022944501Smrg
132122944501Smrg    if ( ret == 0 ) {
132222944501Smrg	request->granted_count = dma.granted_count;
132322944501Smrg	return 0;
132422944501Smrg    } else {
132522944501Smrg	return -errno;
132622944501Smrg    }
132722944501Smrg}
132822944501Smrg
132922944501Smrg
133022944501Smrg/**
133122944501Smrg * Obtain heavyweight hardware lock.
133222944501Smrg *
133322944501Smrg * \param fd file descriptor.
133422944501Smrg * \param context context.
133522944501Smrg * \param flags flags that determine the sate of the hardware when the function
133622944501Smrg * returns.
133722944501Smrg *
133822944501Smrg * \return always zero.
133922944501Smrg *
134022944501Smrg * \internal
134122944501Smrg * This function translates the arguments into a drm_lock structure and issue
134222944501Smrg * the DRM_IOCTL_LOCK ioctl until the lock is successfully acquired.
134322944501Smrg */
134422944501Smrgint drmGetLock(int fd, drm_context_t context, drmLockFlags flags)
134522944501Smrg{
134622944501Smrg    drm_lock_t lock;
134722944501Smrg
134822944501Smrg    lock.context = context;
134922944501Smrg    lock.flags   = 0;
135022944501Smrg    if (flags & DRM_LOCK_READY)      lock.flags |= _DRM_LOCK_READY;
135122944501Smrg    if (flags & DRM_LOCK_QUIESCENT)  lock.flags |= _DRM_LOCK_QUIESCENT;
135222944501Smrg    if (flags & DRM_LOCK_FLUSH)      lock.flags |= _DRM_LOCK_FLUSH;
135322944501Smrg    if (flags & DRM_LOCK_FLUSH_ALL)  lock.flags |= _DRM_LOCK_FLUSH_ALL;
135422944501Smrg    if (flags & DRM_HALT_ALL_QUEUES) lock.flags |= _DRM_HALT_ALL_QUEUES;
135522944501Smrg    if (flags & DRM_HALT_CUR_QUEUES) lock.flags |= _DRM_HALT_CUR_QUEUES;
135622944501Smrg
135722944501Smrg    while (drmIoctl(fd, DRM_IOCTL_LOCK, &lock))
135822944501Smrg	;
135922944501Smrg    return 0;
136022944501Smrg}
136122944501Smrg
136222944501Smrg/**
136322944501Smrg * Release the hardware lock.
136422944501Smrg *
136522944501Smrg * \param fd file descriptor.
136622944501Smrg * \param context context.
136722944501Smrg *
136822944501Smrg * \return zero on success, or a negative value on failure.
136922944501Smrg *
137022944501Smrg * \internal
137122944501Smrg * This function is a wrapper around the DRM_IOCTL_UNLOCK ioctl, passing the
137222944501Smrg * argument in a drm_lock structure.
137322944501Smrg */
137422944501Smrgint drmUnlock(int fd, drm_context_t context)
137522944501Smrg{
137622944501Smrg    drm_lock_t lock;
137722944501Smrg
137822944501Smrg    lock.context = context;
137922944501Smrg    lock.flags   = 0;
138022944501Smrg    return drmIoctl(fd, DRM_IOCTL_UNLOCK, &lock);
138122944501Smrg}
138222944501Smrg
138322944501Smrgdrm_context_t *drmGetReservedContextList(int fd, int *count)
138422944501Smrg{
138522944501Smrg    drm_ctx_res_t res;
138622944501Smrg    drm_ctx_t     *list;
138722944501Smrg    drm_context_t * retval;
138822944501Smrg    int           i;
138922944501Smrg
139022944501Smrg    res.count    = 0;
139122944501Smrg    res.contexts = NULL;
139222944501Smrg    if (drmIoctl(fd, DRM_IOCTL_RES_CTX, &res))
139322944501Smrg	return NULL;
139422944501Smrg
139522944501Smrg    if (!res.count)
139622944501Smrg	return NULL;
139722944501Smrg
139822944501Smrg    if (!(list   = drmMalloc(res.count * sizeof(*list))))
139922944501Smrg	return NULL;
140022944501Smrg    if (!(retval = drmMalloc(res.count * sizeof(*retval)))) {
140122944501Smrg	drmFree(list);
140222944501Smrg	return NULL;
140322944501Smrg    }
140422944501Smrg
140522944501Smrg    res.contexts = list;
140622944501Smrg    if (drmIoctl(fd, DRM_IOCTL_RES_CTX, &res))
140722944501Smrg	return NULL;
140822944501Smrg
140922944501Smrg    for (i = 0; i < res.count; i++)
141022944501Smrg	retval[i] = list[i].handle;
141122944501Smrg    drmFree(list);
141222944501Smrg
141322944501Smrg    *count = res.count;
141422944501Smrg    return retval;
141522944501Smrg}
141622944501Smrg
141722944501Smrgvoid drmFreeReservedContextList(drm_context_t *pt)
141822944501Smrg{
141922944501Smrg    drmFree(pt);
142022944501Smrg}
142122944501Smrg
142222944501Smrg/**
142322944501Smrg * Create context.
142422944501Smrg *
142522944501Smrg * Used by the X server during GLXContext initialization. This causes
142622944501Smrg * per-context kernel-level resources to be allocated.
142722944501Smrg *
142822944501Smrg * \param fd file descriptor.
142922944501Smrg * \param handle is set on success. To be used by the client when requesting DMA
143022944501Smrg * dispatch with drmDMA().
143122944501Smrg *
143222944501Smrg * \return zero on success, or a negative value on failure.
143322944501Smrg *
143422944501Smrg * \note May only be called by root.
143522944501Smrg *
143622944501Smrg * \internal
143722944501Smrg * This function is a wrapper around the DRM_IOCTL_ADD_CTX ioctl, passing the
143822944501Smrg * argument in a drm_ctx structure.
143922944501Smrg */
144022944501Smrgint drmCreateContext(int fd, drm_context_t *handle)
144122944501Smrg{
144222944501Smrg    drm_ctx_t ctx;
144322944501Smrg
144422944501Smrg    ctx.flags = 0;	/* Modified with functions below */
144522944501Smrg    if (drmIoctl(fd, DRM_IOCTL_ADD_CTX, &ctx))
144622944501Smrg	return -errno;
144722944501Smrg    *handle = ctx.handle;
144822944501Smrg    return 0;
144922944501Smrg}
145022944501Smrg
145122944501Smrgint drmSwitchToContext(int fd, drm_context_t context)
145222944501Smrg{
145322944501Smrg    drm_ctx_t ctx;
145422944501Smrg
145522944501Smrg    ctx.handle = context;
145622944501Smrg    if (drmIoctl(fd, DRM_IOCTL_SWITCH_CTX, &ctx))
145722944501Smrg	return -errno;
145822944501Smrg    return 0;
145922944501Smrg}
146022944501Smrg
146122944501Smrgint drmSetContextFlags(int fd, drm_context_t context, drm_context_tFlags flags)
146222944501Smrg{
146322944501Smrg    drm_ctx_t ctx;
146422944501Smrg
146522944501Smrg    /*
146622944501Smrg     * Context preserving means that no context switches are done between DMA
146722944501Smrg     * buffers from one context and the next.  This is suitable for use in the
146822944501Smrg     * X server (which promises to maintain hardware context), or in the
146922944501Smrg     * client-side library when buffers are swapped on behalf of two threads.
147022944501Smrg     */
147122944501Smrg    ctx.handle = context;
147222944501Smrg    ctx.flags  = 0;
147322944501Smrg    if (flags & DRM_CONTEXT_PRESERVED)
147422944501Smrg	ctx.flags |= _DRM_CONTEXT_PRESERVED;
147522944501Smrg    if (flags & DRM_CONTEXT_2DONLY)
147622944501Smrg	ctx.flags |= _DRM_CONTEXT_2DONLY;
147722944501Smrg    if (drmIoctl(fd, DRM_IOCTL_MOD_CTX, &ctx))
147822944501Smrg	return -errno;
147922944501Smrg    return 0;
148022944501Smrg}
148122944501Smrg
148222944501Smrgint drmGetContextFlags(int fd, drm_context_t context,
148322944501Smrg                       drm_context_tFlagsPtr flags)
148422944501Smrg{
148522944501Smrg    drm_ctx_t ctx;
148622944501Smrg
148722944501Smrg    ctx.handle = context;
148822944501Smrg    if (drmIoctl(fd, DRM_IOCTL_GET_CTX, &ctx))
148922944501Smrg	return -errno;
149022944501Smrg    *flags = 0;
149122944501Smrg    if (ctx.flags & _DRM_CONTEXT_PRESERVED)
149222944501Smrg	*flags |= DRM_CONTEXT_PRESERVED;
149322944501Smrg    if (ctx.flags & _DRM_CONTEXT_2DONLY)
149422944501Smrg	*flags |= DRM_CONTEXT_2DONLY;
149522944501Smrg    return 0;
149622944501Smrg}
149722944501Smrg
149822944501Smrg/**
149922944501Smrg * Destroy context.
150022944501Smrg *
150122944501Smrg * Free any kernel-level resources allocated with drmCreateContext() associated
150222944501Smrg * with the context.
150322944501Smrg *
150422944501Smrg * \param fd file descriptor.
150522944501Smrg * \param handle handle given by drmCreateContext().
150622944501Smrg *
150722944501Smrg * \return zero on success, or a negative value on failure.
150822944501Smrg *
150922944501Smrg * \note May only be called by root.
151022944501Smrg *
151122944501Smrg * \internal
151222944501Smrg * This function is a wrapper around the DRM_IOCTL_RM_CTX ioctl, passing the
151322944501Smrg * argument in a drm_ctx structure.
151422944501Smrg */
151522944501Smrgint drmDestroyContext(int fd, drm_context_t handle)
151622944501Smrg{
151722944501Smrg    drm_ctx_t ctx;
151822944501Smrg    ctx.handle = handle;
151922944501Smrg    if (drmIoctl(fd, DRM_IOCTL_RM_CTX, &ctx))
152022944501Smrg	return -errno;
152122944501Smrg    return 0;
152222944501Smrg}
152322944501Smrg
152422944501Smrgint drmCreateDrawable(int fd, drm_drawable_t *handle)
152522944501Smrg{
152622944501Smrg    drm_draw_t draw;
152722944501Smrg    if (drmIoctl(fd, DRM_IOCTL_ADD_DRAW, &draw))
152822944501Smrg	return -errno;
152922944501Smrg    *handle = draw.handle;
153022944501Smrg    return 0;
153122944501Smrg}
153222944501Smrg
153322944501Smrgint drmDestroyDrawable(int fd, drm_drawable_t handle)
153422944501Smrg{
153522944501Smrg    drm_draw_t draw;
153622944501Smrg    draw.handle = handle;
153722944501Smrg    if (drmIoctl(fd, DRM_IOCTL_RM_DRAW, &draw))
153822944501Smrg	return -errno;
153922944501Smrg    return 0;
154022944501Smrg}
154122944501Smrg
154222944501Smrgint drmUpdateDrawableInfo(int fd, drm_drawable_t handle,
154322944501Smrg			   drm_drawable_info_type_t type, unsigned int num,
154422944501Smrg			   void *data)
154522944501Smrg{
154622944501Smrg    drm_update_draw_t update;
154722944501Smrg
154822944501Smrg    update.handle = handle;
154922944501Smrg    update.type = type;
155022944501Smrg    update.num = num;
155122944501Smrg    update.data = (unsigned long long)(unsigned long)data;
155222944501Smrg
155322944501Smrg    if (drmIoctl(fd, DRM_IOCTL_UPDATE_DRAW, &update))
155422944501Smrg	return -errno;
155522944501Smrg
155622944501Smrg    return 0;
155722944501Smrg}
155822944501Smrg
155922944501Smrg/**
156022944501Smrg * Acquire the AGP device.
156122944501Smrg *
156222944501Smrg * Must be called before any of the other AGP related calls.
156322944501Smrg *
156422944501Smrg * \param fd file descriptor.
156522944501Smrg *
156622944501Smrg * \return zero on success, or a negative value on failure.
156722944501Smrg *
156822944501Smrg * \internal
156922944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_ACQUIRE ioctl.
157022944501Smrg */
157122944501Smrgint drmAgpAcquire(int fd)
157222944501Smrg{
157322944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AGP_ACQUIRE, NULL))
157422944501Smrg	return -errno;
157522944501Smrg    return 0;
157622944501Smrg}
157722944501Smrg
157822944501Smrg
157922944501Smrg/**
158022944501Smrg * Release the AGP device.
158122944501Smrg *
158222944501Smrg * \param fd file descriptor.
158322944501Smrg *
158422944501Smrg * \return zero on success, or a negative value on failure.
158522944501Smrg *
158622944501Smrg * \internal
158722944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_RELEASE ioctl.
158822944501Smrg */
158922944501Smrgint drmAgpRelease(int fd)
159022944501Smrg{
159122944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AGP_RELEASE, NULL))
159222944501Smrg	return -errno;
159322944501Smrg    return 0;
159422944501Smrg}
159522944501Smrg
159622944501Smrg
159722944501Smrg/**
159822944501Smrg * Set the AGP mode.
159922944501Smrg *
160022944501Smrg * \param fd file descriptor.
160122944501Smrg * \param mode AGP mode.
160222944501Smrg *
160322944501Smrg * \return zero on success, or a negative value on failure.
160422944501Smrg *
160522944501Smrg * \internal
160622944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_ENABLE ioctl, passing the
160722944501Smrg * argument in a drm_agp_mode structure.
160822944501Smrg */
160922944501Smrgint drmAgpEnable(int fd, unsigned long mode)
161022944501Smrg{
161122944501Smrg    drm_agp_mode_t m;
161222944501Smrg
161322944501Smrg    m.mode = mode;
161422944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AGP_ENABLE, &m))
161522944501Smrg	return -errno;
161622944501Smrg    return 0;
161722944501Smrg}
161822944501Smrg
161922944501Smrg
162022944501Smrg/**
162122944501Smrg * Allocate a chunk of AGP memory.
162222944501Smrg *
162322944501Smrg * \param fd file descriptor.
162422944501Smrg * \param size requested memory size in bytes. Will be rounded to page boundary.
162522944501Smrg * \param type type of memory to allocate.
162622944501Smrg * \param address if not zero, will be set to the physical address of the
162722944501Smrg * allocated memory.
162822944501Smrg * \param handle on success will be set to a handle of the allocated memory.
162922944501Smrg *
163022944501Smrg * \return zero on success, or a negative value on failure.
163122944501Smrg *
163222944501Smrg * \internal
163322944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_ALLOC ioctl, passing the
163422944501Smrg * arguments in a drm_agp_buffer structure.
163522944501Smrg */
163622944501Smrgint drmAgpAlloc(int fd, unsigned long size, unsigned long type,
163722944501Smrg		unsigned long *address, drm_handle_t *handle)
163822944501Smrg{
163922944501Smrg    drm_agp_buffer_t b;
164022944501Smrg
164122944501Smrg    *handle = DRM_AGP_NO_HANDLE;
164222944501Smrg    b.size   = size;
164322944501Smrg    b.handle = 0;
164422944501Smrg    b.type   = type;
164522944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AGP_ALLOC, &b))
164622944501Smrg	return -errno;
164722944501Smrg    if (address != 0UL)
164822944501Smrg	*address = b.physical;
164922944501Smrg    *handle = b.handle;
165022944501Smrg    return 0;
165122944501Smrg}
165222944501Smrg
165322944501Smrg
165422944501Smrg/**
165522944501Smrg * Free a chunk of AGP memory.
165622944501Smrg *
165722944501Smrg * \param fd file descriptor.
165822944501Smrg * \param handle handle to the allocated memory, as given by drmAgpAllocate().
165922944501Smrg *
166022944501Smrg * \return zero on success, or a negative value on failure.
166122944501Smrg *
166222944501Smrg * \internal
166322944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_FREE ioctl, passing the
166422944501Smrg * argument in a drm_agp_buffer structure.
166522944501Smrg */
166622944501Smrgint drmAgpFree(int fd, drm_handle_t handle)
166722944501Smrg{
166822944501Smrg    drm_agp_buffer_t b;
166922944501Smrg
167022944501Smrg    b.size   = 0;
167122944501Smrg    b.handle = handle;
167222944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AGP_FREE, &b))
167322944501Smrg	return -errno;
167422944501Smrg    return 0;
167522944501Smrg}
167622944501Smrg
167722944501Smrg
167822944501Smrg/**
167922944501Smrg * Bind a chunk of AGP memory.
168022944501Smrg *
168122944501Smrg * \param fd file descriptor.
168222944501Smrg * \param handle handle to the allocated memory, as given by drmAgpAllocate().
168322944501Smrg * \param offset offset in bytes. It will round to page boundary.
168422944501Smrg *
168522944501Smrg * \return zero on success, or a negative value on failure.
168622944501Smrg *
168722944501Smrg * \internal
168822944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_BIND ioctl, passing the
168922944501Smrg * argument in a drm_agp_binding structure.
169022944501Smrg */
169122944501Smrgint drmAgpBind(int fd, drm_handle_t handle, unsigned long offset)
169222944501Smrg{
169322944501Smrg    drm_agp_binding_t b;
169422944501Smrg
169522944501Smrg    b.handle = handle;
169622944501Smrg    b.offset = offset;
169722944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AGP_BIND, &b))
169822944501Smrg	return -errno;
169922944501Smrg    return 0;
170022944501Smrg}
170122944501Smrg
170222944501Smrg
170322944501Smrg/**
170422944501Smrg * Unbind a chunk of AGP memory.
170522944501Smrg *
170622944501Smrg * \param fd file descriptor.
170722944501Smrg * \param handle handle to the allocated memory, as given by drmAgpAllocate().
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_UNBIND ioctl, passing
171322944501Smrg * the argument in a drm_agp_binding structure.
171422944501Smrg */
171522944501Smrgint drmAgpUnbind(int fd, drm_handle_t handle)
171622944501Smrg{
171722944501Smrg    drm_agp_binding_t b;
171822944501Smrg
171922944501Smrg    b.handle = handle;
172022944501Smrg    b.offset = 0;
172122944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AGP_UNBIND, &b))
172222944501Smrg	return -errno;
172322944501Smrg    return 0;
172422944501Smrg}
172522944501Smrg
172622944501Smrg
172722944501Smrg/**
172822944501Smrg * Get AGP driver major version number.
172922944501Smrg *
173022944501Smrg * \param fd file descriptor.
173122944501Smrg *
173222944501Smrg * \return major version number on success, or a negative value on failure..
173322944501Smrg *
173422944501Smrg * \internal
173522944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
173622944501Smrg * necessary information in a drm_agp_info structure.
173722944501Smrg */
173822944501Smrgint drmAgpVersionMajor(int fd)
173922944501Smrg{
174022944501Smrg    drm_agp_info_t i;
174122944501Smrg
174222944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
174322944501Smrg	return -errno;
174422944501Smrg    return i.agp_version_major;
174522944501Smrg}
174622944501Smrg
174722944501Smrg
174822944501Smrg/**
174922944501Smrg * Get AGP driver minor version number.
175022944501Smrg *
175122944501Smrg * \param fd file descriptor.
175222944501Smrg *
175322944501Smrg * \return minor version number on success, or a negative value on failure.
175422944501Smrg *
175522944501Smrg * \internal
175622944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
175722944501Smrg * necessary information in a drm_agp_info structure.
175822944501Smrg */
175922944501Smrgint drmAgpVersionMinor(int fd)
176022944501Smrg{
176122944501Smrg    drm_agp_info_t i;
176222944501Smrg
176322944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
176422944501Smrg	return -errno;
176522944501Smrg    return i.agp_version_minor;
176622944501Smrg}
176722944501Smrg
176822944501Smrg
176922944501Smrg/**
177022944501Smrg * Get AGP mode.
177122944501Smrg *
177222944501Smrg * \param fd file descriptor.
177322944501Smrg *
177422944501Smrg * \return mode on success, or zero on failure.
177522944501Smrg *
177622944501Smrg * \internal
177722944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
177822944501Smrg * necessary information in a drm_agp_info structure.
177922944501Smrg */
178022944501Smrgunsigned long drmAgpGetMode(int fd)
178122944501Smrg{
178222944501Smrg    drm_agp_info_t i;
178322944501Smrg
178422944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
178522944501Smrg	return 0;
178622944501Smrg    return i.mode;
178722944501Smrg}
178822944501Smrg
178922944501Smrg
179022944501Smrg/**
179122944501Smrg * Get AGP aperture base.
179222944501Smrg *
179322944501Smrg * \param fd file descriptor.
179422944501Smrg *
179522944501Smrg * \return aperture base on success, zero on failure.
179622944501Smrg *
179722944501Smrg * \internal
179822944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
179922944501Smrg * necessary information in a drm_agp_info structure.
180022944501Smrg */
180122944501Smrgunsigned long drmAgpBase(int fd)
180222944501Smrg{
180322944501Smrg    drm_agp_info_t i;
180422944501Smrg
180522944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
180622944501Smrg	return 0;
180722944501Smrg    return i.aperture_base;
180822944501Smrg}
180922944501Smrg
181022944501Smrg
181122944501Smrg/**
181222944501Smrg * Get AGP aperture size.
181322944501Smrg *
181422944501Smrg * \param fd file descriptor.
181522944501Smrg *
181622944501Smrg * \return aperture size on success, zero on failure.
181722944501Smrg *
181822944501Smrg * \internal
181922944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
182022944501Smrg * necessary information in a drm_agp_info structure.
182122944501Smrg */
182222944501Smrgunsigned long drmAgpSize(int fd)
182322944501Smrg{
182422944501Smrg    drm_agp_info_t i;
182522944501Smrg
182622944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
182722944501Smrg	return 0;
182822944501Smrg    return i.aperture_size;
182922944501Smrg}
183022944501Smrg
183122944501Smrg
183222944501Smrg/**
183322944501Smrg * Get used AGP memory.
183422944501Smrg *
183522944501Smrg * \param fd file descriptor.
183622944501Smrg *
183722944501Smrg * \return memory used on success, or zero on failure.
183822944501Smrg *
183922944501Smrg * \internal
184022944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
184122944501Smrg * necessary information in a drm_agp_info structure.
184222944501Smrg */
184322944501Smrgunsigned long drmAgpMemoryUsed(int fd)
184422944501Smrg{
184522944501Smrg    drm_agp_info_t i;
184622944501Smrg
184722944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
184822944501Smrg	return 0;
184922944501Smrg    return i.memory_used;
185022944501Smrg}
185122944501Smrg
185222944501Smrg
185322944501Smrg/**
185422944501Smrg * Get available AGP memory.
185522944501Smrg *
185622944501Smrg * \param fd file descriptor.
185722944501Smrg *
185822944501Smrg * \return memory available on success, or zero on failure.
185922944501Smrg *
186022944501Smrg * \internal
186122944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
186222944501Smrg * necessary information in a drm_agp_info structure.
186322944501Smrg */
186422944501Smrgunsigned long drmAgpMemoryAvail(int fd)
186522944501Smrg{
186622944501Smrg    drm_agp_info_t i;
186722944501Smrg
186822944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
186922944501Smrg	return 0;
187022944501Smrg    return i.memory_allowed;
187122944501Smrg}
187222944501Smrg
187322944501Smrg
187422944501Smrg/**
187522944501Smrg * Get hardware vendor ID.
187622944501Smrg *
187722944501Smrg * \param fd file descriptor.
187822944501Smrg *
187922944501Smrg * \return vendor ID on success, or zero on failure.
188022944501Smrg *
188122944501Smrg * \internal
188222944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
188322944501Smrg * necessary information in a drm_agp_info structure.
188422944501Smrg */
188522944501Smrgunsigned int drmAgpVendorId(int fd)
188622944501Smrg{
188722944501Smrg    drm_agp_info_t i;
188822944501Smrg
188922944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
189022944501Smrg	return 0;
189122944501Smrg    return i.id_vendor;
189222944501Smrg}
189322944501Smrg
189422944501Smrg
189522944501Smrg/**
189622944501Smrg * Get hardware device ID.
189722944501Smrg *
189822944501Smrg * \param fd file descriptor.
189922944501Smrg *
190022944501Smrg * \return zero on success, or zero on failure.
190122944501Smrg *
190222944501Smrg * \internal
190322944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
190422944501Smrg * necessary information in a drm_agp_info structure.
190522944501Smrg */
190622944501Smrgunsigned int drmAgpDeviceId(int fd)
190722944501Smrg{
190822944501Smrg    drm_agp_info_t i;
190922944501Smrg
191022944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
191122944501Smrg	return 0;
191222944501Smrg    return i.id_device;
191322944501Smrg}
191422944501Smrg
191522944501Smrgint drmScatterGatherAlloc(int fd, unsigned long size, drm_handle_t *handle)
191622944501Smrg{
191722944501Smrg    drm_scatter_gather_t sg;
191822944501Smrg
191922944501Smrg    *handle = 0;
192022944501Smrg    sg.size   = size;
192122944501Smrg    sg.handle = 0;
192222944501Smrg    if (drmIoctl(fd, DRM_IOCTL_SG_ALLOC, &sg))
192322944501Smrg	return -errno;
192422944501Smrg    *handle = sg.handle;
192522944501Smrg    return 0;
192622944501Smrg}
192722944501Smrg
192822944501Smrgint drmScatterGatherFree(int fd, drm_handle_t handle)
192922944501Smrg{
193022944501Smrg    drm_scatter_gather_t sg;
193122944501Smrg
193222944501Smrg    sg.size   = 0;
193322944501Smrg    sg.handle = handle;
193422944501Smrg    if (drmIoctl(fd, DRM_IOCTL_SG_FREE, &sg))
193522944501Smrg	return -errno;
193622944501Smrg    return 0;
193722944501Smrg}
193822944501Smrg
193922944501Smrg/**
194022944501Smrg * Wait for VBLANK.
194122944501Smrg *
194222944501Smrg * \param fd file descriptor.
194322944501Smrg * \param vbl pointer to a drmVBlank structure.
194422944501Smrg *
194522944501Smrg * \return zero on success, or a negative value on failure.
194622944501Smrg *
194722944501Smrg * \internal
194822944501Smrg * This function is a wrapper around the DRM_IOCTL_WAIT_VBLANK ioctl.
194922944501Smrg */
195022944501Smrgint drmWaitVBlank(int fd, drmVBlankPtr vbl)
195122944501Smrg{
195222944501Smrg    struct timespec timeout, cur;
195322944501Smrg    int ret;
195422944501Smrg
195522944501Smrg    ret = clock_gettime(CLOCK_MONOTONIC, &timeout);
195622944501Smrg    if (ret < 0) {
195720131375Smrg	fprintf(stderr, "clock_gettime failed: %s\n", strerror(errno));
195822944501Smrg	goto out;
195922944501Smrg    }
196022944501Smrg    timeout.tv_sec++;
196122944501Smrg
196222944501Smrg    do {
196322944501Smrg       ret = ioctl(fd, DRM_IOCTL_WAIT_VBLANK, vbl);
196422944501Smrg       vbl->request.type &= ~DRM_VBLANK_RELATIVE;
196522944501Smrg       if (ret && errno == EINTR) {
196622944501Smrg	       clock_gettime(CLOCK_MONOTONIC, &cur);
196722944501Smrg	       /* Timeout after 1s */
196822944501Smrg	       if (cur.tv_sec > timeout.tv_sec + 1 ||
196922944501Smrg		   (cur.tv_sec == timeout.tv_sec && cur.tv_nsec >=
197022944501Smrg		    timeout.tv_nsec)) {
197122944501Smrg		       errno = EBUSY;
197222944501Smrg		       ret = -1;
197322944501Smrg		       break;
197422944501Smrg	       }
197522944501Smrg       }
197622944501Smrg    } while (ret && errno == EINTR);
197722944501Smrg
197822944501Smrgout:
197922944501Smrg    return ret;
198022944501Smrg}
198122944501Smrg
198222944501Smrgint drmError(int err, const char *label)
198322944501Smrg{
198422944501Smrg    switch (err) {
198522944501Smrg    case DRM_ERR_NO_DEVICE:
198622944501Smrg	fprintf(stderr, "%s: no device\n", label);
198722944501Smrg	break;
198822944501Smrg    case DRM_ERR_NO_ACCESS:
198922944501Smrg	fprintf(stderr, "%s: no access\n", label);
199022944501Smrg	break;
199122944501Smrg    case DRM_ERR_NOT_ROOT:
199222944501Smrg	fprintf(stderr, "%s: not root\n", label);
199322944501Smrg	break;
199422944501Smrg    case DRM_ERR_INVALID:
199522944501Smrg	fprintf(stderr, "%s: invalid args\n", label);
199622944501Smrg	break;
199722944501Smrg    default:
199822944501Smrg	if (err < 0)
199922944501Smrg	    err = -err;
200022944501Smrg	fprintf( stderr, "%s: error %d (%s)\n", label, err, strerror(err) );
200122944501Smrg	break;
200222944501Smrg    }
200322944501Smrg
200422944501Smrg    return 1;
200522944501Smrg}
200622944501Smrg
200722944501Smrg/**
200822944501Smrg * Install IRQ handler.
200922944501Smrg *
201022944501Smrg * \param fd file descriptor.
201122944501Smrg * \param irq IRQ number.
201222944501Smrg *
201322944501Smrg * \return zero on success, or a negative value on failure.
201422944501Smrg *
201522944501Smrg * \internal
201622944501Smrg * This function is a wrapper around the DRM_IOCTL_CONTROL ioctl, passing the
201722944501Smrg * argument in a drm_control structure.
201822944501Smrg */
201922944501Smrgint drmCtlInstHandler(int fd, int irq)
202022944501Smrg{
202122944501Smrg    drm_control_t ctl;
202222944501Smrg
202322944501Smrg    ctl.func  = DRM_INST_HANDLER;
202422944501Smrg    ctl.irq   = irq;
202522944501Smrg    if (drmIoctl(fd, DRM_IOCTL_CONTROL, &ctl))
202622944501Smrg	return -errno;
202722944501Smrg    return 0;
202822944501Smrg}
202922944501Smrg
203022944501Smrg
203122944501Smrg/**
203222944501Smrg * Uninstall IRQ handler.
203322944501Smrg *
203422944501Smrg * \param fd file descriptor.
203522944501Smrg *
203622944501Smrg * \return zero on success, or a negative value on failure.
203722944501Smrg *
203822944501Smrg * \internal
203922944501Smrg * This function is a wrapper around the DRM_IOCTL_CONTROL ioctl, passing the
204022944501Smrg * argument in a drm_control structure.
204122944501Smrg */
204222944501Smrgint drmCtlUninstHandler(int fd)
204322944501Smrg{
204422944501Smrg    drm_control_t ctl;
204522944501Smrg
204622944501Smrg    ctl.func  = DRM_UNINST_HANDLER;
204722944501Smrg    ctl.irq   = 0;
204822944501Smrg    if (drmIoctl(fd, DRM_IOCTL_CONTROL, &ctl))
204922944501Smrg	return -errno;
205022944501Smrg    return 0;
205122944501Smrg}
205222944501Smrg
205322944501Smrgint drmFinish(int fd, int context, drmLockFlags flags)
205422944501Smrg{
205522944501Smrg    drm_lock_t lock;
205622944501Smrg
205722944501Smrg    lock.context = context;
205822944501Smrg    lock.flags   = 0;
205922944501Smrg    if (flags & DRM_LOCK_READY)      lock.flags |= _DRM_LOCK_READY;
206022944501Smrg    if (flags & DRM_LOCK_QUIESCENT)  lock.flags |= _DRM_LOCK_QUIESCENT;
206122944501Smrg    if (flags & DRM_LOCK_FLUSH)      lock.flags |= _DRM_LOCK_FLUSH;
206222944501Smrg    if (flags & DRM_LOCK_FLUSH_ALL)  lock.flags |= _DRM_LOCK_FLUSH_ALL;
206322944501Smrg    if (flags & DRM_HALT_ALL_QUEUES) lock.flags |= _DRM_HALT_ALL_QUEUES;
206422944501Smrg    if (flags & DRM_HALT_CUR_QUEUES) lock.flags |= _DRM_HALT_CUR_QUEUES;
206522944501Smrg    if (drmIoctl(fd, DRM_IOCTL_FINISH, &lock))
206622944501Smrg	return -errno;
206722944501Smrg    return 0;
206822944501Smrg}
206922944501Smrg
207022944501Smrg/**
207122944501Smrg * Get IRQ from bus ID.
207222944501Smrg *
207322944501Smrg * \param fd file descriptor.
207422944501Smrg * \param busnum bus number.
207522944501Smrg * \param devnum device number.
207622944501Smrg * \param funcnum function number.
207722944501Smrg *
207822944501Smrg * \return IRQ number on success, or a negative value on failure.
207922944501Smrg *
208022944501Smrg * \internal
208122944501Smrg * This function is a wrapper around the DRM_IOCTL_IRQ_BUSID ioctl, passing the
208222944501Smrg * arguments in a drm_irq_busid structure.
208322944501Smrg */
208422944501Smrgint drmGetInterruptFromBusID(int fd, int busnum, int devnum, int funcnum)
208522944501Smrg{
208622944501Smrg    drm_irq_busid_t p;
208722944501Smrg
208822944501Smrg    p.busnum  = busnum;
208922944501Smrg    p.devnum  = devnum;
209022944501Smrg    p.funcnum = funcnum;
209122944501Smrg    if (drmIoctl(fd, DRM_IOCTL_IRQ_BUSID, &p))
209222944501Smrg	return -errno;
209322944501Smrg    return p.irq;
209422944501Smrg}
209522944501Smrg
209622944501Smrgint drmAddContextTag(int fd, drm_context_t context, void *tag)
209722944501Smrg{
209822944501Smrg    drmHashEntry  *entry = drmGetEntry(fd);
209922944501Smrg
210022944501Smrg    if (drmHashInsert(entry->tagTable, context, tag)) {
210122944501Smrg	drmHashDelete(entry->tagTable, context);
210222944501Smrg	drmHashInsert(entry->tagTable, context, tag);
210322944501Smrg    }
210422944501Smrg    return 0;
210522944501Smrg}
210622944501Smrg
210722944501Smrgint drmDelContextTag(int fd, drm_context_t context)
210822944501Smrg{
210922944501Smrg    drmHashEntry  *entry = drmGetEntry(fd);
211022944501Smrg
211122944501Smrg    return drmHashDelete(entry->tagTable, context);
211222944501Smrg}
211322944501Smrg
211422944501Smrgvoid *drmGetContextTag(int fd, drm_context_t context)
211522944501Smrg{
211622944501Smrg    drmHashEntry  *entry = drmGetEntry(fd);
211722944501Smrg    void          *value;
211822944501Smrg
211922944501Smrg    if (drmHashLookup(entry->tagTable, context, &value))
212022944501Smrg	return NULL;
212122944501Smrg
212222944501Smrg    return value;
212322944501Smrg}
212422944501Smrg
212522944501Smrgint drmAddContextPrivateMapping(int fd, drm_context_t ctx_id,
212622944501Smrg                                drm_handle_t handle)
212722944501Smrg{
212822944501Smrg    drm_ctx_priv_map_t map;
212922944501Smrg
213022944501Smrg    map.ctx_id = ctx_id;
213120131375Smrg    map.handle = (void *)(uintptr_t)handle;
213222944501Smrg
213322944501Smrg    if (drmIoctl(fd, DRM_IOCTL_SET_SAREA_CTX, &map))
213422944501Smrg	return -errno;
213522944501Smrg    return 0;
213622944501Smrg}
213722944501Smrg
213822944501Smrgint drmGetContextPrivateMapping(int fd, drm_context_t ctx_id,
213922944501Smrg                                drm_handle_t *handle)
214022944501Smrg{
214122944501Smrg    drm_ctx_priv_map_t map;
214222944501Smrg
214322944501Smrg    map.ctx_id = ctx_id;
214422944501Smrg
214522944501Smrg    if (drmIoctl(fd, DRM_IOCTL_GET_SAREA_CTX, &map))
214622944501Smrg	return -errno;
214722944501Smrg    if (handle)
214820131375Smrg	*handle = (drm_handle_t)(uintptr_t)map.handle;
214922944501Smrg
215022944501Smrg    return 0;
215122944501Smrg}
215222944501Smrg
215322944501Smrgint drmGetMap(int fd, int idx, drm_handle_t *offset, drmSize *size,
215422944501Smrg	      drmMapType *type, drmMapFlags *flags, drm_handle_t *handle,
215522944501Smrg	      int *mtrr)
215622944501Smrg{
215722944501Smrg    drm_map_t map;
215822944501Smrg
215922944501Smrg    map.offset = idx;
216022944501Smrg    if (drmIoctl(fd, DRM_IOCTL_GET_MAP, &map))
216122944501Smrg	return -errno;
216222944501Smrg    *offset = map.offset;
216322944501Smrg    *size   = map.size;
216422944501Smrg    *type   = map.type;
216522944501Smrg    *flags  = map.flags;
216622944501Smrg    *handle = (unsigned long)map.handle;
216722944501Smrg    *mtrr   = map.mtrr;
216822944501Smrg    return 0;
216922944501Smrg}
217022944501Smrg
217122944501Smrgint drmGetClient(int fd, int idx, int *auth, int *pid, int *uid,
217222944501Smrg		 unsigned long *magic, unsigned long *iocs)
217322944501Smrg{
217422944501Smrg    drm_client_t client;
217522944501Smrg
217622944501Smrg    client.idx = idx;
217722944501Smrg    if (drmIoctl(fd, DRM_IOCTL_GET_CLIENT, &client))
217822944501Smrg	return -errno;
217922944501Smrg    *auth      = client.auth;
218022944501Smrg    *pid       = client.pid;
218122944501Smrg    *uid       = client.uid;
218222944501Smrg    *magic     = client.magic;
218322944501Smrg    *iocs      = client.iocs;
218422944501Smrg    return 0;
218522944501Smrg}
218622944501Smrg
218722944501Smrgint drmGetStats(int fd, drmStatsT *stats)
218822944501Smrg{
218922944501Smrg    drm_stats_t s;
219022944501Smrg    int         i;
219122944501Smrg
219222944501Smrg    if (drmIoctl(fd, DRM_IOCTL_GET_STATS, &s))
219322944501Smrg	return -errno;
219422944501Smrg
219522944501Smrg    stats->count = 0;
219622944501Smrg    memset(stats, 0, sizeof(*stats));
219722944501Smrg    if (s.count > sizeof(stats->data)/sizeof(stats->data[0]))
219822944501Smrg	return -1;
219922944501Smrg
220022944501Smrg#define SET_VALUE                              \
220122944501Smrg    stats->data[i].long_format = "%-20.20s";   \
220222944501Smrg    stats->data[i].rate_format = "%8.8s";      \
220322944501Smrg    stats->data[i].isvalue     = 1;            \
220422944501Smrg    stats->data[i].verbose     = 0
220522944501Smrg
220622944501Smrg#define SET_COUNT                              \
220722944501Smrg    stats->data[i].long_format = "%-20.20s";   \
220822944501Smrg    stats->data[i].rate_format = "%5.5s";      \
220922944501Smrg    stats->data[i].isvalue     = 0;            \
221022944501Smrg    stats->data[i].mult_names  = "kgm";        \
221122944501Smrg    stats->data[i].mult        = 1000;         \
221222944501Smrg    stats->data[i].verbose     = 0
221322944501Smrg
221422944501Smrg#define SET_BYTE                               \
221522944501Smrg    stats->data[i].long_format = "%-20.20s";   \
221622944501Smrg    stats->data[i].rate_format = "%5.5s";      \
221722944501Smrg    stats->data[i].isvalue     = 0;            \
221822944501Smrg    stats->data[i].mult_names  = "KGM";        \
221922944501Smrg    stats->data[i].mult        = 1024;         \
222022944501Smrg    stats->data[i].verbose     = 0
222122944501Smrg
222222944501Smrg
222322944501Smrg    stats->count = s.count;
222422944501Smrg    for (i = 0; i < s.count; i++) {
222522944501Smrg	stats->data[i].value = s.data[i].value;
222622944501Smrg	switch (s.data[i].type) {
222722944501Smrg	case _DRM_STAT_LOCK:
222822944501Smrg	    stats->data[i].long_name = "Lock";
222922944501Smrg	    stats->data[i].rate_name = "Lock";
223022944501Smrg	    SET_VALUE;
223122944501Smrg	    break;
223222944501Smrg	case _DRM_STAT_OPENS:
223322944501Smrg	    stats->data[i].long_name = "Opens";
223422944501Smrg	    stats->data[i].rate_name = "O";
223522944501Smrg	    SET_COUNT;
223622944501Smrg	    stats->data[i].verbose   = 1;
223722944501Smrg	    break;
223822944501Smrg	case _DRM_STAT_CLOSES:
223922944501Smrg	    stats->data[i].long_name = "Closes";
224022944501Smrg	    stats->data[i].rate_name = "Lock";
224122944501Smrg	    SET_COUNT;
224222944501Smrg	    stats->data[i].verbose   = 1;
224322944501Smrg	    break;
224422944501Smrg	case _DRM_STAT_IOCTLS:
224522944501Smrg	    stats->data[i].long_name = "Ioctls";
224622944501Smrg	    stats->data[i].rate_name = "Ioc/s";
224722944501Smrg	    SET_COUNT;
224822944501Smrg	    break;
224922944501Smrg	case _DRM_STAT_LOCKS:
225022944501Smrg	    stats->data[i].long_name = "Locks";
225122944501Smrg	    stats->data[i].rate_name = "Lck/s";
225222944501Smrg	    SET_COUNT;
225322944501Smrg	    break;
225422944501Smrg	case _DRM_STAT_UNLOCKS:
225522944501Smrg	    stats->data[i].long_name = "Unlocks";
225622944501Smrg	    stats->data[i].rate_name = "Unl/s";
225722944501Smrg	    SET_COUNT;
225822944501Smrg	    break;
225922944501Smrg	case _DRM_STAT_IRQ:
226022944501Smrg	    stats->data[i].long_name = "IRQs";
226122944501Smrg	    stats->data[i].rate_name = "IRQ/s";
226222944501Smrg	    SET_COUNT;
226322944501Smrg	    break;
226422944501Smrg	case _DRM_STAT_PRIMARY:
226522944501Smrg	    stats->data[i].long_name = "Primary Bytes";
226622944501Smrg	    stats->data[i].rate_name = "PB/s";
226722944501Smrg	    SET_BYTE;
226822944501Smrg	    break;
226922944501Smrg	case _DRM_STAT_SECONDARY:
227022944501Smrg	    stats->data[i].long_name = "Secondary Bytes";
227122944501Smrg	    stats->data[i].rate_name = "SB/s";
227222944501Smrg	    SET_BYTE;
227322944501Smrg	    break;
227422944501Smrg	case _DRM_STAT_DMA:
227522944501Smrg	    stats->data[i].long_name = "DMA";
227622944501Smrg	    stats->data[i].rate_name = "DMA/s";
227722944501Smrg	    SET_COUNT;
227822944501Smrg	    break;
227922944501Smrg	case _DRM_STAT_SPECIAL:
228022944501Smrg	    stats->data[i].long_name = "Special DMA";
228122944501Smrg	    stats->data[i].rate_name = "dma/s";
228222944501Smrg	    SET_COUNT;
228322944501Smrg	    break;
228422944501Smrg	case _DRM_STAT_MISSED:
228522944501Smrg	    stats->data[i].long_name = "Miss";
228622944501Smrg	    stats->data[i].rate_name = "Ms/s";
228722944501Smrg	    SET_COUNT;
228822944501Smrg	    break;
228922944501Smrg	case _DRM_STAT_VALUE:
229022944501Smrg	    stats->data[i].long_name = "Value";
229122944501Smrg	    stats->data[i].rate_name = "Value";
229222944501Smrg	    SET_VALUE;
229322944501Smrg	    break;
229422944501Smrg	case _DRM_STAT_BYTE:
229522944501Smrg	    stats->data[i].long_name = "Bytes";
229622944501Smrg	    stats->data[i].rate_name = "B/s";
229722944501Smrg	    SET_BYTE;
229822944501Smrg	    break;
229922944501Smrg	case _DRM_STAT_COUNT:
230022944501Smrg	default:
230122944501Smrg	    stats->data[i].long_name = "Count";
230222944501Smrg	    stats->data[i].rate_name = "Cnt/s";
230322944501Smrg	    SET_COUNT;
230422944501Smrg	    break;
230522944501Smrg	}
230622944501Smrg    }
230722944501Smrg    return 0;
230822944501Smrg}
230922944501Smrg
231022944501Smrg/**
231122944501Smrg * Issue a set-version ioctl.
231222944501Smrg *
231322944501Smrg * \param fd file descriptor.
231422944501Smrg * \param drmCommandIndex command index
231522944501Smrg * \param data source pointer of the data to be read and written.
231622944501Smrg * \param size size of the data to be read and written.
231722944501Smrg *
231822944501Smrg * \return zero on success, or a negative value on failure.
231922944501Smrg *
232022944501Smrg * \internal
232122944501Smrg * It issues a read-write ioctl given by
232222944501Smrg * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
232322944501Smrg */
232422944501Smrgint drmSetInterfaceVersion(int fd, drmSetVersion *version)
232522944501Smrg{
232622944501Smrg    int retcode = 0;
232722944501Smrg    drm_set_version_t sv;
232822944501Smrg
232922944501Smrg    sv.drm_di_major = version->drm_di_major;
233022944501Smrg    sv.drm_di_minor = version->drm_di_minor;
233122944501Smrg    sv.drm_dd_major = version->drm_dd_major;
233222944501Smrg    sv.drm_dd_minor = version->drm_dd_minor;
233322944501Smrg
233422944501Smrg    if (drmIoctl(fd, DRM_IOCTL_SET_VERSION, &sv)) {
233522944501Smrg	retcode = -errno;
233622944501Smrg    }
233722944501Smrg
233822944501Smrg    version->drm_di_major = sv.drm_di_major;
233922944501Smrg    version->drm_di_minor = sv.drm_di_minor;
234022944501Smrg    version->drm_dd_major = sv.drm_dd_major;
234122944501Smrg    version->drm_dd_minor = sv.drm_dd_minor;
234222944501Smrg
234322944501Smrg    return retcode;
234422944501Smrg}
234522944501Smrg
234622944501Smrg/**
234722944501Smrg * Send a device-specific command.
234822944501Smrg *
234922944501Smrg * \param fd file descriptor.
235022944501Smrg * \param drmCommandIndex command index
235122944501Smrg *
235222944501Smrg * \return zero on success, or a negative value on failure.
235322944501Smrg *
235422944501Smrg * \internal
235522944501Smrg * It issues a ioctl given by
235622944501Smrg * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
235722944501Smrg */
235822944501Smrgint drmCommandNone(int fd, unsigned long drmCommandIndex)
235922944501Smrg{
236022944501Smrg    void *data = NULL; /* dummy */
236122944501Smrg    unsigned long request;
236222944501Smrg
236322944501Smrg    request = DRM_IO( DRM_COMMAND_BASE + drmCommandIndex);
236422944501Smrg
236522944501Smrg    if (drmIoctl(fd, request, data)) {
236622944501Smrg	return -errno;
236722944501Smrg    }
236822944501Smrg    return 0;
236922944501Smrg}
237022944501Smrg
237122944501Smrg
237222944501Smrg/**
237322944501Smrg * Send a device-specific read command.
237422944501Smrg *
237522944501Smrg * \param fd file descriptor.
237622944501Smrg * \param drmCommandIndex command index
237722944501Smrg * \param data destination pointer of the data to be read.
237822944501Smrg * \param size size of the data to be read.
237922944501Smrg *
238022944501Smrg * \return zero on success, or a negative value on failure.
238122944501Smrg *
238222944501Smrg * \internal
238322944501Smrg * It issues a read ioctl given by
238422944501Smrg * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
238522944501Smrg */
238622944501Smrgint drmCommandRead(int fd, unsigned long drmCommandIndex, void *data,
238722944501Smrg                   unsigned long size)
238822944501Smrg{
238922944501Smrg    unsigned long request;
239022944501Smrg
239122944501Smrg    request = DRM_IOC( DRM_IOC_READ, DRM_IOCTL_BASE,
239222944501Smrg	DRM_COMMAND_BASE + drmCommandIndex, size);
239322944501Smrg
239422944501Smrg    if (drmIoctl(fd, request, data)) {
239522944501Smrg	return -errno;
239622944501Smrg    }
239722944501Smrg    return 0;
239822944501Smrg}
239922944501Smrg
240022944501Smrg
240122944501Smrg/**
240222944501Smrg * Send a device-specific write command.
240322944501Smrg *
240422944501Smrg * \param fd file descriptor.
240522944501Smrg * \param drmCommandIndex command index
240622944501Smrg * \param data source pointer of the data to be written.
240722944501Smrg * \param size size of the data to be written.
240822944501Smrg *
240922944501Smrg * \return zero on success, or a negative value on failure.
241022944501Smrg *
241122944501Smrg * \internal
241222944501Smrg * It issues a write ioctl given by
241322944501Smrg * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
241422944501Smrg */
241522944501Smrgint drmCommandWrite(int fd, unsigned long drmCommandIndex, void *data,
241622944501Smrg                    unsigned long size)
241722944501Smrg{
241822944501Smrg    unsigned long request;
241922944501Smrg
242022944501Smrg    request = DRM_IOC( DRM_IOC_WRITE, DRM_IOCTL_BASE,
242122944501Smrg	DRM_COMMAND_BASE + drmCommandIndex, size);
242222944501Smrg
242322944501Smrg    if (drmIoctl(fd, request, data)) {
242422944501Smrg	return -errno;
242522944501Smrg    }
242622944501Smrg    return 0;
242722944501Smrg}
242822944501Smrg
242922944501Smrg
243022944501Smrg/**
243122944501Smrg * Send a device-specific read-write command.
243222944501Smrg *
243322944501Smrg * \param fd file descriptor.
243422944501Smrg * \param drmCommandIndex command index
243522944501Smrg * \param data source pointer of the data to be read and written.
243622944501Smrg * \param size size of the data to be read and written.
243722944501Smrg *
243822944501Smrg * \return zero on success, or a negative value on failure.
243922944501Smrg *
244022944501Smrg * \internal
244122944501Smrg * It issues a read-write ioctl given by
244222944501Smrg * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
244322944501Smrg */
244422944501Smrgint drmCommandWriteRead(int fd, unsigned long drmCommandIndex, void *data,
244522944501Smrg                        unsigned long size)
244622944501Smrg{
244722944501Smrg    unsigned long request;
244822944501Smrg
244922944501Smrg    request = DRM_IOC( DRM_IOC_READ|DRM_IOC_WRITE, DRM_IOCTL_BASE,
245022944501Smrg	DRM_COMMAND_BASE + drmCommandIndex, size);
245122944501Smrg
245222944501Smrg    if (drmIoctl(fd, request, data))
245322944501Smrg	return -errno;
245422944501Smrg    return 0;
245522944501Smrg}
245622944501Smrg
245722944501Smrg#define DRM_MAX_FDS 16
245822944501Smrgstatic struct {
245922944501Smrg    char *BusID;
246022944501Smrg    int fd;
246122944501Smrg    int refcount;
246222944501Smrg} connection[DRM_MAX_FDS];
246322944501Smrg
246422944501Smrgstatic int nr_fds = 0;
246522944501Smrg
246622944501Smrgint drmOpenOnce(void *unused,
246722944501Smrg		const char *BusID,
246822944501Smrg		int *newlyopened)
246922944501Smrg{
247022944501Smrg    int i;
247122944501Smrg    int fd;
247222944501Smrg
247322944501Smrg    for (i = 0; i < nr_fds; i++)
247422944501Smrg	if (strcmp(BusID, connection[i].BusID) == 0) {
247522944501Smrg	    connection[i].refcount++;
247622944501Smrg	    *newlyopened = 0;
247722944501Smrg	    return connection[i].fd;
247822944501Smrg	}
247922944501Smrg
248022944501Smrg    fd = drmOpen(unused, BusID);
248122944501Smrg    if (fd <= 0 || nr_fds == DRM_MAX_FDS)
248222944501Smrg	return fd;
248322944501Smrg
248422944501Smrg    connection[nr_fds].BusID = strdup(BusID);
248522944501Smrg    connection[nr_fds].fd = fd;
248622944501Smrg    connection[nr_fds].refcount = 1;
248722944501Smrg    *newlyopened = 1;
248822944501Smrg
248922944501Smrg    if (0)
249022944501Smrg	fprintf(stderr, "saved connection %d for %s %d\n",
249122944501Smrg		nr_fds, connection[nr_fds].BusID,
249222944501Smrg		strcmp(BusID, connection[nr_fds].BusID));
249322944501Smrg
249422944501Smrg    nr_fds++;
249522944501Smrg
249622944501Smrg    return fd;
249722944501Smrg}
249822944501Smrg
249922944501Smrgvoid drmCloseOnce(int fd)
250022944501Smrg{
250122944501Smrg    int i;
250222944501Smrg
250322944501Smrg    for (i = 0; i < nr_fds; i++) {
250422944501Smrg	if (fd == connection[i].fd) {
250522944501Smrg	    if (--connection[i].refcount == 0) {
250622944501Smrg		drmClose(connection[i].fd);
250722944501Smrg		free(connection[i].BusID);
250822944501Smrg
250922944501Smrg		if (i < --nr_fds)
251022944501Smrg		    connection[i] = connection[nr_fds];
251122944501Smrg
251222944501Smrg		return;
251322944501Smrg	    }
251422944501Smrg	}
251522944501Smrg    }
251622944501Smrg}
251722944501Smrg
251822944501Smrgint drmSetMaster(int fd)
251922944501Smrg{
252022944501Smrg	return ioctl(fd, DRM_IOCTL_SET_MASTER, 0);
252122944501Smrg}
252222944501Smrg
252322944501Smrgint drmDropMaster(int fd)
252422944501Smrg{
252522944501Smrg	return ioctl(fd, DRM_IOCTL_DROP_MASTER, 0);
252622944501Smrg}
252722944501Smrg
252822944501Smrgchar *drmGetDeviceNameFromFd(int fd)
252922944501Smrg{
253022944501Smrg	char name[128];
253122944501Smrg	struct stat sbuf;
253222944501Smrg	dev_t d;
253322944501Smrg	int i;
253422944501Smrg
253522944501Smrg	/* The whole drmOpen thing is a fiasco and we need to find a way
253622944501Smrg	 * back to just using open(2).  For now, however, lets just make
253722944501Smrg	 * things worse with even more ad hoc directory walking code to
253822944501Smrg	 * discover the device file name. */
253922944501Smrg
254022944501Smrg	fstat(fd, &sbuf);
254122944501Smrg	d = sbuf.st_rdev;
254222944501Smrg
254322944501Smrg	for (i = 0; i < DRM_MAX_MINOR; i++) {
254422944501Smrg		snprintf(name, sizeof name, DRM_DEV_NAME, DRM_DIR_NAME, i);
254522944501Smrg		if (stat(name, &sbuf) == 0 && sbuf.st_rdev == d)
254622944501Smrg			break;
254722944501Smrg	}
254822944501Smrg	if (i == DRM_MAX_MINOR)
254922944501Smrg		return NULL;
255022944501Smrg
25519ce4edccSmrg	return strdup(name);
255222944501Smrg}
255320131375Smrg
255420131375Smrgint drmPrimeHandleToFD(int fd, uint32_t handle, uint32_t flags, int *prime_fd)
255520131375Smrg{
255620131375Smrg	struct drm_prime_handle args;
255720131375Smrg	int ret;
255820131375Smrg
255920131375Smrg	args.handle = handle;
256020131375Smrg	args.flags = flags;
256120131375Smrg	ret = drmIoctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &args);
256220131375Smrg	if (ret)
256320131375Smrg		return ret;
256420131375Smrg
256520131375Smrg	*prime_fd = args.fd;
256620131375Smrg	return 0;
256720131375Smrg}
256820131375Smrg
256920131375Smrgint drmPrimeFDToHandle(int fd, int prime_fd, uint32_t *handle)
257020131375Smrg{
257120131375Smrg	struct drm_prime_handle args;
257220131375Smrg	int ret;
257320131375Smrg
257420131375Smrg	args.fd = prime_fd;
257520131375Smrg	args.flags = 0;
257620131375Smrg	ret = drmIoctl(fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &args);
257720131375Smrg	if (ret)
257820131375Smrg		return ret;
257920131375Smrg
258020131375Smrg	*handle = args.handle;
258120131375Smrg	return 0;
258220131375Smrg}
258320131375Smrg
2584