# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#	           ChangeSet	1.676.14.4 -> 1.676.14.5
#	drivers/char/drm-4.0/radeon_drv.c	1.1     -> 1.2    
#	drivers/char/drm-4.0/bufs.c	1.1     -> 1.2    
#	drivers/char/drm-4.0/tdfx_drv.c	1.2     -> 1.3    
#	drivers/char/drm-4.0/i810_drv.c	1.1     -> 1.2    
#	drivers/char/drm-4.0/radeon_cp.c	1.1     -> 1.2    
#	drivers/char/drm-4.0/mga_drv.h	1.1     -> 1.2    
#	drivers/char/drm-4.0/vm.c	1.1     -> 1.2    
#	drivers/char/drm-4.0/r128_drv.c	1.1     -> 1.2    
#	drivers/char/drm-4.0/drmP.h	1.1     -> 1.2    
#	drivers/char/drm-4.0/gamma_drv.c	1.1     -> 1.2    
#	drivers/char/drm-4.0/mga_dma.c	1.1     -> 1.2    
#	drivers/char/drm-4.0/i810_dma.c	1.3     -> 1.4    
#	drivers/char/drm-4.0/ffb_drv.c	1.3     -> 1.4    
#	drivers/char/drm-4.0/r128_cce.c	1.1     -> 1.2    
#	drivers/char/drm-4.0/radeon_drv.h	1.1     -> 1.2    
#	drivers/char/drm-4.0/mga_drv.c	1.1     -> 1.2    
#	drivers/char/drm-4.0/agpsupport.c	1.1     -> 1.2    
#	drivers/char/drm-4.0/memory.c	1.1     -> 1.2    
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/09/27	bjorn_helgaas@hp.com	1.676.14.5
# DRM 4.0 support for AGP bridges where CPU accesses don't go through
# GART aperture.
# --------------------------------------------
#
diff -Nru a/drivers/char/drm-4.0/agpsupport.c b/drivers/char/drm-4.0/agpsupport.c
--- a/drivers/char/drm-4.0/agpsupport.c	Wed Oct  8 09:07:08 2003
+++ b/drivers/char/drm-4.0/agpsupport.c	Wed Oct  8 09:07:08 2003
@@ -30,6 +30,7 @@
 
 #define __NO_VERSION__
 #include "drmP.h"
+#include <linux/config.h>
 #include <linux/module.h>
 #if LINUX_VERSION_CODE < 0x020400
 #include "agpsupport-pre24.h"
@@ -297,6 +298,13 @@
 
 		default:		head->chipset = "Unknown";       break;
 		}
+#if LINUX_VERSION_CODE <= 0x020408
+		head->cant_use_aperture = 0;
+		head->page_mask = ~(0xfff);
+#else
+		head->cant_use_aperture = head->agp_info.cant_use_aperture;
+		head->page_mask = head->agp_info.page_mask;
+#endif
 		DRM_INFO("AGP %d.%d on %s @ 0x%08lx %ZuMB\n",
 			 head->agp_info.version.major,
 			 head->agp_info.version.minor,
diff -Nru a/drivers/char/drm-4.0/bufs.c b/drivers/char/drm-4.0/bufs.c
--- a/drivers/char/drm-4.0/bufs.c	Wed Oct  8 09:07:08 2003
+++ b/drivers/char/drm-4.0/bufs.c	Wed Oct  8 09:07:08 2003
@@ -73,7 +73,7 @@
 	switch (map->type) {
 	case _DRM_REGISTERS:
 	case _DRM_FRAME_BUFFER:
-#ifndef __sparc__
+#if !defined(__sparc__) && !defined(__ia64__)
 		if (map->offset + map->size < map->offset
 		    || map->offset < virt_to_phys(high_memory)) {
 			drm_free(map, sizeof(*map), DRM_MEM_MAPS);
@@ -87,7 +87,7 @@
 					     MTRR_TYPE_WRCOMB, 1);
 		}
 #endif
-		map->handle = drm_ioremap(map->offset, map->size);
+		map->handle = drm_ioremap(map->offset, map->size, dev);
 		break;
 			
 
diff -Nru a/drivers/char/drm-4.0/drmP.h b/drivers/char/drm-4.0/drmP.h
--- a/drivers/char/drm-4.0/drmP.h	Wed Oct  8 09:07:08 2003
+++ b/drivers/char/drm-4.0/drmP.h	Wed Oct  8 09:07:08 2003
@@ -510,6 +510,8 @@
 	int                acquired;
 	unsigned long      base;
    	int 		   agp_mtrr;
+	int		   cant_use_aperture;
+	unsigned long	   page_mask;
 } drm_agp_head_t;
 #endif
 
