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