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

List:       dri-patches
Subject:    drm: Branch 'modesetting-101' - 22 commits
From:       airlied () kemper ! freedesktop ! org (Dave Airlie)
Date:       2007-11-15 5:53:05
Message-ID: 20071115055306.0993A10096 () kemper ! freedesktop ! org
[Download RAW message or body]

bsd-core/drmP.h             |    1 
 bsd-core/drm_internal.h     |    1 
 linux-core/drmP.h           |   10 ---
 linux-core/drm_crtc.c       |    4 +
 linux-core/drm_crtc.h       |    8 --
 linux-core/drm_drv.c        |    6 +-
 linux-core/drm_internal.h   |    1 
 linux-core/drm_sysfs.c      |    2 
 linux-core/i915_compat.c    |  124 +++++++++++++++++++++++++++++++++-----------
 linux-core/i915_drv.c       |   11 +++
 linux-core/intel_crt.c      |    2 
 linux-core/nouveau_fence.c  |    3 -
 shared-core/drm.h           |   10 +++
 shared-core/drm_internal.h  |   40 ++++++++++++++
 shared-core/nouveau_dma.c   |    6 +-
 shared-core/nouveau_dma.h   |    3 -
 shared-core/nouveau_drv.h   |   17 +++++-
 shared-core/nouveau_fifo.c  |  114 ++++++++++++++++++++++++----------------
 shared-core/nouveau_irq.c   |   11 ++-
 shared-core/nouveau_reg.h   |   48 +++++++++++++----
 shared-core/nouveau_state.c |   31 +++++++++++
 shared-core/nv04_fifo.c     |   12 +++-
 shared-core/nv04_graph.c    |    5 +
 shared-core/nv04_instmem.c  |    9 +--
 shared-core/nv10_fifo.c     |   12 +++-
 shared-core/nv10_graph.c    |   11 ++-
 shared-core/nv20_graph.c    |   15 ++++-
 shared-core/nv40_fifo.c     |    4 +
 shared-core/nv50_fifo.c     |    9 +++
 tests/mode/modetest.c       |    4 -
 tests/ttmtest/src/ttmtest.c |   39 +++++++------
 tests/ttmtest/src/xf86dri.c |    1 
 32 files changed, 421 insertions(+), 153 deletions(-)

New commits:
commit 2520d3fd99636e493060d51b1c3287a5faac22bf
Author: Dave Airlie <airlied@linux.ie>
Date:   Thu Nov 15 16:52:04 2007 +1100

    modes: pass type to userspace for preferred showing

diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c
index cad7cd8..5b00c11 100644
--- a/linux-core/drm_crtc.c
+++ b/linux-core/drm_crtc.c
@@ -1076,6 +1076,7 @@ void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out, struct drm_display
 	out->vscan = in->vscan;
 	out->vrefresh = in->vrefresh;
 	out->flags = in->flags;
+	out->type = in->type;
 	strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN);
 	out->name[DRM_DISPLAY_MODE_LEN-1] = 0;
 }
@@ -1106,6 +1107,7 @@ void drm_crtc_convert_umode(struct drm_display_mode *out, struct drm_mode_modein
 	out->vscan = in->vscan;
 	out->vrefresh = in->vrefresh;
 	out->flags = in->flags;
+	out->type = in->type;
 	strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN);
 	out->name[DRM_DISPLAY_MODE_LEN-1] = 0;
 }
@@ -1345,6 +1347,8 @@ int drm_mode_getoutput(struct drm_device *dev,
 	else
 		out_resp->crtc = 0;
 
+	out_resp->crtcs = output->possible_crtcs;
+	out_resp->clones = output->possible_clones;
 	if ((out_resp->count_modes >= mode_count) && mode_count) {
 		copied = 0;
 		list_for_each_entry(mode, &output->modes, head) {
diff --git a/linux-core/drm_crtc.h b/linux-core/drm_crtc.h
index 9dd00b3..0ddefc8 100644
--- a/linux-core/drm_crtc.h
+++ b/linux-core/drm_crtc.h
@@ -64,14 +64,6 @@ enum drm_mode_status {
     MODE_ERROR	= -1	/* error condition */
 };
 
-#define DRM_MODE_TYPE_BUILTIN	(1<<0)
-#define DRM_MODE_TYPE_CLOCK_C	((1<<1) | DRM_MODE_TYPE_BUILTIN)
-#define DRM_MODE_TYPE_CRTC_C	((1<<2) | DRM_MODE_TYPE_BUILTIN)
-#define DRM_MODE_TYPE_PREFERRED	(1<<3)
-#define DRM_MODE_TYPE_DEFAULT	(1<<4)
-#define DRM_MODE_TYPE_USERDEF	(1<<5)
-#define DRM_MODE_TYPE_DRIVER	(1<<6)
-
 #define DRM_MODE_TYPE_CLOCK_CRTC_C (DRM_MODE_TYPE_CLOCK_C | \
 				    DRM_MODE_TYPE_CRTC_C)
 
diff --git a/shared-core/drm.h b/shared-core/drm.h
index e10ceb1..59cbfaf 100644
--- a/shared-core/drm.h
+++ b/shared-core/drm.h
@@ -898,6 +898,14 @@ struct drm_mm_init_arg {
 #define DRM_OUTPUT_NAME_LEN 32
 #define DRM_DISPLAY_MODE_LEN 32
 
+#define DRM_MODE_TYPE_BUILTIN	(1<<0)
+#define DRM_MODE_TYPE_CLOCK_C	((1<<1) | DRM_MODE_TYPE_BUILTIN)
+#define DRM_MODE_TYPE_CRTC_C	((1<<2) | DRM_MODE_TYPE_BUILTIN)
+#define DRM_MODE_TYPE_PREFERRED	(1<<3)
+#define DRM_MODE_TYPE_DEFAULT	(1<<4)
+#define DRM_MODE_TYPE_USERDEF	(1<<5)
+#define DRM_MODE_TYPE_DRIVER	(1<<6)
+
 struct drm_mode_modeinfo {
 
 	unsigned int id;
@@ -909,7 +917,7 @@ struct drm_mode_modeinfo {
 	unsigned int vrefresh; /* vertical refresh * 1000 */
 
 	unsigned int flags;
-
+	unsigned int type;
 	char name[DRM_DISPLAY_MODE_LEN];
 };
 
commit 7136f55faaf3afefe522ec978a4cbc906dace861
Author: Dave Airlie <airlied@linux.ie>
Date:   Thu Nov 15 16:51:48 2007 +1100

    drm: don't remove mappings added by the driver

diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c
index 8313b3e..99eba97 100644
--- a/linux-core/drm_drv.c
+++ b/linux-core/drm_drv.c
@@ -250,8 +250,10 @@ int drm_lastclose(struct drm_device * dev)
 	}
 
 	list_for_each_entry_safe(r_list, list_t, &dev->maplist, head) {
-		drm_rmmap_locked(dev, r_list->map);
-		r_list = NULL;
+		if (!(r_list->map->flags & _DRM_DRIVER)) {
+			drm_rmmap_locked(dev, r_list->map);
+			r_list = NULL;
+		}
 	}
 
 	if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) && dev->queuelist) {
commit 12cbe1365b38ae04ad4979123eb5b4e9538ee533
Author: Dave Airlie <airlied@linux.ie>
Date:   Thu Nov 15 16:51:35 2007 +1100

    intel: fixup || vs |

diff --git a/linux-core/intel_crt.c b/linux-core/intel_crt.c
index d2e1f95..29c2e61 100644
--- a/linux-core/intel_crt.c
+++ b/linux-core/intel_crt.c
@@ -177,7 +177,7 @@ static enum drm_output_status intel_crt_detect(struct drm_output *output)
 {
 	struct drm_device *dev = output->dev;
 	
-	if (IS_I945G(dev)| IS_I945GM(dev) || IS_I965G(dev)) {
+	if (IS_I945G(dev) || IS_I945GM(dev) || IS_I965G(dev)) {
 		if (intel_crt_detect_hotplug(output))
 			return output_status_connected;
 		else
commit d275bb8fb87d8dc23e9a62c5f82627e36c8dc589
Author: Dave Airlie <airlied@linux.ie>
Date:   Thu Nov 15 16:51:15 2007 +1100

    tests: update for new drm interface

diff --git a/tests/mode/modetest.c b/tests/mode/modetest.c
index bf1a516..8f15175 100644
--- a/tests/mode/modetest.c
+++ b/tests/mode/modetest.c
@@ -288,12 +288,12 @@ int testFrameBufferAdd(int fd, drmModeResPtr res)
 
 	printf("\tRemoveing BO\n");
 
-	ret = drmBODestroy(fb, &bo);
+	ret = drmBOUnreference(fb, &bo);
 
 	return 0;
 	
 err_bo:
-	drmBODestroy(fd, &bo);
+	drmBOUnreference(fd, &bo);
 
 err:
 	printf("\tFailed\n");
commit f0fe478c1587780690edc465d957a762e02acc8a
Merge: e1bc147... 62cdc6d...
Author: Dave Airlie <airlied@linux.ie>
Date:   Thu Nov 15 15:04:19 2007 +1100

    Merge branch 'master' into modesetting-101
    
    Conflicts:
    
    	shared-core/i915_dma.c
    	tests/ttmtest/src/ttmtest.c

commit 62cdc6dbb3545d21bc3a68987d0781f277ae6ee4
Author: Dave Airlie <airlied@linux.ie>
Date:   Thu Nov 15 14:43:23 2007 +1100

    i915: remove excess debug output

diff --git a/linux-core/i915_compat.c b/linux-core/i915_compat.c
index e8890f6..e119a99 100644
--- a/linux-core/i915_compat.c
+++ b/linux-core/i915_compat.c
@@ -127,8 +127,6 @@ static void intel_i8xx_setup_flush(struct drm_device *dev)
 	i8xx_private.flush_page = kmap(i8xx_private.page);
 	if (!i8xx_private.flush_page)
 		intel_i8xx_fini_flush(dev);
-
-	DRM_ERROR("i8xx got flush page %p %p\n", i8xx_private.page, i8xx_private.flush_page);
 }
 
 
commit 2cf7ad0d9b2f265537c7030c6f93b4275cb2d051
Author: Stephane Marchesin <marchesin@icps.u-strasbg.fr>
Date:   Thu Nov 15 03:43:22 2007 +0100

    nouveau: Copy the PPC bios to RAMIN on init, that lets us do proper output detection in user space.

diff --git a/shared-core/nouveau_state.c b/shared-core/nouveau_state.c
index 35042cd..57ae924 100644
--- a/shared-core/nouveau_state.c
+++ b/shared-core/nouveau_state.c
@@ -285,6 +285,9 @@ nouveau_card_init(struct drm_device *dev)
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_engine *engine;
 	int ret;
+#if defined(__powerpc__)
+	struct device_node *dn;
+#endif
 
 	DRM_DEBUG("prev state = %d\n", dev_priv->init_state);
 
@@ -304,6 +307,22 @@ nouveau_card_init(struct drm_device *dev)
 	DRM_MEMORYBARRIER();
 #endif
 
+#if defined(__powerpc__)
+	/* if we have an OF card, copy vbios to RAMIN */
+	dn = pci_device_to_OF_node(dev->pdev);
+	if (dn)
+	{
+		int size; 
+		const uint32_t *bios = of_get_property(dn, "NVDA,BMP", &size);
+		if (bios)
+		{
+			int i;
+			for(i=0;i<size;i+=4)
+				NV_WI32(i, bios[i/4]);
+		}
+	}
+#endif
+
 	/* Determine exact chipset we're running on */
 	if (dev_priv->card_type < NV_10)
 		dev_priv->chipset = dev_priv->card_type;
commit 2eee33ace5b647153a7cf20990efd12313cc8472
Author: Dave Airlie <airlied@linux.ie>
Date:   Thu Nov 15 13:29:55 2007 +1100

    intel: add flushing for i8xx chipsets.
    
    Add a nut vs hammer style chipset flush for the i8xx chipsets - reenable TTM
    code paths

diff --git a/linux-core/i915_compat.c b/linux-core/i915_compat.c
index b09cc9f..e8890f6 100644
--- a/linux-core/i915_compat.c
+++ b/linux-core/i915_compat.c
@@ -19,10 +19,15 @@
 #define I915_IFPADDR    0x60
 #define I965_IFPADDR    0x70
 
-static struct _intel_private_compat {
+static struct _i9xx_private_compat {
 	void __iomem *flush_page;
 	struct resource ifp_resource;
-} intel_private;
+} i9xx_private;
+
+static struct _i8xx_private_compat {
+	void *flush_page;
+	struct page *page;
+} i8xx_private;
 
 static void
 intel_compat_align_resource(void *data, struct resource *res,
@@ -35,7 +40,7 @@ intel_compat_align_resource(void *data, struct resource *res,
 static int intel_alloc_chipset_flush_resource(struct pci_dev *pdev)
 {
 	int ret;
-	ret = pci_bus_alloc_resource(pdev->bus, &intel_private.ifp_resource, PAGE_SIZE,
+	ret = pci_bus_alloc_resource(pdev->bus, &i9xx_private.ifp_resource, PAGE_SIZE,
 				     PAGE_SIZE, PCIBIOS_MIN_MEM, 0,
 				     intel_compat_align_resource, pdev);
 	if (ret != 0)
@@ -53,15 +58,15 @@ static void intel_i915_setup_chipset_flush(struct pci_dev *pdev)
 	if (!(temp & 0x1)) {
 		intel_alloc_chipset_flush_resource(pdev);
 
-		pci_write_config_dword(pdev, I915_IFPADDR, (intel_private.ifp_resource.start & 0xffffffff) | 0x1);
+		pci_write_config_dword(pdev, I915_IFPADDR, (i9xx_private.ifp_resource.start & 0xffffffff) | 0x1);
 	} else {
 		temp &= ~1;
 
-		intel_private.ifp_resource.start = temp;
-		intel_private.ifp_resource.end = temp + PAGE_SIZE;
-		ret = request_resource(&iomem_resource, &intel_private.ifp_resource);
+		i9xx_private.ifp_resource.start = temp;
+		i9xx_private.ifp_resource.end = temp + PAGE_SIZE;
+		ret = request_resource(&iomem_resource, &i9xx_private.ifp_resource);
 		if (ret) {
-			intel_private.ifp_resource.start = 0;
+			i9xx_private.ifp_resource.start = 0;
 			printk("Failed inserting resource into tree\n");
 		}
 	}
@@ -79,34 +84,72 @@ static void intel_i965_g33_setup_chipset_flush(struct pci_dev *pdev)
 
 		intel_alloc_chipset_flush_resource(pdev);
 
-		pci_write_config_dword(pdev, I965_IFPADDR + 4, (intel_private.ifp_resource.start >> 32));
-		pci_write_config_dword(pdev, I965_IFPADDR, (intel_private.ifp_resource.start & 0xffffffff) | 0x1);
+		pci_write_config_dword(pdev, I965_IFPADDR + 4, (i9xx_private.ifp_resource.start >> 32));
+		pci_write_config_dword(pdev, I965_IFPADDR, (i9xx_private.ifp_resource.start & 0xffffffff) | 0x1);
 	} else {
 		u64 l64;
 
 		temp_lo &= ~0x1;
 		l64 = ((u64)temp_hi << 32) | temp_lo;
 
-		intel_private.ifp_resource.start = l64;
-		intel_private.ifp_resource.end = l64 + PAGE_SIZE;
-		ret = request_resource(&iomem_resource, &intel_private.ifp_resource);
+		i9xx_private.ifp_resource.start = l64;
+		i9xx_private.ifp_resource.end = l64 + PAGE_SIZE;
+		ret = request_resource(&iomem_resource, &i9xx_private.ifp_resource);
 		if (!ret) {
-			intel_private.ifp_resource.start = 0;
+			i9xx_private.ifp_resource.start = 0;
 			printk("Failed inserting resource into tree\n");
 		}
 	}
 }
 
-void intel_init_chipset_flush_compat(struct drm_device *dev)
+static void intel_i8xx_fini_flush(struct drm_device *dev)
 {
-	struct pci_dev *agp_dev = dev->agp->agp_info.device;
+	kunmap(i8xx_private.page);
+	i8xx_private.flush_page = NULL;
+	unmap_page_from_agp(i8xx_private.page);
+	flush_agp_mappings();
 
-	/* not flush on i8xx */
-	if (!IS_I9XX(dev))
+	__free_page(i8xx_private.page);
+}
+
+static void intel_i8xx_setup_flush(struct drm_device *dev)
+{
+
+	i8xx_private.page = alloc_page(GFP_KERNEL | __GFP_ZERO | GFP_DMA32);
+	if (!i8xx_private.page) {
 		return;
+	}
 
-	intel_private.ifp_resource.name = "GMCH IFPBAR";
-	intel_private.ifp_resource.flags = IORESOURCE_MEM;
+	/* make page uncached */
+	map_page_into_agp(i8xx_private.page);
+	flush_agp_mappings();
+
+	i8xx_private.flush_page = kmap(i8xx_private.page);
+	if (!i8xx_private.flush_page)
+		intel_i8xx_fini_flush(dev);
+
+	DRM_ERROR("i8xx got flush page %p %p\n", i8xx_private.page, i8xx_private.flush_page);
+}
+
+
+static void intel_i8xx_flush_page(struct drm_device *dev)
+{
+	unsigned int *pg = i8xx_private.flush_page;
+	int i;
+
+	/* HAI NUT CAN I HAZ HAMMER?? */
+	for (i = 0; i < 256; i++)
+		*(pg + i) = i;
+	
+	DRM_MEMORYBARRIER();
+}
+
+static void intel_i9xx_setup_flush(struct drm_device *dev)
+{
+	struct pci_dev *agp_dev = dev->agp->agp_info.device;
+
+	i9xx_private.ifp_resource.name = "GMCH IFPBAR";
+	i9xx_private.ifp_resource.flags = IORESOURCE_MEM;
 
 	/* Setup chipset flush for 915 */
 	if (IS_I965G(dev) || IS_G33(dev)) {
@@ -115,26 +158,49 @@ void intel_init_chipset_flush_compat(struct drm_device *dev)
 		intel_i915_setup_chipset_flush(agp_dev);
 	}
 
-	if (intel_private.ifp_resource.start) {
-		intel_private.flush_page = ioremap_nocache(intel_private.ifp_resource.start, PAGE_SIZE);
-		if (!intel_private.flush_page)
+	if (i9xx_private.ifp_resource.start) {
+		i9xx_private.flush_page = ioremap_nocache(i9xx_private.ifp_resource.start, PAGE_SIZE);
+		if (!i9xx_private.flush_page)
 			printk("unable to ioremap flush  page - no chipset flushing");
 	}
 }
 
-void intel_fini_chipset_flush_compat(struct drm_device *dev)
+static void intel_i9xx_fini_flush(struct drm_device *dev)
+{
+	iounmap(i9xx_private.flush_page);
+	release_resource(&i9xx_private.ifp_resource);
+}
+
+static void intel_i9xx_flush_page(struct drm_device *dev)
+{
+	if (i9xx_private.flush_page)
+		writel(1, i9xx_private.flush_page);
+}
+
+void intel_init_chipset_flush_compat(struct drm_device *dev)
 {
 	/* not flush on i8xx */
-	if (!IS_I9XX(dev))
-		return;
+	if (IS_I9XX(dev))	
+		intel_i9xx_setup_flush(dev);
+	else
+		intel_i8xx_setup_flush(dev);
+	
+}
 
-	iounmap(intel_private.flush_page);
-	release_resource(&intel_private.ifp_resource);
+void intel_fini_chipset_flush_compat(struct drm_device *dev)
+{
+	/* not flush on i8xx */
+	if (IS_I9XX(dev))
+		intel_i9xx_fini_flush(dev);
+	else
+		intel_i8xx_fini_flush(dev);
 }
 
 void drm_agp_chipset_flush(struct drm_device *dev)
 {
-	if (intel_private.flush_page)
-		writel(1, intel_private.flush_page);
+	if (IS_I9XX(dev))
+		intel_i9xx_flush_page(dev);
+	else
+		intel_i8xx_flush_page(dev);
 }
 #endif
diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c
index 5bc3c49..4d77dfc 100644
--- a/shared-core/i915_dma.c
+++ b/shared-core/i915_dma.c
@@ -1402,8 +1402,7 @@ int i915_driver_device_is_agp(struct drm_device * dev)
 int i915_driver_firstopen(struct drm_device *dev)
 {
 #ifdef I915_HAVE_BUFFER
-	if (IS_I9XX(dev))
-		drm_bo_driver_init(dev);
+	drm_bo_driver_init(dev);
 #endif
 	return 0;
 }
commit 46235ea4595152d8dd5f016c18c6845a77db30b0
Author: Patrice Mandin <pmandin@caramail.com>
Date:   Wed Nov 14 23:31:59 2007 +0100

    nouveau: nv30: missing ramin init, does it brake other hw?

diff --git a/shared-core/nv20_graph.c b/shared-core/nv20_graph.c
index 797983f..dace7ed 100644
--- a/shared-core/nv20_graph.c
+++ b/shared-core/nv20_graph.c
@@ -432,6 +432,19 @@ static void nv30_31_graph_context_init(struct drm_device *dev,
 	INSTANCE_WR(ctx, 0x385c/4, 0x3f800000);
 	INSTANCE_WR(ctx, 0x3864/4, 0xbf800000);
 	INSTANCE_WR(ctx, 0x386c/4, 0xbf800000);
+
+	/* nv30gl stuff */
+	for (i=0; i<8; i++) {
+		INSTANCE_WR(ctx, (0x4dfc/4)+i, 0x001c527d);
+	}
+	INSTANCE_WR(ctx, 0x4e3c/4, 0x001c527c);
+/* these ones make dma fifo hang
+	INSTANCE_WR(ctx, 0x567c/4, 0x000a0000);
+	INSTANCE_WR(ctx, 0x0878/4, 0x01000000);
+	INSTANCE_WR(ctx, 0x02f4/4, 0x0001ffff);
+
+	INSTANCE_WR(ctx, 0x0028/4, INSTANCE_RD(ctx, 0x0028/4) | 1);
+*/
 }
 
 static void nv34_graph_context_init(struct drm_device *dev,
commit 68cdcda1eaf02353f2ef2d637c6bf1003c849185
Author: Kristian Høgsberg <krh@temari.boston.redhat.com>
Date:   Wed Nov 14 14:28:34 2007 -0500

    Add new shared header file drm_internal.h.
    
    This header file is shared across linux and bsd, but is not installed
    for user space to access.  It's the place to put prototypes and data
    types that aren't platform or chipset specific, but still internal to
    the drm.

diff --git a/bsd-core/drmP.h b/bsd-core/drmP.h
index 8a768f0..9732d50 100644
--- a/bsd-core/drmP.h
+++ b/bsd-core/drmP.h
@@ -108,6 +108,7 @@ typedef struct drm_file drm_file_t;
 #include "drm.h"
 #include "drm_linux_list.h"
 #include "drm_atomic.h"
+#include "drm_internal.h"
 
 #ifdef __FreeBSD__
 #include <opt_drm.h>
diff --git a/bsd-core/drm_internal.h b/bsd-core/drm_internal.h
new file mode 120000
index 0000000..b30ef94
--- /dev/null
+++ b/bsd-core/drm_internal.h
@@ -0,0 +1 @@
+../shared-core/drm_internal.h
\ No newline at end of file
diff --git a/linux-core/drmP.h b/linux-core/drmP.h
index 759d257..356131e 100644
--- a/linux-core/drmP.h
+++ b/linux-core/drmP.h
@@ -83,6 +83,7 @@
 
 #include "drm_os_linux.h"
 #include "drm_hashtab.h"
+#include "drm_internal.h"
 
 struct drm_file;
 
@@ -586,15 +587,6 @@ struct drm_vbl_sig {
 	struct task_struct *task;
 };
 
-/**
- * Drawable information.
- */
-struct drm_drawable_info {
-	unsigned int num_rects;
-	struct drm_clip_rect *rects;
-};
-
-
 /* location of GART table */
 #define DRM_ATI_GART_MAIN 1
 #define DRM_ATI_GART_FB   2
diff --git a/linux-core/drm_internal.h b/linux-core/drm_internal.h
new file mode 120000
index 0000000..b30ef94
--- /dev/null
+++ b/linux-core/drm_internal.h
@@ -0,0 +1 @@
+../shared-core/drm_internal.h
\ No newline at end of file
diff --git a/shared-core/drm_internal.h b/shared-core/drm_internal.h
new file mode 100644
index 0000000..b82a189
--- /dev/null
+++ b/shared-core/drm_internal.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2007 Red Hat, Inc
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 (including the next
+ * paragraph) 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
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/* This header file holds function prototypes and data types that are
+ * internal to the drm (not exported to user space) but shared across
+ * drivers and platforms */
+
+#ifndef __DRM_INTERNAL_H__
+#define __DRM_INTERNAL_H__
+
+/**
+ * Drawable information.
+ */
+struct drm_drawable_info {
+	unsigned int num_rects;
+	struct drm_clip_rect *rects;
+};
+
+#endif
commit 448ccf13ba647a4b649857c661ab9c64bce91795
Author: Stephane Marchesin <marchesin@icps.u-strasbg.fr>
Date:   Wed Nov 14 02:52:55 2007 +0100

    nouveau: adjust the size of the NV34 context. That fixes mobile PPC cards.

diff --git a/shared-core/nv20_graph.c b/shared-core/nv20_graph.c
index a21fde7..797983f 100644
--- a/shared-core/nv20_graph.c
+++ b/shared-core/nv20_graph.c
@@ -29,7 +29,7 @@
 #define NV2A_GRCTX_SIZE (3500*4)
 
 #define NV30_31_GRCTX_SIZE (24392)
-#define NV34_GRCTX_SIZE    (18140)
+#define NV34_GRCTX_SIZE    (22000)
 #define NV35_36_GRCTX_SIZE (22396)
 
 static void nv20_graph_context_init(struct drm_device *dev,
commit f3708b4c04b35b03c28b2297c23eb424206747cd
Author: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
Date:   Tue Nov 13 15:42:08 2007 +0100

    Fix ttmtest.

diff --git a/tests/ttmtest/src/ttmtest.c b/tests/ttmtest/src/ttmtest.c
index 606fb0c..36df242 100644
--- a/tests/ttmtest/src/ttmtest.c
+++ b/tests/ttmtest/src/ttmtest.c
@@ -35,6 +35,7 @@
 
 #include <X11/Xlib.h>
 #include <X11/Xutil.h>
+#include <stdint.h>
 #include <drm/drm.h>
 #include "xf86dri.h"
 #include "xf86drm.h"
@@ -176,13 +177,11 @@ benchmarkBuffer(TinyDRIContext * ctx, unsigned long size,
     /*
      * Test system memory objects.
      */
-
     oldTime = fastrdtsc();
-    BM_CKFATAL(drmBOCreate(ctx->drmFD, 0, size, 0, NULL,
-	    drm_bo_type_dc,
-	    DRM_BO_FLAG_READ |
-	    DRM_BO_FLAG_WRITE |
-			   DRM_BO_FLAG_MEM_LOCAL /*| DRM_BO_FLAG_NO_MOVE*/, 0, &buf));
+    BM_CKFATAL(drmBOCreate(ctx->drmFD, size, 0, NULL,
+			   DRM_BO_FLAG_READ |
+			   DRM_BO_FLAG_WRITE |
+			   DRM_BO_FLAG_MEM_LOCAL, 0, &buf));
     curTime = fastrdtsc();
     *ticks++ = time_diff(oldTime, curTime);
 
@@ -216,12 +215,12 @@ benchmarkBuffer(TinyDRIContext * ctx, unsigned long size,
      * Test TT bound buffer objects.
      */
 
-    BM_CKFATAL(drmGetLock(ctx->drmFD, ctx->hwContext, 0));
     oldTime = fastrdtsc();
-    BM_CKFATAL(drmBOValidate(ctx->drmFD, &buf,
-	    DRM_BO_FLAG_MEM_TT, DRM_BO_MASK_MEM, DRM_BO_HINT_DONT_FENCE));
+    BM_CKFATAL(drmBOSetStatus(ctx->drmFD, &buf,
+			     DRM_BO_FLAG_MEM_TT, 
+			     DRM_BO_MASK_MEM, 
+			      0,0,0));
     curTime = fastrdtsc();
-    BM_CKFATAL(drmUnlock(ctx->drmFD, ctx->hwContext));
     *ticks++ = time_diff(oldTime, curTime);
 
     oldTime = fastrdtsc();
@@ -247,10 +246,9 @@ benchmarkBuffer(TinyDRIContext * ctx, unsigned long size,
 
     BM_CKFATAL(drmBOUnmap(ctx->drmFD, &buf));
 
-    BM_CKFATAL(drmGetLock(ctx->drmFD, ctx->hwContext, 0));
     oldTime = fastrdtsc();
-    BM_CKFATAL(drmBOValidate(ctx->drmFD, &buf,
-	    DRM_BO_FLAG_MEM_LOCAL, DRM_BO_MASK_MEM, DRM_BO_HINT_DONT_FENCE));
+    BM_CKFATAL(drmBOSetStatus(ctx->drmFD, &buf,
+			     DRM_BO_FLAG_MEM_LOCAL, DRM_BO_MASK_MEM, 0, 0,0));
     curTime = fastrdtsc();
     *ticks++ = time_diff(oldTime, curTime);
 
@@ -259,15 +257,18 @@ benchmarkBuffer(TinyDRIContext * ctx, unsigned long size,
      */
 
     oldTime = fastrdtsc();
-    ret = drmBOValidate(ctx->drmFD, &buf,
-	DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_CACHED | DRM_BO_FLAG_FORCE_CACHING,
-	DRM_BO_MASK_MEMTYPE | DRM_BO_FLAG_FORCE_CACHING, DRM_BO_HINT_DONT_FENCE);
+    ret = drmBOSetStatus(ctx->drmFD, &buf,
+			 DRM_BO_FLAG_MEM_TT | 
+			 DRM_BO_FLAG_CACHED | 
+			 DRM_BO_FLAG_FORCE_CACHING,
+			 DRM_BO_MASK_MEMTYPE | 
+			 DRM_BO_FLAG_FORCE_CACHING,
+			 0, 0, 0);
     curTime = fastrdtsc();
-    drmUnlock(ctx->drmFD, ctx->hwContext);
 
     if (ret) {
 	printf("Couldn't bind cached. Probably no support\n");
-	BM_CKFATAL(drmBODestroy(ctx->drmFD, &buf));
+	BM_CKFATAL(drmBOUnreference(ctx->drmFD, &buf));
 	return 1;
     }
     *ticks++ = time_diff(oldTime, curTime);
@@ -295,7 +296,7 @@ benchmarkBuffer(TinyDRIContext * ctx, unsigned long size,
     *ticks++ = time_diff(oldTime, curTime);
 
     BM_CKFATAL(drmBOUnmap(ctx->drmFD, &buf));
-    BM_CKFATAL(drmBODestroy(ctx->drmFD, &buf));
+    BM_CKFATAL(drmBOUnreference(ctx->drmFD, &buf));
 
     return 0;
 }
diff --git a/tests/ttmtest/src/xf86dri.c b/tests/ttmtest/src/xf86dri.c
index ad92504..5491473 100644
--- a/tests/ttmtest/src/xf86dri.c
+++ b/tests/ttmtest/src/xf86dri.c
@@ -45,6 +45,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include <X11/Xlibint.h>
 #include <X11/extensions/Xext.h>
 #include <X11/extensions/extutil.h>
+#include <stdint.h>
 #include "xf86dristr.h"
 
 static XExtensionInfo _xf86dri_info_data;
commit 2d7eb4434f50ab190b530a7ef23e4a361092a33d
Author: Ben Skeggs <skeggsb@gmail.com>
Date:   Wed Nov 14 05:36:20 2007 +1100

    nouveau: Also wait until CACHE1 gets emptied.

diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c
index 3c993f3..d00f193 100644
--- a/shared-core/nouveau_fifo.c
+++ b/shared-core/nouveau_fifo.c
@@ -419,7 +419,9 @@ void nouveau_fifo_free(struct nouveau_channel *chan)
 
 	/* Give the channel a chance to idle, wait 2s (hopefully) */
 	t_start = engine->timer.read(dev);
-	while (NV_READ(chan->get) != NV_READ(chan->put)) {
+	while (NV_READ(chan->get) != NV_READ(chan->put) ||
+	       NV_READ(NV03_PFIFO_CACHE1_GET) !=
+	       NV_READ(NV03_PFIFO_CACHE1_PUT)) {
 		if (engine->timer.read(dev) - t_start > 2000000000ULL) {
 			DRM_ERROR("Failed to idle channel %d before destroy."
 				  "Prepare for strangeness..\n", chan->id);
@@ -427,6 +429,10 @@ void nouveau_fifo_free(struct nouveau_channel *chan)
 		}
 	}
 
+	/*XXX: Maybe should wait for PGRAPH to finish with the stuff it fetched
+	 *     from CACHE1 too?
+	 */
+
 	/* disable the fifo caches */
 	NV_WRITE(NV03_PFIFO_CACHES, 0x00000000);
 	NV_WRITE(NV04_PFIFO_CACHE1_DMA_PUSH, NV_READ(NV04_PFIFO_CACHE1_DMA_PUSH)&(~0x1));
diff --git a/shared-core/nouveau_reg.h b/shared-core/nouveau_reg.h
index bc71e5f..7ac02f4 100644
--- a/shared-core/nouveau_reg.h
+++ b/shared-core/nouveau_reg.h
@@ -435,6 +435,7 @@
 #define NV03_PFIFO_CACHE1_PUSH1_CHID_MASK                  0x0000000f
 #define NV10_PFIFO_CACHE1_PUSH1_CHID_MASK                  0x0000001f
 #define NV50_PFIFO_CACHE1_PUSH1_CHID_MASK                  0x0000007f
+#define NV03_PFIFO_CACHE1_PUT                              0x00003210
 #define NV04_PFIFO_CACHE1_DMA_PUSH                         0x00003220
 #define NV04_PFIFO_CACHE1_DMA_FETCH                        0x00003224
 #    define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_8_BYTES         0x00000000
commit 7e4bb6099a492b90374565aa574ba65f19ae2ab2
Author: Ben Skeggs <skeggsb@gmail.com>
Date:   Wed Nov 14 05:11:11 2007 +1100

    Revert "nouveau: stub superioctl"
    
    This reverts commit 2370ded79b4176d76cda1ec5f495fd33c2d566ed.
    
    Err.. didn't mean for that to slip in :)

diff --git a/linux-core/Makefile.kernel b/linux-core/Makefile.kernel
index 92e1eb7..e7c280d 100644
--- a/linux-core/Makefile.kernel
+++ b/linux-core/Makefile.kernel
@@ -23,7 +23,7 @@ i915-objs   := i915_drv.o i915_dma.o i915_irq.o i915_mem.o i915_fence.o \
 		i915_buffer.o i915_compat.o
 nouveau-objs := nouveau_drv.o nouveau_state.o nouveau_fifo.o nouveau_mem.o \
 		nouveau_object.o nouveau_irq.o nouveau_notifier.o nouveau_swmthd.o \
-		nouveau_sgdma.o nouveau_dma.o nouveau_bo.o nouveau_fence.o \
+		nouveau_sgdma.o nouveau_dma.o nouveau_buffer.o nouveau_fence.o \
 		nv04_timer.o \
 		nv04_mc.o nv40_mc.o nv50_mc.o \
 		nv04_fb.o nv10_fb.o nv40_fb.o \
diff --git a/linux-core/nouveau_bo.c b/linux-core/nouveau_bo.c
deleted file mode 100644
index f0b0576..0000000
--- a/linux-core/nouveau_bo.c
+++ /dev/null
@@ -1,265 +0,0 @@
-/*
- * Copyright 2007 Dave Airlied
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, 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 (including the next
- * paragraph) 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
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-/*
- * Authors: Dave Airlied <airlied@linux.ie>
- *	    Ben Skeggs   <darktama@iinet.net.au>
- *	    Jeremy Kolb  <jkolb@brandeis.edu>
- */
-
-#include "drmP.h"
-#include "nouveau_drm.h"
-#include "nouveau_drv.h"
-#include "nouveau_dma.h"
-
-static struct drm_ttm_backend *
-nouveau_bo_create_ttm_backend_entry(struct drm_device * dev)
-{
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-
-	switch (dev_priv->gart_info.type) {
-	case NOUVEAU_GART_AGP:
-		return drm_agp_init_ttm(dev);
-	case NOUVEAU_GART_SGDMA:
-		return nouveau_sgdma_init_ttm(dev);
-	default:
-		DRM_ERROR("Unknown GART type %d\n", dev_priv->gart_info.type);
-		break;
-	}
-
-	return NULL;
-}
-
-static int
-nouveau_bo_fence_type(struct drm_buffer_object *bo,
-		      uint32_t *fclass, uint32_t *type)
-{
-	/* When we get called, *fclass is set to the requested fence class */
-
-	if (bo->mem.mask & (DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE))
-		*type = 3;
-	else
-		*type = 1;
-	return 0;
-
-}
-
-static int
-nouveau_bo_invalidate_caches(struct drm_device *dev, uint64_t buffer_flags)
-{
-	/* We'll do this from user space. */
-	return 0;
-}
-
-static int
-nouveau_bo_init_mem_type(struct drm_device *dev, uint32_t type,
-			 struct drm_mem_type_manager *man)
-{
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-
-	switch (type) {
-	case DRM_BO_MEM_LOCAL:
-		man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE |
-			     _DRM_FLAG_MEMTYPE_CACHED;
-		man->drm_bus_maptype = 0;
-		break;
-	case DRM_BO_MEM_VRAM:
-		man->flags = _DRM_FLAG_MEMTYPE_FIXED |
-			     _DRM_FLAG_MEMTYPE_MAPPABLE |
-			     _DRM_FLAG_NEEDS_IOREMAP;
-		man->io_addr = NULL;
-		man->drm_bus_maptype = _DRM_FRAME_BUFFER;
-		man->io_offset = drm_get_resource_start(dev, 1);
-		man->io_size = drm_get_resource_len(dev, 1);
-		if (man->io_size > nouveau_mem_fb_amount(dev))
-			man->io_size = nouveau_mem_fb_amount(dev);
-		break;
-	case DRM_BO_MEM_PRIV0:
-		/* Unmappable VRAM */
-		man->flags = _DRM_FLAG_MEMTYPE_CMA;
-		man->drm_bus_maptype = 0;
-		break;
-	case DRM_BO_MEM_TT:
-		switch (dev_priv->gart_info.type) {
-		case NOUVEAU_GART_AGP:
-			man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE |
-				     _DRM_FLAG_MEMTYPE_CSELECT |
-				     _DRM_FLAG_NEEDS_IOREMAP;
-			man->drm_bus_maptype = _DRM_AGP;
-			break;
-		case NOUVEAU_GART_SGDMA:
-			man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE |
-				     _DRM_FLAG_MEMTYPE_CSELECT |
-				     _DRM_FLAG_MEMTYPE_CMA;
-			man->drm_bus_maptype = _DRM_SCATTER_GATHER;
-			break;
-		default:
-			DRM_ERROR("Unknown GART type: %d\n",
-				  dev_priv->gart_info.type);
-			return -EINVAL;
-		}
-
-		man->io_offset  = dev_priv->gart_info.aper_base;
-		man->io_size    = dev_priv->gart_info.aper_size;
-		man->io_addr   = NULL;
-		break;
-	default:
-		DRM_ERROR("Unsupported memory type %u\n", (unsigned)type);
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static uint32_t
-nouveau_bo_evict_mask(struct drm_buffer_object *bo)
-{
-	switch (bo->mem.mem_type) {
-	case DRM_BO_MEM_LOCAL:
-	case DRM_BO_MEM_TT:
-		return DRM_BO_FLAG_MEM_LOCAL;
-	default:
-		return DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_CACHED;
-	}
-	return 0;
-}
-
-/* GPU-assisted copy using NV_MEMORY_TO_MEMORY_FORMAT, can access
- * DRM_BO_MEM_{VRAM,PRIV0,TT} directly.
- */
-static int
-nouveau_bo_move_m2mf(struct drm_buffer_object *bo, int evict, int no_wait,
-		struct drm_bo_mem_reg *new_mem)
-{
-	struct drm_device *dev = bo->dev;
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_drm_channel *dchan = &dev_priv->channel;
-	struct drm_bo_mem_reg *old_mem = &bo->mem;
-	uint32_t srch, dsth, page_count;
-
-	/* Can happen during init/takedown */
-	if (!dchan->chan)
-		return -EINVAL;
-
-	srch = old_mem->mem_type == DRM_BO_MEM_TT ? NvDmaTT : NvDmaFB;
-	dsth = new_mem->mem_type == DRM_BO_MEM_TT ? NvDmaTT : NvDmaFB;
-	if (srch != dchan->m2mf_dma_source || dsth != dchan->m2mf_dma_destin) {
-		dchan->m2mf_dma_source = srch;
-		dchan->m2mf_dma_destin = dsth;
-
-		BEGIN_RING(NvSubM2MF,
-			   NV_MEMORY_TO_MEMORY_FORMAT_SET_DMA_SOURCE, 2);
-		OUT_RING  (dchan->m2mf_dma_source);
-		OUT_RING  (dchan->m2mf_dma_destin);
-	}
-
-	page_count = new_mem->num_pages;
-	while (page_count) {
-		int line_count = (page_count > 2047) ? 2047 : page_count;
-
-		BEGIN_RING(NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
-		OUT_RING  (old_mem->mm_node->start << PAGE_SHIFT);
-		OUT_RING  (new_mem->mm_node->start << PAGE_SHIFT);
-		OUT_RING  (PAGE_SIZE); /* src_pitch */
-		OUT_RING  (PAGE_SIZE); /* dst_pitch */
-		OUT_RING  (PAGE_SIZE); /* line_length */
-		OUT_RING  (line_count);
-		OUT_RING  ((1<<8)|(1<<0));
-		OUT_RING  (0);
-		BEGIN_RING(NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_NOP, 1);
-		OUT_RING  (0);
-
-		page_count -= line_count;
-	}
-
-	return drm_bo_move_accel_cleanup(bo, evict, no_wait, dchan->chan->id,
-					 DRM_FENCE_TYPE_EXE, 0, new_mem);
-}
-
-static int
-nouveau_bo_move(struct drm_buffer_object *bo, int evict, int no_wait,
-		struct drm_bo_mem_reg *new_mem)
-{
-	struct drm_bo_mem_reg *old_mem = &bo->mem;
-
-	if (new_mem->mem_type == DRM_BO_MEM_LOCAL) {
-		if (old_mem->mem_type == DRM_BO_MEM_LOCAL)
-			return drm_bo_move_memcpy(bo, evict, no_wait, new_mem);
-#if 0
-		if (!nouveau_bo_move_flipd(bo, evict, no_wait, new_mem))
-#endif
-			return drm_bo_move_memcpy(bo, evict, no_wait, new_mem);
-	}
-	else
-	if (old_mem->mem_type == DRM_BO_MEM_LOCAL) {
-#if 0
-		if (nouveau_bo_move_flips(bo, evict, no_wait, new_mem))
-#endif
-			return drm_bo_move_memcpy(bo, evict, no_wait, new_mem);
-	}
-	else {
-//		if (nouveau_bo_move_m2mf(bo, evict, no_wait, new_mem))
-			return drm_bo_move_memcpy(bo, evict, no_wait, new_mem);
-	}
-	return 0;
-}
-
-static void
-nouveau_bo_flush_ttm(struct drm_ttm *ttm)
-{
-}
-
-static uint32_t nouveau_mem_prios[]  = {
-	DRM_BO_MEM_PRIV0,
-	DRM_BO_MEM_VRAM,
-	DRM_BO_MEM_TT,
-	DRM_BO_MEM_LOCAL
-};
-static uint32_t nouveau_busy_prios[] = {
-	DRM_BO_MEM_TT,
-	DRM_BO_MEM_PRIV0,
-	DRM_BO_MEM_VRAM,
-	DRM_BO_MEM_LOCAL
-};
-
-struct drm_bo_driver nouveau_bo_driver = {
-	.mem_type_prio = nouveau_mem_prios,
-	.mem_busy_prio = nouveau_busy_prios,
-	.num_mem_type_prio = sizeof(nouveau_mem_prios)/sizeof(uint32_t),
-	.num_mem_busy_prio = sizeof(nouveau_busy_prios)/sizeof(uint32_t),
-	.create_ttm_backend_entry = nouveau_bo_create_ttm_backend_entry,
-	.fence_type = nouveau_bo_fence_type,
-	.invalidate_caches = nouveau_bo_invalidate_caches,
-	.init_mem_type = nouveau_bo_init_mem_type,
-	.evict_mask = nouveau_bo_evict_mask,
-	.move = nouveau_bo_move,
-	.ttm_cache_flush= nouveau_bo_flush_ttm
-};
-
-int
-nouveau_bo_validate(struct drm_device *dev, void *data,
-		    struct drm_file *file_priv)
-{
-	DRM_ERROR("unimplemented\n");
-	return -EINVAL;
-}
-
diff --git a/linux-core/nouveau_buffer.c b/linux-core/nouveau_buffer.c
new file mode 100644
index 0000000..c40dff6
--- /dev/null
+++ b/linux-core/nouveau_buffer.c
@@ -0,0 +1,256 @@
+/*
+ * Copyright 2007 Dave Airlied
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 (including the next
+ * paragraph) 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
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+/*
+ * Authors: Dave Airlied <airlied@linux.ie>
+ *	    Ben Skeggs   <darktama@iinet.net.au>
+ *	    Jeremy Kolb  <jkolb@brandeis.edu>
+ */
+
+#include "drmP.h"
+#include "nouveau_drm.h"
+#include "nouveau_drv.h"
+#include "nouveau_dma.h"
+
+static struct drm_ttm_backend *
+nouveau_bo_create_ttm_backend_entry(struct drm_device * dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	switch (dev_priv->gart_info.type) {
+	case NOUVEAU_GART_AGP:
+		return drm_agp_init_ttm(dev);
+	case NOUVEAU_GART_SGDMA:
+		return nouveau_sgdma_init_ttm(dev);
+	default:
+		DRM_ERROR("Unknown GART type %d\n", dev_priv->gart_info.type);
+		break;
+	}
+
+	return NULL;
+}
+
+static int
+nouveau_bo_fence_type(struct drm_buffer_object *bo,
+		      uint32_t *fclass, uint32_t *type)
+{
+	/* When we get called, *fclass is set to the requested fence class */
+
+	if (bo->mem.mask & (DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE))
+		*type = 3;
+	else
+		*type = 1;
+	return 0;
+
+}
+
+static int
+nouveau_bo_invalidate_caches(struct drm_device *dev, uint64_t buffer_flags)
+{
+	/* We'll do this from user space. */
+	return 0;
+}
+
+static int
+nouveau_bo_init_mem_type(struct drm_device *dev, uint32_t type,
+			 struct drm_mem_type_manager *man)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	switch (type) {
+	case DRM_BO_MEM_LOCAL:
+		man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE |
+			     _DRM_FLAG_MEMTYPE_CACHED;
+		man->drm_bus_maptype = 0;
+		break;
+	case DRM_BO_MEM_VRAM:
+		man->flags = _DRM_FLAG_MEMTYPE_FIXED |
+			     _DRM_FLAG_MEMTYPE_MAPPABLE |
+			     _DRM_FLAG_NEEDS_IOREMAP;
+		man->io_addr = NULL;
+		man->drm_bus_maptype = _DRM_FRAME_BUFFER;
+		man->io_offset = drm_get_resource_start(dev, 1);
+		man->io_size = drm_get_resource_len(dev, 1);
+		if (man->io_size > nouveau_mem_fb_amount(dev))
+			man->io_size = nouveau_mem_fb_amount(dev);
+		break;
+	case DRM_BO_MEM_PRIV0:
+		/* Unmappable VRAM */
+		man->flags = _DRM_FLAG_MEMTYPE_CMA;
+		man->drm_bus_maptype = 0;
+		break;
+	case DRM_BO_MEM_TT:
+		switch (dev_priv->gart_info.type) {
+		case NOUVEAU_GART_AGP:
+			man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE |
+				     _DRM_FLAG_MEMTYPE_CSELECT |
+				     _DRM_FLAG_NEEDS_IOREMAP;
+			man->drm_bus_maptype = _DRM_AGP;
+			break;
+		case NOUVEAU_GART_SGDMA:
+			man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE |
+				     _DRM_FLAG_MEMTYPE_CSELECT |
+				     _DRM_FLAG_MEMTYPE_CMA;
+			man->drm_bus_maptype = _DRM_SCATTER_GATHER;
+			break;
+		default:
+			DRM_ERROR("Unknown GART type: %d\n",
+				  dev_priv->gart_info.type);
+			return -EINVAL;
+		}
+
+		man->io_offset  = dev_priv->gart_info.aper_base;
+		man->io_size    = dev_priv->gart_info.aper_size;
+		man->io_addr   = NULL;
+		break;
+	default:
+		DRM_ERROR("Unsupported memory type %u\n", (unsigned)type);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static uint32_t
+nouveau_bo_evict_mask(struct drm_buffer_object *bo)
+{
+	switch (bo->mem.mem_type) {
+	case DRM_BO_MEM_LOCAL:
+	case DRM_BO_MEM_TT:
+		return DRM_BO_FLAG_MEM_LOCAL;
+	default:
+		return DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_CACHED;
+	}
+	return 0;
+}
+
+/* GPU-assisted copy using NV_MEMORY_TO_MEMORY_FORMAT, can access
+ * DRM_BO_MEM_{VRAM,PRIV0,TT} directly.
+ */
+static int
+nouveau_bo_move_m2mf(struct drm_buffer_object *bo, int evict, int no_wait,
+		struct drm_bo_mem_reg *new_mem)
+{
+	struct drm_device *dev = bo->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_drm_channel *dchan = &dev_priv->channel;
+	struct drm_bo_mem_reg *old_mem = &bo->mem;
+	uint32_t srch, dsth, page_count;
+
+	/* Can happen during init/takedown */
+	if (!dchan->chan)
+		return -EINVAL;
+
+	srch = old_mem->mem_type == DRM_BO_MEM_TT ? NvDmaTT : NvDmaFB;
+	dsth = new_mem->mem_type == DRM_BO_MEM_TT ? NvDmaTT : NvDmaFB;
+	if (srch != dchan->m2mf_dma_source || dsth != dchan->m2mf_dma_destin) {
+		dchan->m2mf_dma_source = srch;
+		dchan->m2mf_dma_destin = dsth;
+
+		BEGIN_RING(NvSubM2MF,
+			   NV_MEMORY_TO_MEMORY_FORMAT_SET_DMA_SOURCE, 2);
+		OUT_RING  (dchan->m2mf_dma_source);
+		OUT_RING  (dchan->m2mf_dma_destin);
+	}
+
+	page_count = new_mem->num_pages;
+	while (page_count) {
+		int line_count = (page_count > 2047) ? 2047 : page_count;
+
+		BEGIN_RING(NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
+		OUT_RING  (old_mem->mm_node->start << PAGE_SHIFT);
+		OUT_RING  (new_mem->mm_node->start << PAGE_SHIFT);
+		OUT_RING  (PAGE_SIZE); /* src_pitch */
+		OUT_RING  (PAGE_SIZE); /* dst_pitch */
+		OUT_RING  (PAGE_SIZE); /* line_length */
+		OUT_RING  (line_count);
+		OUT_RING  ((1<<8)|(1<<0));
+		OUT_RING  (0);
+		BEGIN_RING(NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_NOP, 1);
+		OUT_RING  (0);
+
+		page_count -= line_count;
+	}
+
+	return drm_bo_move_accel_cleanup(bo, evict, no_wait, dchan->chan->id,
+					 DRM_FENCE_TYPE_EXE, 0, new_mem);
+}
+
+static int
+nouveau_bo_move(struct drm_buffer_object *bo, int evict, int no_wait,
+		struct drm_bo_mem_reg *new_mem)
+{
+	struct drm_bo_mem_reg *old_mem = &bo->mem;
+
+	if (new_mem->mem_type == DRM_BO_MEM_LOCAL) {
+		if (old_mem->mem_type == DRM_BO_MEM_LOCAL)
+			return drm_bo_move_memcpy(bo, evict, no_wait, new_mem);
+#if 0
+		if (!nouveau_bo_move_flipd(bo, evict, no_wait, new_mem))
+#endif
+			return drm_bo_move_memcpy(bo, evict, no_wait, new_mem);
+	}
+	else
+	if (old_mem->mem_type == DRM_BO_MEM_LOCAL) {
+#if 0
+		if (nouveau_bo_move_flips(bo, evict, no_wait, new_mem))
+#endif
+			return drm_bo_move_memcpy(bo, evict, no_wait, new_mem);
+	}
+	else {
+//		if (nouveau_bo_move_m2mf(bo, evict, no_wait, new_mem))
+			return drm_bo_move_memcpy(bo, evict, no_wait, new_mem);
+	}
+	return 0;
+}
+
+static void
+nouveau_bo_flush_ttm(struct drm_ttm *ttm)
+{
+}
+
+static uint32_t nouveau_mem_prios[]  = {
+	DRM_BO_MEM_PRIV0,
+	DRM_BO_MEM_VRAM,
+	DRM_BO_MEM_TT,
+	DRM_BO_MEM_LOCAL
+};
+static uint32_t nouveau_busy_prios[] = {
+	DRM_BO_MEM_TT,
+	DRM_BO_MEM_PRIV0,
+	DRM_BO_MEM_VRAM,
+	DRM_BO_MEM_LOCAL
+};
+
+struct drm_bo_driver nouveau_bo_driver = {
+	.mem_type_prio = nouveau_mem_prios,
+	.mem_busy_prio = nouveau_busy_prios,
+	.num_mem_type_prio = sizeof(nouveau_mem_prios)/sizeof(uint32_t),
+	.num_mem_busy_prio = sizeof(nouveau_busy_prios)/sizeof(uint32_t),
+	.create_ttm_backend_entry = nouveau_bo_create_ttm_backend_entry,
+	.fence_type = nouveau_bo_fence_type,
+	.invalidate_caches = nouveau_bo_invalidate_caches,
+	.init_mem_type = nouveau_bo_init_mem_type,
+	.evict_mask = nouveau_bo_evict_mask,
+	.move = nouveau_bo_move,
+	.ttm_cache_flush= nouveau_bo_flush_ttm
+};
diff --git a/shared-core/nouveau_drm.h b/shared-core/nouveau_drm.h
index 3a9a529..3bf4008 100644
--- a/shared-core/nouveau_drm.h
+++ b/shared-core/nouveau_drm.h
@@ -25,7 +25,7 @@
 #ifndef __NOUVEAU_DRM_H__
 #define __NOUVEAU_DRM_H__
 
-#define NOUVEAU_DRM_HEADER_PATCHLEVEL 11
+#define NOUVEAU_DRM_HEADER_PATCHLEVEL 10
 
 struct drm_nouveau_channel_alloc {
 	uint32_t     fb_ctxdma_handle;
@@ -117,9 +117,6 @@ struct drm_nouveau_setparam {
 	uint64_t value;
 };
 
-struct drm_nouveau_bo_validate {
-};
-
 enum nouveau_card_type {
 	NV_UNKNOWN =0,
 	NV_04      =4,
@@ -159,6 +156,5 @@ struct drm_nouveau_sarea {
 #define DRM_NOUVEAU_GPUOBJ_FREE        0x07
 #define DRM_NOUVEAU_MEM_ALLOC          0x08
 #define DRM_NOUVEAU_MEM_FREE           0x09
-#define DRM_NOUVEAU_BO_VALIDATE        0x0a
 
 #endif /* __NOUVEAU_DRM_H__ */
diff --git a/shared-core/nouveau_drv.h b/shared-core/nouveau_drv.h
index f2d018b..85a0d0b 100644
--- a/shared-core/nouveau_drv.h
+++ b/shared-core/nouveau_drv.h
@@ -34,7 +34,7 @@
 
 #define DRIVER_MAJOR		0
 #define DRIVER_MINOR		0
-#define DRIVER_PATCHLEVEL	11
+#define DRIVER_PATCHLEVEL	10
 
 #define NOUVEAU_FAMILY   0x0000FFFF
 #define NOUVEAU_FLAGS    0xFFFF0000
@@ -572,10 +572,8 @@ extern void nv04_timer_takedown(struct drm_device *);
 extern long nouveau_compat_ioctl(struct file *file, unsigned int cmd,
 				 unsigned long arg);
 
-/* nouveau_bo.c */
+/* nouveau_buffer.c */
 extern struct drm_bo_driver nouveau_bo_driver;
-extern int nouveau_bo_validate(struct drm_device *, void *data,
-			       struct drm_file *);
 
 /* nouveau_fence.c */
 extern struct drm_fence_driver nouveau_fence_driver;
diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c
index cb912f2..3c993f3 100644
--- a/shared-core/nouveau_fifo.c
+++ b/shared-core/nouveau_fifo.c
@@ -585,7 +585,6 @@ struct drm_ioctl_desc nouveau_ioctls[] = {
 	DRM_IOCTL_DEF(DRM_NOUVEAU_GPUOBJ_FREE, nouveau_ioctl_gpuobj_free, DRM_AUTH),
 	DRM_IOCTL_DEF(DRM_NOUVEAU_MEM_ALLOC, nouveau_ioctl_mem_alloc, DRM_AUTH),
 	DRM_IOCTL_DEF(DRM_NOUVEAU_MEM_FREE, nouveau_ioctl_mem_free, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_NOUVEAU_BO_VALIDATE, nouveau_bo_validate, DRM_AUTH),
 };
 
 int nouveau_max_ioctl = DRM_ARRAY_SIZE(nouveau_ioctls);
diff --git a/shared-core/nouveau_state.c b/shared-core/nouveau_state.c
index 82a04b5..35042cd 100644
--- a/shared-core/nouveau_state.c
+++ b/shared-core/nouveau_state.c
@@ -290,7 +290,7 @@ nouveau_card_init(struct drm_device *dev)
 
 	if (dev_priv->init_state == NOUVEAU_CARD_INIT_DONE)
 		return 0;
-	dev_priv->ttm = 1;
+	dev_priv->ttm = 0;
 
 	/* Map any PCI resources we need on the card */
 	ret = nouveau_init_card_mappings(dev);
commit eb5487b9ca1d7ce60d5ddc784089d91cf176f439
Merge: 2370ded... 7c1e59f...
Author: Ben Skeggs <skeggsb@gmail.com>
Date:   Wed Nov 14 05:09:07 2007 +1100

    Merge branch 'fifo-cleanup' into upstream-master

commit 7c1e59fb0c5043d3d369f5feb8e195a6a3da3457
Author: Ben Skeggs <skeggsb@gmail.com>
Date:   Wed Nov 14 04:24:36 2007 +1100

    nouveau: Attempt to wait for channel idle before we destroy it.

diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c
index 7e109ad..3c993f3 100644
--- a/shared-core/nouveau_fifo.c
+++ b/shared-core/nouveau_fifo.c
@@ -402,9 +402,31 @@ void nouveau_fifo_free(struct nouveau_channel *chan)
 	struct drm_device *dev = chan->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_engine *engine = &dev_priv->Engine;
+	uint64_t t_start;
 
 	DRM_INFO("%s: freeing fifo %d\n", __func__, chan->id);
 
+	/* Disable channel switching, if this channel isn't currenly
+	 * active re-enable it if there's still pending commands.
+	 * We really should do a manual context switch here, but I'm
+	 * not sure I trust our ability to do this reliably yet..
+	 */
+	NV_WRITE(NV03_PFIFO_CACHES, 0);
+	if (engine->fifo.channel_id(dev) != chan->id &&
+	    NV_READ(chan->get) != NV_READ(chan->put)) {
+		NV_WRITE(NV03_PFIFO_CACHES, 1);
+	}
+
+	/* Give the channel a chance to idle, wait 2s (hopefully) */
+	t_start = engine->timer.read(dev);
+	while (NV_READ(chan->get) != NV_READ(chan->put)) {
+		if (engine->timer.read(dev) - t_start > 2000000000ULL) {
+			DRM_ERROR("Failed to idle channel %d before destroy."
+				  "Prepare for strangeness..\n", chan->id);
+			break;
+		}
+	}
+
 	/* disable the fifo caches */
 	NV_WRITE(NV03_PFIFO_CACHES, 0x00000000);
 	NV_WRITE(NV04_PFIFO_CACHE1_DMA_PUSH, NV_READ(NV04_PFIFO_CACHE1_DMA_PUSH)&(~0x1));
commit 53ab6026cfb20bfdf34b245e41af424be62941a8
Author: Ben Skeggs <skeggsb@gmail.com>
Date:   Wed Nov 14 04:15:13 2007 +1100

    nouveau: Use "new" NV40 USER control regs.
    
    Probably entirely pointless, but a simple change in any case.

diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c
index 45b8211..7e109ad 100644
--- a/shared-core/nouveau_fifo.c
+++ b/shared-core/nouveau_fifo.c
@@ -295,12 +295,19 @@ nouveau_fifo_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret,
 	DRM_INFO("Allocating FIFO number %d\n", channel);
 
 	/* Locate channel's user control regs */
-	if (dev_priv->card_type < NV_50) {
+	if (dev_priv->card_type < NV_40) {
 		chan->user = NV03_USER(channel);
 		chan->user_size = NV03_USER_SIZE;
 		chan->put = NV03_USER_DMA_PUT(channel);
 		chan->get = NV03_USER_DMA_GET(channel);
 		chan->ref_cnt = NV03_USER_REF_CNT(channel);
+	} else
+	if (dev_priv->card_type < NV_50) {
+		chan->user = NV40_USER(channel);
+		chan->user_size = NV40_USER_SIZE;
+		chan->put = NV40_USER_DMA_PUT(channel);
+		chan->get = NV40_USER_DMA_GET(channel);
+		chan->ref_cnt = NV40_USER_REF_CNT(channel);
 	} else {
 		chan->user = NV50_USER(channel);
 		chan->user_size = NV50_USER_SIZE;
commit 7246a33dd104903bc9227628270712ea9e6168d8
Author: Ben Skeggs <skeggsb@gmail.com>
Date:   Wed Nov 14 04:05:48 2007 +1100

    nouveau: store user control reg offsets in channel struct

diff --git a/linux-core/nouveau_fence.c b/linux-core/nouveau_fence.c
index b3e81a8..4e624a7 100644
--- a/linux-core/nouveau_fence.c
+++ b/linux-core/nouveau_fence.c
@@ -79,6 +79,7 @@ nouveau_fence_perform_flush(struct drm_device *dev, uint32_t class)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct drm_fence_class_manager *fc = &dev->fm.fence_class[class];
+	struct nouveau_channel *chan = dev_priv->fifos[class];
 	uint32_t pending_types = 0;
 
 	DRM_DEBUG("class=%d\n", class);
@@ -89,7 +90,7 @@ nouveau_fence_perform_flush(struct drm_device *dev, uint32_t class)
 					      fc->pending_flush);
 
 	if (pending_types) {
-		uint32_t sequence = NV_READ(NV03_FIFO_REGS(class) + 0x48);
+		uint32_t sequence = NV_READ(chan->ref_cnt);
 
 		DRM_DEBUG("got 0x%08x\n", sequence);
 		drm_fence_handler(dev, class, sequence, pending_types, 0);
diff --git a/shared-core/nouveau_dma.c b/shared-core/nouveau_dma.c
index b406c22..dff786d 100644
--- a/shared-core/nouveau_dma.c
+++ b/shared-core/nouveau_dma.c
@@ -133,10 +133,10 @@ nouveau_dma_channel_takedown(struct drm_device *dev)
 
 #define RING_SKIPS 8
 
-#define READ_GET() ((NV_READ(NV03_FIFO_REGS_DMAGET(dchan->chan->id)) -         \
-		     dchan->chan->pushbuf_base) >> 2)
+#define READ_GET() ((NV_READ(dchan->chan->get) -                               \
+		    dchan->chan->pushbuf_base) >> 2)
 #define WRITE_PUT(val) do {                                                    \
-	NV_WRITE(NV03_FIFO_REGS_DMAPUT(dchan->chan->id),                       \
+	NV_WRITE(dchan->chan->put,                                             \
 		 ((val) << 2) + dchan->chan->pushbuf_base);                    \
 } while(0)
 
diff --git a/shared-core/nouveau_dma.h b/shared-core/nouveau_dma.h
index f8df54e..ce3c58c 100644
--- a/shared-core/nouveau_dma.h
+++ b/shared-core/nouveau_dma.h
@@ -89,8 +89,7 @@ typedef enum {
 	if (dchan->cur != dchan->put) {                                        \
 		DRM_MEMORYBARRIER();                                           \
 		dchan->put = dchan->cur;                                       \
-		NV_WRITE(NV03_FIFO_REGS_DMAPUT(dchan->chan->id),               \
-			 (dchan->put<<2));                                     \
+		NV_WRITE(dchan->chan->put, dchan->put << 2);                   \
 	}                                                                      \
 } while(0)
 
diff --git a/shared-core/nouveau_drv.h b/shared-core/nouveau_drv.h
index 07bd88e..85a0d0b 100644
--- a/shared-core/nouveau_drv.h
+++ b/shared-core/nouveau_drv.h
@@ -114,6 +114,12 @@ struct nouveau_channel
 	struct mem_block          *pushbuf_mem;
 	uint32_t                   pushbuf_base;
 
+	/* FIFO user control regs */
+	uint32_t user, user_size;
+	uint32_t put;
+	uint32_t get;
+	uint32_t ref_cnt;
+
 	/* Notifier memory */
 	struct mem_block *notifier_block;
 	struct mem_block *notifier_heap;
@@ -225,6 +231,7 @@ struct nouveau_engine {
 	struct nouveau_fifo_engine    fifo;
 };
 
+#define NOUVEAU_MAX_CHANNEL_NR 128
 struct drm_nouveau_private {
 	enum {
 		NOUVEAU_CARD_INIT_DOWN,
@@ -245,7 +252,7 @@ struct drm_nouveau_private {
 	drm_local_map_t *ramin; /* NV40 onwards */
 
 	int fifo_alloc_count;
-	struct nouveau_channel *fifos[NV_MAX_FIFO_NUMBER];
+	struct nouveau_channel *fifos[NOUVEAU_MAX_CHANNEL_NR];
 
 	struct nouveau_engine Engine;
 	struct nouveau_drm_channel channel;
diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c
index 7c24ed2..45b8211 100644
--- a/shared-core/nouveau_fifo.c
+++ b/shared-core/nouveau_fifo.c
@@ -294,6 +294,21 @@ nouveau_fifo_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret,
 
 	DRM_INFO("Allocating FIFO number %d\n", channel);
 
+	/* Locate channel's user control regs */
+	if (dev_priv->card_type < NV_50) {
+		chan->user = NV03_USER(channel);
+		chan->user_size = NV03_USER_SIZE;
+		chan->put = NV03_USER_DMA_PUT(channel);
+		chan->get = NV03_USER_DMA_GET(channel);
+		chan->ref_cnt = NV03_USER_REF_CNT(channel);
+	} else {
+		chan->user = NV50_USER(channel);
+		chan->user_size = NV50_USER_SIZE;
+		chan->put = NV50_USER_DMA_PUT(channel);
+		chan->get = NV50_USER_DMA_GET(channel);
+		chan->ref_cnt = NV50_USER_REF_CNT(channel);
+	}
+
 	/* Allocate space for per-channel fixed notifier memory */
 	ret = nouveau_notifier_init_channel(chan);
 	if (ret) {
@@ -337,14 +352,11 @@ nouveau_fifo_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret,
 		return ret;
 	}
 
-	/* setup channel's default get/put values */
-	if (dev_priv->card_type < NV_50) {
-		NV_WRITE(NV03_FIFO_REGS_DMAPUT(channel), chan->pushbuf_base);
-		NV_WRITE(NV03_FIFO_REGS_DMAGET(channel), chan->pushbuf_base);
-	} else {
-		NV_WRITE(NV50_FIFO_REGS_DMAPUT(channel), chan->pushbuf_base);
-		NV_WRITE(NV50_FIFO_REGS_DMAGET(channel), chan->pushbuf_base);
-	}
+	/* setup channel's default get/put values
+	 * XXX: quite possibly extremely pointless..
+	 */
+	NV_WRITE(chan->get, chan->pushbuf_base);
+	NV_WRITE(chan->put, chan->pushbuf_base);
 
 	/* If this is the first channel, setup PFIFO ourselves.  For any
 	 * other case, the GPU will handle this when it switches contexts.
@@ -393,14 +405,12 @@ void nouveau_fifo_free(struct nouveau_channel *chan)
 	NV_WRITE(NV04_PFIFO_CACHE1_PULL0, 0x00000000);
 
 	/* stop the fifo, otherwise it could be running and
-	 * it will crash when removing gpu objects */
-	if (dev_priv->card_type < NV_50) {
-		NV_WRITE(NV03_FIFO_REGS_DMAPUT(chan->id), chan->pushbuf_base);
-		NV_WRITE(NV03_FIFO_REGS_DMAGET(chan->id), chan->pushbuf_base);
-	} else {
-		NV_WRITE(NV50_FIFO_REGS_DMAPUT(chan->id), chan->pushbuf_base);
-		NV_WRITE(NV50_FIFO_REGS_DMAGET(chan->id), chan->pushbuf_base);
-	}
+	 * it will crash when removing gpu objects
+	 *XXX: from real-world evidence, absolutely useless..
+	 */
+	NV_WRITE(chan->get, chan->pushbuf_base);
+	NV_WRITE(chan->put, chan->pushbuf_base);
+
 	// FIXME XXX needs more code
 
 	engine->fifo.destroy_context(chan);
@@ -495,14 +505,8 @@ static int nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data,
 
 	/* make the fifo available to user space */
 	/* first, the fifo control regs */
-	init->ctrl = dev_priv->mmio->offset;
-	if (dev_priv->card_type < NV_50) {
-		init->ctrl      += NV03_FIFO_REGS(init->channel);
-		init->ctrl_size  = NV03_FIFO_REGS_SIZE;
-	} else {
-		init->ctrl      += NV50_FIFO_REGS(init->channel);
-		init->ctrl_size  = NV50_FIFO_REGS_SIZE;
-	}
+	init->ctrl = dev_priv->mmio->offset + chan->user;
+	init->ctrl_size = chan->user_size;
 	res = drm_addmap(dev, init->ctrl, init->ctrl_size, _DRM_REGISTERS,
 			 0, &chan->regs);
 	if (res != 0)
diff --git a/shared-core/nouveau_reg.h b/shared-core/nouveau_reg.h
index e097e01..bc71e5f 100644
--- a/shared-core/nouveau_reg.h
+++ b/shared-core/nouveau_reg.h
@@ -45,16 +45,40 @@
 #define NV_CLASS_NULL                                      0x00000030
 #define NV_CLASS_DMA_IN_MEMORY                             0x0000003D
 
+#define NV03_USER(i)                             (0x00800000+(i*NV03_USER_SIZE))
+#define NV03_USER__SIZE                                                       16
+#define NV10_USER__SIZE                                                       32
+#define NV03_USER_SIZE                                                0x00010000
+#define NV03_USER_DMA_PUT(i)                     (0x00800040+(i*NV03_USER_SIZE))
+#define NV03_USER_DMA_PUT__SIZE                                               16
+#define NV10_USER_DMA_PUT__SIZE                                               32
+#define NV03_USER_DMA_GET(i)                     (0x00800044+(i*NV03_USER_SIZE))
+#define NV03_USER_DMA_GET__SIZE                                               16
+#define NV10_USER_DMA_GET__SIZE                                               32
+#define NV03_USER_REF_CNT(i)                     (0x00800048+(i*NV03_USER_SIZE))
+#define NV03_USER_REF_CNT__SIZE                                               16
+#define NV10_USER_REF_CNT__SIZE                                               32
+
+#define NV40_USER(i)                             (0x00c00000+(i*NV40_USER_SIZE))
+#define NV40_USER_SIZE                                                0x00001000
+#define NV40_USER_DMA_PUT(i)                     (0x00c00040+(i*NV40_USER_SIZE))
+#define NV40_USER_DMA_PUT__SIZE                                               32
+#define NV40_USER_DMA_GET(i)                     (0x00c00044+(i*NV40_USER_SIZE))
+#define NV40_USER_DMA_GET__SIZE                                               32
+#define NV40_USER_REF_CNT(i)                     (0x00c00048+(i*NV40_USER_SIZE))
+#define NV40_USER_REF_CNT__SIZE                                               32
+
+#define NV50_USER(i)                             (0x00c00000+(i*NV50_USER_SIZE))
+#define NV50_USER_SIZE                                                0x00002000
+#define NV50_USER_DMA_PUT(i)                     (0x00c00040+(i*NV50_USER_SIZE))
+#define NV50_USER_DMA_PUT__SIZE                                              128
+#define NV50_USER_DMA_GET(i)                     (0x00c00044+(i*NV50_USER_SIZE))
+#define NV50_USER_DMA_GET__SIZE                                              128
+/*XXX: I don't think this actually exists.. */
+#define NV50_USER_REF_CNT(i)                     (0x00c00048+(i*NV50_USER_SIZE))
+#define NV50_USER_REF_CNT__SIZE                                              128
+
 #define NV03_FIFO_SIZE                                     0x8000UL
-#define NV_MAX_FIFO_NUMBER                                 128
-#define NV03_FIFO_REGS_SIZE                                0x10000
-#define NV03_FIFO_REGS(i)                                  (0x00800000+i*NV03_FIFO_REGS_SIZE)
-#    define NV03_FIFO_REGS_DMAPUT(i)                       (NV03_FIFO_REGS(i)+0x40)
-#    define NV03_FIFO_REGS_DMAGET(i)                       (NV03_FIFO_REGS(i)+0x44)
-#define NV50_FIFO_REGS_SIZE                                0x2000
-#define NV50_FIFO_REGS(i)                                  (0x00c00000+i*NV50_FIFO_REGS_SIZE)
-#    define NV50_FIFO_REGS_DMAPUT(i)                       (NV50_FIFO_REGS(i)+0x40)
-#    define NV50_FIFO_REGS_DMAGET(i)                       (NV50_FIFO_REGS(i)+0x44)
 
 #define NV03_PMC_BOOT_0                                    0x00000000
 #define NV03_PMC_BOOT_1                                    0x00000004
commit d0904f0f2b87c725d3e67060419c445259bd4a5e
Author: Ben Skeggs <skeggsb@gmail.com>
Date:   Wed Nov 14 03:27:37 2007 +1100

    nouveau: funcs to determine active channel on PFIFO.

diff --git a/shared-core/nouveau_drv.h b/shared-core/nouveau_drv.h
index 8b00726..07bd88e 100644
--- a/shared-core/nouveau_drv.h
+++ b/shared-core/nouveau_drv.h
@@ -193,9 +193,13 @@ struct nouveau_fb_engine {
 struct nouveau_fifo_engine {
 	void *priv;
 
+	int  channels;
+
 	int  (*init)(struct drm_device *);
 	void (*takedown)(struct drm_device *);
 
+	int  (*channel_id)(struct drm_device *);
+
 	int  (*create_context)(struct nouveau_channel *);
 	void (*destroy_context)(struct nouveau_channel *);
 	int  (*load_context)(struct nouveau_channel *);
@@ -364,7 +368,6 @@ extern int  nouveau_ioctl_notifier_free(struct drm_device *, void *data,
 
 /* nouveau_fifo.c */
 extern int  nouveau_fifo_init(struct drm_device *);
-extern int  nouveau_fifo_number(struct drm_device *);
 extern int  nouveau_fifo_ctx_size(struct drm_device *);
 extern void nouveau_fifo_cleanup(struct drm_device *, struct drm_file *);
 extern int  nouveau_fifo_owner(struct drm_device *, struct drm_file *,
@@ -452,12 +455,14 @@ extern int  nv40_fb_init(struct drm_device *);
 extern void nv40_fb_takedown(struct drm_device *);
 
 /* nv04_fifo.c */
+extern int  nv04_fifo_channel_id(struct drm_device *);
 extern int  nv04_fifo_create_context(struct nouveau_channel *);
 extern void nv04_fifo_destroy_context(struct nouveau_channel *);
 extern int  nv04_fifo_load_context(struct nouveau_channel *);
 extern int  nv04_fifo_save_context(struct nouveau_channel *);
 
 /* nv10_fifo.c */
+extern int  nv10_fifo_channel_id(struct drm_device *);
 extern int  nv10_fifo_create_context(struct nouveau_channel *);
 extern void nv10_fifo_destroy_context(struct nouveau_channel *);
 extern int  nv10_fifo_load_context(struct nouveau_channel *);
@@ -473,6 +478,7 @@ extern int  nv40_fifo_save_context(struct nouveau_channel *);
 /* nv50_fifo.c */
 extern int  nv50_fifo_init(struct drm_device *);
 extern void nv50_fifo_takedown(struct drm_device *);
+extern int  nv50_fifo_channel_id(struct drm_device *);
 extern int  nv50_fifo_create_context(struct nouveau_channel *);
 extern void nv50_fifo_destroy_context(struct nouveau_channel *);
 extern int  nv50_fifo_load_context(struct nouveau_channel *);
diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c
index e2cb209..7c24ed2 100644
--- a/shared-core/nouveau_fifo.c
+++ b/shared-core/nouveau_fifo.c
@@ -28,22 +28,6 @@
 #include "nouveau_drm.h"
 
 
-/* returns the number of hw fifos */
-int nouveau_fifo_number(struct drm_device *dev)
-{
-	struct drm_nouveau_private *dev_priv=dev->dev_private;
-	switch(dev_priv->card_type)
-	{
-		case NV_04:
-		case NV_05:
-			return 16;
-		case NV_50:
-			return 128;
-		default:
-			return 32;
-	}
-}
-
 /* returns the size of fifo context */
 int nouveau_fifo_ctx_size(struct drm_device *dev)
 {
@@ -288,12 +272,13 @@ nouveau_fifo_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret,
 	 * (woo, full userspace command submission !)
 	 * When there are no more contexts, you lost
 	 */
-	for(channel=0; channel<nouveau_fifo_number(dev); channel++) {
+	for (channel = 0; channel < engine->fifo.channels; channel++) {
 		if (dev_priv->fifos[channel] == NULL)
 			break;
 	}
+
 	/* no more fifos. you lost. */
-	if (channel==nouveau_fifo_number(dev))
+	if (channel == engine->fifo.channels)
 		return -EINVAL;
 
 	dev_priv->fifos[channel] = drm_calloc(1, sizeof(struct nouveau_channel),
@@ -451,10 +436,11 @@ void nouveau_fifo_free(struct nouveau_channel *chan)
 void nouveau_fifo_cleanup(struct drm_device *dev, struct drm_file *file_priv)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_engine *engine = &dev_priv->Engine;
 	int i;
 
 	DRM_DEBUG("clearing FIFO enables from file_priv\n");
-	for(i = 0; i < nouveau_fifo_number(dev); i++) {
+	for(i = 0; i < engine->fifo.channels; i++) {
 		struct nouveau_channel *chan = dev_priv->fifos[i];
 
 		if (chan && chan->file_priv == file_priv)
@@ -467,8 +453,9 @@ nouveau_fifo_owner(struct drm_device *dev, struct drm_file *file_priv,
 		   int channel)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_engine *engine = &dev_priv->Engine;
 
-	if (channel >= nouveau_fifo_number(dev))
+	if (channel >= engine->fifo.channels)
 		return 0;
 	if (dev_priv->fifos[channel] == NULL)
 		return 0;
diff --git a/shared-core/nouveau_irq.c b/shared-core/nouveau_irq.c
index 43f37ca..500fda2 100644
--- a/shared-core/nouveau_irq.c
+++ b/shared-core/nouveau_irq.c
@@ -68,6 +68,7 @@ static void
 nouveau_fifo_irq_handler(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_engine *engine = &dev_priv->Engine;
 	uint32_t status;
 
 	while ((status = NV_READ(NV03_PFIFO_INTR_0))) {
@@ -75,8 +76,7 @@ nouveau_fifo_irq_handler(struct drm_device *dev)
 
 		NV_WRITE(NV03_PFIFO_CACHES, 0);
 
-		chid = NV_READ(NV03_PFIFO_CACHE1_PUSH1) &
-				(nouveau_fifo_number(dev) - 1);
+		chid = engine->fifo.channel_id(dev);
 		get  = NV_READ(NV03_PFIFO_CACHE1_GET);
 
 		if (status & NV_PFIFO_INTR_CACHE_ERROR) {
@@ -190,6 +190,7 @@ static int
 nouveau_graph_trapped_channel(struct drm_device *dev, int *channel_ret)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_engine *engine = &dev_priv->Engine;
 	int channel;
 
 	if (dev_priv->card_type < NV_10) {
@@ -234,8 +235,7 @@ nouveau_graph_trapped_channel(struct drm_device *dev, int *channel_ret)
 		}
 	}
 
-	if (channel > nouveau_fifo_number(dev) ||
-	    dev_priv->fifos[channel] == NULL) {
+	if (channel > engine->fifo.channels || !dev_priv->fifos[channel]) {
 		DRM_ERROR("AIII, invalid/inactive channel id %d\n", channel);
 		return -EINVAL;
 	}
@@ -365,9 +365,10 @@ static inline void
 nouveau_pgraph_intr_context_switch(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_engine *engine = &dev_priv->Engine;
 	uint32_t chid;
 
-	chid = NV_READ(NV03_PFIFO_CACHE1_PUSH1) & (nouveau_fifo_number(dev)-1);
+	chid = engine->fifo.channel_id(dev);
 	DRM_DEBUG("PGRAPH context switch interrupt channel %x\n", chid);
 
 	switch(dev_priv->card_type) {
diff --git a/shared-core/nouveau_reg.h b/shared-core/nouveau_reg.h
index 43573f2..e097e01 100644
--- a/shared-core/nouveau_reg.h
+++ b/shared-core/nouveau_reg.h
@@ -406,6 +406,11 @@
 #define NV04_PFIFO_CACHE0_PULL1                            0x00003054
 #define NV03_PFIFO_CACHE1_PUSH0                            0x00003200
 #define NV03_PFIFO_CACHE1_PUSH1                            0x00003204
+#define NV03_PFIFO_CACHE1_PUSH1_DMA                            (1<<8)
+#define NV40_PFIFO_CACHE1_PUSH1_DMA                           (1<<16)
+#define NV03_PFIFO_CACHE1_PUSH1_CHID_MASK                  0x0000000f
+#define NV10_PFIFO_CACHE1_PUSH1_CHID_MASK                  0x0000001f
+#define NV50_PFIFO_CACHE1_PUSH1_CHID_MASK                  0x0000007f
 #define NV04_PFIFO_CACHE1_DMA_PUSH                         0x00003220
 #define NV04_PFIFO_CACHE1_DMA_FETCH                        0x00003224
 #    define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_8_BYTES         0x00000000
diff --git a/shared-core/nouveau_state.c b/shared-core/nouveau_state.c
index 610d24e..35042cd 100644
--- a/shared-core/nouveau_state.c
+++ b/shared-core/nouveau_state.c
@@ -116,8 +116,10 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
 		engine->graph.destroy_context	= nv04_graph_destroy_context;
 		engine->graph.load_context	= nv04_graph_load_context;
 		engine->graph.save_context	= nv04_graph_save_context;
+		engine->fifo.channels	= 16;
 		engine->fifo.init	= nouveau_fifo_init;
 		engine->fifo.takedown	= nouveau_stub_takedown;
+		engine->fifo.channel_id		= nv04_fifo_channel_id;
 		engine->fifo.create_context	= nv04_fifo_create_context;
 		engine->fifo.destroy_context	= nv04_fifo_destroy_context;
 		engine->fifo.load_context	= nv04_fifo_load_context;
@@ -143,8 +145,10 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
 		engine->graph.destroy_context	= nv10_graph_destroy_context;
 		engine->graph.load_context	= nv10_graph_load_context;
 		engine->graph.save_context	= nv10_graph_save_context;
+		engine->fifo.channels	= 32;
 		engine->fifo.init	= nouveau_fifo_init;
 		engine->fifo.takedown	= nouveau_stub_takedown;
+		engine->fifo.channel_id		= nv10_fifo_channel_id;
 		engine->fifo.create_context	= nv10_fifo_create_context;
 		engine->fifo.destroy_context	= nv10_fifo_destroy_context;
 		engine->fifo.load_context	= nv10_fifo_load_context;
@@ -170,8 +174,10 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
 		engine->graph.destroy_context	= nv20_graph_destroy_context;
 		engine->graph.load_context	= nv20_graph_load_context;
 		engine->graph.save_context	= nv20_graph_save_context;
+		engine->fifo.channels	= 32;
 		engine->fifo.init	= nouveau_fifo_init;
 		engine->fifo.takedown	= nouveau_stub_takedown;
+		engine->fifo.channel_id		= nv10_fifo_channel_id;
 		engine->fifo.create_context	= nv10_fifo_create_context;
 		engine->fifo.destroy_context	= nv10_fifo_destroy_context;
 		engine->fifo.load_context	= nv10_fifo_load_context;
@@ -197,8 +203,10 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
 		engine->graph.destroy_context	= nv20_graph_destroy_context;
 		engine->graph.load_context	= nv20_graph_load_context;
 		engine->graph.save_context	= nv20_graph_save_context;
+		engine->fifo.channels	= 32;
 		engine->fifo.init	= nouveau_fifo_init;
 		engine->fifo.takedown	= nouveau_stub_takedown;
+		engine->fifo.channel_id		= nv10_fifo_channel_id;
 		engine->fifo.create_context	= nv10_fifo_create_context;
 		engine->fifo.destroy_context	= nv10_fifo_destroy_context;
 		engine->fifo.load_context	= nv10_fifo_load_context;
@@ -224,8 +232,10 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
 		engine->graph.destroy_context	= nv40_graph_destroy_context;
 		engine->graph.load_context	= nv40_graph_load_context;
 		engine->graph.save_context	= nv40_graph_save_context;
+		engine->fifo.channels	= 32;
 		engine->fifo.init	= nv40_fifo_init;
 		engine->fifo.takedown	= nouveau_stub_takedown;
+		engine->fifo.channel_id		= nv10_fifo_channel_id;
 		engine->fifo.create_context	= nv40_fifo_create_context;
 		engine->fifo.destroy_context	= nv40_fifo_destroy_context;
 		engine->fifo.load_context	= nv40_fifo_load_context;
@@ -252,8 +262,10 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
 		engine->graph.destroy_context	= nv50_graph_destroy_context;
 		engine->graph.load_context	= nv50_graph_load_context;
 		engine->graph.save_context	= nv50_graph_save_context;
+		engine->fifo.channels	= 128;
 		engine->fifo.init	= nv50_fifo_init;
 		engine->fifo.takedown	= nv50_fifo_takedown;
+		engine->fifo.channel_id		= nv50_fifo_channel_id;
 		engine->fifo.create_context	= nv50_fifo_create_context;
 		engine->fifo.destroy_context	= nv50_fifo_destroy_context;
 		engine->fifo.load_context	= nv50_fifo_load_context;
diff --git a/shared-core/nv04_fifo.c b/shared-core/nv04_fifo.c
index d172302..230c8e7 100644
--- a/shared-core/nv04_fifo.c
+++ b/shared-core/nv04_fifo.c
@@ -36,6 +36,15 @@
 #define NV04_RAMFC__SIZE 32
 
 int
+nv04_fifo_channel_id(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	return (NV_READ(NV03_PFIFO_CACHE1_PUSH1) &
+			NV03_PFIFO_CACHE1_PUSH1_CHID_MASK);
+}
+
+int
 nv04_fifo_create_context(struct nouveau_channel *chan)
 {
 	struct drm_device *dev = chan->dev;
@@ -84,7 +93,8 @@ nv04_fifo_load_context(struct nouveau_channel *chan)
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	uint32_t tmp;
 
-	NV_WRITE(NV03_PFIFO_CACHE1_PUSH1, (1<<8) | chan->id);
+	NV_WRITE(NV03_PFIFO_CACHE1_PUSH1,
+		 NV03_PFIFO_CACHE1_PUSH1_DMA | chan->id);
 
 	NV_WRITE(NV04_PFIFO_CACHE1_DMA_GET, RAMFC_RD(DMA_GET));
 	NV_WRITE(NV04_PFIFO_CACHE1_DMA_PUT, RAMFC_RD(DMA_PUT));
diff --git a/shared-core/nv04_graph.c b/shared-core/nv04_graph.c
index 04dbf0e..81a6d5c 100644
--- a/shared-core/nv04_graph.c
+++ b/shared-core/nv04_graph.c
@@ -353,6 +353,7 @@ struct graph_state {
 void nouveau_nv04_context_switch(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_engine *engine = &dev_priv->Engine;
 	struct nouveau_channel *next, *last;
 	int chid;
 
@@ -370,7 +371,7 @@ void nouveau_nv04_context_switch(struct drm_device *dev)
 		return;
 	}
 
-	chid = NV_READ(NV03_PFIFO_CACHE1_PUSH1)&(nouveau_fifo_number(dev)-1);
+	chid = engine->fifo.channel_id(dev);
 	next = dev_priv->fifos[chid];
 
 	if (!next) {
@@ -378,7 +379,7 @@ void nouveau_nv04_context_switch(struct drm_device *dev)
 		return;
 	}
 
-	chid = (NV_READ(NV04_PGRAPH_CTX_USER) >> 24) & (nouveau_fifo_number(dev)-1);
+	chid = (NV_READ(NV04_PGRAPH_CTX_USER) >> 24) & (engine->fifo.channels - 1);
 	last = dev_priv->fifos[chid];
 
 	if (!last) {
diff --git a/shared-core/nv04_instmem.c b/shared-core/nv04_instmem.c
index 5696818..804f9a7 100644
--- a/shared-core/nv04_instmem.c
+++ b/shared-core/nv04_instmem.c
@@ -33,6 +33,7 @@ static void
 nv04_instmem_configure_fixed_tables(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_engine *engine = &dev_priv->Engine;
 
 	/* FIFO hash table (RAMHT)
 	 *   use 4k hash table at RAMIN+0x10000
@@ -61,8 +62,8 @@ nv04_instmem_configure_fixed_tables(struct drm_device *dev)
 		case NV_40:
 		case NV_44:
 			dev_priv->ramfc_offset = 0x20000;
-			dev_priv->ramfc_size   = nouveau_fifo_number(dev) *
-				nouveau_fifo_ctx_size(dev);
+			dev_priv->ramfc_size   = engine->fifo.channels *
+						 nouveau_fifo_ctx_size(dev);
 			break;
 		case NV_30:
 		case NV_20:
@@ -72,8 +73,8 @@ nv04_instmem_configure_fixed_tables(struct drm_device *dev)
 		case NV_04:
 		default:
 			dev_priv->ramfc_offset = 0x11400;
-			dev_priv->ramfc_size   = nouveau_fifo_number(dev) *
-				nouveau_fifo_ctx_size(dev);
+			dev_priv->ramfc_size   = engine->fifo.channels *
+						 nouveau_fifo_ctx_size(dev);
 			break;
 	}
 	DRM_DEBUG("RAMFC offset=0x%x, size=%d\n", dev_priv->ramfc_offset,
diff --git a/shared-core/nv10_fifo.c b/shared-core/nv10_fifo.c
index 45d2603..6d50b6c 100644
--- a/shared-core/nv10_fifo.c
+++ b/shared-core/nv10_fifo.c
@@ -37,6 +37,15 @@
 #define NV10_RAMFC__SIZE ((dev_priv->chipset) >= 0x17 ? 64 : 32)
 
 int
+nv10_fifo_channel_id(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	return (NV_READ(NV03_PFIFO_CACHE1_PUSH1) &
+			NV10_PFIFO_CACHE1_PUSH1_CHID_MASK);
+}
+
+int
 nv10_fifo_create_context(struct nouveau_channel *chan)
 {
 	struct drm_device *dev = chan->dev;
@@ -87,7 +96,8 @@ nv10_fifo_load_context(struct nouveau_channel *chan)
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	uint32_t tmp;
 
-	NV_WRITE(NV03_PFIFO_CACHE1_PUSH1            , 0x00000100 | chan->id);
+	NV_WRITE(NV03_PFIFO_CACHE1_PUSH1,
+		 NV03_PFIFO_CACHE1_PUSH1_DMA | chan->id);
 
 	NV_WRITE(NV04_PFIFO_CACHE1_DMA_GET          , RAMFC_RD(DMA_GET));
 	NV_WRITE(NV04_PFIFO_CACHE1_DMA_PUT          , RAMFC_RD(DMA_PUT));
diff --git a/shared-core/nv10_graph.c b/shared-core/nv10_graph.c
index 606fb43..d0c2285 100644
--- a/shared-core/nv10_graph.c
+++ b/shared-core/nv10_graph.c
@@ -692,6 +692,7 @@ int nv10_graph_save_context(struct nouveau_channel *chan)
 void nouveau_nv10_context_switch(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv;
+	struct nouveau_engine *engine;
 	struct nouveau_channel *next, *last;
 	int chid;
 
@@ -708,8 +709,10 @@ void nouveau_nv10_context_switch(struct drm_device *dev)
 		DRM_DEBUG("Invalid drm_nouveau_private->fifos\n");
 		return;
 	}
+	engine = &dev_priv->Engine;
 
-	chid = (NV_READ(NV04_PGRAPH_TRAPPED_ADDR) >> 20)&(nouveau_fifo_number(dev)-1);
+	chid = (NV_READ(NV04_PGRAPH_TRAPPED_ADDR) >> 20) &
+		(engine->fifo.channels - 1);
 	next = dev_priv->fifos[chid];
 
 	if (!next) {
@@ -717,7 +720,8 @@ void nouveau_nv10_context_switch(struct drm_device *dev)
 		return;
 	}
 
-	chid = (NV_READ(NV10_PGRAPH_CTX_USER) >> 24) & (nouveau_fifo_number(dev)-1);
+	chid = (NV_READ(NV10_PGRAPH_CTX_USER) >> 24) & 
+		(engine->fifo.channels - 1);
 	last = dev_priv->fifos[chid];
 
 	if (!last) {
@@ -827,13 +831,14 @@ void nv10_graph_destroy_context(struct nouveau_channel *chan)
 {
 	struct drm_device *dev = chan->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_engine *engine = &dev_priv->Engine;
 	struct graph_state* pgraph_ctx = chan->pgraph_ctx;
 	int chid;
 
 	drm_free(pgraph_ctx, sizeof(*pgraph_ctx), DRM_MEM_DRIVER);
 	chan->pgraph_ctx = NULL;
 
-	chid = (NV_READ(NV10_PGRAPH_CTX_USER) >> 24) & (nouveau_fifo_number(dev)-1);
+	chid = (NV_READ(NV10_PGRAPH_CTX_USER) >> 24) & (engine->fifo.channels - 1);
 
 	/* This code seems to corrupt the 3D pipe, but blob seems to do similar things ????
 	 */
diff --git a/shared-core/nv40_fifo.c b/shared-core/nv40_fifo.c
index 5b3eda0..7f9d5e3 100644
--- a/shared-core/nv40_fifo.c
+++ b/shared-core/nv40_fifo.c
@@ -135,7 +135,9 @@ nv40_fifo_load_context(struct nouveau_channel *chan)
 	NV_WRITE(NV04_PFIFO_DMA_TIMESLICE, tmp);
 
 	/* Set channel active, and in DMA mode */
-	NV_WRITE(NV03_PFIFO_CACHE1_PUSH1  , 0x00010000 | chan->id);
+	NV_WRITE(NV03_PFIFO_CACHE1_PUSH1,
+		 NV03_PFIFO_CACHE1_PUSH1_DMA | chan->id);
+
 	/* Reset DMA_CTL_AT_INFO to INVALID */
 	tmp = NV_READ(NV04_PFIFO_CACHE1_DMA_CTL) & ~(1<<31);
 	NV_WRITE(NV04_PFIFO_CACHE1_DMA_CTL, tmp);
diff --git a/shared-core/nv50_fifo.c b/shared-core/nv50_fifo.c
index f77de6e..c5cde91 100644
--- a/shared-core/nv50_fifo.c
+++ b/shared-core/nv50_fifo.c
@@ -213,6 +213,15 @@ nv50_fifo_takedown(struct drm_device *dev)
 }
 
 int
+nv50_fifo_channel_id(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	return (NV_READ(NV03_PFIFO_CACHE1_PUSH1) &
+			NV50_PFIFO_CACHE1_PUSH1_CHID_MASK);
+}
+
+int
 nv50_fifo_create_context(struct nouveau_channel *chan)
 {
 	struct drm_device *dev = chan->dev;
commit 2370ded79b4176d76cda1ec5f495fd33c2d566ed
Author: Ben Skeggs <skeggsb@gmail.com>
Date:   Fri Nov 9 04:27:23 2007 +1100

    nouveau: stub superioctl

diff --git a/linux-core/Makefile.kernel b/linux-core/Makefile.kernel
index e7c280d..92e1eb7 100644
--- a/linux-core/Makefile.kernel
+++ b/linux-core/Makefile.kernel
@@ -23,7 +23,7 @@ i915-objs   := i915_drv.o i915_dma.o i915_irq.o i915_mem.o i915_fence.o \
 		i915_buffer.o i915_compat.o
 nouveau-objs := nouveau_drv.o nouveau_state.o nouveau_fifo.o nouveau_mem.o \
 		nouveau_object.o nouveau_irq.o nouveau_notifier.o nouveau_swmthd.o \
-		nouveau_sgdma.o nouveau_dma.o nouveau_buffer.o nouveau_fence.o \
+		nouveau_sgdma.o nouveau_dma.o nouveau_bo.o nouveau_fence.o \
 		nv04_timer.o \
 		nv04_mc.o nv40_mc.o nv50_mc.o \
 		nv04_fb.o nv10_fb.o nv40_fb.o \
diff --git a/linux-core/nouveau_bo.c b/linux-core/nouveau_bo.c
new file mode 100644
index 0000000..f0b0576
--- /dev/null
+++ b/linux-core/nouveau_bo.c
@@ -0,0 +1,265 @@
+/*
+ * Copyright 2007 Dave Airlied
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 (including the next
+ * paragraph) 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
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+/*
+ * Authors: Dave Airlied <airlied@linux.ie>
+ *	    Ben Skeggs   <darktama@iinet.net.au>
+ *	    Jeremy Kolb  <jkolb@brandeis.edu>
+ */
+
+#include "drmP.h"
+#include "nouveau_drm.h"
+#include "nouveau_drv.h"
+#include "nouveau_dma.h"
+
+static struct drm_ttm_backend *
+nouveau_bo_create_ttm_backend_entry(struct drm_device * dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	switch (dev_priv->gart_info.type) {
+	case NOUVEAU_GART_AGP:
+		return drm_agp_init_ttm(dev);
+	case NOUVEAU_GART_SGDMA:
+		return nouveau_sgdma_init_ttm(dev);
+	default:
+		DRM_ERROR("Unknown GART type %d\n", dev_priv->gart_info.type);
+		break;
+	}
+
+	return NULL;
+}
+
+static int
+nouveau_bo_fence_type(struct drm_buffer_object *bo,
+		      uint32_t *fclass, uint32_t *type)
+{
+	/* When we get called, *fclass is set to the requested fence class */
+
+	if (bo->mem.mask & (DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE))
+		*type = 3;
+	else
+		*type = 1;
+	return 0;
+
+}
+
+static int
+nouveau_bo_invalidate_caches(struct drm_device *dev, uint64_t buffer_flags)
+{
+	/* We'll do this from user space. */
+	return 0;
+}
+
+static int
+nouveau_bo_init_mem_type(struct drm_device *dev, uint32_t type,
+			 struct drm_mem_type_manager *man)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	switch (type) {
+	case DRM_BO_MEM_LOCAL:
+		man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE |
+			     _DRM_FLAG_MEMTYPE_CACHED;
+		man->drm_bus_maptype = 0;
+		break;
+	case DRM_BO_MEM_VRAM:
+		man->flags = _DRM_FLAG_MEMTYPE_FIXED |
+			     _DRM_FLAG_MEMTYPE_MAPPABLE |
+			     _DRM_FLAG_NEEDS_IOREMAP;
+		man->io_addr = NULL;
+		man->drm_bus_maptype = _DRM_FRAME_BUFFER;
+		man->io_offset = drm_get_resource_start(dev, 1);
+		man->io_size = drm_get_resource_len(dev, 1);
+		if (man->io_size > nouveau_mem_fb_amount(dev))
+			man->io_size = nouveau_mem_fb_amount(dev);
+		break;
+	case DRM_BO_MEM_PRIV0:
+		/* Unmappable VRAM */
+		man->flags = _DRM_FLAG_MEMTYPE_CMA;
+		man->drm_bus_maptype = 0;
+		break;
+	case DRM_BO_MEM_TT:
+		switch (dev_priv->gart_info.type) {
+		case NOUVEAU_GART_AGP:
+			man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE |
+				     _DRM_FLAG_MEMTYPE_CSELECT |
+				     _DRM_FLAG_NEEDS_IOREMAP;
+			man->drm_bus_maptype = _DRM_AGP;
+			break;
+		case NOUVEAU_GART_SGDMA:
+			man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE |
+				     _DRM_FLAG_MEMTYPE_CSELECT |
+				     _DRM_FLAG_MEMTYPE_CMA;
+			man->drm_bus_maptype = _DRM_SCATTER_GATHER;
+			break;
+		default:
+			DRM_ERROR("Unknown GART type: %d\n",
+				  dev_priv->gart_info.type);
+			return -EINVAL;
+		}
+
+		man->io_offset  = dev_priv->gart_info.aper_base;
+		man->io_size    = dev_priv->gart_info.aper_size;
+		man->io_addr   = NULL;
+		break;
+	default:
+		DRM_ERROR("Unsupported memory type %u\n", (unsigned)type);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static uint32_t
+nouveau_bo_evict_mask(struct drm_buffer_object *bo)
+{
+	switch (bo->mem.mem_type) {
+	case DRM_BO_MEM_LOCAL:
+	case DRM_BO_MEM_TT:
+		return DRM_BO_FLAG_MEM_LOCAL;
+	default:
+		return DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_CACHED;
+	}
+	return 0;
+}
+
+/* GPU-assisted copy using NV_MEMORY_TO_MEMORY_FORMAT, can access
+ * DRM_BO_MEM_{VRAM,PRIV0,TT} directly.
+ */
+static int
+nouveau_bo_move_m2mf(struct drm_buffer_object *bo, int evict, int no_wait,
+		struct drm_bo_mem_reg *new_mem)
+{
+	struct drm_device *dev = bo->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_drm_channel *dchan = &dev_priv->channel;
+	struct drm_bo_mem_reg *old_mem = &bo->mem;
+	uint32_t srch, dsth, page_count;
+
+	/* Can happen during init/takedown */
+	if (!dchan->chan)
+		return -EINVAL;
+
+	srch = old_mem->mem_type == DRM_BO_MEM_TT ? NvDmaTT : NvDmaFB;
+	dsth = new_mem->mem_type == DRM_BO_MEM_TT ? NvDmaTT : NvDmaFB;
+	if (srch != dchan->m2mf_dma_source || dsth != dchan->m2mf_dma_destin) {
+		dchan->m2mf_dma_source = srch;
+		dchan->m2mf_dma_destin = dsth;
+
+		BEGIN_RING(NvSubM2MF,
+			   NV_MEMORY_TO_MEMORY_FORMAT_SET_DMA_SOURCE, 2);
+		OUT_RING  (dchan->m2mf_dma_source);
+		OUT_RING  (dchan->m2mf_dma_destin);
+	}
+
+	page_count = new_mem->num_pages;
+	while (page_count) {
+		int line_count = (page_count > 2047) ? 2047 : page_count;
+
+		BEGIN_RING(NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
+		OUT_RING  (old_mem->mm_node->start << PAGE_SHIFT);
+		OUT_RING  (new_mem->mm_node->start << PAGE_SHIFT);
+		OUT_RING  (PAGE_SIZE); /* src_pitch */
+		OUT_RING  (PAGE_SIZE); /* dst_pitch */
+		OUT_RING  (PAGE_SIZE); /* line_length */
+		OUT_RING  (line_count);
+		OUT_RING  ((1<<8)|(1<<0));
+		OUT_RING  (0);
+		BEGIN_RING(NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_NOP, 1);
+		OUT_RING  (0);
+
+		page_count -= line_count;
+	}
+
+	return drm_bo_move_accel_cleanup(bo, evict, no_wait, dchan->chan->id,
+					 DRM_FENCE_TYPE_EXE, 0, new_mem);
+}
+
+static int
+nouveau_bo_move(struct drm_buffer_object *bo, int evict, int no_wait,
+		struct drm_bo_mem_reg *new_mem)
+{
+	struct drm_bo_mem_reg *old_mem = &bo->mem;
+
+	if (new_mem->mem_type == DRM_BO_MEM_LOCAL) {
+		if (old_mem->mem_type == DRM_BO_MEM_LOCAL)
+			return drm_bo_move_memcpy(bo, evict, no_wait, new_mem);
+#if 0
+		if (!nouveau_bo_move_flipd(bo, evict, no_wait, new_mem))
+#endif
+			return drm_bo_move_memcpy(bo, evict, no_wait, new_mem);
+	}
+	else
+	if (old_mem->mem_type == DRM_BO_MEM_LOCAL) {
+#if 0
+		if (nouveau_bo_move_flips(bo, evict, no_wait, new_mem))
+#endif
+			return drm_bo_move_memcpy(bo, evict, no_wait, new_mem);
+	}
+	else {
+//		if (nouveau_bo_move_m2mf(bo, evict, no_wait, new_mem))
+			return drm_bo_move_memcpy(bo, evict, no_wait, new_mem);
+	}
+	return 0;
+}
+
+static void
+nouveau_bo_flush_ttm(struct drm_ttm *ttm)
+{
+}
+
+static uint32_t nouveau_mem_prios[]  = {
+	DRM_BO_MEM_PRIV0,
+	DRM_BO_MEM_VRAM,
+	DRM_BO_MEM_TT,
+	DRM_BO_MEM_LOCAL
+};
+static uint32_t nouveau_busy_prios[] = {
+	DRM_BO_MEM_TT,
+	DRM_BO_MEM_PRIV0,
+	DRM_BO_MEM_VRAM,
+	DRM_BO_MEM_LOCAL
+};
+
+struct drm_bo_driver nouveau_bo_driver = {
+	.mem_type_prio = nouveau_mem_prios,
+	.mem_busy_prio = nouveau_busy_prios,
+	.num_mem_type_prio = sizeof(nouveau_mem_prios)/sizeof(uint32_t),
+	.num_mem_busy_prio = sizeof(nouveau_busy_prios)/sizeof(uint32_t),
+	.create_ttm_backend_entry = nouveau_bo_create_ttm_backend_entry,
+	.fence_type = nouveau_bo_fence_type,
+	.invalidate_caches = nouveau_bo_invalidate_caches,
+	.init_mem_type = nouveau_bo_init_mem_type,
+	.evict_mask = nouveau_bo_evict_mask,
+	.move = nouveau_bo_move,
+	.ttm_cache_flush= nouveau_bo_flush_ttm
+};
+
+int
+nouveau_bo_validate(struct drm_device *dev, void *data,
+		    struct drm_file *file_priv)
+{
+	DRM_ERROR("unimplemented\n");
+	return -EINVAL;
+}
+
diff --git a/linux-core/nouveau_buffer.c b/linux-core/nouveau_buffer.c
deleted file mode 100644
index c40dff6..0000000
--- a/linux-core/nouveau_buffer.c
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * Copyright 2007 Dave Airlied
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, 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 (including the next
- * paragraph) 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
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-/*
- * Authors: Dave Airlied <airlied@linux.ie>
- *	    Ben Skeggs   <darktama@iinet.net.au>
- *	    Jeremy Kolb  <jkolb@brandeis.edu>
- */
-
-#include "drmP.h"
-#include "nouveau_drm.h"
-#include "nouveau_drv.h"
-#include "nouveau_dma.h"
-
-static struct drm_ttm_backend *
-nouveau_bo_create_ttm_backend_entry(struct drm_device * dev)
-{
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-
-	switch (dev_priv->gart_info.type) {
-	case NOUVEAU_GART_AGP:
-		return drm_agp_init_ttm(dev);
-	case NOUVEAU_GART_SGDMA:
-		return nouveau_sgdma_init_ttm(dev);
-	default:
-		DRM_ERROR("Unknown GART type %d\n", dev_priv->gart_info.type);
-		break;
-	}
-
-	return NULL;
-}
-
-static int
-nouveau_bo_fence_type(struct drm_buffer_object *bo,
-		      uint32_t *fclass, uint32_t *type)
-{
-	/* When we get called, *fclass is set to the requested fence class */
-
-	if (bo->mem.mask & (DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE))
-		*type = 3;
-	else
-		*type = 1;
-	return 0;
-
-}
-
-static int
-nouveau_bo_invalidate_caches(struct drm_device *dev, uint64_t buffer_flags)
-{
-	/* We'll do this from user space. */
-	return 0;
-}
-
-static int
-nouveau_bo_init_mem_type(struct drm_device *dev, uint32_t type,
-			 struct drm_mem_type_manager *man)
-{
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-
-	switch (type) {
-	case DRM_BO_MEM_LOCAL:
-		man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE |
-			     _DRM_FLAG_MEMTYPE_CACHED;
-		man->drm_bus_maptype = 0;
-		break;
-	case DRM_BO_MEM_VRAM:
-		man->flags = _DRM_FLAG_MEMTYPE_FIXED |
-			     _DRM_FLAG_MEMTYPE_MAPPABLE |
-			     _DRM_FLAG_NEEDS_IOREMAP;
-		man->io_addr = NULL;
-		man->drm_bus_maptype = _DRM_FRAME_BUFFER;
-		man->io_offset = drm_get_resource_start(dev, 1);
-		man->io_size = drm_get_resource_len(dev, 1);
-		if (man->io_size > nouveau_mem_fb_amount(dev))
-			man->io_size = nouveau_mem_fb_amount(dev);
-		break;
-	case DRM_BO_MEM_PRIV0:
-		/* Unmappable VRAM */
-		man->flags = _DRM_FLAG_MEMTYPE_CMA;
-		man->drm_bus_maptype = 0;
-		break;
-	case DRM_BO_MEM_TT:
-		switch (dev_priv->gart_info.type) {
-		case NOUVEAU_GART_AGP:
-			man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE |
-				     _DRM_FLAG_MEMTYPE_CSELECT |
-				     _DRM_FLAG_NEEDS_IOREMAP;
-			man->drm_bus_maptype = _DRM_AGP;
-			break;
-		case NOUVEAU_GART_SGDMA:
-			man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE |
-				     _DRM_FLAG_MEMTYPE_CSELECT |
-				     _DRM_FLAG_MEMTYPE_CMA;
-			man->drm_bus_maptype = _DRM_SCATTER_GATHER;
-			break;
-		default:
-			DRM_ERROR("Unknown GART type: %d\n",
-				  dev_priv->gart_info.type);
-			return -EINVAL;
-		}
-
-		man->io_offset  = dev_priv->gart_info.aper_base;
-		man->io_size    = dev_priv->gart_info.aper_size;
-		man->io_addr   = NULL;
-		break;
-	default:
-		DRM_ERROR("Unsupported memory type %u\n", (unsigned)type);
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static uint32_t
-nouveau_bo_evict_mask(struct drm_buffer_object *bo)
-{
-	switch (bo->mem.mem_type) {
-	case DRM_BO_MEM_LOCAL:
-	case DRM_BO_MEM_TT:
-		return DRM_BO_FLAG_MEM_LOCAL;
-	default:
-		return DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_CACHED;
-	}
-	return 0;
-}
-
-/* GPU-assisted copy using NV_MEMORY_TO_MEMORY_FORMAT, can access
- * DRM_BO_MEM_{VRAM,PRIV0,TT} directly.
- */
-static int
-nouveau_bo_move_m2mf(struct drm_buffer_object *bo, int evict, int no_wait,
-		struct drm_bo_mem_reg *new_mem)
-{
-	struct drm_device *dev = bo->dev;
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_drm_channel *dchan = &dev_priv->channel;
-	struct drm_bo_mem_reg *old_mem = &bo->mem;
-	uint32_t srch, dsth, page_count;
-
-	/* Can happen during init/takedown */
-	if (!dchan->chan)
-		return -EINVAL;
-
-	srch = old_mem->mem_type == DRM_BO_MEM_TT ? NvDmaTT : NvDmaFB;
-	dsth = new_mem->mem_type == DRM_BO_MEM_TT ? NvDmaTT : NvDmaFB;
-	if (srch != dchan->m2mf_dma_source || dsth != dchan->m2mf_dma_destin) {
-		dchan->m2mf_dma_source = srch;
-		dchan->m2mf_dma_destin = dsth;
-
-		BEGIN_RING(NvSubM2MF,
-			   NV_MEMORY_TO_MEMORY_FORMAT_SET_DMA_SOURCE, 2);
-		OUT_RING  (dchan->m2mf_dma_source);
-		OUT_RING  (dchan->m2mf_dma_destin);
-	}
-
-	page_count = new_mem->num_pages;
-	while (page_count) {
-		int line_count = (page_count > 2047) ? 2047 : page_count;
-
-		BEGIN_RING(NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
-		OUT_RING  (old_mem->mm_node->start << PAGE_SHIFT);
-		OUT_RING  (new_mem->mm_node->start << PAGE_SHIFT);
-		OUT_RING  (PAGE_SIZE); /* src_pitch */
-		OUT_RING  (PAGE_SIZE); /* dst_pitch */
-		OUT_RING  (PAGE_SIZE); /* line_length */
-		OUT_RING  (line_count);
-		OUT_RING  ((1<<8)|(1<<0));
-		OUT_RING  (0);
-		BEGIN_RING(NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_NOP, 1);
-		OUT_RING  (0);
-
-		page_count -= line_count;
-	}
-
-	return drm_bo_move_accel_cleanup(bo, evict, no_wait, dchan->chan->id,
-					 DRM_FENCE_TYPE_EXE, 0, new_mem);
-}
-
-static int
-nouveau_bo_move(struct drm_buffer_object *bo, int evict, int no_wait,
-		struct drm_bo_mem_reg *new_mem)
-{
-	struct drm_bo_mem_reg *old_mem = &bo->mem;
-
-	if (new_mem->mem_type == DRM_BO_MEM_LOCAL) {
-		if (old_mem->mem_type == DRM_BO_MEM_LOCAL)
-			return drm_bo_move_memcpy(bo, evict, no_wait, new_mem);
-#if 0
-		if (!nouveau_bo_move_flipd(bo, evict, no_wait, new_mem))
-#endif
-			return drm_bo_move_memcpy(bo, evict, no_wait, new_mem);
-	}
-	else
-	if (old_mem->mem_type == DRM_BO_MEM_LOCAL) {
-#if 0
-		if (nouveau_bo_move_flips(bo, evict, no_wait, new_mem))
-#endif
-			return drm_bo_move_memcpy(bo, evict, no_wait, new_mem);
-	}
-	else {
-//		if (nouveau_bo_move_m2mf(bo, evict, no_wait, new_mem))
-			return drm_bo_move_memcpy(bo, evict, no_wait, new_mem);
-	}
-	return 0;
-}
-
-static void
-nouveau_bo_flush_ttm(struct drm_ttm *ttm)
-{
-}
-
-static uint32_t nouveau_mem_prios[]  = {
-	DRM_BO_MEM_PRIV0,
-	DRM_BO_MEM_VRAM,
-	DRM_BO_MEM_TT,
-	DRM_BO_MEM_LOCAL
-};
-static uint32_t nouveau_busy_prios[] = {
-	DRM_BO_MEM_TT,
-	DRM_BO_MEM_PRIV0,
-	DRM_BO_MEM_VRAM,
-	DRM_BO_MEM_LOCAL
-};
-
-struct drm_bo_driver nouveau_bo_driver = {
-	.mem_type_prio = nouveau_mem_prios,
-	.mem_busy_prio = nouveau_busy_prios,
-	.num_mem_type_prio = sizeof(nouveau_mem_prios)/sizeof(uint32_t),
-	.num_mem_busy_prio = sizeof(nouveau_busy_prios)/sizeof(uint32_t),
-	.create_ttm_backend_entry = nouveau_bo_create_ttm_backend_entry,
-	.fence_type = nouveau_bo_fence_type,
-	.invalidate_caches = nouveau_bo_invalidate_caches,
-	.init_mem_type = nouveau_bo_init_mem_type,
-	.evict_mask = nouveau_bo_evict_mask,
-	.move = nouveau_bo_move,
-	.ttm_cache_flush= nouveau_bo_flush_ttm
-};
diff --git a/shared-core/nouveau_drm.h b/shared-core/nouveau_drm.h
index 3bf4008..3a9a529 100644
--- a/shared-core/nouveau_drm.h
+++ b/shared-core/nouveau_drm.h
@@ -25,7 +25,7 @@
 #ifndef __NOUVEAU_DRM_H__
 #define __NOUVEAU_DRM_H__
 
-#define NOUVEAU_DRM_HEADER_PATCHLEVEL 10
+#define NOUVEAU_DRM_HEADER_PATCHLEVEL 11
 
 struct drm_nouveau_channel_alloc {
 	uint32_t     fb_ctxdma_handle;
@@ -117,6 +117,9 @@ struct drm_nouveau_setparam {
 	uint64_t value;
 };
 
+struct drm_nouveau_bo_validate {
+};
+
 enum nouveau_card_type {
 	NV_UNKNOWN =0,
 	NV_04      =4,
@@ -156,5 +159,6 @@ struct drm_nouveau_sarea {
 #define DRM_NOUVEAU_GPUOBJ_FREE        0x07
 #define DRM_NOUVEAU_MEM_ALLOC          0x08
 #define DRM_NOUVEAU_MEM_FREE           0x09
+#define DRM_NOUVEAU_BO_VALIDATE        0x0a
 
 #endif /* __NOUVEAU_DRM_H__ */
diff --git a/shared-core/nouveau_drv.h b/shared-core/nouveau_drv.h
index 8b00726..c276b69 100644
--- a/shared-core/nouveau_drv.h
+++ b/shared-core/nouveau_drv.h
@@ -34,7 +34,7 @@
 
 #define DRIVER_MAJOR		0
 #define DRIVER_MINOR		0
-#define DRIVER_PATCHLEVEL	10
+#define DRIVER_PATCHLEVEL	11
 
 #define NOUVEAU_FAMILY   0x0000FFFF
 #define NOUVEAU_FLAGS    0xFFFF0000
@@ -559,8 +559,10 @@ extern void nv04_timer_takedown(struct drm_device *);
 extern long nouveau_compat_ioctl(struct file *file, unsigned int cmd,
 				 unsigned long arg);
 
-/* nouveau_buffer.c */
+/* nouveau_bo.c */
 extern struct drm_bo_driver nouveau_bo_driver;
+extern int nouveau_bo_validate(struct drm_device *, void *data,
+			       struct drm_file *);
 
 /* nouveau_fence.c */
 extern struct drm_fence_driver nouveau_fence_driver;
diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c
index e2cb209..4b84f9c 100644
--- a/shared-core/nouveau_fifo.c
+++ b/shared-core/nouveau_fifo.c
@@ -565,6 +565,7 @@ struct drm_ioctl_desc nouveau_ioctls[] = {
 	DRM_IOCTL_DEF(DRM_NOUVEAU_GPUOBJ_FREE, nouveau_ioctl_gpuobj_free, DRM_AUTH),
 	DRM_IOCTL_DEF(DRM_NOUVEAU_MEM_ALLOC, nouveau_ioctl_mem_alloc, DRM_AUTH),
 	DRM_IOCTL_DEF(DRM_NOUVEAU_MEM_FREE, nouveau_ioctl_mem_free, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_NOUVEAU_BO_VALIDATE, nouveau_bo_validate, DRM_AUTH),
 };
 
 int nouveau_max_ioctl = DRM_ARRAY_SIZE(nouveau_ioctls);
diff --git a/shared-core/nouveau_state.c b/shared-core/nouveau_state.c
index 610d24e..c19d7bf 100644
--- a/shared-core/nouveau_state.c
+++ b/shared-core/nouveau_state.c
@@ -278,7 +278,7 @@ nouveau_card_init(struct drm_device *dev)
 
 	if (dev_priv->init_state == NOUVEAU_CARD_INIT_DONE)
 		return 0;
-	dev_priv->ttm = 0;
+	dev_priv->ttm = 1;
 
 	/* Map any PCI resources we need on the card */
 	ret = nouveau_init_card_mappings(dev);
commit 793cd1dad5e248509a1b09dce7126f236efadb3e
Author: Jesse Barnes <jbarnes@hobbes.virtuousgeek.org>
Date:   Sat Nov 10 14:39:36 2007 -0800

    Make sure PLLs are enabled before writing pipe configuration regs
    
    Fix from the X driver.  Make sure the PLLs are enabled and not in VGA mode
    before writing PIPE(A|B)CONF regs to avoid hangs or crashes.

diff --git a/linux-core/i915_drv.c b/linux-core/i915_drv.c
index 798491a..d2bcf4b 100644
--- a/linux-core/i915_drv.c
+++ b/linux-core/i915_drv.c
@@ -431,7 +431,11 @@ static int i915_resume(struct drm_device *dev)
 		I915_WRITE(DSPASURF, dev_priv->saveDSPASURF);
 		I915_WRITE(DSPATILEOFF, dev_priv->saveDSPATILEOFF);
 	}
-	I915_WRITE(PIPEACONF, dev_priv->savePIPEACONF);
+
+	if ((dev_priv->saveDPLL_A & DPLL_VCO_ENABLE) &&
+	    (dev_priv->saveDPLL_A & DPLL_VGA_MODE_DIS))
+		I915_WRITE(PIPEACONF, dev_priv->savePIPEACONF);
+
 	i915_restore_palette(dev, PIPE_A);
 	/* Enable the plane */
 	I915_WRITE(DSPACNTR, dev_priv->saveDSPACNTR);
@@ -471,7 +475,10 @@ static int i915_resume(struct drm_device *dev)
 		I915_WRITE(DSPBSURF, dev_priv->saveDSPBSURF);
 		I915_WRITE(DSPBTILEOFF, dev_priv->saveDSPBTILEOFF);
 	}
-	I915_WRITE(PIPEBCONF, dev_priv->savePIPEBCONF);
+
+	if ((dev_priv->saveDPLL_B & DPLL_VCO_ENABLE) &&
+	    (dev_priv->saveDPLL_B & DPLL_VGA_MODE_DIS))
+		I915_WRITE(PIPEBCONF, dev_priv->savePIPEBCONF);
 	i915_restore_palette(dev, PIPE_A);
 	/* Enable the plane */
 	I915_WRITE(DSPBCNTR, dev_priv->saveDSPBCNTR);
commit c2f80ecf4be09b5b9866d12e3b25cdcf7996b1f4
Author: Patrice Mandin <pmandin@caramail.com>
Date:   Fri Nov 9 18:08:08 2007 +0100

    suspend() and resume() need kernel 2.6.22 or later

diff --git a/linux-core/drm_sysfs.c b/linux-core/drm_sysfs.c
index 6f8623c..caec120 100644
--- a/linux-core/drm_sysfs.c
+++ b/linux-core/drm_sysfs.c
@@ -89,8 +89,10 @@ struct class *drm_sysfs_create(struct module *owner, char *name)
 		goto err_out;
 	}
 
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22))
 	class->suspend = drm_sysfs_suspend;
 	class->resume = drm_sysfs_resume;
+#endif
 
 	err = class_create_file(class, &class_attr_version);
 	if (err)



-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/

--
_______________________________________________
Dri-patches mailing list
Dri-patches@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/dri-patches


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

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