diff options
author | Aapo Tahkola <aet@rasterburn.org> | 2006-03-06 20:08:50 +0000 |
---|---|---|
committer | Aapo Tahkola <aet@rasterburn.org> | 2006-03-06 20:08:50 +0000 |
commit | b3fdf9bb7acd023060e0dba07d3b439c3b64faef (patch) | |
tree | c8c57bc2b05aac1fc9b1632d3d991644f2e560fd /shared-core/r300_cmdbuf.c | |
parent | 02f76f41b12e1465db4e4a48c0b81977a8bd3d8d (diff) |
Add general-purpose packet for manipulating scratch registers (r300)
Diffstat (limited to 'shared-core/r300_cmdbuf.c')
-rw-r--r-- | shared-core/r300_cmdbuf.c | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/shared-core/r300_cmdbuf.c b/shared-core/r300_cmdbuf.c index 9af5c073..988734cf 100644 --- a/shared-core/r300_cmdbuf.c +++ b/shared-core/r300_cmdbuf.c @@ -702,6 +702,63 @@ static void r300_discard_buffer(drm_device_t * dev, drm_buf_t * buf) buf->used = 0; } +static __inline__ int r300_scratch(drm_radeon_private_t *dev_priv, + drm_radeon_kcmd_buffer_t *cmdbuf, + drm_r300_cmd_header_t header) +{ + u32 *ref_age_base; + u32 i, buf_idx, h_pending; + RING_LOCALS; + + if (cmdbuf->bufsz < sizeof(u32 *) + header.scratch.n_bufs * sizeof(buf_idx) ) { + return DRM_ERR(EINVAL); + } + + if (header.scratch.reg >= 5) { + return DRM_ERR(EINVAL); + } + + dev_priv->scratch_ages[header.scratch.reg] ++; + + ref_age_base = *((u32 **)cmdbuf->buf); + + cmdbuf->buf += sizeof(u32 *); + cmdbuf->bufsz -= sizeof(u32 *); + + for (i=0; i < header.scratch.n_bufs; i++) { + buf_idx = *((u32 *)cmdbuf->buf); + buf_idx *= 2; /* 8 bytes per buf */ + + if (DRM_COPY_TO_USER(ref_age_base + buf_idx, &dev_priv->scratch_ages[header.scratch.reg], sizeof(u32))) { + return DRM_ERR(EINVAL); + } + + if (DRM_COPY_FROM_USER(&h_pending, ref_age_base + buf_idx + 1, sizeof(u32))) { + return DRM_ERR(EINVAL); + } + + if (h_pending == 0) { + return DRM_ERR(EINVAL); + } + + h_pending--; + + if (DRM_COPY_TO_USER(ref_age_base + buf_idx + 1, &h_pending, sizeof(u32))) { + return DRM_ERR(EINVAL); + } + + cmdbuf->buf += sizeof(buf_idx); + cmdbuf->bufsz -= sizeof(buf_idx); + } + + BEGIN_RING(2); + OUT_RING( CP_PACKET0( RADEON_SCRATCH_REG0 + header.scratch.reg * 4, 0 ) ); + OUT_RING( dev_priv->scratch_ages[header.scratch.reg] ); + ADVANCE_RING(); + + return 0; +} + /** * Parses and validates a user-supplied command buffer and emits appropriate * commands on the DMA ring buffer. @@ -839,6 +896,15 @@ int r300_do_cp_cmdbuf(drm_device_t *dev, } break; + case R300_CMD_SCRATCH: + DRM_DEBUG("R300_CMD_SCRATCH\n"); + ret = r300_scratch(dev_priv, cmdbuf, header); + if (ret) { + DRM_ERROR("r300_scratch failed\n"); + goto cleanup; + } + break; + default: DRM_ERROR("bad cmd_type %i at %p\n", header.header.cmd_type, |