[libdrm/f17] libdrm 2.4.37

Ben Skeggs bskeggs at fedoraproject.org
Tue Jul 3 06:58:05 UTC 2012


commit 6c57a7bbf84b1e56ed3372b9f546c9eb67f0fa4b
Author: Ben Skeggs <bskeggs at redhat.com>
Date:   Mon Jul 2 17:09:36 2012 +1000

    libdrm 2.4.37

 .gitignore                    |    1 +
 libdrm-2.4.37-nouveau-1.patch | 3061 +++++++++++++++++++++++++++++++++++++++++
 libdrm.spec                   |   18 +-
 sources                       |    2 +-
 4 files changed, 3078 insertions(+), 4 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index a7c1334..be127df 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,3 +15,4 @@ libdrm-20100612.tar.bz2
 /libdrm-2.4.31.tar.bz2
 /libdrm-2.4.32.tar.bz2
 /libdrm-2.4.33.tar.bz2
+/libdrm-2.4.37.tar.bz2
diff --git a/libdrm-2.4.37-nouveau-1.patch b/libdrm-2.4.37-nouveau-1.patch
new file mode 100644
index 0000000..e24bb71
--- /dev/null
+++ b/libdrm-2.4.37-nouveau-1.patch
@@ -0,0 +1,3061 @@
+From 77e3ab9962c13e75c121ba3686a07e441ebf9191 Mon Sep 17 00:00:00 2001
+From: Ben Skeggs <bskeggs at redhat.com>
+Date: Mon, 2 Jul 2012 10:50:45 +1000
+Subject: [PATCH] nouveau: forward-port old nouveau interface to libdrm 2.4.37
+
+For compatibility with current F17, the old interface's pkgconfig data
+is the same as it was before.  If we ever want to update the DDX or Mesa
+to use the newer interface instead, libdrm_nouveau2 pkgconfig will be
+needed instead.
+
+v2: renamed libdrm_nouveau_2 to libdrm_nouveau2 as suggested by airlied
+---
+ Makefile.am                    |    2 +-
+ configure.ac                   |    4 +-
+ nouveau-1/Makefile.am          |   43 ++++
+ nouveau-1/libdrm_nouveau.pc.in |   11 +
+ nouveau-1/nouveau_bo.c         |  549 ++++++++++++++++++++++++++++++++++++++++
+ nouveau-1/nouveau_bo.h         |  104 ++++++++
+ nouveau-1/nouveau_channel.c    |  142 +++++++++++
+ nouveau-1/nouveau_channel.h    |   57 +++++
+ nouveau-1/nouveau_device.c     |  198 +++++++++++++++
+ nouveau-1/nouveau_device.h     |   33 +++
+ nouveau-1/nouveau_drmif.h      |   58 +++++
+ nouveau-1/nouveau_grobj.c      |  148 +++++++++++
+ nouveau-1/nouveau_grobj.h      |   48 ++++
+ nouveau-1/nouveau_notifier.c   |  148 +++++++++++
+ nouveau-1/nouveau_notifier.h   |   63 +++++
+ nouveau-1/nouveau_private.h    |  136 ++++++++++
+ nouveau-1/nouveau_pushbuf.c    |  344 +++++++++++++++++++++++++
+ nouveau-1/nouveau_pushbuf.h    |  162 ++++++++++++
+ nouveau-1/nouveau_reloc.c      |  154 +++++++++++
+ nouveau-1/nouveau_reloc.h      |   32 +++
+ nouveau-1/nouveau_resource.c   |  124 +++++++++
+ nouveau-1/nouveau_resource.h   |   51 ++++
+ nouveau-1/nv04_pushbuf.h       |   66 +++++
+ nouveau-1/nvc0_pushbuf.h       |   92 +++++++
+ nouveau/Makefile.am            |   20 +-
+ nouveau/libdrm_nouveau.pc.in   |   11 -
+ nouveau/libdrm_nouveau2.pc.in  |   11 +
+ 27 files changed, 2788 insertions(+), 23 deletions(-)
+ create mode 100644 nouveau-1/Makefile.am
+ create mode 100644 nouveau-1/libdrm_nouveau.pc.in
+ create mode 100644 nouveau-1/nouveau_bo.c
+ create mode 100644 nouveau-1/nouveau_bo.h
+ create mode 100644 nouveau-1/nouveau_channel.c
+ create mode 100644 nouveau-1/nouveau_channel.h
+ create mode 100644 nouveau-1/nouveau_device.c
+ create mode 100644 nouveau-1/nouveau_device.h
+ create mode 100644 nouveau-1/nouveau_drmif.h
+ create mode 100644 nouveau-1/nouveau_grobj.c
+ create mode 100644 nouveau-1/nouveau_grobj.h
+ create mode 100644 nouveau-1/nouveau_notifier.c
+ create mode 100644 nouveau-1/nouveau_notifier.h
+ create mode 100644 nouveau-1/nouveau_private.h
+ create mode 100644 nouveau-1/nouveau_pushbuf.c
+ create mode 100644 nouveau-1/nouveau_pushbuf.h
+ create mode 100644 nouveau-1/nouveau_reloc.c
+ create mode 100644 nouveau-1/nouveau_reloc.h
+ create mode 100644 nouveau-1/nouveau_resource.c
+ create mode 100644 nouveau-1/nouveau_resource.h
+ create mode 100644 nouveau-1/nv04_pushbuf.h
+ create mode 100644 nouveau-1/nvc0_pushbuf.h
+ delete mode 100644 nouveau/libdrm_nouveau.pc.in
+ create mode 100644 nouveau/libdrm_nouveau2.pc.in
+
+diff --git a/Makefile.am b/Makefile.am
+index 256a8cc..045add1 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -34,7 +34,7 @@ INTEL_SUBDIR = intel
+ endif
+ 
+ if HAVE_NOUVEAU
+-NOUVEAU_SUBDIR = nouveau
++NOUVEAU_SUBDIR = nouveau-1 nouveau
+ endif
+ 
+ if HAVE_RADEON
+diff --git a/configure.ac b/configure.ac
+index a1c8c69..86dd25e 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -319,8 +319,10 @@ AC_CONFIG_FILES([
+ 	intel/libdrm_intel.pc
+ 	radeon/Makefile
+ 	radeon/libdrm_radeon.pc
++	nouveau-1/Makefile
++	nouveau-1/libdrm_nouveau.pc
+ 	nouveau/Makefile
+-	nouveau/libdrm_nouveau.pc
++	nouveau/libdrm_nouveau2.pc
+ 	omap/Makefile
+ 	omap/libdrm_omap.pc
+ 	exynos/Makefile
+diff --git a/nouveau-1/Makefile.am b/nouveau-1/Makefile.am
+new file mode 100644
+index 0000000..8b89916
+--- /dev/null
++++ b/nouveau-1/Makefile.am
+@@ -0,0 +1,43 @@
++AM_CFLAGS = \
++	$(WARN_CFLAGS) \
++	-I$(top_srcdir) \
++	-I$(top_srcdir)/nouveau \
++	$(PTHREADSTUBS_CFLAGS) \
++	-I$(top_srcdir)/include/drm
++
++libdrm_nouveau_la_LTLIBRARIES = libdrm_nouveau.la
++libdrm_nouveau_ladir = $(libdir)
++libdrm_nouveau_la_LDFLAGS = -version-number 1:0:0 -no-undefined
++libdrm_nouveau_la_LIBADD = ../libdrm.la @PTHREADSTUBS_LIBS@
++
++libdrm_nouveau_la_SOURCES = \
++			    nouveau_device.c \
++			    nouveau_channel.c \
++			    nouveau_pushbuf.c \
++			    nouveau_grobj.c \
++			    nouveau_notifier.c \
++			    nouveau_bo.c \
++			    nouveau_resource.c \
++			    nouveau_private.h \
++			    nouveau_reloc.c
++
++libdrm_nouveaucommonincludedir = ${includedir}/nouveau
++libdrm_nouveaucommoninclude_HEADERS = \
++				nouveau_device.h \
++				nouveau_channel.h \
++				nouveau_grobj.h \
++				nouveau_notifier.h \
++				nouveau_pushbuf.h \
++				nv04_pushbuf.h \
++				nvc0_pushbuf.h \
++				nouveau_bo.h \
++				nouveau_resource.h \
++				nouveau_reloc.h
++
++
++libdrm_nouveauincludedir = ${includedir}/libdrm
++libdrm_nouveauinclude_HEADERS = \
++				nouveau_drmif.h
++
++pkgconfigdir = @pkgconfigdir@
++pkgconfig_DATA = libdrm_nouveau.pc
+diff --git a/nouveau-1/libdrm_nouveau.pc.in b/nouveau-1/libdrm_nouveau.pc.in
+new file mode 100644
+index 0000000..c78a28a
+--- /dev/null
++++ b/nouveau-1/libdrm_nouveau.pc.in
+@@ -0,0 +1,11 @@
++prefix=@prefix@
++exec_prefix=@exec_prefix@
++libdir=@libdir@
++includedir=@includedir@
++
++Name: libdrm_nouveau
++Description: Userspace interface to nouveau kernel DRM services
++Version: 0.6
++Libs: -L${libdir} -ldrm_nouveau
++Cflags: -I${includedir} -I${includedir}/libdrm -I${includedir}/nouveau
++Requires.private: libdrm
+diff --git a/nouveau-1/nouveau_bo.c b/nouveau-1/nouveau_bo.c
+new file mode 100644
+index 0000000..d6bb22d
+--- /dev/null
++++ b/nouveau-1/nouveau_bo.c
+@@ -0,0 +1,549 @@
++/*
++ * Copyright 2007 Nouveau Project
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++ * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
++ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif
++#include <stdint.h>
++#include <stdlib.h>
++#include <errno.h>
++#include <assert.h>
++
++#include <sys/mman.h>
++
++#include "nouveau_private.h"
++
++int
++nouveau_bo_init(struct nouveau_device *dev)
++{
++	return 0;
++}
++
++void
++nouveau_bo_takedown(struct nouveau_device *dev)
++{
++}
++
++static int
++nouveau_bo_info(struct nouveau_bo_priv *nvbo, struct drm_nouveau_gem_info *arg)
++{
++	nvbo->handle = nvbo->base.handle = arg->handle;
++	nvbo->domain = arg->domain;
++	nvbo->size = arg->size;
++	nvbo->offset = arg->offset;
++	nvbo->map_handle = arg->map_handle;
++	nvbo->base.tile_mode = arg->tile_mode;
++	/* XXX - flag inverted for backwards compatibility */
++	nvbo->base.tile_flags = arg->tile_flags ^ NOUVEAU_GEM_TILE_NONCONTIG;
++	return 0;
++}
++
++static int
++nouveau_bo_allocated(struct nouveau_bo_priv *nvbo)
++{
++	if (nvbo->sysmem || nvbo->handle)
++		return 1;
++	return 0;
++}
++
++static int
++nouveau_bo_ualloc(struct nouveau_bo_priv *nvbo)
++{
++	if (nvbo->user || nvbo->sysmem) {
++		assert(nvbo->sysmem);
++		return 0;
++	}
++
++	nvbo->sysmem = malloc(nvbo->size);
++	if (!nvbo->sysmem)
++		return -ENOMEM;
++
++	return 0;
++}
++
++static void
++nouveau_bo_ufree(struct nouveau_bo_priv *nvbo)
++{
++	if (nvbo->sysmem) {
++		if (!nvbo->user)
++			free(nvbo->sysmem);
++		nvbo->sysmem = NULL;
++	}
++}
++
++static void
++nouveau_bo_kfree(struct nouveau_bo_priv *nvbo)
++{
++	struct nouveau_device_priv *nvdev = nouveau_device(nvbo->base.device);
++	struct drm_gem_close req;
++
++	if (!nvbo->handle)
++		return;
++
++	if (nvbo->map) {
++		munmap(nvbo->map, nvbo->size);
++		nvbo->map = NULL;
++	}
++
++	req.handle = nvbo->handle;
++	nvbo->handle = 0;
++	drmIoctl(nvdev->fd, DRM_IOCTL_GEM_CLOSE, &req);
++}
++
++static int
++nouveau_bo_kalloc(struct nouveau_bo_priv *nvbo, struct nouveau_channel *chan)
++{
++	struct nouveau_device_priv *nvdev = nouveau_device(nvbo->base.device);
++	struct drm_nouveau_gem_new req;
++	struct drm_nouveau_gem_info *info = &req.info;
++	int ret;
++
++	if (nvbo->handle)
++		return 0;
++
++	req.channel_hint = chan ? chan->id : 0;
++	req.align = nvbo->align;
++
++
++	info->size = nvbo->size;
++	info->domain = 0;
++
++	if (nvbo->flags & NOUVEAU_BO_VRAM)
++		info->domain |= NOUVEAU_GEM_DOMAIN_VRAM;
++	if (nvbo->flags & NOUVEAU_BO_GART)
++		info->domain |= NOUVEAU_GEM_DOMAIN_GART;
++	if (!info->domain) {
++		info->domain |= (NOUVEAU_GEM_DOMAIN_VRAM |
++				 NOUVEAU_GEM_DOMAIN_GART);
++	}
++
++	if (nvbo->flags & NOUVEAU_BO_MAP)
++		info->domain |= NOUVEAU_GEM_DOMAIN_MAPPABLE;
++
++	info->tile_mode = nvbo->base.tile_mode;
++	info->tile_flags = nvbo->base.tile_flags;
++	/* XXX - flag inverted for backwards compatibility */
++	info->tile_flags ^= NOUVEAU_GEM_TILE_NONCONTIG;
++	if (!nvdev->has_bo_usage)
++		info->tile_flags &= NOUVEAU_GEM_TILE_LAYOUT_MASK;
++
++	ret = drmCommandWriteRead(nvdev->fd, DRM_NOUVEAU_GEM_NEW,
++				  &req, sizeof(req));
++	if (ret)
++		return ret;
++
++	nouveau_bo_info(nvbo, &req.info);
++	return 0;
++}
++
++static int
++nouveau_bo_kmap(struct nouveau_bo_priv *nvbo)
++{
++	struct nouveau_device_priv *nvdev = nouveau_device(nvbo->base.device);
++
++	if (nvbo->map)
++		return 0;
++
++	if (!nvbo->map_handle)
++		return -EINVAL;
++
++	nvbo->map = mmap(0, nvbo->size, PROT_READ | PROT_WRITE,
++			 MAP_SHARED, nvdev->fd, nvbo->map_handle);
++	if (nvbo->map == MAP_FAILED) {
++		nvbo->map = NULL;
++		return -errno;
++	}
++
++	return 0;
++}
++
++int
++nouveau_bo_new_tile(struct nouveau_device *dev, uint32_t flags, int align,
++		    int size, uint32_t tile_mode, uint32_t tile_flags,
++		    struct nouveau_bo **bo)
++{
++	struct nouveau_bo_priv *nvbo;
++	int ret;
++
++	if (!dev || !bo || *bo)
++		return -EINVAL;
++
++	nvbo = calloc(1, sizeof(struct nouveau_bo_priv));
++	if (!nvbo)
++		return -ENOMEM;
++	nvbo->base.device = dev;
++	nvbo->base.size = size;
++	nvbo->base.tile_mode = tile_mode;
++	nvbo->base.tile_flags = tile_flags;
++
++	nvbo->refcount = 1;
++	nvbo->flags = flags;
++	nvbo->size = size;
++	nvbo->align = align;
++
++	if (flags & (NOUVEAU_BO_VRAM | NOUVEAU_BO_GART)) {
++		ret = nouveau_bo_kalloc(nvbo, NULL);
++		if (ret) {
++			nouveau_bo_ref(NULL, (void *)&nvbo);
++			return ret;
++		}
++	}
++
++	*bo = &nvbo->base;
++	return 0;
++}
++
++int
++nouveau_bo_new(struct nouveau_device *dev, uint32_t flags, int align,
++	       int size, struct nouveau_bo **bo)
++{
++	return nouveau_bo_new_tile(dev, flags, align, size, 0, 0, bo);
++}
++
++int
++nouveau_bo_user(struct nouveau_device *dev, void *ptr, int size,
++		struct nouveau_bo **bo)
++{
++	struct nouveau_bo_priv *nvbo;
++	int ret;
++
++	ret = nouveau_bo_new(dev, NOUVEAU_BO_MAP, 0, size, bo);
++	if (ret)
++		return ret;
++	nvbo = nouveau_bo(*bo);
++
++	nvbo->sysmem = ptr;
++	nvbo->user = 1;
++	return 0;
++}
++
++int
++nouveau_bo_wrap(struct nouveau_device *dev, uint32_t handle,
++		struct nouveau_bo **bo)
++{
++	struct nouveau_device_priv *nvdev = nouveau_device(dev);
++	struct drm_nouveau_gem_info req;
++	struct nouveau_bo_priv *nvbo;
++	int ret;
++
++	ret = nouveau_bo_new(dev, 0, 0, 0, bo);
++	if (ret)
++		return ret;
++	nvbo = nouveau_bo(*bo);
++
++	req.handle = handle;
++	ret = drmCommandWriteRead(nvdev->fd, DRM_NOUVEAU_GEM_INFO,
++				  &req, sizeof(req));
++	if (ret) {
++		nouveau_bo_ref(NULL, bo);
++		return ret;
++	}
++
++	nouveau_bo_info(nvbo, &req);
++	nvbo->base.size = nvbo->size;
++	return 0;
++}
++
++int
++nouveau_bo_handle_get(struct nouveau_bo *bo, uint32_t *handle)
++{
++	struct nouveau_device_priv *nvdev = nouveau_device(bo->device);
++	struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
++	int ret;
++ 
++	if (!bo || !handle)
++		return -EINVAL;
++
++	if (!nvbo->global_handle) {
++		struct drm_gem_flink req;
++ 
++		ret = nouveau_bo_kalloc(nvbo, NULL);
++		if (ret)
++			return ret;
++
++		req.handle = nvbo->handle;
++		ret = drmIoctl(nvdev->fd, DRM_IOCTL_GEM_FLINK, &req);
++		if (ret) {
++			nouveau_bo_kfree(nvbo);
++			return ret;
++		}
++
++		nvbo->global_handle = req.name;
++	}
++ 
++	*handle = nvbo->global_handle;
++	return 0;
++}
++ 
++int
++nouveau_bo_handle_ref(struct nouveau_device *dev, uint32_t handle,
++		      struct nouveau_bo **bo)
++{
++	struct nouveau_device_priv *nvdev = nouveau_device(dev);
++	struct nouveau_bo_priv *nvbo;
++	struct drm_gem_open req;
++	int ret;
++
++	req.name = handle;
++	ret = drmIoctl(nvdev->fd, DRM_IOCTL_GEM_OPEN, &req);
++	if (ret) {
++		nouveau_bo_ref(NULL, bo);
++		return ret;
++	}
++
++	ret = nouveau_bo_wrap(dev, req.handle, bo);
++	if (ret) {
++		nouveau_bo_ref(NULL, bo);
++		return ret;
++	}
++
++	nvbo = nouveau_bo(*bo);
++	nvbo->base.handle = nvbo->handle;
++	return 0;
++} 
++
++static void
++nouveau_bo_del(struct nouveau_bo **bo)
++{
++	struct nouveau_bo_priv *nvbo;
++
++	if (!bo || !*bo)
++		return;
++	nvbo = nouveau_bo(*bo);
++	*bo = NULL;
++
++	if (--nvbo->refcount)
++		return;
++
++	if (nvbo->pending) {
++		nvbo->pending = NULL;
++		nouveau_pushbuf_flush(nvbo->pending_channel, 0);
++	}
++
++	nouveau_bo_ufree(nvbo);
++	nouveau_bo_kfree(nvbo);
++	free(nvbo);
++}
++
++int
++nouveau_bo_ref(struct nouveau_bo *ref, struct nouveau_bo **pbo)
++{
++	if (!pbo)
++		return -EINVAL;
++
++	if (ref)
++		nouveau_bo(ref)->refcount++;
++
++	if (*pbo)
++		nouveau_bo_del(pbo);
++
++	*pbo = ref;
++	return 0;
++}
++
++static int
++nouveau_bo_wait(struct nouveau_bo *bo, int cpu_write, int no_wait, int no_block)
++{
++	struct nouveau_device_priv *nvdev = nouveau_device(bo->device);
++	struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
++	struct drm_nouveau_gem_cpu_prep req;
++	int ret;
++
++	if (!nvbo->global_handle && !nvbo->write_marker && !cpu_write)
++		return 0;
++
++	if (nvbo->pending &&
++	    (nvbo->pending->write_domains || cpu_write)) {
++		nvbo->pending = NULL;
++		nouveau_pushbuf_flush(nvbo->pending_channel, 0);
++	}
++
++	req.handle = nvbo->handle;
++	req.flags = 0;
++	if (cpu_write)
++		req.flags |= NOUVEAU_GEM_CPU_PREP_WRITE;
++	if (no_wait)
++		req.flags |= NOUVEAU_GEM_CPU_PREP_NOWAIT;
++	if (no_block)
++		req.flags |= NOUVEAU_GEM_CPU_PREP_NOBLOCK;
++
++	do {
++		ret = drmCommandWrite(nvdev->fd, DRM_NOUVEAU_GEM_CPU_PREP,
++				      &req, sizeof(req));
++	} while (ret == -EAGAIN);
++	if (ret)
++		return ret;
++
++	if (ret == 0)
++		nvbo->write_marker = 0;
++	return 0;
++}
++
++int
++nouveau_bo_map_range(struct nouveau_bo *bo, uint32_t delta, uint32_t size,
++		     uint32_t flags)
++{
++	struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
++	int ret;
++
++	if (!nvbo || bo->map)
++		return -EINVAL;
++
++	if (!nouveau_bo_allocated(nvbo)) {
++		if (nvbo->flags & (NOUVEAU_BO_VRAM | NOUVEAU_BO_GART)) {
++			ret = nouveau_bo_kalloc(nvbo, NULL);
++			if (ret)
++				return ret;
++		}
++
++		if (!nouveau_bo_allocated(nvbo)) {
++			ret = nouveau_bo_ualloc(nvbo);
++			if (ret)
++				return ret;
++		}
++	}
++
++	if (nvbo->sysmem) {
++		bo->map = (char *)nvbo->sysmem + delta;
++	} else {
++		ret = nouveau_bo_kmap(nvbo);
++		if (ret)
++			return ret;
++
++		if (!(flags & NOUVEAU_BO_NOSYNC)) {
++			ret = nouveau_bo_wait(bo, (flags & NOUVEAU_BO_WR),
++					      (flags & NOUVEAU_BO_NOWAIT), 0);
++			if (ret)
++				return ret;
++
++			nvbo->map_refcnt++;
++		}
++
++		bo->map = (char *)nvbo->map + delta;
++	}
++
++	return 0;
++}
++
++void
++nouveau_bo_map_flush(struct nouveau_bo *bo, uint32_t delta, uint32_t size)
++{
++}
++
++int
++nouveau_bo_map(struct nouveau_bo *bo, uint32_t flags)
++{
++	return nouveau_bo_map_range(bo, 0, bo->size, flags);
++}
++
++void
++nouveau_bo_unmap(struct nouveau_bo *bo)
++{
++	struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
++
++	if (bo->map && !nvbo->sysmem && nvbo->map_refcnt) {
++		struct nouveau_device_priv *nvdev = nouveau_device(bo->device);
++		struct drm_nouveau_gem_cpu_fini req;
++
++		req.handle = nvbo->handle;
++		drmCommandWrite(nvdev->fd, DRM_NOUVEAU_GEM_CPU_FINI,
++				&req, sizeof(req));
++		nvbo->map_refcnt--;
++	}
++
++	bo->map = NULL;
++}
++
++int
++nouveau_bo_busy(struct nouveau_bo *bo, uint32_t access)
++{
++	return nouveau_bo_wait(bo, (access & NOUVEAU_BO_WR), 1, 1);
++}
++
++uint32_t
++nouveau_bo_pending(struct nouveau_bo *bo)
++{
++	struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
++	uint32_t flags;
++
++	if (!nvbo->pending)
++		return 0;
++
++	flags = 0;
++	if (nvbo->pending->read_domains)
++		flags |= NOUVEAU_BO_RD;
++	if (nvbo->pending->write_domains)
++		flags |= NOUVEAU_BO_WR;
++
++	return flags;
++}
++
++struct drm_nouveau_gem_pushbuf_bo *
++nouveau_bo_emit_buffer(struct nouveau_channel *chan, struct nouveau_bo *bo)
++{
++	struct nouveau_pushbuf_priv *nvpb = &nouveau_channel(chan)->pb;
++	struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
++	struct drm_nouveau_gem_pushbuf_bo *pbbo;
++	struct nouveau_bo *ref = NULL;
++	int ret;
++
++	if (nvbo->pending)
++		return nvbo->pending;
++
++	if (!nvbo->handle) {
++		ret = nouveau_bo_kalloc(nvbo, chan);
++		if (ret)
++			return NULL;
++
++		if (nvbo->sysmem) {
++			void *sysmem_tmp = nvbo->sysmem;
++
++			nvbo->sysmem = NULL;
++			ret = nouveau_bo_map(bo, NOUVEAU_BO_WR);
++			if (ret)
++				return NULL;
++			nvbo->sysmem = sysmem_tmp;
++
++			memcpy(bo->map, nvbo->sysmem, nvbo->base.size);
++			nouveau_bo_ufree(nvbo);
++			nouveau_bo_unmap(bo);
++		}
++	}
++
++	if (nvpb->nr_buffers >= NOUVEAU_GEM_MAX_BUFFERS)
++		return NULL;
++	pbbo = nvpb->buffers + nvpb->nr_buffers++;
++	nvbo->pending = pbbo;
++	nvbo->pending_channel = chan;
++	nvbo->pending_refcnt = 0;
++
++	nouveau_bo_ref(bo, &ref);
++	pbbo->user_priv = (uint64_t)(unsigned long)ref;
++	pbbo->handle = nvbo->handle;
++	pbbo->valid_domains = NOUVEAU_GEM_DOMAIN_VRAM | NOUVEAU_GEM_DOMAIN_GART;
++	pbbo->read_domains = 0;
++	pbbo->write_domains = 0;
++	pbbo->presumed.domain = nvbo->domain;
++	pbbo->presumed.offset = nvbo->offset;
++	pbbo->presumed.valid = 1;
++	return pbbo;
++}
+diff --git a/nouveau-1/nouveau_bo.h b/nouveau-1/nouveau_bo.h
+new file mode 100644
+index 0000000..3a1f2d4
+--- /dev/null
++++ b/nouveau-1/nouveau_bo.h
+@@ -0,0 +1,104 @@
++/*
++ * Copyright 2007 Nouveau Project
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++ * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
++ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#ifndef __NOUVEAU_BO_H__
++#define __NOUVEAU_BO_H__
++
++/* Relocation/Buffer type flags */
++#define NOUVEAU_BO_VRAM   (1 << 0)
++#define NOUVEAU_BO_GART   (1 << 1)
++#define NOUVEAU_BO_RD     (1 << 2)
++#define NOUVEAU_BO_WR     (1 << 3)
++#define NOUVEAU_BO_RDWR   (NOUVEAU_BO_RD | NOUVEAU_BO_WR)
++#define NOUVEAU_BO_MAP    (1 << 4)
++#define NOUVEAU_BO_LOW    (1 << 6)
++#define NOUVEAU_BO_HIGH   (1 << 7)
++#define NOUVEAU_BO_OR     (1 << 8)
++#define NOUVEAU_BO_INVAL  (1 << 12)
++#define NOUVEAU_BO_NOSYNC (1 << 13)
++#define NOUVEAU_BO_NOWAIT (1 << 14)
++#define NOUVEAU_BO_IFLUSH (1 << 15)
++#define NOUVEAU_BO_DUMMY  (1 << 31)
++
++#define NOUVEAU_BO_TILE_LAYOUT_MASK 0x0000ff00
++#define NOUVEAU_BO_TILE_16BPP       0x00000001
++#define NOUVEAU_BO_TILE_32BPP       0x00000002
++#define NOUVEAU_BO_TILE_ZETA        0x00000004
++#define NOUVEAU_BO_TILE_SCANOUT     0x00000008
++
++struct nouveau_bo {
++	struct nouveau_device *device;
++	uint32_t handle;
++
++	uint64_t size;
++	void *map;
++
++	uint32_t tile_mode;
++	uint32_t tile_flags;
++};
++
++int
++nouveau_bo_new(struct nouveau_device *, uint32_t flags, int align, int size,
++	       struct nouveau_bo **);
++
++int
++nouveau_bo_new_tile(struct nouveau_device *, uint32_t flags, int align,
++		    int size, uint32_t tile_mode, uint32_t tile_flags,
++		    struct nouveau_bo **);
++
++int
++nouveau_bo_user(struct nouveau_device *, void *ptr, int size,
++		struct nouveau_bo **);
++
++int
++nouveau_bo_wrap(struct nouveau_device *, uint32_t handle, struct nouveau_bo **);
++
++int
++nouveau_bo_handle_get(struct nouveau_bo *, uint32_t *);
++
++int
++nouveau_bo_handle_ref(struct nouveau_device *, uint32_t handle,
++		      struct nouveau_bo **);
++
++int
++nouveau_bo_ref(struct nouveau_bo *, struct nouveau_bo **);
++
++int
++nouveau_bo_map_range(struct nouveau_bo *, uint32_t delta, uint32_t size,
++		     uint32_t flags);
++
++void
++nouveau_bo_map_flush(struct nouveau_bo *, uint32_t delta, uint32_t size);
++
++int
++nouveau_bo_map(struct nouveau_bo *, uint32_t flags);
++
++void
++nouveau_bo_unmap(struct nouveau_bo *);
++
++int
++nouveau_bo_busy(struct nouveau_bo *, uint32_t access);
++
++uint32_t
++nouveau_bo_pending(struct nouveau_bo *);
++
++#endif
+diff --git a/nouveau-1/nouveau_channel.c b/nouveau-1/nouveau_channel.c
+new file mode 100644
+index 0000000..96fa03b
+--- /dev/null
++++ b/nouveau-1/nouveau_channel.c
+@@ -0,0 +1,142 @@
++/*
++ * Copyright 2007 Nouveau Project
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++ * THE AUTHORS 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.
++ */
++
++#include <stdlib.h>
++#include <string.h>
++#include <errno.h>
++
++#include "nouveau_private.h"
++
++int
++nouveau_channel_alloc(struct nouveau_device *dev, uint32_t fb_ctxdma,
++		      uint32_t tt_ctxdma, int pushbuf_size,
++		      struct nouveau_channel **chan)
++{
++	struct nouveau_device_priv *nvdev = nouveau_device(dev);
++	struct nouveau_channel_priv *nvchan;
++	unsigned i;
++	int ret;
++
++	if (!nvdev || !chan || *chan)
++	    return -EINVAL;
++
++	nvchan = calloc(1, sizeof(struct nouveau_channel_priv));
++	if (!nvchan)
++		return -ENOMEM;
++	nvchan->base.device = dev;
++
++	nvchan->drm.fb_ctxdma_handle = fb_ctxdma;
++	nvchan->drm.tt_ctxdma_handle = tt_ctxdma;
++	ret = drmCommandWriteRead(nvdev->fd, DRM_NOUVEAU_CHANNEL_ALLOC,
++				  &nvchan->drm, sizeof(nvchan->drm));
++	if (ret) {
++		free(nvchan);
++		return ret;
++	}
++
++	nvchan->base.id = nvchan->drm.channel;
++	if (nouveau_grobj_ref(&nvchan->base, nvchan->drm.fb_ctxdma_handle,
++			      &nvchan->base.vram) ||
++	    nouveau_grobj_ref(&nvchan->base, nvchan->drm.tt_ctxdma_handle,
++		    	      &nvchan->base.gart)) {
++		nouveau_channel_free((void *)&nvchan);
++		return -EINVAL;
++	}
++
++	/* Mark all DRM-assigned subchannels as in-use */
++	for (i = 0; i < nvchan->drm.nr_subchan; i++) {
++		struct nouveau_grobj_priv *gr = calloc(1, sizeof(*gr));
++
++		gr->base.bound = NOUVEAU_GROBJ_BOUND_EXPLICIT;
++		gr->base.subc = i;
++		gr->base.handle = nvchan->drm.subchan[i].handle;
++		gr->base.grclass = nvchan->drm.subchan[i].grclass;
++		gr->base.channel = &nvchan->base;
++
++		nvchan->base.subc[i].gr = &gr->base;
++	}
++
++	if (dev->chipset < 0xc0) {
++		ret = nouveau_bo_wrap(dev, nvchan->drm.notifier_handle,
++				      &nvchan->notifier_bo);
++		if (!ret)
++			ret = nouveau_bo_map(nvchan->notifier_bo,
++					     NOUVEAU_BO_RDWR);
++		if (ret) {
++			nouveau_channel_free((void *)&nvchan);
++			return ret;
++		}
++
++		ret = nouveau_grobj_alloc(&nvchan->base, 0x00000000, 0x0030,
++					  &nvchan->base.nullobj);
++		if (ret) {
++			nouveau_channel_free((void *)&nvchan);
++			return ret;
++		}
++	}
++
++	ret = nouveau_pushbuf_init(&nvchan->base, pushbuf_size);
++	if (ret) {
++		nouveau_channel_free((void *)&nvchan);
++		return ret;
++	}
++
++	*chan = &nvchan->base;
++	return 0;
++}
++
++void
++nouveau_channel_free(struct nouveau_channel **chan)
++{
++	struct nouveau_channel_priv *nvchan;
++	struct nouveau_device_priv *nvdev;
++	struct drm_nouveau_channel_free cf;
++	unsigned i;
++
++	if (!chan || !*chan)
++		return;
++	nvchan = nouveau_channel(*chan);
++	(*chan)->flush_notify = NULL;
++	*chan = NULL;
++	nvdev = nouveau_device(nvchan->base.device);
++
++	FIRE_RING(&nvchan->base);
++
++	nouveau_pushbuf_fini(&nvchan->base);
++	if (nvchan->notifier_bo) {
++		nouveau_bo_unmap(nvchan->notifier_bo);
++		nouveau_bo_ref(NULL, &nvchan->notifier_bo);
++	}
++
++	for (i = 0; i < nvchan->drm.nr_subchan; i++)
++		free(nvchan->base.subc[i].gr);
++
++	nouveau_grobj_free(&nvchan->base.vram);
++	nouveau_grobj_free(&nvchan->base.gart);
++	nouveau_grobj_free(&nvchan->base.nullobj);
++
++	cf.channel = nvchan->drm.channel;
++	drmCommandWrite(nvdev->fd, DRM_NOUVEAU_CHANNEL_FREE, &cf, sizeof(cf));
++	free(nvchan);
++}
++
++
+diff --git a/nouveau-1/nouveau_channel.h b/nouveau-1/nouveau_channel.h
+new file mode 100644
+index 0000000..d61a4c0
+--- /dev/null
++++ b/nouveau-1/nouveau_channel.h
+@@ -0,0 +1,57 @@
++/*
++ * Copyright 2007 Nouveau Project
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++ * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
++ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#ifndef __NOUVEAU_CHANNEL_H__
++#define __NOUVEAU_CHANNEL_H__
++
++struct nouveau_subchannel {
++	struct nouveau_grobj *gr;
++	unsigned sequence;
++};
++
++struct nouveau_channel {
++	uint32_t *cur;
++	uint32_t *end;
++
++	struct nouveau_device *device;
++	int id;
++
++	struct nouveau_grobj *nullobj;
++	struct nouveau_grobj *vram;
++	struct nouveau_grobj *gart;
++
++	void *user_private;
++	void (*hang_notify)(struct nouveau_channel *);
++	void (*flush_notify)(struct nouveau_channel *);
++
++	struct nouveau_subchannel subc[8];
++	unsigned subc_sequence;
++};
++
++int
++nouveau_channel_alloc(struct nouveau_device *, uint32_t fb, uint32_t tt,
++		      int pushbuf_size, struct nouveau_channel **);
++
++void
++nouveau_channel_free(struct nouveau_channel **);
++
++#endif
+diff --git a/nouveau-1/nouveau_device.c b/nouveau-1/nouveau_device.c
+new file mode 100644
+index 0000000..425c5d2
+--- /dev/null
++++ b/nouveau-1/nouveau_device.c
+@@ -0,0 +1,198 @@
++/*
++ * Copyright 2007 Nouveau Project
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++ * THE AUTHORS 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.
++ */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <errno.h>
++
++#include "nouveau_private.h"
++
++int
++nouveau_device_open_existing(struct nouveau_device **dev, int close,
++			     int fd, drm_context_t ctx)
++{
++	struct nouveau_device_priv *nvdev;
++	drmVersionPtr ver;
++	uint64_t value;
++	int ret;
++
++	if (!dev || *dev)
++	    return -EINVAL;
++
++	nvdev = calloc(1, sizeof(*nvdev));
++	if (!nvdev)
++	    return -ENOMEM;
++	nvdev->fd = fd;
++	nvdev->ctx = ctx;
++	nvdev->needs_close = close;
++
++	ver = drmGetVersion(fd);
++	if (!ver) {
++		nouveau_device_close((void *)&nvdev);
++		return -EINVAL;
++	}
++
++	if ((ver->version_major == 0 && ver->version_patchlevel != 16) ||
++	     ver->version_major > 1) {
++		nouveau_device_close((void *)&nvdev);
++		return -EINVAL;
++	}
++
++	drmFreeVersion(ver);
++
++	ret = nouveau_device_get_param(&nvdev->base,
++				       NOUVEAU_GETPARAM_VM_VRAM_BASE, &value);
++	if (ret) {
++		nouveau_device_close((void *)&nvdev);
++		return ret;
++	}
++	nvdev->base.vm_vram_base = value;
++
++	ret = nouveau_device_get_param(&nvdev->base,
++				       NOUVEAU_GETPARAM_FB_SIZE, &value);
++	if (ret) {
++		nouveau_device_close((void *)&nvdev);
++		return ret;
++	}
++	nvdev->base.vm_vram_size = value;
++
++	ret = nouveau_device_get_param(&nvdev->base,
++				       NOUVEAU_GETPARAM_AGP_SIZE, &value);
++	if (ret) {
++		nouveau_device_close((void *)&nvdev);
++		return ret;
++	}
++	nvdev->base.vm_gart_size = value;
++
++	ret = nouveau_bo_init(&nvdev->base);
++	if (ret) {
++		nouveau_device_close((void *)&nvdev);
++		return ret;
++	}
++
++	ret = nouveau_device_get_param(&nvdev->base,
++				       NOUVEAU_GETPARAM_CHIPSET_ID, &value);
++	if (ret) {
++		nouveau_device_close((void *)&nvdev);
++		return ret;
++	}
++	nvdev->base.chipset = value;
++
++	ret = nouveau_device_get_param(&nvdev->base,
++				       NOUVEAU_GETPARAM_HAS_BO_USAGE, &value);
++	if (!ret)
++		nvdev->has_bo_usage = value;
++
++	*dev = &nvdev->base;
++	return 0;
++}
++
++int
++nouveau_device_open(struct nouveau_device **dev, const char *busid)
++{
++	drm_context_t ctx;
++	int fd, ret;
++
++	if (!dev || *dev)
++		return -EINVAL;
++
++	fd = drmOpen("nouveau", busid);
++	if (fd < 0)
++		return -EINVAL;
++
++	ret = drmCreateContext(fd, &ctx);
++	if (ret) {
++		drmClose(fd);
++		return ret;
++	}
++
++	ret = nouveau_device_open_existing(dev, 1, fd, ctx);
++	if (ret) {
++	    drmDestroyContext(fd, ctx);
++	    drmClose(fd);
++	    return ret;
++	}
++
++	return 0;
++}
++
++void
++nouveau_device_close(struct nouveau_device **dev)
++{
++	struct nouveau_device_priv *nvdev;
++
++	if (!dev || !*dev)
++		return;
++	nvdev = nouveau_device(*dev);
++	*dev = NULL;
++
++	nouveau_bo_takedown(&nvdev->base);
++
++	if (nvdev->needs_close) {
++		drmDestroyContext(nvdev->fd, nvdev->ctx);
++		drmClose(nvdev->fd);
++	}
++	free(nvdev);
++}
++
++int
++nouveau_device_get_param(struct nouveau_device *dev,
++			 uint64_t param, uint64_t *value)
++{
++	struct nouveau_device_priv *nvdev = nouveau_device(dev);
++	struct drm_nouveau_getparam g;
++	int ret;
++
++	if (!nvdev || !value)
++		return -EINVAL;
++
++	g.param = param;
++	ret = drmCommandWriteRead(nvdev->fd, DRM_NOUVEAU_GETPARAM,
++				  &g, sizeof(g));
++	if (ret)
++		return ret;
++
++	*value = g.value;
++	return 0;
++}
++
++int
++nouveau_device_set_param(struct nouveau_device *dev,
++			 uint64_t param, uint64_t value)
++{
++	struct nouveau_device_priv *nvdev = nouveau_device(dev);
++	struct drm_nouveau_setparam s;
++	int ret;
++
++	if (!nvdev)
++		return -EINVAL;
++
++	s.param = param;
++	s.value = value;
++	ret = drmCommandWriteRead(nvdev->fd, DRM_NOUVEAU_SETPARAM,
++				  &s, sizeof(s));
++	if (ret)
++		return ret;
++
++	return 0;
++}
++
+diff --git a/nouveau-1/nouveau_device.h b/nouveau-1/nouveau_device.h
+new file mode 100644
+index 0000000..c0d9333
+--- /dev/null
++++ b/nouveau-1/nouveau_device.h
+@@ -0,0 +1,33 @@
++/*
++ * Copyright 2007 Nouveau Project
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++ * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
++ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#ifndef __NOUVEAU_DEVICE_H__
++#define __NOUVEAU_DEVICE_H__
++
++struct nouveau_device {
++	unsigned chipset;
++	uint64_t vm_vram_base;
++	uint64_t vm_vram_size;
++	uint64_t vm_gart_size;
++};
++
++#endif
+diff --git a/nouveau-1/nouveau_drmif.h b/nouveau-1/nouveau_drmif.h
+new file mode 100644
+index 0000000..ec226a2
+--- /dev/null
++++ b/nouveau-1/nouveau_drmif.h
+@@ -0,0 +1,58 @@
++/*
++ * Copyright 2008 Nouveau Project
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++ * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
++ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#ifndef __NOUVEAU_DRMIF_H__
++#define __NOUVEAU_DRMIF_H__
++
++#include <stdint.h>
++#include <xf86drm.h>
++
++#include "nouveau_device.h"
++
++struct nouveau_device_priv {
++	struct nouveau_device base;
++
++	int fd;
++	drm_context_t ctx;
++	drmLock *lock;
++	int needs_close;
++	int has_bo_usage;
++};
++#define nouveau_device(n) ((struct nouveau_device_priv *)(n))
++
++int
++nouveau_device_open_existing(struct nouveau_device **, int close,
++			     int fd, drm_context_t ctx);
++
++int
++nouveau_device_open(struct nouveau_device **, const char *busid);
++
++void
++nouveau_device_close(struct nouveau_device **);
++
++int
++nouveau_device_get_param(struct nouveau_device *, uint64_t param, uint64_t *v);
++
++int
++nouveau_device_set_param(struct nouveau_device *, uint64_t param, uint64_t val);
++
++#endif
+diff --git a/nouveau-1/nouveau_grobj.c b/nouveau-1/nouveau_grobj.c
+new file mode 100644
+index 0000000..36344b9
+--- /dev/null
++++ b/nouveau-1/nouveau_grobj.c
+@@ -0,0 +1,148 @@
++/*
++ * Copyright 2007 Nouveau Project
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++ * THE AUTHORS 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.
++ */
++
++#include <stdlib.h>
++#include <errno.h>
++
++#include "nouveau_private.h"
++
++int
++nouveau_grobj_alloc(struct nouveau_channel *chan, uint32_t handle,
++		    int class, struct nouveau_grobj **grobj)
++{
++	struct nouveau_device_priv *nvdev = nouveau_device(chan->device);
++	struct nouveau_grobj_priv *nvgrobj;
++	struct drm_nouveau_grobj_alloc g;
++	int ret;
++
++	if (!nvdev || !grobj || *grobj)
++		return -EINVAL;
++
++	nvgrobj = calloc(1, sizeof(*nvgrobj));
++	if (!nvgrobj)
++		return -ENOMEM;
++	nvgrobj->base.channel = chan;
++	nvgrobj->base.handle  = handle;
++	nvgrobj->base.grclass = class;
++	nvgrobj->base.bound   = NOUVEAU_GROBJ_UNBOUND;
++	nvgrobj->base.subc    = -1;
++
++	g.channel = chan->id;
++	g.handle  = handle;
++	g.class   = class;
++	ret = drmCommandWrite(nvdev->fd, DRM_NOUVEAU_GROBJ_ALLOC,
++			      &g, sizeof(g));
++	if (ret) {
++		nouveau_grobj_free((void *)&nvgrobj);
++		return ret;
++	}
++
++	*grobj = &nvgrobj->base;
++	return 0;
++}
++
++int
++nouveau_grobj_ref(struct nouveau_channel *chan, uint32_t handle,
++		  struct nouveau_grobj **grobj)
++{
++	struct nouveau_grobj_priv *nvgrobj;
++
++	if (!chan || !grobj || *grobj)
++		return -EINVAL;
++
++	nvgrobj = calloc(1, sizeof(struct nouveau_grobj_priv));
++	if (!nvgrobj)
++		return -ENOMEM;
++	nvgrobj->base.channel = chan;
++	nvgrobj->base.handle = handle;
++	nvgrobj->base.grclass = 0;
++
++	*grobj = &nvgrobj->base;
++	return 0;
++}
++
++void
++nouveau_grobj_free(struct nouveau_grobj **grobj)
++{
++	struct nouveau_device_priv *nvdev;
++	struct nouveau_channel_priv *chan;
++	struct nouveau_grobj_priv *nvgrobj;
++
++	if (!grobj || !*grobj)
++		return;
++	nvgrobj = nouveau_grobj(*grobj);
++	*grobj = NULL;
++
++
++	chan = nouveau_channel(nvgrobj->base.channel);
++	nvdev = nouveau_device(chan->base.device);
++
++	if (nvgrobj->base.grclass) {
++		struct drm_nouveau_gpuobj_free f;
++
++		FIRE_RING(&chan->base);
++		f.channel = chan->drm.channel;
++		f.handle  = nvgrobj->base.handle;
++		drmCommandWrite(nvdev->fd, DRM_NOUVEAU_GPUOBJ_FREE,
++				&f, sizeof(f));	
++	}
++	if (nvgrobj->base.bound != NOUVEAU_GROBJ_UNBOUND)
++		chan->base.subc[nvgrobj->base.subc].gr = NULL;
++	free(nvgrobj);
++}
++
++void
++nouveau_grobj_autobind(struct nouveau_grobj *grobj)
++{
++	struct nouveau_channel *chan = grobj->channel;
++	struct nouveau_subchannel *subc = NULL;
++	int i;
++
++	for (i = 0; i < 8; i++) {
++		struct nouveau_subchannel *scc = &grobj->channel->subc[i];
++
++		if (scc->gr && scc->gr->bound == NOUVEAU_GROBJ_BOUND_EXPLICIT)
++			continue;
++
++		if (!subc || scc->sequence < subc->sequence)
++			subc = scc;
++	}
++
++	if (subc->gr) {
++		subc->gr->bound = NOUVEAU_GROBJ_UNBOUND;
++		subc->gr->subc  = -1;
++	}
++
++	subc->gr = grobj;
++	subc->gr->bound = NOUVEAU_GROBJ_BOUND;
++	subc->gr->subc  = subc - &grobj->channel->subc[0];
++
++	WAIT_RING(chan, 2);
++	if (chan->device->chipset < 0xc0) {
++		OUT_RING (chan, (1 << 18) | (grobj->subc << 13));
++		OUT_RING (chan, grobj->handle);
++	} else {
++		OUT_RING (chan, (2 << 28) | (1 << 16) | (grobj->subc << 13));
++		OUT_RING (chan, grobj->grclass);
++	}
++}
++
+diff --git a/nouveau-1/nouveau_grobj.h b/nouveau-1/nouveau_grobj.h
+new file mode 100644
+index 0000000..51ac7d9
+--- /dev/null
++++ b/nouveau-1/nouveau_grobj.h
+@@ -0,0 +1,48 @@
++/*
++ * Copyright 2007 Nouveau Project
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++ * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
++ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#ifndef __NOUVEAU_GROBJ_H__
++#define __NOUVEAU_GROBJ_H__
++
++#include "nouveau_channel.h"
++
++struct nouveau_grobj {
++	struct nouveau_channel *channel;
++	int grclass;
++	uint32_t handle;
++
++	enum {
++		NOUVEAU_GROBJ_UNBOUND = 0,
++		NOUVEAU_GROBJ_BOUND = 1,
++		NOUVEAU_GROBJ_BOUND_EXPLICIT = 2
++	} bound;
++	int subc;
++};
++
++int nouveau_grobj_alloc(struct nouveau_channel *, uint32_t handle,
++			       int class, struct nouveau_grobj **);
++int nouveau_grobj_ref(struct nouveau_channel *, uint32_t handle,
++			     struct nouveau_grobj **);
++void nouveau_grobj_free(struct nouveau_grobj **);
++void nouveau_grobj_autobind(struct nouveau_grobj *);
++
++#endif
+diff --git a/nouveau-1/nouveau_notifier.c b/nouveau-1/nouveau_notifier.c
+new file mode 100644
+index 0000000..513fa63
+--- /dev/null
++++ b/nouveau-1/nouveau_notifier.c
+@@ -0,0 +1,148 @@
++/*
++ * Copyright 2007 Nouveau Project
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++ * THE AUTHORS 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.
++ */
++
++#include <stdlib.h>
++#include <errno.h>
++#include <sys/time.h>
++
++#include "nouveau_private.h"
++
++#define NOTIFIER(__v)                                                          \
++	struct nouveau_notifier_priv *nvnotify = nouveau_notifier(notifier);   \
++	volatile uint32_t *__v = (uint32_t *)((char *)nvnotify->map + (id * 32))
++
++int
++nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle,
++		       int count, struct nouveau_notifier **notifier)
++{
++	struct nouveau_notifier_priv *nvnotify;
++	int ret;
++
++	if (!chan || !notifier || *notifier)
++		return -EINVAL;
++
++	nvnotify = calloc(1, sizeof(struct nouveau_notifier_priv));
++	if (!nvnotify)
++		return -ENOMEM;
++	nvnotify->base.channel = chan;
++	nvnotify->base.handle  = handle;
++
++	nvnotify->drm.channel = chan->id;
++	nvnotify->drm.handle  = handle;
++	nvnotify->drm.size    = (count * 32);
++	if ((ret = drmCommandWriteRead(nouveau_device(chan->device)->fd,
++				       DRM_NOUVEAU_NOTIFIEROBJ_ALLOC,
++				       &nvnotify->drm,
++				       sizeof(nvnotify->drm)))) {
++		nouveau_notifier_free((void *)&nvnotify);
++		return ret;
++	}
++
++	nvnotify->map = (char *)nouveau_channel(chan)->notifier_bo->map +
++				nvnotify->drm.offset;
++	*notifier = &nvnotify->base;
++	return 0;
++}
++
++void
++nouveau_notifier_free(struct nouveau_notifier **notifier)
++{
++
++	struct nouveau_notifier_priv *nvnotify;
++	struct nouveau_channel_priv *nvchan;
++	struct nouveau_device_priv *nvdev;
++	struct drm_nouveau_gpuobj_free f;
++
++	if (!notifier || !*notifier)
++		return;
++	nvnotify = nouveau_notifier(*notifier);
++	*notifier = NULL;
++
++	nvchan = nouveau_channel(nvnotify->base.channel);
++	nvdev   = nouveau_device(nvchan->base.device);
++
++	FIRE_RING(&nvchan->base);
++
++	f.channel = nvchan->drm.channel;
++	f.handle  = nvnotify->base.handle;
++	drmCommandWrite(nvdev->fd, DRM_NOUVEAU_GPUOBJ_FREE, &f, sizeof(f));		
++	free(nvnotify);
++}
++
++void
++nouveau_notifier_reset(struct nouveau_notifier *notifier, int id)
++{
++	NOTIFIER(n);
++
++	n[NV_NOTIFY_TIME_0      /4] = 0x00000000;
++	n[NV_NOTIFY_TIME_1      /4] = 0x00000000;
++	n[NV_NOTIFY_RETURN_VALUE/4] = 0x00000000;
++	n[NV_NOTIFY_STATE       /4] = (NV_NOTIFY_STATE_STATUS_IN_PROCESS <<
++				       NV_NOTIFY_STATE_STATUS_SHIFT);
++}
++
++uint32_t
++nouveau_notifier_status(struct nouveau_notifier *notifier, int id)
++{
++	NOTIFIER(n);
++
++	return n[NV_NOTIFY_STATE/4] >> NV_NOTIFY_STATE_STATUS_SHIFT;
++}
++
++uint32_t
++nouveau_notifier_return_val(struct nouveau_notifier *notifier, int id)
++{
++	NOTIFIER(n);
++
++	return n[NV_NOTIFY_RETURN_VALUE/4];
++}
++
++static inline double
++gettime(void)
++{
++	struct timeval tv;
++
++	gettimeofday(&tv, NULL);
++	return (double)tv.tv_sec + tv.tv_usec / 1000000.0;
++}
++
++int
++nouveau_notifier_wait_status(struct nouveau_notifier *notifier, int id,
++			     uint32_t status, double timeout)
++{
++	NOTIFIER(n);
++	double time = 0, t_start = gettime();
++
++	while (time <= timeout) {
++		uint32_t v;
++
++		v = n[NV_NOTIFY_STATE/4] >> NV_NOTIFY_STATE_STATUS_SHIFT;
++		if (v == status)
++			return 0;
++
++		if (timeout)
++			time = gettime() - t_start;
++	}
++
++	return -EBUSY;
++}
++
+diff --git a/nouveau-1/nouveau_notifier.h b/nouveau-1/nouveau_notifier.h
+new file mode 100644
+index 0000000..dbc6a3b
+--- /dev/null
++++ b/nouveau-1/nouveau_notifier.h
+@@ -0,0 +1,63 @@
++/*
++ * Copyright 2007 Nouveau Project
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++ * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
++ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#ifndef __NOUVEAU_NOTIFIER_H__
++#define __NOUVEAU_NOTIFIER_H__
++
++#define NV_NOTIFIER_SIZE                                                      32
++#define NV_NOTIFY_TIME_0                                              0x00000000
++#define NV_NOTIFY_TIME_1                                              0x00000004
++#define NV_NOTIFY_RETURN_VALUE                                        0x00000008
++#define NV_NOTIFY_STATE                                               0x0000000C
++#define NV_NOTIFY_STATE_STATUS_MASK                                   0xFF000000
++#define NV_NOTIFY_STATE_STATUS_SHIFT                                          24
++#define NV_NOTIFY_STATE_STATUS_COMPLETED                                    0x00
++#define NV_NOTIFY_STATE_STATUS_IN_PROCESS                                   0x01
++#define NV_NOTIFY_STATE_ERROR_CODE_MASK                               0x0000FFFF
++#define NV_NOTIFY_STATE_ERROR_CODE_SHIFT                                       0
++
++struct nouveau_notifier {
++	struct nouveau_channel *channel;
++	uint32_t handle;
++};
++
++int
++nouveau_notifier_alloc(struct nouveau_channel *, uint32_t handle, int count,
++		       struct nouveau_notifier **);
++
++void
++nouveau_notifier_free(struct nouveau_notifier **);
++
++void
++nouveau_notifier_reset(struct nouveau_notifier *, int id);
++
++uint32_t
++nouveau_notifier_status(struct nouveau_notifier *, int id);
++
++uint32_t
++nouveau_notifier_return_val(struct nouveau_notifier *, int id);
++
++int
++nouveau_notifier_wait_status(struct nouveau_notifier *, int id, uint32_t status,
++			     double timeout);
++
++#endif
+diff --git a/nouveau-1/nouveau_private.h b/nouveau-1/nouveau_private.h
+new file mode 100644
+index 0000000..124fe87
+--- /dev/null
++++ b/nouveau-1/nouveau_private.h
+@@ -0,0 +1,136 @@
++/*
++ * Copyright 2007 Nouveau Project
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++ * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
++ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#ifndef __NOUVEAU_PRIVATE_H__
++#define __NOUVEAU_PRIVATE_H__
++
++#include <stdint.h>
++#include <xf86drm.h>
++#include <nouveau_drm.h>
++
++#include "nouveau_drmif.h"
++#include "nouveau_device.h"
++#include "nouveau_channel.h"
++#include "nouveau_grobj.h"
++#include "nouveau_notifier.h"
++#include "nouveau_bo.h"
++#include "nouveau_resource.h"
++#include "nouveau_pushbuf.h"
++#include "nouveau_reloc.h"
++
++#define CALPB_BUFFERS 3
++
++struct nouveau_pushbuf_priv {
++	uint32_t cal_suffix0;
++	uint32_t cal_suffix1;
++	struct nouveau_bo *buffer[CALPB_BUFFERS];
++	int current;
++	int current_offset;
++
++	unsigned *pushbuf;
++	unsigned size;
++
++	uint32_t *marker;
++	unsigned marker_offset;
++	unsigned marker_relocs;
++	unsigned marker_push;
++
++	struct drm_nouveau_gem_pushbuf_bo *buffers;
++	unsigned nr_buffers;
++	struct drm_nouveau_gem_pushbuf_reloc *relocs;
++	unsigned nr_relocs;
++	struct drm_nouveau_gem_pushbuf_push push[NOUVEAU_GEM_MAX_PUSH];
++	unsigned nr_push;
++};
++#define nouveau_pushbuf(n) ((struct nouveau_pushbuf_priv *)(n))
++
++int
++nouveau_pushbuf_init(struct nouveau_channel *, int buf_size);
++void
++nouveau_pushbuf_fini(struct nouveau_channel *);
++
++struct nouveau_channel_priv {
++	struct nouveau_channel base;
++
++	struct drm_nouveau_channel_alloc drm;
++
++	struct nouveau_bo *notifier_bo;
++
++	struct nouveau_pushbuf_priv pb;
++};
++#define nouveau_channel(n) ((struct nouveau_channel_priv *)(n))
++
++struct nouveau_grobj_priv {
++	struct nouveau_grobj base;
++};
++#define nouveau_grobj(n) ((struct nouveau_grobj_priv *)(n))
++
++struct nouveau_notifier_priv {
++	struct nouveau_notifier base;
++
++	struct drm_nouveau_notifierobj_alloc drm;
++	volatile void *map;
++};
++#define nouveau_notifier(n) ((struct nouveau_notifier_priv *)(n))
++
++struct nouveau_bo_priv {
++	struct nouveau_bo base;
++	int refcount;
++
++	/* Buffer configuration + usage hints */
++	unsigned flags;
++	unsigned size;
++	unsigned align;
++	int user;
++
++	/* Tracking */
++	struct drm_nouveau_gem_pushbuf_bo *pending;
++	struct nouveau_channel *pending_channel;
++	int pending_refcnt;
++	int write_marker;
++
++	/* Userspace object */
++	void *sysmem;
++
++	/* Kernel object */
++	uint32_t global_handle;
++	drm_handle_t handle;
++	uint64_t map_handle;
++	int map_refcnt;
++	void *map;
++
++	/* Last known information from kernel on buffer status */
++	uint64_t offset;
++	uint32_t domain;
++};
++#define nouveau_bo(n) ((struct nouveau_bo_priv *)(n))
++
++int
++nouveau_bo_init(struct nouveau_device *);
++
++void
++nouveau_bo_takedown(struct nouveau_device *);
++
++struct drm_nouveau_gem_pushbuf_bo *
++nouveau_bo_emit_buffer(struct nouveau_channel *, struct nouveau_bo *);
++
++#endif
+diff --git a/nouveau-1/nouveau_pushbuf.c b/nouveau-1/nouveau_pushbuf.c
+new file mode 100644
+index 0000000..59f60d9
+--- /dev/null
++++ b/nouveau-1/nouveau_pushbuf.c
+@@ -0,0 +1,344 @@
++/*
++ * Copyright 2007 Nouveau Project
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++ * THE AUTHORS 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.
++ */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <errno.h>
++#include <assert.h>
++
++#include "nouveau_private.h"
++
++#define PB_BUFMGR_DWORDS   (4096 / 2)
++#define PB_MIN_USER_DWORDS  2048
++
++static int
++nouveau_pushbuf_space(struct nouveau_channel *chan, unsigned min)
++{
++	struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
++	struct nouveau_pushbuf_priv *nvpb = &nvchan->pb;
++	struct nouveau_bo *bo;
++	int ret;
++
++	if (min < PB_MIN_USER_DWORDS)
++		min = PB_MIN_USER_DWORDS;
++
++	nvpb->current_offset = chan->cur - nvpb->pushbuf;
++	if (chan->cur + min + 2 <= chan->end)
++		return 0;
++
++	nvpb->current++;
++	if (nvpb->current == CALPB_BUFFERS)
++		nvpb->current = 0;
++	bo = nvpb->buffer[nvpb->current];
++
++	ret = nouveau_bo_map(bo, NOUVEAU_BO_WR);
++	if (ret)
++		return ret;
++
++	nvpb->size = (bo->size - 8) / 4;
++	nvpb->pushbuf = bo->map;
++	nvpb->current_offset = 0;
++
++	chan->cur = nvpb->pushbuf;
++	chan->end = nvpb->pushbuf + nvpb->size;
++
++	nouveau_bo_unmap(bo);
++	return 0;
++}
++
++static void
++nouveau_pushbuf_fini_call(struct nouveau_channel *chan)
++{
++	struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
++	struct nouveau_pushbuf_priv *nvpb = &nvchan->pb;
++	int i;
++
++	for (i = 0; i < CALPB_BUFFERS; i++)
++		nouveau_bo_ref(NULL, &nvpb->buffer[i]);
++	nvpb->pushbuf = NULL;
++}
++
++static int
++nouveau_pushbuf_init_call(struct nouveau_channel *chan, int buf_size)
++{
++	struct drm_nouveau_gem_pushbuf req;
++	struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
++	struct nouveau_pushbuf_priv *nvpb = &nvchan->pb;
++	struct nouveau_device *dev = chan->device;
++	uint32_t flags = 0;
++	int i, ret;
++
++	if (nvchan->drm.pushbuf_domains & NOUVEAU_GEM_DOMAIN_GART)
++		flags |= NOUVEAU_BO_GART;
++	else
++		flags |= NOUVEAU_BO_VRAM;
++
++	req.channel = chan->id;
++	req.nr_push = 0;
++	ret = drmCommandWriteRead(nouveau_device(dev)->fd,
++				  DRM_NOUVEAU_GEM_PUSHBUF, &req, sizeof(req));
++	if (ret)
++		return ret;
++
++	for (i = 0; i < CALPB_BUFFERS; i++) {
++		ret = nouveau_bo_new(dev, flags | NOUVEAU_BO_MAP,
++				     0, buf_size, &nvpb->buffer[i]);
++		if (ret) {
++			nouveau_pushbuf_fini_call(chan);
++			return ret;
++		}
++	}
++
++	nvpb->cal_suffix0 = req.suffix0;
++	nvpb->cal_suffix1 = req.suffix1;
++	return 0;
++}
++
++int
++nouveau_pushbuf_init(struct nouveau_channel *chan, int buf_size)
++{
++	struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
++	struct nouveau_pushbuf_priv *nvpb = &nvchan->pb;
++	int ret;
++
++	ret = nouveau_pushbuf_init_call(chan, buf_size);
++	if (ret)
++		return ret;
++
++	ret = nouveau_pushbuf_space(chan, 0);
++	if (ret)
++		return ret;
++
++	nvpb->buffers = calloc(NOUVEAU_GEM_MAX_BUFFERS,
++			       sizeof(struct drm_nouveau_gem_pushbuf_bo));
++	nvpb->relocs = calloc(NOUVEAU_GEM_MAX_RELOCS,
++			      sizeof(struct drm_nouveau_gem_pushbuf_reloc));
++	return 0;
++}
++
++void
++nouveau_pushbuf_fini(struct nouveau_channel *chan)
++{
++	struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
++	struct nouveau_pushbuf_priv *nvpb = &nvchan->pb;
++	nouveau_pushbuf_fini_call(chan);
++	free(nvpb->buffers);
++	free(nvpb->relocs);
++}
++
++static int
++nouveau_pushbuf_bo_add(struct nouveau_channel *chan, struct nouveau_bo *bo,
++		       unsigned offset, unsigned length)
++{
++	struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
++	struct nouveau_pushbuf_priv *nvpb = &nvchan->pb;
++	struct drm_nouveau_gem_pushbuf_push *p = &nvpb->push[nvpb->nr_push++];
++	struct drm_nouveau_gem_pushbuf_bo *pbbo;
++	struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
++
++	pbbo = nouveau_bo_emit_buffer(chan, bo);
++	if (!pbbo)
++		return -ENOMEM;
++	pbbo->valid_domains &= nvchan->drm.pushbuf_domains;
++	pbbo->read_domains |= nvchan->drm.pushbuf_domains;
++	nvbo->pending_refcnt++;
++
++	p->bo_index = pbbo - nvpb->buffers;
++	p->offset = offset;
++	p->length = length;
++	return 0;
++}
++
++int
++nouveau_pushbuf_submit(struct nouveau_channel *chan, struct nouveau_bo *bo,
++		       unsigned offset, unsigned length)
++{
++	struct nouveau_pushbuf_priv *nvpb = &nouveau_channel(chan)->pb;
++	int ret, len;
++
++	if ((AVAIL_RING(chan) + nvpb->current_offset) != nvpb->size) {
++		if (nvpb->cal_suffix0 || nvpb->cal_suffix1) {
++			*(chan->cur++) = nvpb->cal_suffix0;
++			*(chan->cur++) = nvpb->cal_suffix1;
++		}
++
++		len = (chan->cur - nvpb->pushbuf) - nvpb->current_offset;
++
++		ret = nouveau_pushbuf_bo_add(chan, nvpb->buffer[nvpb->current],
++					     nvpb->current_offset * 4, len * 4);
++		if (ret)
++			return ret;
++
++		nvpb->current_offset += len;
++	}
++
++	return bo ? nouveau_pushbuf_bo_add(chan, bo, offset, length) : 0;
++}
++
++static void
++nouveau_pushbuf_bo_unref(struct nouveau_pushbuf_priv *nvpb, int index)
++{
++	struct drm_nouveau_gem_pushbuf_bo *pbbo = &nvpb->buffers[index];
++	struct nouveau_bo *bo = (void *)(unsigned long)pbbo->user_priv;
++	struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
++
++	if (--nvbo->pending_refcnt)
++		return;
++
++	if (pbbo->presumed.valid == 0) {
++		nvbo->domain = pbbo->presumed.domain;
++		nvbo->offset = pbbo->presumed.offset;
++	}
++
++	nvbo->pending = NULL;
++	nouveau_bo_ref(NULL, &bo);
++
++	/* we only ever remove from the tail of the pending lists,
++	 * so this is safe.
++	 */
++	nvpb->nr_buffers--;
++}
++
++int
++nouveau_pushbuf_flush(struct nouveau_channel *chan, unsigned min)
++{
++	struct nouveau_device_priv *nvdev = nouveau_device(chan->device);
++	struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
++	struct nouveau_pushbuf_priv *nvpb = &nvchan->pb;
++	struct drm_nouveau_gem_pushbuf req;
++	unsigned i;
++	int ret;
++
++	ret = nouveau_pushbuf_submit(chan, NULL, 0, 0);
++	if (ret)
++		return ret;
++
++	if (!nvpb->nr_push)
++		return 0;
++
++	req.channel = chan->id;
++	req.nr_push = nvpb->nr_push;
++	req.push = (uint64_t)(unsigned long)nvpb->push;
++	req.nr_buffers = nvpb->nr_buffers;
++	req.buffers = (uint64_t)(unsigned long)nvpb->buffers;
++	req.nr_relocs = nvpb->nr_relocs;
++	req.relocs = (uint64_t)(unsigned long)nvpb->relocs;
++	req.suffix0 = nvpb->cal_suffix0;
++	req.suffix1 = nvpb->cal_suffix1;
++
++	do {
++		ret = drmCommandWriteRead(nvdev->fd, DRM_NOUVEAU_GEM_PUSHBUF,
++					  &req, sizeof(req));
++	} while (ret == -EAGAIN);
++	nvpb->cal_suffix0 = req.suffix0;
++	nvpb->cal_suffix1 = req.suffix1;
++	nvdev->base.vm_vram_size = req.vram_available;
++	nvdev->base.vm_gart_size = req.gart_available;
++
++	/* Update presumed offset/domain for any buffers that moved.
++	 * Dereference all buffers on validate list
++	 */
++	for (i = 0; i < nvpb->nr_relocs; i++) {
++		nouveau_pushbuf_bo_unref(nvpb, nvpb->relocs[i].bo_index);
++		nouveau_pushbuf_bo_unref(nvpb, nvpb->relocs[i].reloc_bo_index);
++	}
++
++	for (i = 0; i < nvpb->nr_push; i++)
++		nouveau_pushbuf_bo_unref(nvpb, nvpb->push[i].bo_index);
++
++	nvpb->nr_buffers = 0;
++	nvpb->nr_relocs = 0;
++	nvpb->nr_push = 0;
++
++	/* Allocate space for next push buffer */
++	if (nouveau_pushbuf_space(chan, min))
++		assert(0);
++
++	if (chan->flush_notify)
++		chan->flush_notify(chan);
++
++	nvpb->marker = NULL;
++	return ret;
++}
++
++int
++nouveau_pushbuf_marker_emit(struct nouveau_channel *chan,
++			    unsigned wait_dwords, unsigned wait_relocs)
++{
++	struct nouveau_pushbuf_priv *nvpb = &nouveau_channel(chan)->pb;
++
++	if (AVAIL_RING(chan) < wait_dwords)
++		return nouveau_pushbuf_flush(chan, wait_dwords);
++
++	if (nvpb->nr_relocs + wait_relocs >= NOUVEAU_GEM_MAX_RELOCS)
++		return nouveau_pushbuf_flush(chan, wait_dwords);
++
++	nvpb->marker = chan->cur;
++	nvpb->marker_offset = nvpb->current_offset;
++	nvpb->marker_push = nvpb->nr_push;
++	nvpb->marker_relocs = nvpb->nr_relocs;
++	return 0;
++}
++
++void
++nouveau_pushbuf_marker_undo(struct nouveau_channel *chan)
++{
++	struct nouveau_pushbuf_priv *nvpb = &nouveau_channel(chan)->pb;
++	unsigned i;
++
++	if (!nvpb->marker)
++		return;
++
++	/* undo any relocs/buffers added to the list since last marker */
++	for (i = nvpb->marker_relocs; i < nvpb->nr_relocs; i++) {
++		nouveau_pushbuf_bo_unref(nvpb, nvpb->relocs[i].bo_index);
++		nouveau_pushbuf_bo_unref(nvpb, nvpb->relocs[i].reloc_bo_index);
++	}
++	nvpb->nr_relocs = nvpb->marker_relocs;
++
++	for (i = nvpb->marker_push; i < nvpb->nr_push; i++)
++		nouveau_pushbuf_bo_unref(nvpb, nvpb->push[i].bo_index);
++	nvpb->nr_push = nvpb->marker_push;
++
++	/* reset pushbuf back to last marker */
++	chan->cur = nvpb->marker;
++	nvpb->current_offset = nvpb->marker_offset;
++	nvpb->marker = NULL;
++}
++
++int
++nouveau_pushbuf_emit_reloc(struct nouveau_channel *chan, void *ptr,
++			   struct nouveau_bo *bo, uint32_t data, uint32_t data2,
++			   uint32_t flags, uint32_t vor, uint32_t tor)
++{
++	struct nouveau_pushbuf_priv *nvpb = &nouveau_channel(chan)->pb;
++	int ret;
++
++	ret = nouveau_reloc_emit(chan, nvpb->buffer[nvpb->current],
++				 (char *)ptr - (char *)nvpb->pushbuf, ptr,
++				 bo, data, data2, flags, vor, tor);
++	if (ret)
++		return ret;
++
++	return 0;
++}
++
+diff --git a/nouveau-1/nouveau_pushbuf.h b/nouveau-1/nouveau_pushbuf.h
+new file mode 100644
+index 0000000..2a98789
+--- /dev/null
++++ b/nouveau-1/nouveau_pushbuf.h
+@@ -0,0 +1,162 @@
++/*
++ * Copyright 2007 Nouveau Project
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++ * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
++ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#ifndef __NOUVEAU_PUSHBUF_H__
++#define __NOUVEAU_PUSHBUF_H__
++
++#include <assert.h>
++#include <string.h>
++
++#include "nouveau_bo.h"
++#include "nouveau_grobj.h"
++
++int
++nouveau_pushbuf_flush(struct nouveau_channel *, unsigned min);
++
++int
++nouveau_pushbuf_marker_emit(struct nouveau_channel *chan,
++			    unsigned wait_dwords, unsigned wait_relocs);
++
++void
++nouveau_pushbuf_marker_undo(struct nouveau_channel *chan);
++
++int
++nouveau_pushbuf_emit_reloc(struct nouveau_channel *, void *ptr,
++			   struct nouveau_bo *, uint32_t data, uint32_t data2,
++			   uint32_t flags, uint32_t vor, uint32_t tor);
++
++int
++nouveau_pushbuf_submit(struct nouveau_channel *chan, struct nouveau_bo *bo,
++		       unsigned offset, unsigned length);
++
++/* Push buffer access macros */
++static __inline__ int
++MARK_RING(struct nouveau_channel *chan, unsigned dwords, unsigned relocs)
++{
++	return nouveau_pushbuf_marker_emit(chan, dwords, relocs);
++}
++
++static __inline__ void
++MARK_UNDO(struct nouveau_channel *chan)
++{
++	nouveau_pushbuf_marker_undo(chan);
++}
++
++static __inline__ void
++OUT_RING(struct nouveau_channel *chan, unsigned data)
++{
++	*(chan->cur++) = (data);
++}
++
++static __inline__ void
++OUT_RINGp(struct nouveau_channel *chan, const void *data, unsigned size)
++{
++	memcpy(chan->cur, data, size * 4);
++	chan->cur += size;
++}
++
++static __inline__ void
++OUT_RINGf(struct nouveau_channel *chan, float f)
++{
++	union { uint32_t i; float f; } c;
++	c.f = f;
++	OUT_RING(chan, c.i);
++}
++
++static __inline__ unsigned
++AVAIL_RING(struct nouveau_channel *chan)
++{
++	return chan->end - chan->cur;
++}
++
++static __inline__ void
++WAIT_RING(struct nouveau_channel *chan, unsigned size)
++{
++	if (chan->cur + size > chan->end)
++		nouveau_pushbuf_flush(chan, size);
++}
++
++static __inline__ void
++FIRE_RING(struct nouveau_channel *chan)
++{
++	nouveau_pushbuf_flush(chan, 0);
++}
++
++static __inline__ int
++OUT_RELOC(struct nouveau_channel *chan, struct nouveau_bo *bo,
++	  unsigned data, unsigned flags, unsigned vor, unsigned tor)
++{
++	return nouveau_pushbuf_emit_reloc(chan, chan->cur++, bo,
++					  data, 0, flags, vor, tor);
++}
++
++static __inline__ int
++OUT_RELOC2(struct nouveau_channel *chan, struct nouveau_bo *bo,
++	   unsigned data, unsigned data2, unsigned flags,
++	   unsigned vor, unsigned tor)
++{
++	return nouveau_pushbuf_emit_reloc(chan, chan->cur++, bo,
++					  data, data2, flags, vor, tor);
++}
++
++/* Raw data + flags depending on FB/TT buffer */
++static __inline__ int
++OUT_RELOCd(struct nouveau_channel *chan, struct nouveau_bo *bo,
++	   unsigned data, unsigned flags, unsigned vor, unsigned tor)
++{
++	return OUT_RELOC(chan, bo, data, flags | NOUVEAU_BO_OR, vor, tor);
++}
++
++/* FB/TT object handle */
++static __inline__ int
++OUT_RELOCo(struct nouveau_channel *chan, struct nouveau_bo *bo,
++	   unsigned flags)
++{
++	return OUT_RELOC(chan, bo, 0, flags | NOUVEAU_BO_OR,
++			 chan->vram->handle, chan->gart->handle);
++}
++
++/* Low 32-bits of offset */
++static __inline__ int
++OUT_RELOCl(struct nouveau_channel *chan, struct nouveau_bo *bo,
++	   unsigned delta, unsigned flags)
++{
++	return OUT_RELOC(chan, bo, delta, flags | NOUVEAU_BO_LOW, 0, 0);
++}
++
++/* Low 32-bits of offset + GPU linear access range info */
++static __inline__ int
++OUT_RELOCr(struct nouveau_channel *chan, struct nouveau_bo *bo,
++	   unsigned delta, unsigned size, unsigned flags)
++{
++	return OUT_RELOC2(chan, bo, delta, size, flags | NOUVEAU_BO_LOW, 0, 0);
++}
++
++/* High 32-bits of offset */
++static __inline__ int
++OUT_RELOCh(struct nouveau_channel *chan, struct nouveau_bo *bo,
++	   unsigned delta, unsigned flags)
++{
++	return OUT_RELOC(chan, bo, delta, flags | NOUVEAU_BO_HIGH, 0, 0);
++}
++
++#endif
+diff --git a/nouveau-1/nouveau_reloc.c b/nouveau-1/nouveau_reloc.c
+new file mode 100644
+index 0000000..cd219db
+--- /dev/null
++++ b/nouveau-1/nouveau_reloc.c
+@@ -0,0 +1,154 @@
++/*
++ * Copyright 2010 Nouveau Project
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++ * THE AUTHORS 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.
++ */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <errno.h>
++#include <assert.h>
++
++#include "nouveau_private.h"
++
++static uint32_t
++nouveau_reloc_calc(struct drm_nouveau_gem_pushbuf_bo *pbbo,
++		   struct drm_nouveau_gem_pushbuf_reloc *r)
++{
++	uint32_t push = 0;
++
++	if (r->flags & NOUVEAU_GEM_RELOC_LOW)
++		push = (pbbo->presumed.offset + r->data);
++	else
++	if (r->flags & NOUVEAU_GEM_RELOC_HIGH)
++		push = (pbbo->presumed.offset + r->data) >> 32;
++	else
++		push = r->data;
++
++	if (r->flags & NOUVEAU_GEM_RELOC_OR) {
++		if (pbbo->presumed.domain & NOUVEAU_GEM_DOMAIN_VRAM)
++			push |= r->vor;
++		else
++			push |= r->tor;
++	}
++
++	return push;
++}
++
++int
++nouveau_reloc_emit(struct nouveau_channel *chan, struct nouveau_bo *reloc_bo,
++		   uint32_t reloc_offset, uint32_t *reloc_ptr,
++		   struct nouveau_bo *bo, uint32_t data, uint32_t data2,
++		   uint32_t flags, uint32_t vor, uint32_t tor)
++{
++	struct nouveau_pushbuf_priv *nvpb = &nouveau_channel(chan)->pb;
++	struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
++	struct drm_nouveau_gem_pushbuf_reloc *r;
++	struct drm_nouveau_gem_pushbuf_bo *pbbo, *rpbbo;
++	uint32_t domains = 0;
++
++	if (nvpb->nr_relocs >= NOUVEAU_GEM_MAX_RELOCS) {
++		fprintf(stderr, "too many relocs!!\n");
++		return -ENOMEM;
++	}
++
++	if (nvbo->user && (flags & NOUVEAU_BO_WR)) {
++		fprintf(stderr, "write to user buffer!!\n");
++		return -EINVAL;
++	}
++
++	/* We're about to reloc a user buffer, better make sure we don't cause
++	 * a double migration.
++	 */
++	if (!(nvbo->flags & (NOUVEAU_BO_GART | NOUVEAU_BO_VRAM)))
++		nvbo->flags |= (flags & (NOUVEAU_BO_GART | NOUVEAU_BO_VRAM));
++
++	/* add buffer to validation list */
++	pbbo = nouveau_bo_emit_buffer(chan, bo);
++	if (!pbbo) {
++		fprintf(stderr, "buffer emit fail :(\n");
++		return -ENOMEM;
++	}
++	nouveau_bo(bo)->pending_refcnt++;
++
++	if (flags & (NOUVEAU_BO_VRAM | NOUVEAU_BO_GART)) {
++		if (flags & NOUVEAU_BO_VRAM)
++			domains |= NOUVEAU_GEM_DOMAIN_VRAM;
++		if (flags & NOUVEAU_BO_GART)
++			domains |= NOUVEAU_GEM_DOMAIN_GART;
++	} else
++		domains |= nvbo->domain;
++
++	if (!(pbbo->valid_domains & domains)) {
++		fprintf(stderr, "no valid domains remain!\n");
++		return -EINVAL;
++	}
++	pbbo->valid_domains &= domains;
++
++	assert(flags & NOUVEAU_BO_RDWR);
++	if (flags & NOUVEAU_BO_RD) {
++		pbbo->read_domains |= domains;
++	}
++	if (flags & NOUVEAU_BO_WR) {
++		pbbo->write_domains |= domains;
++		nvbo->write_marker = 1;
++	}
++
++	/* nvc0 gallium driver uses reloc_emit() with NULL target buffer
++	 * to inform bufmgr of a buffer's use - however, we need something
++	 * to track, so create a reloc for now, and hope it never triggers
++	 * (it shouldn't, constant virtual address..)..
++	 */
++	if (!reloc_bo) {
++		reloc_bo  = nvpb->buffer[nvpb->current];
++		reloc_offset = 0;
++		reloc_ptr = NULL;
++	}
++
++	/* add reloc target bo to validation list, and create the reloc */
++	rpbbo = nouveau_bo_emit_buffer(chan, reloc_bo);
++	if (!rpbbo)
++		return -ENOMEM;
++	nouveau_bo(reloc_bo)->pending_refcnt++;
++
++	r = nvpb->relocs + nvpb->nr_relocs++;
++	r->reloc_bo_index = rpbbo - nvpb->buffers;
++	r->reloc_bo_offset = reloc_offset;
++	r->bo_index = pbbo - nvpb->buffers;
++	r->flags = 0;
++	if (flags & NOUVEAU_BO_LOW)
++		r->flags |= NOUVEAU_GEM_RELOC_LOW;
++	if (flags & NOUVEAU_BO_HIGH)
++		r->flags |= NOUVEAU_GEM_RELOC_HIGH;
++	if (flags & NOUVEAU_BO_OR)
++		r->flags |= NOUVEAU_GEM_RELOC_OR;
++	r->data = data;
++	r->vor = vor;
++	r->tor = tor;
++
++	if (reloc_ptr) {
++		if (flags & NOUVEAU_BO_DUMMY)
++			*reloc_ptr = 0;
++		else
++			*reloc_ptr = nouveau_reloc_calc(pbbo, r);
++	}
++
++	return 0;
++}
++
+diff --git a/nouveau-1/nouveau_reloc.h b/nouveau-1/nouveau_reloc.h
+new file mode 100644
+index 0000000..24ddb52
+--- /dev/null
++++ b/nouveau-1/nouveau_reloc.h
+@@ -0,0 +1,32 @@
++/*
++ * Copyright 2010 Nouveau Project
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++ * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
++ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#ifndef __NOUVEAU_RELOC_H__
++#define __NOUVEAU_RELOC_H__
++
++int
++nouveau_reloc_emit(struct nouveau_channel *chan, struct nouveau_bo *reloc_bo,
++		   uint32_t reloc_offset, uint32_t *reloc_ptr,
++		   struct nouveau_bo *bo, uint32_t data, uint32_t data2,
++		   uint32_t flags, uint32_t vor, uint32_t tor);
++
++#endif
+diff --git a/nouveau-1/nouveau_resource.c b/nouveau-1/nouveau_resource.c
+new file mode 100644
+index 0000000..7acaf7d
+--- /dev/null
++++ b/nouveau-1/nouveau_resource.c
+@@ -0,0 +1,124 @@
++/*
++ * Copyright 2007 Nouveau Project
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++ * THE AUTHORS 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.
++ */
++
++#include <stdlib.h>
++#include <errno.h>
++
++#include "nouveau_private.h"
++
++int
++nouveau_resource_init(struct nouveau_resource **heap,
++		      unsigned start, unsigned size)
++{
++	struct nouveau_resource *r;
++
++	r = calloc(1, sizeof(struct nouveau_resource));
++	if (!r)
++		return 1;
++
++	r->start = start;
++	r->size  = size;
++	*heap = r;
++	return 0;
++}
++
++void
++nouveau_resource_destroy(struct nouveau_resource **heap)
++{
++	if (!*heap)
++		return;
++	free(*heap);
++	*heap = NULL;
++}
++
++int
++nouveau_resource_alloc(struct nouveau_resource *heap, unsigned size, void *priv,
++		       struct nouveau_resource **res)
++{
++	struct nouveau_resource *r;
++
++	if (!heap || !size || !res || *res)
++		return 1;
++
++	while (heap) {
++		if (!heap->in_use && heap->size >= size) {
++			r = calloc(1, sizeof(struct nouveau_resource));
++			if (!r)
++				return 1;
++
++			r->start  = (heap->start + heap->size) - size;
++			r->size   = size;
++			r->in_use = 1;
++			r->priv   = priv;
++
++			heap->size -= size;
++
++			r->next = heap->next;
++			if (heap->next)
++				heap->next->prev = r;
++			r->prev = heap;
++			heap->next = r;
++
++			*res = r;
++			return 0;
++		}
++			
++		heap = heap->next;
++	}
++
++	return 1;
++}
++
++void
++nouveau_resource_free(struct nouveau_resource **res)
++{
++	struct nouveau_resource *r;
++
++	if (!res || !*res)
++		return;
++	r = *res;
++	*res = NULL;
++
++	r->in_use = 0;
++
++	if (r->next && !r->next->in_use) {
++		struct nouveau_resource *new = r->next;
++
++		new->prev = r->prev;
++		if (r->prev)
++			r->prev->next = new;
++		new->size += r->size;
++		new->start = r->start;
++
++		free(r);
++		r = new;
++	}
++
++	if (r->prev && !r->prev->in_use) {
++		r->prev->next = r->next;
++		if (r->next)
++			r->next->prev = r->prev;
++		r->prev->size += r->size;
++		free(r);
++	}
++	
++}
+diff --git a/nouveau-1/nouveau_resource.h b/nouveau-1/nouveau_resource.h
+new file mode 100644
+index 0000000..b760dfb
+--- /dev/null
++++ b/nouveau-1/nouveau_resource.h
+@@ -0,0 +1,51 @@
++/*
++ * Copyright 2007 Nouveau Project
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++ * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
++ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#ifndef __NOUVEAU_RESOURCE_H__
++#define __NOUVEAU_RESOURCE_H__
++
++struct nouveau_resource {
++	struct nouveau_resource *prev;
++	struct nouveau_resource *next;
++
++	int in_use;
++	void *priv;
++
++	unsigned int start;
++	unsigned int size;
++};
++
++int
++nouveau_resource_init(struct nouveau_resource **heap, unsigned start,
++		      unsigned size);
++
++void
++nouveau_resource_destroy(struct nouveau_resource **heap);
++
++int
++nouveau_resource_alloc(struct nouveau_resource *heap, unsigned size, void *priv,
++		       struct nouveau_resource **);
++
++void
++nouveau_resource_free(struct nouveau_resource **);
++
++#endif
+diff --git a/nouveau-1/nv04_pushbuf.h b/nouveau-1/nv04_pushbuf.h
+new file mode 100644
+index 0000000..586b284
+--- /dev/null
++++ b/nouveau-1/nv04_pushbuf.h
+@@ -0,0 +1,66 @@
++/*
++ * Copyright 2007 Nouveau Project
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++ * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
++ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#ifndef __NV04_PUSHBUF_H__
++#define __NV04_PUSHBUF_H__
++
++#include "nouveau_pushbuf.h"
++
++static __inline__ void
++BEGIN_RING(struct nouveau_channel *chan, struct nouveau_grobj *gr,
++	   unsigned mthd, unsigned size)
++{
++	if (gr->bound == NOUVEAU_GROBJ_UNBOUND)
++		nouveau_grobj_autobind(gr);
++	chan->subc[gr->subc].sequence = chan->subc_sequence++;
++
++	WAIT_RING(chan, size + 1);
++	OUT_RING(chan, (gr->subc << 13) | (size << 18) | mthd);
++}
++
++/* non-incrementing BEGIN_RING */
++static __inline__ void
++BEGIN_RING_NI(struct nouveau_channel *chan, struct nouveau_grobj *gr,
++	   unsigned mthd, unsigned size)
++{
++	BEGIN_RING(chan, gr, mthd | 0x40000000, size);
++}
++
++static __inline__ void
++BIND_RING(struct nouveau_channel *chan, struct nouveau_grobj *gr, unsigned sc)
++{
++	struct nouveau_subchannel *subc = &gr->channel->subc[sc];
++
++	if (subc->gr) {
++		if (subc->gr->bound == NOUVEAU_GROBJ_BOUND_EXPLICIT)
++			assert(0);
++		subc->gr->bound = NOUVEAU_GROBJ_UNBOUND;
++	}
++	subc->gr = gr;
++	subc->gr->subc = sc;
++	subc->gr->bound = NOUVEAU_GROBJ_BOUND_EXPLICIT;
++
++	BEGIN_RING(chan, gr, 0x0000, 1);
++	OUT_RING  (chan, gr->handle);
++}
++
++#endif
+diff --git a/nouveau-1/nvc0_pushbuf.h b/nouveau-1/nvc0_pushbuf.h
+new file mode 100644
+index 0000000..40dc7e6
+--- /dev/null
++++ b/nouveau-1/nvc0_pushbuf.h
+@@ -0,0 +1,92 @@
++/*
++ * Copyright 2010 Nouveau Project
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++ * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
++ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#ifndef __NVC0_PUSHBUF_H__
++#define __NVC0_PUSHBUF_H__
++
++#include "nouveau_pushbuf.h"
++
++#define SUBC_BIND(chan, gr) do {                                               \
++	if (gr->bound == NOUVEAU_GROBJ_UNBOUND)                                \
++		nouveau_grobj_autobind(gr);                                    \
++	chan->subc[gr->subc].sequence = chan->subc_sequence++;                 \
++} while (0)
++
++/* incremental methods */
++static __inline__ void
++BEGIN_RING(struct nouveau_channel *chan, struct nouveau_grobj *gr,
++	   unsigned mthd, unsigned size)
++{
++	SUBC_BIND(chan, gr);
++	WAIT_RING(chan, size + 1);
++	OUT_RING (chan, (0x2 << 28) | (size << 16) | (gr->subc << 13) | (mthd >> 2));
++}
++
++/* non-incremental */
++static __inline__ void
++BEGIN_RING_NI(struct nouveau_channel *chan, struct nouveau_grobj *gr,
++	      unsigned mthd, unsigned size)
++{
++	SUBC_BIND(chan, gr);
++	WAIT_RING(chan, size + 1);
++	OUT_RING (chan, (0x6 << 28) | (size << 16) | (gr->subc << 13) | (mthd >> 2));
++}
++
++/* increment-once */
++static __inline__ void
++BEGIN_RING_1I(struct nouveau_channel *chan, struct nouveau_grobj *gr,
++	      unsigned mthd, unsigned size)
++{
++	SUBC_BIND(chan, gr);
++	WAIT_RING(chan, size + 1);
++	OUT_RING (chan, (0xa << 28) | (size << 16) | (gr->subc << 13) | (mthd >> 2));
++}
++
++/* inline-data */
++static __inline__ void
++IMMED_RING(struct nouveau_channel *chan, struct nouveau_grobj *gr,
++	   unsigned mthd, unsigned data)
++{
++	SUBC_BIND(chan, gr);
++	WAIT_RING(chan, 1);
++	OUT_RING (chan, (0x8 << 28) | (data << 16) | (gr->subc << 13) | (mthd >> 2));
++}
++
++static __inline__ void
++BIND_RING(struct nouveau_channel *chan, struct nouveau_grobj *gr, unsigned sc)
++{
++	struct nouveau_subchannel *subc = &gr->channel->subc[sc];
++
++	if (subc->gr) {
++		if (subc->gr->bound == NOUVEAU_GROBJ_BOUND_EXPLICIT)
++			assert(0);
++		subc->gr->bound = NOUVEAU_GROBJ_UNBOUND;
++	}
++	subc->gr = gr;
++	subc->gr->subc = sc;
++	subc->gr->bound = NOUVEAU_GROBJ_BOUND_EXPLICIT;
++
++	BEGIN_RING(chan, gr, 0x0000, 1);
++	OUT_RING  (chan, gr->grclass);
++}
++
++#endif
+diff --git a/nouveau/Makefile.am b/nouveau/Makefile.am
+index 206e892..f21157e 100644
+--- a/nouveau/Makefile.am
++++ b/nouveau/Makefile.am
+@@ -6,20 +6,20 @@ AM_CFLAGS = \
+ 	-I$(top_srcdir)/include/drm \
+ 	-DDEBUG
+ 
+-libdrm_nouveau_la_LTLIBRARIES = libdrm_nouveau.la
+-libdrm_nouveau_ladir = $(libdir)
+-libdrm_nouveau_la_LDFLAGS = -version-number 2:0:0 -no-undefined
+-libdrm_nouveau_la_LIBADD = ../libdrm.la @PTHREADSTUBS_LIBS@
++libdrm_nouveau2_la_LTLIBRARIES = libdrm_nouveau2.la
++libdrm_nouveau2_ladir = $(libdir)
++libdrm_nouveau2_la_LDFLAGS = -version-number 2:0:0 -no-undefined
++libdrm_nouveau2_la_LIBADD = ../libdrm.la @PTHREADSTUBS_LIBS@
+ 
+-libdrm_nouveau_la_SOURCES = nouveau.c \
+-			    pushbuf.c \
+-			    bufctx.c \
+-			    abi16.c \
+-			    private.h
++libdrm_nouveau2_la_SOURCES = nouveau.c \
++			     pushbuf.c \
++			     bufctx.c \
++			     abi16.c \
++			     private.h
+ 
+ 
+ libdrm_nouveauincludedir = ${includedir}/libdrm
+ libdrm_nouveauinclude_HEADERS = nouveau.h
+ 
+ pkgconfigdir = @pkgconfigdir@
+-pkgconfig_DATA = libdrm_nouveau.pc
++pkgconfig_DATA = libdrm_nouveau2.pc
+diff --git a/nouveau/libdrm_nouveau.pc.in b/nouveau/libdrm_nouveau.pc.in
+deleted file mode 100644
+index 6170613..0000000
+--- a/nouveau/libdrm_nouveau.pc.in
++++ /dev/null
+@@ -1,11 +0,0 @@
+-prefix=@prefix@
+-exec_prefix=@exec_prefix@
+-libdir=@libdir@
+-includedir=@includedir@
+-
+-Name: libdrm_nouveau
+-Description: Userspace interface to nouveau kernel DRM services
+-Version: 2.4.33
+-Libs: -L${libdir} -ldrm_nouveau
+-Cflags: -I${includedir} -I${includedir}/libdrm -I${includedir}/nouveau
+-Requires.private: libdrm
+diff --git a/nouveau/libdrm_nouveau2.pc.in b/nouveau/libdrm_nouveau2.pc.in
+new file mode 100644
+index 0000000..36971e8
+--- /dev/null
++++ b/nouveau/libdrm_nouveau2.pc.in
+@@ -0,0 +1,11 @@
++prefix=@prefix@
++exec_prefix=@exec_prefix@
++libdir=@libdir@
++includedir=@includedir@
++
++Name: libdrm_nouveau2
++Description: Userspace interface to nouveau kernel DRM services
++Version: 2.4.33
++Libs: -L${libdir} -ldrm_nouveau2
++Cflags: -I${includedir} -I${includedir}/libdrm
++Requires.private: libdrm
+-- 
+1.7.10.2
+
diff --git a/libdrm.spec b/libdrm.spec
index 8e0efd7..a52d29f 100644
--- a/libdrm.spec
+++ b/libdrm.spec
@@ -2,8 +2,8 @@
 
 Summary: Direct Rendering Manager runtime library
 Name: libdrm
