[prev in list] [next in list] [prev in thread] [next in thread] 

List:       dri-patches
Subject:    drm: Branch 'master' - 2 commits
From:       darktama () kemper ! freedesktop ! org (Ben Skeggs)
Date:       2012-04-13 16:48:00
Message-ID: 20120413164800.BA2361004A () kemper ! freedesktop ! org
[Download RAW message or body]

 configure.ac                 |   25 +
 libdrm_lists.h               |   29 +
 nouveau/Makefile.am          |   36 --
 nouveau/abi16.c              |  197 ++++++++++
 nouveau/bufctx.c             |  170 +++++++++
 nouveau/libdrm_nouveau.pc.in |    2 
 nouveau/nouveau.c            |  489 +++++++++++++++++++++++++++
 nouveau/nouveau.h            |  211 +++++++++++
 nouveau/nouveau_bo.c         |  549 ------------------------------
 nouveau/nouveau_bo.h         |  104 -----
 nouveau/nouveau_channel.c    |  142 -------
 nouveau/nouveau_channel.h    |   57 ---
 nouveau/nouveau_device.c     |  198 -----------
 nouveau/nouveau_device.h     |   33 -
 nouveau/nouveau_drmif.h      |   58 ---
 nouveau/nouveau_grobj.c      |  148 --------
 nouveau/nouveau_grobj.h      |   48 --
 nouveau/nouveau_notifier.c   |  148 --------
 nouveau/nouveau_notifier.h   |   63 ---
 nouveau/nouveau_private.h    |  136 -------
 nouveau/nouveau_pushbuf.c    |  344 -------------------
 nouveau/nouveau_pushbuf.h    |  162 ---------
 nouveau/nouveau_reloc.c      |  154 --------
 nouveau/nouveau_reloc.h      |   32 -
 nouveau/nouveau_resource.c   |  124 ------
 nouveau/nouveau_resource.h   |   51 --
 nouveau/nv04_pushbuf.h       |   66 ---
 nouveau/nvc0_pushbuf.h       |   92 -----
 nouveau/private.h            |  122 ++++++
 nouveau/pushbuf.c            |  774 +++++++++++++++++++++++++++++++++++++++++++
 30 files changed, 2020 insertions(+), 2744 deletions(-)

New commits:
commit 292da616fe1f936ca78a3fa8e1b1b19883e343b6
Author: Ben Skeggs <bskeggs@redhat.com>
Date:   Fri Dec 9 16:11:06 2011 +1000

    nouveau: pull in major libdrm rewrite
    
    Redesigned primarily to allow us to better take advantage of BO's having
    fixed GPU virtual addresses on GeForce 8 and up, and to reduce the overhead
    of handling relocations on earlier chipsets.
    
    Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
    Signed-off-by: Christoph Bumiller <e0425955@student.tuwien.ac.at>

