diff -urN drm-HEAD.orig/shared-core/radeon_cp.c drm-HEAD/shared-core/radeon_cp.c --- drm-HEAD.orig/shared-core/radeon_cp.c 2006-01-09 19:18:24.000000000 +1100 +++ drm-HEAD/shared-core/radeon_cp.c 2006-01-26 10:06:27.000000000 +1100 @@ -1118,11 +1118,16 @@ { u32 ring_start, cur_read_ptr; u32 tmp; - - /* Initialize the memory controller */ - RADEON_WRITE(RADEON_MC_FB_LOCATION, - ((dev_priv->gart_vm_start - 1) & 0xffff0000) - | (dev_priv->fb_location >> 16)); + + /* Initialize the memory controller. With new memory map, the fb location + * is not changed, it should have been properly initialized already. Part + * of the problem is that the code below is bogus, assuming the GART is + * always appended to the fb which is not necessarily the case + */ + if (!dev_priv->new_memmap) + RADEON_WRITE(RADEON_MC_FB_LOCATION, + ((dev_priv->gart_vm_start - 1) & 0xffff0000) + | (dev_priv->fb_location >> 16)); #if __OS_HAS_AGP if (dev_priv->flags & CHIP_IS_AGP) { @@ -1504,7 +1509,41 @@ dev_priv->gart_size = init->gart_size; - dev_priv->gart_vm_start = dev_priv->fb_location + RADEON_READ(RADEON_CONFIG_APER_SIZE); + /* New let's set the memory map ... */ + if (dev_priv->new_memmap) { + u32 base = 0; + u32 fb_end = (RADEON_READ(RADEON_MC_FB_LOCATION) & 0xffff0000u); + fb_end = (fb_end | 0xffff) + 1; + + DRM_DEBUG("Setting AGP location based on new memory map\n"); + + /* If using AGP, try to locate the AGP aperture at the same + * location in the card and on the bus, though we have to + * align it down. + */ +#if __OS_HAS_AGP + if (dev_priv->flags & CHIP_IS_AGP) { + base = dev->agp->base; + /* Check if valid */ + if ((base + dev_priv->gart_size) > dev_priv->fb_location && + base < fb_end) + base = 0; + } +#endif + /* If not or if AGP is at 0 (Macs), try to put it elsewhere */ + if (base == 0) { + base = fb_end; + if (((base + dev_priv->gart_size) & 0xfffffffful) + < base) + base = dev_priv->fb_location + - dev_priv->gart_size; + } + dev_priv->gart_vm_start = base & 0xffc00000u; + } else { + DRM_DEBUG("Setting AGP location based on old memory map\n"); + dev_priv->gart_vm_start = dev_priv->fb_location + + RADEON_READ(RADEON_CONFIG_APER_SIZE); + } #if __OS_HAS_AGP if (dev_priv->flags & CHIP_IS_AGP) diff -urN drm-HEAD.orig/shared-core/radeon_drm.h drm-HEAD/shared-core/radeon_drm.h --- drm-HEAD.orig/shared-core/radeon_drm.h 2006-01-09 19:18:24.000000000 +1100 +++ drm-HEAD/shared-core/radeon_drm.h 2006-01-25 17:16:15.000000000 +1100 @@ -698,6 +698,8 @@ #define RADEON_SETPARAM_SWITCH_TILING 2 /* enable/disable color tiling */ #define RADEON_SETPARAM_PCIGART_LOCATION 3 /* PCI Gart Location */ +#define RADEON_SETPARAM_NEW_MEMMAP 4 /* Use new memory map */ + /* 1.14: Clients can allocate/free a surface */ typedef struct drm_radeon_surface_alloc { diff -urN drm-HEAD.orig/shared-core/radeon_drv.h drm-HEAD/shared-core/radeon_drv.h --- drm-HEAD.orig/shared-core/radeon_drv.h 2006-01-25 16:52:10.000000000 +1100 +++ drm-HEAD/shared-core/radeon_drv.h 2006-01-25 17:16:40.000000000 +1100 @@ -93,7 +93,7 @@ */ #define DRIVER_MAJOR 1 -#define DRIVER_MINOR 22 +#define DRIVER_MINOR 23 #define DRIVER_PATCHLEVEL 0 enum radeon_family { @@ -197,6 +197,7 @@ drm_radeon_sarea_t *sarea_priv; u32 fb_location; + int new_memmap; int gart_size; u32 gart_vm_start; diff -urN drm-HEAD.orig/shared-core/radeon_state.c drm-HEAD/shared-core/radeon_state.c --- drm-HEAD.orig/shared-core/radeon_state.c 2006-01-09 19:18:25.000000000 +1100 +++ drm-HEAD/shared-core/radeon_state.c 2006-01-25 17:17:15.000000000 +1100 @@ -3014,6 +3014,9 @@ case RADEON_SETPARAM_PCIGART_LOCATION: dev_priv->pcigart_offset = sp.value; break; + case RADEON_SETPARAM_NEW_MEMMAP: + dev_priv->new_memmap = sp.value; + break; default: DRM_DEBUG("Invalid parameter %d\n", sp.param); return DRM_ERR(EINVAL);