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