diff options
author | Reinhard Tartler <siretart@tauware.de> | 2011-10-10 17:43:39 +0200 |
---|---|---|
committer | Reinhard Tartler <siretart@tauware.de> | 2011-10-10 17:43:39 +0200 |
commit | f4092abdf94af6a99aff944d6264bc1284e8bdd4 (patch) | |
tree | 2ac1c9cc16ceb93edb2c4382c088dac5aeafdf0f /nx-X11/extras/drm/libdrm | |
parent | a840692edc9c6d19cd7c057f68e39c7d95eb767d (diff) | |
download | nx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.tar.gz nx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.tar.bz2 nx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.zip |
Imported nx-X11-3.1.0-1.tar.gznx-X11/3.1.0-1
Summary: Imported nx-X11-3.1.0-1.tar.gz
Keywords:
Imported nx-X11-3.1.0-1.tar.gz
into Git repository
Diffstat (limited to 'nx-X11/extras/drm/libdrm')
-rw-r--r-- | nx-X11/extras/drm/libdrm/.cvsignore | 8 | ||||
-rw-r--r-- | nx-X11/extras/drm/libdrm/Makefile.am | 29 | ||||
-rw-r--r-- | nx-X11/extras/drm/libdrm/xf86drm.c | 2332 | ||||
-rw-r--r-- | nx-X11/extras/drm/libdrm/xf86drm.h | 638 | ||||
-rw-r--r-- | nx-X11/extras/drm/libdrm/xf86drmCompat.c | 1079 | ||||
-rw-r--r-- | nx-X11/extras/drm/libdrm/xf86drmCompat.h | 259 | ||||
-rw-r--r-- | nx-X11/extras/drm/libdrm/xf86drmHash.c | 440 | ||||
-rw-r--r-- | nx-X11/extras/drm/libdrm/xf86drmRandom.c | 224 | ||||
-rw-r--r-- | nx-X11/extras/drm/libdrm/xf86drmSL.c | 495 |
9 files changed, 5504 insertions, 0 deletions
diff --git a/nx-X11/extras/drm/libdrm/.cvsignore b/nx-X11/extras/drm/libdrm/.cvsignore new file mode 100644 index 000000000..a979bc4fd --- /dev/null +++ b/nx-X11/extras/drm/libdrm/.cvsignore @@ -0,0 +1,8 @@ +.deps +.libs +Makefile +Makefile.in +config.h +*.la +*.lo +stamp-h1 diff --git a/nx-X11/extras/drm/libdrm/Makefile.am b/nx-X11/extras/drm/libdrm/Makefile.am new file mode 100644 index 000000000..e3d2b4475 --- /dev/null +++ b/nx-X11/extras/drm/libdrm/Makefile.am @@ -0,0 +1,29 @@ +# Copyright 2005 Adam Jackson. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# on the rights to use, copy, modify, merge, publish, distribute, sub +# license, and/or sell copies of the Software, and to permit persons to whom +# the Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice (including the next +# paragraph) shall be included in all copies or substantial portions of the +# Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +# ADAM JACKSON BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +libdrm_la_LTLIBRARIES = libdrm.la +libdrm_ladir = $(libdir) +libdrm_la_LDFLAGS = -version-number 2:0:0 -no-undefined + +AM_CFLAGS = -I$(top_srcdir)/shared-core +libdrm_la_SOURCES = xf86drm.c xf86drmHash.c xf86drmRandom.c xf86drmSL.c + +libdrmincludedir = ${includedir} +libdrminclude_HEADERS = xf86drm.h diff --git a/nx-X11/extras/drm/libdrm/xf86drm.c b/nx-X11/extras/drm/libdrm/xf86drm.c new file mode 100644 index 000000000..0980e7884 --- /dev/null +++ b/nx-X11/extras/drm/libdrm/xf86drm.c @@ -0,0 +1,2332 @@ +/** + * \file xf86drm.c + * User-level interface to DRM device + * + * \author Rickard E. (Rik) Faith <faith@valinux.com> + * \author Kevin E. Martin <martin@valinux.com> + */ + +/* + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drm.c,v 1.36 2003/08/24 17:35:35 tsi Exp $ */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#ifdef XFree86Server +# include "xf86.h" +# include "xf86_OSproc.h" +# include "drm.h" +# include "xf86_ansic.h" +# define _DRM_MALLOC xalloc +# define _DRM_FREE xfree +# ifndef XFree86LOADER +# include <sys/mman.h> +# endif +#else +# include <stdio.h> +# include <stdlib.h> +# include <unistd.h> +# include <string.h> +# include <ctype.h> +# include <fcntl.h> +# include <errno.h> +# include <signal.h> +# include <sys/types.h> +# include <sys/stat.h> +# define stat_t struct stat +# include <sys/ioctl.h> +# include <sys/mman.h> +# include <sys/time.h> +# include <stdarg.h> +# ifdef DRM_USE_MALLOC +# define _DRM_MALLOC malloc +# define _DRM_FREE free +# else +# define _DRM_MALLOC malloc +# define _DRM_FREE free +# endif +# include "drm.h" +#endif + +/* No longer needed with CVS kernel modules on alpha +#if defined(__alpha__) && defined(__linux__) +extern unsigned long _bus_base(void); +#define BUS_BASE _bus_base() +#endif +*/ + +/* Not all systems have MAP_FAILED defined */ +#ifndef MAP_FAILED +#define MAP_FAILED ((void *)-1) +#endif + +#include "xf86drm.h" + +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) +#define DRM_MAJOR 145 +#endif + +#ifdef __NetBSD__ +#define DRM_MAJOR 34 +#endif + +# ifdef __OpenBSD__ +# define DRM_MAJOR 81 +# endif + +#ifndef DRM_MAJOR +#define DRM_MAJOR 226 /* Linux */ +#endif + +#ifndef DRM_MAX_MINOR +#define DRM_MAX_MINOR 16 +#endif + +#ifndef makedev + /* This definition needs to be changed on + some systems if dev_t is a structure. + If there is a header file we can get it + from, there would be best. */ +#define makedev(x,y) ((dev_t)(((x) << 8) | (y))) +#endif + +#define DRM_MSG_VERBOSITY 3 + +/** + * Output a message to stderr. + * + * \param format printf() like format string. + * + * \internal + * This function is a wrapper around vfprintf(). + */ +static void +drmMsg(const char *format, ...) +{ + va_list ap; + +#ifndef XFree86Server + const char *env; + if ((env = getenv("LIBGL_DEBUG")) && strstr(env, "verbose")) +#endif + { + va_start(ap, format); +#ifdef XFree86Server + xf86VDrvMsgVerb(-1, X_NONE, DRM_MSG_VERBOSITY, format, ap); +#else + vfprintf(stderr, format, ap); +#endif + va_end(ap); + } +} + +static void *drmHashTable = NULL; /* Context switch callbacks */ + +typedef struct drmHashEntry { + int fd; + void (*f)(int, void *, void *); + void *tagTable; +} drmHashEntry; + +void *drmMalloc(int size) +{ + void *pt; + if ((pt = _DRM_MALLOC(size))) memset(pt, 0, size); + return pt; +} + +void drmFree(void *pt) +{ + if (pt) _DRM_FREE(pt); +} + +/* drmStrdup can't use strdup(3), since it doesn't call _DRM_MALLOC... */ +static char *drmStrdup(const char *s) +{ + char *retval = NULL; + + if (s) { + retval = _DRM_MALLOC(strlen(s)+1); + strcpy(retval, s); + } + return retval; +} + + +static unsigned long drmGetKeyFromFd(int fd) +{ + stat_t st; + + st.st_rdev = 0; + fstat(fd, &st); + return st.st_rdev; +} + +static drmHashEntry *drmGetEntry(int fd) +{ + unsigned long key = drmGetKeyFromFd(fd); + void *value; + drmHashEntry *entry; + + if (!drmHashTable) drmHashTable = drmHashCreate(); + + if (drmHashLookup(drmHashTable, key, &value)) { + entry = drmMalloc(sizeof(*entry)); + entry->fd = fd; + entry->f = NULL; + entry->tagTable = drmHashCreate(); + drmHashInsert(drmHashTable, key, entry); + } else { + entry = value; + } + return entry; +} + +/** + * Compare two busid strings + * + * \param first + * \param second + * + * \return 1 if matched. + * + * \internal + * This function compares two bus ID strings. It understands the older + * PCI:b:d:f format and the newer pci:oooo:bb:dd.f format. In the format, o is + * domain, b is bus, d is device, f is function. + */ +static int drmMatchBusID(const char *id1, const char *id2) +{ + /* First, check if the IDs are exactly the same */ + if (strcasecmp(id1, id2) == 0) + return 1; + + /* Try to match old/new-style PCI bus IDs. */ + if (strncasecmp(id1, "pci", 3) == 0) { + int o1, b1, d1, f1; + int o2, b2, d2, f2; + int ret; + + ret = sscanf(id1, "pci:%04x:%02x:%02x.%d", &o1, &b1, &d1, &f1); + if (ret != 4) { + o1 = 0; + ret = sscanf(id1, "PCI:%d:%d:%d", &b1, &d1, &f1); + if (ret != 3) + return 0; + } + + ret = sscanf(id2, "pci:%04x:%02x:%02x.%d", &o2, &b2, &d2, &f2); + if (ret != 4) { + o2 = 0; + ret = sscanf(id2, "PCI:%d:%d:%d", &b2, &d2, &f2); + if (ret != 3) + return 0; + } + + if ((o1 != o2) || (b1 != b2) || (d1 != d2) || (f1 != f2)) + return 0; + else + return 1; + } + return 0; +} + +/** + * Open the DRM device, creating it if necessary. + * + * \param dev major and minor numbers of the device. + * \param minor minor number of the device. + * + * \return a file descriptor on success, or a negative value on error. + * + * \internal + * Assembles the device name from \p minor and opens it, creating the device + * special file node with the major and minor numbers specified by \p dev and + * parent directory if necessary and was called by root. + */ +static int drmOpenDevice(long dev, int minor) +{ + stat_t st; + char buf[64]; + int fd; + mode_t devmode = DRM_DEV_MODE; + int isroot = !geteuid(); +#if defined(XFree86Server) + uid_t user = DRM_DEV_UID; + gid_t group = DRM_DEV_GID; +#endif + + sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, minor); + drmMsg("drmOpenDevice: node name is %s\n", buf); + +#if defined(XFree86Server) + devmode = xf86ConfigDRI.mode ? xf86ConfigDRI.mode : DRM_DEV_MODE; + devmode &= ~(S_IXUSR|S_IXGRP|S_IXOTH); + group = (xf86ConfigDRI.group >= 0) ? xf86ConfigDRI.group : DRM_DEV_GID; +#endif + + if (stat(DRM_DIR_NAME, &st)) { + if (!isroot) return DRM_ERR_NOT_ROOT; + mkdir(DRM_DIR_NAME, DRM_DEV_DIRMODE); + chown(DRM_DIR_NAME, 0, 0); /* root:root */ + chmod(DRM_DIR_NAME, DRM_DEV_DIRMODE); + } + + /* Check if the device node exists and create it if necessary. */ + if (stat(buf, &st)) { + if (!isroot) return DRM_ERR_NOT_ROOT; + remove(buf); + mknod(buf, S_IFCHR | devmode, dev); + } +#if defined(XFree86Server) + chown(buf, user, group); + chmod(buf, devmode); +#endif + + fd = open(buf, O_RDWR, 0); + drmMsg("drmOpenDevice: open result is %d, (%s)\n", + fd, fd < 0 ? strerror(errno) : "OK"); + if (fd >= 0) return fd; + + /* Check if the device node is not what we expect it to be, and recreate it + * and try again if so. + */ + if (st.st_rdev != dev) { + if (!isroot) return DRM_ERR_NOT_ROOT; + remove(buf); + mknod(buf, S_IFCHR | devmode, dev); +#if defined(XFree86Server) + chown(buf, user, group); + chmod(buf, devmode); +#endif + } + fd = open(buf, O_RDWR, 0); + drmMsg("drmOpenDevice: open result is %d, (%s)\n", + fd, fd < 0 ? strerror(errno) : "OK"); + if (fd >= 0) return fd; + + drmMsg("drmOpenDevice: Open failed\n"); + remove(buf); + return -errno; +} + + +/** + * Open the DRM device + * + * \param minor device minor number. + * \param create allow to create the device if set. + * + * \return a file descriptor on success, or a negative value on error. + * + * \internal + * Calls drmOpenDevice() if \p create is set, otherwise assembles the device + * name from \p minor and opens it. + */ +static int drmOpenMinor(int minor, int create) +{ + int fd; + char buf[64]; + + if (create) return drmOpenDevice(makedev(DRM_MAJOR, minor), minor); + + sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, minor); + if ((fd = open(buf, O_RDWR, 0)) >= 0) return fd; + return -errno; +} + + +/** + * Determine whether the DRM kernel driver has been loaded. + * + * \return 1 if the DRM driver is loaded, 0 otherwise. + * + * \internal + * Determine the presence of the kernel driver by attempting to open the 0 + * minor and get version information. For backward compatibility with older + * Linux implementations, /proc/dri is also checked. + */ +int drmAvailable(void) +{ + drmVersionPtr version; + int retval = 0; + int fd; + + if ((fd = drmOpenMinor(0, 1)) < 0) { +#ifdef __linux__ + /* Try proc for backward Linux compatibility */ + if (!access("/proc/dri/0", R_OK)) return 1; +#endif + return 0; + } + + if ((version = drmGetVersion(fd))) { + retval = 1; + drmFreeVersion(version); + } + close(fd); + + return retval; +} + + +/** + * Open the device by bus ID. + * + * \param busid bus ID. + * + * \return a file descriptor on success, or a negative value on error. + * + * \internal + * This function attempts to open every possible minor (up to DRM_MAX_MINOR), + * comparing the device bus ID with the one supplied. + * + * \sa drmOpenMinor() and drmGetBusid(). + */ +static int drmOpenByBusid(const char *busid) +{ + int i; + int fd; + const char *buf; + drmSetVersion sv; + + drmMsg("drmOpenByBusid: Searching for BusID %s\n", busid); + for (i = 0; i < DRM_MAX_MINOR; i++) { + fd = drmOpenMinor(i, 1); + drmMsg("drmOpenByBusid: drmOpenMinor returns %d\n", fd); + if (fd >= 0) { + sv.drm_di_major = 1; + sv.drm_di_minor = 1; + sv.drm_dd_major = -1; /* Don't care */ + drmSetInterfaceVersion(fd, &sv); + buf = drmGetBusid(fd); + drmMsg("drmOpenByBusid: drmGetBusid reports %s\n", buf); + if (buf && drmMatchBusID(buf, busid)) { + drmFreeBusid(buf); + return fd; + } + if (buf) drmFreeBusid(buf); + close(fd); + } + } + return -1; +} + + +/** + * Open the device by name. + * + * \param name driver name. + * + * \return a file descriptor on success, or a negative value on error. + * + * \internal + * This function opens the first minor number that matches the driver name and + * isn't already in use. If it's in use it then it will already have a bus ID + * assigned. + * + * \sa drmOpenMinor(), drmGetVersion() and drmGetBusid(). + */ +static int drmOpenByName(const char *name) +{ + int i; + int fd; + drmVersionPtr version; + char * id; + + if (!drmAvailable()) { +#if !defined(XFree86Server) + return -1; +#else + /* try to load the kernel module now */ + if (!xf86LoadKernelModule(name)) { + ErrorF("[drm] failed to load kernel module \"%s\"\n", + name); + return -1; + } +#endif + } + + /* + * Open the first minor number that matches the driver name and isn't + * already in use. If it's in use it will have a busid assigned already. + */ + for (i = 0; i < DRM_MAX_MINOR; i++) { + if ((fd = drmOpenMinor(i, 1)) >= 0) { + if ((version = drmGetVersion(fd))) { + if (!strcmp(version->name, name)) { + drmFreeVersion(version); + id = drmGetBusid(fd); + drmMsg("drmGetBusid returned '%s'\n", id ? id : "NULL"); + if (!id || !*id) { + if (id) { + drmFreeBusid(id); + } + return fd; + } else { + drmFreeBusid(id); + } + } else { + drmFreeVersion(version); + } + } + close(fd); + } + } + +#ifdef __linux__ + /* Backward-compatibility /proc support */ + for (i = 0; i < 8; i++) { + char proc_name[64], buf[512]; + char *driver, *pt, *devstring; + int retcode; + + sprintf(proc_name, "/proc/dri/%d/name", i); + if ((fd = open(proc_name, 0, 0)) >= 0) { + retcode = read(fd, buf, sizeof(buf)-1); + close(fd); + if (retcode) { + buf[retcode-1] = '\0'; + for (driver = pt = buf; *pt && *pt != ' '; ++pt) + ; + if (*pt) { /* Device is next */ + *pt = '\0'; + if (!strcmp(driver, name)) { /* Match */ + for (devstring = ++pt; *pt && *pt != ' '; ++pt) + ; + if (*pt) { /* Found busid */ + return drmOpenByBusid(++pt); + } else { /* No busid */ + return drmOpenDevice(strtol(devstring, NULL, 0),i); + } + } + } + } + } + } +#endif + + return -1; +} + + +/** + * Open the DRM device. + * + * Looks up the specified name and bus ID, and opens the device found. The + * entry in /dev/dri is created if necessary and if called by root. + * + * \param name driver name. Not referenced if bus ID is supplied. + * \param busid bus ID. Zero if not known. + * + * \return a file descriptor on success, or a negative value on error. + * + * \internal + * It calls drmOpenByBusid() if \p busid is specified or drmOpenByName() + * otherwise. + */ +int drmOpen(const char *name, const char *busid) +{ +#ifdef XFree86Server + if (!drmAvailable() && name != NULL) { + /* try to load the kernel */ + if (!xf86LoadKernelModule(name)) { + ErrorF("[drm] failed to load kernel module \"%s\"\n", + name); + return -1; + } + } +#endif + + if (busid) { + int fd; + + fd = drmOpenByBusid(busid); + if (fd >= 0) + return fd; + } + if (name) + return drmOpenByName(name); + return -1; +} + + +/** + * Free the version information returned by drmGetVersion(). + * + * \param v pointer to the version information. + * + * \internal + * It frees the memory pointed by \p %v as well as all the non-null strings + * pointers in it. + */ +void drmFreeVersion(drmVersionPtr v) +{ + if (!v) return; + if (v->name) drmFree(v->name); + if (v->date) drmFree(v->date); + if (v->desc) drmFree(v->desc); + drmFree(v); +} + + +/** + * Free the non-public version information returned by the kernel. + * + * \param v pointer to the version information. + * + * \internal + * Used by drmGetVersion() to free the memory pointed by \p %v as well as all + * the non-null strings pointers in it. + */ +static void drmFreeKernelVersion(drm_version_t *v) +{ + if (!v) return; + if (v->name) drmFree(v->name); + if (v->date) drmFree(v->date); + if (v->desc) drmFree(v->desc); + drmFree(v); +} + + +/** + * Copy version information. + * + * \param d destination pointer. + * \param s source pointer. + * + * \internal + * Used by drmGetVersion() to translate the information returned by the ioctl + * interface in a private structure into the public structure counterpart. + */ +static void drmCopyVersion(drmVersionPtr d, const drm_version_t *s) +{ + d->version_major = s->version_major; + d->version_minor = s->version_minor; + d->version_patchlevel = s->version_patchlevel; + d->name_len = s->name_len; + d->name = drmStrdup(s->name); + d->date_len = s->date_len; + d->date = drmStrdup(s->date); + d->desc_len = s->desc_len; + d->desc = drmStrdup(s->desc); +} + + +/** + * Query the driver version information. + * + * \param fd file descriptor. + * + * \return pointer to a drmVersion structure which should be freed with + * drmFreeVersion(). + * + * \note Similar information is available via /proc/dri. + * + * \internal + * It gets the version information via successive DRM_IOCTL_VERSION ioctls, + * first with zeros to get the string lengths, and then the actually strings. + * It also null-terminates them since they might not be already. + */ +drmVersionPtr drmGetVersion(int fd) +{ + drmVersionPtr retval; + drm_version_t *version = drmMalloc(sizeof(*version)); + + /* First, get the lengths */ + version->name_len = 0; + version->name = NULL; + version->date_len = 0; + version->date = NULL; + version->desc_len = 0; + version->desc = NULL; + + if (ioctl(fd, DRM_IOCTL_VERSION, version)) { + drmFreeKernelVersion(version); + return NULL; + } + + /* Now, allocate space and get the data */ + if (version->name_len) + version->name = drmMalloc(version->name_len + 1); + if (version->date_len) + version->date = drmMalloc(version->date_len + 1); + if (version->desc_len) + version->desc = drmMalloc(version->desc_len + 1); + + if (ioctl(fd, DRM_IOCTL_VERSION, version)) { + drmMsg("DRM_IOCTL_VERSION: %s\n", strerror(errno)); + drmFreeKernelVersion(version); + return NULL; + } + + /* The results might not be null-terminated + strings, so terminate them. */ + + if (version->name_len) version->name[version->name_len] = '\0'; + if (version->date_len) version->date[version->date_len] = '\0'; + if (version->desc_len) version->desc[version->desc_len] = '\0'; + + /* Now, copy it all back into the + client-visible data structure... */ + retval = drmMalloc(sizeof(*retval)); + drmCopyVersion(retval, version); + drmFreeKernelVersion(version); + return retval; +} + + +/** + * Get version information for the DRM user space library. + * + * This version number is driver independent. + * + * \param fd file descriptor. + * + * \return version information. + * + * \internal + * This function allocates and fills a drm_version structure with a hard coded + * version number. + */ +drmVersionPtr drmGetLibVersion(int fd) +{ + drm_version_t *version = drmMalloc(sizeof(*version)); + + /* Version history: + * revision 1.0.x = original DRM interface with no drmGetLibVersion + * entry point and many drm<Device> extensions + * revision 1.1.x = added drmCommand entry points for device extensions + * added drmGetLibVersion to identify libdrm.a version + * revision 1.2.x = added drmSetInterfaceVersion + * modified drmOpen to handle both busid and name + */ + version->version_major = 1; + version->version_minor = 2; + version->version_patchlevel = 0; + + return (drmVersionPtr)version; +} + + +/** + * Free the bus ID information. + * + * \param busid bus ID information string as given by drmGetBusid(). + * + * \internal + * This function is just frees the memory pointed by \p busid. + */ +void drmFreeBusid(const char *busid) +{ + drmFree((void *)busid); +} + + +/** + * Get the bus ID of the device. + * + * \param fd file descriptor. + * + * \return bus ID string. + * + * \internal + * This function gets the bus ID via successive DRM_IOCTL_GET_UNIQUE ioctls to + * get the string length and data, passing the arguments in a drm_unique + * structure. + */ +char *drmGetBusid(int fd) +{ + drm_unique_t u; + + u.unique_len = 0; + u.unique = NULL; + + if (ioctl(fd, DRM_IOCTL_GET_UNIQUE, &u)) return NULL; + u.unique = drmMalloc(u.unique_len + 1); + if (ioctl(fd, DRM_IOCTL_GET_UNIQUE, &u)) return NULL; + u.unique[u.unique_len] = '\0'; + + return u.unique; +} + + +/** + * Set the bus ID of the device. + * + * \param fd file descriptor. + * \param busid bus ID string. + * + * \return zero on success, negative on failure. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_SET_UNIQUE ioctl, passing + * the arguments in a drm_unique structure. + */ +int drmSetBusid(int fd, const char *busid) +{ + drm_unique_t u; + + u.unique = (char *)busid; + u.unique_len = strlen(busid); + + if (ioctl(fd, DRM_IOCTL_SET_UNIQUE, &u)) { + return -errno; + } + return 0; +} + +int drmGetMagic(int fd, drm_magic_t * magic) +{ + drm_auth_t auth; + + *magic = 0; + if (ioctl(fd, DRM_IOCTL_GET_MAGIC, &auth)) return -errno; + *magic = auth.magic; + return 0; +} + +int drmAuthMagic(int fd, drm_magic_t magic) +{ + drm_auth_t auth; + + auth.magic = magic; + if (ioctl(fd, DRM_IOCTL_AUTH_MAGIC, &auth)) return -errno; + return 0; +} + +/** + * Specifies a range of memory that is available for mapping by a + * non-root process. + * + * \param fd file descriptor. + * \param offset usually the physical address. The actual meaning depends of + * the \p type parameter. See below. + * \param size of the memory in bytes. + * \param type type of the memory to be mapped. + * \param flags combination of several flags to modify the function actions. + * \param handle will be set to a value that may be used as the offset + * parameter for mmap(). + * + * \return zero on success or a negative value on error. + * + * \par Mapping the frame buffer + * For the frame buffer + * - \p offset will be the physical address of the start of the frame buffer, + * - \p size will be the size of the frame buffer in bytes, and + * - \p type will be DRM_FRAME_BUFFER. + * + * \par + * The area mapped will be uncached. If MTRR support is available in the + * kernel, the frame buffer area will be set to write combining. + * + * \par Mapping the MMIO register area + * For the MMIO register area, + * - \p offset will be the physical address of the start of the register area, + * - \p size will be the size of the register area bytes, and + * - \p type will be DRM_REGISTERS. + * \par + * The area mapped will be uncached. + * + * \par Mapping the SAREA + * For the SAREA, + * - \p offset will be ignored and should be set to zero, + * - \p size will be the desired size of the SAREA in bytes, + * - \p type will be DRM_SHM. + * + * \par + * A shared memory area of the requested size will be created and locked in + * kernel memory. This area may be mapped into client-space by using the handle + * returned. + * + * \note May only be called by root. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_ADD_MAP ioctl, passing + * the arguments in a drm_map structure. + */ +int drmAddMap(int fd, + drm_handle_t offset, + drmSize size, + drmMapType type, + drmMapFlags flags, + drm_handle_t * handle) +{ + drm_map_t map; + + map.offset = offset; +/* No longer needed with CVS kernel modules on alpha +#ifdef __alpha__ + if (type != DRM_SHM) + map.offset += BUS_BASE; +#endif +*/ + map.size = size; + map.handle = 0; + map.type = type; + map.flags = flags; + if (ioctl(fd, DRM_IOCTL_ADD_MAP, &map)) return -errno; + if (handle) *handle = (drm_handle_t)(unsigned long)map.handle; + return 0; +} + +int drmRmMap(int fd, drm_handle_t handle) +{ + drm_map_t map; + + map.handle = (void *)(unsigned long)handle; + + if(ioctl(fd, DRM_IOCTL_RM_MAP, &map)) return -errno; + return 0; +} + +/** + * Make buffers available for DMA transfers. + * + * \param fd file descriptor. + * \param count number of buffers. + * \param size size of each buffer. + * \param flags buffer allocation flags. + * \param agp_offset offset in the AGP aperture + * + * \return number of buffers allocated, negative on error. + * + * \internal + * This function is a wrapper around DRM_IOCTL_ADD_BUFS ioctl. + * + * \sa drm_buf_desc. + */ +int drmAddBufs(int fd, int count, int size, drmBufDescFlags flags, + int agp_offset) +{ + drm_buf_desc_t request; + + request.count = count; + request.size = size; + request.low_mark = 0; + request.high_mark = 0; + request.flags = flags; + request.agp_start = agp_offset; + + if (ioctl(fd, DRM_IOCTL_ADD_BUFS, &request)) return -errno; + return request.count; +} + +int drmMarkBufs(int fd, double low, double high) +{ + drm_buf_info_t info; + int i; + + info.count = 0; + info.list = NULL; + + if (ioctl(fd, DRM_IOCTL_INFO_BUFS, &info)) return -EINVAL; + + if (!info.count) return -EINVAL; + + if (!(info.list = drmMalloc(info.count * sizeof(*info.list)))) + return -ENOMEM; + + if (ioctl(fd, DRM_IOCTL_INFO_BUFS, &info)) { + int retval = -errno; + drmFree(info.list); + return retval; + } + + for (i = 0; i < info.count; i++) { + info.list[i].low_mark = low * info.list[i].count; + info.list[i].high_mark = high * info.list[i].count; + if (ioctl(fd, DRM_IOCTL_MARK_BUFS, &info.list[i])) { + int retval = -errno; + drmFree(info.list); + return retval; + } + } + drmFree(info.list); + + return 0; +} + +/** + * Free buffers. + * + * \param fd file descriptor. + * \param count number of buffers to free. + * \param list list of buffers to be freed. + * + * \return zero on success, or a negative value on failure. + * + * \note This function is primarily used for debugging. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_FREE_BUFS ioctl, passing + * the arguments in a drm_buf_free structure. + */ +int drmFreeBufs(int fd, int count, int *list) +{ + drm_buf_free_t request; + + request.count = count; + request.list = list; + if (ioctl(fd, DRM_IOCTL_FREE_BUFS, &request)) return -errno; + return 0; +} + + +/** + * Close the device. + * + * \param fd file descriptor. + * + * \internal + * This function closes the file descriptor. + */ +int drmClose(int fd) +{ + unsigned long key = drmGetKeyFromFd(fd); + drmHashEntry *entry = drmGetEntry(fd); + + drmHashDestroy(entry->tagTable); + entry->fd = 0; + entry->f = NULL; + entry->tagTable = NULL; + + drmHashDelete(drmHashTable, key); + drmFree(entry); + + return close(fd); +} + + +/** + * Map a region of memory. + * + * \param fd file descriptor. + * \param handle handle returned by drmAddMap(). + * \param size size in bytes. Must match the size used by drmAddMap(). + * \param address will contain the user-space virtual address where the mapping + * begins. + * + * \return zero on success, or a negative value on failure. + * + * \internal + * This function is a wrapper for mmap(). + */ +int drmMap(int fd, + drm_handle_t handle, + drmSize size, + drmAddressPtr address) +{ + static unsigned long pagesize_mask = 0; + + if (fd < 0) return -EINVAL; + + if (!pagesize_mask) + pagesize_mask = getpagesize() - 1; + + size = (size + pagesize_mask) & ~pagesize_mask; + + *address = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, handle); + if (*address == MAP_FAILED) return -errno; + return 0; +} + + +/** + * Unmap mappings obtained with drmMap(). + * + * \param address address as given by drmMap(). + * \param size size in bytes. Must match the size used by drmMap(). + * + * \return zero on success, or a negative value on failure. + * + * \internal + * This function is a wrapper for unmap(). + */ +int drmUnmap(drmAddress address, drmSize size) +{ + return munmap(address, size); +} + +drmBufInfoPtr drmGetBufInfo(int fd) +{ + drm_buf_info_t info; + drmBufInfoPtr retval; + int i; + + info.count = 0; + info.list = NULL; + + if (ioctl(fd, DRM_IOCTL_INFO_BUFS, &info)) return NULL; + + if (info.count) { + if (!(info.list = drmMalloc(info.count * sizeof(*info.list)))) + return NULL; + + if (ioctl(fd, DRM_IOCTL_INFO_BUFS, &info)) { + drmFree(info.list); + return NULL; + } + /* Now, copy it all back into the + client-visible data structure... */ + retval = drmMalloc(sizeof(*retval)); + retval->count = info.count; + retval->list = drmMalloc(info.count * sizeof(*retval->list)); + for (i = 0; i < info.count; i++) { + retval->list[i].count = info.list[i].count; + retval->list[i].size = info.list[i].size; + retval->list[i].low_mark = info.list[i].low_mark; + retval->list[i].high_mark = info.list[i].high_mark; + } + drmFree(info.list); + return retval; + } + return NULL; +} + +/** + * Map all DMA buffers into client-virtual space. + * + * \param fd file descriptor. + * + * \return a pointer to a ::drmBufMap structure. + * + * \note The client may not use these buffers until obtaining buffer indices + * with drmDMA(). + * + * \internal + * This function calls the DRM_IOCTL_MAP_BUFS ioctl and copies the returned + * information about the buffers in a drm_buf_map structure into the + * client-visible data structures. + */ +drmBufMapPtr drmMapBufs(int fd) +{ + drm_buf_map_t bufs; + drmBufMapPtr retval; + int i; + + bufs.count = 0; + bufs.list = NULL; + bufs.virtual = NULL; + if (ioctl(fd, DRM_IOCTL_MAP_BUFS, &bufs)) return NULL; + + if (!bufs.count) return NULL; + + if (!(bufs.list = drmMalloc(bufs.count * sizeof(*bufs.list)))) + return NULL; + + if (ioctl(fd, DRM_IOCTL_MAP_BUFS, &bufs)) { + drmFree(bufs.list); + return NULL; + } + /* Now, copy it all back into the + client-visible data structure... */ + retval = drmMalloc(sizeof(*retval)); + retval->count = bufs.count; + retval->list = drmMalloc(bufs.count * sizeof(*retval->list)); + for (i = 0; i < bufs.count; i++) { + retval->list[i].idx = bufs.list[i].idx; + retval->list[i].total = bufs.list[i].total; + retval->list[i].used = 0; + retval->list[i].address = bufs.list[i].address; + } + + drmFree(bufs.list); + + return retval; +} + + +/** + * Unmap buffers allocated with drmMapBufs(). + * + * \return zero on success, or negative value on failure. + * + * \internal + * Calls munmap() for every buffer stored in \p bufs and frees the + * memory allocated by drmMapBufs(). + */ +int drmUnmapBufs(drmBufMapPtr bufs) +{ + int i; + + for (i = 0; i < bufs->count; i++) { + munmap(bufs->list[i].address, bufs->list[i].total); + } + + drmFree(bufs->list); + drmFree(bufs); + + return 0; +} + + +#define DRM_DMA_RETRY 16 + +/** + * Reserve DMA buffers. + * + * \param fd file descriptor. + * \param request + * + * \return zero on success, or a negative value on failure. + * + * \internal + * Assemble the arguments into a drm_dma structure and keeps issuing the + * DRM_IOCTL_DMA ioctl until success or until maximum number of retries. + */ +int drmDMA(int fd, drmDMAReqPtr request) +{ + drm_dma_t dma; + int ret, i = 0; + + /* Copy to hidden structure */ + dma.context = request->context; + dma.send_count = request->send_count; + dma.send_indices = request->send_list; + dma.send_sizes = request->send_sizes; + dma.flags = request->flags; + dma.request_count = request->request_count; + dma.request_size = request->request_size; + dma.request_indices = request->request_list; + dma.request_sizes = request->request_sizes; + dma.granted_count = 0; + + do { + ret = ioctl( fd, DRM_IOCTL_DMA, &dma ); + } while ( ret && errno == EAGAIN && i++ < DRM_DMA_RETRY ); + + if ( ret == 0 ) { + request->granted_count = dma.granted_count; + return 0; + } else { + return -errno; + } +} + + +/** + * Obtain heavyweight hardware lock. + * + * \param fd file descriptor. + * \param context context. + * \param flags flags that determine the sate of the hardware when the function + * returns. + * + * \return always zero. + * + * \internal + * This function translates the arguments into a drm_lock structure and issue + * the DRM_IOCTL_LOCK ioctl until the lock is successfully acquired. + */ +int drmGetLock(int fd, drm_context_t context, drmLockFlags flags) +{ + drm_lock_t lock; + + lock.context = context; + lock.flags = 0; + if (flags & DRM_LOCK_READY) lock.flags |= _DRM_LOCK_READY; + if (flags & DRM_LOCK_QUIESCENT) lock.flags |= _DRM_LOCK_QUIESCENT; + if (flags & DRM_LOCK_FLUSH) lock.flags |= _DRM_LOCK_FLUSH; + if (flags & DRM_LOCK_FLUSH_ALL) lock.flags |= _DRM_LOCK_FLUSH_ALL; + if (flags & DRM_HALT_ALL_QUEUES) lock.flags |= _DRM_HALT_ALL_QUEUES; + if (flags & DRM_HALT_CUR_QUEUES) lock.flags |= _DRM_HALT_CUR_QUEUES; + + while (ioctl(fd, DRM_IOCTL_LOCK, &lock)) + ; + return 0; +} + +/** + * Release the hardware lock. + * + * \param fd file descriptor. + * \param context context. + * + * \return zero on success, or a negative value on failure. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_UNLOCK ioctl, passing the + * argument in a drm_lock structure. + */ +int drmUnlock(int fd, drm_context_t context) +{ + drm_lock_t lock; + + lock.context = context; + lock.flags = 0; + return ioctl(fd, DRM_IOCTL_UNLOCK, &lock); +} + +drm_context_t * drmGetReservedContextList(int fd, int *count) +{ + drm_ctx_res_t res; + drm_ctx_t *list; + drm_context_t * retval; + int i; + + res.count = 0; + res.contexts = NULL; + if (ioctl(fd, DRM_IOCTL_RES_CTX, &res)) return NULL; + + if (!res.count) return NULL; + + if (!(list = drmMalloc(res.count * sizeof(*list)))) return NULL; + if (!(retval = drmMalloc(res.count * sizeof(*retval)))) { + drmFree(list); + return NULL; + } + + res.contexts = list; + if (ioctl(fd, DRM_IOCTL_RES_CTX, &res)) return NULL; + + for (i = 0; i < res.count; i++) retval[i] = list[i].handle; + drmFree(list); + + *count = res.count; + return retval; +} + +void drmFreeReservedContextList(drm_context_t * pt) +{ + drmFree(pt); +} + +/** + * Create context. + * + * Used by the X server during GLXContext initialization. This causes + * per-context kernel-level resources to be allocated. + * + * \param fd file descriptor. + * \param handle is set on success. To be used by the client when requesting DMA + * dispatch with drmDMA(). + * + * \return zero on success, or a negative value on failure. + * + * \note May only be called by root. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_ADD_CTX ioctl, passing the + * argument in a drm_ctx structure. + */ +int drmCreateContext(int fd, drm_context_t * handle) +{ + drm_ctx_t ctx; + + ctx.flags = 0; /* Modified with functions below */ + if (ioctl(fd, DRM_IOCTL_ADD_CTX, &ctx)) return -errno; + *handle = ctx.handle; + return 0; +} + +int drmSwitchToContext(int fd, drm_context_t context) +{ + drm_ctx_t ctx; + + ctx.handle = context; + if (ioctl(fd, DRM_IOCTL_SWITCH_CTX, &ctx)) return -errno; + return 0; +} + +int drmSetContextFlags(int fd, drm_context_t context, drm_context_tFlags flags) +{ + drm_ctx_t ctx; + + /* Context preserving means that no context + switched are done between DMA buffers + from one context and the next. This is + suitable for use in the X server (which + promises to maintain hardware context, + or in the client-side library when + buffers are swapped on behalf of two + threads. */ + ctx.handle = context; + ctx.flags = 0; + if (flags & DRM_CONTEXT_PRESERVED) ctx.flags |= _DRM_CONTEXT_PRESERVED; + if (flags & DRM_CONTEXT_2DONLY) ctx.flags |= _DRM_CONTEXT_2DONLY; + if (ioctl(fd, DRM_IOCTL_MOD_CTX, &ctx)) return -errno; + return 0; +} + +int drmGetContextFlags(int fd, drm_context_t context, drm_context_tFlagsPtr flags) +{ + drm_ctx_t ctx; + + ctx.handle = context; + if (ioctl(fd, DRM_IOCTL_GET_CTX, &ctx)) return -errno; + *flags = 0; + if (ctx.flags & _DRM_CONTEXT_PRESERVED) *flags |= DRM_CONTEXT_PRESERVED; + if (ctx.flags & _DRM_CONTEXT_2DONLY) *flags |= DRM_CONTEXT_2DONLY; + return 0; +} + +/** + * Destroy context. + * + * Free any kernel-level resources allocated with drmCreateContext() associated + * with the context. + * + * \param fd file descriptor. + * \param handle handle given by drmCreateContext(). + * + * \return zero on success, or a negative value on failure. + * + * \note May only be called by root. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_RM_CTX ioctl, passing the + * argument in a drm_ctx structure. + */ +int drmDestroyContext(int fd, drm_context_t handle) +{ + drm_ctx_t ctx; + ctx.handle = handle; + if (ioctl(fd, DRM_IOCTL_RM_CTX, &ctx)) return -errno; + return 0; +} + +int drmCreateDrawable(int fd, drm_drawable_t * handle) +{ + drm_draw_t draw; + if (ioctl(fd, DRM_IOCTL_ADD_DRAW, &draw)) return -errno; + *handle = draw.handle; + return 0; +} + +int drmDestroyDrawable(int fd, drm_drawable_t handle) +{ + drm_draw_t draw; + draw.handle = handle; + if (ioctl(fd, DRM_IOCTL_RM_DRAW, &draw)) return -errno; + return 0; +} + +/** + * Acquire the AGP device. + * + * Must be called before any of the other AGP related calls. + * + * \param fd file descriptor. + * + * \return zero on success, or a negative value on failure. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_AGP_ACQUIRE ioctl. + */ +int drmAgpAcquire(int fd) +{ + if (ioctl(fd, DRM_IOCTL_AGP_ACQUIRE, NULL)) return -errno; + return 0; +} + + +/** + * Release the AGP device. + * + * \param fd file descriptor. + * + * \return zero on success, or a negative value on failure. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_AGP_RELEASE ioctl. + */ +int drmAgpRelease(int fd) +{ + if (ioctl(fd, DRM_IOCTL_AGP_RELEASE, NULL)) return -errno; + return 0; +} + + +/** + * Set the AGP mode. + * + * \param fd file descriptor. + * \param mode AGP mode. + * + * \return zero on success, or a negative value on failure. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_AGP_ENABLE ioctl, passing the + * argument in a drm_agp_mode structure. + */ +int drmAgpEnable(int fd, unsigned long mode) +{ + drm_agp_mode_t m; + + m.mode = mode; + if (ioctl(fd, DRM_IOCTL_AGP_ENABLE, &m)) return -errno; + return 0; +} + + +/** + * Allocate a chunk of AGP memory. + * + * \param fd file descriptor. + * \param size requested memory size in bytes. Will be rounded to page boundary. + * \param type type of memory to allocate. + * \param address if not zero, will be set to the physical address of the + * allocated memory. + * \param handle on success will be set to a handle of the allocated memory. + * + * \return zero on success, or a negative value on failure. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_AGP_ALLOC ioctl, passing the + * arguments in a drm_agp_buffer structure. + */ +int drmAgpAlloc(int fd, unsigned long size, unsigned long type, + unsigned long *address, drm_handle_t *handle) +{ + drm_agp_buffer_t b; + + *handle = DRM_AGP_NO_HANDLE; + b.size = size; + b.handle = 0; + b.type = type; + if (ioctl(fd, DRM_IOCTL_AGP_ALLOC, &b)) return -errno; + if (address != 0UL) *address = b.physical; + *handle = b.handle; + return 0; +} + + +/** + * Free a chunk of AGP memory. + * + * \param fd file descriptor. + * \param handle handle to the allocated memory, as given by drmAgpAllocate(). + * + * \return zero on success, or a negative value on failure. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_AGP_FREE ioctl, passing the + * argument in a drm_agp_buffer structure. + */ +int drmAgpFree(int fd, drm_handle_t handle) +{ + drm_agp_buffer_t b; + + b.size = 0; + b.handle = handle; + if (ioctl(fd, DRM_IOCTL_AGP_FREE, &b)) return -errno; + return 0; +} + + +/** + * Bind a chunk of AGP memory. + * + * \param fd file descriptor. + * \param handle handle to the allocated memory, as given by drmAgpAllocate(). + * \param offset offset in bytes. It will round to page boundary. + * + * \return zero on success, or a negative value on failure. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_AGP_BIND ioctl, passing the + * argument in a drm_agp_binding structure. + */ +int drmAgpBind(int fd, drm_handle_t handle, unsigned long offset) +{ + drm_agp_binding_t b; + + b.handle = handle; + b.offset = offset; + if (ioctl(fd, DRM_IOCTL_AGP_BIND, &b)) return -errno; + return 0; +} + + +/** + * Unbind a chunk of AGP memory. + * + * \param fd file descriptor. + * \param handle handle to the allocated memory, as given by drmAgpAllocate(). + * + * \return zero on success, or a negative value on failure. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_AGP_UNBIND ioctl, passing + * the argument in a drm_agp_binding structure. + */ +int drmAgpUnbind(int fd, drm_handle_t handle) +{ + drm_agp_binding_t b; + + b.handle = handle; + b.offset = 0; + if (ioctl(fd, DRM_IOCTL_AGP_UNBIND, &b)) return -errno; + return 0; +} + + +/** + * Get AGP driver major version number. + * + * \param fd file descriptor. + * + * \return major version number on success, or a negative value on failure.. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the + * necessary information in a drm_agp_info structure. + */ +int drmAgpVersionMajor(int fd) +{ + drm_agp_info_t i; + + if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return -errno; + return i.agp_version_major; +} + + +/** + * Get AGP driver minor version number. + * + * \param fd file descriptor. + * + * \return minor version number on success, or a negative value on failure. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the + * necessary information in a drm_agp_info structure. + */ +int drmAgpVersionMinor(int fd) +{ + drm_agp_info_t i; + + if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return -errno; + return i.agp_version_minor; +} + + +/** + * Get AGP mode. + * + * \param fd file descriptor. + * + * \return mode on success, or zero on failure. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the + * necessary information in a drm_agp_info structure. + */ +unsigned long drmAgpGetMode(int fd) +{ + drm_agp_info_t i; + + if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0; + return i.mode; +} + + +/** + * Get AGP aperture base. + * + * \param fd file descriptor. + * + * \return aperture base on success, zero on failure. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the + * necessary information in a drm_agp_info structure. + */ +unsigned long drmAgpBase(int fd) +{ + drm_agp_info_t i; + + if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0; + return i.aperture_base; +} + + +/** + * Get AGP aperture size. + * + * \param fd file descriptor. + * + * \return aperture size on success, zero on failure. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the + * necessary information in a drm_agp_info structure. + */ +unsigned long drmAgpSize(int fd) +{ + drm_agp_info_t i; + + if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0; + return i.aperture_size; +} + + +/** + * Get used AGP memory. + * + * \param fd file descriptor. + * + * \return memory used on success, or zero on failure. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the + * necessary information in a drm_agp_info structure. + */ +unsigned long drmAgpMemoryUsed(int fd) +{ + drm_agp_info_t i; + + if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0; + return i.memory_used; +} + + +/** + * Get available AGP memory. + * + * \param fd file descriptor. + * + * \return memory available on success, or zero on failure. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the + * necessary information in a drm_agp_info structure. + */ +unsigned long drmAgpMemoryAvail(int fd) +{ + drm_agp_info_t i; + + if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0; + return i.memory_allowed; +} + + +/** + * Get hardware vendor ID. + * + * \param fd file descriptor. + * + * \return vendor ID on success, or zero on failure. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the + * necessary information in a drm_agp_info structure. + */ +unsigned int drmAgpVendorId(int fd) +{ + drm_agp_info_t i; + + if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0; + return i.id_vendor; +} + + +/** + * Get hardware device ID. + * + * \param fd file descriptor. + * + * \return zero on success, or zero on failure. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the + * necessary information in a drm_agp_info structure. + */ +unsigned int drmAgpDeviceId(int fd) +{ + drm_agp_info_t i; + + if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0; + return i.id_device; +} + +int drmScatterGatherAlloc(int fd, unsigned long size, drm_handle_t *handle) +{ + drm_scatter_gather_t sg; + + *handle = 0; + sg.size = size; + sg.handle = 0; + if (ioctl(fd, DRM_IOCTL_SG_ALLOC, &sg)) return -errno; + *handle = sg.handle; + return 0; +} + +int drmScatterGatherFree(int fd, drm_handle_t handle) +{ + drm_scatter_gather_t sg; + + sg.size = 0; + sg.handle = handle; + if (ioctl(fd, DRM_IOCTL_SG_FREE, &sg)) return -errno; + return 0; +} + +/** + * Wait for VBLANK. + * + * \param fd file descriptor. + * \param vbl pointer to a drmVBlank structure. + * + * \return zero on success, or a negative value on failure. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_WAIT_VBLANK ioctl. + */ +int drmWaitVBlank(int fd, drmVBlankPtr vbl) +{ + int ret; + + do { + ret = ioctl(fd, DRM_IOCTL_WAIT_VBLANK, vbl); + vbl->request.type &= ~DRM_VBLANK_RELATIVE; + } while (ret && errno == EINTR); + + return ret; +} + +int drmError(int err, const char *label) +{ + switch (err) { + case DRM_ERR_NO_DEVICE: fprintf(stderr, "%s: no device\n", label); break; + case DRM_ERR_NO_ACCESS: fprintf(stderr, "%s: no access\n", label); break; + case DRM_ERR_NOT_ROOT: fprintf(stderr, "%s: not root\n", label); break; + case DRM_ERR_INVALID: fprintf(stderr, "%s: invalid args\n", label);break; + default: + if (err < 0) err = -err; + fprintf( stderr, "%s: error %d (%s)\n", label, err, strerror(err) ); + break; + } + + return 1; +} + +/** + * Install IRQ handler. + * + * \param fd file descriptor. + * \param irq IRQ number. + * + * \return zero on success, or a negative value on failure. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_CONTROL ioctl, passing the + * argument in a drm_control structure. + */ +int drmCtlInstHandler(int fd, int irq) +{ + drm_control_t ctl; + + ctl.func = DRM_INST_HANDLER; + ctl.irq = irq; + if (ioctl(fd, DRM_IOCTL_CONTROL, &ctl)) return -errno; + return 0; +} + + +/** + * Uninstall IRQ handler. + * + * \param fd file descriptor. + * + * \return zero on success, or a negative value on failure. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_CONTROL ioctl, passing the + * argument in a drm_control structure. + */ +int drmCtlUninstHandler(int fd) +{ + drm_control_t ctl; + + ctl.func = DRM_UNINST_HANDLER; + ctl.irq = 0; + if (ioctl(fd, DRM_IOCTL_CONTROL, &ctl)) return -errno; + return 0; +} + +int drmFinish(int fd, int context, drmLockFlags flags) +{ + drm_lock_t lock; + + lock.context = context; + lock.flags = 0; + if (flags & DRM_LOCK_READY) lock.flags |= _DRM_LOCK_READY; + if (flags & DRM_LOCK_QUIESCENT) lock.flags |= _DRM_LOCK_QUIESCENT; + if (flags & DRM_LOCK_FLUSH) lock.flags |= _DRM_LOCK_FLUSH; + if (flags & DRM_LOCK_FLUSH_ALL) lock.flags |= _DRM_LOCK_FLUSH_ALL; + if (flags & DRM_HALT_ALL_QUEUES) lock.flags |= _DRM_HALT_ALL_QUEUES; + if (flags & DRM_HALT_CUR_QUEUES) lock.flags |= _DRM_HALT_CUR_QUEUES; + if (ioctl(fd, DRM_IOCTL_FINISH, &lock)) return -errno; + return 0; +} + +/** + * Get IRQ from bus ID. + * + * \param fd file descriptor. + * \param busnum bus number. + * \param devnum device number. + * \param funcnum function number. + * + * \return IRQ number on success, or a negative value on failure. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_IRQ_BUSID ioctl, passing the + * arguments in a drm_irq_busid structure. + */ +int drmGetInterruptFromBusID(int fd, int busnum, int devnum, int funcnum) +{ + drm_irq_busid_t p; + + p.busnum = busnum; + p.devnum = devnum; + p.funcnum = funcnum; + if (ioctl(fd, DRM_IOCTL_IRQ_BUSID, &p)) return -errno; + return p.irq; +} + +int drmAddContextTag(int fd, drm_context_t context, void *tag) +{ + drmHashEntry *entry = drmGetEntry(fd); + + if (drmHashInsert(entry->tagTable, context, tag)) { + drmHashDelete(entry->tagTable, context); + drmHashInsert(entry->tagTable, context, tag); + } + return 0; +} + +int drmDelContextTag(int fd, drm_context_t context) +{ + drmHashEntry *entry = drmGetEntry(fd); + + return drmHashDelete(entry->tagTable, context); +} + +void *drmGetContextTag(int fd, drm_context_t context) +{ + drmHashEntry *entry = drmGetEntry(fd); + void *value; + + if (drmHashLookup(entry->tagTable, context, &value)) return NULL; + + return value; +} + +int drmAddContextPrivateMapping(int fd, drm_context_t ctx_id, drm_handle_t handle) +{ + drm_ctx_priv_map_t map; + + map.ctx_id = ctx_id; + map.handle = (void *)(unsigned long)handle; + + if (ioctl(fd, DRM_IOCTL_SET_SAREA_CTX, &map)) return -errno; + return 0; +} + +int drmGetContextPrivateMapping(int fd, drm_context_t ctx_id, drm_handle_t * handle) +{ + drm_ctx_priv_map_t map; + + map.ctx_id = ctx_id; + + if (ioctl(fd, DRM_IOCTL_GET_SAREA_CTX, &map)) return -errno; + if (handle) *handle = (drm_handle_t)(unsigned long)map.handle; + + return 0; +} + +int drmGetMap(int fd, int idx, drm_handle_t *offset, drmSize *size, + drmMapType *type, drmMapFlags *flags, drm_handle_t *handle, + int *mtrr) +{ + drm_map_t map; + + map.offset = idx; + if (ioctl(fd, DRM_IOCTL_GET_MAP, &map)) return -errno; + *offset = map.offset; + *size = map.size; + *type = map.type; + *flags = map.flags; + *handle = (drm_handle_t)(unsigned long)map.handle; + *mtrr = map.mtrr; + return 0; +} + +int drmGetClient(int fd, int idx, int *auth, int *pid, int *uid, + unsigned long *magic, unsigned long *iocs) +{ + drm_client_t client; + + client.idx = idx; + if (ioctl(fd, DRM_IOCTL_GET_CLIENT, &client)) return -errno; + *auth = client.auth; + *pid = client.pid; + *uid = client.uid; + *magic = client.magic; + *iocs = client.iocs; + return 0; +} + +int drmGetStats(int fd, drmStatsT *stats) +{ + drm_stats_t s; + unsigned int i; + + if (ioctl(fd, DRM_IOCTL_GET_STATS, &s)) return -errno; + + stats->count = 0; + memset(stats, 0, sizeof(*stats)); + if (s.count > sizeof(stats->data)/sizeof(stats->data[0])) + return -1; + +#define SET_VALUE \ + stats->data[i].long_format = "%-20.20s"; \ + stats->data[i].rate_format = "%8.8s"; \ + stats->data[i].isvalue = 1; \ + stats->data[i].verbose = 0 + +#define SET_COUNT \ + stats->data[i].long_format = "%-20.20s"; \ + stats->data[i].rate_format = "%5.5s"; \ + stats->data[i].isvalue = 0; \ + stats->data[i].mult_names = "kgm"; \ + stats->data[i].mult = 1000; \ + stats->data[i].verbose = 0 + +#define SET_BYTE \ + stats->data[i].long_format = "%-20.20s"; \ + stats->data[i].rate_format = "%5.5s"; \ + stats->data[i].isvalue = 0; \ + stats->data[i].mult_names = "KGM"; \ + stats->data[i].mult = 1024; \ + stats->data[i].verbose = 0 + + + stats->count = s.count; + for (i = 0; i < s.count; i++) { + stats->data[i].value = s.data[i].value; + switch (s.data[i].type) { + case _DRM_STAT_LOCK: + stats->data[i].long_name = "Lock"; + stats->data[i].rate_name = "Lock"; + SET_VALUE; + break; + case _DRM_STAT_OPENS: + stats->data[i].long_name = "Opens"; + stats->data[i].rate_name = "O"; + SET_COUNT; + stats->data[i].verbose = 1; + break; + case _DRM_STAT_CLOSES: + stats->data[i].long_name = "Closes"; + stats->data[i].rate_name = "Lock"; + SET_COUNT; + stats->data[i].verbose = 1; + break; + case _DRM_STAT_IOCTLS: + stats->data[i].long_name = "Ioctls"; + stats->data[i].rate_name = "Ioc/s"; + SET_COUNT; + break; + case _DRM_STAT_LOCKS: + stats->data[i].long_name = "Locks"; + stats->data[i].rate_name = "Lck/s"; + SET_COUNT; + break; + case _DRM_STAT_UNLOCKS: + stats->data[i].long_name = "Unlocks"; + stats->data[i].rate_name = "Unl/s"; + SET_COUNT; + break; + case _DRM_STAT_IRQ: + stats->data[i].long_name = "IRQs"; + stats->data[i].rate_name = "IRQ/s"; + SET_COUNT; + break; + case _DRM_STAT_PRIMARY: + stats->data[i].long_name = "Primary Bytes"; + stats->data[i].rate_name = "PB/s"; + SET_BYTE; + break; + case _DRM_STAT_SECONDARY: + stats->data[i].long_name = "Secondary Bytes"; + stats->data[i].rate_name = "SB/s"; + SET_BYTE; + break; + case _DRM_STAT_DMA: + stats->data[i].long_name = "DMA"; + stats->data[i].rate_name = "DMA/s"; + SET_COUNT; + break; + case _DRM_STAT_SPECIAL: + stats->data[i].long_name = "Special DMA"; + stats->data[i].rate_name = "dma/s"; + SET_COUNT; + break; + case _DRM_STAT_MISSED: + stats->data[i].long_name = "Miss"; + stats->data[i].rate_name = "Ms/s"; + SET_COUNT; + break; + case _DRM_STAT_VALUE: + stats->data[i].long_name = "Value"; + stats->data[i].rate_name = "Value"; + SET_VALUE; + break; + case _DRM_STAT_BYTE: + stats->data[i].long_name = "Bytes"; + stats->data[i].rate_name = "B/s"; + SET_BYTE; + break; + case _DRM_STAT_COUNT: + default: + stats->data[i].long_name = "Count"; + stats->data[i].rate_name = "Cnt/s"; + SET_COUNT; + break; + } + } + return 0; +} + +/** + * Issue a set-version ioctl. + * + * \param fd file descriptor. + * \param drmCommandIndex command index + * \param data source pointer of the data to be read and written. + * \param size size of the data to be read and written. + * + * \return zero on success, or a negative value on failure. + * + * \internal + * It issues a read-write ioctl given by + * \code DRM_COMMAND_BASE + drmCommandIndex \endcode. + */ +int drmSetInterfaceVersion(int fd, drmSetVersion *version ) +{ + int retcode = 0; + drm_set_version_t sv; + + sv.drm_di_major = version->drm_di_major; + sv.drm_di_minor = version->drm_di_minor; + sv.drm_dd_major = version->drm_dd_major; + sv.drm_dd_minor = version->drm_dd_minor; + + if (ioctl(fd, DRM_IOCTL_SET_VERSION, &sv)) { + retcode = -errno; + } + + version->drm_di_major = sv.drm_di_major; + version->drm_di_minor = sv.drm_di_minor; + version->drm_dd_major = sv.drm_dd_major; + version->drm_dd_minor = sv.drm_dd_minor; + + return retcode; +} + +/** + * Send a device-specific command. + * + * \param fd file descriptor. + * \param drmCommandIndex command index + * + * \return zero on success, or a negative value on failure. + * + * \internal + * It issues a ioctl given by + * \code DRM_COMMAND_BASE + drmCommandIndex \endcode. + */ +int drmCommandNone(int fd, unsigned long drmCommandIndex) +{ + void *data = NULL; /* dummy */ + unsigned long request; + + request = DRM_IO( DRM_COMMAND_BASE + drmCommandIndex); + + if (ioctl(fd, request, data)) { + return -errno; + } + return 0; +} + + +/** + * Send a device-specific read command. + * + * \param fd file descriptor. + * \param drmCommandIndex command index + * \param data destination pointer of the data to be read. + * \param size size of the data to be read. + * + * \return zero on success, or a negative value on failure. + * + * \internal + * It issues a read ioctl given by + * \code DRM_COMMAND_BASE + drmCommandIndex \endcode. + */ +int drmCommandRead(int fd, unsigned long drmCommandIndex, + void *data, unsigned long size ) +{ + unsigned long request; + + request = DRM_IOC( DRM_IOC_READ, DRM_IOCTL_BASE, + DRM_COMMAND_BASE + drmCommandIndex, size); + + if (ioctl(fd, request, data)) { + return -errno; + } + return 0; +} + + +/** + * Send a device-specific write command. + * + * \param fd file descriptor. + * \param drmCommandIndex command index + * \param data source pointer of the data to be written. + * \param size size of the data to be written. + * + * \return zero on success, or a negative value on failure. + * + * \internal + * It issues a write ioctl given by + * \code DRM_COMMAND_BASE + drmCommandIndex \endcode. + */ +int drmCommandWrite(int fd, unsigned long drmCommandIndex, + void *data, unsigned long size ) +{ + unsigned long request; + + request = DRM_IOC( DRM_IOC_WRITE, DRM_IOCTL_BASE, + DRM_COMMAND_BASE + drmCommandIndex, size); + + if (ioctl(fd, request, data)) { + return -errno; + } + return 0; +} + + +/** + * Send a device-specific read-write command. + * + * \param fd file descriptor. + * \param drmCommandIndex command index + * \param data source pointer of the data to be read and written. + * \param size size of the data to be read and written. + * + * \return zero on success, or a negative value on failure. + * + * \internal + * It issues a read-write ioctl given by + * \code DRM_COMMAND_BASE + drmCommandIndex \endcode. + */ +int drmCommandWriteRead(int fd, unsigned long drmCommandIndex, + void *data, unsigned long size ) +{ + unsigned long request; + + request = DRM_IOC( DRM_IOC_READ|DRM_IOC_WRITE, DRM_IOCTL_BASE, + DRM_COMMAND_BASE + drmCommandIndex, size); + + if (ioctl(fd, request, data)) { + return -errno; + } + return 0; +} + +#if defined(XFree86Server) +static void drmSIGIOHandler(int interrupt, void *closure) +{ + unsigned long key; + void *value; + ssize_t count; + drm_ctx_t ctx; + typedef void (*_drmCallback)(int, void *, void *); + char buf[256]; + drm_context_t old; + drm_context_t new; + void *oldctx; + void *newctx; + char *pt; + drmHashEntry *entry; + + if (!drmHashTable) return; + if (drmHashFirst(drmHashTable, &key, &value)) { + entry = value; + do { +#if 0 + fprintf(stderr, "Trying %d\n", entry->fd); +#endif + if ((count = read(entry->fd, buf, sizeof(buf))) > 0) { + buf[count] = '\0'; +#if 0 + fprintf(stderr, "Got %s\n", buf); +#endif + + for (pt = buf; *pt != ' '; ++pt); /* Find first space */ + ++pt; + old = strtol(pt, &pt, 0); + new = strtol(pt, NULL, 0); + oldctx = drmGetContextTag(entry->fd, old); + newctx = drmGetContextTag(entry->fd, new); +#if 0 + fprintf(stderr, "%d %d %p %p\n", old, new, oldctx, newctx); +#endif + ((_drmCallback)entry->f)(entry->fd, oldctx, newctx); + ctx.handle = new; + ioctl(entry->fd, DRM_IOCTL_NEW_CTX, &ctx); + } + } while (drmHashNext(drmHashTable, &key, &value)); + } +} + +int drmInstallSIGIOHandler(int fd, void (*f)(int, void *, void *)) +{ + drmHashEntry *entry; + + entry = drmGetEntry(fd); + entry->f = f; + + return xf86InstallSIGIOHandler(fd, drmSIGIOHandler, 0); +} + +int drmRemoveSIGIOHandler(int fd) +{ + drmHashEntry *entry = drmGetEntry(fd); + + entry->f = NULL; + + return xf86RemoveSIGIOHandler(fd); +} +#endif diff --git a/nx-X11/extras/drm/libdrm/xf86drm.h b/nx-X11/extras/drm/libdrm/xf86drm.h new file mode 100644 index 000000000..4be417a62 --- /dev/null +++ b/nx-X11/extras/drm/libdrm/xf86drm.h @@ -0,0 +1,638 @@ +/** + * \file xf86drm.h + * OS-independent header for DRM user-level library interface. + * + * \author Rickard E. (Rik) Faith <faith@valinux.com> + */ + +/* + * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/xf86drm.h,v 1.26 2003/08/16 19:26:37 dawes Exp $ */ + +#ifndef _XF86DRM_H_ +#define _XF86DRM_H_ + +#include <drm.h> + + /* Defaults, if nothing set in xf86config */ +#define DRM_DEV_UID 0 +#define DRM_DEV_GID 0 +/* Default /dev/dri directory permissions 0755 */ +#define DRM_DEV_DIRMODE \ + (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) +#define DRM_DEV_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) + +#define DRM_DIR_NAME "/dev/dri" +#define DRM_DEV_NAME "%s/card%d" +#define DRM_PROC_NAME "/proc/dri/" /* For backward Linux compatibility */ + +#define DRM_ERR_NO_DEVICE (-1001) +#define DRM_ERR_NO_ACCESS (-1002) +#define DRM_ERR_NOT_ROOT (-1003) +#define DRM_ERR_INVALID (-1004) +#define DRM_ERR_NO_FD (-1005) + +#define DRM_AGP_NO_HANDLE 0 + +typedef unsigned int drmSize, *drmSizePtr; /**< For mapped regions */ +typedef void *drmAddress, **drmAddressPtr; /**< For mapped regions */ + +/** + * Driver version information. + * + * \sa drmGetVersion() and drmSetVersion(). + */ +typedef struct _drmVersion { + int version_major; /**< Major version */ + int version_minor; /**< Minor version */ + int version_patchlevel; /**< Patch level */ + int name_len; /**< Length of name buffer */ + char *name; /**< Name of driver */ + int date_len; /**< Length of date buffer */ + char *date; /**< User-space buffer to hold date */ + int desc_len; /**< Length of desc buffer */ + char *desc; /**< User-space buffer to hold desc */ +} drmVersion, *drmVersionPtr; + +typedef struct _drmStats { + unsigned long count; /**< Number of data */ + struct { + unsigned long value; /**< Value from kernel */ + const char *long_format; /**< Suggested format for long_name */ + const char *long_name; /**< Long name for value */ + const char *rate_format; /**< Suggested format for rate_name */ + const char *rate_name; /**< Short name for value per second */ + int isvalue; /**< True if value (vs. counter) */ + const char *mult_names; /**< Multiplier names (e.g., "KGM") */ + int mult; /**< Multiplier value (e.g., 1024) */ + int verbose; /**< Suggest only in verbose output */ + } data[15]; +} drmStatsT; + + + /* All of these enums *MUST* match with the + kernel implementation -- so do *NOT* + change them! (The drmlib implementation + will just copy the flags instead of + translating them.) */ +typedef enum { + DRM_FRAME_BUFFER = 0, /**< WC, no caching, no core dump */ + DRM_REGISTERS = 1, /**< no caching, no core dump */ + DRM_SHM = 2, /**< shared, cached */ + DRM_AGP = 3, /**< AGP/GART */ + DRM_SCATTER_GATHER = 4, /**< PCI scatter/gather */ + DRM_CONSISTENT = 5 /**< PCI consistent */ +} drmMapType; + +typedef enum { + DRM_RESTRICTED = 0x0001, /**< Cannot be mapped to client-virtual */ + DRM_READ_ONLY = 0x0002, /**< Read-only in client-virtual */ + DRM_LOCKED = 0x0004, /**< Physical pages locked */ + DRM_KERNEL = 0x0008, /**< Kernel requires access */ + DRM_WRITE_COMBINING = 0x0010, /**< Use write-combining, if available */ + DRM_CONTAINS_LOCK = 0x0020, /**< SHM page that contains lock */ + DRM_REMOVABLE = 0x0040 /**< Removable mapping */ +} drmMapFlags; + +/** + * \warning These values *MUST* match drm.h + */ +typedef enum { + /** \name Flags for DMA buffer dispatch */ + /*@{*/ + DRM_DMA_BLOCK = 0x01, /**< + * Block until buffer dispatched. + * + * \note the buffer may not yet have been + * processed by the hardware -- getting a + * hardware lock with the hardware quiescent + * will ensure that the buffer has been + * processed. + */ + DRM_DMA_WHILE_LOCKED = 0x02, /**< Dispatch while lock held */ + DRM_DMA_PRIORITY = 0x04, /**< High priority dispatch */ + /*@}*/ + + /** \name Flags for DMA buffer request */ + /*@{*/ + DRM_DMA_WAIT = 0x10, /**< Wait for free buffers */ + DRM_DMA_SMALLER_OK = 0x20, /**< Smaller-than-requested buffers OK */ + DRM_DMA_LARGER_OK = 0x40 /**< Larger-than-requested buffers OK */ + /*@}*/ +} drmDMAFlags; + +typedef enum { + DRM_PAGE_ALIGN = 0x01, + DRM_AGP_BUFFER = 0x02, + DRM_SG_BUFFER = 0x04, + DRM_FB_BUFFER = 0x08 +} drmBufDescFlags; + +typedef enum { + DRM_LOCK_READY = 0x01, /**< Wait until hardware is ready for DMA */ + DRM_LOCK_QUIESCENT = 0x02, /**< Wait until hardware quiescent */ + DRM_LOCK_FLUSH = 0x04, /**< Flush this context's DMA queue first */ + DRM_LOCK_FLUSH_ALL = 0x08, /**< Flush all DMA queues first */ + /* These *HALT* flags aren't supported yet + -- they will be used to support the + full-screen DGA-like mode. */ + DRM_HALT_ALL_QUEUES = 0x10, /**< Halt all current and future queues */ + DRM_HALT_CUR_QUEUES = 0x20 /**< Halt all current queues */ +} drmLockFlags; + +typedef enum { + DRM_CONTEXT_PRESERVED = 0x01, /**< This context is preserved and + never swapped. */ + DRM_CONTEXT_2DONLY = 0x02 /**< This context is for 2D rendering only. */ +} drm_context_tFlags, *drm_context_tFlagsPtr; + +typedef struct _drmBufDesc { + int count; /**< Number of buffers of this size */ + int size; /**< Size in bytes */ + int low_mark; /**< Low water mark */ + int high_mark; /**< High water mark */ +} drmBufDesc, *drmBufDescPtr; + +typedef struct _drmBufInfo { + int count; /**< Number of buffers described in list */ + drmBufDescPtr list; /**< List of buffer descriptions */ +} drmBufInfo, *drmBufInfoPtr; + +typedef struct _drmBuf { + int idx; /**< Index into the master buffer list */ + int total; /**< Buffer size */ + int used; /**< Amount of buffer in use (for DMA) */ + drmAddress address; /**< Address */ +} drmBuf, *drmBufPtr; + +/** + * Buffer mapping information. + * + * Used by drmMapBufs() and drmUnmapBufs() to store information about the + * mapped buffers. + */ +typedef struct _drmBufMap { + int count; /**< Number of buffers mapped */ + drmBufPtr list; /**< Buffers */ +} drmBufMap, *drmBufMapPtr; + +typedef struct _drmLock { + volatile unsigned int lock; + char padding[60]; + /* This is big enough for most current (and future?) architectures: + DEC Alpha: 32 bytes + Intel Merced: ? + Intel P5/PPro/PII/PIII: 32 bytes + Intel StrongARM: 32 bytes + Intel i386/i486: 16 bytes + MIPS: 32 bytes (?) + Motorola 68k: 16 bytes + Motorola PowerPC: 32 bytes + Sun SPARC: 32 bytes + */ +} drmLock, *drmLockPtr; + +/** + * Indices here refer to the offset into + * list in drmBufInfo + */ +typedef struct _drmDMAReq { + drm_context_t context; /**< Context handle */ + int send_count; /**< Number of buffers to send */ + int *send_list; /**< List of handles to buffers */ + int *send_sizes; /**< Lengths of data to send, in bytes */ + drmDMAFlags flags; /**< Flags */ + int request_count; /**< Number of buffers requested */ + int request_size; /**< Desired size of buffers requested */ + int *request_list; /**< Buffer information */ + int *request_sizes; /**< Minimum acceptable sizes */ + int granted_count; /**< Number of buffers granted at this size */ +} drmDMAReq, *drmDMAReqPtr; + +typedef struct _drmRegion { + drm_handle_t handle; + unsigned int offset; + drmSize size; + drmAddress map; +} drmRegion, *drmRegionPtr; + +typedef struct _drmTextureRegion { + unsigned char next; + unsigned char prev; + unsigned char in_use; + unsigned char padding; /**< Explicitly pad this out */ + unsigned int age; +} drmTextureRegion, *drmTextureRegionPtr; + + +typedef enum { + DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */ + DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */ + DRM_VBLANK_SIGNAL = 0x40000000 /* Send signal instead of blocking */ +} drmVBlankSeqType; + +typedef struct _drmVBlankReq { + drmVBlankSeqType type; + unsigned int sequence; + unsigned long signal; +} drmVBlankReq, *drmVBlankReqPtr; + +typedef struct _drmVBlankReply { + drmVBlankSeqType type; + unsigned int sequence; + long tval_sec; + long tval_usec; +} drmVBlankReply, *drmVBlankReplyPtr; + +typedef union _drmVBlank { + drmVBlankReq request; + drmVBlankReply reply; +} drmVBlank, *drmVBlankPtr; + +typedef struct _drmSetVersion { + int drm_di_major; + int drm_di_minor; + int drm_dd_major; + int drm_dd_minor; +} drmSetVersion, *drmSetVersionPtr; + + +#define __drm_dummy_lock(lock) (*(__volatile__ unsigned int *)lock) + +#define DRM_LOCK_HELD 0x80000000U /**< Hardware lock is held */ +#define DRM_LOCK_CONT 0x40000000U /**< Hardware lock is contended */ + +#if defined(__GNUC__) && (__GNUC__ >= 2) +# if defined(__i386) || defined(__AMD64__) || defined(__x86_64__) || defined(__amd64__) + /* Reflect changes here to drmP.h */ +#define DRM_CAS(lock,old,new,__ret) \ + do { \ + int __dummy; /* Can't mark eax as clobbered */ \ + __asm__ __volatile__( \ + "lock ; cmpxchg %4,%1\n\t" \ + "setnz %0" \ + : "=d" (__ret), \ + "=m" (__drm_dummy_lock(lock)), \ + "=a" (__dummy) \ + : "2" (old), \ + "r" (new)); \ + } while (0) + +#elif defined(__alpha__) + +#define DRM_CAS(lock, old, new, ret) \ + do { \ + int old32; \ + int cur32; \ + __asm__ __volatile__( \ + " mb\n" \ + " zap %4, 0xF0, %0\n" \ + " ldl_l %1, %2\n" \ + " zap %1, 0xF0, %1\n" \ + " cmpeq %0, %1, %1\n" \ + " beq %1, 1f\n" \ + " bis %5, %5, %1\n" \ + " stl_c %1, %2\n" \ + "1: xor %1, 1, %1\n" \ + " stl %1, %3" \ + : "=r" (old32), \ + "=&r" (cur32), \ + "=m" (__drm_dummy_lock(lock)),\ + "=m" (ret) \ + : "r" (old), \ + "r" (new)); \ + } while(0) + +#elif defined(__sparc__) + +#define DRM_CAS(lock,old,new,__ret) \ +do { register unsigned int __old __asm("o0"); \ + register unsigned int __new __asm("o1"); \ + register volatile unsigned int *__lock __asm("o2"); \ + __old = old; \ + __new = new; \ + __lock = (volatile unsigned int *)lock; \ + __asm__ __volatile__( \ + /*"cas [%2], %3, %0"*/ \ + ".word 0xd3e29008\n\t" \ + /*"membar #StoreStore | #StoreLoad"*/ \ + ".word 0x8143e00a" \ + : "=&r" (__new) \ + : "0" (__new), \ + "r" (__lock), \ + "r" (__old) \ + : "memory"); \ + __ret = (__new != __old); \ +} while(0) + +#elif defined(__ia64__) + +#ifdef __INTEL_COMPILER +/* this currently generates bad code (missing stop bits)... */ +#include <ia64intrin.h> + +#define DRM_CAS(lock,old,new,__ret) \ + do { \ + unsigned long __result, __old = (old) & 0xffffffff; \ + __mf(); \ + __result = _InterlockedCompareExchange_acq(&__drm_dummy_lock(lock), (new), __old);\ + __ret = (__result) != (__old); \ +/* __ret = (__sync_val_compare_and_swap(&__drm_dummy_lock(lock), \ + (old), (new)) \ + != (old)); */\ + } while (0) + +#else +#define DRM_CAS(lock,old,new,__ret) \ + do { \ + unsigned int __result, __old = (old); \ + __asm__ __volatile__( \ + "mf\n" \ + "mov ar.ccv=%2\n" \ + ";;\n" \ + "cmpxchg4.acq %0=%1,%3,ar.ccv" \ + : "=r" (__result), "=m" (__drm_dummy_lock(lock)) \ + : "r" ((unsigned long)__old), "r" (new) \ + : "memory"); \ + __ret = (__result) != (__old); \ + } while (0) + +#endif + +#elif defined(__powerpc__) + +#define DRM_CAS(lock,old,new,__ret) \ + do { \ + __asm__ __volatile__( \ + "sync;" \ + "0: lwarx %0,0,%1;" \ + " xor. %0,%3,%0;" \ + " bne 1f;" \ + " stwcx. %2,0,%1;" \ + " bne- 0b;" \ + "1: " \ + "sync;" \ + : "=&r"(__ret) \ + : "r"(lock), "r"(new), "r"(old) \ + : "cr0", "memory"); \ + } while (0) + +#endif /* architecture */ +#endif /* __GNUC__ >= 2 */ + +#ifndef DRM_CAS +#define DRM_CAS(lock,old,new,ret) do { ret=1; } while (0) /* FAST LOCK FAILS */ +#endif + +#if defined(__alpha__) || defined(__powerpc__) +#define DRM_CAS_RESULT(_result) int _result +#else +#define DRM_CAS_RESULT(_result) char _result +#endif + +#define DRM_LIGHT_LOCK(fd,lock,context) \ + do { \ + DRM_CAS_RESULT(__ret); \ + DRM_CAS(lock,context,DRM_LOCK_HELD|context,__ret); \ + if (__ret) drmGetLock(fd,context,0); \ + } while(0) + + /* This one counts fast locks -- for + benchmarking only. */ +#define DRM_LIGHT_LOCK_COUNT(fd,lock,context,count) \ + do { \ + DRM_CAS_RESULT(__ret); \ + DRM_CAS(lock,context,DRM_LOCK_HELD|context,__ret); \ + if (__ret) drmGetLock(fd,context,0); \ + else ++count; \ + } while(0) + +#define DRM_LOCK(fd,lock,context,flags) \ + do { \ + if (flags) drmGetLock(fd,context,flags); \ + else DRM_LIGHT_LOCK(fd,lock,context); \ + } while(0) + +#define DRM_UNLOCK(fd,lock,context) \ + do { \ + DRM_CAS_RESULT(__ret); \ + DRM_CAS(lock,DRM_LOCK_HELD|context,context,__ret); \ + if (__ret) drmUnlock(fd,context); \ + } while(0) + + /* Simple spin locks */ +#define DRM_SPINLOCK(spin,val) \ + do { \ + DRM_CAS_RESULT(__ret); \ + do { \ + DRM_CAS(spin,0,val,__ret); \ + if (__ret) while ((spin)->lock); \ + } while (__ret); \ + } while(0) + +#define DRM_SPINLOCK_TAKE(spin,val) \ + do { \ + DRM_CAS_RESULT(__ret); \ + int cur; \ + do { \ + cur = (*spin).lock; \ + DRM_CAS(spin,cur,val,__ret); \ + } while (__ret); \ + } while(0) + +#define DRM_SPINLOCK_COUNT(spin,val,count,__ret) \ + do { \ + int __i; \ + __ret = 1; \ + for (__i = 0; __ret && __i < count; __i++) { \ + DRM_CAS(spin,0,val,__ret); \ + if (__ret) for (;__i < count && (spin)->lock; __i++); \ + } \ + } while(0) + +#define DRM_SPINUNLOCK(spin,val) \ + do { \ + DRM_CAS_RESULT(__ret); \ + if ((*spin).lock == val) { /* else server stole lock */ \ + do { \ + DRM_CAS(spin,val,0,__ret); \ + } while (__ret); \ + } \ + } while(0) + +/* General user-level programmer's API: unprivileged */ +extern int drmAvailable(void); +extern int drmOpen(const char *name, const char *busid); +extern int drmClose(int fd); +extern drmVersionPtr drmGetVersion(int fd); +extern drmVersionPtr drmGetLibVersion(int fd); +extern void drmFreeVersion(drmVersionPtr); +extern int drmGetMagic(int fd, drm_magic_t * magic); +extern char *drmGetBusid(int fd); +extern int drmGetInterruptFromBusID(int fd, int busnum, int devnum, + int funcnum); +extern int drmGetMap(int fd, int idx, drm_handle_t *offset, + drmSize *size, drmMapType *type, + drmMapFlags *flags, drm_handle_t *handle, + int *mtrr); +extern int drmGetClient(int fd, int idx, int *auth, int *pid, + int *uid, unsigned long *magic, + unsigned long *iocs); +extern int drmGetStats(int fd, drmStatsT *stats); +extern int drmSetInterfaceVersion(int fd, drmSetVersion *version); +extern int drmCommandNone(int fd, unsigned long drmCommandIndex); +extern int drmCommandRead(int fd, unsigned long drmCommandIndex, + void *data, unsigned long size); +extern int drmCommandWrite(int fd, unsigned long drmCommandIndex, + void *data, unsigned long size); +extern int drmCommandWriteRead(int fd, unsigned long drmCommandIndex, + void *data, unsigned long size); + +/* General user-level programmer's API: X server (root) only */ +extern void drmFreeBusid(const char *busid); +extern int drmSetBusid(int fd, const char *busid); +extern int drmAuthMagic(int fd, drm_magic_t magic); +extern int drmAddMap(int fd, + drm_handle_t offset, + drmSize size, + drmMapType type, + drmMapFlags flags, + drm_handle_t * handle); +extern int drmRmMap(int fd, drm_handle_t handle); +extern int drmAddContextPrivateMapping(int fd, drm_context_t ctx_id, + drm_handle_t handle); + +extern int drmAddBufs(int fd, int count, int size, + drmBufDescFlags flags, + int agp_offset); +extern int drmMarkBufs(int fd, double low, double high); +extern int drmCreateContext(int fd, drm_context_t * handle); +extern int drmSetContextFlags(int fd, drm_context_t context, + drm_context_tFlags flags); +extern int drmGetContextFlags(int fd, drm_context_t context, + drm_context_tFlagsPtr flags); +extern int drmAddContextTag(int fd, drm_context_t context, void *tag); +extern int drmDelContextTag(int fd, drm_context_t context); +extern void *drmGetContextTag(int fd, drm_context_t context); +extern drm_context_t * drmGetReservedContextList(int fd, int *count); +extern void drmFreeReservedContextList(drm_context_t *); +extern int drmSwitchToContext(int fd, drm_context_t context); +extern int drmDestroyContext(int fd, drm_context_t handle); +extern int drmCreateDrawable(int fd, drm_drawable_t * handle); +extern int drmDestroyDrawable(int fd, drm_drawable_t handle); +extern int drmCtlInstHandler(int fd, int irq); +extern int drmCtlUninstHandler(int fd); +extern int drmInstallSIGIOHandler(int fd, + void (*f)(int fd, + void *oldctx, + void *newctx)); +extern int drmRemoveSIGIOHandler(int fd); + +/* General user-level programmer's API: authenticated client and/or X */ +extern int drmMap(int fd, + drm_handle_t handle, + drmSize size, + drmAddressPtr address); +extern int drmUnmap(drmAddress address, drmSize size); +extern drmBufInfoPtr drmGetBufInfo(int fd); +extern drmBufMapPtr drmMapBufs(int fd); +extern int drmUnmapBufs(drmBufMapPtr bufs); +extern int drmDMA(int fd, drmDMAReqPtr request); +extern int drmFreeBufs(int fd, int count, int *list); +extern int drmGetLock(int fd, + drm_context_t context, + drmLockFlags flags); +extern int drmUnlock(int fd, drm_context_t context); +extern int drmFinish(int fd, int context, drmLockFlags flags); +extern int drmGetContextPrivateMapping(int fd, drm_context_t ctx_id, + drm_handle_t * handle); + +/* AGP/GART support: X server (root) only */ +extern int drmAgpAcquire(int fd); +extern int drmAgpRelease(int fd); +extern int drmAgpEnable(int fd, unsigned long mode); +extern int drmAgpAlloc(int fd, unsigned long size, + unsigned long type, unsigned long *address, + drm_handle_t *handle); +extern int drmAgpFree(int fd, drm_handle_t handle); +extern int drmAgpBind(int fd, drm_handle_t handle, + unsigned long offset); +extern int drmAgpUnbind(int fd, drm_handle_t handle); + +/* AGP/GART info: authenticated client and/or X */ +extern int drmAgpVersionMajor(int fd); +extern int drmAgpVersionMinor(int fd); +extern unsigned long drmAgpGetMode(int fd); +extern unsigned long drmAgpBase(int fd); /* Physical location */ +extern unsigned long drmAgpSize(int fd); /* Bytes */ +extern unsigned long drmAgpMemoryUsed(int fd); +extern unsigned long drmAgpMemoryAvail(int fd); +extern unsigned int drmAgpVendorId(int fd); +extern unsigned int drmAgpDeviceId(int fd); + +/* PCI scatter/gather support: X server (root) only */ +extern int drmScatterGatherAlloc(int fd, unsigned long size, + drm_handle_t *handle); +extern int drmScatterGatherFree(int fd, drm_handle_t handle); + +extern int drmWaitVBlank(int fd, drmVBlankPtr vbl); + +/* Support routines */ +extern int drmError(int err, const char *label); +extern void *drmMalloc(int size); +extern void drmFree(void *pt); + +/* Hash table routines */ +extern void *drmHashCreate(void); +extern int drmHashDestroy(void *t); +extern int drmHashLookup(void *t, unsigned long key, void **value); +extern int drmHashInsert(void *t, unsigned long key, void *value); +extern int drmHashDelete(void *t, unsigned long key); +extern int drmHashFirst(void *t, unsigned long *key, void **value); +extern int drmHashNext(void *t, unsigned long *key, void **value); + +/* PRNG routines */ +extern void *drmRandomCreate(unsigned long seed); +extern int drmRandomDestroy(void *state); +extern unsigned long drmRandom(void *state); +extern double drmRandomDouble(void *state); + +/* Skip list routines */ + +extern void *drmSLCreate(void); +extern int drmSLDestroy(void *l); +extern int drmSLLookup(void *l, unsigned long key, void **value); +extern int drmSLInsert(void *l, unsigned long key, void *value); +extern int drmSLDelete(void *l, unsigned long key); +extern int drmSLNext(void *l, unsigned long *key, void **value); +extern int drmSLFirst(void *l, unsigned long *key, void **value); +extern void drmSLDump(void *l); +extern int drmSLLookupNeighbors(void *l, unsigned long key, + unsigned long *prev_key, void **prev_value, + unsigned long *next_key, void **next_value); + +#endif diff --git a/nx-X11/extras/drm/libdrm/xf86drmCompat.c b/nx-X11/extras/drm/libdrm/xf86drmCompat.c new file mode 100644 index 000000000..d284941b6 --- /dev/null +++ b/nx-X11/extras/drm/libdrm/xf86drmCompat.c @@ -0,0 +1,1079 @@ +/* xf86drmCompat.c -- User-level interface to old DRM device drivers + * + * Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Backwards compatability modules broken out by: + * Jens Owen <jens@tungstengraphics.com> + * + */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drmCompat.c,v 1.1 2002/10/30 12:52:33 alanh Exp $ */ + +#ifdef XFree86Server +# include "xf86.h" +# include "xf86_OSproc.h" +# include "xf86_ansic.h" +# define _DRM_MALLOC xalloc +# define _DRM_FREE xfree +# ifndef XFree86LOADER +# include <sys/mman.h> +# endif +#else +# include <stdio.h> +# include <stdlib.h> +# include <unistd.h> +# include <string.h> +# include <ctype.h> +# include <fcntl.h> +# include <errno.h> +# include <signal.h> +# include <sys/types.h> +# include <sys/ioctl.h> +# include <sys/mman.h> +# include <sys/time.h> +# ifdef DRM_USE_MALLOC +# define _DRM_MALLOC malloc +# define _DRM_FREE free +extern int xf86InstallSIGIOHandler(int fd, void (*f)(int, void *), void *); +extern int xf86RemoveSIGIOHandler(int fd); +# else +# include <X11/Xlibint.h> +# define _DRM_MALLOC Xmalloc +# define _DRM_FREE Xfree +# endif +#endif + +/* Not all systems have MAP_FAILED defined */ +#ifndef MAP_FAILED +#define MAP_FAILED ((void *)-1) +#endif + +#ifdef __linux__ +#include <sys/sysmacros.h> /* for makedev() */ +#endif +#include "drm.h" +#include "xf86drm.h" +#include "xf86drmCompat.h" +#include "mga_drm.h" +#include "r128_drm.h" +#include <inttypes.h> /* for int64_t & friends */ +#include "radeon_drm.h" +#ifndef __FreeBSD__ +#include "sis_drm.h" +#include "i810_drm.h" +#include "i830_drm.h" +#endif + +/* WARNING: Do not change, or add, anything to this file. It is only provided + * for binary backwards compatability with the old driver specific DRM + * extensions used before XFree86 4.3. + */ + +#ifndef __FreeBSD__ +/* I810 */ + +Bool drmI810CleanupDma(int driSubFD) +{ + drm_i810_init_t init; + + memset(&init, 0, sizeof(drm_i810_init_t)); + init.func = I810_CLEANUP_DMA; + + if(ioctl(driSubFD, DRM_IOCTL_I810_INIT, &init)) { + return 0; /* FALSE */ + } + + return 1; /* TRUE */ +} + +Bool drmI810InitDma(int driSubFD, drmCompatI810Init *info) +{ + drm_i810_init_t init; + + memset(&init, 0, sizeof(drm_i810_init_t)); + + init.func = I810_INIT_DMA; + init.mmio_offset = info->mmio_offset; + init.buffers_offset = info->buffers_offset; + init.ring_start = info->start; + init.ring_end = info->end; + init.ring_size = info->size; + init.sarea_priv_offset = info->sarea_off; + init.front_offset = info->front_offset; + init.back_offset = info->back_offset; + init.depth_offset = info->depth_offset; + init.overlay_offset = info->overlay_offset; + init.overlay_physical = info->overlay_physical; + init.w = info->w; + init.h = info->h; + init.pitch = info->pitch; + init.pitch_bits = info->pitch_bits; + + if(ioctl(driSubFD, DRM_IOCTL_I810_INIT, &init)) { + return 0; /* FALSE */ + } + return 1; /* TRUE */ +} +#endif /* __FreeBSD__ */ + +/* Mga */ + +#define MGA_IDLE_RETRY 2048 + +int drmMGAInitDMA( int fd, drmCompatMGAInit *info ) +{ + drm_mga_init_t init; + + memset( &init, 0, sizeof(drm_mga_init_t) ); + + init.func = MGA_INIT_DMA; + + init.sarea_priv_offset = info->sarea_priv_offset; + init.sgram = info->sgram; + init.chipset = info->chipset; + init.maccess = info->maccess; + + init.fb_cpp = info->fb_cpp; + init.front_offset = info->front_offset; + init.front_pitch = info->front_pitch; + init.back_offset = info->back_offset; + init.back_pitch = info->back_pitch; + + init.depth_cpp = info->depth_cpp; + init.depth_offset = info->depth_offset; + init.depth_pitch = info->depth_pitch; + + init.texture_offset[0] = info->texture_offset[0]; + init.texture_size[0] = info->texture_size[0]; + init.texture_offset[1] = info->texture_offset[1]; + init.texture_size[1] = info->texture_size[1]; + + init.fb_offset = info->fb_offset; + init.mmio_offset = info->mmio_offset; + init.status_offset = info->status_offset; + init.warp_offset = info->warp_offset; + init.primary_offset = info->primary_offset; + init.buffers_offset = info->buffers_offset; + + if ( ioctl( fd, DRM_IOCTL_MGA_INIT, &init ) ) { + return -errno; + } else { + return 0; + } +} + +int drmMGACleanupDMA( int fd ) +{ + drm_mga_init_t init; + + memset( &init, 0, sizeof(drm_mga_init_t) ); + + init.func = MGA_CLEANUP_DMA; + + if ( ioctl( fd, DRM_IOCTL_MGA_INIT, &init ) ) { + return -errno; + } else { + return 0; + } +} + +int drmMGAFlushDMA( int fd, drmLockFlags flags ) +{ + drm_lock_t lock; + int ret, i = 0; + + memset( &lock, 0, sizeof(drm_lock_t) ); + + if ( flags & DRM_LOCK_QUIESCENT ) lock.flags |= _DRM_LOCK_QUIESCENT; + if ( flags & DRM_LOCK_FLUSH ) lock.flags |= _DRM_LOCK_FLUSH; + if ( flags & DRM_LOCK_FLUSH_ALL ) lock.flags |= _DRM_LOCK_FLUSH_ALL; + + do { + ret = ioctl( fd, DRM_IOCTL_MGA_FLUSH, &lock ); + } while ( ret && errno == EBUSY && i++ < MGA_IDLE_RETRY ); + + if ( ret == 0 ) + return 0; + if ( errno != EBUSY ) + return -errno; + + if ( lock.flags & _DRM_LOCK_QUIESCENT ) { + /* Only keep trying if we need quiescence. + */ + lock.flags &= ~(_DRM_LOCK_FLUSH | _DRM_LOCK_FLUSH_ALL); + + do { + ret = ioctl( fd, DRM_IOCTL_MGA_FLUSH, &lock ); + } while ( ret && errno == EBUSY && i++ < MGA_IDLE_RETRY ); + } + + if ( ret == 0 ) { + return 0; + } else { + return -errno; + } +} + +int drmMGAEngineReset( int fd ) +{ + if ( ioctl( fd, DRM_IOCTL_MGA_RESET, NULL ) ) { + return -errno; + } else { + return 0; + } +} + +int drmMGAFullScreen( int fd, int enable ) +{ + return -EINVAL; +} + +int drmMGASwapBuffers( int fd ) +{ + int ret, i = 0; + + do { + ret = ioctl( fd, DRM_IOCTL_MGA_SWAP, NULL ); + } while ( ret && errno == EBUSY && i++ < MGA_IDLE_RETRY ); + + if ( ret == 0 ) { + return 0; + } else { + return -errno; + } +} + +int drmMGAClear( int fd, unsigned int flags, + unsigned int clear_color, unsigned int clear_depth, + unsigned int color_mask, unsigned int depth_mask ) +{ + drm_mga_clear_t clear; + int ret, i = 0; + + clear.flags = flags; + clear.clear_color = clear_color; + clear.clear_depth = clear_depth; + clear.color_mask = color_mask; + clear.depth_mask = depth_mask; + + do { + ret = ioctl( fd, DRM_IOCTL_MGA_CLEAR, &clear ); + } while ( ret && errno == EBUSY && i++ < MGA_IDLE_RETRY ); + + if ( ret == 0 ) { + return 0; + } else { + return -errno; + } +} + +int drmMGAFlushVertexBuffer( int fd, int index, int used, int discard ) +{ + drm_mga_vertex_t vertex; + + vertex.idx = index; + vertex.used = used; + vertex.discard = discard; + + if ( ioctl( fd, DRM_IOCTL_MGA_VERTEX, &vertex ) ) { + return -errno; + } else { + return 0; + } +} + +int drmMGAFlushIndices( int fd, int index, int start, int end, int discard ) +{ + drm_mga_indices_t indices; + + indices.idx = index; + indices.start = start; + indices.end = end; + indices.discard = discard; + + if ( ioctl( fd, DRM_IOCTL_MGA_INDICES, &indices ) ) { + return -errno; + } else { + return 0; + } +} + +int drmMGATextureLoad( int fd, int index, + unsigned int dstorg, unsigned int length ) +{ + drm_mga_iload_t iload; + int ret, i = 0; + + iload.idx = index; + iload.dstorg = dstorg; + iload.length = length; + + do { + ret = ioctl( fd, DRM_IOCTL_MGA_ILOAD, &iload ); + } while ( ret && errno == EBUSY && i++ < MGA_IDLE_RETRY ); + + if ( ret == 0 ) { + return 0; + } else { + return -errno; + } +} + +int drmMGAAgpBlit( int fd, unsigned int planemask, + unsigned int src_offset, int src_pitch, + unsigned int dst_offset, int dst_pitch, + int delta_sx, int delta_sy, + int delta_dx, int delta_dy, + int height, int ydir ) +{ + drm_mga_blit_t blit; + int ret, i = 0; + + blit.planemask = planemask; + blit.srcorg = src_offset; + blit.dstorg = dst_offset; + blit.src_pitch = src_pitch; + blit.dst_pitch = dst_pitch; + blit.delta_sx = delta_sx; + blit.delta_sy = delta_sy; + blit.delta_dx = delta_dx; + blit.delta_dx = delta_dx; + blit.height = height; + blit.ydir = ydir; + + do { + ret = ioctl( fd, DRM_IOCTL_MGA_BLIT, &blit ); + } while ( ret && errno == EBUSY && i++ < MGA_IDLE_RETRY ); + + if ( ret == 0 ) { + return 0; + } else { + return -errno; + } +} + +/* R128 */ + +#define R128_BUFFER_RETRY 32 +#define R128_IDLE_RETRY 32 + +int drmR128InitCCE( int fd, drmCompatR128Init *info ) +{ + drm_r128_init_t init; + + memset( &init, 0, sizeof(drm_r128_init_t) ); + + init.func = R128_INIT_CCE; + init.sarea_priv_offset = info->sarea_priv_offset; + init.is_pci = info->is_pci; + init.cce_mode = info->cce_mode; + init.cce_secure = info->cce_secure; + init.ring_size = info->ring_size; + init.usec_timeout = info->usec_timeout; + + init.fb_bpp = info->fb_bpp; + init.front_offset = info->front_offset; + init.front_pitch = info->front_pitch; + init.back_offset = info->back_offset; + init.back_pitch = info->back_pitch; + + init.depth_bpp = info->depth_bpp; + init.depth_offset = info->depth_offset; + init.depth_pitch = info->depth_pitch; + init.span_offset = info->span_offset; + + init.fb_offset = info->fb_offset; + init.mmio_offset = info->mmio_offset; + init.ring_offset = info->ring_offset; + init.ring_rptr_offset = info->ring_rptr_offset; + init.buffers_offset = info->buffers_offset; + init.agp_textures_offset = info->agp_textures_offset; + + if ( ioctl( fd, DRM_IOCTL_R128_INIT, &init ) ) { + return -errno; + } else { + return 0; + } +} + +int drmR128CleanupCCE( int fd ) +{ + drm_r128_init_t init; + + memset( &init, 0, sizeof(drm_r128_init_t) ); + + init.func = R128_CLEANUP_CCE; + + if ( ioctl( fd, DRM_IOCTL_R128_INIT, &init ) ) { + return -errno; + } else { + return 0; + } +} + +int drmR128StartCCE( int fd ) +{ + if ( ioctl( fd, DRM_IOCTL_R128_CCE_START, NULL ) ) { + return -errno; + } else { + return 0; + } +} + +int drmR128StopCCE( int fd ) +{ + drm_r128_cce_stop_t stop; + int ret, i = 0; + + stop.flush = 1; + stop.idle = 1; + + ret = ioctl( fd, DRM_IOCTL_R128_CCE_STOP, &stop ); + + if ( ret == 0 ) { + return 0; + } else if ( errno != EBUSY ) { + return -errno; + } + + stop.flush = 0; + + do { + ret = ioctl( fd, DRM_IOCTL_R128_CCE_STOP, &stop ); + } while ( ret && errno == EBUSY && i++ < R128_IDLE_RETRY ); + + if ( ret == 0 ) { + return 0; + } else if ( errno != EBUSY ) { + return -errno; + } + + stop.idle = 0; + + if ( ioctl( fd, DRM_IOCTL_R128_CCE_STOP, &stop ) ) { + return -errno; + } else { + return 0; + } +} + +int drmR128ResetCCE( int fd ) +{ + if ( ioctl( fd, DRM_IOCTL_R128_CCE_RESET, NULL ) ) { + return -errno; + } else { + return 0; + } +} + +int drmR128WaitForIdleCCE( int fd ) +{ + int ret, i = 0; + + do { + ret = ioctl( fd, DRM_IOCTL_R128_CCE_IDLE, NULL ); + } while ( ret && errno == EBUSY && i++ < R128_IDLE_RETRY ); + + if ( ret == 0 ) { + return 0; + } else { + return -errno; + } +} + +int drmR128EngineReset( int fd ) +{ + if ( ioctl( fd, DRM_IOCTL_R128_RESET, NULL ) ) { + return -errno; + } else { + return 0; + } +} + +int drmR128FullScreen( int fd, int enable ) +{ + drm_r128_fullscreen_t fs; + + if ( enable ) { + fs.func = R128_INIT_FULLSCREEN; + } else { + fs.func = R128_CLEANUP_FULLSCREEN; + } + + if ( ioctl( fd, DRM_IOCTL_R128_FULLSCREEN, &fs ) ) { + return -errno; + } else { + return 0; + } +} + +int drmR128SwapBuffers( int fd ) +{ + if ( ioctl( fd, DRM_IOCTL_R128_SWAP, NULL ) ) { + return -errno; + } else { + return 0; + } +} + +int drmR128Clear( int fd, unsigned int flags, + unsigned int clear_color, unsigned int clear_depth, + unsigned int color_mask, unsigned int depth_mask ) +{ + drm_r128_clear_t clear; + + clear.flags = flags; + clear.clear_color = clear_color; + clear.clear_depth = clear_depth; + clear.color_mask = color_mask; + clear.depth_mask = depth_mask; + + if ( ioctl( fd, DRM_IOCTL_R128_CLEAR, &clear ) < 0 ) { + return -errno; + } else { + return 0; + } +} + +int drmR128FlushVertexBuffer( int fd, int prim, int index, + int count, int discard ) +{ + drm_r128_vertex_t v; + + v.prim = prim; + v.idx = index; + v.count = count; + v.discard = discard; + + if ( ioctl( fd, DRM_IOCTL_R128_VERTEX, &v ) < 0 ) { + return -errno; + } else { + return 0; + } +} + +int drmR128FlushIndices( int fd, int prim, int index, + int start, int end, int discard ) +{ + drm_r128_indices_t elts; + + elts.prim = prim; + elts.idx = index; + elts.start = start; + elts.end = end; + elts.discard = discard; + + if ( ioctl( fd, DRM_IOCTL_R128_INDICES, &elts ) < 0 ) { + return -errno; + } else { + return 0; + } +} + +int drmR128TextureBlit( int fd, int index, + int offset, int pitch, int format, + int x, int y, int width, int height ) +{ + drm_r128_blit_t blit; + + blit.idx = index; + blit.offset = offset; + blit.pitch = pitch; + blit.format = format; + blit.x = x; + blit.y = y; + blit.width = width; + blit.height = height; + + if ( ioctl( fd, DRM_IOCTL_R128_BLIT, &blit ) < 0 ) { + return -errno; + } else { + return 0; + } +} + +int drmR128WriteDepthSpan( int fd, int n, int x, int y, + const unsigned int depth[], + const unsigned char mask[] ) +{ + drm_r128_depth_t d; + + d.func = R128_WRITE_SPAN; + d.n = n; + d.x = &x; + d.y = &y; + d.buffer = (unsigned int *)depth; + d.mask = (unsigned char *)mask; + + if ( ioctl( fd, DRM_IOCTL_R128_DEPTH, &d ) < 0 ) { + return -errno; + } else { + return 0; + } +} + +int drmR128WriteDepthPixels( int fd, int n, + const int x[], const int y[], + const unsigned int depth[], + const unsigned char mask[] ) +{ + drm_r128_depth_t d; + + d.func = R128_WRITE_PIXELS; + d.n = n; + d.x = (int *)x; + d.y = (int *)y; + d.buffer = (unsigned int *)depth; + d.mask = (unsigned char *)mask; + + if ( ioctl( fd, DRM_IOCTL_R128_DEPTH, &d ) < 0 ) { + return -errno; + } else { + return 0; + } +} + +int drmR128ReadDepthSpan( int fd, int n, int x, int y ) +{ + drm_r128_depth_t d; + + d.func = R128_READ_SPAN; + d.n = n; + d.x = &x; + d.y = &y; + d.buffer = NULL; + d.mask = NULL; + + if ( ioctl( fd, DRM_IOCTL_R128_DEPTH, &d ) < 0 ) { + return -errno; + } else { + return 0; + } +} + +int drmR128ReadDepthPixels( int fd, int n, + const int x[], const int y[] ) +{ + drm_r128_depth_t d; + + d.func = R128_READ_PIXELS; + d.n = n; + d.x = (int *)x; + d.y = (int *)y; + d.buffer = NULL; + d.mask = NULL; + + if ( ioctl( fd, DRM_IOCTL_R128_DEPTH, &d ) < 0 ) { + return -errno; + } else { + return 0; + } +} + +int drmR128PolygonStipple( int fd, unsigned int *mask ) +{ + drm_r128_stipple_t stipple; + + stipple.mask = mask; + + if ( ioctl( fd, DRM_IOCTL_R128_STIPPLE, &stipple ) < 0 ) { + return -errno; + } else { + return 0; + } +} + +int drmR128FlushIndirectBuffer( int fd, int index, + int start, int end, int discard ) +{ + drm_r128_indirect_t ind; + + ind.idx = index; + ind.start = start; + ind.end = end; + ind.discard = discard; + + if ( ioctl( fd, DRM_IOCTL_R128_INDIRECT, &ind ) < 0 ) { + return -errno; + } else { + return 0; + } +} + +/* Radeon */ + +#define RADEON_BUFFER_RETRY 32 +#define RADEON_IDLE_RETRY 16 + +int drmRadeonInitCP( int fd, drmCompatRadeonInit *info ) +{ + drm_radeon_init_t init; + + memset( &init, 0, sizeof(drm_radeon_init_t) ); + + init.func = RADEON_INIT_CP; + init.sarea_priv_offset = info->sarea_priv_offset; + init.is_pci = info->is_pci; + init.cp_mode = info->cp_mode; + init.gart_size = info->agp_size; + init.ring_size = info->ring_size; + init.usec_timeout = info->usec_timeout; + + init.fb_bpp = info->fb_bpp; + init.front_offset = info->front_offset; + init.front_pitch = info->front_pitch; + init.back_offset = info->back_offset; + init.back_pitch = info->back_pitch; + + init.depth_bpp = info->depth_bpp; + init.depth_offset = info->depth_offset; + init.depth_pitch = info->depth_pitch; + + init.fb_offset = info->fb_offset; + init.mmio_offset = info->mmio_offset; + init.ring_offset = info->ring_offset; + init.ring_rptr_offset = info->ring_rptr_offset; + init.buffers_offset = info->buffers_offset; + init.gart_textures_offset = info->agp_textures_offset; + + if ( ioctl( fd, DRM_IOCTL_RADEON_CP_INIT, &init ) ) { + return -errno; + } else { + return 0; + } +} + +int drmRadeonCleanupCP( int fd ) +{ + drm_radeon_init_t init; + + memset( &init, 0, sizeof(drm_radeon_init_t) ); + + init.func = RADEON_CLEANUP_CP; + + if ( ioctl( fd, DRM_IOCTL_RADEON_CP_INIT, &init ) ) { + return -errno; + } else { + return 0; + } +} + +int drmRadeonStartCP( int fd ) +{ + if ( ioctl( fd, DRM_IOCTL_RADEON_CP_START, NULL ) ) { + return -errno; + } else { + return 0; + } +} + +int drmRadeonStopCP( int fd ) +{ + drm_radeon_cp_stop_t stop; + int ret, i = 0; + + stop.flush = 1; + stop.idle = 1; + + ret = ioctl( fd, DRM_IOCTL_RADEON_CP_STOP, &stop ); + + if ( ret == 0 ) { + return 0; + } else if ( errno != EBUSY ) { + return -errno; + } + + stop.flush = 0; + + do { + ret = ioctl( fd, DRM_IOCTL_RADEON_CP_STOP, &stop ); + } while ( ret && errno == EBUSY && i++ < RADEON_IDLE_RETRY ); + + if ( ret == 0 ) { + return 0; + } else if ( errno != EBUSY ) { + return -errno; + } + + stop.idle = 0; + + if ( ioctl( fd, DRM_IOCTL_RADEON_CP_STOP, &stop ) ) { + return -errno; + } else { + return 0; + } +} + +int drmRadeonResetCP( int fd ) +{ + if ( ioctl( fd, DRM_IOCTL_RADEON_CP_RESET, NULL ) ) { + return -errno; + } else { + return 0; + } +} + +int drmRadeonWaitForIdleCP( int fd ) +{ + int ret, i = 0; + + do { + ret = ioctl( fd, DRM_IOCTL_RADEON_CP_IDLE, NULL ); + } while ( ret && errno == EBUSY && i++ < RADEON_IDLE_RETRY ); + + if ( ret == 0 ) { + return 0; + } else { + return -errno; + } +} + +int drmRadeonEngineReset( int fd ) +{ + if ( ioctl( fd, DRM_IOCTL_RADEON_RESET, NULL ) ) { + return -errno; + } else { + return 0; + } +} + +int drmRadeonFullScreen( int fd, int enable ) +{ + drm_radeon_fullscreen_t fs; + + if ( enable ) { + fs.func = RADEON_INIT_FULLSCREEN; + } else { + fs.func = RADEON_CLEANUP_FULLSCREEN; + } + + if ( ioctl( fd, DRM_IOCTL_RADEON_FULLSCREEN, &fs ) ) { + return -errno; + } else { + return 0; + } +} + +int drmRadeonSwapBuffers( int fd ) +{ + if ( ioctl( fd, DRM_IOCTL_RADEON_SWAP, NULL ) ) { + return -errno; + } else { + return 0; + } +} + +int drmRadeonClear( int fd, unsigned int flags, + unsigned int clear_color, unsigned int clear_depth, + unsigned int color_mask, unsigned int stencil, + void *b, int nbox ) +{ + drm_radeon_clear_t clear; + drm_radeon_clear_rect_t depth_boxes[RADEON_NR_SAREA_CLIPRECTS]; + drm_clip_rect_t *boxes = (drm_clip_rect_t *)b; + int i; + + clear.flags = flags; + clear.clear_color = clear_color; + clear.clear_depth = clear_depth; + clear.color_mask = color_mask; + clear.depth_mask = stencil; /* misnamed field in ioctl */ + clear.depth_boxes = depth_boxes; + + /* We can remove this when we do real depth clears, instead of + * rendering a rectangle into the depth buffer. This prevents + * floating point calculations being done in the kernel. + */ + for ( i = 0 ; i < nbox ; i++ ) { + depth_boxes[i].f[CLEAR_X1] = (float)boxes[i].x1; + depth_boxes[i].f[CLEAR_Y1] = (float)boxes[i].y1; + depth_boxes[i].f[CLEAR_X2] = (float)boxes[i].x2; + depth_boxes[i].f[CLEAR_Y2] = (float)boxes[i].y2; + depth_boxes[i].f[CLEAR_DEPTH] = (float)clear_depth; + } + + if ( ioctl( fd, DRM_IOCTL_RADEON_CLEAR, &clear ) < 0 ) { + return -errno; + } else { + return 0; + } +} + +int drmRadeonFlushVertexBuffer( int fd, int prim, int index, + int count, int discard ) +{ + drm_radeon_vertex_t v; + + v.prim = prim; + v.idx = index; + v.count = count; + v.discard = discard; + + if ( ioctl( fd, DRM_IOCTL_RADEON_VERTEX, &v ) < 0 ) { + return -errno; + } else { + return 0; + } +} + +int drmRadeonFlushIndices( int fd, int prim, int index, + int start, int end, int discard ) +{ + drm_radeon_indices_t elts; + + elts.prim = prim; + elts.idx = index; + elts.start = start; + elts.end = end; + elts.discard = discard; + + if ( ioctl( fd, DRM_IOCTL_RADEON_INDICES, &elts ) < 0 ) { + return -errno; + } else { + return 0; + } +} + +int drmRadeonLoadTexture( int fd, int offset, int pitch, int format, int width, + int height, drmCompatRadeonTexImage *image ) +{ + drm_radeon_texture_t tex; + drm_radeon_tex_image_t tmp; + int ret; + + tex.offset = offset; + tex.pitch = pitch; + tex.format = format; + tex.width = width; + tex.height = height; + tex.image = &tmp; + + /* This gets updated by the kernel when a multipass blit is needed. + */ + memcpy( &tmp, image, sizeof(drm_radeon_tex_image_t) ); + + do { + ret = ioctl( fd, DRM_IOCTL_RADEON_TEXTURE, &tex ); + } while ( ret && errno == EAGAIN ); + + if ( ret == 0 ) { + return 0; + } else { + return -errno; + } +} + +int drmRadeonPolygonStipple( int fd, unsigned int *mask ) +{ + drm_radeon_stipple_t stipple; + + stipple.mask = mask; + + if ( ioctl( fd, DRM_IOCTL_RADEON_STIPPLE, &stipple ) < 0 ) { + return -errno; + } else { + return 0; + } +} + +int drmRadeonFlushIndirectBuffer( int fd, int index, + int start, int end, int discard ) +{ + drm_radeon_indirect_t ind; + + ind.idx = index; + ind.start = start; + ind.end = end; + ind.discard = discard; + + if ( ioctl( fd, DRM_IOCTL_RADEON_INDIRECT, &ind ) < 0 ) { + return -errno; + } else { + return 0; + } +} + +#ifndef __FreeBSD__ +/* SiS */ + +Bool drmSiSAgpInit(int driSubFD, int offset, int size) +{ + drm_sis_agp_t agp; + + agp.offset = offset; + agp.size = size; + ioctl(driSubFD, DRM_IOCTL_SIS_AGP_INIT, &agp); + + return 1; /* TRUE */ +} + +/* I830 */ + +Bool drmI830CleanupDma(int driSubFD) +{ + drm_i830_init_t init; + + memset(&init, 0, sizeof(drm_i830_init_t)); + init.func = I810_CLEANUP_DMA; + + if(ioctl(driSubFD, DRM_IOCTL_I830_INIT, &init)) { + return 0; /* FALSE */ + } + + return 1; /* TRUE */ +} + +Bool drmI830InitDma(int driSubFD, drmCompatI830Init *info) +{ + drm_i830_init_t init; + + memset(&init, 0, sizeof(drm_i830_init_t)); + + init.func = I810_INIT_DMA; + init.mmio_offset = info->mmio_offset; + init.buffers_offset = info->buffers_offset; + init.ring_start = info->start; + init.ring_end = info->end; + init.ring_size = info->size; + init.sarea_priv_offset = info->sarea_off; + init.front_offset = info->front_offset; + init.back_offset = info->back_offset; + init.depth_offset = info->depth_offset; + init.w = info->w; + init.h = info->h; + init.pitch = info->pitch; + init.pitch_bits = info->pitch_bits; + init.back_pitch = info->pitch; + init.depth_pitch = info->pitch; + init.cpp = info->cpp; + + if(ioctl(driSubFD, DRM_IOCTL_I830_INIT, &init)) { + return 0; /* FALSE */ + } + return 1; /* TRUE */ +} +#endif /* __FreeBSD__ */ + +/* WARNING: Do not change, or add, anything to this file. It is only provided + * for binary backwards compatability with the old driver specific DRM + * extensions used before XFree86 4.3. + */ diff --git a/nx-X11/extras/drm/libdrm/xf86drmCompat.h b/nx-X11/extras/drm/libdrm/xf86drmCompat.h new file mode 100644 index 000000000..bdca46626 --- /dev/null +++ b/nx-X11/extras/drm/libdrm/xf86drmCompat.h @@ -0,0 +1,259 @@ +/* xf86drmCompat.h -- OS-independent header for old device specific DRM user-level + * library interface + * + * Copyright 2000 VA Linux Systems, Inc., Fremont, California. + * Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Gareth Hughes <gareth@valinux.com> + * Kevin E. Martin <martin@valinux.com> + * Keith Whitwell <keith@tungstengraphics.com> + * + * Backwards compatability modules broken out by: + * Jens Owen <jens@tungstengraphics.com> + * + * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/xf86drmCompat.h,v 1.1 2002/10/30 12:52:23 alanh Exp $ + * + */ + +#ifndef _XF86DRI_COMPAT_H_ +#define _XF86DRI_COMPAT_H_ + +/* WARNING: Do not change, or add, anything to this file. It is only provided + * for binary backwards compatability with the old driver specific DRM + * extensions used before XFree86 4.3. + */ + +#ifndef __user +#define __user +#endif + +/* I810 */ + +typedef struct { + unsigned int start; + unsigned int end; + unsigned int size; + unsigned int mmio_offset; + unsigned int buffers_offset; + int sarea_off; + + unsigned int front_offset; + unsigned int back_offset; + unsigned int depth_offset; + unsigned int overlay_offset; + unsigned int overlay_physical; + unsigned int w; + unsigned int h; + unsigned int pitch; + unsigned int pitch_bits; +} drmCompatI810Init; + +extern Bool drmI810CleanupDma(int driSubFD); +extern Bool drmI810InitDma(int driSubFD, drmCompatI810Init *info ); + +/* Mga */ + +typedef struct { + unsigned long sarea_priv_offset; + int chipset; + int sgram; + unsigned int maccess; + unsigned int fb_cpp; + unsigned int front_offset, front_pitch; + unsigned int back_offset, back_pitch; + unsigned int depth_cpp; + unsigned int depth_offset, depth_pitch; + unsigned int texture_offset[2]; + unsigned int texture_size[2]; + unsigned long fb_offset; + unsigned long mmio_offset; + unsigned long status_offset; + unsigned long warp_offset; + unsigned long primary_offset; + unsigned long buffers_offset; +} drmCompatMGAInit; + +extern int drmMGAInitDMA( int fd, drmCompatMGAInit *info ); +extern int drmMGACleanupDMA( int fd ); +extern int drmMGAFlushDMA( int fd, drmLockFlags flags ); +extern int drmMGAEngineReset( int fd ); +extern int drmMGAFullScreen( int fd, int enable ); +extern int drmMGASwapBuffers( int fd ); +extern int drmMGAClear( int fd, unsigned int flags, + unsigned int clear_color, unsigned int clear_depth, + unsigned int color_mask, unsigned int depth_mask ); +extern int drmMGAFlushVertexBuffer( int fd, int indx, int used, int discard ); +extern int drmMGAFlushIndices( int fd, int indx, + int start, int end, int discard ); +extern int drmMGATextureLoad( int fd, int indx, + unsigned int dstorg, unsigned int length ); +extern int drmMGAAgpBlit( int fd, unsigned int planemask, + unsigned int src, int src_pitch, + unsigned int dst, int dst_pitch, + int delta_sx, int delta_sy, + int delta_dx, int delta_dy, + int height, int ydir ); + +/* R128 */ + +typedef struct { + unsigned long sarea_priv_offset; + int is_pci; + int cce_mode; + int cce_secure; + int ring_size; + int usec_timeout; + unsigned int fb_bpp; + unsigned int front_offset, front_pitch; + unsigned int back_offset, back_pitch; + unsigned int depth_bpp; + unsigned int depth_offset, depth_pitch; + unsigned int span_offset; + unsigned long fb_offset; + unsigned long mmio_offset; + unsigned long ring_offset; + unsigned long ring_rptr_offset; + unsigned long buffers_offset; + unsigned long agp_textures_offset; +} drmCompatR128Init; + +extern int drmR128InitCCE( int fd, drmCompatR128Init *info ); +extern int drmR128CleanupCCE( int fd ); +extern int drmR128StartCCE( int fd ); +extern int drmR128StopCCE( int fd ); +extern int drmR128ResetCCE( int fd ); +extern int drmR128WaitForIdleCCE( int fd ); +extern int drmR128EngineReset( int fd ); +extern int drmR128FullScreen( int fd, int enable ); +extern int drmR128SwapBuffers( int fd ); +extern int drmR128Clear( int fd, unsigned int flags, + unsigned int clear_color, unsigned int clear_depth, + unsigned int color_mask, unsigned int depth_mask ); +extern int drmR128FlushVertexBuffer( int fd, int prim, int indx, + int count, int discard ); +extern int drmR128FlushIndices( int fd, int prim, int indx, + int start, int end, int discard ); +extern int drmR128TextureBlit( int fd, int indx, + int offset, int pitch, int format, + int x, int y, int width, int height ); +extern int drmR128WriteDepthSpan( int fd, int n, int x, int y, + const unsigned int depth[], + const unsigned char mask[] ); +extern int drmR128WriteDepthPixels( int fd, int n, + const int x[], const int y[], + const unsigned int depth[], + const unsigned char mask[] ); +extern int drmR128ReadDepthSpan( int fd, int n, int x, int y ); +extern int drmR128ReadDepthPixels( int fd, int n, + const int x[], const int y[] ); +extern int drmR128PolygonStipple( int fd, unsigned int *mask ); +extern int drmR128FlushIndirectBuffer( int fd, int indx, + int start, int end, int discard ); + +/* Radeon */ + +typedef struct { + unsigned long sarea_priv_offset; + int is_pci; + int cp_mode; + int agp_size; + int ring_size; + int usec_timeout; + + unsigned int fb_bpp; + unsigned int front_offset, front_pitch; + unsigned int back_offset, back_pitch; + unsigned int depth_bpp; + unsigned int depth_offset, depth_pitch; + + unsigned long fb_offset; + unsigned long mmio_offset; + unsigned long ring_offset; + unsigned long ring_rptr_offset; + unsigned long buffers_offset; + unsigned long agp_textures_offset; +} drmCompatRadeonInit; + +typedef struct { + unsigned int x; + unsigned int y; + unsigned int width; + unsigned int height; + void *data; +} drmCompatRadeonTexImage; + +extern int drmRadeonInitCP( int fd, drmCompatRadeonInit *info ); +extern int drmRadeonCleanupCP( int fd ); +extern int drmRadeonStartCP( int fd ); +extern int drmRadeonStopCP( int fd ); +extern int drmRadeonResetCP( int fd ); +extern int drmRadeonWaitForIdleCP( int fd ); +extern int drmRadeonEngineReset( int fd ); +extern int drmRadeonFullScreen( int fd, int enable ); +extern int drmRadeonSwapBuffers( int fd ); +extern int drmRadeonClear( int fd, unsigned int flags, + unsigned int clear_color, unsigned int clear_depth, + unsigned int color_mask, unsigned int stencil, + void *boxes, int nbox ); +extern int drmRadeonFlushVertexBuffer( int fd, int prim, int indx, + int count, int discard ); +extern int drmRadeonFlushIndices( int fd, int prim, int indx, + int start, int end, int discard ); +extern int drmRadeonLoadTexture( int fd, int offset, int pitch, int format, + int width, int height, + drmCompatRadeonTexImage *image ); +extern int drmRadeonPolygonStipple( int fd, unsigned int *mask ); +extern int drmRadeonFlushIndirectBuffer( int fd, int indx, + int start, int end, int discard ); + +/* SiS */ +extern Bool drmSiSAgpInit(int driSubFD, int offset, int size); + +/* I830 */ +typedef struct { + unsigned int start; + unsigned int end; + unsigned int size; + unsigned int mmio_offset; + unsigned int buffers_offset; + int sarea_off; + unsigned int front_offset; + unsigned int back_offset; + unsigned int depth_offset; + unsigned int w; + unsigned int h; + unsigned int pitch; + unsigned int pitch_bits; + unsigned int cpp; +} drmCompatI830Init; + +extern Bool drmI830CleanupDma(int driSubFD); +extern Bool drmI830InitDma(int driSubFD, drmCompatI830Init *info ); + +#endif + +/* WARNING: Do not change, or add, anything to this file. It is only provided + * for binary backwards compatability with the old driver specific DRM + * extensions used before XFree86 4.3. + */ diff --git a/nx-X11/extras/drm/libdrm/xf86drmHash.c b/nx-X11/extras/drm/libdrm/xf86drmHash.c new file mode 100644 index 000000000..4fbc88a12 --- /dev/null +++ b/nx-X11/extras/drm/libdrm/xf86drmHash.c @@ -0,0 +1,440 @@ +/* xf86drmHash.c -- Small hash table support for integer -> integer mapping + * Created: Sun Apr 18 09:35:45 1999 by faith@precisioninsight.com + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: Rickard E. (Rik) Faith <faith@valinux.com> + * + * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drmHash.c,v 1.4 2001/03/21 18:08:54 dawes Exp $ + * + * DESCRIPTION + * + * This file contains a straightforward implementation of a fixed-sized + * hash table using self-organizing linked lists [Knuth73, pp. 398-399] for + * collision resolution. There are two potentially interesting things + * about this implementation: + * + * 1) The table is power-of-two sized. Prime sized tables are more + * traditional, but do not have a significant advantage over power-of-two + * sized table, especially when double hashing is not used for collision + * resolution. + * + * 2) The hash computation uses a table of random integers [Hanson97, + * pp. 39-41]. + * + * FUTURE ENHANCEMENTS + * + * With a table size of 512, the current implementation is sufficient for a + * few hundred keys. Since this is well above the expected size of the + * tables for which this implementation was designed, the implementation of + * dynamic hash tables was postponed until the need arises. A common (and + * naive) approach to dynamic hash table implementation simply creates a + * new hash table when necessary, rehashes all the data into the new table, + * and destroys the old table. The approach in [Larson88] is superior in + * two ways: 1) only a portion of the table is expanded when needed, + * distributing the expansion cost over several insertions, and 2) portions + * of the table can be locked, enabling a scalable thread-safe + * implementation. + * + * REFERENCES + * + * [Hanson97] David R. Hanson. C Interfaces and Implementations: + * Techniques for Creating Reusable Software. Reading, Massachusetts: + * Addison-Wesley, 1997. + * + * [Knuth73] Donald E. Knuth. The Art of Computer Programming. Volume 3: + * Sorting and Searching. Reading, Massachusetts: Addison-Wesley, 1973. + * + * [Larson88] Per-Ake Larson. "Dynamic Hash Tables". CACM 31(4), April + * 1988, pp. 446-457. + * + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#define HASH_MAIN 0 + +#if HASH_MAIN +# include <stdio.h> +# include <stdlib.h> +#else +# include "drm.h" +# include "xf86drm.h" +# ifdef XFree86LOADER +# include "xf86.h" +# include "xf86_ansic.h" +# else +# include <stdio.h> +# include <stdlib.h> +# endif +#endif + +#define N(x) drm##x + +#define HASH_MAGIC 0xdeadbeef +#define HASH_DEBUG 0 +#define HASH_SIZE 512 /* Good for about 100 entries */ + /* If you change this value, you probably + have to change the HashHash hashing + function! */ + +#if HASH_MAIN +#define HASH_ALLOC malloc +#define HASH_FREE free +#define HASH_RANDOM_DECL +#define HASH_RANDOM_INIT(seed) srandom(seed) +#define HASH_RANDOM random() +#else +#define HASH_ALLOC drmMalloc +#define HASH_FREE drmFree +#define HASH_RANDOM_DECL void *state +#define HASH_RANDOM_INIT(seed) state = drmRandomCreate(seed) +#define HASH_RANDOM drmRandom(state) + +#endif + +typedef struct HashBucket { + unsigned long key; + void *value; + struct HashBucket *next; +} HashBucket, *HashBucketPtr; + +typedef struct HashTable { + unsigned long magic; + unsigned long entries; + unsigned long hits; /* At top of linked list */ + unsigned long partials; /* Not at top of linked list */ + unsigned long misses; /* Not in table */ + HashBucketPtr buckets[HASH_SIZE]; + int p0; + HashBucketPtr p1; +} HashTable, *HashTablePtr; + +#if HASH_MAIN +extern void *N(HashCreate)(void); +extern int N(HashDestroy)(void *t); +extern int N(HashLookup)(void *t, unsigned long key, unsigned long *value); +extern int N(HashInsert)(void *t, unsigned long key, unsigned long value); +extern int N(HashDelete)(void *t, unsigned long key); +#endif + +static unsigned long HashHash(unsigned long key) +{ + unsigned long hash = 0; + unsigned long tmp = key; + static int init = 0; + static unsigned long scatter[256]; + int i; + + if (!init) { + HASH_RANDOM_DECL; + HASH_RANDOM_INIT(37); + for (i = 0; i < 256; i++) scatter[i] = HASH_RANDOM; + ++init; + } + + while (tmp) { + hash = (hash << 1) + scatter[tmp & 0xff]; + tmp >>= 8; + } + + hash %= HASH_SIZE; +#if HASH_DEBUG + printf( "Hash(%d) = %d\n", key, hash); +#endif + return hash; +} + +void *N(HashCreate)(void) +{ + HashTablePtr table; + int i; + + table = HASH_ALLOC(sizeof(*table)); + if (!table) return NULL; + table->magic = HASH_MAGIC; + table->entries = 0; + table->hits = 0; + table->partials = 0; + table->misses = 0; + + for (i = 0; i < HASH_SIZE; i++) table->buckets[i] = NULL; + return table; +} + +int N(HashDestroy)(void *t) +{ + HashTablePtr table = (HashTablePtr)t; + HashBucketPtr bucket; + HashBucketPtr next; + int i; + + if (table->magic != HASH_MAGIC) return -1; /* Bad magic */ + + for (i = 0; i < HASH_SIZE; i++) { + for (bucket = table->buckets[i]; bucket;) { + next = bucket->next; + HASH_FREE(bucket); + bucket = next; + } + } + HASH_FREE(table); + return 0; +} + +/* Find the bucket and organize the list so that this bucket is at the + top. */ + +static HashBucketPtr HashFind(HashTablePtr table, + unsigned long key, unsigned long *h) +{ + unsigned long hash = HashHash(key); + HashBucketPtr prev = NULL; + HashBucketPtr bucket; + + if (h) *h = hash; + + for (bucket = table->buckets[hash]; bucket; bucket = bucket->next) { + if (bucket->key == key) { + if (prev) { + /* Organize */ + prev->next = bucket->next; + bucket->next = table->buckets[hash]; + table->buckets[hash] = bucket; + ++table->partials; + } else { + ++table->hits; + } + return bucket; + } + prev = bucket; + } + ++table->misses; + return NULL; +} + +int N(HashLookup)(void *t, unsigned long key, void **value) +{ + HashTablePtr table = (HashTablePtr)t; + HashBucketPtr bucket; + + if (!table || table->magic != HASH_MAGIC) return -1; /* Bad magic */ + + bucket = HashFind(table, key, NULL); + if (!bucket) return 1; /* Not found */ + *value = bucket->value; + return 0; /* Found */ +} + +int N(HashInsert)(void *t, unsigned long key, void *value) +{ + HashTablePtr table = (HashTablePtr)t; + HashBucketPtr bucket; + unsigned long hash; + + if (table->magic != HASH_MAGIC) return -1; /* Bad magic */ + + if (HashFind(table, key, &hash)) return 1; /* Already in table */ + + bucket = HASH_ALLOC(sizeof(*bucket)); + if (!bucket) return -1; /* Error */ + bucket->key = key; + bucket->value = value; + bucket->next = table->buckets[hash]; + table->buckets[hash] = bucket; +#if HASH_DEBUG + printf("Inserted %d at %d/%p\n", key, hash, bucket); +#endif + return 0; /* Added to table */ +} + +int N(HashDelete)(void *t, unsigned long key) +{ + HashTablePtr table = (HashTablePtr)t; + unsigned long hash; + HashBucketPtr bucket; + + if (table->magic != HASH_MAGIC) return -1; /* Bad magic */ + + bucket = HashFind(table, key, &hash); + + if (!bucket) return 1; /* Not found */ + + table->buckets[hash] = bucket->next; + HASH_FREE(bucket); + return 0; +} + +int N(HashNext)(void *t, unsigned long *key, void **value) +{ + HashTablePtr table = (HashTablePtr)t; + + for (; table->p0 < HASH_SIZE; + ++table->p0, table->p1 = table->buckets[table->p0]) { + if (table->p1) { + *key = table->p1->key; + *value = table->p1->value; + table->p1 = table->p1->next; + return 1; + } + } + return 0; +} + +int N(HashFirst)(void *t, unsigned long *key, void **value) +{ + HashTablePtr table = (HashTablePtr)t; + + if (table->magic != HASH_MAGIC) return -1; /* Bad magic */ + + table->p0 = 0; + table->p1 = table->buckets[0]; + return N(HashNext)(table, key, value); +} + +#if HASH_MAIN +#define DIST_LIMIT 10 +static int dist[DIST_LIMIT]; + +static void clear_dist(void) { + int i; + + for (i = 0; i < DIST_LIMIT; i++) dist[i] = 0; +} + +static int count_entries(HashBucketPtr bucket) +{ + int count = 0; + + for (; bucket; bucket = bucket->next) ++count; + return count; +} + +static void update_dist(int count) +{ + if (count >= DIST_LIMIT) ++dist[DIST_LIMIT-1]; + else ++dist[count]; +} + +static void compute_dist(HashTablePtr table) +{ + int i; + HashBucketPtr bucket; + + printf("Entries = %ld, hits = %ld, partials = %ld, misses = %ld\n", + table->entries, table->hits, table->partials, table->misses); + clear_dist(); + for (i = 0; i < HASH_SIZE; i++) { + bucket = table->buckets[i]; + update_dist(count_entries(bucket)); + } + for (i = 0; i < DIST_LIMIT; i++) { + if (i != DIST_LIMIT-1) printf("%5d %10d\n", i, dist[i]); + else printf("other %10d\n", dist[i]); + } +} + +static void check_table(HashTablePtr table, + unsigned long key, unsigned long value) +{ + unsigned long retval = 0; + int retcode = N(HashLookup)(table, key, &retval); + + switch (retcode) { + case -1: + printf("Bad magic = 0x%08lx:" + " key = %lu, expected = %lu, returned = %lu\n", + table->magic, key, value, retval); + break; + case 1: + printf("Not found: key = %lu, expected = %lu returned = %lu\n", + key, value, retval); + break; + case 0: + if (value != retval) + printf("Bad value: key = %lu, expected = %lu, returned = %lu\n", + key, value, retval); + break; + default: + printf("Bad retcode = %d: key = %lu, expected = %lu, returned = %lu\n", + retcode, key, value, retval); + break; + } +} + +int main(void) +{ + HashTablePtr table; + int i; + + printf("\n***** 256 consecutive integers ****\n"); + table = N(HashCreate)(); + for (i = 0; i < 256; i++) N(HashInsert)(table, i, i); + for (i = 0; i < 256; i++) check_table(table, i, i); + for (i = 256; i >= 0; i--) check_table(table, i, i); + compute_dist(table); + N(HashDestroy)(table); + + printf("\n***** 1024 consecutive integers ****\n"); + table = N(HashCreate)(); + for (i = 0; i < 1024; i++) N(HashInsert)(table, i, i); + for (i = 0; i < 1024; i++) check_table(table, i, i); + for (i = 1024; i >= 0; i--) check_table(table, i, i); + compute_dist(table); + N(HashDestroy)(table); + + printf("\n***** 1024 consecutive page addresses (4k pages) ****\n"); + table = N(HashCreate)(); + for (i = 0; i < 1024; i++) N(HashInsert)(table, i*4096, i); + for (i = 0; i < 1024; i++) check_table(table, i*4096, i); + for (i = 1024; i >= 0; i--) check_table(table, i*4096, i); + compute_dist(table); + N(HashDestroy)(table); + + printf("\n***** 1024 random integers ****\n"); + table = N(HashCreate)(); + srandom(0xbeefbeef); + for (i = 0; i < 1024; i++) N(HashInsert)(table, random(), i); + srandom(0xbeefbeef); + for (i = 0; i < 1024; i++) check_table(table, random(), i); + srandom(0xbeefbeef); + for (i = 0; i < 1024; i++) check_table(table, random(), i); + compute_dist(table); + N(HashDestroy)(table); + + printf("\n***** 5000 random integers ****\n"); + table = N(HashCreate)(); + srandom(0xbeefbeef); + for (i = 0; i < 5000; i++) N(HashInsert)(table, random(), i); + srandom(0xbeefbeef); + for (i = 0; i < 5000; i++) check_table(table, random(), i); + srandom(0xbeefbeef); + for (i = 0; i < 5000; i++) check_table(table, random(), i); + compute_dist(table); + N(HashDestroy)(table); + + return 0; +} +#endif diff --git a/nx-X11/extras/drm/libdrm/xf86drmRandom.c b/nx-X11/extras/drm/libdrm/xf86drmRandom.c new file mode 100644 index 000000000..301aaf4c2 --- /dev/null +++ b/nx-X11/extras/drm/libdrm/xf86drmRandom.c @@ -0,0 +1,224 @@ +/* xf86drmRandom.c -- "Minimal Standard" PRNG Implementation + * Created: Mon Apr 19 08:28:13 1999 by faith@precisioninsight.com + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: Rickard E. (Rik) Faith <faith@valinux.com> + * + * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drmRandom.c,v 1.4 2000/06/17 00:03:34 martin Exp $ + * + * DESCRIPTION + * + * This file contains a simple, straightforward implementation of the Park + * & Miller "Minimal Standard" PRNG [PM88, PMS93], which is a Lehmer + * multiplicative linear congruential generator (MLCG) with a period of + * 2^31-1. + * + * This implementation is intended to provide a reliable, portable PRNG + * that is suitable for testing a hash table implementation and for + * implementing skip lists. + * + * FUTURE ENHANCEMENTS + * + * If initial seeds are not selected randomly, two instances of the PRNG + * can be correlated. [Knuth81, pp. 32-33] describes a shuffling technique + * that can eliminate this problem. + * + * If PRNGs are used for simulation, the period of the current + * implementation may be too short. [LE88] discusses methods of combining + * MLCGs to produce much longer periods, and suggests some alternative + * values for A and M. [LE90 and Sch92] also provide information on + * long-period PRNGs. + * + * REFERENCES + * + * [Knuth81] Donald E. Knuth. The Art of Computer Programming. Volume 2: + * Seminumerical Algorithms. Reading, Massachusetts: Addison-Wesley, 1981. + * + * [LE88] Pierre L'Ecuyer. "Efficient and Portable Combined Random Number + * Generators". CACM 31(6), June 1988, pp. 742-774. + * + * [LE90] Pierre L'Ecuyer. "Random Numbers for Simulation". CACM 33(10, + * October 1990, pp. 85-97. + * + * [PM88] Stephen K. Park and Keith W. Miller. "Random Number Generators: + * Good Ones are Hard to Find". CACM 31(10), October 1988, pp. 1192-1201. + * + * [Sch92] Bruce Schneier. "Pseudo-Ransom Sequence Generator for 32-Bit + * CPUs". Dr. Dobb's Journal 17(2), February 1992, pp. 34, 37-38, 40. + * + * [PMS93] Stephen K. Park, Keith W. Miller, and Paul K. Stockmeyer. In + * "Technical Correspondence: Remarks on Choosing and Implementing Random + * Number Generators". CACM 36(7), July 1993, pp. 105-110. + * + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#define RANDOM_MAIN 0 + +#if RANDOM_MAIN +# include <stdio.h> +# include <stdlib.h> +#else +# include "drm.h" +# include "xf86drm.h" +# ifdef XFree86LOADER +# include "xf86.h" +# include "xf86_ansic.h" +# else +# include <stdio.h> +# include <stdlib.h> +# endif +#endif + +#define N(x) drm##x + +#define RANDOM_MAGIC 0xfeedbeef +#define RANDOM_DEBUG 0 + +#if RANDOM_MAIN +#define RANDOM_ALLOC malloc +#define RANDOM_FREE free +#else +#define RANDOM_ALLOC drmMalloc +#define RANDOM_FREE drmFree +#endif + +typedef struct RandomState { + unsigned long magic; + unsigned long a; + unsigned long m; + unsigned long q; /* m div a */ + unsigned long r; /* m mod a */ + unsigned long check; + long seed; +} RandomState; + +#if RANDOM_MAIN +extern void *N(RandomCreate)(unsigned long seed); +extern int N(RandomDestroy)(void *state); +extern unsigned long N(Random)(void *state); +extern double N(RandomDouble)(void *state); +#endif + +void *N(RandomCreate)(unsigned long seed) +{ + RandomState *state; + + state = RANDOM_ALLOC(sizeof(*state)); + if (!state) return NULL; + state->magic = RANDOM_MAGIC; +#if 0 + /* Park & Miller, October 1988 */ + state->a = 16807; + state->m = 2147483647; + state->check = 1043618065; /* After 10000 iterations */ +#else + /* Park, Miller, and Stockmeyer, July 1993 */ + state->a = 48271; + state->m = 2147483647; + state->check = 399268537; /* After 10000 iterations */ +#endif + state->q = state->m / state->a; + state->r = state->m % state->a; + + state->seed = seed; + /* Check for illegal boundary conditions, + and choose closest legal value. */ + if (state->seed <= 0) state->seed = 1; + if (state->seed >= state->m) state->seed = state->m - 1; + + return state; +} + +int N(RandomDestroy)(void *state) +{ + RANDOM_FREE(state); + return 0; +} + +unsigned long N(Random)(void *state) +{ + RandomState *s = (RandomState *)state; + long hi; + long lo; + + hi = s->seed / s->q; + lo = s->seed % s->q; + s->seed = s->a * lo - s->r * hi; + if (s->seed <= 0) s->seed += s->m; + + return s->seed; +} + +double N(RandomDouble)(void *state) +{ + RandomState *s = (RandomState *)state; + + return (double)N(Random)(state)/(double)s->m; +} + +#if RANDOM_MAIN +static void check_period(long seed) +{ + unsigned long count = 0; + unsigned long initial; + void *state; + + state = N(RandomCreate)(seed); + initial = N(Random)(state); + ++count; + while (initial != N(Random)(state)) { + if (!++count) break; + } + printf("With seed of %10ld, period = %10lu (0x%08lx)\n", + seed, count, count); + N(RandomDestroy)(state); +} + +int main(void) +{ + RandomState *state; + int i; + unsigned long rand; + + state = N(RandomCreate)(1); + for (i = 0; i < 10000; i++) { + rand = N(Random)(state); + } + printf("After 10000 iterations: %lu (%lu expected): %s\n", + rand, state->check, + rand - state->check ? "*INCORRECT*" : "CORRECT"); + N(RandomDestroy)(state); + + printf("Checking periods...\n"); + check_period(1); + check_period(2); + check_period(31415926); + + return 0; +} +#endif diff --git a/nx-X11/extras/drm/libdrm/xf86drmSL.c b/nx-X11/extras/drm/libdrm/xf86drmSL.c new file mode 100644 index 000000000..5f3c88d23 --- /dev/null +++ b/nx-X11/extras/drm/libdrm/xf86drmSL.c @@ -0,0 +1,495 @@ +/* xf86drmSL.c -- Skip list support + * Created: Mon May 10 09:28:13 1999 by faith@precisioninsight.com + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: Rickard E. (Rik) Faith <faith@valinux.com> + * + * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drmSL.c,v 1.3 2000/06/17 00:03:34 martin Exp $ + * + * DESCRIPTION + * + * This file contains a straightforward skip list implementation.n + * + * FUTURE ENHANCEMENTS + * + * REFERENCES + * + * [Pugh90] William Pugh. Skip Lists: A Probabilistic Alternative to + * Balanced Trees. CACM 33(6), June 1990, pp. 668-676. + * + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#define SL_MAIN 0 + +#if SL_MAIN +# include <stdio.h> +# include <stdlib.h> +# include <sys/time.h> +#else +# include "drm.h" +# include "xf86drm.h" +# ifdef XFree86LOADER +# include "xf86.h" +# include "xf86_ansic.h" +# else +# include <stdio.h> +# include <stdlib.h> +# endif +#endif + +#define N(x) drm##x + +#define SL_LIST_MAGIC 0xfacade00LU +#define SL_ENTRY_MAGIC 0x00fab1edLU +#define SL_FREED_MAGIC 0xdecea5edLU +#define SL_MAX_LEVEL 16 +#define SL_DEBUG 0 +#define SL_RANDOM_SEED 0xc01055a1LU + +#if SL_MAIN +#define SL_ALLOC malloc +#define SL_FREE free +#define SL_RANDOM_DECL static int state = 0; +#define SL_RANDOM_INIT(seed) if (!state) { srandom(seed); ++state; } +#define SL_RANDOM random() +#else +#define SL_ALLOC drmMalloc +#define SL_FREE drmFree +#define SL_RANDOM_DECL static void *state = NULL +#define SL_RANDOM_INIT(seed) if (!state) state = drmRandomCreate(seed) +#define SL_RANDOM drmRandom(state) + +#endif + +typedef struct SLEntry { + unsigned long magic; /* SL_ENTRY_MAGIC */ + unsigned long key; + void *value; + int levels; + struct SLEntry *forward[1]; /* variable sized array */ +} SLEntry, *SLEntryPtr; + +typedef struct SkipList { + unsigned long magic; /* SL_LIST_MAGIC */ + int level; + int count; + SLEntryPtr head; + SLEntryPtr p0; /* Position for iteration */ +} SkipList, *SkipListPtr; + +#if SL_MAIN +extern void *N(SLCreate)(void); +extern int N(SLDestroy)(void *l); +extern int N(SLLookup)(void *l, unsigned long key, void **value); +extern int N(SLInsert)(void *l, unsigned long key, void *value); +extern int N(SLDelete)(void *l, unsigned long key); +extern int N(SLNext)(void *l, unsigned long *key, void **value); +extern int N(SLFirst)(void *l, unsigned long *key, void **value); +extern void N(SLDump)(void *l); +extern int N(SLLookupNeighbors)(void *l, unsigned long key, + unsigned long *prev_key, void **prev_value, + unsigned long *next_key, void **next_value); +#endif + +static SLEntryPtr SLCreateEntry(int max_level, unsigned long key, void *value) +{ + SLEntryPtr entry; + + if (max_level < 0 || max_level > SL_MAX_LEVEL) max_level = SL_MAX_LEVEL; + + entry = SL_ALLOC(sizeof(*entry) + + (max_level + 1) * sizeof(entry->forward[0])); + if (!entry) return NULL; + entry->magic = SL_ENTRY_MAGIC; + entry->key = key; + entry->value = value; + entry->levels = max_level + 1; + + return entry; +} + +static int SLRandomLevel(void) +{ + int level = 1; + SL_RANDOM_DECL; + + SL_RANDOM_INIT(SL_RANDOM_SEED); + + while ((SL_RANDOM & 0x01) && level < SL_MAX_LEVEL) ++level; + return level; +} + +void *N(SLCreate)(void) +{ + SkipListPtr list; + int i; + + list = SL_ALLOC(sizeof(*list)); + if (!list) return NULL; + list->magic = SL_LIST_MAGIC; + list->level = 0; + list->head = SLCreateEntry(SL_MAX_LEVEL, 0, NULL); + list->count = 0; + + for (i = 0; i <= SL_MAX_LEVEL; i++) list->head->forward[i] = NULL; + + return list; +} + +int N(SLDestroy)(void *l) +{ + SkipListPtr list = (SkipListPtr)l; + SLEntryPtr entry; + SLEntryPtr next; + + if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */ + + for (entry = list->head; entry; entry = next) { + if (entry->magic != SL_ENTRY_MAGIC) return -1; /* Bad magic */ + next = entry->forward[0]; + entry->magic = SL_FREED_MAGIC; + SL_FREE(entry); + } + + list->magic = SL_FREED_MAGIC; + SL_FREE(list); + return 0; +} + +static SLEntryPtr SLLocate(void *l, unsigned long key, SLEntryPtr *update) +{ + SkipListPtr list = (SkipListPtr)l; + SLEntryPtr entry; + int i; + + if (list->magic != SL_LIST_MAGIC) return NULL; + + for (i = list->level, entry = list->head; i >= 0; i--) { + while (entry->forward[i] && entry->forward[i]->key < key) + entry = entry->forward[i]; + update[i] = entry; + } + + return entry->forward[0]; +} + +int N(SLInsert)(void *l, unsigned long key, void *value) +{ + SkipListPtr list = (SkipListPtr)l; + SLEntryPtr entry; + SLEntryPtr update[SL_MAX_LEVEL + 1]; + int level; + int i; + + if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */ + + entry = SLLocate(list, key, update); + + if (entry && entry->key == key) return 1; /* Already in list */ + + + level = SLRandomLevel(); + if (level > list->level) { + level = ++list->level; + update[level] = list->head; + } + + entry = SLCreateEntry(level, key, value); + + /* Fix up forward pointers */ + for (i = 0; i <= level; i++) { + entry->forward[i] = update[i]->forward[i]; + update[i]->forward[i] = entry; + } + + ++list->count; + return 0; /* Added to table */ +} + +int N(SLDelete)(void *l, unsigned long key) +{ + SkipListPtr list = (SkipListPtr)l; + SLEntryPtr update[SL_MAX_LEVEL + 1]; + SLEntryPtr entry; + int i; + + if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */ + + entry = SLLocate(list, key, update); + + if (!entry || entry->key != key) return 1; /* Not found */ + + /* Fix up forward pointers */ + for (i = 0; i <= list->level; i++) { + if (update[i]->forward[i] == entry) + update[i]->forward[i] = entry->forward[i]; + } + + entry->magic = SL_FREED_MAGIC; + SL_FREE(entry); + + while (list->level && !list->head->forward[list->level]) --list->level; + --list->count; + return 0; +} + +int N(SLLookup)(void *l, unsigned long key, void **value) +{ + SkipListPtr list = (SkipListPtr)l; + SLEntryPtr update[SL_MAX_LEVEL + 1]; + SLEntryPtr entry; + + entry = SLLocate(list, key, update); + + if (entry && entry->key == key) { + *value = entry; + return 0; + } + *value = NULL; + return -1; +} + +int N(SLLookupNeighbors)(void *l, unsigned long key, + unsigned long *prev_key, void **prev_value, + unsigned long *next_key, void **next_value) +{ + SkipListPtr list = (SkipListPtr)l; + SLEntryPtr update[SL_MAX_LEVEL + 1]; + SLEntryPtr entry; + int retcode = 0; + + entry = SLLocate(list, key, update); + + *prev_key = *next_key = key; + *prev_value = *next_value = NULL; + + if (update[0]) { + *prev_key = update[0]->key; + *prev_value = update[0]->value; + ++retcode; + if (update[0]->forward[0]) { + *next_key = update[0]->forward[0]->key; + *next_value = update[0]->forward[0]->value; + ++retcode; + } + } + return retcode; +} + +int N(SLNext)(void *l, unsigned long *key, void **value) +{ + SkipListPtr list = (SkipListPtr)l; + SLEntryPtr entry; + + if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */ + + entry = list->p0; + + if (entry) { + list->p0 = entry->forward[0]; + *key = entry->key; + *value = entry->value; + return 1; + } + list->p0 = NULL; + return 0; +} + +int N(SLFirst)(void *l, unsigned long *key, void **value) +{ + SkipListPtr list = (SkipListPtr)l; + + if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */ + + list->p0 = list->head->forward[0]; + return N(SLNext)(list, key, value); +} + +/* Dump internal data structures for debugging. */ +void N(SLDump)(void *l) +{ + SkipListPtr list = (SkipListPtr)l; + SLEntryPtr entry; + int i; + + if (list->magic != SL_LIST_MAGIC) { + printf("Bad magic: 0x%08lx (expected 0x%08lx)\n", + list->magic, SL_LIST_MAGIC); + return; + } + + printf("Level = %d, count = %d\n", list->level, list->count); + for (entry = list->head; entry; entry = entry->forward[0]) { + if (entry->magic != SL_ENTRY_MAGIC) { + printf("Bad magic: 0x%08lx (expected 0x%08lx)\n", + list->magic, SL_ENTRY_MAGIC); + } + printf("\nEntry %p <0x%08lx, %p> has %2d levels\n", + entry, entry->key, entry->value, entry->levels); + for (i = 0; i < entry->levels; i++) { + if (entry->forward[i]) { + printf(" %2d: %p <0x%08lx, %p>\n", + i, + entry->forward[i], + entry->forward[i]->key, + entry->forward[i]->value); + } else { + printf(" %2d: %p\n", i, entry->forward[i]); + } + } + } +} + +#if SL_MAIN +static void print(SkipListPtr list) +{ + unsigned long key; + void *value; + + if (N(SLFirst)(list, &key, &value)) { + do { + printf("key = %5lu, value = %p\n", key, value); + } while (N(SLNext)(list, &key, &value)); + } +} + +static double do_time(int size, int iter) +{ + SkipListPtr list; + int i, j; + unsigned long keys[1000000]; + unsigned long previous; + unsigned long key; + void *value; + struct timeval start, stop; + double usec; + SL_RANDOM_DECL; + + SL_RANDOM_INIT(12345); + + list = N(SLCreate)(); + + for (i = 0; i < size; i++) { + keys[i] = SL_RANDOM; + N(SLInsert)(list, keys[i], NULL); + } + + previous = 0; + if (N(SLFirst)(list, &key, &value)) { + do { + if (key <= previous) { + printf( "%lu !< %lu\n", previous, key); + } + previous = key; + } while (N(SLNext)(list, &key, &value)); + } + + gettimeofday(&start, NULL); + for (j = 0; j < iter; j++) { + for (i = 0; i < size; i++) { + if (N(SLLookup)(list, keys[i], &value)) + printf("Error %lu %d\n", keys[i], i); + } + } + gettimeofday(&stop, NULL); + + usec = (double)(stop.tv_sec * 1000000 + stop.tv_usec + - start.tv_sec * 1000000 - start.tv_usec) / (size * iter); + + printf("%0.2f microseconds for list length %d\n", usec, size); + + N(SLDestroy)(list); + + return usec; +} + +static void print_neighbors(void *list, unsigned long key) +{ + unsigned long prev_key = 0; + unsigned long next_key = 0; + void *prev_value; + void *next_value; + int retval; + + retval = drmSLLookupNeighbors(list, key, + &prev_key, &prev_value, + &next_key, &next_value); + printf("Neighbors of %5lu: %d %5lu %5lu\n", + key, retval, prev_key, next_key); +} + +int main(void) +{ + SkipListPtr list; + double usec, usec2, usec3, usec4; + + list = N(SLCreate)(); + printf( "list at %p\n", list); + + print(list); + printf("\n==============================\n\n"); + + N(SLInsert)(list, 123, NULL); + N(SLInsert)(list, 213, NULL); + N(SLInsert)(list, 50, NULL); + print(list); + printf("\n==============================\n\n"); + + print_neighbors(list, 0); + print_neighbors(list, 50); + print_neighbors(list, 51); + print_neighbors(list, 123); + print_neighbors(list, 200); + print_neighbors(list, 213); + print_neighbors(list, 256); + printf("\n==============================\n\n"); + + N(SLDelete)(list, 50); + print(list); + printf("\n==============================\n\n"); + + N(SLDump)(list); + N(SLDestroy)(list); + printf("\n==============================\n\n"); + + usec = do_time(100, 10000); + usec2 = do_time(1000, 500); + printf("Table size increased by %0.2f, search time increased by %0.2f\n", + 1000.0/100.0, usec2 / usec); + + usec3 = do_time(10000, 50); + printf("Table size increased by %0.2f, search time increased by %0.2f\n", + 10000.0/100.0, usec3 / usec); + + usec4 = do_time(100000, 4); + printf("Table size increased by %0.2f, search time increased by %0.2f\n", + 100000.0/100.0, usec4 / usec); + + return 0; +} +#endif |