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