-Version: 2.4.33
-Release: 3%{?dist}
+Version: 2.4.37
+Release: 1%{?dist}
 License: MIT
 Group: System Environment/Libraries
 URL: http://dri.sourceforge.net
@@ -28,6 +28,8 @@ Patch3: libdrm-make-dri-perms-okay.patch
 Patch4: libdrm-2.4.0-no-bc.patch
 # make rule to print the list of test programs
 Patch5: libdrm-2.4.25-check-programs.patch
+# patch back in nouveau-1 interfaces
+Patch6: libdrm-2.4.37-nouveau-1.patch
 
 %description
 Direct Rendering Manager runtime library
@@ -55,10 +57,11 @@ Utility programs for the kernel DRM interface.  Will void your warranty.
 %patch3 -p1 -b .forceperms
 %patch4 -p1 -b .no-bc
 %patch5 -p1 -b .check
+%patch6 -p1 -b .nouveau-1
 
 %build
 autoreconf -v --install || exit 1
-%configure --enable-udev --enable-nouveau-experimental-api \
+%configure --enable-udev \
 %ifarch %{arm}
            --enable-omap-experimental-api \
 %endif
@@ -109,6 +112,8 @@ done
 %{_libdir}/libdrm_radeon.so.1.0.0
 %{_libdir}/libdrm_nouveau.so.1
 %{_libdir}/libdrm_nouveau.so.1.0.0
