summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Hellstrom <thomas-at-tungstengraphics-dot-com>2006-10-27 18:26:30 +0200
committerThomas Hellstrom <thomas-at-tungstengraphics-dot-com>2006-10-27 18:26:30 +0200
commit92d04e746bd9b8ad3ee217c165ace20468e079cf (patch)
treed578509fbb44334ddf2d6a70c8249fe51b7f35d7
parent004d00e6689f452fc9fdf91f5ffc6d6aed697d54 (diff)
Import libdrm functions for the drm memory manager.
-rw-r--r--configure.ac2
-rw-r--r--hw/xfree86/os-support/drm/xf86drm.c954
-rw-r--r--hw/xfree86/os-support/xf86drm.h1
-rw-r--r--hw/xfree86/os-support/xf86mm.h210
4 files changed, 1167 insertions, 0 deletions
diff --git a/configure.ac b/configure.ac
index c0cc00311..140757f9f 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 214e58ba7..ade4266a4 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 107670672..18e4564d1 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 000000000..e1a4e3ed9
--- /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