diff options
author | Dave Airlie <airlied@linux.ie> | 2006-03-19 19:37:55 +1100 |
---|---|---|
committer | Dave Airlie <airlied@linux.ie> | 2006-03-19 19:37:55 +1100 |
commit | d5ea702f1e8e3edeea6b673a58281bf99f3dbec5 (patch) | |
tree | dae329419620db61ccfaa9a50394e07c31f21d1f /drivers/char/drm/radeon_state.c | |
parent | 45f17100bfd18c99d6479e94598f4e533bbe30d8 (diff) |
drm: rework radeon memory map (radeon 1.23)
This code reworks the radeon memory map so it works better
for newer r300 chips and for a lot of older PCI chips.
It really requires a new X driver in order to take advantage of this code.
From: Ben Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Dave Airlie <airlied@linux.ie>
Diffstat (limited to 'drivers/char/drm/radeon_state.c')
-rw-r--r-- | drivers/char/drm/radeon_state.c | 58 |
1 files changed, 46 insertions, 12 deletions
diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c index 7bc27516d425..56e56b873616 100644 --- a/drivers/char/drm/radeon_state.c +++ b/drivers/char/drm/radeon_state.c @@ -45,22 +45,53 @@ static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t * u32 off = *offset; struct drm_radeon_driver_file_fields *radeon_priv; - if (off >= dev_priv->fb_location && - off < (dev_priv->gart_vm_start + dev_priv->gart_size)) - return 0; - - radeon_priv = filp_priv->driver_priv; - off += radeon_priv->radeon_fb_delta; + /* Hrm ... the story of the offset ... So this function converts + * the various ideas of what userland clients might have for an + * offset in the card address space into an offset into the card + * address space :) So with a sane client, it should just keep + * the value intact and just do some boundary checking. However, + * not all clients are sane. Some older clients pass us 0 based + * offsets relative to the start of the framebuffer and some may + * assume the AGP aperture it appended to the framebuffer, so we + * try to detect those cases and fix them up. + * + * Note: It might be a good idea here to make sure the offset lands + * in some "allowed" area to protect things like the PCIE GART... + */ - DRM_DEBUG("offset fixed up to 0x%x\n", off); + /* First, the best case, the offset already lands in either the + * framebuffer or the GART mapped space + */ + if ((off >= dev_priv->fb_location && + off < (dev_priv->fb_location + dev_priv->fb_size)) || + (off >= dev_priv->gart_vm_start && + off < (dev_priv->gart_vm_start + dev_priv->gart_size))) + return 0; - if (off < dev_priv->fb_location || - off >= (dev_priv->gart_vm_start + dev_priv->gart_size)) - return DRM_ERR(EINVAL); + /* Ok, that didn't happen... now check if we have a zero based + * offset that fits in the framebuffer + gart space, apply the + * magic offset we get from SETPARAM or calculated from fb_location + */ + if (off < (dev_priv->fb_size + dev_priv->gart_size)) { + radeon_priv = filp_priv->driver_priv; + off += radeon_priv->radeon_fb_delta; + } - *offset = off; + /* Finally, assume we aimed at a GART offset if beyond the fb */ + if (off > (dev_priv->fb_location + dev_priv->fb_size)) + off = off - (dev_priv->fb_location + dev_priv->fb_size) + + dev_priv->gart_vm_start; - return 0; + /* Now recheck and fail if out of bounds */ + if ((off >= dev_priv->fb_location && + off < (dev_priv->fb_location + dev_priv->fb_size)) || + (off >= dev_priv->gart_vm_start && + off < (dev_priv->gart_vm_start + dev_priv->gart_size))) { + DRM_DEBUG("offset fixed up to 0x%x\n", off); + *offset = off; + return 0; + } + return DRM_ERR(EINVAL); } static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t * @@ -3012,6 +3043,9 @@ static int radeon_cp_setparam(DRM_IOCTL_ARGS) 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); |