+%{_libdir}/libdrm_nouveau2.so.2
+%{_libdir}/libdrm_nouveau2.so.2.0.0
 /lib/udev/rules.d/91-drm-modeset.rules
 
 %files -n drm-utils
@@ -158,6 +163,7 @@ done
 %{_includedir}/libdrm/radeon_surface.h
 %{_includedir}/libdrm/r600_pci_ids.h
 %{_includedir}/libdrm/nouveau_drmif.h
+%{_includedir}/libdrm/nouveau.h
 %{_includedir}/libdrm/*_drm.h
 %dir %{_includedir}/nouveau
 %{_includedir}/nouveau/nouveau_*.h
@@ -172,6 +178,7 @@ done
 %endif
 %{_libdir}/libdrm_radeon.so
 %{_libdir}/libdrm_nouveau.so
+%{_libdir}/libdrm_nouveau2.so
 %{_libdir}/pkgconfig/libdrm.pc
 %ifarch %{ix86} x86_64 ia64
 %{_libdir}/pkgconfig/libdrm_intel.pc
@@ -181,9 +188,14 @@ done
 %endif
 %{_libdir}/pkgconfig/libdrm_radeon.pc
 %{_libdir}/pkgconfig/libdrm_nouveau.pc
+%{_libdir}/pkgconfig/libdrm_nouveau2.pc
 %{_libdir}/pkgconfig/libkms.pc
 
 %changelog
+* Mon Jul 2 2012 Ben Skeggs <bskeggs at redhat.com> 2.4.37-1
+- libdrm 2.4.37
+- patched in dual-support for old nouveau api
+
 * Fri May 11 2012 Dennis Gilmore <dennis at ausil.us> 2.4.33-3
 - enable libdrm_omap on arm arches
 
diff --git a/sources b/sources
index f4e5841..ca0e873 100644
--- a/sources
+++ b/sources
@@ -1 +1 @@
-eb2a76720af5051b1687328a2240daed  libdrm-2.4.33.tar.bz2
+9765919c28d4a54887576db3680137cc  libdrm-2.4.37.tar.bz2


More information about the scm-commits mailing list