@@ -679,8 +681,10 @@
 extern unsigned long drm_alloc_pages(int order, int area);
 extern void	     drm_free_pages(unsigned long address, int order,
 				    int area);
-extern void	     *drm_ioremap(unsigned long offset, unsigned long size);
-extern void	     drm_ioremapfree(void *pt, unsigned long size);
+extern void	     *drm_ioremap(unsigned long offset, unsigned long size,
+				  drm_device_t *dev);
+extern void	     drm_ioremapfree(void *pt, unsigned long size,
+				     drm_device_t *dev);
 
 #if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
 extern agp_memory    *drm_alloc_agp(int pages, u32 type);
diff -Nru a/drivers/char/drm-4.0/ffb_drv.c b/drivers/char/drm-4.0/ffb_drv.c
--- a/drivers/char/drm-4.0/ffb_drv.c	Wed Oct  8 09:07:08 2003
+++ b/drivers/char/drm-4.0/ffb_drv.c	Wed Oct  8 09:07:08 2003
@@ -158,7 +158,7 @@
 			switch (map->type) {
 			case _DRM_REGISTERS:
 			case _DRM_FRAME_BUFFER:
-				drm_ioremapfree(map->handle, map->size);
+				drm_ioremapfree(map->handle, map->size, dev);
 				break;
 
 			case _DRM_SHM:
diff -Nru a/drivers/char/drm-4.0/gamma_drv.c b/drivers/char/drm-4.0/gamma_drv.c
--- a/drivers/char/drm-4.0/gamma_drv.c	Wed Oct  8 09:07:08 2003
+++ b/drivers/char/drm-4.0/gamma_drv.c	Wed Oct  8 09:07:08 2003
@@ -258,7 +258,7 @@
 					DRM_DEBUG("mtrr_del = %d\n", retcode);
 				}
 #endif
-				drm_ioremapfree(map->handle, map->size);
+				drm_ioremapfree(map->handle, map->size, dev);
 				break;
 			case _DRM_SHM:
 				drm_free_pages((unsigned long)map->handle,
diff -Nru a/drivers/char/drm-4.0/i810_dma.c b/drivers/char/drm-4.0/i810_dma.c
--- a/drivers/char/drm-4.0/i810_dma.c	Wed Oct  8 09:07:08 2003
+++ b/drivers/char/drm-4.0/i810_dma.c	Wed Oct  8 09:07:08 2003
@@ -309,7 +309,7 @@
 	   
 	   	if(dev_priv->ring.virtual_start) {
 		   	drm_ioremapfree((void *) dev_priv->ring.virtual_start,
-					dev_priv->ring.Size);
+					dev_priv->ring.Size, dev);
 		}
 	   	if(dev_priv->hw_status_page != 0UL) {
 		   	i810_free_page(dev, dev_priv->hw_status_page);
@@ -323,7 +323,8 @@
 		for (i = 0; i < dma->buf_count; i++) {
 			drm_buf_t *buf = dma->buflist[ i ];
 			drm_i810_buf_priv_t *buf_priv = buf->dev_private;
-			drm_ioremapfree(buf_priv->kernel_virtual, buf->total);
+			drm_ioremapfree(buf_priv->kernel_virtual,
+							buf->total, dev);
 		}
 	}
    	return 0;
