CS packet parse functions have a lot of in common across
all ASICs. Implement a common function and take care of
small differences between families inside the function.

This patch is a prep for major refactoring and consolidation
of CS parsing code.

Signed-off-by: Ilija Hadzic <ihad...@research.bell-labs.com>
---
 drivers/gpu/drm/radeon/radeon_cs.c  | 53 +++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/radeon/radeon_reg.h | 11 ++++++++
 2 files changed, 64 insertions(+)

diff --git a/drivers/gpu/drm/radeon/radeon_cs.c 
b/drivers/gpu/drm/radeon/radeon_cs.c
index 8b03f1c..95eb673 100644
--- a/drivers/gpu/drm/radeon/radeon_cs.c
+++ b/drivers/gpu/drm/radeon/radeon_cs.c
@@ -639,3 +639,56 @@ u32 radeon_get_ib_value(struct radeon_cs_parser *p, int 
idx)
        idx_value = ibc->kpage[new_page][pg_offset/4];
        return idx_value;
 }
+
+/**
+ * radeon_cs_packet_parse() - parse cp packet and point ib index to next packet
+ * @parser:    parser structure holding parsing context.
+ * @pkt:       where to store packet information
+ *
+ * Assume that chunk_ib_index is properly set. Will return -EINVAL
+ * if packet is bigger than remaining ib size. or if packets is unknown.
+ **/
+int radeon_cs_packet_parse(struct radeon_cs_parser *p,
+                          struct radeon_cs_packet *pkt,
+                          unsigned idx)
+{
+       struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx];
+       struct radeon_device *rdev = p->rdev;
+       uint32_t header;
+
+       if (idx >= ib_chunk->length_dw) {
+               DRM_ERROR("Can not parse packet at %d after CS end %d !\n",
+                         idx, ib_chunk->length_dw);
+               return -EINVAL;
+       }
+       header = radeon_get_ib_value(p, idx);
+       pkt->idx = idx;
+       pkt->type = RADEON_CP_PACKET_GET_TYPE(header);
+       pkt->count = RADEON_CP_PACKET_GET_COUNT(header);
+       pkt->one_reg_wr = 0;
+       switch (pkt->type) {
+       case RADEON_PACKET_TYPE0:
+               if (rdev->family < CHIP_R600) {
+                       pkt->reg = R100_CP_PACKET0_GET_REG(header);
+                       pkt->one_reg_wr =
+                               RADEON_CP_PACKET0_GET_ONE_REG_WR(header);
+               } else
+                       pkt->reg = R600_CP_PACKET0_GET_REG(header);
+               break;
+       case RADEON_PACKET_TYPE3:
+               pkt->opcode = RADEON_CP_PACKET3_GET_OPCODE(header);
+               break;
+       case RADEON_PACKET_TYPE2:
+               pkt->count = -1;
+               break;
+       default:
+               DRM_ERROR("Unknown packet type %d at %d !\n", pkt->type, idx);
+               return -EINVAL;
+       }
+       if ((pkt->count + 1 + pkt->idx) >= ib_chunk->length_dw) {
+               DRM_ERROR("Packet (%d:%d:%d) end after CS buffer (%d) !\n",
+                         pkt->idx, pkt->type, pkt->count, ib_chunk->length_dw);
+               return -EINVAL;
+       }
+       return 0;
+}
diff --git a/drivers/gpu/drm/radeon/radeon_reg.h 
b/drivers/gpu/drm/radeon/radeon_reg.h
index 5d8f735..d9e4204 100644
--- a/drivers/gpu/drm/radeon/radeon_reg.h
+++ b/drivers/gpu/drm/radeon/radeon_reg.h
@@ -3706,4 +3706,15 @@
 
 #define RV530_GB_PIPE_SELECT2           0x4124
 
+#define RADEON_CP_PACKET_GET_TYPE(h) (((h) >> 30) & 3)
+#define RADEON_CP_PACKET_GET_COUNT(h) (((h) >> 16) & 0x3FFF)
+#define RADEON_CP_PACKET0_GET_ONE_REG_WR(h) (((h) >> 15) & 1)
+#define RADEON_CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF)
+#define R100_CP_PACKET0_GET_REG(h) (((h) & 0x1FFF) << 2)
+#define R600_CP_PACKET0_GET_REG(h) (((h) & 0xFFFF) << 2)
+#define RADEON_PACKET_TYPE0 0
+#define RADEON_PACKET_TYPE1 1
+#define RADEON_PACKET_TYPE2 2
+#define RADEON_PACKET_TYPE3 3
+
 #endif
-- 
1.7.12

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to