xf86drm.c revision 9ce4edcc
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
81422944501Smrg
81522944501Smrg/**
81622944501Smrg * Free the bus ID information.
81722944501Smrg *
81822944501Smrg * \param busid bus ID information string as given by drmGetBusid().
81922944501Smrg *
82022944501Smrg * \internal
82122944501Smrg * This function is just frees the memory pointed by \p busid.
82222944501Smrg */
82322944501Smrgvoid drmFreeBusid(const char *busid)
82422944501Smrg{
82522944501Smrg    drmFree((void *)busid);
82622944501Smrg}
82722944501Smrg
82822944501Smrg
82922944501Smrg/**
83022944501Smrg * Get the bus ID of the device.
83122944501Smrg *
83222944501Smrg * \param fd file descriptor.
83322944501Smrg *
83422944501Smrg * \return bus ID string.
83522944501Smrg *
83622944501Smrg * \internal
83722944501Smrg * This function gets the bus ID via successive DRM_IOCTL_GET_UNIQUE ioctls to
83822944501Smrg * get the string length and data, passing the arguments in a drm_unique
83922944501Smrg * structure.
84022944501Smrg */
84122944501Smrgchar *drmGetBusid(int fd)
84222944501Smrg{
84322944501Smrg    drm_unique_t u;
84422944501Smrg
84522944501Smrg    u.unique_len = 0;
84622944501Smrg    u.unique     = NULL;
84722944501Smrg
84822944501Smrg    if (drmIoctl(fd, DRM_IOCTL_GET_UNIQUE, &u))
84922944501Smrg	return NULL;
85022944501Smrg    u.unique = drmMalloc(u.unique_len + 1);
85122944501Smrg    if (drmIoctl(fd, DRM_IOCTL_GET_UNIQUE, &u))
85222944501Smrg	return NULL;
85322944501Smrg    u.unique[u.unique_len] = '\0';
85422944501Smrg
85522944501Smrg    return u.unique;
85622944501Smrg}
85722944501Smrg
85822944501Smrg
85922944501Smrg/**
86022944501Smrg * Set the bus ID of the device.
86122944501Smrg *
86222944501Smrg * \param fd file descriptor.
86322944501Smrg * \param busid bus ID string.
86422944501Smrg *
86522944501Smrg * \return zero on success, negative on failure.
86622944501Smrg *
86722944501Smrg * \internal
86822944501Smrg * This function is a wrapper around the DRM_IOCTL_SET_UNIQUE ioctl, passing
86922944501Smrg * the arguments in a drm_unique structure.
87022944501Smrg */
87122944501Smrgint drmSetBusid(int fd, const char *busid)
87222944501Smrg{
87322944501Smrg    drm_unique_t u;
87422944501Smrg
87522944501Smrg    u.unique     = (char *)busid;
87622944501Smrg    u.unique_len = strlen(busid);
87722944501Smrg
87822944501Smrg    if (drmIoctl(fd, DRM_IOCTL_SET_UNIQUE, &u)) {
87922944501Smrg	return -errno;
88022944501Smrg    }
88122944501Smrg    return 0;
88222944501Smrg}
88322944501Smrg
88422944501Smrgint drmGetMagic(int fd, drm_magic_t * magic)
88522944501Smrg{
88622944501Smrg    drm_auth_t auth;
88722944501Smrg
88822944501Smrg    *magic = 0;
88922944501Smrg    if (drmIoctl(fd, DRM_IOCTL_GET_MAGIC, &auth))
89022944501Smrg	return -errno;
89122944501Smrg    *magic = auth.magic;
89222944501Smrg    return 0;
89322944501Smrg}
89422944501Smrg
89522944501Smrgint drmAuthMagic(int fd, drm_magic_t magic)
89622944501Smrg{
89722944501Smrg    drm_auth_t auth;
89822944501Smrg
89922944501Smrg    auth.magic = magic;
90022944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AUTH_MAGIC, &auth))
90122944501Smrg	return -errno;
90222944501Smrg    return 0;
90322944501Smrg}
90422944501Smrg
90522944501Smrg/**
90622944501Smrg * Specifies a range of memory that is available for mapping by a
90722944501Smrg * non-root process.
90822944501Smrg *
90922944501Smrg * \param fd file descriptor.
91022944501Smrg * \param offset usually the physical address. The actual meaning depends of
91122944501Smrg * the \p type parameter. See below.
91222944501Smrg * \param size of the memory in bytes.
91322944501Smrg * \param type type of the memory to be mapped.
91422944501Smrg * \param flags combination of several flags to modify the function actions.
91522944501Smrg * \param handle will be set to a value that may be used as the offset
91622944501Smrg * parameter for mmap().
91722944501Smrg *
91822944501Smrg * \return zero on success or a negative value on error.
91922944501Smrg *
92022944501Smrg * \par Mapping the frame buffer
92122944501Smrg * For the frame buffer
92222944501Smrg * - \p offset will be the physical address of the start of the frame buffer,
92322944501Smrg * - \p size will be the size of the frame buffer in bytes, and
92422944501Smrg * - \p type will be DRM_FRAME_BUFFER.
92522944501Smrg *
92622944501Smrg * \par
92722944501Smrg * The area mapped will be uncached. If MTRR support is available in the
92822944501Smrg * kernel, the frame buffer area will be set to write combining.
92922944501Smrg *
93022944501Smrg * \par Mapping the MMIO register area
93122944501Smrg * For the MMIO register area,
93222944501Smrg * - \p offset will be the physical address of the start of the register area,
93322944501Smrg * - \p size will be the size of the register area bytes, and
93422944501Smrg * - \p type will be DRM_REGISTERS.
93522944501Smrg * \par
93622944501Smrg * The area mapped will be uncached.
93722944501Smrg *
93822944501Smrg * \par Mapping the SAREA
93922944501Smrg * For the SAREA,
94022944501Smrg * - \p offset will be ignored and should be set to zero,
94122944501Smrg * - \p size will be the desired size of the SAREA in bytes,
94222944501Smrg * - \p type will be DRM_SHM.
94322944501Smrg *
94422944501Smrg * \par
94522944501Smrg * A shared memory area of the requested size will be created and locked in
94622944501Smrg * kernel memory. This area may be mapped into client-space by using the handle
94722944501Smrg * returned.
94822944501Smrg *
94922944501Smrg * \note May only be called by root.
95022944501Smrg *
95122944501Smrg * \internal
95222944501Smrg * This function is a wrapper around the DRM_IOCTL_ADD_MAP ioctl, passing
95322944501Smrg * the arguments in a drm_map structure.
95422944501Smrg */
95522944501Smrgint drmAddMap(int fd, drm_handle_t offset, drmSize size, drmMapType type,
95622944501Smrg	      drmMapFlags flags, drm_handle_t *handle)
95722944501Smrg{
95822944501Smrg    drm_map_t map;
95922944501Smrg
96022944501Smrg    map.offset  = offset;
96122944501Smrg    map.size    = size;
96222944501Smrg    map.handle  = 0;
96322944501Smrg    map.type    = type;
96422944501Smrg    map.flags   = flags;
96522944501Smrg    if (drmIoctl(fd, DRM_IOCTL_ADD_MAP, &map))
96622944501Smrg	return -errno;
96722944501Smrg    if (handle)
96822944501Smrg	*handle = (drm_handle_t)map.handle;
96922944501Smrg    return 0;
97022944501Smrg}
97122944501Smrg
97222944501Smrgint drmRmMap(int fd, drm_handle_t handle)
97322944501Smrg{
97422944501Smrg    drm_map_t map;
97522944501Smrg
97622944501Smrg    map.handle = (void *)handle;
97722944501Smrg
97822944501Smrg    if(drmIoctl(fd, DRM_IOCTL_RM_MAP, &map))
97922944501Smrg	return -errno;
98022944501Smrg    return 0;
98122944501Smrg}
98222944501Smrg
98322944501Smrg/**
98422944501Smrg * Make buffers available for DMA transfers.
98522944501Smrg *
98622944501Smrg * \param fd file descriptor.
98722944501Smrg * \param count number of buffers.
98822944501Smrg * \param size size of each buffer.
98922944501Smrg * \param flags buffer allocation flags.
99022944501Smrg * \param agp_offset offset in the AGP aperture
99122944501Smrg *
99222944501Smrg * \return number of buffers allocated, negative on error.
99322944501Smrg *
99422944501Smrg * \internal
99522944501Smrg * This function is a wrapper around DRM_IOCTL_ADD_BUFS ioctl.
99622944501Smrg *
99722944501Smrg * \sa drm_buf_desc.
99822944501Smrg */
99922944501Smrgint drmAddBufs(int fd, int count, int size, drmBufDescFlags flags,
100022944501Smrg	       int agp_offset)
100122944501Smrg{
100222944501Smrg    drm_buf_desc_t request;
100322944501Smrg
100422944501Smrg    request.count     = count;
100522944501Smrg    request.size      = size;
100622944501Smrg    request.low_mark  = 0;
100722944501Smrg    request.high_mark = 0;
100822944501Smrg    request.flags     = flags;
100922944501Smrg    request.agp_start = agp_offset;
101022944501Smrg
101122944501Smrg    if (drmIoctl(fd, DRM_IOCTL_ADD_BUFS, &request))
101222944501Smrg	return -errno;
101322944501Smrg    return request.count;
101422944501Smrg}
101522944501Smrg
101622944501Smrgint drmMarkBufs(int fd, double low, double high)
101722944501Smrg{
101822944501Smrg    drm_buf_info_t info;
101922944501Smrg    int            i;
102022944501Smrg
102122944501Smrg    info.count = 0;
102222944501Smrg    info.list  = NULL;
102322944501Smrg
102422944501Smrg    if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info))
102522944501Smrg	return -EINVAL;
102622944501Smrg
102722944501Smrg    if (!info.count)
102822944501Smrg	return -EINVAL;
102922944501Smrg
103022944501Smrg    if (!(info.list = drmMalloc(info.count * sizeof(*info.list))))
103122944501Smrg	return -ENOMEM;
103222944501Smrg
103322944501Smrg    if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info)) {
103422944501Smrg	int retval = -errno;
103522944501Smrg	drmFree(info.list);
103622944501Smrg	return retval;
103722944501Smrg    }
103822944501Smrg
103922944501Smrg    for (i = 0; i < info.count; i++) {
104022944501Smrg	info.list[i].low_mark  = low  * info.list[i].count;
104122944501Smrg	info.list[i].high_mark = high * info.list[i].count;
104222944501Smrg	if (drmIoctl(fd, DRM_IOCTL_MARK_BUFS, &info.list[i])) {
104322944501Smrg	    int retval = -errno;
104422944501Smrg	    drmFree(info.list);
104522944501Smrg	    return retval;
104622944501Smrg	}
104722944501Smrg    }
104822944501Smrg    drmFree(info.list);
104922944501Smrg
105022944501Smrg    return 0;
105122944501Smrg}
105222944501Smrg
105322944501Smrg/**
105422944501Smrg * Free buffers.
105522944501Smrg *
105622944501Smrg * \param fd file descriptor.
105722944501Smrg * \param count number of buffers to free.
105822944501Smrg * \param list list of buffers to be freed.
105922944501Smrg *
106022944501Smrg * \return zero on success, or a negative value on failure.
106122944501Smrg *
106222944501Smrg * \note This function is primarily used for debugging.
106322944501Smrg *
106422944501Smrg * \internal
106522944501Smrg * This function is a wrapper around the DRM_IOCTL_FREE_BUFS ioctl, passing
106622944501Smrg * the arguments in a drm_buf_free structure.
106722944501Smrg */
106822944501Smrgint drmFreeBufs(int fd, int count, int *list)
106922944501Smrg{
107022944501Smrg    drm_buf_free_t request;
107122944501Smrg
107222944501Smrg    request.count = count;
107322944501Smrg    request.list  = list;
107422944501Smrg    if (drmIoctl(fd, DRM_IOCTL_FREE_BUFS, &request))
107522944501Smrg	return -errno;
107622944501Smrg    return 0;
107722944501Smrg}
107822944501Smrg
107922944501Smrg
108022944501Smrg/**
108122944501Smrg * Close the device.
108222944501Smrg *
108322944501Smrg * \param fd file descriptor.
108422944501Smrg *
108522944501Smrg * \internal
108622944501Smrg * This function closes the file descriptor.
108722944501Smrg */
108822944501Smrgint drmClose(int fd)
108922944501Smrg{
109022944501Smrg    unsigned long key    = drmGetKeyFromFd(fd);
109122944501Smrg    drmHashEntry  *entry = drmGetEntry(fd);
109222944501Smrg
109322944501Smrg    drmHashDestroy(entry->tagTable);
109422944501Smrg    entry->fd       = 0;
109522944501Smrg    entry->f        = NULL;
109622944501Smrg    entry->tagTable = NULL;
109722944501Smrg
109822944501Smrg    drmHashDelete(drmHashTable, key);
109922944501Smrg    drmFree(entry);
110022944501Smrg
110122944501Smrg    return close(fd);
110222944501Smrg}
110322944501Smrg
110422944501Smrg
110522944501Smrg/**
110622944501Smrg * Map a region of memory.
110722944501Smrg *
110822944501Smrg * \param fd file descriptor.
110922944501Smrg * \param handle handle returned by drmAddMap().
111022944501Smrg * \param size size in bytes. Must match the size used by drmAddMap().
111122944501Smrg * \param address will contain the user-space virtual address where the mapping
111222944501Smrg * begins.
111322944501Smrg *
111422944501Smrg * \return zero on success, or a negative value on failure.
111522944501Smrg *
111622944501Smrg * \internal
111722944501Smrg * This function is a wrapper for mmap().
111822944501Smrg */
111922944501Smrgint drmMap(int fd, drm_handle_t handle, drmSize size, drmAddressPtr address)
112022944501Smrg{
112122944501Smrg    static unsigned long pagesize_mask = 0;
112222944501Smrg
112322944501Smrg    if (fd < 0)
112422944501Smrg	return -EINVAL;
112522944501Smrg
112622944501Smrg    if (!pagesize_mask)
112722944501Smrg	pagesize_mask = getpagesize() - 1;
112822944501Smrg
112922944501Smrg    size = (size + pagesize_mask) & ~pagesize_mask;
113022944501Smrg
113122944501Smrg    *address = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, handle);
113222944501Smrg    if (*address == MAP_FAILED)
113322944501Smrg	return -errno;
113422944501Smrg    return 0;
113522944501Smrg}
113622944501Smrg
113722944501Smrg
113822944501Smrg/**
113922944501Smrg * Unmap mappings obtained with drmMap().
114022944501Smrg *
114122944501Smrg * \param address address as given by drmMap().
114222944501Smrg * \param size size in bytes. Must match the size used by drmMap().
114322944501Smrg *
114422944501Smrg * \return zero on success, or a negative value on failure.
114522944501Smrg *
114622944501Smrg * \internal
114722944501Smrg * This function is a wrapper for munmap().
114822944501Smrg */
114922944501Smrgint drmUnmap(drmAddress address, drmSize size)
115022944501Smrg{
115122944501Smrg    return munmap(address, size);
115222944501Smrg}
115322944501Smrg
115422944501SmrgdrmBufInfoPtr drmGetBufInfo(int fd)
115522944501Smrg{
115622944501Smrg    drm_buf_info_t info;
115722944501Smrg    drmBufInfoPtr  retval;
115822944501Smrg    int            i;
115922944501Smrg
116022944501Smrg    info.count = 0;
116122944501Smrg    info.list  = NULL;
116222944501Smrg
116322944501Smrg    if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info))
116422944501Smrg	return NULL;
116522944501Smrg
116622944501Smrg    if (info.count) {
116722944501Smrg	if (!(info.list = drmMalloc(info.count * sizeof(*info.list))))
116822944501Smrg	    return NULL;
116922944501Smrg
117022944501Smrg	if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info)) {
117122944501Smrg	    drmFree(info.list);
117222944501Smrg	    return NULL;
117322944501Smrg	}
117422944501Smrg
117522944501Smrg	retval = drmMalloc(sizeof(*retval));
117622944501Smrg	retval->count = info.count;
117722944501Smrg	retval->list  = drmMalloc(info.count * sizeof(*retval->list));
117822944501Smrg	for (i = 0; i < info.count; i++) {
117922944501Smrg	    retval->list[i].count     = info.list[i].count;
118022944501Smrg	    retval->list[i].size      = info.list[i].size;
118122944501Smrg	    retval->list[i].low_mark  = info.list[i].low_mark;
118222944501Smrg	    retval->list[i].high_mark = info.list[i].high_mark;
118322944501Smrg	}
118422944501Smrg	drmFree(info.list);
118522944501Smrg	return retval;
118622944501Smrg    }
118722944501Smrg    return NULL;
118822944501Smrg}
118922944501Smrg
119022944501Smrg/**
119122944501Smrg * Map all DMA buffers into client-virtual space.
119222944501Smrg *
119322944501Smrg * \param fd file descriptor.
119422944501Smrg *
119522944501Smrg * \return a pointer to a ::drmBufMap structure.
119622944501Smrg *
119722944501Smrg * \note The client may not use these buffers until obtaining buffer indices
119822944501Smrg * with drmDMA().
119922944501Smrg *
120022944501Smrg * \internal
120122944501Smrg * This function calls the DRM_IOCTL_MAP_BUFS ioctl and copies the returned
120222944501Smrg * information about the buffers in a drm_buf_map structure into the
120322944501Smrg * client-visible data structures.
120422944501Smrg */
120522944501SmrgdrmBufMapPtr drmMapBufs(int fd)
120622944501Smrg{
120722944501Smrg    drm_buf_map_t bufs;
120822944501Smrg    drmBufMapPtr  retval;
120922944501Smrg    int           i;
121022944501Smrg
121122944501Smrg    bufs.count = 0;
121222944501Smrg    bufs.list  = NULL;
121322944501Smrg    bufs.virtual = NULL;
121422944501Smrg    if (drmIoctl(fd, DRM_IOCTL_MAP_BUFS, &bufs))
121522944501Smrg	return NULL;
121622944501Smrg
121722944501Smrg    if (!bufs.count)
121822944501Smrg	return NULL;
121922944501Smrg
122022944501Smrg	if (!(bufs.list = drmMalloc(bufs.count * sizeof(*bufs.list))))
122122944501Smrg	    return NULL;
122222944501Smrg
122322944501Smrg	if (drmIoctl(fd, DRM_IOCTL_MAP_BUFS, &bufs)) {
122422944501Smrg	    drmFree(bufs.list);
122522944501Smrg	    return NULL;
122622944501Smrg	}
122722944501Smrg
122822944501Smrg	retval = drmMalloc(sizeof(*retval));
122922944501Smrg	retval->count = bufs.count;
123022944501Smrg	retval->list  = drmMalloc(bufs.count * sizeof(*retval->list));
123122944501Smrg	for (i = 0; i < bufs.count; i++) {
123222944501Smrg	    retval->list[i].idx     = bufs.list[i].idx;
123322944501Smrg	    retval->list[i].total   = bufs.list[i].total;
123422944501Smrg	    retval->list[i].used    = 0;
123522944501Smrg	    retval->list[i].address = bufs.list[i].address;
123622944501Smrg	}
123722944501Smrg
123822944501Smrg	drmFree(bufs.list);
123922944501Smrg
124022944501Smrg	return retval;
124122944501Smrg}
124222944501Smrg
124322944501Smrg
124422944501Smrg/**
124522944501Smrg * Unmap buffers allocated with drmMapBufs().
124622944501Smrg *
124722944501Smrg * \return zero on success, or negative value on failure.
124822944501Smrg *
124922944501Smrg * \internal
125022944501Smrg * Calls munmap() for every buffer stored in \p bufs and frees the
125122944501Smrg * memory allocated by drmMapBufs().
125222944501Smrg */
125322944501Smrgint drmUnmapBufs(drmBufMapPtr bufs)
125422944501Smrg{
125522944501Smrg    int i;
125622944501Smrg
125722944501Smrg    for (i = 0; i < bufs->count; i++) {
125822944501Smrg	munmap(bufs->list[i].address, bufs->list[i].total);
125922944501Smrg    }
126022944501Smrg
126122944501Smrg    drmFree(bufs->list);
126222944501Smrg    drmFree(bufs);
126322944501Smrg
126422944501Smrg    return 0;
126522944501Smrg}
126622944501Smrg
126722944501Smrg
126822944501Smrg#define DRM_DMA_RETRY		16
126922944501Smrg
127022944501Smrg/**
127122944501Smrg * Reserve DMA buffers.
127222944501Smrg *
127322944501Smrg * \param fd file descriptor.
127422944501Smrg * \param request
127522944501Smrg *
127622944501Smrg * \return zero on success, or a negative value on failure.
127722944501Smrg *
127822944501Smrg * \internal
127922944501Smrg * Assemble the arguments into a drm_dma structure and keeps issuing the
128022944501Smrg * DRM_IOCTL_DMA ioctl until success or until maximum number of retries.
128122944501Smrg */
128222944501Smrgint drmDMA(int fd, drmDMAReqPtr request)
128322944501Smrg{
128422944501Smrg    drm_dma_t dma;
128522944501Smrg    int ret, i = 0;
128622944501Smrg
128722944501Smrg    dma.context         = request->context;
128822944501Smrg    dma.send_count      = request->send_count;
128922944501Smrg    dma.send_indices    = request->send_list;
129022944501Smrg    dma.send_sizes      = request->send_sizes;
129122944501Smrg    dma.flags           = request->flags;
129222944501Smrg    dma.request_count   = request->request_count;
129322944501Smrg    dma.request_size    = request->request_size;
129422944501Smrg    dma.request_indices = request->request_list;
129522944501Smrg    dma.request_sizes   = request->request_sizes;
129622944501Smrg    dma.granted_count   = 0;
129722944501Smrg
129822944501Smrg    do {
129922944501Smrg	ret = ioctl( fd, DRM_IOCTL_DMA, &dma );
130022944501Smrg    } while ( ret && errno == EAGAIN && i++ < DRM_DMA_RETRY );
130122944501Smrg
130222944501Smrg    if ( ret == 0 ) {
130322944501Smrg	request->granted_count = dma.granted_count;
130422944501Smrg	return 0;
130522944501Smrg    } else {
130622944501Smrg	return -errno;
130722944501Smrg    }
130822944501Smrg}
130922944501Smrg
131022944501Smrg
131122944501Smrg/**
131222944501Smrg * Obtain heavyweight hardware lock.
131322944501Smrg *
131422944501Smrg * \param fd file descriptor.
131522944501Smrg * \param context context.
131622944501Smrg * \param flags flags that determine the sate of the hardware when the function
131722944501Smrg * returns.
131822944501Smrg *
131922944501Smrg * \return always zero.
132022944501Smrg *
132122944501Smrg * \internal
132222944501Smrg * This function translates the arguments into a drm_lock structure and issue
132322944501Smrg * the DRM_IOCTL_LOCK ioctl until the lock is successfully acquired.
132422944501Smrg */
132522944501Smrgint drmGetLock(int fd, drm_context_t context, drmLockFlags flags)
132622944501Smrg{
132722944501Smrg    drm_lock_t lock;
132822944501Smrg
132922944501Smrg    lock.context = context;
133022944501Smrg    lock.flags   = 0;
133122944501Smrg    if (flags & DRM_LOCK_READY)      lock.flags |= _DRM_LOCK_READY;
133222944501Smrg    if (flags & DRM_LOCK_QUIESCENT)  lock.flags |= _DRM_LOCK_QUIESCENT;
133322944501Smrg    if (flags & DRM_LOCK_FLUSH)      lock.flags |= _DRM_LOCK_FLUSH;
133422944501Smrg    if (flags & DRM_LOCK_FLUSH_ALL)  lock.flags |= _DRM_LOCK_FLUSH_ALL;
133522944501Smrg    if (flags & DRM_HALT_ALL_QUEUES) lock.flags |= _DRM_HALT_ALL_QUEUES;
133622944501Smrg    if (flags & DRM_HALT_CUR_QUEUES) lock.flags |= _DRM_HALT_CUR_QUEUES;
133722944501Smrg
133822944501Smrg    while (drmIoctl(fd, DRM_IOCTL_LOCK, &lock))
133922944501Smrg	;
134022944501Smrg    return 0;
134122944501Smrg}
134222944501Smrg
134322944501Smrg/**
134422944501Smrg * Release the hardware lock.
134522944501Smrg *
134622944501Smrg * \param fd file descriptor.
134722944501Smrg * \param context context.
134822944501Smrg *
134922944501Smrg * \return zero on success, or a negative value on failure.
135022944501Smrg *
135122944501Smrg * \internal
135222944501Smrg * This function is a wrapper around the DRM_IOCTL_UNLOCK ioctl, passing the
135322944501Smrg * argument in a drm_lock structure.
135422944501Smrg */
135522944501Smrgint drmUnlock(int fd, drm_context_t context)
135622944501Smrg{
135722944501Smrg    drm_lock_t lock;
135822944501Smrg
135922944501Smrg    lock.context = context;
136022944501Smrg    lock.flags   = 0;
136122944501Smrg    return drmIoctl(fd, DRM_IOCTL_UNLOCK, &lock);
136222944501Smrg}
136322944501Smrg
136422944501Smrgdrm_context_t *drmGetReservedContextList(int fd, int *count)
136522944501Smrg{
136622944501Smrg    drm_ctx_res_t res;
136722944501Smrg    drm_ctx_t     *list;
136822944501Smrg    drm_context_t * retval;
136922944501Smrg    int           i;
137022944501Smrg
137122944501Smrg    res.count    = 0;
137222944501Smrg    res.contexts = NULL;
137322944501Smrg    if (drmIoctl(fd, DRM_IOCTL_RES_CTX, &res))
137422944501Smrg	return NULL;
137522944501Smrg
137622944501Smrg    if (!res.count)
137722944501Smrg	return NULL;
137822944501Smrg
137922944501Smrg    if (!(list   = drmMalloc(res.count * sizeof(*list))))
138022944501Smrg	return NULL;
138122944501Smrg    if (!(retval = drmMalloc(res.count * sizeof(*retval)))) {
138222944501Smrg	drmFree(list);
138322944501Smrg	return NULL;
138422944501Smrg    }
138522944501Smrg
138622944501Smrg    res.contexts = list;
138722944501Smrg    if (drmIoctl(fd, DRM_IOCTL_RES_CTX, &res))
138822944501Smrg	return NULL;
138922944501Smrg
139022944501Smrg    for (i = 0; i < res.count; i++)
139122944501Smrg	retval[i] = list[i].handle;
139222944501Smrg    drmFree(list);
139322944501Smrg
139422944501Smrg    *count = res.count;
139522944501Smrg    return retval;
139622944501Smrg}
139722944501Smrg
139822944501Smrgvoid drmFreeReservedContextList(drm_context_t *pt)
139922944501Smrg{
140022944501Smrg    drmFree(pt);
140122944501Smrg}
140222944501Smrg
140322944501Smrg/**
140422944501Smrg * Create context.
140522944501Smrg *
140622944501Smrg * Used by the X server during GLXContext initialization. This causes
140722944501Smrg * per-context kernel-level resources to be allocated.
140822944501Smrg *
140922944501Smrg * \param fd file descriptor.
141022944501Smrg * \param handle is set on success. To be used by the client when requesting DMA
141122944501Smrg * dispatch with drmDMA().
141222944501Smrg *
141322944501Smrg * \return zero on success, or a negative value on failure.
141422944501Smrg *
141522944501Smrg * \note May only be called by root.
141622944501Smrg *
141722944501Smrg * \internal
141822944501Smrg * This function is a wrapper around the DRM_IOCTL_ADD_CTX ioctl, passing the
141922944501Smrg * argument in a drm_ctx structure.
142022944501Smrg */
142122944501Smrgint drmCreateContext(int fd, drm_context_t *handle)
142222944501Smrg{
142322944501Smrg    drm_ctx_t ctx;
142422944501Smrg
142522944501Smrg    ctx.flags = 0;	/* Modified with functions below */
142622944501Smrg    if (drmIoctl(fd, DRM_IOCTL_ADD_CTX, &ctx))
142722944501Smrg	return -errno;
142822944501Smrg    *handle = ctx.handle;
142922944501Smrg    return 0;
143022944501Smrg}
143122944501Smrg
143222944501Smrgint drmSwitchToContext(int fd, drm_context_t context)
143322944501Smrg{
143422944501Smrg    drm_ctx_t ctx;
143522944501Smrg
143622944501Smrg    ctx.handle = context;
143722944501Smrg    if (drmIoctl(fd, DRM_IOCTL_SWITCH_CTX, &ctx))
143822944501Smrg	return -errno;
143922944501Smrg    return 0;
144022944501Smrg}
144122944501Smrg
144222944501Smrgint drmSetContextFlags(int fd, drm_context_t context, drm_context_tFlags flags)
144322944501Smrg{
144422944501Smrg    drm_ctx_t ctx;
144522944501Smrg
144622944501Smrg    /*
144722944501Smrg     * Context preserving means that no context switches are done between DMA
144822944501Smrg     * buffers from one context and the next.  This is suitable for use in the
144922944501Smrg     * X server (which promises to maintain hardware context), or in the
145022944501Smrg     * client-side library when buffers are swapped on behalf of two threads.
145122944501Smrg     */
145222944501Smrg    ctx.handle = context;
145322944501Smrg    ctx.flags  = 0;
145422944501Smrg    if (flags & DRM_CONTEXT_PRESERVED)
145522944501Smrg	ctx.flags |= _DRM_CONTEXT_PRESERVED;
145622944501Smrg    if (flags & DRM_CONTEXT_2DONLY)
145722944501Smrg	ctx.flags |= _DRM_CONTEXT_2DONLY;
145822944501Smrg    if (drmIoctl(fd, DRM_IOCTL_MOD_CTX, &ctx))
145922944501Smrg	return -errno;
146022944501Smrg    return 0;
146122944501Smrg}
146222944501Smrg
146322944501Smrgint drmGetContextFlags(int fd, drm_context_t context,
146422944501Smrg                       drm_context_tFlagsPtr flags)
146522944501Smrg{
146622944501Smrg    drm_ctx_t ctx;
146722944501Smrg
146822944501Smrg    ctx.handle = context;
146922944501Smrg    if (drmIoctl(fd, DRM_IOCTL_GET_CTX, &ctx))
147022944501Smrg	return -errno;
147122944501Smrg    *flags = 0;
147222944501Smrg    if (ctx.flags & _DRM_CONTEXT_PRESERVED)
147322944501Smrg	*flags |= DRM_CONTEXT_PRESERVED;
147422944501Smrg    if (ctx.flags & _DRM_CONTEXT_2DONLY)
147522944501Smrg	*flags |= DRM_CONTEXT_2DONLY;
147622944501Smrg    return 0;
147722944501Smrg}
147822944501Smrg
147922944501Smrg/**
148022944501Smrg * Destroy context.
148122944501Smrg *
148222944501Smrg * Free any kernel-level resources allocated with drmCreateContext() associated
148322944501Smrg * with the context.
148422944501Smrg *
148522944501Smrg * \param fd file descriptor.
148622944501Smrg * \param handle handle given by drmCreateContext().
148722944501Smrg *
148822944501Smrg * \return zero on success, or a negative value on failure.
148922944501Smrg *
149022944501Smrg * \note May only be called by root.
149122944501Smrg *
149222944501Smrg * \internal
149322944501Smrg * This function is a wrapper around the DRM_IOCTL_RM_CTX ioctl, passing the
149422944501Smrg * argument in a drm_ctx structure.
149522944501Smrg */
149622944501Smrgint drmDestroyContext(int fd, drm_context_t handle)
149722944501Smrg{
149822944501Smrg    drm_ctx_t ctx;
149922944501Smrg    ctx.handle = handle;
150022944501Smrg    if (drmIoctl(fd, DRM_IOCTL_RM_CTX, &ctx))
150122944501Smrg	return -errno;
150222944501Smrg    return 0;
150322944501Smrg}
150422944501Smrg
150522944501Smrgint drmCreateDrawable(int fd, drm_drawable_t *handle)
150622944501Smrg{
150722944501Smrg    drm_draw_t draw;
150822944501Smrg    if (drmIoctl(fd, DRM_IOCTL_ADD_DRAW, &draw))
150922944501Smrg	return -errno;
151022944501Smrg    *handle = draw.handle;
151122944501Smrg    return 0;
151222944501Smrg}
151322944501Smrg
151422944501Smrgint drmDestroyDrawable(int fd, drm_drawable_t handle)
151522944501Smrg{
151622944501Smrg    drm_draw_t draw;
151722944501Smrg    draw.handle = handle;
151822944501Smrg    if (drmIoctl(fd, DRM_IOCTL_RM_DRAW, &draw))
151922944501Smrg	return -errno;
152022944501Smrg    return 0;
152122944501Smrg}
152222944501Smrg
152322944501Smrgint drmUpdateDrawableInfo(int fd, drm_drawable_t handle,
152422944501Smrg			   drm_drawable_info_type_t type, unsigned int num,
152522944501Smrg			   void *data)
152622944501Smrg{
152722944501Smrg    drm_update_draw_t update;
152822944501Smrg
152922944501Smrg    update.handle = handle;
153022944501Smrg    update.type = type;
153122944501Smrg    update.num = num;
153222944501Smrg    update.data = (unsigned long long)(unsigned long)data;
153322944501Smrg
153422944501Smrg    if (drmIoctl(fd, DRM_IOCTL_UPDATE_DRAW, &update))
153522944501Smrg	return -errno;
153622944501Smrg
153722944501Smrg    return 0;
153822944501Smrg}
153922944501Smrg
154022944501Smrg/**
154122944501Smrg * Acquire the AGP device.
154222944501Smrg *
154322944501Smrg * Must be called before any of the other AGP related calls.
154422944501Smrg *
154522944501Smrg * \param fd file descriptor.
154622944501Smrg *
154722944501Smrg * \return zero on success, or a negative value on failure.
154822944501Smrg *
154922944501Smrg * \internal
155022944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_ACQUIRE ioctl.
155122944501Smrg */
155222944501Smrgint drmAgpAcquire(int fd)
155322944501Smrg{
155422944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AGP_ACQUIRE, NULL))
155522944501Smrg	return -errno;
155622944501Smrg    return 0;
155722944501Smrg}
155822944501Smrg
155922944501Smrg
156022944501Smrg/**
156122944501Smrg * Release the AGP device.
156222944501Smrg *
156322944501Smrg * \param fd file descriptor.
156422944501Smrg *
156522944501Smrg * \return zero on success, or a negative value on failure.
156622944501Smrg *
156722944501Smrg * \internal
156822944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_RELEASE ioctl.
156922944501Smrg */
157022944501Smrgint drmAgpRelease(int fd)
157122944501Smrg{
157222944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AGP_RELEASE, NULL))
157322944501Smrg	return -errno;
157422944501Smrg    return 0;
157522944501Smrg}
157622944501Smrg
157722944501Smrg
157822944501Smrg/**
157922944501Smrg * Set the AGP mode.
158022944501Smrg *
158122944501Smrg * \param fd file descriptor.
158222944501Smrg * \param mode AGP mode.
158322944501Smrg *
158422944501Smrg * \return zero on success, or a negative value on failure.
158522944501Smrg *
158622944501Smrg * \internal
158722944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_ENABLE ioctl, passing the
158822944501Smrg * argument in a drm_agp_mode structure.
158922944501Smrg */
159022944501Smrgint drmAgpEnable(int fd, unsigned long mode)
159122944501Smrg{
159222944501Smrg    drm_agp_mode_t m;
159322944501Smrg
159422944501Smrg    m.mode = mode;
159522944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AGP_ENABLE, &m))
159622944501Smrg	return -errno;
159722944501Smrg    return 0;
159822944501Smrg}
159922944501Smrg
160022944501Smrg
160122944501Smrg/**
160222944501Smrg * Allocate a chunk of AGP memory.
160322944501Smrg *
160422944501Smrg * \param fd file descriptor.
160522944501Smrg * \param size requested memory size in bytes. Will be rounded to page boundary.
160622944501Smrg * \param type type of memory to allocate.
160722944501Smrg * \param address if not zero, will be set to the physical address of the
160822944501Smrg * allocated memory.
160922944501Smrg * \param handle on success will be set to a handle of the allocated memory.
161022944501Smrg *
161122944501Smrg * \return zero on success, or a negative value on failure.
161222944501Smrg *
161322944501Smrg * \internal
161422944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_ALLOC ioctl, passing the
161522944501Smrg * arguments in a drm_agp_buffer structure.
161622944501Smrg */
161722944501Smrgint drmAgpAlloc(int fd, unsigned long size, unsigned long type,
161822944501Smrg		unsigned long *address, drm_handle_t *handle)
161922944501Smrg{
162022944501Smrg    drm_agp_buffer_t b;
162122944501Smrg
162222944501Smrg    *handle = DRM_AGP_NO_HANDLE;
162322944501Smrg    b.size   = size;
162422944501Smrg    b.handle = 0;
162522944501Smrg    b.type   = type;
162622944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AGP_ALLOC, &b))
162722944501Smrg	return -errno;
162822944501Smrg    if (address != 0UL)
162922944501Smrg	*address = b.physical;
163022944501Smrg    *handle = b.handle;
163122944501Smrg    return 0;
163222944501Smrg}
163322944501Smrg
163422944501Smrg
163522944501Smrg/**
163622944501Smrg * Free a chunk of AGP memory.
163722944501Smrg *
163822944501Smrg * \param fd file descriptor.
163922944501Smrg * \param handle handle to the allocated memory, as given by drmAgpAllocate().
164022944501Smrg *
164122944501Smrg * \return zero on success, or a negative value on failure.
164222944501Smrg *
164322944501Smrg * \internal
164422944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_FREE ioctl, passing the
164522944501Smrg * argument in a drm_agp_buffer structure.
164622944501Smrg */
164722944501Smrgint drmAgpFree(int fd, drm_handle_t handle)
164822944501Smrg{
164922944501Smrg    drm_agp_buffer_t b;
165022944501Smrg
165122944501Smrg    b.size   = 0;
165222944501Smrg    b.handle = handle;
165322944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AGP_FREE, &b))
165422944501Smrg	return -errno;
165522944501Smrg    return 0;
165622944501Smrg}
165722944501Smrg
165822944501Smrg
165922944501Smrg/**
166022944501Smrg * Bind a chunk of AGP memory.
166122944501Smrg *
166222944501Smrg * \param fd file descriptor.
166322944501Smrg * \param handle handle to the allocated memory, as given by drmAgpAllocate().
166422944501Smrg * \param offset offset in bytes. It will round to page boundary.
166522944501Smrg *
166622944501Smrg * \return zero on success, or a negative value on failure.
166722944501Smrg *
166822944501Smrg * \internal
166922944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_BIND ioctl, passing the
167022944501Smrg * argument in a drm_agp_binding structure.
167122944501Smrg */
167222944501Smrgint drmAgpBind(int fd, drm_handle_t handle, unsigned long offset)
167322944501Smrg{
167422944501Smrg    drm_agp_binding_t b;
167522944501Smrg
167622944501Smrg    b.handle = handle;
167722944501Smrg    b.offset = offset;
167822944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AGP_BIND, &b))
167922944501Smrg	return -errno;
168022944501Smrg    return 0;
168122944501Smrg}
168222944501Smrg
168322944501Smrg
168422944501Smrg/**
168522944501Smrg * Unbind a chunk of AGP memory.
168622944501Smrg *
168722944501Smrg * \param fd file descriptor.
168822944501Smrg * \param handle handle to the allocated memory, as given by drmAgpAllocate().
168922944501Smrg *
169022944501Smrg * \return zero on success, or a negative value on failure.
169122944501Smrg *
169222944501Smrg * \internal
169322944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_UNBIND ioctl, passing
169422944501Smrg * the argument in a drm_agp_binding structure.
169522944501Smrg */
169622944501Smrgint drmAgpUnbind(int fd, drm_handle_t handle)
169722944501Smrg{
169822944501Smrg    drm_agp_binding_t b;
169922944501Smrg
170022944501Smrg    b.handle = handle;
170122944501Smrg    b.offset = 0;
170222944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AGP_UNBIND, &b))
170322944501Smrg	return -errno;
170422944501Smrg    return 0;
170522944501Smrg}
170622944501Smrg
170722944501Smrg
170822944501Smrg/**
170922944501Smrg * Get AGP driver major version number.
171022944501Smrg *
171122944501Smrg * \param fd file descriptor.
171222944501Smrg *
171322944501Smrg * \return major version number on success, or a negative value on failure..
171422944501Smrg *
171522944501Smrg * \internal
171622944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
171722944501Smrg * necessary information in a drm_agp_info structure.
171822944501Smrg */
171922944501Smrgint drmAgpVersionMajor(int fd)
172022944501Smrg{
172122944501Smrg    drm_agp_info_t i;
172222944501Smrg
172322944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
172422944501Smrg	return -errno;
172522944501Smrg    return i.agp_version_major;
172622944501Smrg}
172722944501Smrg
172822944501Smrg
172922944501Smrg/**
173022944501Smrg * Get AGP driver minor version number.
173122944501Smrg *
173222944501Smrg * \param fd file descriptor.
173322944501Smrg *
173422944501Smrg * \return minor version number on success, or a negative value on failure.
173522944501Smrg *
173622944501Smrg * \internal
173722944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
173822944501Smrg * necessary information in a drm_agp_info structure.
173922944501Smrg */
174022944501Smrgint drmAgpVersionMinor(int fd)
174122944501Smrg{
174222944501Smrg    drm_agp_info_t i;
174322944501Smrg
174422944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
174522944501Smrg	return -errno;
174622944501Smrg    return i.agp_version_minor;
174722944501Smrg}
174822944501Smrg
174922944501Smrg
175022944501Smrg/**
175122944501Smrg * Get AGP mode.
175222944501Smrg *
175322944501Smrg * \param fd file descriptor.
175422944501Smrg *
175522944501Smrg * \return mode on success, or zero on failure.
175622944501Smrg *
175722944501Smrg * \internal
175822944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
175922944501Smrg * necessary information in a drm_agp_info structure.
176022944501Smrg */
176122944501Smrgunsigned long drmAgpGetMode(int fd)
176222944501Smrg{
176322944501Smrg    drm_agp_info_t i;
176422944501Smrg
176522944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
176622944501Smrg	return 0;
176722944501Smrg    return i.mode;
176822944501Smrg}
176922944501Smrg
177022944501Smrg
177122944501Smrg/**
177222944501Smrg * Get AGP aperture base.
177322944501Smrg *
177422944501Smrg * \param fd file descriptor.
177522944501Smrg *
177622944501Smrg * \return aperture base on success, zero on failure.
177722944501Smrg *
177822944501Smrg * \internal
177922944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
178022944501Smrg * necessary information in a drm_agp_info structure.
178122944501Smrg */
178222944501Smrgunsigned long drmAgpBase(int fd)
178322944501Smrg{
178422944501Smrg    drm_agp_info_t i;
178522944501Smrg
178622944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
178722944501Smrg	return 0;
178822944501Smrg    return i.aperture_base;
178922944501Smrg}
179022944501Smrg
179122944501Smrg
179222944501Smrg/**
179322944501Smrg * Get AGP aperture size.
179422944501Smrg *
179522944501Smrg * \param fd file descriptor.
179622944501Smrg *
179722944501Smrg * \return aperture size on success, zero on failure.
179822944501Smrg *
179922944501Smrg * \internal
180022944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
180122944501Smrg * necessary information in a drm_agp_info structure.
180222944501Smrg */
180322944501Smrgunsigned long drmAgpSize(int fd)
180422944501Smrg{
180522944501Smrg    drm_agp_info_t i;
180622944501Smrg
180722944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
180822944501Smrg	return 0;
180922944501Smrg    return i.aperture_size;
181022944501Smrg}
181122944501Smrg
181222944501Smrg
181322944501Smrg/**
181422944501Smrg * Get used AGP memory.
181522944501Smrg *
181622944501Smrg * \param fd file descriptor.
181722944501Smrg *
181822944501Smrg * \return memory used on success, or zero on failure.
181922944501Smrg *
182022944501Smrg * \internal
182122944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
182222944501Smrg * necessary information in a drm_agp_info structure.
182322944501Smrg */
182422944501Smrgunsigned long drmAgpMemoryUsed(int fd)
182522944501Smrg{
182622944501Smrg    drm_agp_info_t i;
182722944501Smrg
182822944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
182922944501Smrg	return 0;
183022944501Smrg    return i.memory_used;
183122944501Smrg}
183222944501Smrg
183322944501Smrg
183422944501Smrg/**
183522944501Smrg * Get available AGP memory.
183622944501Smrg *
183722944501Smrg * \param fd file descriptor.
183822944501Smrg *
183922944501Smrg * \return memory available on success, or zero on failure.
184022944501Smrg *
184122944501Smrg * \internal
184222944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
184322944501Smrg * necessary information in a drm_agp_info structure.
184422944501Smrg */
184522944501Smrgunsigned long drmAgpMemoryAvail(int fd)
184622944501Smrg{
184722944501Smrg    drm_agp_info_t i;
184822944501Smrg
184922944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
185022944501Smrg	return 0;
185122944501Smrg    return i.memory_allowed;
185222944501Smrg}
185322944501Smrg
185422944501Smrg
185522944501Smrg/**
185622944501Smrg * Get hardware vendor ID.
185722944501Smrg *
185822944501Smrg * \param fd file descriptor.
185922944501Smrg *
186022944501Smrg * \return vendor ID on success, or zero on failure.
186122944501Smrg *
186222944501Smrg * \internal
186322944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
186422944501Smrg * necessary information in a drm_agp_info structure.
186522944501Smrg */
186622944501Smrgunsigned int drmAgpVendorId(int fd)
186722944501Smrg{
186822944501Smrg    drm_agp_info_t i;
186922944501Smrg
187022944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
187122944501Smrg	return 0;
187222944501Smrg    return i.id_vendor;
187322944501Smrg}
187422944501Smrg
187522944501Smrg
187622944501Smrg/**
187722944501Smrg * Get hardware device ID.
187822944501Smrg *
187922944501Smrg * \param fd file descriptor.
188022944501Smrg *
188122944501Smrg * \return zero on success, or zero on failure.
188222944501Smrg *
188322944501Smrg * \internal
188422944501Smrg * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
188522944501Smrg * necessary information in a drm_agp_info structure.
188622944501Smrg */
188722944501Smrgunsigned int drmAgpDeviceId(int fd)
188822944501Smrg{
188922944501Smrg    drm_agp_info_t i;
189022944501Smrg
189122944501Smrg    if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i))
189222944501Smrg	return 0;
189322944501Smrg    return i.id_device;
189422944501Smrg}
189522944501Smrg
189622944501Smrgint drmScatterGatherAlloc(int fd, unsigned long size, drm_handle_t *handle)
189722944501Smrg{
189822944501Smrg    drm_scatter_gather_t sg;
189922944501Smrg
190022944501Smrg    *handle = 0;
190122944501Smrg    sg.size   = size;
190222944501Smrg    sg.handle = 0;
190322944501Smrg    if (drmIoctl(fd, DRM_IOCTL_SG_ALLOC, &sg))
190422944501Smrg	return -errno;
190522944501Smrg    *handle = sg.handle;
190622944501Smrg    return 0;
190722944501Smrg}
190822944501Smrg
190922944501Smrgint drmScatterGatherFree(int fd, drm_handle_t handle)
191022944501Smrg{
191122944501Smrg    drm_scatter_gather_t sg;
191222944501Smrg
191322944501Smrg    sg.size   = 0;
191422944501Smrg    sg.handle = handle;
191522944501Smrg    if (drmIoctl(fd, DRM_IOCTL_SG_FREE, &sg))
191622944501Smrg	return -errno;
191722944501Smrg    return 0;
191822944501Smrg}
191922944501Smrg
192022944501Smrg/**
192122944501Smrg * Wait for VBLANK.
192222944501Smrg *
192322944501Smrg * \param fd file descriptor.
192422944501Smrg * \param vbl pointer to a drmVBlank structure.
192522944501Smrg *
192622944501Smrg * \return zero on success, or a negative value on failure.
192722944501Smrg *
192822944501Smrg * \internal
192922944501Smrg * This function is a wrapper around the DRM_IOCTL_WAIT_VBLANK ioctl.
193022944501Smrg */
193122944501Smrgint drmWaitVBlank(int fd, drmVBlankPtr vbl)
193222944501Smrg{
193322944501Smrg    struct timespec timeout, cur;
193422944501Smrg    int ret;
193522944501Smrg
193622944501Smrg    ret = clock_gettime(CLOCK_MONOTONIC, &timeout);
193722944501Smrg    if (ret < 0) {
193822944501Smrg	fprintf(stderr, "clock_gettime failed: %s\n", strerror(ret));
193922944501Smrg	goto out;
194022944501Smrg    }
194122944501Smrg    timeout.tv_sec++;
194222944501Smrg
194322944501Smrg    do {
194422944501Smrg       ret = ioctl(fd, DRM_IOCTL_WAIT_VBLANK, vbl);
194522944501Smrg       vbl->request.type &= ~DRM_VBLANK_RELATIVE;
194622944501Smrg       if (ret && errno == EINTR) {
194722944501Smrg	       clock_gettime(CLOCK_MONOTONIC, &cur);
194822944501Smrg	       /* Timeout after 1s */
194922944501Smrg	       if (cur.tv_sec > timeout.tv_sec + 1 ||
195022944501Smrg		   (cur.tv_sec == timeout.tv_sec && cur.tv_nsec >=
195122944501Smrg		    timeout.tv_nsec)) {
195222944501Smrg		       errno = EBUSY;
195322944501Smrg		       ret = -1;
195422944501Smrg		       break;
195522944501Smrg	       }
195622944501Smrg       }
195722944501Smrg    } while (ret && errno == EINTR);
195822944501Smrg
195922944501Smrgout:
196022944501Smrg    return ret;
196122944501Smrg}
196222944501Smrg
196322944501Smrgint drmError(int err, const char *label)
196422944501Smrg{
196522944501Smrg    switch (err) {
196622944501Smrg    case DRM_ERR_NO_DEVICE:
196722944501Smrg	fprintf(stderr, "%s: no device\n", label);
196822944501Smrg	break;
196922944501Smrg    case DRM_ERR_NO_ACCESS:
197022944501Smrg	fprintf(stderr, "%s: no access\n", label);
197122944501Smrg	break;
197222944501Smrg    case DRM_ERR_NOT_ROOT:
197322944501Smrg	fprintf(stderr, "%s: not root\n", label);
197422944501Smrg	break;
197522944501Smrg    case DRM_ERR_INVALID:
197622944501Smrg	fprintf(stderr, "%s: invalid args\n", label);
197722944501Smrg	break;
197822944501Smrg    default:
197922944501Smrg	if (err < 0)
198022944501Smrg	    err = -err;
198122944501Smrg	fprintf( stderr, "%s: error %d (%s)\n", label, err, strerror(err) );
198222944501Smrg	break;
198322944501Smrg    }
198422944501Smrg
198522944501Smrg    return 1;
198622944501Smrg}
198722944501Smrg
198822944501Smrg/**
198922944501Smrg * Install IRQ handler.
199022944501Smrg *
199122944501Smrg * \param fd file descriptor.
199222944501Smrg * \param irq IRQ number.
199322944501Smrg *
199422944501Smrg * \return zero on success, or a negative value on failure.
199522944501Smrg *
199622944501Smrg * \internal
199722944501Smrg * This function is a wrapper around the DRM_IOCTL_CONTROL ioctl, passing the
199822944501Smrg * argument in a drm_control structure.
199922944501Smrg */
200022944501Smrgint drmCtlInstHandler(int fd, int irq)
200122944501Smrg{
200222944501Smrg    drm_control_t ctl;
200322944501Smrg
200422944501Smrg    ctl.func  = DRM_INST_HANDLER;
200522944501Smrg    ctl.irq   = irq;
200622944501Smrg    if (drmIoctl(fd, DRM_IOCTL_CONTROL, &ctl))
200722944501Smrg	return -errno;
200822944501Smrg    return 0;
200922944501Smrg}
201022944501Smrg
201122944501Smrg
201222944501Smrg/**
201322944501Smrg * Uninstall IRQ handler.
201422944501Smrg *
201522944501Smrg * \param fd file descriptor.
201622944501Smrg *
201722944501Smrg * \return zero on success, or a negative value on failure.
201822944501Smrg *
201922944501Smrg * \internal
202022944501Smrg * This function is a wrapper around the DRM_IOCTL_CONTROL ioctl, passing the
202122944501Smrg * argument in a drm_control structure.
202222944501Smrg */
202322944501Smrgint drmCtlUninstHandler(int fd)
202422944501Smrg{
202522944501Smrg    drm_control_t ctl;
202622944501Smrg
202722944501Smrg    ctl.func  = DRM_UNINST_HANDLER;
202822944501Smrg    ctl.irq   = 0;
202922944501Smrg    if (drmIoctl(fd, DRM_IOCTL_CONTROL, &ctl))
203022944501Smrg	return -errno;
203122944501Smrg    return 0;
203222944501Smrg}
203322944501Smrg
203422944501Smrgint drmFinish(int fd, int context, drmLockFlags flags)
203522944501Smrg{
203622944501Smrg    drm_lock_t lock;
203722944501Smrg
203822944501Smrg    lock.context = context;
203922944501Smrg    lock.flags   = 0;
204022944501Smrg    if (flags & DRM_LOCK_READY)      lock.flags |= _DRM_LOCK_READY;
204122944501Smrg    if (flags & DRM_LOCK_QUIESCENT)  lock.flags |= _DRM_LOCK_QUIESCENT;
204222944501Smrg    if (flags & DRM_LOCK_FLUSH)      lock.flags |= _DRM_LOCK_FLUSH;
204322944501Smrg    if (flags & DRM_LOCK_FLUSH_ALL)  lock.flags |= _DRM_LOCK_FLUSH_ALL;
204422944501Smrg    if (flags & DRM_HALT_ALL_QUEUES) lock.flags |= _DRM_HALT_ALL_QUEUES;
204522944501Smrg    if (flags & DRM_HALT_CUR_QUEUES) lock.flags |= _DRM_HALT_CUR_QUEUES;
204622944501Smrg    if (drmIoctl(fd, DRM_IOCTL_FINISH, &lock))
204722944501Smrg	return -errno;
204822944501Smrg    return 0;
204922944501Smrg}
205022944501Smrg
205122944501Smrg/**
205222944501Smrg * Get IRQ from bus ID.
205322944501Smrg *
205422944501Smrg * \param fd file descriptor.
205522944501Smrg * \param busnum bus number.
205622944501Smrg * \param devnum device number.
205722944501Smrg * \param funcnum function number.
205822944501Smrg *
205922944501Smrg * \return IRQ number on success, or a negative value on failure.
206022944501Smrg *
206122944501Smrg * \internal
206222944501Smrg * This function is a wrapper around the DRM_IOCTL_IRQ_BUSID ioctl, passing the
206322944501Smrg * arguments in a drm_irq_busid structure.
206422944501Smrg */
206522944501Smrgint drmGetInterruptFromBusID(int fd, int busnum, int devnum, int funcnum)
206622944501Smrg{
206722944501Smrg    drm_irq_busid_t p;
206822944501Smrg
206922944501Smrg    p.busnum  = busnum;
207022944501Smrg    p.devnum  = devnum;
207122944501Smrg    p.funcnum = funcnum;
207222944501Smrg    if (drmIoctl(fd, DRM_IOCTL_IRQ_BUSID, &p))
207322944501Smrg	return -errno;
207422944501Smrg    return p.irq;
207522944501Smrg}
207622944501Smrg
207722944501Smrgint drmAddContextTag(int fd, drm_context_t context, void *tag)
207822944501Smrg{
207922944501Smrg    drmHashEntry  *entry = drmGetEntry(fd);
208022944501Smrg
208122944501Smrg    if (drmHashInsert(entry->tagTable, context, tag)) {
208222944501Smrg	drmHashDelete(entry->tagTable, context);
208322944501Smrg	drmHashInsert(entry->tagTable, context, tag);
208422944501Smrg    }
208522944501Smrg    return 0;
208622944501Smrg}
208722944501Smrg
208822944501Smrgint drmDelContextTag(int fd, drm_context_t context)
208922944501Smrg{
209022944501Smrg    drmHashEntry  *entry = drmGetEntry(fd);
209122944501Smrg
209222944501Smrg    return drmHashDelete(entry->tagTable, context);
209322944501Smrg}
209422944501Smrg
209522944501Smrgvoid *drmGetContextTag(int fd, drm_context_t context)
209622944501Smrg{
209722944501Smrg    drmHashEntry  *entry = drmGetEntry(fd);
209822944501Smrg    void          *value;
209922944501Smrg
210022944501Smrg    if (drmHashLookup(entry->tagTable, context, &value))
210122944501Smrg	return NULL;
210222944501Smrg
210322944501Smrg    return value;
210422944501Smrg}
210522944501Smrg
210622944501Smrgint drmAddContextPrivateMapping(int fd, drm_context_t ctx_id,
210722944501Smrg                                drm_handle_t handle)
210822944501Smrg{
210922944501Smrg    drm_ctx_priv_map_t map;
211022944501Smrg
211122944501Smrg    map.ctx_id = ctx_id;
211222944501Smrg    map.handle = (void *)handle;
211322944501Smrg
211422944501Smrg    if (drmIoctl(fd, DRM_IOCTL_SET_SAREA_CTX, &map))
211522944501Smrg	return -errno;
211622944501Smrg    return 0;
211722944501Smrg}
211822944501Smrg
211922944501Smrgint drmGetContextPrivateMapping(int fd, drm_context_t ctx_id,
212022944501Smrg                                drm_handle_t *handle)
212122944501Smrg{
212222944501Smrg    drm_ctx_priv_map_t map;
212322944501Smrg
212422944501Smrg    map.ctx_id = ctx_id;
212522944501Smrg
212622944501Smrg    if (drmIoctl(fd, DRM_IOCTL_GET_SAREA_CTX, &map))
212722944501Smrg	return -errno;
212822944501Smrg    if (handle)
212922944501Smrg	*handle = (drm_handle_t)map.handle;
213022944501Smrg
213122944501Smrg    return 0;
213222944501Smrg}
213322944501Smrg
213422944501Smrgint drmGetMap(int fd, int idx, drm_handle_t *offset, drmSize *size,
213522944501Smrg	      drmMapType *type, drmMapFlags *flags, drm_handle_t *handle,
213622944501Smrg	      int *mtrr)
213722944501Smrg{
213822944501Smrg    drm_map_t map;
213922944501Smrg
214022944501Smrg    map.offset = idx;
214122944501Smrg    if (drmIoctl(fd, DRM_IOCTL_GET_MAP, &map))
214222944501Smrg	return -errno;
214322944501Smrg    *offset = map.offset;
214422944501Smrg    *size   = map.size;
214522944501Smrg    *type   = map.type;
214622944501Smrg    *flags  = map.flags;
214722944501Smrg    *handle = (unsigned long)map.handle;
214822944501Smrg    *mtrr   = map.mtrr;
214922944501Smrg    return 0;
215022944501Smrg}
215122944501Smrg
215222944501Smrgint drmGetClient(int fd, int idx, int *auth, int *pid, int *uid,
215322944501Smrg		 unsigned long *magic, unsigned long *iocs)
215422944501Smrg{
215522944501Smrg    drm_client_t client;
215622944501Smrg
215722944501Smrg    client.idx = idx;
215822944501Smrg    if (drmIoctl(fd, DRM_IOCTL_GET_CLIENT, &client))
215922944501Smrg	return -errno;
216022944501Smrg    *auth      = client.auth;
216122944501Smrg    *pid       = client.pid;
216222944501Smrg    *uid       = client.uid;
216322944501Smrg    *magic     = client.magic;
216422944501Smrg    *iocs      = client.iocs;
216522944501Smrg    return 0;
216622944501Smrg}
216722944501Smrg
216822944501Smrgint drmGetStats(int fd, drmStatsT *stats)
216922944501Smrg{
217022944501Smrg    drm_stats_t s;
217122944501Smrg    int         i;
217222944501Smrg
217322944501Smrg    if (drmIoctl(fd, DRM_IOCTL_GET_STATS, &s))
217422944501Smrg	return -errno;
217522944501Smrg
217622944501Smrg    stats->count = 0;
217722944501Smrg    memset(stats, 0, sizeof(*stats));
217822944501Smrg    if (s.count > sizeof(stats->data)/sizeof(stats->data[0]))
217922944501Smrg	return -1;
218022944501Smrg
218122944501Smrg#define SET_VALUE                              \
218222944501Smrg    stats->data[i].long_format = "%-20.20s";   \
218322944501Smrg    stats->data[i].rate_format = "%8.8s";      \
218422944501Smrg    stats->data[i].isvalue     = 1;            \
218522944501Smrg    stats->data[i].verbose     = 0
218622944501Smrg
218722944501Smrg#define SET_COUNT                              \
218822944501Smrg    stats->data[i].long_format = "%-20.20s";   \
218922944501Smrg    stats->data[i].rate_format = "%5.5s";      \
219022944501Smrg    stats->data[i].isvalue     = 0;            \
219122944501Smrg    stats->data[i].mult_names  = "kgm";        \
219222944501Smrg    stats->data[i].mult        = 1000;         \
219322944501Smrg    stats->data[i].verbose     = 0
219422944501Smrg
219522944501Smrg#define SET_BYTE                               \
219622944501Smrg    stats->data[i].long_format = "%-20.20s";   \
219722944501Smrg    stats->data[i].rate_format = "%5.5s";      \
219822944501Smrg    stats->data[i].isvalue     = 0;            \
219922944501Smrg    stats->data[i].mult_names  = "KGM";        \
220022944501Smrg    stats->data[i].mult        = 1024;         \
220122944501Smrg    stats->data[i].verbose     = 0
220222944501Smrg
220322944501Smrg
220422944501Smrg    stats->count = s.count;
220522944501Smrg    for (i = 0; i < s.count; i++) {
220622944501Smrg	stats->data[i].value = s.data[i].value;
220722944501Smrg	switch (s.data[i].type) {
220822944501Smrg	case _DRM_STAT_LOCK:
220922944501Smrg	    stats->data[i].long_name = "Lock";
221022944501Smrg	    stats->data[i].rate_name = "Lock";
221122944501Smrg	    SET_VALUE;
221222944501Smrg	    break;
221322944501Smrg	case _DRM_STAT_OPENS:
221422944501Smrg	    stats->data[i].long_name = "Opens";
221522944501Smrg	    stats->data[i].rate_name = "O";
221622944501Smrg	    SET_COUNT;
221722944501Smrg	    stats->data[i].verbose   = 1;
221822944501Smrg	    break;
221922944501Smrg	case _DRM_STAT_CLOSES:
222022944501Smrg	    stats->data[i].long_name = "Closes";
222122944501Smrg	    stats->data[i].rate_name = "Lock";
222222944501Smrg	    SET_COUNT;
222322944501Smrg	    stats->data[i].verbose   = 1;
222422944501Smrg	    break;
222522944501Smrg	case _DRM_STAT_IOCTLS:
222622944501Smrg	    stats->data[i].long_name = "Ioctls";
222722944501Smrg	    stats->data[i].rate_name = "Ioc/s";
222822944501Smrg	    SET_COUNT;
222922944501Smrg	    break;
223022944501Smrg	case _DRM_STAT_LOCKS:
223122944501Smrg	    stats->data[i].long_name = "Locks";
223222944501Smrg	    stats->data[i].rate_name = "Lck/s";
223322944501Smrg	    SET_COUNT;
223422944501Smrg	    break;
223522944501Smrg	case _DRM_STAT_UNLOCKS:
223622944501Smrg	    stats->data[i].long_name = "Unlocks";
223722944501Smrg	    stats->data[i].rate_name = "Unl/s";
223822944501Smrg	    SET_COUNT;
223922944501Smrg	    break;
224022944501Smrg	case _DRM_STAT_IRQ:
224122944501Smrg	    stats->data[i].long_name = "IRQs";
224222944501Smrg	    stats->data[i].rate_name = "IRQ/s";
224322944501Smrg	    SET_COUNT;
224422944501Smrg	    break;
224522944501Smrg	case _DRM_STAT_PRIMARY:
224622944501Smrg	    stats->data[i].long_name = "Primary Bytes";
224722944501Smrg	    stats->data[i].rate_name = "PB/s";
224822944501Smrg	    SET_BYTE;
224922944501Smrg	    break;
225022944501Smrg	case _DRM_STAT_SECONDARY:
225122944501Smrg	    stats->data[i].long_name = "Secondary Bytes";
225222944501Smrg	    stats->data[i].rate_name = "SB/s";
225322944501Smrg	    SET_BYTE;
225422944501Smrg	    break;
225522944501Smrg	case _DRM_STAT_DMA:
225622944501Smrg	    stats->data[i].long_name = "DMA";
225722944501Smrg	    stats->data[i].rate_name = "DMA/s";
225822944501Smrg	    SET_COUNT;
225922944501Smrg	    break;
226022944501Smrg	case _DRM_STAT_SPECIAL:
226122944501Smrg	    stats->data[i].long_name = "Special DMA";
226222944501Smrg	    stats->data[i].rate_name = "dma/s";
226322944501Smrg	    SET_COUNT;
226422944501Smrg	    break;
226522944501Smrg	case _DRM_STAT_MISSED:
226622944501Smrg	    stats->data[i].long_name = "Miss";
226722944501Smrg	    stats->data[i].rate_name = "Ms/s";
226822944501Smrg	    SET_COUNT;
226922944501Smrg	    break;
227022944501Smrg	case _DRM_STAT_VALUE:
227122944501Smrg	    stats->data[i].long_name = "Value";
227222944501Smrg	    stats->data[i].rate_name = "Value";
227322944501Smrg	    SET_VALUE;
227422944501Smrg	    break;
227522944501Smrg	case _DRM_STAT_BYTE:
227622944501Smrg	    stats->data[i].long_name = "Bytes";
227722944501Smrg	    stats->data[i].rate_name = "B/s";
227822944501Smrg	    SET_BYTE;
227922944501Smrg	    break;
228022944501Smrg	case _DRM_STAT_COUNT:
228122944501Smrg	default:
228222944501Smrg	    stats->data[i].long_name = "Count";
228322944501Smrg	    stats->data[i].rate_name = "Cnt/s";
228422944501Smrg	    SET_COUNT;
228522944501Smrg	    break;
228622944501Smrg	}
228722944501Smrg    }
228822944501Smrg    return 0;
228922944501Smrg}
229022944501Smrg
229122944501Smrg/**
229222944501Smrg * Issue a set-version ioctl.
229322944501Smrg *
229422944501Smrg * \param fd file descriptor.
229522944501Smrg * \param drmCommandIndex command index
229622944501Smrg * \param data source pointer of the data to be read and written.
229722944501Smrg * \param size size of the data to be read and written.
229822944501Smrg *
229922944501Smrg * \return zero on success, or a negative value on failure.
230022944501Smrg *
230122944501Smrg * \internal
230222944501Smrg * It issues a read-write ioctl given by
230322944501Smrg * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
230422944501Smrg */
230522944501Smrgint drmSetInterfaceVersion(int fd, drmSetVersion *version)
230622944501Smrg{
230722944501Smrg    int retcode = 0;
230822944501Smrg    drm_set_version_t sv;
230922944501Smrg
231022944501Smrg    sv.drm_di_major = version->drm_di_major;
231122944501Smrg    sv.drm_di_minor = version->drm_di_minor;
231222944501Smrg    sv.drm_dd_major = version->drm_dd_major;
231322944501Smrg    sv.drm_dd_minor = version->drm_dd_minor;
231422944501Smrg
231522944501Smrg    if (drmIoctl(fd, DRM_IOCTL_SET_VERSION, &sv)) {
231622944501Smrg	retcode = -errno;
231722944501Smrg    }
231822944501Smrg
231922944501Smrg    version->drm_di_major = sv.drm_di_major;
232022944501Smrg    version->drm_di_minor = sv.drm_di_minor;
232122944501Smrg    version->drm_dd_major = sv.drm_dd_major;
232222944501Smrg    version->drm_dd_minor = sv.drm_dd_minor;
232322944501Smrg
232422944501Smrg    return retcode;
232522944501Smrg}
232622944501Smrg
232722944501Smrg/**
232822944501Smrg * Send a device-specific command.
232922944501Smrg *
233022944501Smrg * \param fd file descriptor.
233122944501Smrg * \param drmCommandIndex command index
233222944501Smrg *
233322944501Smrg * \return zero on success, or a negative value on failure.
233422944501Smrg *
233522944501Smrg * \internal
233622944501Smrg * It issues a ioctl given by
233722944501Smrg * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
233822944501Smrg */
233922944501Smrgint drmCommandNone(int fd, unsigned long drmCommandIndex)
234022944501Smrg{
234122944501Smrg    void *data = NULL; /* dummy */
234222944501Smrg    unsigned long request;
234322944501Smrg
234422944501Smrg    request = DRM_IO( DRM_COMMAND_BASE + drmCommandIndex);
234522944501Smrg
234622944501Smrg    if (drmIoctl(fd, request, data)) {
234722944501Smrg	return -errno;
234822944501Smrg    }
234922944501Smrg    return 0;
235022944501Smrg}
235122944501Smrg
235222944501Smrg
235322944501Smrg/**
235422944501Smrg * Send a device-specific read command.
235522944501Smrg *
235622944501Smrg * \param fd file descriptor.
235722944501Smrg * \param drmCommandIndex command index
235822944501Smrg * \param data destination pointer of the data to be read.
235922944501Smrg * \param size size of the data to be read.
236022944501Smrg *
236122944501Smrg * \return zero on success, or a negative value on failure.
236222944501Smrg *
236322944501Smrg * \internal
236422944501Smrg * It issues a read ioctl given by
236522944501Smrg * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
236622944501Smrg */
236722944501Smrgint drmCommandRead(int fd, unsigned long drmCommandIndex, void *data,
236822944501Smrg                   unsigned long size)
236922944501Smrg{
237022944501Smrg    unsigned long request;
237122944501Smrg
237222944501Smrg    request = DRM_IOC( DRM_IOC_READ, DRM_IOCTL_BASE,
237322944501Smrg	DRM_COMMAND_BASE + drmCommandIndex, size);
237422944501Smrg
237522944501Smrg    if (drmIoctl(fd, request, data)) {
237622944501Smrg	return -errno;
237722944501Smrg    }
237822944501Smrg    return 0;
237922944501Smrg}
238022944501Smrg
238122944501Smrg
238222944501Smrg/**
238322944501Smrg * Send a device-specific write command.
238422944501Smrg *
238522944501Smrg * \param fd file descriptor.
238622944501Smrg * \param drmCommandIndex command index
238722944501Smrg * \param data source pointer of the data to be written.
238822944501Smrg * \param size size of the data to be written.
238922944501Smrg *
239022944501Smrg * \return zero on success, or a negative value on failure.
239122944501Smrg *
239222944501Smrg * \internal
239322944501Smrg * It issues a write ioctl given by
239422944501Smrg * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
239522944501Smrg */
239622944501Smrgint drmCommandWrite(int fd, unsigned long drmCommandIndex, void *data,
239722944501Smrg                    unsigned long size)
239822944501Smrg{
239922944501Smrg    unsigned long request;
240022944501Smrg
240122944501Smrg    request = DRM_IOC( DRM_IOC_WRITE, DRM_IOCTL_BASE,
240222944501Smrg	DRM_COMMAND_BASE + drmCommandIndex, size);
240322944501Smrg
240422944501Smrg    if (drmIoctl(fd, request, data)) {
240522944501Smrg	return -errno;
240622944501Smrg    }
240722944501Smrg    return 0;
240822944501Smrg}
240922944501Smrg
241022944501Smrg
241122944501Smrg/**
241222944501Smrg * Send a device-specific read-write command.
241322944501Smrg *
241422944501Smrg * \param fd file descriptor.
241522944501Smrg * \param drmCommandIndex command index
241622944501Smrg * \param data source pointer of the data to be read and written.
241722944501Smrg * \param size size of the data to be read and written.
241822944501Smrg *
241922944501Smrg * \return zero on success, or a negative value on failure.
242022944501Smrg *
242122944501Smrg * \internal
242222944501Smrg * It issues a read-write ioctl given by
242322944501Smrg * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
242422944501Smrg */
242522944501Smrgint drmCommandWriteRead(int fd, unsigned long drmCommandIndex, void *data,
242622944501Smrg                        unsigned long size)
242722944501Smrg{
242822944501Smrg    unsigned long request;
242922944501Smrg
243022944501Smrg    request = DRM_IOC( DRM_IOC_READ|DRM_IOC_WRITE, DRM_IOCTL_BASE,
243122944501Smrg	DRM_COMMAND_BASE + drmCommandIndex, size);
243222944501Smrg
243322944501Smrg    if (drmIoctl(fd, request, data))
243422944501Smrg	return -errno;
243522944501Smrg    return 0;
243622944501Smrg}
243722944501Smrg
243822944501Smrg#define DRM_MAX_FDS 16
243922944501Smrgstatic struct {
244022944501Smrg    char *BusID;
244122944501Smrg    int fd;
244222944501Smrg    int refcount;
244322944501Smrg} connection[DRM_MAX_FDS];
244422944501Smrg
244522944501Smrgstatic int nr_fds = 0;
244622944501Smrg
244722944501Smrgint drmOpenOnce(void *unused,
244822944501Smrg		const char *BusID,
244922944501Smrg		int *newlyopened)
245022944501Smrg{
245122944501Smrg    int i;
245222944501Smrg    int fd;
245322944501Smrg
245422944501Smrg    for (i = 0; i < nr_fds; i++)
245522944501Smrg	if (strcmp(BusID, connection[i].BusID) == 0) {
245622944501Smrg	    connection[i].refcount++;
245722944501Smrg	    *newlyopened = 0;
245822944501Smrg	    return connection[i].fd;
245922944501Smrg	}
246022944501Smrg
246122944501Smrg    fd = drmOpen(unused, BusID);
246222944501Smrg    if (fd <= 0 || nr_fds == DRM_MAX_FDS)
246322944501Smrg	return fd;
246422944501Smrg
246522944501Smrg    connection[nr_fds].BusID = strdup(BusID);
246622944501Smrg    connection[nr_fds].fd = fd;
246722944501Smrg    connection[nr_fds].refcount = 1;
246822944501Smrg    *newlyopened = 1;
246922944501Smrg
247022944501Smrg    if (0)
247122944501Smrg	fprintf(stderr, "saved connection %d for %s %d\n",
247222944501Smrg		nr_fds, connection[nr_fds].BusID,
247322944501Smrg		strcmp(BusID, connection[nr_fds].BusID));
247422944501Smrg
247522944501Smrg    nr_fds++;
247622944501Smrg
247722944501Smrg    return fd;
247822944501Smrg}
247922944501Smrg
248022944501Smrgvoid drmCloseOnce(int fd)
248122944501Smrg{
248222944501Smrg    int i;
248322944501Smrg
248422944501Smrg    for (i = 0; i < nr_fds; i++) {
248522944501Smrg	if (fd == connection[i].fd) {
248622944501Smrg	    if (--connection[i].refcount == 0) {
248722944501Smrg		drmClose(connection[i].fd);
248822944501Smrg		free(connection[i].BusID);
248922944501Smrg
249022944501Smrg		if (i < --nr_fds)
249122944501Smrg		    connection[i] = connection[nr_fds];
249222944501Smrg
249322944501Smrg		return;
249422944501Smrg	    }
249522944501Smrg	}
249622944501Smrg    }
249722944501Smrg}
249822944501Smrg
249922944501Smrgint drmSetMaster(int fd)
250022944501Smrg{
250122944501Smrg	return ioctl(fd, DRM_IOCTL_SET_MASTER, 0);
250222944501Smrg}
250322944501Smrg
250422944501Smrgint drmDropMaster(int fd)
250522944501Smrg{
250622944501Smrg	return ioctl(fd, DRM_IOCTL_DROP_MASTER, 0);
250722944501Smrg}
250822944501Smrg
250922944501Smrgchar *drmGetDeviceNameFromFd(int fd)
251022944501Smrg{
251122944501Smrg	char name[128];
251222944501Smrg	struct stat sbuf;
251322944501Smrg	dev_t d;
251422944501Smrg	int i;
251522944501Smrg
251622944501Smrg	/* The whole drmOpen thing is a fiasco and we need to find a way
251722944501Smrg	 * back to just using open(2).  For now, however, lets just make
251822944501Smrg	 * things worse with even more ad hoc directory walking code to
251922944501Smrg	 * discover the device file name. */
252022944501Smrg
252122944501Smrg	fstat(fd, &sbuf);
252222944501Smrg	d = sbuf.st_rdev;
252322944501Smrg
252422944501Smrg	for (i = 0; i < DRM_MAX_MINOR; i++) {
252522944501Smrg		snprintf(name, sizeof name, DRM_DEV_NAME, DRM_DIR_NAME, i);
252622944501Smrg		if (stat(name, &sbuf) == 0 && sbuf.st_rdev == d)
252722944501Smrg			break;
252822944501Smrg	}
252922944501Smrg	if (i == DRM_MAX_MINOR)
253022944501Smrg		return NULL;
253122944501Smrg
25329ce4edccSmrg	return strdup(name);
253322944501Smrg}
2534