summaryrefslogtreecommitdiff
path: root/shared-core
diff options
context:
space:
mode:
authorJerome Glisse <glisse@freedesktop.org>2008-11-09 18:48:46 +0100
committerJerome Glisse <glisse@freedesktop.org>2008-11-09 18:48:46 +0100
commit7abb8416a7fd8d69f1f2317cdac2baa8e640671e (patch)
tree0a81377fd014366b2f6c2cfa9a9ac22c3a02f524 /shared-core
parent751d024dd5c91831a8141810c0f40ecdb235e7ca (diff)
radeon: add more packet3 relocations handling
Diffstat (limited to 'shared-core')
-rw-r--r--shared-core/radeon_cs.c99
1 files changed, 78 insertions, 21 deletions
diff --git a/shared-core/radeon_cs.c b/shared-core/radeon_cs.c
index 3dde321d..56f6cbac 100644
--- a/shared-core/radeon_cs.c
+++ b/shared-core/radeon_cs.c
@@ -180,7 +180,6 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv)
struct drm_radeon_cs *cs = data;
uint32_t *packets = NULL;
uint32_t cs_id;
- uint32_t card_offset;
long size;
int r;
struct drm_radeon_kernel_chunk chunk_fake[1];
@@ -280,12 +279,11 @@ static __inline__ int radeon_cs_relocate_packet0(struct drm_radeon_cs_parser *pa
old kernels ignore it. */
if (parser->reloc_index == -1) {
if (packet3_hdr != (RADEON_CP_PACKET3 | RADEON_CP_NOP | (RELOC_SIZE << 16))) {
- DRM_ERROR("Packet 3 was %x should have been %x: reg is %x\n", packet3_hdr, RADEON_CP_PACKET3 | RADEON_CP_NOP | (RELOC_SIZE << 16), reg);
+ DRM_ERROR("Packet 3 was %x should have been %x: reg is %x at %d\n", packet3_hdr, RADEON_CP_PACKET3 | RADEON_CP_NOP | (RELOC_SIZE << 16), reg, offset_dw);
return -EINVAL;
}
- } else {
if (packet3_hdr != (RADEON_CP_PACKET3 | RADEON_CP_NOP | (RELOC_SIZE_NEW << 16))) {
- DRM_ERROR("Packet 3 was %x should have been %x: reg is %x\n", packet3_hdr, RADEON_CP_PACKET3 | RADEON_CP_NOP | (RELOC_SIZE_NEW << 16), reg);
+ DRM_ERROR("Packet 3 was %x should have been %x: reg is %x at %d\n", packet3_hdr, RADEON_CP_PACKET3 | RADEON_CP_NOP | (RELOC_SIZE_NEW << 16), reg, offset_dw);
return -EINVAL;
}
@@ -295,9 +293,11 @@ static __inline__ int radeon_cs_relocate_packet0(struct drm_radeon_cs_parser *pa
case RADEON_DST_PITCH_OFFSET:
case RADEON_SRC_PITCH_OFFSET:
/* pass in the start of the reloc */
- ret = dev_priv->cs.relocate(parser, ib_chunk->kdata + offset_dw + 2, &offset);
- if (ret)
+ ret = dev_priv->cs.relocate(parser,
+ ib_chunk->kdata + offset_dw + 2, &offset);
+ if (ret) {
return ret;
+ }
tmp = (val & RADEON_2D_OFFSET_MASK) << 10;
val &= ~RADEON_2D_OFFSET_MASK;
offset += tmp;
@@ -313,9 +313,12 @@ static __inline__ int radeon_cs_relocate_packet0(struct drm_radeon_cs_parser *pa
case R200_PP_TXOFFSET_1:
case RADEON_PP_TXOFFSET_0:
case RADEON_PP_TXOFFSET_1:
- ret = dev_priv->cs.relocate(parser, ib_chunk->kdata + offset_dw + 2, &offset);
- if (ret)
+ ret = dev_priv->cs.relocate(parser,
+ ib_chunk->kdata + offset_dw + 2, &offset);
+ if (ret) {
+ DRM_ERROR("Failed to relocate %d\n", offset_dw);
return ret;
+ }
offset &= 0xffffffe0;
val += offset;
@@ -332,8 +335,9 @@ static int radeon_cs_relocate_packet3(struct drm_radeon_cs_parser *parser,
uint32_t offset_dw)
{
drm_radeon_private_t *dev_priv = parser->dev->dev_private;
- uint32_t hdr, num_dw, reg;
- uint32_t offset, val, tmp;
+ uint32_t hdr, num_dw, reg, i;
+ uint32_t offset, val, tmp, nptr, cptr;
+ uint32_t *reloc;
int ret;
struct drm_radeon_kernel_chunk *ib_chunk;
@@ -347,11 +351,13 @@ static int radeon_cs_relocate_packet3(struct drm_radeon_cs_parser *parser,
switch(reg) {
case RADEON_CNTL_HOSTDATA_BLT:
- {
val = ib_chunk->kdata[offset_dw + 2];
- ret = dev_priv->cs.relocate(parser, ib_chunk->kdata + offset_dw + num_dw + 2, &offset);
- if (ret)
+ ret = dev_priv->cs.relocate(parser,
+ ib_chunk->kdata + offset_dw + num_dw + 2,
+ &offset);
+ if (ret) {
return ret;
+ }
tmp = (val & RADEON_2D_OFFSET_MASK) << 10;
val &= ~RADEON_2D_OFFSET_MASK;
@@ -360,8 +366,48 @@ static int radeon_cs_relocate_packet3(struct drm_radeon_cs_parser *parser,
val |= offset;
ib_chunk->kdata[offset_dw + 2] = val;
- }
+ break;
+ case RADEON_3D_LOAD_VBPNTR:
+ nptr = ib_chunk->kdata[offset_dw + 1];
+ cptr = offset_dw + 3;
+ for (i = 0; i < (nptr & ~1); i+= 2) {
+ reloc = ib_chunk->kdata + offset_dw + num_dw + 2;
+ reloc += ((i + 0) * 2);
+ ret = dev_priv->cs.relocate(parser, reloc, &offset);
+ if (ret) {
+ return ret;
+ }
+ ib_chunk->kdata[cptr] += offset;
+ cptr += 1;
+ reloc = ib_chunk->kdata + offset_dw + num_dw + 2;
+ reloc += ((i + 1) * 2);
+ ret = dev_priv->cs.relocate(parser, reloc, &offset);
+ if (ret) {
+ return ret;
+ }
+ ib_chunk->kdata[cptr] += offset;
+ cptr += 2;
+ }
+ if (nptr & 1) {
+ reloc = ib_chunk->kdata + offset_dw + num_dw + 2;
+ reloc += ((nptr - 1) * 2);
+ ret = dev_priv->cs.relocate(parser, reloc, &offset);
+ if (ret) {
+ return ret;
+ }
+ ib_chunk->kdata[cptr] += offset;
+ }
+ break;
+ case RADEON_CP_INDX_BUFFER:
+ reloc = ib_chunk->kdata + offset_dw + num_dw + 2;
+ ret = dev_priv->cs.relocate(parser, reloc, &offset);
+ if (ret) {
+ return ret;
+ }
+ ib_chunk->kdata[offset_dw + 2] += offset;
+ break;
default:
+ DRM_ERROR("Unknown packet3 0x%08X\n", hdr);
return -EINVAL;
}
return 0;
@@ -377,6 +423,12 @@ int radeon_cs_packet0(struct drm_radeon_cs_parser *parser, uint32_t offset_dw)
num_dw = ((hdr & RADEON_CP_PACKET_COUNT_MASK) >> 16) + 2;
reg = (hdr & R300_CP_PACKET0_REG_MASK) << 2;
+ if (hdr & (1 << 15)) {
+ if (reg == 0x2208) {
+ return 0;
+ }
+ }
+
while (count_dw < num_dw) {
/* need to have something like the r300 validation here -
list of allowed registers */
@@ -405,7 +457,8 @@ int radeon_cs_packet0(struct drm_radeon_cs_parser *parser, uint32_t offset_dw)
} else if (flags == MARK_CHECK_SCISSOR) {
DRM_DEBUG("need to validate scissor %x %d\n", reg, flags);
} else {
- DRM_DEBUG("illegal register %x %d\n", reg, flags);
+
+ DRM_ERROR("illegal register 0x%x %d at %d\n", reg, flags, offset_dw);
return -EINVAL;
}
break;
@@ -435,6 +488,8 @@ int radeon_cs_parse(struct drm_radeon_cs_parser *parser)
switch (hdr & RADEON_CP_PACKET_MASK) {
case RADEON_CP_PACKET0:
ret = radeon_cs_packet0(parser, count_dw);
+ if (ret)
+ return ret;
break;
case RADEON_CP_PACKET1:
case RADEON_CP_PACKET2:
@@ -446,14 +501,17 @@ int radeon_cs_parse(struct drm_radeon_cs_parser *parser)
reg = hdr & 0xff00;
switch(reg) {
+ case RADEON_3D_LOAD_VBPNTR:
+ case RADEON_CP_INDX_BUFFER:
case RADEON_CNTL_HOSTDATA_BLT:
- radeon_cs_relocate_packet3(parser, count_dw);
+ ret =radeon_cs_relocate_packet3(parser,
+ count_dw);
+ if (ret)
+ return ret;
break;
case RADEON_CNTL_BITBLT_MULTI:
- case RADEON_3D_LOAD_VBPNTR: /* load vertex array pointers */
- case RADEON_CP_INDX_BUFFER:
- DRM_ERROR("need relocate packet 3 for %x\n", reg);
+ DRM_ERROR("need relocate packet 3 for %x %d\n", reg, count_dw);
break;
case RADEON_3D_DRAW_IMMD: /* triggers drawing using in-packet vertex data */
@@ -464,12 +522,11 @@ int radeon_cs_parse(struct drm_radeon_cs_parser *parser)
case RADEON_CP_NOP:
break;
default:
- DRM_ERROR("unknown packet 3 %x\n", reg);
+ DRM_ERROR("unknown packet 3 %x at %d\n", reg, count_dw);
ret = -EINVAL;
}
break;
}
-
count_dw += num_dw+2;
}