@@ -397,7 +398,7 @@
 	   	*buf_priv->in_use = I810_BUF_FREE;
 
 		buf_priv->kernel_virtual = drm_ioremap(buf->bus_address, 
-						       buf->total);
+						       buf->total, dev);
 	}
 	return 0;
 }
@@ -434,7 +435,7 @@
 
    	dev_priv->ring.virtual_start = drm_ioremap(dev->agp->base + 
 						   init->ring_start, 
-						   init->ring_size);
+						   init->ring_size, dev);
 
    	dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
    
diff -Nru a/drivers/char/drm-4.0/i810_drv.c b/drivers/char/drm-4.0/i810_drv.c
--- a/drivers/char/drm-4.0/i810_drv.c	Wed Oct  8 09:07:08 2003
+++ b/drivers/char/drm-4.0/i810_drv.c	Wed Oct  8 09:07:08 2003
@@ -286,7 +286,7 @@
 					DRM_DEBUG("mtrr_del = %d\n", retcode);
 				}
 #endif
-				drm_ioremapfree(map->handle, map->size);
+				drm_ioremapfree(map->handle, map->size, dev);
 				break;
 			case _DRM_SHM:
 				drm_free_pages((unsigned long)map->handle,
diff -Nru a/drivers/char/drm-4.0/memory.c b/drivers/char/drm-4.0/memory.c
--- a/drivers/char/drm-4.0/memory.c	Wed Oct  8 09:07:08 2003
+++ b/drivers/char/drm-4.0/memory.c	Wed Oct  8 09:07:08 2003
@@ -296,7 +296,7 @@
 	}
 }
 
-void *drm_ioremap(unsigned long offset, unsigned long size)
+void *drm_ioremap(unsigned long offset, unsigned long size, drm_device_t *dev)
 {
 	void *pt;
 	
@@ -306,12 +306,44 @@
 		return NULL;
 	}
 	
+	if (dev->agp->cant_use_aperture) {
+		drm_map_t *map    = NULL;
+		int i;
+
+		for (i = 0; i < dev->map_count; i++) {
+			map = dev->maplist[i];
+			if (!map) continue;
+			if (map->offset <= offset &&
+				(map->offset + map->size) >= (offset + size))
+				break;
+		}
+		
+		if (map && map->type == _DRM_AGP) {
+			struct drm_agp_mem *agpmem;
+
+			for (agpmem = dev->agp->memory; agpmem;
+						agpmem = agpmem->next) {
+				if(agpmem->bound <= offset &&
+				   (agpmem->bound + (agpmem->pages
+					<< PAGE_SHIFT)) >= (offset + size))
+					break;
+			}
+
+			if (agpmem) {
+				pt = agpmem->memory->vmptr + (offset - agpmem->bound);
+				goto ioremap_success;
+			}
+		}
+	}
+
 	if (!(pt = ioremap(offset, size))) {
 		spin_lock(&drm_mem_lock);
 		++drm_mem_stats[DRM_MEM_MAPPINGS].fail_count;
 		spin_unlock(&drm_mem_lock);
 		return NULL;
 	}
+
+ioremap_success:
 	spin_lock(&drm_mem_lock);
 	++drm_mem_stats[DRM_MEM_MAPPINGS].succeed_count;
 	drm_mem_stats[DRM_MEM_MAPPINGS].bytes_allocated += size;
@@ -319,7 +351,7 @@
 	return pt;
 }
 
