diff options
-rw-r--r-- | configure.ac | 4 | ||||
-rw-r--r-- | hw/xfree86/common/xf86Config.c | 2 | ||||
-rw-r--r-- | hw/xfree86/dri/Makefile.am | 5 | ||||
-rw-r--r-- | hw/xfree86/dri/dri.c | 94 | ||||
-rw-r--r-- | hw/xfree86/dri/dri.h | 2 | ||||
-rw-r--r-- | hw/xfree86/dri/drimodule.c | 13 | ||||
-rw-r--r-- | hw/xfree86/os-support/Makefile.am | 6 | ||||
-rw-r--r-- | hw/xfree86/os-support/drm/Makefile.am | 19 | ||||
-rw-r--r-- | hw/xfree86/os-support/drm/drmmodule.c | 57 | ||||
-rw-r--r-- | hw/xfree86/os-support/drm/xf86drm.c | 3262 | ||||
-rw-r--r-- | hw/xfree86/os-support/drm/xf86drmHash.c | 432 | ||||
-rw-r--r-- | hw/xfree86/os-support/drm/xf86drmRandom.c | 216 | ||||
-rw-r--r-- | hw/xfree86/os-support/drm/xf86drmSL.c | 488 | ||||
-rw-r--r-- | hw/xfree86/os-support/xf86drm.h | 641 |
14 files changed, 103 insertions, 5138 deletions
diff --git a/configure.ac b/configure.ac index 314840329..0977ee385 100644 --- a/configure.ac +++ b/configure.ac @@ -654,10 +654,11 @@ AM_CONDITIONAL(DRI, test "x$DRI" = xyes) if test "x$DRI" = xyes; then AC_DEFINE(XF86DRI, 1, [Build DRI extension]) PKG_CHECK_MODULES([DRIPROTO], [xf86driproto]) - PKG_CHECK_MODULES([LIBDRM], [libdrm]) + PKG_CHECK_MODULES([LIBDRM], [libdrm >= 2.3.0]) PKG_CHECK_MODULES([GL], [glproto >= 1.4.1]) AC_SUBST(DRIPROTO_CFLAGS) AC_SUBST(LIBDRM_CFLAGS) + AC_SUBST(LIBDRM_LIBS) AC_SUBST(GL_CFLAGS) fi @@ -1840,7 +1841,6 @@ hw/xfree86/loader/Makefile hw/xfree86/os-support/Makefile hw/xfree86/os-support/bsd/Makefile hw/xfree86/os-support/bus/Makefile -hw/xfree86/os-support/drm/Makefile hw/xfree86/os-support/hurd/Makefile hw/xfree86/os-support/misc/Makefile hw/xfree86/os-support/linux/Makefile diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c index 57f929b58..ffdca12a5 100644 --- a/hw/xfree86/common/xf86Config.c +++ b/hw/xfree86/common/xf86Config.c @@ -251,7 +251,7 @@ xf86ModulelistFromConfig(pointer **optlist) { int count = 0, i = 0; char **modulearray; - char *ignore[] = { "GLcore", "speedo", "bitmap", NULL }; + char *ignore[] = { "GLcore", "speedo", "bitmap", "drm", NULL }; pointer *optarray; XF86LoadPtr modp; diff --git a/hw/xfree86/dri/Makefile.am b/hw/xfree86/dri/Makefile.am index e711846b2..4def3874b 100644 --- a/hw/xfree86/dri/Makefile.am +++ b/hw/xfree86/dri/Makefile.am @@ -7,13 +7,10 @@ libdri_la_CFLAGS = -I$(top_srcdir)/hw/xfree86/common \ -I$(top_builddir)/GL/include \ -I@MESA_SOURCE@/include \ -DHAVE_XORG_CONFIG_H \ - \ - \ - \ @DRIPROTO_CFLAGS@ \ @LIBDRM_CFLAGS@ \ @GL_CFLAGS@ -libdri_la_LDFLAGS = -module -avoid-version +libdri_la_LDFLAGS = -module -avoid-version @LIBDRM_LIBS@ libdri_ladir = $(moduledir)/extensions libdri_la_SOURCES = \ dri.c \ diff --git a/hw/xfree86/dri/dri.c b/hw/xfree86/dri/dri.c index 9e52e6146..fbb24e44b 100644 --- a/hw/xfree86/dri/dri.c +++ b/hw/xfree86/dri/dri.c @@ -42,11 +42,13 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include <unistd.h> #include <string.h> #include <stdio.h> +#include <sys/ioctl.h> #define NEED_REPLIES #define NEED_EVENTS #include <X11/X.h> #include <X11/Xproto.h> +#include "xf86drm.h" #include "misc.h" #include "dixstruct.h" #include "extnsionst.h" @@ -67,6 +69,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "glxserver.h" #include "mi.h" #include "mipointer.h" +#include "xf86_OSproc.h" #if !defined(PANORAMIX) extern Bool noPanoramiXExtension; @@ -104,6 +107,7 @@ DRIDrvMsg(int scrnIndex, MessageType type, const char *format, ...) va_end(ap); } + Bool DRIScreenInit(ScreenPtr pScreen, DRIInfoPtr pDRIInfo, int *pDRMFD) { @@ -571,6 +575,26 @@ DRICloseScreen(ScreenPtr pScreen) } } +#define DRM_MSG_VERBOSITY 3 + +static int dri_drm_debug_print(const char *format, va_list ap) +{ + xf86VDrvMsgVerb(-1, X_NONE, DRM_MSG_VERBOSITY, format, ap); + return 0; +} + +static void dri_drm_get_perms(gid_t *group, mode_t *mode) +{ + *group = xf86ConfigDRI.group; + *mode = xf86ConfigDRI.mode; +} + +static drmServerInfo DRIDRMServerInfo = { + dri_drm_debug_print, + xf86LoadKernelModule, + dri_drm_get_perms, +}; + Bool DRIExtensionInit(void) { @@ -598,6 +622,8 @@ DRIExtensionInit(void) return FALSE; } + drmSetServerInfo(&DRIDRMServerInfo); + RegisterBlockAndWakeupHandlers(DRIBlockHandler, DRIWakeupHandler, NULL); return TRUE; @@ -2093,3 +2119,71 @@ DRICreatePCIBusID(pciVideoPtr PciInfo) PciInfo->device, PciInfo->func); return busID; } + +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; + void *hash_table; + + hash_table = drmGetHashTable(); + + if (!hash_table) return; + if (drmHashFirst(hash_table, &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(hash_table, &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); +} diff --git a/hw/xfree86/dri/dri.h b/hw/xfree86/dri/dri.h index b49c426eb..dca0edde8 100644 --- a/hw/xfree86/dri/dri.h +++ b/hw/xfree86/dri/dri.h @@ -339,6 +339,8 @@ extern void DRIMoveBuffersHelper(ScreenPtr pScreen, extern char *DRICreatePCIBusID(pciVideoPtr PciInfo); +extern int drmInstallSIGIOHandler(int fd, void (*f)(int, void *, void *)); +extern int drmRemoveSIGIOHandler(int fd); #define _DRI_H_ #endif diff --git a/hw/xfree86/dri/drimodule.c b/hw/xfree86/dri/drimodule.c index 331de8287..b39c22e11 100644 --- a/hw/xfree86/dri/drimodule.c +++ b/hw/xfree86/dri/drimodule.c @@ -74,23 +74,14 @@ static pointer driSetup(pointer module, pointer opts, int *errmaj, int *errmin) { static Bool setupDone = FALSE; - pointer drm = NULL; if (!setupDone) { setupDone = TRUE; - - drm = - LoadSubModule(module, "drm", NULL, NULL, NULL, NULL, errmaj, errmin); - - if (!drm) { - if (errmaj) *errmaj = LDR_NOSUBENT; - } else { - LoadExtension(&XF86DRIExt, FALSE); - } + LoadExtension(&XF86DRIExt, FALSE); } else { if (errmaj) *errmaj = LDR_ONCEONLY; } /* Need a non-NULL return value to indicate success */ - return drm; + return 1; } diff --git a/hw/xfree86/os-support/Makefile.am b/hw/xfree86/os-support/Makefile.am index b07e3c9ae..f9a888e2f 100644 --- a/hw/xfree86/os-support/Makefile.am +++ b/hw/xfree86/os-support/Makefile.am @@ -1,14 +1,10 @@ -if DRI -DRI_SUBDIRS=drm -endif - SUBDIRS = bus @XORG_OS_SUBDIR@ misc $(DRI_SUBDIRS) DIST_SUBDIRS = bsd bus drm misc linux lynxos solaris sysv sco usl hurd sdk_HEADERS = xf86_OSproc.h xf86_OSlib.h xf86_ansic.h xf86_libc.h \ assyntax.h xf86OSmouse.h -EXTRA_DIST = int10Defines.h xf86OSpriv.h README.OS-lib xf86drm.h +EXTRA_DIST = int10Defines.h xf86OSpriv.h README.OS-lib # to get the grouping semantics right, you have to glom these three together # as one library, otherwise libtool will actively defeat your attempts to diff --git a/hw/xfree86/os-support/drm/Makefile.am b/hw/xfree86/os-support/drm/Makefile.am deleted file mode 100644 index 53893251a..000000000 --- a/hw/xfree86/os-support/drm/Makefile.am +++ /dev/null @@ -1,19 +0,0 @@ -libdrm_la_LTLIBRARIES = libdrm.la -libdrm_la_CFLAGS = -I$(top_srcdir)/hw/xfree86/common \ - -I$(top_srcdir)/hw/xfree86/dri \ - -I$(top_srcdir)/hw/xfree86/os-support \ - -I$(top_srcdir)/hw/xfree86/os-support/bus \ - -I$(top_srcdir)/hw/xfree86/os-suport/shared/drm/kernel \ - -I$(top_srcdir)/GL/glx \ - -I$(top_srcdir)/GL/include \ - -DHAVE_XORG_CONFIG_H \ - @LIBDRM_CFLAGS@ - -libdrm_la_LDFLAGS = -module -avoid-version -libdrm_ladir = $(moduledir)/@XORG_OS@ -libdrm_la_SOURCES = \ - xf86drm.c \ - xf86drmHash.c \ - xf86drmRandom.c \ - xf86drmSL.c \ - drmmodule.c diff --git a/hw/xfree86/os-support/drm/drmmodule.c b/hw/xfree86/os-support/drm/drmmodule.c deleted file mode 100644 index 8d2b4bc12..000000000 --- a/hw/xfree86/os-support/drm/drmmodule.c +++ /dev/null @@ -1,57 +0,0 @@ -/* drmmodule.c -- Module initialization - * Created: Fri Jun 4 09:05:48 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> - */ - -#ifdef HAVE_XORG_CONFIG_H -#include <xorg-config.h> -#endif - -#include "xf86Module.h" - -static MODULESETUPPROTO(drmSetup); - -static XF86ModuleVersionInfo VersRec = -{ - "drm", - MODULEVENDORSTRING, - MODINFOSTRING1, - MODINFOSTRING2, - XORG_VERSION_CURRENT, - 1, 0, 0, - ABI_CLASS_EXTENSION, - ABI_EXTENSION_VERSION, - MOD_CLASS_NONE, - {0,0,0,0} -}; - -_X_EXPORT XF86ModuleData drmModuleData = { &VersRec, drmSetup, NULL }; - -static pointer -drmSetup(pointer module, pointer opts, int *errmaj, int *errmin) -{ - return (void *)1; -} diff --git a/hw/xfree86/os-support/drm/xf86drm.c b/hw/xfree86/os-support/drm/xf86drm.c deleted file mode 100644 index e990e286b..000000000 --- a/hw/xfree86/os-support/drm/xf86drm.c +++ /dev/null @@ -1,3262 +0,0 @@ -/** - * \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. - */ - - -#ifdef HAVE_XORG_CONFIG_H -#include <libdrm-config.h> -#include <xorg-config.h> -#endif - -#include "xf86.h" -#include "xf86_OSproc.h" -#define _DRM_MALLOC xalloc -#define _DRM_FREE xfree - -#include "drm.h" -#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> - -/* 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; - - va_start(ap, format); - xf86VDrvMsgVerb(-1, X_NONE, DRM_MSG_VERBOSITY, format, ap); - 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(); - uid_t user = DRM_DEV_UID; - gid_t group = DRM_DEV_GID; - - sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, minor); - drmMsg("drmOpenDevice: node name is %s\n", buf); - - devmode = xf86ConfigDRI.mode ? xf86ConfigDRI.mode : DRM_DEV_MODE; - devmode &= ~(S_IXUSR|S_IXGRP|S_IXOTH); - group = (xf86ConfigDRI.group >= 0) ? xf86ConfigDRI.group : DRM_DEV_GID; - - 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); - } - chown(buf, user, group); - chmod(buf, devmode); - - 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); - chown(buf, user, group); - chmod(buf, devmode); - } - 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()) { - /* try to load the kernel module now */ - if (!xf86LoadKernelModule(name)) { - ErrorF("[drm] failed to load kernel module \"%s\"\n", - name); - return -1; - } - } - - /* - * 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) -{ - if (!drmAvailable() && name != NULL) { - /* try to load the kernel */ - if (!xf86LoadKernelModule(name)) { - ErrorF("[drm] failed to load kernel module \"%s\"\n", - name); - return -1; - } - } - - 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; -} - -int drmUpdateDrawableInfo(int fd, drm_drawable_t handle, - drm_drawable_info_type_t type, unsigned int num, - void *data) -{ - drm_update_draw_t update; - - update.handle = handle; - update.type = type; - update.num = num; - update.data = (unsigned long long)(unsigned long)data; - - if (ioctl(fd, DRM_IOCTL_UPDATE_DRAW, &update)) 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; -} - -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); -} - -/* - * Valid flags are - * DRM_FENCE_FLAG_EMIT - * DRM_FENCE_FLAG_SHAREABLE - * DRM_FENCE_MASK_DRIVER - */ - -int drmFenceCreate(int fd, unsigned flags, int class,unsigned type, - drmFence *fence) -{ - drm_fence_arg_t arg; - - memset(&arg, 0, sizeof(arg)); - arg.type = type; - arg.class = class; - arg.op = drm_fence_create; - if (ioctl(fd, DRM_IOCTL_FENCE, &arg)) - return -errno; - fence->handle = arg.handle; - fence->class = arg.class; - fence->type = arg.type; - fence->flags = arg.flags; - fence->signaled = 0; - return 0; -} - -/* - * Valid flags are - * DRM_FENCE_FLAG_SHAREABLE - * DRM_FENCE_MASK_DRIVER - */ - -int drmFenceBuffers(int fd, unsigned flags, drmFence *fence) -{ - drm_fence_arg_t arg; - - memset(&arg, 0, sizeof(arg)); - arg.flags = flags; - arg.op = drm_fence_buffers; - if (ioctl(fd, DRM_IOCTL_FENCE, &arg)) - return -errno; - fence->handle = arg.handle; - fence->class = arg.class; - fence->type = arg.type; - fence->flags = arg.flags; - fence->signaled = 0; - return 0; -} - -int drmFenceDestroy(int fd, const drmFence *fence) -{ - drm_fence_arg_t arg; - - memset(&arg, 0, sizeof(arg)); - arg.handle = fence->handle; - arg.op = drm_fence_destroy; - if (ioctl(fd, DRM_IOCTL_FENCE, &arg)) - return -errno; - return 0; -} - -int drmFenceReference(int fd, unsigned handle, drmFence *fence) -{ - drm_fence_arg_t arg; - - memset(&arg, 0, sizeof(arg)); - arg.handle = handle; - arg.op = drm_fence_reference; - if (ioctl(fd, DRM_IOCTL_FENCE, &arg)) - return -errno; - fence->handle = arg.handle; - fence->class = arg.class; - fence->type = arg.type; - fence->flags = arg.flags; - fence->signaled = arg.signaled; - return 0; -} - -int drmFenceUnreference(int fd, const drmFence *fence) -{ - drm_fence_arg_t arg; - - memset(&arg, 0, sizeof(arg)); - arg.handle = fence->handle; - arg.op = drm_fence_unreference; - if (ioctl(fd, DRM_IOCTL_FENCE, &arg)) - return -errno; - return 0; -} - -int drmFenceFlush(int fd, drmFence *fence, unsigned flush_type) -{ - drm_fence_arg_t arg; - - memset(&arg, 0, sizeof(arg)); - arg.handle = fence->handle; - arg.type = flush_type; - arg.op = drm_fence_flush; - if (ioctl(fd, DRM_IOCTL_FENCE, &arg)) - return -errno; - fence->class = arg.class; - fence->type = arg.type; - fence->signaled = arg.signaled; - return 0; -} - -int drmFenceUpdate(int fd, drmFence *fence) -{ - drm_fence_arg_t arg; - - memset(&arg, 0, sizeof(arg)); - arg.handle = fence->handle; - arg.op = drm_fence_signaled; - if (ioctl(fd, DRM_IOCTL_FENCE, &arg)) - return -errno; - fence->class = arg.class; - fence->type = arg.type; - fence->signaled = arg.signaled; - return 0; -} - -int drmFenceSignaled(int fd, drmFence *fence, unsigned fenceType, - int *signaled) -{ - int - ret; - - if ((fence->flags & DRM_FENCE_FLAG_SHAREABLE) || - ((fenceType & fence->signaled) != fenceType)) { - - ret = drmFenceFlush(fd, fence, fenceType); - if (ret) - return ret; - } - - *signaled = ((fenceType & fence->signaled) == fenceType); - - return 0; -} - -/* - * Valid flags are - * DRM_FENCE_FLAG_SHAREABLE - * DRM_FENCE_MASK_DRIVER - */ - - -int drmFenceEmit(int fd, unsigned flags, drmFence *fence, unsigned emit_type) -{ - drm_fence_arg_t arg; - - memset(&arg, 0, sizeof(arg)); - arg.flags = flags; - arg.handle = fence->handle; - arg.type = emit_type; - arg.op = drm_fence_emit; - if (ioctl(fd, DRM_IOCTL_FENCE, &arg)) - return -errno; - fence->class = arg.class; - fence->type = arg.type; - fence->signaled = arg.signaled; - return 0; -} - -/* - * Valid flags are - * DRM_FENCE_FLAG_WAIT_LAZY - * DRM_FENCE_FLAG_WAIT_IGNORE_SIGNALS - */ - -int drmFenceWait(int fd, unsigned flags, drmFence *fence, unsigned flush_type) -{ - drm_fence_arg_t arg; - int ret; - - if (flush_type == 0) { - flush_type = fence->type; - } - - if (!(fence->flags & DRM_FENCE_FLAG_SHAREABLE)) { - if ((flush_type & fence->signaled) == flush_type) { - return 0; - } - } - - memset(&arg, 0, sizeof(arg)); - arg.handle = fence->handle; - arg.type = flush_type; - arg.flags = flags; - arg.op = drm_fence_wait; - do { - ret = ioctl(fd, DRM_IOCTL_FENCE, &arg); - } while (ret != 0 && errno == EAGAIN); - - if (ret) - return -errno; - - fence->class = arg.class; - fence->type = arg.type; - fence->signaled = arg.signaled; - return 0; -} - -static int drmAdjustListNodes(drmBOList *list) -{ - drmBONode *node; - drmMMListHead *l; - int ret = 0; - - while(list->numCurrent < list->numTarget) { - node = (drmBONode *) malloc(sizeof(*node)); - if (!node) { - ret = -ENOMEM; - break; - } - list->numCurrent++; - DRMLISTADD(&node->head, &list->free); - } - - while(list->numCurrent > list->numTarget) { - l = list->free.next; - if (l == &list->free) - break; - DRMLISTDEL(l); - node = DRMLISTENTRY(drmBONode, l, head); - free(node); - list->numCurrent--; - } - return ret; -} - -void drmBOFreeList(drmBOList *list) -{ - drmBONode *node; - drmMMListHead *l; - - l = list->list.next; - while(l != &list->list) { - DRMLISTDEL(l); - node = DRMLISTENTRY(drmBONode, l, head); - free(node); - l = list->free.next; - list->numCurrent--; - list->numOnList--; - } - - l = list->free.next; - while(l != &list->free) { - DRMLISTDEL(l); - node = DRMLISTENTRY(drmBONode, l, head); - free(node); - l = list->free.next; - list->numCurrent--; - } -} - -int drmBOResetList(drmBOList *list) { - - drmMMListHead *l; - int ret; - - ret = drmAdjustListNodes(list); - if (ret) - return ret; - - l = list->list.next; - while(l != &list->list) { - DRMLISTDEL(l); - DRMLISTADD(l, &list->free); - list->numOnList--; - l = list->list.next; - } - return drmAdjustListNodes(list); -} - -static drmBONode *drmAddListItem(drmBOList *list, drmBO *item, - unsigned long arg0, - unsigned long arg1) -{ - drmBONode *node; - drmMMListHead *l; - - l = list->free.next; - if (l == &list->free) { - node = (drmBONode *) malloc(sizeof(*node)); - if (!node) { - return NULL; - } - list->numCurrent++; - } else { - DRMLISTDEL(l); - node = DRMLISTENTRY(drmBONode, l, head); - } - node->buf = item; - node->arg0 = arg0; - node->arg1 = arg1; - DRMLISTADD(&node->head, &list->list); - list->numOnList++; - return node; -} - -void *drmBOListIterator(drmBOList *list) -{ - void *ret = list->list.next; - - if (ret == &list->list) - return NULL; - return ret; -} - -void *drmBOListNext(drmBOList *list, void *iterator) -{ - void *ret; - - drmMMListHead *l = (drmMMListHead *) iterator; - ret = l->next; - if (ret == &list->list) - return NULL; - return ret; -} - -drmBO *drmBOListBuf(void *iterator) -{ - drmBONode *node; - drmMMListHead *l = (drmMMListHead *) iterator; - node = DRMLISTENTRY(drmBONode, l, head); - - return node->buf; -} - - -int drmBOCreateList(int numTarget, drmBOList *list) -{ - DRMINITLISTHEAD(&list->list); - DRMINITLISTHEAD(&list->free); - list->numTarget = numTarget; - list->numCurrent = 0; - list->numOnList = 0; - return drmAdjustListNodes(list); -} - -static void drmBOCopyReply(const drm_bo_arg_reply_t *rep, - drmBO *buf) -{ - buf->handle = rep->handle; - buf->flags = rep->flags; - buf->size = rep->size; - buf->offset = rep->offset; - buf->mapHandle = rep->arg_handle; - buf->mask = rep->mask; - buf->start = rep->buffer_start; - buf->fenceFlags = rep->fence_flags; - buf->replyFlags = rep->rep_flags; - buf->pageAlignment = rep->page_alignment; -} - - - -int drmBOCreate(int fd, unsigned long start, unsigned long size, - unsigned pageAlignment, void *user_buffer, drm_bo_type_t type, - unsigned mask, - unsigned hint, drmBO *buf) -{ - drm_bo_arg_t arg; - drm_bo_arg_request_t *req = &arg.d.req; - drm_bo_arg_reply_t *rep = &arg.d.rep; - int ret; - - memset(buf, 0, sizeof(*buf)); - memset(&arg, 0, sizeof(arg)); - req->mask = mask; - req->hint = hint; - req->size = size; - req->type = type; - req->page_alignment = pageAlignment; - - buf->virtual = NULL; - - switch(type) { - case drm_bo_type_dc: - req->buffer_start = start; - break; - case drm_bo_type_user: - req->buffer_start = (unsigned long) user_buffer; - buf->virtual = user_buffer; - break; - case drm_bo_type_fake: - req->buffer_start = start; - break; - default: - return -EINVAL; - } - req->op = drm_bo_create; - - do { - ret = ioctl(fd, DRM_IOCTL_BUFOBJ, &arg); - } while (ret != 0 && errno == EAGAIN); - - if (ret) - return -errno; - if (!arg.handled) { - return -EFAULT; - } - if (rep->ret) { - fprintf(stderr, "Error %d\n", rep->ret); - return rep->ret; - } - - drmBOCopyReply(rep, buf); - buf->mapVirtual = NULL; - buf->mapCount = 0; - - return 0; -} - -int drmBODestroy(int fd, drmBO *buf) -{ - drm_bo_arg_t arg; - drm_bo_arg_request_t *req = &arg.d.req; - drm_bo_arg_reply_t *rep = &arg.d.rep; - - if (buf->mapVirtual && (buf->type != drm_bo_type_fake)) { - (void) drmUnmap(buf->mapVirtual, buf->start + buf->size); - buf->mapVirtual = NULL; - buf->virtual = NULL; - } - - memset(&arg, 0, sizeof(arg)); - req->handle = buf->handle; - req->op = drm_bo_destroy; - - if (ioctl(fd, DRM_IOCTL_BUFOBJ, &arg)) - return -errno; - if (!arg.handled) { - return -EFAULT; - } - if (rep->ret) { - return rep->ret; - } - - buf->handle = 0; - return 0; -} - -int drmBOReference(int fd, unsigned handle, drmBO *buf) -{ - - drm_bo_arg_t arg; - drm_bo_arg_request_t *req = &arg.d.req; - drm_bo_arg_reply_t *rep = &arg.d.rep; - - memset(&arg, 0, sizeof(arg)); - req->handle = handle; - req->op = drm_bo_reference; - - if (ioctl(fd, DRM_IOCTL_BUFOBJ, &arg)) - return -errno; - if (!arg.handled) { - return -EFAULT; - } - if (rep->ret) { - return rep->ret; - } - - drmBOCopyReply(rep, buf); - buf->type = drm_bo_type_dc; - buf->mapVirtual = NULL; - buf->mapCount = 0; - buf->virtual = NULL; - - return 0; -} - -int drmBOUnReference(int fd, drmBO *buf) -{ - drm_bo_arg_t arg; - drm_bo_arg_request_t *req = &arg.d.req; - drm_bo_arg_reply_t *rep = &arg.d.rep; - - - if (buf->mapVirtual && (buf->type != drm_bo_type_fake)) { - (void) munmap(buf->mapVirtual, buf->start + buf->size); - buf->mapVirtual = NULL; - buf->virtual = NULL; - } - - memset(&arg, 0, sizeof(arg)); - req->handle = buf->handle; - req->op = drm_bo_unreference; - - if (ioctl(fd, DRM_IOCTL_BUFOBJ, &arg)) - return -errno; - if (!arg.handled) { - return -EFAULT; - } - if (rep->ret) { - return rep->ret; - } - - buf->handle = 0; - return 0; -} - -/* - * Flags can be DRM_BO_FLAG_READ, DRM_BO_FLAG_WRITE or'ed together - * Hint currently be DRM_BO_HINT_DONT_BLOCK, which makes the - * call return an -EBUSY if it can' immediately honor the mapping request. - */ - -int drmBOMap(int fd, drmBO *buf, unsigned mapFlags, unsigned mapHint, - void **address) -{ - - drm_bo_arg_t arg; - drm_bo_arg_request_t *req = &arg.d.req; - drm_bo_arg_reply_t *rep = &arg.d.rep; - int ret = 0; - - /* - * Make sure we have a virtual address of the buffer. - */ - - if (!buf->virtual && buf->type != drm_bo_type_fake) { - drmAddress virtual; - virtual = mmap(0, buf->size + buf->start, - PROT_READ | PROT_WRITE, MAP_SHARED, - fd, buf->mapHandle); - if (virtual == MAP_FAILED) { - ret = -errno; - } - if (ret) - return ret; - buf->mapVirtual = virtual; - buf->virtual = ((char *) virtual) + buf->start; - } - - memset(&arg, 0, sizeof(arg)); - req->handle = buf->handle; - req->mask = mapFlags; - req->hint = mapHint; - req->op = drm_bo_map; - - /* - * May hang if the buffer object is busy. - * This IOCTL synchronizes the buffer. - */ - - do { - ret = ioctl(fd, DRM_IOCTL_BUFOBJ, &arg); - } while (ret != 0 && errno == EAGAIN); - - if (ret) - return ret; - if (!arg.handled) - return -EFAULT; - if (rep->ret) - return rep->ret; - - drmBOCopyReply(rep, buf); - buf->mapFlags = mapFlags; - ++buf->mapCount; - *address = buf->virtual; - - return 0; -} - -int drmBOUnmap(int fd, drmBO *buf) -{ - drm_bo_arg_t arg; - drm_bo_arg_request_t *req = &arg.d.req; - drm_bo_arg_reply_t *rep = &arg.d.rep; - - - memset(&arg, 0, sizeof(arg)); - req->handle = buf->handle; - req->op = drm_bo_unmap; - - if (ioctl(fd, DRM_IOCTL_BUFOBJ, &arg)) { - return -errno; - } - if (!arg.handled) - return -EFAULT; - if (rep->ret) - return rep->ret; - - return 0; -} - -int drmBOValidate(int fd, drmBO *buf, unsigned flags, unsigned mask, - unsigned hint) -{ - drm_bo_arg_t arg; - drm_bo_arg_request_t *req = &arg.d.req; - drm_bo_arg_reply_t *rep = &arg.d.rep; - int ret = 0; - - memset(&arg, 0, sizeof(arg)); - req->handle = buf->handle; - req->mask = flags; - req->hint = hint; - req->arg_handle = mask; /* Encode mask in the arg_handle field :/ */ - req->op = drm_bo_validate; - - do{ - ret = ioctl(fd, DRM_IOCTL_BUFOBJ, &arg); - } while (ret && errno == EAGAIN); - - if (ret) - return ret; - if (!arg.handled) - return -EFAULT; - if (rep->ret) - return rep->ret; - - drmBOCopyReply(rep, buf); - return 0; -} - - -int drmBOFence(int fd, drmBO *buf, unsigned flags, unsigned fenceHandle) -{ - drm_bo_arg_t arg; - drm_bo_arg_request_t *req = &arg.d.req; - drm_bo_arg_reply_t *rep = &arg.d.rep; - int ret = 0; - - memset(&arg, 0, sizeof(arg)); - req->handle = buf->handle; - req->mask = flags; - req->arg_handle = fenceHandle; - req->op = drm_bo_validate; - - ret = ioctl(fd, DRM_IOCTL_BUFOBJ, &arg); - - if (ret) - return ret; - if (!arg.handled) - return -EFAULT; - if (rep->ret) - return rep->ret; - return 0; -} - -int drmBOInfo(int fd, drmBO *buf) -{ - drm_bo_arg_t arg; - drm_bo_arg_request_t *req = &arg.d.req; - drm_bo_arg_reply_t *rep = &arg.d.rep; - int ret = 0; - - memset(&arg, 0, sizeof(arg)); - req->handle = buf->handle; - req->op = drm_bo_info; - - ret = ioctl(fd, DRM_IOCTL_BUFOBJ, &arg); - - if (ret) - return ret; - if (!arg.handled) - return -EFAULT; - if (rep->ret) - return rep->ret; - drmBOCopyReply(rep, buf); - return 0; -} - -int drmBOWaitIdle(int fd, drmBO *buf, unsigned hint) -{ - drm_bo_arg_t arg; - drm_bo_arg_request_t *req = &arg.d.req; - drm_bo_arg_reply_t *rep = &arg.d.rep; - int ret = 0; - - if ((buf->flags & DRM_BO_FLAG_SHAREABLE) || - (buf->replyFlags & DRM_BO_REP_BUSY)) { - memset(&arg, 0, sizeof(arg)); - req->handle = buf->handle; - req->op = drm_bo_wait_idle; - req->hint = hint; - - do { - ret = ioctl(fd, DRM_IOCTL_BUFOBJ, &arg); - } while (ret && errno == EAGAIN); - - if (ret) - return ret; - if (!arg.handled) - return -EFAULT; - if (rep->ret) - return rep->ret; - drmBOCopyReply(rep, buf); - } - return 0; -} - -int drmBOBusy(int fd, drmBO *buf, int *busy) -{ - if (!(buf->flags & DRM_BO_FLAG_SHAREABLE) && - !(buf->replyFlags & DRM_BO_REP_BUSY)) { - *busy = 0; - return 0; - } else { - int ret = drmBOInfo(fd, buf); - if (ret) - return ret; - *busy = (buf->replyFlags & DRM_BO_REP_BUSY); - return 0; - } -} - - -int drmAddValidateItem(drmBOList *list, drmBO *buf, unsigned flags, - unsigned mask, - int *newItem) -{ - drmBONode *node, *cur; - drmMMListHead *l; - - *newItem = 0; - cur = NULL; - - for (l = list->list.next; l != &list->list; l = l->next) { - node = DRMLISTENTRY(drmBONode, l, head); - if (node->buf == buf) { - cur = node; - break; - } - } - if (!cur) { - cur = drmAddListItem(list, buf, flags, mask); - if (!cur) { - drmMsg("Out of memory creating validate list node.\n"); - return -ENOMEM; - } - *newItem = 1; - cur->arg0 = flags; - cur->arg1 = mask; - } else { - unsigned memMask = (cur->arg1 | mask) & DRM_BO_MASK_MEM; - unsigned memFlags = cur->arg0 & flags & memMask; - - if (!memFlags) { - drmMsg("Incompatible memory location requests " - "on validate list.\n"); - drmMsg("Previous flag: 0x%08lx, mask: 0x%08lx\n", - cur->arg0, cur->arg1); - drmMsg("Current flag: 0x%08lx, mask: 0x%08lx\n", - flags, mask); - return -EINVAL; - } - if (mask & cur->arg1 & ~DRM_BO_MASK_MEM & (cur->arg0 ^ flags)) { - drmMsg("Incompatible buffer flag requests " - "on validate list.\n"); - drmMsg("Previous flag: 0x%08lx, mask: 0x%08lx\n", - cur->arg0, cur->arg1); - drmMsg("Current flag: 0x%08lx, mask: 0x%08lx\n", - flags, mask); - return -EINVAL; - } - cur->arg1 |= mask; - cur->arg0 = memFlags | ((cur->arg0 | flags) & - cur->arg1 & ~DRM_BO_MASK_MEM); - } - return 0; -} - - -int drmBOValidateList(int fd, drmBOList *list) -{ - - drmBONode *node; - drmMMListHead *l; - drm_bo_arg_t *arg, *first; - drm_bo_arg_request_t *req; - drm_bo_arg_reply_t *rep; - drm_u64_t *prevNext = NULL; - drmBO *buf; - int ret; - - first = NULL; - - for (l = list->list.next; l != &list->list; l = l->next) { - node = DRMLISTENTRY(drmBONode, l, head); - - arg = &node->bo_arg; - req = &arg->d.req; - - if (!first) - first = arg; - - if (prevNext) - *prevNext = (unsigned long) arg; - - memset(arg, 0, sizeof(*arg)); - prevNext = &arg->next; - req->handle = node->buf->handle; - req->op = drm_bo_validate; - req->mask = node->arg0; - req->hint = 0; - req->arg_handle = node->arg1; - } - - if (!first) - return 0; - - do{ - ret = ioctl(fd, DRM_IOCTL_BUFOBJ, first); - } while (ret && errno == EAGAIN); - - - if (ret) - return -errno; - - for (l = list->list.next; l != &list->list; l = l->next) { - node = DRMLISTENTRY(drmBONode, l, head); - arg = &node->bo_arg; - rep = &arg->d.rep; - - if (!arg->handled) { - drmMsg("Unhandled request\n"); - return -EFAULT; - } - if (rep->ret) - return rep->ret; - - buf = node->buf; - drmBOCopyReply(rep, buf); - } - - return 0; -} - - -int drmBOFenceList(int fd, drmBOList *list, unsigned fenceHandle) -{ - - drmBONode *node; - drmMMListHead *l; - drm_bo_arg_t *arg, *first; - drm_bo_arg_request_t *req; - drm_bo_arg_reply_t *rep; - drm_u64_t *prevNext = NULL; - int ret; - - first = NULL; - - for (l = list->list.next; l != &list->list; l = l->next) { - node = DRMLISTENTRY(drmBONode, l, head); - - arg = &node->bo_arg; - req = &arg->d.req; - - if (!first) - first = arg; - - if (prevNext) - *prevNext = (unsigned long) arg; - - memset(arg, 0, sizeof(*arg)); - prevNext = &arg->next; - req->handle = node->buf->handle; - req->op = drm_bo_fence; - req->mask = node->arg0; - req->arg_handle = fenceHandle; - } - - if (!first) - return 0; - - ret = ioctl(fd, DRM_IOCTL_BUFOBJ, first); - - if (ret) - return -errno; - - for (l = list->list.next; l != &list->list; l = l->next) { - node = DRMLISTENTRY(drmBONode, l, head); - - arg = &node->bo_arg; - rep = &arg->d.rep; - - if (!arg->handled) - return -EFAULT; - if (rep->ret) - return rep->ret; - drmBOCopyReply(rep, node->buf); - } - - return 0; -} - -int drmMMInit(int fd, unsigned long pOffset, unsigned long pSize, - unsigned memType) -{ - drm_mm_init_arg_t arg; - - memset(&arg, 0, sizeof(arg)); - arg.req.op = mm_init; - arg.req.p_offset = pOffset; - arg.req.p_size = pSize; - arg.req.mem_type = memType; - - if (ioctl(fd, DRM_IOCTL_MM_INIT, &arg)) - return -errno; - - return 0; -} - -int drmMMTakedown(int fd, unsigned memType) -{ - drm_mm_init_arg_t arg; - - - memset(&arg, 0, sizeof(arg)); - arg.req.op = mm_takedown; - arg.req.mem_type = memType; - - if (ioctl(fd, DRM_IOCTL_MM_INIT, &arg)) - return -errno; - - return 0; -} - -int drmMMLock(int fd, unsigned memType) -{ - drm_mm_init_arg_t arg; - int ret; - - memset(&arg, 0, sizeof(arg)); - arg.req.op = mm_lock; - arg.req.mem_type = memType; - - do{ - ret = ioctl(fd, DRM_IOCTL_MM_INIT, &arg); - } while (ret && errno == EAGAIN); - - return ret; -} - -int drmMMUnlock(int fd, unsigned memType) -{ - drm_mm_init_arg_t arg; - int ret; - - memset(&arg, 0, sizeof(arg)); - arg.req.op = mm_unlock; - arg.req.mem_type = memType; - - do{ - ret = ioctl(fd, DRM_IOCTL_MM_INIT, &arg); - } while (ret && errno == EAGAIN); - - return ret; -} diff --git a/hw/xfree86/os-support/drm/xf86drmHash.c b/hw/xfree86/os-support/drm/xf86drmHash.c deleted file mode 100644 index ba81a6e8e..000000000 --- a/hw/xfree86/os-support/drm/xf86drmHash.c +++ /dev/null @@ -1,432 +0,0 @@ -/* 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> - * - * - * 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 - -#include <stdio.h> -#include <stdlib.h> -#if !HASH_MAIN -# include "drm.h" -# include "xf86drm.h" -# include "xf86.h" -#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/hw/xfree86/os-support/drm/xf86drmRandom.c b/hw/xfree86/os-support/drm/xf86drmRandom.c deleted file mode 100644 index cd63aea4e..000000000 --- a/hw/xfree86/os-support/drm/xf86drmRandom.c +++ /dev/null @@ -1,216 +0,0 @@ -/* 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> - * - * - * 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 - -#include <stdio.h> -#include <stdlib.h> -#if !RANDOM_MAIN -# include "drm.h" -# include "xf86drm.h" -# include "xf86.h" -#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/hw/xfree86/os-support/drm/xf86drmSL.c b/hw/xfree86/os-support/drm/xf86drmSL.c deleted file mode 100644 index 36d8fd50e..000000000 --- a/hw/xfree86/os-support/drm/xf86drmSL.c +++ /dev/null @@ -1,488 +0,0 @@ -/* 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> - * - * - * 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" -# include "xf86.h" -#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 diff --git a/hw/xfree86/os-support/xf86drm.h b/hw/xfree86/os-support/xf86drm.h deleted file mode 100644 index 18e4564d1..000000000 --- a/hw/xfree86/os-support/xf86drm.h +++ /dev/null @@ -1,641 +0,0 @@ -/** - * \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. - * - */ - - -#ifndef _XF86DRM_H_ -#define _XF86DRM_H_ - -#include <drm.h> -#include <xf86mm.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 drmUpdateDrawableInfo(int fd, drm_drawable_t handle, - drm_drawable_info_type_t type, - unsigned int num, void *data); -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 |