xserver: Branch 'master' - 3 commits

Thomas Hellstrom thomash at kemper.freedesktop.org
Sun Oct 29 16:27:58 EET 2006


 configure.ac                        |    4 
 hw/xfree86/os-support/drm/xf86drm.c |  955 ++++++++++++++++++++++++++++++++++++
 hw/xfree86/os-support/xf86drm.h     |    1 
 hw/xfree86/os-support/xf86mm.h      |  210 +++++++
 include/libdrm-config.h.in          |   10 
 5 files changed, 1179 insertions(+), 1 deletion(-)

New commits:
diff-tree 0107320fac0913aae2cb169992e31c670b4bd2f7 (from parents)
Merge: 06b6b971d065226b983ba25da7ea8236ec37df04 a34446f5b3d90714969a90583c49cb1eae1c9651
Author: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
Date:   Sun Oct 29 15:23:35 2006 +0100

    Merge branch 'master' of git+ssh://git.freedesktop.org/git/xorg/xserver

diff-tree 06b6b971d065226b983ba25da7ea8236ec37df04 (from 92d04e746bd9b8ad3ee217c165ace20468e079cf)
Author: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
Date:   Sun Oct 29 15:22:37 2006 +0100

    Make sure we have 64-bit file-offsets in libdrm.

diff --git a/configure.ac b/configure.ac
index 140757f..6676ea6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -49,7 +49,8 @@ dnl xwin-config.h covers the XWin DDX.
 AC_CONFIG_HEADERS(include/xwin-config.h)
 dnl kdrive-config.h covers the kdrive DDX
 AC_CONFIG_HEADERS(include/kdrive-config.h)
-
+dnl libdrm now needs 64-bit file offsets
+AC_CONFIG_HEADERS(include/libdrm-config.h)
 
 AC_PROG_CC
 AM_PROG_AS
@@ -62,7 +63,6 @@ AC_PROG_MAKE_SET
 PKG_PROG_PKG_CONFIG
 AC_PROG_LEX
 AC_PROG_YACC
-dnl for libdrm
 AC_SYS_LARGEFILE
 XORG_PROG_RAWCPP
 
diff --git a/hw/xfree86/os-support/drm/xf86drm.c b/hw/xfree86/os-support/drm/xf86drm.c
index ade4266..e990e28 100644
--- a/hw/xfree86/os-support/drm/xf86drm.c
+++ b/hw/xfree86/os-support/drm/xf86drm.c
@@ -33,6 +33,7 @@
 
 
 #ifdef HAVE_XORG_CONFIG_H
+#include <libdrm-config.h>
 #include <xorg-config.h>
 #endif
 
diff --git a/include/libdrm-config.h.in b/include/libdrm-config.h.in
new file mode 100644
index 0000000..286004b
--- /dev/null
+++ b/include/libdrm-config.h.in
@@ -0,0 +1,10 @@
+/* 
+ * libdrm-config.h.in: not at all generated.
+ */
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#undef _FILE_OFFSET_BITS
+
+/* Define for large files, on AIX-style hosts. */
+#undef _LARGE_FILES
+
diff-tree 92d04e746bd9b8ad3ee217c165ace20468e079cf (from 004d00e6689f452fc9fdf91f5ffc6d6aed697d54)
Author: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
Date:   Fri Oct 27 18:26:30 2006 +0200

    Import libdrm functions for the drm memory manager.

diff --git a/configure.ac b/configure.ac
index c0cc003..140757f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -62,6 +62,8 @@ AC_PROG_MAKE_SET
 PKG_PROG_PKG_CONFIG
 AC_PROG_LEX
 AC_PROG_YACC
+dnl for libdrm
+AC_SYS_LARGEFILE
 XORG_PROG_RAWCPP
 
 AC_HEADER_DIRENT
diff --git a/hw/xfree86/os-support/drm/xf86drm.c b/hw/xfree86/os-support/drm/xf86drm.c
index 214e58b..ade4266 100644
--- a/hw/xfree86/os-support/drm/xf86drm.c
+++ b/hw/xfree86/os-support/drm/xf86drm.c
@@ -2305,3 +2305,957 @@ int drmRemoveSIGIOHandler(int fd)
 
     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/xf86drm.h b/hw/xfree86/os-support/xf86drm.h
index 1076706..18e4564 100644
--- a/hw/xfree86/os-support/xf86drm.h
+++ b/hw/xfree86/os-support/xf86drm.h
@@ -36,6 +36,7 @@
 #define _XF86DRM_H_
 
 #include <drm.h>
+#include <xf86mm.h>
 
 				/* Defaults, if nothing set in xf86config */
 #define DRM_DEV_UID	 0
diff --git a/hw/xfree86/os-support/xf86mm.h b/hw/xfree86/os-support/xf86mm.h
new file mode 100644
index 0000000..e1a4e3e
--- /dev/null
+++ b/hw/xfree86/os-support/xf86mm.h
@@ -0,0 +1,210 @@
+/**************************************************************************
+ * 
+ * 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);
+extern int drmFenceUpdate(int fd, 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



More information about the xorg-commit mailing list