-void drm_ioremapfree(void *pt, unsigned long size)
+void drm_ioremapfree(void *pt, unsigned long size, drm_device_t *dev)
 {
 	int alloc_count;
 	int free_count;
@@ -327,7 +359,7 @@
 	if (!pt)
 		DRM_MEM_ERROR(DRM_MEM_MAPPINGS,
 			      "Attempt to free NULL pointer\n");
-	else
+	else if (dev->agp->cant_use_aperture == 0)
 		iounmap(pt);
 	
 	spin_lock(&drm_mem_lock);
diff -Nru a/drivers/char/drm-4.0/mga_dma.c b/drivers/char/drm-4.0/mga_dma.c
--- a/drivers/char/drm-4.0/mga_dma.c	Wed Oct  8 09:07:08 2003
+++ b/drivers/char/drm-4.0/mga_dma.c	Wed Oct  8 09:07:08 2003
@@ -308,7 +308,7 @@
 	temp = ((temp + PAGE_SIZE - 1) / PAGE_SIZE) * PAGE_SIZE;
 
 	dev_priv->ioremap = drm_ioremap(dev->agp->base + offset,
-					temp);
+					temp, dev);
 	if(dev_priv->ioremap == NULL) {
 		DRM_ERROR("Ioremap failed\n");
 		return -ENOMEM;
@@ -635,7 +635,7 @@
 				    dev_priv->primary_size +
 				    PAGE_SIZE - 1) / PAGE_SIZE * PAGE_SIZE;
 
-			drm_ioremapfree((void *) dev_priv->ioremap, temp);
+			drm_ioremapfree((void *) dev_priv->ioremap, temp, dev);
 		}
 	   	if(dev_priv->status_page != NULL) {
 		   	iounmap(dev_priv->status_page);
@@ -741,10 +741,18 @@
 		return -ENOMEM;
 	}
 
-   	/* Write status page when secend or softrap occurs */
+   	/* Write status page when secend or softrap occurs
+	 *
+	 * Disable this on ia64 on the off chance that real status page will be
+	 * above 4GB.
+	 */
+#if defined(__ia64__)
+   	MGA_WRITE(MGAREG_PRIMPTR,
+		  virt_to_bus((void *)dev_priv->real_status_page));
+#else
    	MGA_WRITE(MGAREG_PRIMPTR,
 		  virt_to_bus((void *)dev_priv->real_status_page) | 0x00000003);
-
+#endif
 
 	/* Private is now filled in, initialize the hardware */
 	{
diff -Nru a/drivers/char/drm-4.0/mga_drv.c b/drivers/char/drm-4.0/mga_drv.c
--- a/drivers/char/drm-4.0/mga_drv.c	Wed Oct  8 09:07:08 2003
+++ b/drivers/char/drm-4.0/mga_drv.c	Wed Oct  8 09:07:08 2003
@@ -286,7 +286,7 @@
 					DRM_DEBUG("mtrr_del = %d\n", retcode);
 				}
 #endif
-				drm_ioremapfree(map->handle, map->size);
+				drm_ioremapfree(map->handle, map->size, dev);
 				break;
 			case _DRM_SHM:
 				drm_free_pages((unsigned long)map->handle,
diff -Nru a/drivers/char/drm-4.0/mga_drv.h b/drivers/char/drm-4.0/mga_drv.h
--- a/drivers/char/drm-4.0/mga_drv.h	Wed Oct  8 09:07:08 2003
+++ b/drivers/char/drm-4.0/mga_drv.h	Wed Oct  8 09:07:08 2003
@@ -295,7 +295,7 @@
 		       num_dwords + 1 + outcount, ADRINDEX(reg), val);	\
 	if( ++outcount == 4) {						\
 		outcount = 0;						\
-		dma_ptr[0] = *(unsigned long *)tempIndex;		\
+		dma_ptr[0] = *(u32 *)tempIndex;				\
 		dma_ptr+=5;						\
 		num_dwords += 5;					\
 	}								\
diff -Nru a/drivers/char/drm-4.0/r128_cce.c b/drivers/char/drm-4.0/r128_cce.c
--- a/drivers/char/drm-4.0/r128_cce.c	Wed Oct  8 09:07:08 2003
+++ b/drivers/char/drm-4.0/r128_cce.c	Wed Oct  8 09:07:08 2003
@@ -86,12 +86,13 @@
 };
 
 
-#define DO_REMAP(_m) (_m)->handle = drm_ioremap((_m)->offset, (_m)->size)
+#define DO_REMAP(_m, _d) (_m)->handle = drm_ioremap((_m)->offset,           \
+							 (_m)->size, (_d))
 
