diff options
author | Nian Wu <nian.wu@intel.com> | 2006-11-09 21:21:17 -0800 |
---|---|---|
committer | Nian Wu <nian.wu@intel.com> | 2006-11-09 21:21:17 -0800 |
commit | 14e3f2711e90fe9a9c315d96abd4c7681539936a (patch) | |
tree | 6a562d9035e56671eb7905bac1f3829597f109a9 /libdrm | |
parent | e2ea72187e470c2c13adbd3fba4177bd4a0ecc37 (diff) | |
parent | d51e1bb56ca2f7858cdeac6f61a7b747c1e15b1e (diff) |
Merge branch 'master' into crestline
Conflicts:
shared-core/i915_dma.c
Diffstat (limited to 'libdrm')
-rw-r--r-- | libdrm/Makefile.am | 4 | ||||
-rw-r--r-- | libdrm/xf86drm.c | 1196 | ||||
-rw-r--r-- | libdrm/xf86drm.h | 34 | ||||
-rw-r--r-- | libdrm/xf86mm.h | 209 |
4 files changed, 1361 insertions, 82 deletions
diff --git a/libdrm/Makefile.am b/libdrm/Makefile.am index b12e87fa..e7e07e47 100644 --- a/libdrm/Makefile.am +++ b/libdrm/Makefile.am @@ -20,12 +20,12 @@ libdrm_la_LTLIBRARIES = libdrm.la libdrm_ladir = $(libdir) -libdrm_la_LDFLAGS = -version-number 2:0:0 -no-undefined +libdrm_la_LDFLAGS = -version-number 2:3:0 -no-undefined AM_CFLAGS = -I$(top_srcdir)/shared-core libdrm_la_SOURCES = xf86drm.c xf86drmHash.c xf86drmRandom.c xf86drmSL.c libdrmincludedir = ${includedir} -libdrminclude_HEADERS = xf86drm.h +libdrminclude_HEADERS = xf86drm.h xf86mm.h EXTRA_DIST = ChangeLog TODO diff --git a/libdrm/xf86drm.c b/libdrm/xf86drm.c index c9f1b2db..56450e80 100644 --- a/libdrm/xf86drm.c +++ b/libdrm/xf86drm.c @@ -35,36 +35,25 @@ #include <xorg-config.h> #endif -#ifdef XFree86Server -# include "xf86.h" -# include "xf86_OSproc.h" -# include "drm.h" -# include "xf86_ansic.h" -# define _DRM_MALLOC xalloc -# define _DRM_FREE xfree -# ifndef XFree86LOADER -# include <sys/mman.h> -# endif -#else -# include <stdio.h> -# include <stdlib.h> -# include <unistd.h> -# include <string.h> -# include <ctype.h> -# include <fcntl.h> -# include <errno.h> -# include <signal.h> -# include <sys/types.h> -# include <sys/stat.h> -# define stat_t struct stat -# include <sys/ioctl.h> -# include <sys/mman.h> -# include <sys/time.h> -# include <stdarg.h> -# define _DRM_MALLOC malloc -# define _DRM_FREE free -# include "drm.h" +#ifdef HAVE_CONFIG_H +# include <config.h> #endif +#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> +#include "drm.h" /* Not all systems have MAP_FAILED defined */ #ifndef MAP_FAILED @@ -103,6 +92,13 @@ #define DRM_MSG_VERBOSITY 3 +static drmServerInfoPtr drm_server_info; + +void drmSetServerInfo(drmServerInfoPtr info) +{ + drm_server_info = info; +} + /** * Output a message to stderr. * @@ -111,44 +107,54 @@ * \internal * This function is a wrapper around vfprintf(). */ + +static int drmDebugPrint(const char *format, va_list ap) +{ + return vfprintf(stderr, format, ap); +} + +static int (*drm_debug_print)(const char *format, va_list ap) = drmDebugPrint; + static void drmMsg(const char *format, ...) { va_list ap; - -#ifndef XFree86Server const char *env; - if ((env = getenv("LIBGL_DEBUG")) && strstr(env, "verbose")) -#endif + if (((env = getenv("LIBGL_DEBUG")) && strstr(env, "verbose")) || drm_server_info) { va_start(ap, format); -#ifdef XFree86Server - xf86VDrvMsgVerb(-1, X_NONE, DRM_MSG_VERBOSITY, format, ap); -#else - vfprintf(stderr, format, ap); -#endif + if (drm_server_info) { + drm_server_info->debug_print(format,ap); + } else { + drm_debug_print(format, ap); + } va_end(ap); } } +void +drmSetDebugMsgFunction(int (*debug_msg_ptr)(const char *format, va_list ap)) +{ + drm_debug_print = debug_msg_ptr; +} + static void *drmHashTable = NULL; /* Context switch callbacks */ -typedef struct drmHashEntry { - int fd; - void (*f)(int, void *, void *); - void *tagTable; -} drmHashEntry; +void *drmGetHashTable(void) +{ + return drmHashTable; +} void *drmMalloc(int size) { void *pt; - if ((pt = _DRM_MALLOC(size))) memset(pt, 0, size); + if ((pt = malloc(size))) memset(pt, 0, size); return pt; } void drmFree(void *pt) { - if (pt) _DRM_FREE(pt); + if (pt) free(pt); } /* drmStrdup can't use strdup(3), since it doesn't call _DRM_MALLOC... */ @@ -159,7 +165,7 @@ static char *drmStrdup(const char *s) if (!s) return NULL; - retval = _DRM_MALLOC(strlen(s)+1); + retval = malloc(strlen(s)+1); if (!retval) return NULL; @@ -178,7 +184,7 @@ static unsigned long drmGetKeyFromFd(int fd) return st.st_rdev; } -static drmHashEntry *drmGetEntry(int fd) +drmHashEntry *drmGetEntry(int fd) { unsigned long key = drmGetKeyFromFd(fd); void *value; @@ -265,21 +271,20 @@ static int drmOpenDevice(long dev, int minor) stat_t st; char buf[64]; int fd; - mode_t devmode = DRM_DEV_MODE; + mode_t devmode = DRM_DEV_MODE, serv_mode; int isroot = !geteuid(); -#if defined(XFree86Server) uid_t user = DRM_DEV_UID; - gid_t group = DRM_DEV_GID; -#endif - + gid_t group = DRM_DEV_GID, serv_group; + sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, minor); drmMsg("drmOpenDevice: node name is %s\n", buf); -#if defined(XFree86Server) - devmode = xf86ConfigDRI.mode ? xf86ConfigDRI.mode : DRM_DEV_MODE; - devmode &= ~(S_IXUSR|S_IXGRP|S_IXOTH); - group = (xf86ConfigDRI.group >= 0) ? xf86ConfigDRI.group : DRM_DEV_GID; -#endif + if (drm_server_info) { + drm_server_info->get_perms(&serv_group, &serv_mode); + devmode = serv_mode ? serv_mode : DRM_DEV_MODE; + devmode &= ~(S_IXUSR|S_IXGRP|S_IXOTH); + group = (serv_group >= 0) ? serv_group : DRM_DEV_GID; + } if (stat(DRM_DIR_NAME, &st)) { if (!isroot) return DRM_ERR_NOT_ROOT; @@ -294,10 +299,11 @@ static int drmOpenDevice(long dev, int minor) remove(buf); mknod(buf, S_IFCHR | devmode, dev); } -#if defined(XFree86Server) - chown(buf, user, group); - chmod(buf, devmode); -#endif + + if (drm_server_info) { + chown(buf, user, group); + chmod(buf, devmode); + } fd = open(buf, O_RDWR, 0); drmMsg("drmOpenDevice: open result is %d, (%s)\n", @@ -311,10 +317,10 @@ static int drmOpenDevice(long dev, int minor) if (!isroot) return DRM_ERR_NOT_ROOT; remove(buf); mknod(buf, S_IFCHR | devmode, dev); -#if defined(XFree86Server) - chown(buf, user, group); - chmod(buf, devmode); -#endif + if (drm_server_info) { + chown(buf, user, group); + chmod(buf, devmode); + } } fd = open(buf, O_RDWR, 0); drmMsg("drmOpenDevice: open result is %d, (%s)\n", @@ -452,16 +458,16 @@ static int drmOpenByName(const char *name) char * id; if (!drmAvailable()) { -#if !defined(XFree86Server) + if (!drm_server_info) return -1; -#else + else { /* try to load the kernel module now */ - if (!xf86LoadKernelModule(name)) { - ErrorF("[drm] failed to load kernel module \"%s\"\n", - name); - return -1; + if (!drm_server_info->load_module(name)) { + drmMsg("[drm] failed to load kernel module \"%s\"\n", + name); + return -1; } -#endif + } } /* @@ -543,16 +549,14 @@ static int drmOpenByName(const char *name) */ int drmOpen(const char *name, const char *busid) { -#ifdef XFree86Server - if (!drmAvailable() && name != NULL) { + if (!drmAvailable() && name != NULL && drm_server_info) { /* try to load the kernel */ - if (!xf86LoadKernelModule(name)) { - ErrorF("[drm] failed to load kernel module \"%s\"\n", + if (!drm_server_info->load_module(name)) { + drmMsg("[drm] failed to load kernel module \"%s\"\n", name); return -1; } } -#endif if (busid) { int fd; @@ -706,15 +710,17 @@ drmVersionPtr drmGetLibVersion(int fd) drm_version_t *version = drmMalloc(sizeof(*version)); /* Version history: + * NOTE THIS MUST NOT GO ABOVE VERSION 1.X due to drivers needing it * 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 + * revision 1.3.x = added server + memory manager */ version->version_major = 1; - version->version_minor = 2; + version->version_minor = 3; version->version_patchlevel = 0; return (drmVersionPtr)version; @@ -1397,6 +1403,22 @@ int drmDestroyDrawable(int fd, drm_drawable_t handle) 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. * @@ -2236,3 +2258,1021 @@ int drmCommandWriteRead(int fd, unsigned long drmCommandIndex, void *data, } return 0; } + + +/* + * 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; + drmBO *buf; + unsigned fence_flags; + 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; +} + +#define DRM_MAX_FDS 16 +static struct { + char *BusID; + int fd; + int refcount; +} connection[DRM_MAX_FDS]; + +static int nr_fds = 0; + +int drmOpenOnce(void *unused, + const char *BusID, + int *newlyopened) +{ + int i; + int fd; + + for (i = 0; i < nr_fds; i++) + if (strcmp(BusID, connection[i].BusID) == 0) { + connection[i].refcount++; + *newlyopened = 0; + return connection[i].fd; + } + + fd = drmOpen(unused, BusID); + if (fd <= 0 || nr_fds == DRM_MAX_FDS) + return fd; + + connection[nr_fds].BusID = strdup(BusID); + connection[nr_fds].fd = fd; + connection[nr_fds].refcount = 1; + *newlyopened = 1; + + if (0) + fprintf(stderr, "saved connection %d for %s %d\n", + nr_fds, connection[nr_fds].BusID, + strcmp(BusID, connection[nr_fds].BusID)); + + nr_fds++; + + return fd; +} + +void drmCloseOnce(int fd) +{ + int i; + + for (i = 0; i < nr_fds; i++) { + if (fd == connection[i].fd) { + if (--connection[i].refcount == 0) { + drmClose(connection[i].fd); + free(connection[i].BusID); + + if (i < --nr_fds) + connection[i] = connection[nr_fds]; + + return; + } + } + } +} diff --git a/libdrm/xf86drm.h b/libdrm/xf86drm.h index 48a18f29..34c9ec0e 100644 --- a/libdrm/xf86drm.h +++ b/libdrm/xf86drm.h @@ -36,6 +36,8 @@ #ifndef _XF86DRM_H_ #define _XF86DRM_H_ +#include <stdarg.h> +#include <sys/types.h> #include <drm.h> /* Defaults, if nothing set in xf86config */ @@ -61,6 +63,21 @@ typedef unsigned int drmSize, *drmSizePtr; /**< For mapped regions */ typedef void *drmAddress, **drmAddressPtr; /**< For mapped regions */ +typedef struct _drmServerInfo { + int (*debug_print)(const char *format, va_list ap); + int (*load_module)(const char *name); + void (*get_perms)(gid_t *, mode_t *); +} drmServerInfo, *drmServerInfoPtr; + +typedef struct drmHashEntry { + int fd; + void (*f)(int, void *, void *); + void *tagTable; +} drmHashEntry; + +extern void *drmGetHashTable(void); +extern drmHashEntry *drmGetEntry(int fd); + /** * Driver version information. * @@ -149,7 +166,8 @@ typedef enum { DRM_PAGE_ALIGN = 0x01, DRM_AGP_BUFFER = 0x02, DRM_SG_BUFFER = 0x04, - DRM_FB_BUFFER = 0x08 + DRM_FB_BUFFER = 0x08, + DRM_PCI_BUFFER_RO = 0x10 } drmBufDescFlags; typedef enum { @@ -252,6 +270,8 @@ typedef struct _drmTextureRegion { typedef enum { DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */ DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */ + DRM_VBLANK_NEXTONMISS = 0x10000000, /**< If missed, wait for next vblank */ + DRM_VBLANK_SECONDARY = 0x20000000, /**< Secondary display controller */ DRM_VBLANK_SIGNAL = 0x40000000 /* Send signal instead of blocking */ } drmVBlankSeqType; @@ -280,7 +300,6 @@ typedef struct _drmSetVersion { int drm_dd_minor; } drmSetVersion, *drmSetVersionPtr; - #define __drm_dummy_lock(lock) (*(__volatile__ unsigned int *)lock) #define DRM_LOCK_HELD 0x80000000U /**< Hardware lock is held */ @@ -484,6 +503,8 @@ do { register unsigned int __old __asm("o0"); \ } \ } while(0) + + /* General user-level programmer's API: unprivileged */ extern int drmAvailable(void); extern int drmOpen(const char *name, const char *busid); @@ -544,6 +565,9 @@ 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); @@ -597,6 +621,7 @@ extern int drmScatterGatherFree(int fd, drm_handle_t handle); extern int drmWaitVBlank(int fd, drmVBlankPtr vbl); /* Support routines */ +extern void drmSetServerInfo(drmServerInfoPtr info); extern int drmError(int err, const char *label); extern void *drmMalloc(int size); extern void drmFree(void *pt); @@ -630,4 +655,9 @@ extern int drmSLLookupNeighbors(void *l, unsigned long key, unsigned long *prev_key, void **prev_value, unsigned long *next_key, void **next_value); +extern int drmOpenOnce(void *unused, const char *BusID, int *newlyopened); +extern void drmCloseOnce(int fd); + +#include "xf86mm.h" + #endif diff --git a/libdrm/xf86mm.h b/libdrm/xf86mm.h new file mode 100644 index 00000000..bd0d2812 --- /dev/null +++ b/libdrm/xf86mm.h @@ -0,0 +1,209 @@ +/************************************************************************** + * + * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND. USA. + * 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, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS 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. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * + **************************************************************************/ + +#ifndef _XF86MM_H_ +#define _XF86MM_H_ +#include <stddef.h> +#include "drm.h" + +/* + * Note on multithreaded applications using this interface. + * Libdrm is not threadsafe, so common buffer, TTM, and fence objects need to + * be protected using an external mutex. + * + * Note: Don't protect the following functions, as it may lead to deadlocks: + * drmBOUnmap(), drmFenceBuffers(). + * The kernel is synchronizing and refcounting buffer maps. + * User space only needs to refcount object usage within the same application. + */ + + +/* + * List macros heavily inspired by the Linux kernel + * list handling. No list looping yet. + */ + +typedef struct _drmMMListHead +{ + struct _drmMMListHead *prev; + struct _drmMMListHead *next; +} drmMMListHead; + +#define DRMINITLISTHEAD(__item) \ + do{ \ + (__item)->prev = (__item); \ + (__item)->next = (__item); \ + } while (0) + +#define DRMLISTADD(__item, __list) \ + do { \ + (__item)->prev = (__list); \ + (__item)->next = (__list)->next; \ + (__list)->next->prev = (__item); \ + (__list)->next = (__item); \ + } while (0) + +#define DRMLISTADDTAIL(__item, __list) \ + do { \ + (__item)->next = (__list); \ + (__item)->prev = (__list)->prev; \ + (__list)->prev->next = (__item); \ + (__list)->prev = (__item); \ + } while(0) + +#define DRMLISTDEL(__item) \ + do { \ + (__item)->prev->next = (__item)->next; \ + (__item)->next->prev = (__item)->prev; \ + } while(0) + +#define DRMLISTDELINIT(__item) \ + do { \ + (__item)->prev->next = (__item)->next; \ + (__item)->next->prev = (__item)->prev; \ + (__item)->next = (__item); \ + (__item)->prev = (__item); \ + } while(0) + +#define DRMLISTENTRY(__type, __item, __field) \ + ((__type *)(((char *) (__item)) - offsetof(__type, __field))) + +typedef struct _drmFence{ + unsigned handle; + int class; + unsigned type; + unsigned flags; + unsigned signaled; + unsigned pad[4]; /* for future expansion */ +} drmFence; + +typedef struct _drmBO{ + drm_bo_type_t type; + unsigned handle; + drm_u64_t mapHandle; + unsigned flags; + unsigned mask; + unsigned mapFlags; + unsigned long size; + unsigned long offset; + unsigned long start; + unsigned replyFlags; + unsigned fenceFlags; + unsigned pageAlignment; + void *virtual; + void *mapVirtual; + int mapCount; + unsigned pad[8]; /* for future expansion */ +} drmBO; + + +typedef struct _drmBONode { + drmMMListHead head; + drmBO *buf; + drm_bo_arg_t bo_arg; + unsigned long arg0; + unsigned long arg1; +} drmBONode; + +typedef struct _drmBOList { + unsigned numTarget; + unsigned numCurrent; + unsigned numOnList; + drmMMListHead list; + drmMMListHead free; +} drmBOList; + +/* Fencing */ + +extern int drmFenceCreate(int fd, unsigned flags, int class, + unsigned type, + drmFence *fence); +extern int drmFenceDestroy(int fd, const drmFence *fence); +extern int drmFenceReference(int fd, unsigned handle, drmFence *fence); +extern int drmFenceUnreference(int fd, const drmFence *fence); +extern int drmFenceFlush(int fd, drmFence *fence, unsigned flush_type); +extern int drmFenceSignaled(int fd, drmFence *fence, + unsigned fenceType, int *signaled); +extern int drmFenceWait(int fd, unsigned flags, drmFence *fence, + unsigned flush_type); +extern int drmFenceEmit(int fd, unsigned flags, drmFence *fence, + unsigned emit_type); +extern int drmFenceBuffers(int fd, unsigned flags, drmFence *fence); + + +/* + * Buffer object list functions. + */ + +extern void drmBOFreeList(drmBOList *list); +extern int drmBOResetList(drmBOList *list); +extern void *drmBOListIterator(drmBOList *list); +extern void *drmBOListNext(drmBOList *list, void *iterator); +extern drmBO *drmBOListBuf(void *iterator); +extern int drmBOCreateList(int numTarget, drmBOList *list); + +/* + * Buffer object functions. + */ + +extern 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); +extern int drmBODestroy(int fd, drmBO *buf); +extern int drmBOReference(int fd, unsigned handle, drmBO *buf); +extern int drmBOUnReference(int fd, drmBO *buf); +extern int drmBOMap(int fd, drmBO *buf, unsigned mapFlags, unsigned mapHint, + void **address); +extern int drmBOUnmap(int fd, drmBO *buf); +extern int drmBOValidate(int fd, drmBO *buf, unsigned flags, unsigned mask, + unsigned hint); +extern int drmBOFence(int fd, drmBO *buf, unsigned flags, unsigned fenceHandle); +extern int drmBOInfo(int fd, drmBO *buf); +extern int drmBOBusy(int fd, drmBO *buf, int *busy); + + +extern int drmAddValidateItem(drmBOList *list, drmBO *buf, unsigned flags, + unsigned mask, + int *newItem); +extern int drmBOValidateList(int fd, drmBOList *list); +extern int drmBOFenceList(int fd, drmBOList *list, unsigned fenceHandle); +extern int drmBOWaitIdle(int fd, drmBO *buf, unsigned hint); + +/* + * Initialization functions. + */ + +extern int drmMMInit(int fd, unsigned long pOffset, unsigned long pSize, + unsigned memType); +extern int drmMMTakedown(int fd, unsigned memType); +extern int drmMMLock(int fd, unsigned memType); +extern int drmMMUnlock(int fd, unsigned memType); + + +#endif |