diff options
Diffstat (limited to 'libdrm')
| -rw-r--r-- | libdrm/Makefile.am | 2 | ||||
| -rw-r--r-- | libdrm/xf86drm.c | 964 | ||||
| -rw-r--r-- | libdrm/xf86drm.h | 5 | ||||
| -rw-r--r-- | libdrm/xf86mm.h | 205 | 
4 files changed, 1174 insertions, 2 deletions
| diff --git a/libdrm/Makefile.am b/libdrm/Makefile.am index b12e87fa..91a7e5dc 100644 --- a/libdrm/Makefile.am +++ b/libdrm/Makefile.am @@ -26,6 +26,6 @@ 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 d4f80b4e..9047c8db 100644 --- a/libdrm/xf86drm.c +++ b/libdrm/xf86drm.c @@ -46,6 +46,9 @@  #  include <sys/mman.h>  # endif  #else +# ifdef HAVE_CONFIG_H +#  include <config.h> +# endif  # include <stdio.h>  # include <stdlib.h>  # include <unistd.h> @@ -66,6 +69,7 @@  # include "drm.h"  #endif +  /* Not all systems have MAP_FAILED defined */  #ifndef MAP_FAILED  #define MAP_FAILED ((void *)-1) @@ -2252,3 +2256,963 @@ int drmCommandWriteRead(int fd, unsigned long drmCommandIndex, void *data,      }      return 0;  } + +#ifdef __linux__ + +/* + * 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; +    int ret = 0; + +    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; +} +     +     + +int drmBOCreate(int fd, void *ttm, unsigned long start, unsigned long size, +		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; + +    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; +    unsigned oldFlags, newFlags; +    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, 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;	 +} + + +#endif diff --git a/libdrm/xf86drm.h b/libdrm/xf86drm.h index d58baa76..86ee7d30 100644 --- a/libdrm/xf86drm.h +++ b/libdrm/xf86drm.h @@ -283,7 +283,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 */ @@ -487,6 +486,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); @@ -636,4 +637,6 @@ extern int  drmSLLookupNeighbors(void *l, unsigned long key,  				 unsigned long *prev_key, void **prev_value,  				 unsigned long *next_key, void **next_value); +#include "xf86mm.h" +  #endif diff --git a/libdrm/xf86mm.h b/libdrm/xf86mm.h new file mode 100644 index 00000000..da868fe5 --- /dev/null +++ b/libdrm/xf86mm.h @@ -0,0 +1,205 @@ +/************************************************************************** + *  + * 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; +} 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; +    void *virtual; +    void *mapVirtual; +    int mapCount; +} 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, void *ttm, unsigned long start, unsigned long size, +			      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 | 