-#define DO_REMAPFREE(_m)                                                    \
+#define DO_REMAPFREE(_m, _d)                                                \
 	do {                                                                \
 		if ((_m)->handle && (_m)->size)                             \
-			drm_ioremapfree((_m)->handle, (_m)->size);          \
+			drm_ioremapfree((_m)->handle, (_m)->size, (_d));    \
 	} while (0)
 
 #define DO_FIND_MAP(_m, _o)                                                 \
@@ -481,12 +482,12 @@
 		(drm_r128_sarea_t *)((u8 *)dev_priv->sarea->handle +
 				     init->sarea_priv_offset);
 
-	DO_REMAP( dev_priv->cce_ring );
-	DO_REMAP( dev_priv->ring_rptr );
-	DO_REMAP( dev_priv->buffers );
+	DO_REMAP( dev_priv->cce_ring, dev );
+	DO_REMAP( dev_priv->ring_rptr, dev );
+	DO_REMAP( dev_priv->buffers, dev );
 #if 0
 	if ( !dev_priv->is_pci ) {
-		DO_REMAP( dev_priv->agp_textures );
+		DO_REMAP( dev_priv->agp_textures, dev );
 	}
 #endif
 
@@ -521,12 +522,12 @@
 	if ( dev->dev_private ) {
 		drm_r128_private_t *dev_priv = dev->dev_private;
 
-		DO_REMAPFREE( dev_priv->cce_ring );
-		DO_REMAPFREE( dev_priv->ring_rptr );
-		DO_REMAPFREE( dev_priv->buffers );
+		DO_REMAPFREE( dev_priv->cce_ring, dev );
+		DO_REMAPFREE( dev_priv->ring_rptr, dev );
+		DO_REMAPFREE( dev_priv->buffers, dev );
 #if 0
 		if ( !dev_priv->is_pci ) {
-			DO_REMAPFREE( dev_priv->agp_textures );
+			DO_REMAPFREE( dev_priv->agp_textures, dev );
 		}
 #endif
 
diff -Nru a/drivers/char/drm-4.0/r128_drv.c b/drivers/char/drm-4.0/r128_drv.c
--- a/drivers/char/drm-4.0/r128_drv.c	Wed Oct  8 09:07:08 2003
+++ b/drivers/char/drm-4.0/r128_drv.c	Wed Oct  8 09:07:08 2003
@@ -296,7 +296,7 @@
 					DRM_DEBUG("mtrr_del = %d\n", retcode);
 				}
 #endif
-				drm_ioremapfree(map->handle, map->size);
+				drm_ioremapfree(map->handle, map->size, dev);
 				break;
 			case _DRM_SHM:
 				drm_free_pages((unsigned long)map->handle,
diff -Nru a/drivers/char/drm-4.0/radeon_cp.c b/drivers/char/drm-4.0/radeon_cp.c
--- a/drivers/char/drm-4.0/radeon_cp.c	Wed Oct  8 09:07:08 2003
+++ b/drivers/char/drm-4.0/radeon_cp.c	Wed Oct  8 09:07:08 2003
@@ -300,12 +300,13 @@
 };
 
 
-#define DO_IOREMAP(_m) (_m)->handle = drm_ioremap((_m)->offset, (_m)->size)
+#define DO_IOREMAP(_m, _d) (_m)->handle = drm_ioremap((_m)->offset,	\
+						 	(_m)->size, (_d))
 
-#define DO_IOREMAPFREE(_m)						\
+#define DO_IOREMAPFREE(_m, _d)						\
 	do {								\
 		if ((_m)->handle && (_m)->size)				\
-			drm_ioremapfree((_m)->handle, (_m)->size);	\
+			drm_ioremapfree((_m)->handle, (_m)->size, (_d));\
 	} while (0)
 
 #define DO_FIND_MAP(_m, _o)						\