diff --git a/configure.ac b/configure.ac
index 1ba7eba..6a1d98e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -73,16 +73,16 @@ AC_ARG_ENABLE(radeon,
 	      [Enable support for radeon's KMS API (default: auto)]),
 	      [RADEON=$enableval], [RADEON=auto])
 
+AC_ARG_ENABLE(nouveau,
+	      AS_HELP_STRING([--disable-nouveau],
+	      [Enable support for nouveau's KMS API (default: auto)]),
+	      [NOUVEAU=$enableval], [NOUVEAU=auto])
+
 AC_ARG_ENABLE(vmwgfx-experimental-api,
 	      AS_HELP_STRING([--enable-vmwgfx-experimental-api],
 	      [Install vmwgfx's experimental kernel API header (default: disabled)]),
 	      [VMWGFX=$enableval], [VMWGFX=no])
 
-AC_ARG_ENABLE(nouveau-experimental-api,
-	      AS_HELP_STRING([--enable-nouveau-experimental-api],
-	      [Enable support for nouveau's experimental API (default: disabled)]),
-	      [NOUVEAU=$enableval], [NOUVEAU=no])
-
 AC_ARG_ENABLE(omap-experimental-api,
 	      AS_HELP_STRING([--enable-omap-experimental-api],
 	      [Enable support for OMAP's experimental API (default: disabled)]),
@@ -204,7 +204,7 @@ if test "x$HAVE_LIBUDEV" = xyes; then
 fi
 AM_CONDITIONAL(HAVE_LIBUDEV, [test "x$HAVE_LIBUDEV" = xyes])
 
-if test "x$INTEL" != "xno" -o "x$RADEON" != "xno"; then
+if test "x$INTEL" != "xno" -o "x$RADEON" != "xno" -o "x$NOUVEAU" != "xno"; then
     # Check for atomic intrinsics
     AC_CACHE_CHECK([for native atomic primitives], drm_cv_atomic_primitives,
     [
@@ -252,7 +252,14 @@ if test "x$INTEL" != "xno" -o "x$RADEON" != "xno"; then
                    AC_MSG_WARN([Disabling libdrm_radeon. It depends on atomic \
operations, which were not found for your compiler/cpu. Try compiling with \
-march=native, or install the libatomics-op-dev package.])  RADEON=no
            fi
-
+           if test "x$NOUVEAU" != "xauto"; then
+                   if test "x$NOUVEAU" != "xno"; then
+                        AC_MSG_ERROR([libdrm_nouveau depends upon atomic operations, \
which were not found for your compiler/cpu. Try compiling with -march=native, or \
install the libatomics-op-dev package, or, failing both of those, disable support for \
NVIDIA GPUs by passing --disable-nouveau to ./configure]) +                   fi
+           else
+                   AC_MSG_WARN([Disabling libdrm_nouveau. It depends on atomic \
operations, which were not found for your compiler/cpu. Try compiling with \
-march=native, or install the libatomics-op-dev package.]) +                   \
NOUVEAU=no +           fi
     else
            if test "x$INTEL" != "xno"; then
                    case $host_cpu in
@@ -263,6 +270,9 @@ if test "x$INTEL" != "xno" -o "x$RADEON" != "xno"; then
            if test "x$RADEON" != "xno"; then
                    RADEON=yes
            fi
+           if test "x$NOUVEAU" != "xno"; then
+                   NOUVEAU=yes
+           fi
     fi
 fi
 
@@ -279,6 +289,7 @@ fi
 
 AM_CONDITIONAL(HAVE_INTEL, [test "x$INTEL" != "xno"])
 AM_CONDITIONAL(HAVE_RADEON, [test "x$RADEON" != "xno"])
+AM_CONDITIONAL(HAVE_NOUVEAU, [test "x$NOUVEAU" != "xno"])
 if test "x$RADEON" = xyes; then
 	AC_DEFINE(HAVE_RADEON, 1, [Have radeon support])
 fi
diff --git a/nouveau/Makefile.am b/nouveau/Makefile.am
index 8b89916..206e892 100644
--- a/nouveau/Makefile.am
+++ b/nouveau/Makefile.am
@@ -3,41 +3,23 @@ AM_CFLAGS = \
 	-I$(top_srcdir) \
 	-I$(top_srcdir)/nouveau \
 	$(PTHREADSTUBS_CFLAGS) \
-	-I$(top_srcdir)/include/drm
+	-I$(top_srcdir)/include/drm \
+	-DDEBUG
 
 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_LDFLAGS = -version-number 2: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_nouveau_la_SOURCES = nouveau.c \
+			    pushbuf.c \
+			    bufctx.c \
+			    abi16.c \
+			    private.h
 
 
 libdrm_nouveauincludedir = ${includedir}/libdrm
-libdrm_nouveauinclude_HEADERS = \
-				nouveau_drmif.h
+libdrm_nouveauinclude_HEADERS = nouveau.h
 
 pkgconfigdir = @pkgconfigdir@
 pkgconfig_DATA = libdrm_nouveau.pc
diff --git a/nouveau/abi16.c b/nouveau/abi16.c
new file mode 100644
index 0000000..688a9ac
--- /dev/null
+++ b/nouveau/abi16.c
@@ -0,0 +1,197 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include <stdlib.h>
+#include <stdint.h>
+
+#include "private.h"
+
+int
+abi16_chan_nv04(struct nouveau_object *obj)
+{
+	struct nouveau_device *dev = (struct nouveau_device *)obj->parent;
+	struct drm_nouveau_channel_alloc req;
+	struct nv04_fifo *nv04 = obj->data;
+	int ret;
+
+	req.fb_ctxdma_handle = nv04->vram;
+	req.tt_ctxdma_handle = nv04->gart;
+
+	ret = drmCommandWriteRead(dev->fd, DRM_NOUVEAU_CHANNEL_ALLOC,
+				  &req, sizeof(req));
+	if (ret)
+		return ret;
+
+	nv04->base.channel = req.channel;
+	nv04->base.pushbuf = req.pushbuf_domains;
+	nv04->notify = req.notifier_handle;
+	nv04->base.object->handle = req.channel;
+	nv04->base.object->length = sizeof(*nv04);
+	return 0;
+}
+
+int
+abi16_chan_nvc0(struct nouveau_object *obj)
+{
+	struct nouveau_device *dev = (struct nouveau_device *)obj->parent;
+	struct drm_nouveau_channel_alloc req;
+	struct nvc0_fifo *nvc0 = obj->data;
+	int ret;
+
+	ret = drmCommandWriteRead(dev->fd, DRM_NOUVEAU_CHANNEL_ALLOC,
+				  &req, sizeof(req));
+	if (ret)
+		return ret;
+
+	nvc0->base.channel = req.channel;
+	nvc0->base.pushbuf = req.pushbuf_domains;
+	nvc0->base.object->handle = req.channel;
+	nvc0->base.object->length = sizeof(*nvc0);
+	return 0;
+}
+
+int
+abi16_engobj(struct nouveau_object *obj)
+{
+	struct drm_nouveau_grobj_alloc req = {
+		obj->parent->handle, obj->handle, obj->oclass
+	};
+	struct nouveau_device *dev;
+	int ret;
+
+	dev = nouveau_object_find(obj, NOUVEAU_DEVICE_CLASS);
+	ret = drmCommandWrite(dev->fd, DRM_NOUVEAU_GROBJ_ALLOC,
+			      &req, sizeof(req));
+	if (ret)
+		return ret;
+
+	obj->length = sizeof(struct nouveau_object *);
+	return 0;
+}
+
+int
+abi16_ntfy(struct nouveau_object *obj)
+{
+	struct nv04_notify *ntfy = obj->data;
+	struct drm_nouveau_notifierobj_alloc req = {
+		obj->parent->handle, ntfy->object->handle, ntfy->length
+	};
+	struct nouveau_device *dev;
+	int ret;
+
+	dev = nouveau_object_find(obj, NOUVEAU_DEVICE_CLASS);
+	ret = drmCommandWriteRead(dev->fd, DRM_NOUVEAU_NOTIFIEROBJ_ALLOC,
+				  &req, sizeof(req));
+	if (ret)
+		return ret;
+
+	ntfy->offset = req.offset;
+	ntfy->object->length = sizeof(*ntfy);
+	return 0;
+}
+
+void
+abi16_bo_info(struct nouveau_bo *bo, struct drm_nouveau_gem_info *info)
+{
+	struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
+
+	nvbo->map_handle = info->map_handle;
+	bo->handle = info->handle;
+	bo->size = info->size;
+	bo->offset = info->offset;
+
+	bo->flags = 0;
+	if (info->domain & NOUVEAU_GEM_DOMAIN_VRAM)
+		bo->flags |= NOUVEAU_BO_VRAM;
+	if (info->domain & NOUVEAU_GEM_DOMAIN_GART)
+		bo->flags |= NOUVEAU_BO_GART;
+	if (!(info->tile_flags & NOUVEAU_GEM_TILE_NONCONTIG))
+		bo->flags |= NOUVEAU_BO_CONTIG;
+	if (nvbo->map_handle)
+		bo->flags |= NOUVEAU_BO_MAP;
+
+	if (bo->device->chipset >= 0xc0) {
+		bo->config.nvc0.memtype   = (info->tile_flags & 0xff00) >> 8;
+		bo->config.nvc0.tile_mode = info->tile_mode;
+	} else
+	if (bo->device->chipset >= 0x80 || bo->device->chipset == 0x50) {
+		bo->config.nv50.memtype   = (info->tile_flags & 0x07f00) >> 8 |
+					    (info->tile_flags & 0x30000) >> 9;
+		bo->config.nv50.tile_mode = info->tile_mode << 4;
+	} else {
+		bo->config.nv04.surf_flags = info->tile_flags & 7;
+		bo->config.nv04.surf_pitch = info->tile_mode;
+	}
+}
+
+int
+abi16_bo_init(struct nouveau_bo *bo, uint32_t alignment,
+	      union nouveau_bo_config *config)
+{
+	struct nouveau_device *dev = bo->device;
+	struct drm_nouveau_gem_new req = {};
+	struct drm_nouveau_gem_info *info = &req.info;
+	int ret;
+
+	if (bo->flags & NOUVEAU_BO_VRAM)
+		info->domain |= NOUVEAU_GEM_DOMAIN_VRAM;
+	if (bo->flags & NOUVEAU_BO_GART)
+		info->domain |= NOUVEAU_GEM_DOMAIN_GART;
+	if (!info->domain)
+		info->domain |= NOUVEAU_GEM_DOMAIN_VRAM |
+				NOUVEAU_GEM_DOMAIN_GART;
+
+	if (bo->flags & NOUVEAU_BO_MAP)
+		info->domain |= NOUVEAU_GEM_DOMAIN_MAPPABLE;
+
+	if (!(bo->flags & NOUVEAU_BO_CONTIG))
+		info->tile_flags = NOUVEAU_GEM_TILE_NONCONTIG;
+
+	info->size = bo->size;
+	req.align = alignment;
+
+	if (config) {
+		if (dev->chipset >= 0xc0) {
+			info->tile_flags = (config->nvc0.memtype & 0xff) << 8;
+			info->tile_mode  = config->nvc0.tile_mode;
+		} else
+		if (dev->chipset >= 0x80 || dev->chipset == 0x50) {
+			info->tile_flags = (config->nv50.memtype & 0x07f) << 8 |
+					   (config->nv50.memtype & 0x180) << 9;
+			info->tile_mode  = config->nv50.tile_mode >> 4;
+		} else {
+			info->tile_flags = config->nv04.surf_flags & 7;
+			info->tile_mode  = config->nv04.surf_pitch;
+		}
+	}
+
+	if (!nouveau_device(dev)->have_bo_usage)
+		info->tile_flags &= 0x0000ff00;
+
+	ret = drmCommandWriteRead(dev->fd, DRM_NOUVEAU_GEM_NEW,
+				  &req, sizeof(req));
+	if (ret == 0)
+		abi16_bo_info(bo, &req.info);
+	return ret;
+}
diff --git a/nouveau/bufctx.c b/nouveau/bufctx.c
new file mode 100644
index 0000000..23d6f09
--- /dev/null
+++ b/nouveau/bufctx.c
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "libdrm_lists.h"
+
+#include "nouveau.h"
+#include "private.h"
+
+struct nouveau_bufref_priv {
+	struct nouveau_bufref base;
+	struct nouveau_bufref_priv *next;
+	struct nouveau_bufctx *bufctx;
+};
+
+static inline struct nouveau_bufref_priv *
+nouveau_bufref(struct nouveau_bufref *bctx)
+{
+	return (struct nouveau_bufref_priv *)bctx;
+}
+
+struct nouveau_bufbin_priv {
+	struct nouveau_bufref_priv *list;
+	int relocs;
+};
+
+struct nouveau_bufctx_priv {
+	struct nouveau_bufctx base;
+	struct nouveau_bufref_priv *free;
+	int nr_bins;
+	struct nouveau_bufbin_priv bins[];
+};
+
+static inline struct nouveau_bufctx_priv *
+nouveau_bufctx(struct nouveau_bufctx *bctx)
+{
+	return (struct nouveau_bufctx_priv *)bctx;
+}
+
+int
+nouveau_bufctx_new(struct nouveau_client *client, int bins,
+		   struct nouveau_bufctx **pbctx)
+{
+	struct nouveau_bufctx_priv *priv;
+
+	priv = calloc(1, sizeof(*priv) + sizeof(priv->bins[0]) * bins);
+	if (priv) {
+		DRMINITLISTHEAD(&priv->base.head);
+		DRMINITLISTHEAD(&priv->base.pending);
+		DRMINITLISTHEAD(&priv->base.current);
+		priv->base.client = client;
+		priv->nr_bins = bins;
+		*pbctx = &priv->base;
+		return 0;
+	}
+
+	return -ENOMEM;
+}
+
+void
+nouveau_bufctx_del(struct nouveau_bufctx **pbctx)
+{
+	struct nouveau_bufctx_priv *pctx = nouveau_bufctx(*pbctx);
+	struct nouveau_bufref_priv *pref;
+	if (pctx) {
+		while (pctx->nr_bins--)
+			nouveau_bufctx_reset(&pctx->base, pctx->nr_bins);
+		while ((pref = pctx->free)) {
+			pctx->free = pref->next;
+			free(pref);
+		}
+		free(pctx);
+		*pbctx = NULL;
+	}
+}
+
+void
+nouveau_bufctx_reset(struct nouveau_bufctx *bctx, int bin)
+{
+	struct nouveau_bufctx_priv *pctx = nouveau_bufctx(bctx);
+	struct nouveau_bufbin_priv *pbin = &pctx->bins[bin];
+	struct nouveau_bufref_priv *pref;
+
+	while ((pref = pbin->list)) {
+		DRMLISTDELINIT(&pref->base.thead);
+		pbin->list = pref->next;
+		pref->next = pctx->free;
+		pctx->free = pref;
+	}
+
+	bctx->relocs -= pbin->relocs;
+	pbin->relocs  = 0;
+}
+
+struct nouveau_bufref *
+nouveau_bufctx_refn(struct nouveau_bufctx *bctx, int bin,
+		    struct nouveau_bo *bo, uint32_t flags)
+{
+	struct nouveau_bufctx_priv *pctx = nouveau_bufctx(bctx);
+	struct nouveau_bufbin_priv *pbin = &pctx->bins[bin];
+	struct nouveau_bufref_priv *pref = pctx->free;
+
+	if (!pref)
+		pref = malloc(sizeof(*pref));
+	else
+		pctx->free = pref->next;
+
+	if (pref) {
+		pref->base.bo = bo;
+		pref->base.flags = flags;
+		pref->base.packet = 0;
+
+		DRMLISTADDTAIL(&pref->base.thead, &bctx->pending);
+		pref->bufctx = bctx;
+		pref->next = pbin->list;
+		pbin->list = pref;
+	}
+
+	return &pref->base;
+}
+
+struct nouveau_bufref *
+nouveau_bufctx_mthd(struct nouveau_bufctx *bctx, int bin, uint32_t packet,
+		    struct nouveau_bo *bo, uint64_t data, uint32_t flags,
+		    uint32_t vor, uint32_t tor)
+{
+	struct nouveau_bufctx_priv *pctx = nouveau_bufctx(bctx);
+	struct nouveau_bufbin_priv *pbin = &pctx->bins[bin];
+	struct nouveau_bufref *bref = nouveau_bufctx_refn(bctx, bin, bo, flags);
+	if (bref) {
+		bref->packet = packet;
+		bref->data = data;
+		bref->vor = vor;
+		bref->tor = tor;
+		pbin->relocs++;
+		bctx->relocs++;
+	}
+	return bref;
+}
diff --git a/nouveau/libdrm_nouveau.pc.in b/nouveau/libdrm_nouveau.pc.in
index c78a28a..6170613 100644
--- a/nouveau/libdrm_nouveau.pc.in
+++ b/nouveau/libdrm_nouveau.pc.in
@@ -5,7 +5,7 @@ includedir=@includedir@
 
 Name: libdrm_nouveau
 Description: Userspace interface to nouveau kernel DRM services
-Version: 0.6
+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/nouveau.c b/nouveau/nouveau.c
new file mode 100644
index 0000000..699b9b7
--- /dev/null
+++ b/nouveau/nouveau.c
@@ -0,0 +1,489 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdbool.h>
+#include <assert.h>
+#include <errno.h>
+#include <sys/mman.h>
+
+#include <xf86drm.h>
+#include <xf86atomic.h>
+#include "libdrm_lists.h"
+#include "nouveau_drm.h"
+
+#include "nouveau.h"
+#include "private.h"
+
+#ifdef DEBUG
+uint32_t nouveau_debug = 0;
+
+static void
+debug_init(char *args)
+{
+	if (args) {
+		int n = strtol(args, NULL, 0);
+		if (n >= 0)
+			nouveau_debug = n;
+	}
+}
+#endif
+
+/* this is the old libdrm's version of nouveau_device_wrap(), the symbol
+ * is kept here to prevent AIGLX from crashing if the DDX is linked against
+ * the new libdrm, but the DRI driver against the old
+ */
+int
+nouveau_device_open_existing(struct nouveau_device **pdev, int close, int fd,
+			     drm_context_t ctx)
+{
+	return -EACCES;
+}
+
+int
+nouveau_device_wrap(int fd, int close, struct nouveau_device **pdev)
+{
+	struct nouveau_device_priv *nvdev = calloc(1, sizeof(*nvdev));
+	struct nouveau_device *dev = &nvdev->base;
+	uint64_t chipset, vram, gart, bousage;
+	drmVersionPtr ver;
+	int ret;
+
+#ifdef DEBUG
+	debug_init(getenv("NOUVEAU_LIBDRM_DEBUG"));
+#endif
+
+	if (!nvdev)
+		return -ENOMEM;
+	nvdev->base.fd = fd;
+
+	ver = drmGetVersion(fd);
+	if (ver) dev->drm_version = (ver->version_major << 24) |
+				    (ver->version_minor << 8) |
+				     ver->version_patchlevel;
+	drmFreeVersion(ver);
+
+	if ( dev->drm_version != 0x00000010 &&
+	    (dev->drm_version <  0x01000000 ||
+	     dev->drm_version >= 0x02000000)) {
+		nouveau_device_del(&dev);
+		return -EINVAL;
+	}
+
+	ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_CHIPSET_ID, &chipset);
+	if (ret == 0)
+	ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_FB_SIZE, &vram);
+	if (ret == 0)
+	ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_AGP_SIZE, &gart);
+	if (ret) {
+		nouveau_device_del(&dev);
+		return ret;
+	}
+
+	ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_HAS_BO_USAGE, &bousage);
+	if (ret == 0)
+		nvdev->have_bo_usage = (bousage != 0);
+
+	nvdev->close = close;
+	DRMINITLISTHEAD(&nvdev->bo_list);
+	nvdev->base.object.oclass = NOUVEAU_DEVICE_CLASS;
+	nvdev->base.lib_version = 0x01000000;
+	nvdev->base.chipset = chipset;
+	nvdev->base.vram_size = vram;
+	nvdev->base.gart_size = gart;
+	nvdev->base.vram_limit = (nvdev->base.vram_size * 80) / 100;
+	nvdev->base.gart_limit = (nvdev->base.gart_size * 80) / 100;
+
+	*pdev = &nvdev->base;
+	return 0;
+}
+
+int
+nouveau_device_open(const char *busid, struct nouveau_device **pdev)
+{
+	int ret = -ENODEV, fd = drmOpen("nouveau", busid);
+	if (fd >= 0) {
+		ret = nouveau_device_wrap(fd, 1, pdev);
+		if (ret)
+			drmClose(fd);
+	}
+	return ret;
+}
+
+void
+nouveau_device_del(struct nouveau_device **pdev)
+{
+	struct nouveau_device_priv *nvdev = nouveau_device(*pdev);
+	if (nvdev) {
+		if (nvdev->close)
+			drmClose(nvdev->base.fd);
+		free(nvdev->client);
+		free(nvdev);
+		*pdev = NULL;
+	}
+}
+
+int
+nouveau_getparam(struct nouveau_device *dev, uint64_t param, uint64_t *value)
+{
+	struct drm_nouveau_getparam r = { param, 0 };
+	int fd = dev->fd, ret =
+		drmCommandWriteRead(fd, DRM_NOUVEAU_GETPARAM, &r, sizeof(r));
+	*value = r.value;
+	return ret;
+}
+
+int
+nouveau_setparam(struct nouveau_device *dev, uint64_t param, uint64_t value)
+{
+	struct drm_nouveau_setparam r = { param, value };
+	return drmCommandWrite(dev->fd, DRM_NOUVEAU_SETPARAM, &r, sizeof(r));
+}
+
+int
+nouveau_client_new(struct nouveau_device *dev, struct nouveau_client **pclient)
+{
+	struct nouveau_device_priv *nvdev = nouveau_device(dev);
+	struct nouveau_client_priv *pcli;
+	int id = 0, i, ret = -ENOMEM;
+	uint32_t *clients;
+
+	for (i = 0; i < nvdev->nr_client; i++) {
+		id = ffs(nvdev->client[i]) - 1;
+		if (id >= 0)
+			goto out;
+	}
+
+	clients = realloc(nvdev->client, sizeof(uint32_t) * (i + 1));
+	if (!clients)
+		return ret;
+	nvdev->client = clients;
+	nvdev->client[i] = 0;
+	nvdev->nr_client++;
+
+out:
+	pcli = calloc(1, sizeof(*pcli));
+	if (pcli) {
+		nvdev->client[i] |= (1 << id);
+		pcli->base.device = dev;
+		pcli->base.id = (i * 32) + id;
+		ret = 0;
+	}
+
+	*pclient = &pcli->base;
+	return ret;
+}
+
+void
+nouveau_client_del(struct nouveau_client **pclient)
+{
+	struct nouveau_client_priv *pcli = nouveau_client(*pclient);
+	struct nouveau_device_priv *nvdev;
+	if (pcli) {
+		int id = pcli->base.id;
+		nvdev = nouveau_device(pcli->base.device);
+		nvdev->client[id / 32] &= ~(1 << (id % 32));
+		free(pcli->kref);
+		free(pcli);
+	}
+}
+
+int
+nouveau_object_new(struct nouveau_object *parent, uint64_t handle,
+		   uint32_t oclass, void *data, uint32_t length,
+		   struct nouveau_object **pobj)
+{
+	struct nouveau_device *dev;
+	struct nouveau_object *obj;
+	int ret = -EINVAL;
+
+	if (length == 0)
+		length = sizeof(struct nouveau_object *);
+	obj = malloc(sizeof(*obj) + length);
+	obj->parent = parent;
+	obj->handle = handle;
+	obj->oclass = oclass;
+	obj->length = length;
+	obj->data = obj + 1;
+	if (data)
+		memcpy(obj->data, data, length);
+	*(struct nouveau_object **)obj->data = obj;
+
+	dev = nouveau_object_find(obj, NOUVEAU_DEVICE_CLASS);
+	switch (parent->oclass) {
+	case NOUVEAU_DEVICE_CLASS:
+		switch (obj->oclass) {
+		case NOUVEAU_FIFO_CHANNEL_CLASS:
+		{
+			if (dev->chipset < 0xc0)
+				ret = abi16_chan_nv04(obj);
+			else
+				ret = abi16_chan_nvc0(obj);
+		}
+			break;
+		default:
+			break;
+		}
+		break;
+	case NOUVEAU_FIFO_CHANNEL_CLASS:
+		switch (obj->oclass) {
+		case NOUVEAU_NOTIFIER_CLASS:
+			ret = abi16_ntfy(obj);
+			break;
+		default:
+			ret = abi16_engobj(obj);
+			break;
+		}
+	default:
+		break;
+	}
+
+	if (ret) {
+		free(obj);
+		return ret;
+	}
+
+	*pobj = obj;
+	return 0;
+}
+
+void
+nouveau_object_del(struct nouveau_object **pobj)
+{
+	struct drm_nouveau_gpuobj_free req;
+	struct nouveau_object *obj = *pobj;
+	struct nouveau_device *dev;
+	if (obj) {
+		dev = nouveau_object_find(obj, NOUVEAU_DEVICE_CLASS);
+		req.channel = obj->parent->handle;
+		req.handle  = obj->handle;
+		drmCommandWrite(dev->fd, DRM_NOUVEAU_GPUOBJ_FREE,
+				&req, sizeof(req));
+	}
+	free(obj);
+	*pobj = NULL;
+}
+
+void *
+nouveau_object_find(struct nouveau_object *obj, uint32_t pclass)
+{
+	while (obj && obj->oclass != pclass) {
+		obj = obj->parent;
+		if (pclass == NOUVEAU_PARENT_CLASS)
+			break;
+	}
+	return obj;
+}
+
+static void
+nouveau_bo_del(struct nouveau_bo *bo)
+{
+	struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
+	struct drm_gem_close req = { bo->handle };
+	DRMLISTDEL(&nvbo->head);
+	if (bo->map)
+		munmap(bo->map, bo->size);
+	drmIoctl(bo->device->fd, DRM_IOCTL_GEM_CLOSE, &req);
+	free(nvbo);
+}
+
+int
+nouveau_bo_new(struct nouveau_device *dev, uint32_t flags, uint32_t align,
+	       uint64_t size, union nouveau_bo_config *config,
+	       struct nouveau_bo **pbo)
+{
+	struct nouveau_device_priv *nvdev = nouveau_device(dev);
+	struct nouveau_bo_priv *nvbo = calloc(1, sizeof(*nvbo));
+	struct nouveau_bo *bo = &nvbo->base;
+	int ret;
+
+	if (!nvbo)
+		return -ENOMEM;
+	atomic_set(&nvbo->refcnt, 1);
+	bo->device = dev;
+	bo->flags = flags;
+	bo->size = size;
+
+	ret = abi16_bo_init(bo, align, config);
+	if (ret) {
+		free(nvbo);
+		return ret;
+	}
+
+	DRMLISTADD(&nvbo->head, &nvdev->bo_list);
+
+	*pbo = bo;
+	return 0;
+}
+
+int
+nouveau_bo_wrap(struct nouveau_device *dev, uint32_t handle,
+		struct nouveau_bo **pbo)
+{
+	struct nouveau_device_priv *nvdev = nouveau_device(dev);
+	struct drm_nouveau_gem_info req = { .handle = handle };
+	struct nouveau_bo_priv *nvbo;
+	int ret;
+
+	DRMLISTFOREACHENTRY(nvbo, &nvdev->bo_list, head) {
+		if (nvbo->base.handle == handle) {
+			*pbo = NULL;
+			nouveau_bo_ref(&nvbo->base, pbo);
+			return 0;
+		}
+	}
+
+	ret = drmCommandWriteRead(dev->fd, DRM_NOUVEAU_GEM_INFO,
+				  &req, sizeof(req));
+	if (ret)
+		return ret;
+
+	nvbo = calloc(1, sizeof(*nvbo));
+	if (nvbo) {
+		atomic_set(&nvbo->refcnt, 1);
+		nvbo->base.device = dev;
+		abi16_bo_info(&nvbo->base, &req);
+		DRMLISTADD(&nvbo->head, &nvdev->bo_list);
+		*pbo = &nvbo->base;
+		return 0;
+	}
+
+	return -ENOMEM;
+}
+
+int
+nouveau_bo_name_ref(struct nouveau_device *dev, uint32_t name,
+		    struct nouveau_bo **pbo)
+{
+	struct nouveau_device_priv *nvdev = nouveau_device(dev);
+	struct nouveau_bo_priv *nvbo;
+	struct drm_gem_open req = { .name = name };
+	int ret;
+
+	DRMLISTFOREACHENTRY(nvbo, &nvdev->bo_list, head) {
+		if (nvbo->name == name) {
+			*pbo = NULL;
+			nouveau_bo_ref(&nvbo->base, pbo);
+			return 0;
+		}
+	}
+
+	ret = drmIoctl(dev->fd, DRM_IOCTL_GEM_OPEN, &req);
+	if (ret == 0) {
+		ret = nouveau_bo_wrap(dev, req.handle, pbo);
+		nouveau_bo((*pbo))->name = name;
+	}
+
+	return ret;
+}
+
+int
+nouveau_bo_name_get(struct nouveau_bo *bo, uint32_t *name)
+{
+	struct drm_gem_flink req = { .handle = bo->handle };
+	struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
+	if (!nvbo->name) {
+		int ret = drmIoctl(bo->device->fd, DRM_IOCTL_GEM_FLINK, &req);
+		if (ret)
+			return ret;
+		nvbo->name = req.name;
+	}
+	*name = nvbo->name;
+	return 0;
+}
+
+void
+nouveau_bo_ref(struct nouveau_bo *bo, struct nouveau_bo **pref)
+{
+	struct nouveau_bo *ref = *pref;
+	if (bo) {
+		atomic_inc(&nouveau_bo(bo)->refcnt);
+	}
+	if (ref) {
+		if (atomic_dec_and_test(&nouveau_bo(ref)->refcnt))
+			nouveau_bo_del(ref);
+	}
+	*pref = bo;
+}
+
+int
+nouveau_bo_wait(struct nouveau_bo *bo, uint32_t access,
+		struct nouveau_client *client)
+{
+	struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
+	struct drm_nouveau_gem_cpu_prep req;
+	struct nouveau_pushbuf *push;
+	int ret = 0;
+
+	if (!(access & NOUVEAU_BO_RDWR))
+		return 0;
+
+	push = cli_push_get(client, bo);
+	if (push && push->channel)
+		nouveau_pushbuf_kick(push, push->channel);
+
+	if (!nvbo->name && !(nvbo->access & NOUVEAU_BO_WR) &&
+			   !(      access & NOUVEAU_BO_WR))
+		return 0;
+
+	req.handle = bo->handle;
+	req.flags = 0;
+	if (access & NOUVEAU_BO_WR)
+		req.flags |= NOUVEAU_GEM_CPU_PREP_WRITE;
+	if (access & NOUVEAU_BO_NOBLOCK)
+		req.flags |= NOUVEAU_GEM_CPU_PREP_NOWAIT;
+
+	do {
+		ret = drmCommandWrite(bo->device->fd,
+				      DRM_NOUVEAU_GEM_CPU_PREP,
+				      &req, sizeof(req));
+	} while (ret == -EAGAIN);
+
+	if (ret == 0)
+		nvbo->access = 0;
+	return ret;
+}
+
+int
+nouveau_bo_map(struct nouveau_bo *bo, uint32_t access,
+	       struct nouveau_client *client)
+{
+	struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
+	if (bo->map == NULL) {
+		bo->map = mmap(0, bo->size, PROT_READ | PROT_WRITE,
+			       MAP_SHARED, bo->device->fd, nvbo->map_handle);
+		if (bo->map == MAP_FAILED) {
+			bo->map = NULL;
+			return -errno;
+		}
+	}
+	return nouveau_bo_wait(bo, access, client);
+}
diff --git a/nouveau/nouveau.h b/nouveau/nouveau.h
new file mode 100644
index 0000000..d7954cf
--- /dev/null
+++ b/nouveau/nouveau.h
@@ -0,0 +1,211 @@
+#ifndef __NOUVEAU_H__
+#define __NOUVEAU_H__
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#define NOUVEAU_DEVICE_CLASS       0x80000000
+#define NOUVEAU_FIFO_CHANNEL_CLASS 0x80000001
+#define NOUVEAU_NOTIFIER_CLASS     0x80000002
+#define NOUVEAU_PARENT_CLASS       0xffffffff
+
+struct nouveau_list {
+	struct nouveau_list *prev;
+	struct nouveau_list *next;
+};
+
+struct nouveau_object {
+	struct nouveau_object *parent;
+	uint64_t handle;
+	uint32_t oclass;
+	uint32_t length;
+	void *data;
+};
+
+struct nouveau_fifo {
+	struct nouveau_object *object;
+	uint32_t channel;
+	uint32_t pushbuf;
+	uint64_t unused1[3];
+};
+
+struct nv04_fifo {
+	struct nouveau_fifo base;
+	uint32_t vram;
+	uint32_t gart;
+	uint32_t notify;
+};
+
+struct nvc0_fifo {
+	struct nouveau_fifo base;
+};
+
+struct nv04_notify {
+	struct nouveau_object *object;
+	uint32_t offset;
+	uint32_t length;
+};
+
+int  nouveau_object_new(struct nouveau_object *parent, uint64_t handle,
+			uint32_t oclass, void *data, uint32_t length,
+			struct nouveau_object **);
+void nouveau_object_del(struct nouveau_object **);
+void *nouveau_object_find(struct nouveau_object *, uint32_t parent_class);
+
+struct nouveau_device {
+	struct nouveau_object object;
+	int fd;
+	uint32_t lib_version;
+	uint32_t drm_version;
+	uint32_t chipset;
+	uint64_t vram_size;
+	uint64_t gart_size;
+	uint64_t vram_limit;
+	uint64_t gart_limit;
+};
+
+int  nouveau_device_wrap(int fd, int close, struct nouveau_device **);
+int  nouveau_device_open(const char *busid, struct nouveau_device **);
+void nouveau_device_del(struct nouveau_device **);
+int  nouveau_getparam(struct nouveau_device *, uint64_t param, uint64_t *value);
+int  nouveau_setparam(struct nouveau_device *, uint64_t param, uint64_t value);
+
+struct nouveau_client {
+	struct nouveau_device *device;
+	int id;
+};
+
+int  nouveau_client_new(struct nouveau_device *, struct nouveau_client **);
+void nouveau_client_del(struct nouveau_client **);
+
+union nouveau_bo_config {
+	struct {
+#define NV04_BO_16BPP 0x00000001
+#define NV04_BO_32BPP 0x00000002
+#define NV04_BO_ZETA  0x00000004
+		uint32_t surf_flags;
+		uint32_t surf_pitch;
+	} nv04;
+	struct {
+		uint32_t memtype;
+		uint32_t tile_mode;
+	} nv50;
+	struct {
+		uint32_t memtype;
+		uint32_t tile_mode;
+	} nvc0;
+	uint32_t data[8];
+};
+
+#define NOUVEAU_BO_VRAM    0x00000001
+#define NOUVEAU_BO_GART    0x00000002
+#define NOUVEAU_BO_APER   (NOUVEAU_BO_VRAM | NOUVEAU_BO_GART)
+#define NOUVEAU_BO_RD      0x00000100
+#define NOUVEAU_BO_WR      0x00000200
+#define NOUVEAU_BO_RDWR   (NOUVEAU_BO_RD | NOUVEAU_BO_WR)
+#define NOUVEAU_BO_NOBLOCK 0x00000400
+#define NOUVEAU_BO_LOW     0x00001000
+#define NOUVEAU_BO_HIGH    0x00002000
+#define NOUVEAU_BO_OR      0x00004000
+#define NOUVEAU_BO_MAP     0x80000000
+#define NOUVEAU_BO_CONTIG  0x40000000
+#define NOUVEAU_BO_NOSNOOP 0x20000000
+
+struct nouveau_bo {
+	struct nouveau_device *device;
+	uint32_t handle;
+	uint64_t size;
+	uint32_t flags;
+	uint64_t offset;
+	void *map;
+	union nouveau_bo_config config;
+};
+
+int  nouveau_bo_new(struct nouveau_device *, uint32_t flags, uint32_t align,
+		    uint64_t size, union nouveau_bo_config *,
+		    struct nouveau_bo **);
+int  nouveau_bo_wrap(struct nouveau_device *, uint32_t handle,
+		     struct nouveau_bo **);
+int  nouveau_bo_name_ref(struct nouveau_device *dev, uint32_t name,
+			 struct nouveau_bo **);
+int  nouveau_bo_name_get(struct nouveau_bo *, uint32_t *name);
+void nouveau_bo_ref(struct nouveau_bo *, struct nouveau_bo **);
+int  nouveau_bo_map(struct nouveau_bo *, uint32_t access,
+		    struct nouveau_client *);
+int  nouveau_bo_wait(struct nouveau_bo *, uint32_t access,
+		     struct nouveau_client *);
+
+struct nouveau_bufref {
+	struct nouveau_list thead;
+	struct nouveau_bo *bo;
+	uint32_t packet;
+	uint32_t flags;
+	uint32_t data;
+	uint32_t vor;
+	uint32_t tor;
+	uint32_t priv_data;
+	void *priv;
+};
+
+struct nouveau_bufctx {
+	struct nouveau_client *client;
+	struct nouveau_list head;
+	struct nouveau_list pending;
+	struct nouveau_list current;
+	int relocs;
+};
+
+int  nouveau_bufctx_new(struct nouveau_client *, int bins,
+			struct nouveau_bufctx **);
+void nouveau_bufctx_del(struct nouveau_bufctx **);
+struct nouveau_bufref *
+nouveau_bufctx_refn(struct nouveau_bufctx *, int bin,
+		    struct nouveau_bo *, uint32_t flags);
+struct nouveau_bufref *
+nouveau_bufctx_mthd(struct nouveau_bufctx *, int bin,  uint32_t packet,
+		    struct nouveau_bo *, uint64_t data, uint32_t flags,
+		    uint32_t vor, uint32_t tor);
+void nouveau_bufctx_reset(struct nouveau_bufctx *, int bin);
+
+struct nouveau_pushbuf_krec;
+struct nouveau_pushbuf {
+	struct nouveau_client *client;
+	struct nouveau_object *channel;
+	struct nouveau_bufctx *bufctx;
+	void (*kick_notify)(struct nouveau_pushbuf *);
+	void *user_priv;
+	uint32_t rsvd_kick;
+	uint32_t flags;
+	uint32_t *cur;
+	uint32_t *end;
+};
+
+struct nouveau_pushbuf_refn {
+	struct nouveau_bo *bo;
+	uint32_t flags;
+};
+
+int  nouveau_pushbuf_new(struct nouveau_client *, struct nouveau_object *channel,
+			 int nr, uint32_t size, bool immediate,
+			 struct nouveau_pushbuf **);
+void nouveau_pushbuf_del(struct nouveau_pushbuf **);
+int  nouveau_pushbuf_space(struct nouveau_pushbuf *, uint32_t dwords,
+			   uint32_t relocs, uint32_t pushes);
+void nouveau_pushbuf_data(struct nouveau_pushbuf *, struct nouveau_bo *,
+			  uint64_t offset, uint64_t length);
+int  nouveau_pushbuf_refn(struct nouveau_pushbuf *,
+			  struct nouveau_pushbuf_refn *, int nr);
+/* Emits a reloc into the push buffer at the current position, you *must*
+ * have previously added the referenced buffer to a buffer context, and
+ * validated it against the current push buffer.
+ */
+void nouveau_pushbuf_reloc(struct nouveau_pushbuf *, struct nouveau_bo *,
+			   uint32_t data, uint32_t flags,
+			   uint32_t vor, uint32_t tor);
+int  nouveau_pushbuf_validate(struct nouveau_pushbuf *);
+uint32_t nouveau_pushbuf_refd(struct nouveau_pushbuf *, struct nouveau_bo *);
+int  nouveau_pushbuf_kick(struct nouveau_pushbuf *, struct nouveau_object *channel);
+struct nouveau_bufctx *
+nouveau_pushbuf_bufctx(struct nouveau_pushbuf *, struct nouveau_bufctx *);
+
+#endif
diff --git a/nouveau/nouveau_bo.c b/nouveau/nouveau_bo.c
deleted file mode 100644
index d6bb22d..0000000
--- a/nouveau/nouveau_bo.c
+++ /dev/null
@@ -1,549 +0,0 @@
-/*
- * 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/nouveau_bo.h b/nouveau/nouveau_bo.h
deleted file mode 100644
index 3a1f2d4..0000000
--- a/nouveau/nouveau_bo.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * 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/nouveau_channel.c b/nouveau/nouveau_channel.c
deleted file mode 100644
index 96fa03b..0000000
--- a/nouveau/nouveau_channel.c
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * 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/nouveau_channel.h b/nouveau/nouveau_channel.h
deleted file mode 100644
index d61a4c0..0000000
--- a/nouveau/nouveau_channel.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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/nouveau_device.c b/nouveau/nouveau_device.c
deleted file mode 100644
index 425c5d2..0000000
--- a/nouveau/nouveau_device.c
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * 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/nouveau_device.h b/nouveau/nouveau_device.h
deleted file mode 100644
index c0d9333..0000000
--- a/nouveau/nouveau_device.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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/nouveau_drmif.h b/nouveau/nouveau_drmif.h
deleted file mode 100644
index ec226a2..0000000
--- a/nouveau/nouveau_drmif.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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/nouveau_grobj.c b/nouveau/nouveau_grobj.c
deleted file mode 100644
index 36344b9..0000000
--- a/nouveau/nouveau_grobj.c
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * 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/nouveau_grobj.h b/nouveau/nouveau_grobj.h
deleted file mode 100644
index 51ac7d9..0000000
--- a/nouveau/nouveau_grobj.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * 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/nouveau_notifier.c b/nouveau/nouveau_notifier.c
deleted file mode 100644
index 513fa63..0000000
--- a/nouveau/nouveau_notifier.c
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * 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/nouveau_notifier.h b/nouveau/nouveau_notifier.h
deleted file mode 100644
index dbc6a3b..0000000
--- a/nouveau/nouveau_notifier.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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/nouveau_private.h b/nouveau/nouveau_private.h
deleted file mode 100644
index 124fe87..0000000
--- a/nouveau/nouveau_private.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * 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/nouveau_pushbuf.c b/nouveau/nouveau_pushbuf.c
deleted file mode 100644
index 59f60d9..0000000
--- a/nouveau/nouveau_pushbuf.c
+++ /dev/null
@@ -1,344 +0,0 @@
-/*
- * 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/nouveau_pushbuf.h b/nouveau/nouveau_pushbuf.h
deleted file mode 100644
index 2a98789..0000000
--- a/nouveau/nouveau_pushbuf.h
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * 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/nouveau_reloc.c b/nouveau/nouveau_reloc.c
deleted file mode 100644
index cd219db..0000000
--- a/nouveau/nouveau_reloc.c
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * 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/nouveau_reloc.h b/nouveau/nouveau_reloc.h
deleted file mode 100644
index 24ddb52..0000000
--- a/nouveau/nouveau_reloc.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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/nouveau_resource.c b/nouveau/nouveau_resource.c
deleted file mode 100644
index 7acaf7d..0000000
--- a/nouveau/nouveau_resource.c
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * 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/nouveau_resource.h b/nouveau/nouveau_resource.h
deleted file mode 100644
index b760dfb..0000000
--- a/nouveau/nouveau_resource.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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/nv04_pushbuf.h b/nouveau/nv04_pushbuf.h
deleted file mode 100644
index 586b284..0000000
--- a/nouveau/nv04_pushbuf.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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/nvc0_pushbuf.h b/nouveau/nvc0_pushbuf.h
deleted file mode 100644
index 40dc7e6..0000000
--- a/nouveau/nvc0_pushbuf.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * 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/private.h b/nouveau/private.h
new file mode 100644
index 0000000..b409cc8
--- /dev/null
+++ b/nouveau/private.h
@@ -0,0 +1,122 @@
+#ifndef __NOUVEAU_LIBDRM_PRIVATE_H__
+#define __NOUVEAU_LIBDRM_PRIVATE_H__
+
+#include <xf86drm.h>
+#include <xf86atomic.h>
+#include "nouveau_drm.h"
+
+#include "nouveau.h"
+
+#ifdef DEBUG
+uint32_t nouveau_debug;
+#define dbg_on(lvl) (nouveau_debug & (1 << lvl))
+#define dbg(lvl, fmt, args...) do {                                            \
+	if (dbg_on((lvl)))                                                     \
+		fprintf(stderr, "nouveau: "fmt, ##args);                       \
+} while(0)
+#else
+#define dbg_on(lvl) (0)
+#define dbg(lvl, fmt, args...)
+#endif
+#define err(fmt, args...) fprintf(stderr, "nouveau: "fmt, ##args)
+
+struct nouveau_client_kref {
+	struct drm_nouveau_gem_pushbuf_bo *kref;
+	struct nouveau_pushbuf *push;
+};
+
+struct nouveau_client_priv {
+	struct nouveau_client base;
+	struct nouveau_client_kref *kref;
+	unsigned kref_nr;
+};
+
+static inline struct nouveau_client_priv *
+nouveau_client(struct nouveau_client *client)
+{
+	return (struct nouveau_client_priv *)client;
+}
+
+static inline struct drm_nouveau_gem_pushbuf_bo *
+cli_kref_get(struct nouveau_client *client, struct nouveau_bo *bo)
+{
+	struct nouveau_client_priv *pcli = nouveau_client(client);
+	struct drm_nouveau_gem_pushbuf_bo *kref = NULL;
+	if (pcli->kref_nr > bo->handle)
+		kref = pcli->kref[bo->handle].kref;
+	return kref;
+}
+
+static inline struct nouveau_pushbuf *
+cli_push_get(struct nouveau_client *client, struct nouveau_bo *bo)
+{
+	struct nouveau_client_priv *pcli = nouveau_client(client);
+	struct nouveau_pushbuf *push = NULL;
+	if (pcli->kref_nr > bo->handle)
+		push = pcli->kref[bo->handle].push;
+	return push;
+}
+
+static inline void
+cli_kref_set(struct nouveau_client *client, struct nouveau_bo *bo,
+	     struct drm_nouveau_gem_pushbuf_bo *kref,
+	     struct nouveau_pushbuf *push)
+{
+	struct nouveau_client_priv *pcli = nouveau_client(client);
+	if (pcli->kref_nr <= bo->handle) {
+		pcli->kref = realloc(pcli->kref,
+				     sizeof(*pcli->kref) * bo->handle * 2);
+		while (pcli->kref_nr < bo->handle * 2) {
+			pcli->kref[pcli->kref_nr].kref = NULL;
+			pcli->kref[pcli->kref_nr].push = NULL;
+			pcli->kref_nr++;
+		}
+	}
+	pcli->kref[bo->handle].kref = kref;
+	pcli->kref[bo->handle].push = push;
+}
+
+struct nouveau_bo_priv {
+	struct nouveau_bo base;
+	struct nouveau_list head;
+	atomic_t refcnt;
+	uint64_t map_handle;
+	uint32_t name;
+	uint32_t access;
+};
+
+static inline struct nouveau_bo_priv *
+nouveau_bo(struct nouveau_bo *bo)
+{
+	return (struct nouveau_bo_priv *)bo;
+}
+
+struct nouveau_device_priv {
+	struct nouveau_device base;
+	int close;
+	atomic_t lock;
+	struct nouveau_list bo_list;
+	uint32_t *client;
+	int nr_client;
+	bool have_bo_usage;
+};
+
+static inline struct nouveau_device_priv *
+nouveau_device(struct nouveau_device *dev)
+{
+	return (struct nouveau_device_priv *)dev;
+}
+
+int
+nouveau_device_open_existing(struct nouveau_device **, int, int, drm_context_t);
+
+/* abi16.c */
+int  abi16_chan_nv04(struct nouveau_object *);
+int  abi16_chan_nvc0(struct nouveau_object *);
+int  abi16_engobj(struct nouveau_object *);
+int  abi16_ntfy(struct nouveau_object *);
+void abi16_bo_info(struct nouveau_bo *, struct drm_nouveau_gem_info *);
+int  abi16_bo_init(struct nouveau_bo *, uint32_t alignment,
+		   union nouveau_bo_config *);
+
+#endif
diff --git a/nouveau/pushbuf.c b/nouveau/pushbuf.c
new file mode 100644
index 0000000..103737e
--- /dev/null
+++ b/nouveau/pushbuf.c
@@ -0,0 +1,774 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include <xf86drm.h>
+#include <xf86atomic.h>
+#include "libdrm_lists.h"
+#include "nouveau_drm.h"
+
+#include "nouveau.h"
+#include "private.h"
+
+struct nouveau_pushbuf_krec {
+	struct nouveau_pushbuf_krec *next;
+	struct drm_nouveau_gem_pushbuf_bo buffer[NOUVEAU_GEM_MAX_BUFFERS];
+	struct drm_nouveau_gem_pushbuf_reloc reloc[NOUVEAU_GEM_MAX_RELOCS];
+	struct drm_nouveau_gem_pushbuf_push push[NOUVEAU_GEM_MAX_PUSH];
+	int nr_buffer;
+	int nr_reloc;
+	int nr_push;
+	uint64_t vram_used;
+	uint64_t gart_used;
+};
+
+struct nouveau_pushbuf_priv {
+	struct nouveau_pushbuf base;
+	struct nouveau_pushbuf_krec *list;
+	struct nouveau_pushbuf_krec *krec;
+	struct nouveau_list bctx_list;
+	struct nouveau_bo *bo;
+	uint32_t type;
+	uint32_t suffix0;
+	uint32_t suffix1;
+	uint32_t *ptr;
+	uint32_t *bgn;
+	int bo_next;
+	int bo_nr;
+	struct nouveau_bo *bos[];
+};
+
+static inline struct nouveau_pushbuf_priv *
+nouveau_pushbuf(struct nouveau_pushbuf *push)
+{
+	return (struct nouveau_pushbuf_priv *)push;
+}
+
+static int pushbuf_validate(struct nouveau_pushbuf *, bool);
+static int pushbuf_flush(struct nouveau_pushbuf *);
+
+static bool
+pushbuf_kref_fits(struct nouveau_pushbuf *push, struct nouveau_bo *bo,
+		  uint32_t *domains)
+{
+	struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(push);
+	struct nouveau_pushbuf_krec *krec = nvpb->krec;
+	struct nouveau_device *dev = push->client->device;
+	struct nouveau_bo *kbo;
+	struct drm_nouveau_gem_pushbuf_bo *kref;
+	int i;
+
+	/* VRAM is the only valid domain.  GART and VRAM|GART buffers
+	 * are all accounted to GART, so if this doesn't fit in VRAM
+	 * straight up, a flush is needed.
+	 */
+	if (*domains == NOUVEAU_GEM_DOMAIN_VRAM) {
+		if (krec->vram_used + bo->size > dev->vram_limit)
+			return false;
+		krec->vram_used += bo->size;
+		return true;
+	}
+
+	/* GART or VRAM|GART buffer.  Account both of these buffer types
+	 * to GART only for the moment, which simplifies things.  If the
+	 * buffer can fit already, we're done here.
+	 */
+	if (krec->gart_used + bo->size <= dev->gart_limit) {
+		krec->gart_used += bo->size;
+		return true;
+	}
+
+	/* Ran out of GART space, if it's a VRAM|GART buffer and it'll
+	 * fit into available VRAM, turn it into a VRAM buffer
+	 */
+	if ((*domains & NOUVEAU_GEM_DOMAIN_VRAM) &&
+	    krec->vram_used + bo->size <= dev->vram_limit) {
+		*domains &= NOUVEAU_GEM_DOMAIN_VRAM;
+		krec->vram_used += bo->size;
+		return true;
+	}
+
+	/* Still couldn't fit the buffer in anywhere, so as a last resort;
+	 * scan the buffer list for VRAM|GART buffers and turn them into
+	 * VRAM buffers until we have enough space in GART for this one
+	 */
+	kref = krec->buffer;
+	for (i = 0; i < krec->nr_buffer; i++, kref++) {
+		if (!(kref->valid_domains & NOUVEAU_GEM_DOMAIN_GART))
+			continue;
+
+		kbo = (void *)(unsigned long)kref->user_priv;
+		if (!(kref->valid_domains & NOUVEAU_GEM_DOMAIN_VRAM) ||
+		    krec->vram_used + kbo->size > dev->vram_limit)
+			continue;
+
+		kref->valid_domains &= NOUVEAU_GEM_DOMAIN_VRAM;
+		krec->gart_used -= kbo->size;
+		krec->vram_used += kbo->size;
+		if (krec->gart_used + bo->size <= dev->gart_limit) {
+			krec->gart_used += bo->size;
+			return true;
+		}
+	}
+
+	/* Couldn't resolve a placement, need to force a flush */
+	return false;
+}
+
+static struct drm_nouveau_gem_pushbuf_bo *
+pushbuf_kref(struct nouveau_pushbuf *push, struct nouveau_bo *bo,
+	     uint32_t flags)
+{
+	struct nouveau_device *dev = push->client->device;
+	struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(push);
+	struct nouveau_pushbuf_krec *krec = nvpb->krec;
+	struct nouveau_pushbuf *fpush;
+	struct drm_nouveau_gem_pushbuf_bo *kref;
+	uint32_t domains, domains_wr, domains_rd;
+
+	domains = 0;
+	if (flags & NOUVEAU_BO_VRAM)
+		domains |= NOUVEAU_GEM_DOMAIN_VRAM;
+	if (flags & NOUVEAU_BO_GART)
+		domains |= NOUVEAU_GEM_DOMAIN_GART;
+	domains_wr = domains * !!(flags & NOUVEAU_BO_WR);
+	domains_rd = domains * !!(flags & NOUVEAU_BO_RD);
+
+	/* if buffer is referenced on another pushbuf that is owned by the
+	 * same client, we need to flush the other pushbuf first to ensure
+	 * the correct ordering of commands
+	 */
+	fpush = cli_push_get(push->client, bo);
+	if (fpush && fpush != push)
+		pushbuf_flush(fpush);
+
+	kref = cli_kref_get(push->client, bo);
+	if (kref) {
+		/* possible conflict in memory types - flush and retry */
+		if (!(kref->valid_domains & domains))
+			return NULL;
+
+		/* VRAM|GART buffer turning into a VRAM buffer.  Make sure
+		 * it'll fit in VRAM and force a flush if not.
+		 */
+		if ((kref->valid_domains  & NOUVEAU_GEM_DOMAIN_GART) &&
+		    (            domains == NOUVEAU_GEM_DOMAIN_VRAM)) {
+			if (krec->vram_used + bo->size > dev->vram_limit)
+				return NULL;
+			krec->vram_used += bo->size;
+			krec->gart_used -= bo->size;
+		}
+
+		kref->valid_domains &= domains;
+		kref->write_domains |= domains_wr;
+		kref->read_domains  |= domains_rd;
+	} else {
+		if (krec->nr_buffer == NOUVEAU_GEM_MAX_BUFFERS ||
+		    !pushbuf_kref_fits(push, bo, &domains))
+			return NULL;
+
+		kref = &krec->buffer[krec->nr_buffer++];
+		kref->user_priv = (unsigned long)bo;
+		kref->handle = bo->handle;
+		kref->valid_domains = domains;
+		kref->write_domains = domains_wr;
+		kref->read_domains = domains_rd;
+		kref->presumed.valid = 1;
+		kref->presumed.offset = bo->offset;
+		if (bo->flags & NOUVEAU_BO_VRAM)
+			kref->presumed.domain = NOUVEAU_GEM_DOMAIN_VRAM;
+		else
+			kref->presumed.domain = NOUVEAU_GEM_DOMAIN_GART;
+
+		cli_kref_set(push->client, bo, kref, push);
+		atomic_inc(&nouveau_bo(bo)->refcnt);
+	}
+
+	return kref;
+}
+
+static uint32_t
+pushbuf_krel(struct nouveau_pushbuf *push, struct nouveau_bo *bo,
+	     uint32_t data, uint32_t flags, uint32_t vor, uint32_t tor)
+{
+	struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(push);
+	struct nouveau_pushbuf_krec *krec = nvpb->krec;
+	struct drm_nouveau_gem_pushbuf_reloc *krel;
+	struct drm_nouveau_gem_pushbuf_bo *pkref;
+	struct drm_nouveau_gem_pushbuf_bo *bkref;
+	uint32_t reloc = data;
+
+	pkref = cli_kref_get(push->client, nvpb->bo);
+	bkref = cli_kref_get(push->client, bo);
+	krel  = &krec->reloc[krec->nr_reloc++];
+
+	krel->reloc_bo_index = pkref - krec->buffer;
+	krel->reloc_bo_offset = (push->cur - nvpb->ptr) * 4;
+	krel->bo_index = bkref - krec->buffer;
+	krel->flags = 0;
+	krel->data = data;
+	krel->vor = vor;
+	krel->tor = tor;
+
+	if (flags & NOUVEAU_BO_LOW) {
+		reloc = (bkref->presumed.offset + data);
+		krel->flags |= NOUVEAU_GEM_RELOC_LOW;
+	} else
+	if (flags & NOUVEAU_BO_HIGH) {
+		reloc = (bkref->presumed.offset + data) >> 32;
+		krel->flags |= NOUVEAU_GEM_RELOC_HIGH;
+	}
+	if (flags & NOUVEAU_BO_OR) {
+		if (bkref->presumed.domain & NOUVEAU_GEM_DOMAIN_VRAM)
+			reloc |= vor;
+		else
+			reloc |= tor;
+		krel->flags |= NOUVEAU_GEM_RELOC_OR;
+	}
+
+	return reloc;
+}
+
+static void
+pushbuf_dump(struct nouveau_pushbuf_krec *krec, int krec_id, int chid)
+{
+	struct drm_nouveau_gem_pushbuf_reloc *krel;
+	struct drm_nouveau_gem_pushbuf_push *kpsh;
+	struct drm_nouveau_gem_pushbuf_bo *kref;
+	struct nouveau_bo *bo;
+	uint32_t *bgn, *end;
+	int i;
+
+	err("ch%d: krec %d pushes %d bufs %d relocs %d\n", chid,
+	    krec_id, krec->nr_push, krec->nr_buffer, krec->nr_reloc);
+
+	kref = krec->buffer;
+	for (i = 0; i < krec->nr_buffer; i++, kref++) {
+		err("ch%d: buf %08x %08x %08x %08x %08x\n", chid, i,
+		    kref->handle, kref->valid_domains,
+		    kref->read_domains, kref->write_domains);
+	}
+
+	krel = krec->reloc;
+	for (i = 0; i < krec->nr_reloc; i++, krel++) {
+		err("ch%d: rel %08x %08x %08x %08x %08x %08x %08x\n",
+		    chid, krel->reloc_bo_index, krel->reloc_bo_offset,
+		    krel->bo_index, krel->flags, krel->data,
+		    krel->vor, krel->tor);
+	}
+
+	kpsh = krec->push;
+	for (i = 0; i < krec->nr_push; i++, kpsh++) {
+		kref = krec->buffer + kpsh->bo_index;
+		bo = (void *)(unsigned long)kref->user_priv;
+		bgn = (uint32_t *)((char *)bo->map + kpsh->offset);
+		end = bgn + (kpsh->length /4);
+
+		err("ch%d: psh %08x %010llx %010llx\n", chid, kpsh->bo_index,
+		    (unsigned long long)kpsh->offset,
+		    (unsigned long long)(kpsh->offset + kpsh->length));
+		while (bgn < end)
+			err("\t0x%08x\n", *bgn++);
+	}
+}
+
+static int
+pushbuf_submit(struct nouveau_pushbuf *push, struct nouveau_object *chan)
+{
+	struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(push);
+	struct nouveau_pushbuf_krec *krec = nvpb->list;
+	struct nouveau_device *dev = push->client->device;
+	struct drm_nouveau_gem_pushbuf_bo_presumed *info;
+	struct drm_nouveau_gem_pushbuf_bo *kref;
+	struct drm_nouveau_gem_pushbuf req;
+	struct nouveau_fifo *fifo = chan->data;
+	struct nouveau_bo *bo;
+	int krec_id = 0;
+	int ret = 0, i;
+
+	if (chan->oclass != NOUVEAU_FIFO_CHANNEL_CLASS)
+		return -EINVAL;
+
+	if (push->kick_notify)
+		push->kick_notify(push);
+
+	nouveau_pushbuf_data(push, NULL, 0, 0);
+
+	while (krec && krec->nr_push) {
+		req.channel = fifo->channel;
+		req.nr_buffers = krec->nr_buffer;
+		req.buffers = (uint64_t)(unsigned long)krec->buffer;
+		req.nr_relocs = krec->nr_reloc;
+		req.nr_push = krec->nr_push;
+		req.relocs = (uint64_t)(unsigned long)krec->reloc;
+		req.push = (uint64_t)(unsigned long)krec->push;
+		req.suffix0 = nvpb->suffix0;
+		req.suffix1 = nvpb->suffix1;
+
+		if (dbg_on(0))
+			pushbuf_dump(krec, krec_id++, fifo->channel);
+
+#ifndef SIMULATE
+		do {
+			ret = drmCommandWriteRead(dev->fd,
+						  DRM_NOUVEAU_GEM_PUSHBUF,
+						  &req, sizeof(req));
+		} while (ret == -EAGAIN);
+		nvpb->suffix0 = req.suffix0;
+		nvpb->suffix1 = req.suffix1;
+		dev->vram_limit = (req.vram_available * 80) / 100;
+		dev->gart_limit = (req.gart_available * 80) / 100;
+#else
+		if (dbg_on(31))
+			ret = -EINVAL;
+#endif
+
+		if (ret) {
+			err("kernel rejected pushbuf: %s\n", strerror(-ret));
+			pushbuf_dump(krec, krec_id++, fifo->channel);
+			break;
+		}
+
+		kref = krec->buffer;
+		for (i = 0; i < krec->nr_buffer; i++, kref++) {
+			bo = (void *)(unsigned long)kref->user_priv;
+
+			info = &kref->presumed;
+			if (!info->valid) {
+				bo->flags &= ~NOUVEAU_BO_APER;
+				if (info->domain == NOUVEAU_GEM_DOMAIN_VRAM)
+					bo->flags |= NOUVEAU_BO_VRAM;
+				else
+					bo->flags |= NOUVEAU_BO_GART;
+				bo->offset = info->offset;
+			}
+
+			if (kref->write_domains)
+				nouveau_bo(bo)->access |= NOUVEAU_BO_WR;
+			if (kref->read_domains)
+				nouveau_bo(bo)->access |= NOUVEAU_BO_RD;
+		}
+
+		krec = krec->next;
+	}
+
+	return ret;
+}
+
+static int
+pushbuf_flush(struct nouveau_pushbuf *push)
+{
+	struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(push);
+	struct nouveau_pushbuf_krec *krec = nvpb->krec;
+	struct drm_nouveau_gem_pushbuf_bo *kref;
+	struct nouveau_bufctx *bctx, *btmp;
+	struct nouveau_bo *bo;
+	int ret = 0, i;
+
+	if (push->channel) {
+		ret = pushbuf_submit(push, push->channel);
+	} else {
+		nouveau_pushbuf_data(push, NULL, 0, 0);
+		krec->next = malloc(sizeof(*krec));
+		nvpb->krec = krec->next;
+	}
+
+	kref = krec->buffer;
+	for (i = 0; i < krec->nr_buffer; i++, kref++) {
+		bo = (void *)(unsigned long)kref->user_priv;
+		cli_kref_set(push->client, bo, NULL, NULL);
+		if (push->channel)
+			nouveau_bo_ref(NULL, &bo);
+	}
+
+	krec = nvpb->krec;
+	krec->vram_used = 0;
+	krec->gart_used = 0;
+	krec->nr_buffer = 0;
+	krec->nr_reloc = 0;
+	krec->nr_push = 0;
+
+	DRMLISTFOREACHENTRYSAFE(bctx, btmp, &nvpb->bctx_list, head) {
+		DRMLISTJOIN(&bctx->current, &bctx->pending);
+		DRMINITLISTHEAD(&bctx->current);
+		DRMLISTDELINIT(&bctx->head);
+	}
+
+	return ret;
+}
+
+static void
+pushbuf_refn_fail(struct nouveau_pushbuf *push, int sref, int srel)
+{
+	struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(push);
+	struct nouveau_pushbuf_krec *krec = nvpb->krec;
+	struct drm_nouveau_gem_pushbuf_bo *kref;
+
+	kref = krec->buffer + sref;
+	while (krec->nr_buffer-- > sref) {
+		struct nouveau_bo *bo = (void *)(unsigned long)kref->user_priv;
+		cli_kref_set(push->client, bo, NULL, NULL);
+		nouveau_bo_ref(NULL, &bo);
+		kref++;
+	}
+	krec->nr_buffer = sref;
+	krec->nr_reloc = srel;
+}
+
+static int
+pushbuf_refn(struct nouveau_pushbuf *push, bool retry,
+	     struct nouveau_pushbuf_refn *refs, int nr)
+{
+	struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(push);
+	struct nouveau_pushbuf_krec *krec = nvpb->krec;
+	struct drm_nouveau_gem_pushbuf_bo *kref;
+	int sref = krec->nr_buffer;
+	int ret = 0, i;
+
+	for (i = 0; i < nr; i++) {
+		kref = pushbuf_kref(push, refs[i].bo, refs[i].flags);
+		if (!kref) {
+			ret = -ENOSPC;
+			break;
+		}
+	}
+
+	if (ret) {
+		pushbuf_refn_fail(push, sref, krec->nr_reloc);
+		if (retry) {
+			pushbuf_flush(push);
+			nouveau_pushbuf_space(push, 0, 0, 0);
+			return pushbuf_refn(push, false, refs, nr);
+		}
+	}
+
+	return ret;
+}
+
+static int
+pushbuf_validate(struct nouveau_pushbuf *push, bool retry)
+{
+	struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(push);
+	struct nouveau_pushbuf_krec *krec = nvpb->krec;
+	struct drm_nouveau_gem_pushbuf_bo *kref;
+	struct nouveau_bufctx *bctx = push->bufctx;
+	struct nouveau_bufref *bref;
+	int relocs = bctx ? bctx->relocs * 2: 0;
+	int sref, srel, ret;
+
+	ret = nouveau_pushbuf_space(push, relocs, relocs, 0);
+	if (ret || bctx == NULL)
+		return ret;
+
+	sref = krec->nr_buffer;
+	srel = krec->nr_reloc;
+
+	DRMLISTDEL(&bctx->head);
+	DRMLISTADD(&bctx->head, &nvpb->bctx_list);
+
+	DRMLISTFOREACHENTRY(bref, &bctx->pending, thead) {
+		kref = pushbuf_kref(push, bref->bo, bref->flags);
+		if (!kref) {
+			ret = -ENOSPC;
+			break;
+		}
+
+		if (bref->packet) {
+			pushbuf_krel(push, bref->bo, bref->packet, 0, 0, 0);
+			*push->cur++ = 0;
+			pushbuf_krel(push, bref->bo, bref->data, bref->flags,
+					   bref->vor, bref->tor);
+			*push->cur++ = 0;
+		}
+	}
+
+	DRMLISTJOIN(&bctx->pending, &bctx->current);
+	DRMINITLISTHEAD(&bctx->pending);
+
+	if (ret) {
+		pushbuf_refn_fail(push, sref, srel);
+		if (retry) {
+			pushbuf_flush(push);
+			return pushbuf_validate(push, false);
+		}
+	}
+
+	return 0;
+}
+
+int
+nouveau_pushbuf_new(struct nouveau_client *client, struct nouveau_object *chan,
+		    int nr, uint32_t size, bool immediate,
+		    struct nouveau_pushbuf **ppush)
+{
+	struct nouveau_device *dev = client->device;
+	struct nouveau_fifo *fifo = chan->data;
+	struct nouveau_pushbuf_priv *nvpb;
+	struct nouveau_pushbuf *push;
+	struct drm_nouveau_gem_pushbuf req;
+	int ret;
+
+	if (chan->oclass != NOUVEAU_FIFO_CHANNEL_CLASS)
+		return -EINVAL;
+
+	/* nop pushbuf call, to get the current "return to main" sequence
+	 * we need to append to the pushbuf on early chipsets
+	 */
+	req.channel = fifo->channel;
+	req.nr_push = 0;
+	ret = drmCommandWriteRead(dev->fd, DRM_NOUVEAU_GEM_PUSHBUF,
+				  &req, sizeof(req));
+	if (ret)
+		return ret;
+
+	nvpb = calloc(1, sizeof(*nvpb) + nr * sizeof(*nvpb->bos));
+	if (!nvpb)
+		return -ENOMEM;
+
+#ifndef SIMULATE
+	nvpb->suffix0 = req.suffix0;
+	nvpb->suffix1 = req.suffix1;
+#else
+	nvpb->suffix0 = 0xffffffff;
+	nvpb->suffix1 = 0xffffffff;
+#endif
+	nvpb->krec = calloc(1, sizeof(*nvpb->krec));
+	nvpb->list = nvpb->krec;
+	if (!nvpb->krec) {
+		free(nvpb);
+		return -ENOMEM;
+	}
+
+	push = &nvpb->base;
+	push->client = client;
+	push->channel = immediate ? chan : NULL;
+	push->flags = NOUVEAU_BO_RD;
+	if (fifo->pushbuf & NOUVEAU_GEM_DOMAIN_VRAM) {
+		push->flags |= NOUVEAU_BO_VRAM;
+		nvpb->type   = NOUVEAU_BO_VRAM;
+	}
+	if (fifo->pushbuf & NOUVEAU_GEM_DOMAIN_GART) {
+		push->flags |= NOUVEAU_BO_GART;
+		nvpb->type   = NOUVEAU_BO_GART;
+	}
+	nvpb->type |= NOUVEAU_BO_MAP;
+
+	for (nvpb->bo_nr = 0; nvpb->bo_nr < nr; nvpb->bo_nr++) {
+		ret = nouveau_bo_new(client->device, nvpb->type, 0, size,
+				     NULL, &nvpb->bos[nvpb->bo_nr]);
+		if (ret) {
+			nouveau_pushbuf_del(&push);
+			return ret;
+		}
+	}
+
+	DRMINITLISTHEAD(&nvpb->bctx_list);
+	*ppush = push;
+	return 0;
+}
+
+void
+nouveau_pushbuf_del(struct nouveau_pushbuf **ppush)
+{
+	struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(*ppush);
+	if (nvpb) {
+		struct drm_nouveau_gem_pushbuf_bo *kref;
+		struct nouveau_pushbuf_krec *krec;
+		while ((krec = nvpb->list)) {
+			kref = krec->buffer;
+			while (krec->nr_buffer--) {
+				unsigned long priv = kref++->user_priv;
+				struct nouveau_bo *bo = (void *)priv;
+				cli_kref_set(nvpb->base.client, bo, NULL, NULL);
+				nouveau_bo_ref(NULL, &bo);
+			}
+			nvpb->list = krec->next;
+			free(krec);
+		}
+		while (nvpb->bo_nr--)
+			nouveau_bo_ref(NULL, &nvpb->bos[nvpb->bo_nr]);
+		nouveau_bo_ref(NULL, &nvpb->bo);
+		free(nvpb);
+	}
+	*ppush = NULL;
+}
+
+struct nouveau_bufctx *
+nouveau_pushbuf_bufctx(struct nouveau_pushbuf *push, struct nouveau_bufctx *ctx)
+{
+	struct nouveau_bufctx *prev = push->bufctx;
+	push->bufctx = ctx;
+	return prev;
+}
+
+int
+nouveau_pushbuf_space(struct nouveau_pushbuf *push,
+		      uint32_t dwords, uint32_t relocs, uint32_t pushes)
+{
+	struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(push);
+	struct nouveau_pushbuf_krec *krec = nvpb->krec;
+	struct nouveau_client *client = push->client;
+	struct nouveau_bo *bo = NULL;
+	bool flushed = false;
+	int ret = 0;
+
+	/* switch to next buffer if insufficient space in the current one */
+	if (push->cur + dwords >= push->end) {
+		if (nvpb->bo_next < nvpb->bo_nr) {
+			nouveau_bo_ref(nvpb->bos[nvpb->bo_next++], &bo);
+			if (nvpb->bo_next == nvpb->bo_nr && push->channel)
+				nvpb->bo_next = 0;
+		} else {
+			ret = nouveau_bo_new(client->device, nvpb->type, 0,
+					     nvpb->bos[0]->size, NULL, &bo);
+			if (ret)
+				return ret;
+		}
+	}
+
+	/* make sure there's always enough space to queue up the pending
+	 * data in the pushbuf proper
+	 */
+	pushes++;
+
+	/* need to flush if we've run out of space on an immediate pushbuf,
+	 * if the new buffer won't fit, or if the kernel push/reloc limits
+	 * have been hit
+	 */
+	if ((bo && ( push->channel ||
+		    !pushbuf_kref(push, bo, push->flags))) ||
+	    krec->nr_reloc + relocs >= NOUVEAU_GEM_MAX_RELOCS ||
+	    krec->nr_push + pushes >= NOUVEAU_GEM_MAX_PUSH) {
+		if (nvpb->bo && krec->nr_buffer)
+			pushbuf_flush(push);
+		flushed = true;
+	}
+
+	/* if necessary, switch to new buffer */
+	if (bo) {
+		ret = nouveau_bo_map(bo, NOUVEAU_BO_WR, push->client);
+		if (ret)
+			return ret;
+
+		nouveau_pushbuf_data(push, NULL, 0, 0);
+		nouveau_bo_ref(bo, &nvpb->bo);
+		nouveau_bo_ref(NULL, &bo);
+
+		nvpb->bgn = nvpb->bo->map;
+		nvpb->ptr = nvpb->bgn;
+		push->cur = nvpb->bgn;
+		push->end = push->cur + (nvpb->bo->size / 4);
+		push->end -= 2 + push->rsvd_kick; /* space for suffix */
+	}
+
+	pushbuf_kref(push, nvpb->bo, push->flags);
+	return flushed ? pushbuf_validate(push, false) : 0;
+}
+
+void
+nouveau_pushbuf_data(struct nouveau_pushbuf *push, struct nouveau_bo *bo,
+		     uint64_t offset, uint64_t length)
+{
+	struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(push);
+	struct nouveau_pushbuf_krec *krec = nvpb->krec;
+	struct drm_nouveau_gem_pushbuf_push *kpsh;
+	struct drm_nouveau_gem_pushbuf_bo *kref;
+
+	if (bo != nvpb->bo && nvpb->bgn != push->cur) {
+		if (nvpb->suffix0 || nvpb->suffix1) {
+			*push->cur++ = nvpb->suffix0;
+			*push->cur++ = nvpb->suffix1;
+		}
+
+		nouveau_pushbuf_data(push, nvpb->bo,
+				     (nvpb->bgn - nvpb->ptr) * 4,
+				     (push->cur - nvpb->bgn) * 4);
+		nvpb->bgn = push->cur;
+	}
+
+	if (bo) {
+		kref = cli_kref_get(push->client, bo);
+		kpsh = &krec->push[krec->nr_push++];
+		kpsh->bo_index = kref - krec->buffer;
+		kpsh->offset   = offset;
+		kpsh->length   = length;
+	}
+}
+
+int
+nouveau_pushbuf_refn(struct nouveau_pushbuf *push,
+		     struct nouveau_pushbuf_refn *refs, int nr)
+{
+	return pushbuf_refn(push, true, refs, nr);
+}
+
+void
+nouveau_pushbuf_reloc(struct nouveau_pushbuf *push, struct nouveau_bo *bo,
+		      uint32_t data, uint32_t flags, uint32_t vor, uint32_t tor)
+{
+	*push->cur++ = pushbuf_krel(push, bo, data, flags, vor, tor);
+}
+
+int
+nouveau_pushbuf_validate(struct nouveau_pushbuf *push)
+{
+	return pushbuf_validate(push, true);
+}
+
+uint32_t
+nouveau_pushbuf_refd(struct nouveau_pushbuf *push, struct nouveau_bo *bo)
+{
+	struct drm_nouveau_gem_pushbuf_bo *kref;
+	uint32_t flags = 0;
+
+	if (cli_push_get(push->client, bo) == push) {
+		kref = cli_kref_get(push->client, bo);
+		if (kref->read_domains)
+			flags |= NOUVEAU_BO_RD;
+		if (kref->write_domains)
+			flags |= NOUVEAU_BO_WR;
+	}
+
+	return flags;
+}
+
+int
+nouveau_pushbuf_kick(struct nouveau_pushbuf *push, struct nouveau_object *chan)
+{
+	if (!push->channel)
+		return pushbuf_submit(push, chan);
+	pushbuf_flush(push);
+	return pushbuf_validate(push, false);
+}
commit 0d6350002d74848dd3d1e4d28d514a7ac9d580c9
Author: Ben Skeggs <bskeggs@redhat.com>
Date:   Sat Dec 17 23:37:20 2011 +1000

    lists: add nicer+unsafe foreach, and list join macros
    
    Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
    Signed-off-by: Christoph Bumiller <e0425955@student.tuwien.ac.at>

diff --git a/libdrm_lists.h b/libdrm_lists.h
index 6410f57..8926d8d 100644
--- a/libdrm_lists.h
+++ b/libdrm_lists.h
@@ -78,6 +78,13 @@ typedef struct _drmMMListHead
 
 #define DRMLISTEMPTY(__item) ((__item)->next == (__item))
 
+#define DRMLISTSINGLE(__list) \
+	(!DRMLISTEMPTY(__list) && ((__list)->next == (__list)->prev))
+
+#define DRMLISTFOREACH(__item, __list)					\
+	for ((__item) = (__list)->next;					\
+	     (__item) != (__list); (__item) = (__item)->next)
+
 #define DRMLISTFOREACHSAFE(__item, __temp, __list)			\
 	for ((__item) = (__list)->next, (__temp) = (__item)->next;	\
 	     (__item) != (__list);					\
@@ -87,3 +94,25 @@ typedef struct _drmMMListHead
 	for ((__item) = (__list)->prev, (__temp) = (__item)->prev;	\
 	     (__item) != (__list);					\
 	     (__item) = (__temp), (__temp) = (__item)->prev)
+
+#define DRMLISTFOREACHENTRY(__item, __list, __head)                            \
+	for ((__item) = DRMLISTENTRY(typeof(*__item), (__list)->next, __head); \
+	     &(__item)->__head != (__list);                                    \
+	     (__item) = DRMLISTENTRY(typeof(*__item),                          \
+				     (__item)->__head.next, __head))
+
+#define DRMLISTFOREACHENTRYSAFE(__item, __temp, __list, __head)                \
+	for ((__item) = DRMLISTENTRY(typeof(*__item), (__list)->next, __head), \
+	     (__temp) = DRMLISTENTRY(typeof(*__item),                          \
+				     (__item)->__head.next, __head);           \
+	     &(__item)->__head != (__list);                                    \
+	     (__item) = (__temp),                                              \
+	     (__temp) = DRMLISTENTRY(typeof(*__item),                          \
+				     (__temp)->__head.next, __head))
+
+#define DRMLISTJOIN(__list, __join) if (!DRMLISTEMPTY(__list)) {	\
+	(__list)->next->prev = (__join);				\
+	(__list)->prev->next = (__join)->next;				\
+	(__join)->next->prev = (__list)->prev;				\
+	(__join)->next = (__list)->next;				\
+}

------------------------------------------------------------------------------
For Developers, A Lot Can Happen In A Second.
Boundary is the first to Know...and Tell You.
Monitor Your Applications in Ultra-Fine Resolution. Try it FREE!
http://p.sf.net/sfu/Boundary-d2dvs2
--
_______________________________________________
Dri-patches mailing list
Dri-patches@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/dri-patches


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic