aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/drm/r300_cmdbuf.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/drm/r300_cmdbuf.c')
-rw-r--r--drivers/char/drm/r300_cmdbuf.c86
1 files changed, 78 insertions, 8 deletions
diff --git a/drivers/char/drm/r300_cmdbuf.c b/drivers/char/drm/r300_cmdbuf.c
index c08fa5076f05..b108c7f913b2 100644
--- a/drivers/char/drm/r300_cmdbuf.c
+++ b/drivers/char/drm/r300_cmdbuf.c
@@ -214,13 +214,13 @@ void r300_init_reg_flags(void)
214 ADD_RANGE(0x4F54, 1); 214 ADD_RANGE(0x4F54, 1);
215 215
216 ADD_RANGE(R300_TX_FILTER_0, 16); 216 ADD_RANGE(R300_TX_FILTER_0, 16);
217 ADD_RANGE(R300_TX_UNK1_0, 16); 217 ADD_RANGE(R300_TX_FILTER1_0, 16);
218 ADD_RANGE(R300_TX_SIZE_0, 16); 218 ADD_RANGE(R300_TX_SIZE_0, 16);
219 ADD_RANGE(R300_TX_FORMAT_0, 16); 219 ADD_RANGE(R300_TX_FORMAT_0, 16);
220 ADD_RANGE(R300_TX_PITCH_0, 16); 220 ADD_RANGE(R300_TX_PITCH_0, 16);
221 /* Texture offset is dangerous and needs more checking */ 221 /* Texture offset is dangerous and needs more checking */
222 ADD_RANGE_MARK(R300_TX_OFFSET_0, 16, MARK_CHECK_OFFSET); 222 ADD_RANGE_MARK(R300_TX_OFFSET_0, 16, MARK_CHECK_OFFSET);
223 ADD_RANGE(R300_TX_UNK4_0, 16); 223 ADD_RANGE(R300_TX_CHROMA_KEY_0, 16);
224 ADD_RANGE(R300_TX_BORDER_COLOR_0, 16); 224 ADD_RANGE(R300_TX_BORDER_COLOR_0, 16);
225 225
226 /* Sporadic registers used as primitives are emitted */ 226 /* Sporadic registers used as primitives are emitted */
@@ -242,8 +242,10 @@ static __inline__ int r300_check_range(unsigned reg, int count)
242 return 0; 242 return 0;
243} 243}
244 244
245 /* we expect offsets passed to the framebuffer to be either within video memory or 245/*
246 within AGP space */ 246 * we expect offsets passed to the framebuffer to be either within video
247 * memory or within AGP space
248 */
247static __inline__ int r300_check_offset(drm_radeon_private_t *dev_priv, 249static __inline__ int r300_check_offset(drm_radeon_private_t *dev_priv,
248 u32 offset) 250 u32 offset)
249{ 251{
@@ -251,11 +253,11 @@ static __inline__ int r300_check_offset(drm_radeon_private_t *dev_priv,
251 but this value is not being kept. 253 but this value is not being kept.
252 This code is correct for now (does the same thing as the 254 This code is correct for now (does the same thing as the
253 code that sets MC_FB_LOCATION) in radeon_cp.c */ 255 code that sets MC_FB_LOCATION) in radeon_cp.c */
254 if ((offset >= dev_priv->fb_location) && 256 if (offset >= dev_priv->fb_location &&
255 (offset < dev_priv->gart_vm_start)) 257 offset < (dev_priv->fb_location + dev_priv->fb_size))
256 return 0; 258 return 0;
257 if ((offset >= dev_priv->gart_vm_start) && 259 if (offset >= dev_priv->gart_vm_start &&
258 (offset < dev_priv->gart_vm_start + dev_priv->gart_size)) 260 offset < (dev_priv->gart_vm_start + dev_priv->gart_size))
259 return 0; 261 return 0;
260 return 1; 262 return 1;
261} 263}
@@ -490,6 +492,7 @@ static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t *dev_priv,
490 492
491 return 0; 493 return 0;
492} 494}
495
493static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv, 496static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv,
494 drm_radeon_kcmd_buffer_t *cmdbuf) 497 drm_radeon_kcmd_buffer_t *cmdbuf)
495{ 498{
@@ -701,6 +704,64 @@ static void r300_discard_buffer(drm_device_t * dev, drm_buf_t * buf)
701 buf->used = 0; 704 buf->used = 0;
702} 705}
703 706
707static int r300_scratch(drm_radeon_private_t *dev_priv,
708 drm_radeon_kcmd_buffer_t *cmdbuf,
709 drm_r300_cmd_header_t header)
710{
711 u32 *ref_age_base;
712 u32 i, buf_idx, h_pending;
713 RING_LOCALS;
714
715 if (cmdbuf->bufsz <
716 (sizeof(u64) + header.scratch.n_bufs * sizeof(buf_idx))) {
717 return DRM_ERR(EINVAL);
718 }
719
720 if (header.scratch.reg >= 5) {
721 return DRM_ERR(EINVAL);
722 }
723
724 dev_priv->scratch_ages[header.scratch.reg]++;
725
726 ref_age_base = *(u32 **)cmdbuf->buf;
727
728 cmdbuf->buf += sizeof(u64);
729 cmdbuf->bufsz -= sizeof(u64);
730
731 for (i=0; i < header.scratch.n_bufs; i++) {
732 buf_idx = *(u32 *)cmdbuf->buf;
733 buf_idx *= 2; /* 8 bytes per buf */
734
735 if (DRM_COPY_TO_USER(ref_age_base + buf_idx, &dev_priv->scratch_ages[header.scratch.reg], sizeof(u32))) {
736 return DRM_ERR(EINVAL);
737 }
738
739 if (DRM_COPY_FROM_USER(&h_pending, ref_age_base + buf_idx + 1, sizeof(u32))) {
740 return DRM_ERR(EINVAL);
741 }
742
743 if (h_pending == 0) {
744 return DRM_ERR(EINVAL);
745 }
746
747 h_pending--;
748
749 if (DRM_COPY_TO_USER(ref_age_base + buf_idx + 1, &h_pending, sizeof(u32))) {
750 return DRM_ERR(EINVAL);
751 }
752
753 cmdbuf->buf += sizeof(buf_idx);
754 cmdbuf->bufsz -= sizeof(buf_idx);
755 }
756
757 BEGIN_RING(2);
758 OUT_RING(CP_PACKET0(RADEON_SCRATCH_REG0 + header.scratch.reg * 4, 0));
759 OUT_RING(dev_priv->scratch_ages[header.scratch.reg]);
760 ADVANCE_RING();
761
762 return 0;
763}
764
704/** 765/**
705 * Parses and validates a user-supplied command buffer and emits appropriate 766 * Parses and validates a user-supplied command buffer and emits appropriate
706 * commands on the DMA ring buffer. 767 * commands on the DMA ring buffer.
@@ -838,6 +899,15 @@ int r300_do_cp_cmdbuf(drm_device_t *dev,
838 } 899 }
839 break; 900 break;
840 901
902 case R300_CMD_SCRATCH:
903 DRM_DEBUG("R300_CMD_SCRATCH\n");
904 ret = r300_scratch(dev_priv, cmdbuf, header);
905 if (ret) {
906 DRM_ERROR("r300_scratch failed\n");
907 goto cleanup;
908 }
909 break;
910
841 default: 911 default:
842 DRM_ERROR("bad cmd_type %i at %p\n", 912 DRM_ERROR("bad cmd_type %i at %p\n",
843 header.header.cmd_type, 913 header.header.cmd_type,