@@ -757,12 +758,12 @@
 		(drm_radeon_sarea_t *)((u8 *)dev_priv->sarea->handle +
 				       init->sarea_priv_offset);
 
-	DO_IOREMAP( dev_priv->cp_ring );
-	DO_IOREMAP( dev_priv->ring_rptr );
-	DO_IOREMAP( dev_priv->buffers );
+	DO_IOREMAP( dev_priv->cp_ring, dev );
+	DO_IOREMAP( dev_priv->ring_rptr, dev );
+	DO_IOREMAP( dev_priv->buffers, dev );
 #if 0
 	if ( !dev_priv->is_pci ) {
-		DO_IOREMAP( dev_priv->agp_textures );
+		DO_IOREMAP( dev_priv->agp_textures, dev );
 	}
 #endif
 
@@ -828,12 +829,12 @@
 	if ( dev->dev_private ) {
 		drm_radeon_private_t *dev_priv = dev->dev_private;
 
-		DO_IOREMAPFREE( dev_priv->cp_ring );
-		DO_IOREMAPFREE( dev_priv->ring_rptr );
-		DO_IOREMAPFREE( dev_priv->buffers );
+		DO_IOREMAPFREE( dev_priv->cp_ring, dev );
+		DO_IOREMAPFREE( dev_priv->ring_rptr, dev );
+		DO_IOREMAPFREE( dev_priv->buffers, dev );
 #if 0
 		if ( !dev_priv->is_pci ) {
-			DO_IOREMAPFREE( dev_priv->agp_textures );
+			DO_IOREMAPFREE( dev_priv->agp_textures, dev );
 		}
 #endif
 
diff -Nru a/drivers/char/drm-4.0/radeon_drv.c b/drivers/char/drm-4.0/radeon_drv.c
--- a/drivers/char/drm-4.0/radeon_drv.c	Wed Oct  8 09:07:08 2003
+++ b/drivers/char/drm-4.0/radeon_drv.c	Wed Oct  8 09:07:08 2003
@@ -294,7 +294,7 @@
 					DRM_DEBUG("mtrr_del = %d\n", retcode);
 				}
 #endif
-				drm_ioremapfree(map->handle, map->size);
+				drm_ioremapfree(map->handle, map->size, dev);
 				break;
 			case _DRM_SHM:
 				drm_free_pages((unsigned long)map->handle,
diff -Nru a/drivers/char/drm-4.0/radeon_drv.h b/drivers/char/drm-4.0/radeon_drv.h
--- a/drivers/char/drm-4.0/radeon_drv.h	Wed Oct  8 09:07:08 2003
+++ b/drivers/char/drm-4.0/radeon_drv.h	Wed Oct  8 09:07:08 2003
@@ -535,7 +535,7 @@
 #define RADEON_MAX_VB_VERTS		(0xffff)
 
 
-#define RADEON_BASE(reg)	((u32)(dev_priv->mmio->handle))
+#define RADEON_BASE(reg)	((unsigned long)(dev_priv->mmio->handle))
 #define RADEON_ADDR(reg)	(RADEON_BASE(reg) + reg)
 
 #define RADEON_DEREF(reg)	*(__volatile__ u32 *)RADEON_ADDR(reg)
diff -Nru a/drivers/char/drm-4.0/tdfx_drv.c b/drivers/char/drm-4.0/tdfx_drv.c
--- a/drivers/char/drm-4.0/tdfx_drv.c	Wed Oct  8 09:07:08 2003
+++ b/drivers/char/drm-4.0/tdfx_drv.c	Wed Oct  8 09:07:08 2003
@@ -264,7 +264,7 @@
 					DRM_DEBUG("mtrr_del = %d\n", retcode);
 				}
 #endif
-				drm_ioremapfree(map->handle, map->size);
+				drm_ioremapfree(map->handle, map->size, dev);
 				break;
 			case _DRM_SHM:
 				drm_free_pages((unsigned long)map->handle,
diff -Nru a/drivers/char/drm-4.0/vm.c b/drivers/char/drm-4.0/vm.c
--- a/drivers/char/drm-4.0/vm.c	Wed Oct  8 09:07:08 2003
+++ b/drivers/char/drm-4.0/vm.c	Wed Oct  8 09:07:08 2003
@@ -30,6 +30,7 @@
  */
 
 #define __NO_VERSION__
+#include <linux/config.h>
 #include "drmP.h"
 
 struct vm_operations_struct   drm_vm_ops = {
@@ -67,7 +68,56 @@
 			   int write_access)
 #endif
 {
-	return NOPAGE_SIGBUS;		/* Disallow mremap */
+        drm_file_t *priv  = vma->vm_file->private_data;
+        drm_device_t *dev = priv->dev;
+        drm_map_t *map    = NULL;
+	int i;
+
+	if (!dev->agp->cant_use_aperture)
+		return NOPAGE_SIGBUS;		/* Disallow mremap */
+
+        /*
+         * Find the right map
+         */
+	for (i = 0; i < dev->map_count; i++) {
+                map = dev->maplist[i];
+                if (!map) continue;
+                if (map->offset == VM_OFFSET(vma)) break;
+        }
+
+        if (map && map->type == _DRM_AGP) {
+                unsigned long offset = address - vma->vm_start;
+                unsigned long baddr = VM_OFFSET(vma) + offset, paddr;
+                struct drm_agp_mem *agpmem;
+                struct page *page;
+
+                /*
+                 * It's AGP memory - find the real physical page to map
+                 */
+                for (agpmem = dev->agp->memory; agpmem; agpmem = agpmem->next) {
+                        if (agpmem->bound <= baddr &&
+                            agpmem->bound + agpmem->pages * PAGE_SIZE > baddr) 
+                                break;
+                }
+
+                if (!agpmem)
+			return NOPAGE_SIGBUS;
+
+                /*
+                 * Get the page, inc the use count, and return it
+                 */
+                offset = (baddr - agpmem->bound) >> PAGE_SHIFT;
+		paddr = agpmem->memory->memory[offset];
+                page = virt_to_page(__va(paddr));
+                get_page(page);
+
+#if LINUX_VERSION_CODE < 0x020317
+		return page_address(page);
+#else
+		return page;
+#endif
+        }
+	return NOPAGE_SIGBUS;
 }
 
 #if LINUX_VERSION_CODE < 0x020317
@@ -272,6 +322,7 @@
 	drm_file_t	*priv	= filp->private_data;
 	drm_device_t	*dev	= priv->dev;
 	drm_map_t	*map	= NULL;
+	unsigned long	off;
 	int		i;
 	
 	DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n",
@@ -288,7 +339,16 @@
 				   bit longer. */
 	for (i = 0; i < dev->map_count; i++) {
 		map = dev->maplist[i];
-		if (map->offset == VM_OFFSET(vma)) break;
+		off = map->offset ^ VM_OFFSET(vma);
+#ifdef	__ia64__
+		/*
+		 * Ignore region bits, makes IA32 processes happier
+		 * XXX This is a hack...
+		 */
+		off &= ~0xe000000000000000;
+#endif
+		if (off == 0)
+			break;
 	}
 	
 	if (i >= dev->map_count) return -EINVAL;
@@ -312,9 +372,19 @@
 	}
 
 	switch (map->type) {
+	case _DRM_AGP:
+		if (dev->agp->cant_use_aperture) {
+			/*
+			 * On some systems we can't talk to bus dma address from
+			 * the CPU, so for memory of type DRM_AGP, we'll deal
+			 * with sorting out the real physical pages and mappings
+			 * in nopage()
+			 */
+			vma->vm_ops = &drm_vm_ops;
+			break;
+		}
 	case _DRM_FRAME_BUFFER:
 	case _DRM_REGISTERS:
-	case _DRM_AGP:
 		if (VM_OFFSET(vma) >= __pa(high_memory)) {
 #if defined(__i386__) || defined(__x86_64__)
 			if (boot_cpu_data.x86 > 3 && map->type != _DRM_AGP) {