r300: initial command stream parser for packet 0.
authorDave Airlie <airlied@redhat.com>
Mon, 28 Jul 2008 07:27:24 +0000 (17:27 +1000)
committerDave Airlie <airlied@redhat.com>
Mon, 28 Jul 2008 07:27:24 +0000 (17:27 +1000)
this at least parses the DDX stream and lets me run gnome-terminal/metacity

linux-core/radeon_reg.h
shared-core/r300_cmdbuf.c
shared-core/radeon_cp.c
shared-core/radeon_cs.c
shared-core/radeon_drv.h

index a5be6a6..784b3b5 100644 (file)
 #       define RADEON_CP_PACKET_COUNT_MASK          0x3fff0000
 #       define RADEON_CP_PACKET_MAX_DWORDS          (1 << 12)
 #       define RADEON_CP_PACKET0_REG_MASK           0x000007ff
+#       define R300_CP_PACKET0_REG_MASK             0x00001fff
 #       define RADEON_CP_PACKET1_REG0_MASK          0x000007ff
 #       define RADEON_CP_PACKET1_REG1_MASK          0x003ff800
 
index e8f18db..f411155 100644 (file)
@@ -151,8 +151,6 @@ void r300_init_reg_flags(struct drm_device *dev)
                for(i=((reg)>>2);i<((reg)>>2)+(count);i++)\
                        r300_reg_flags[i]|=(mark);
 
-#define MARK_SAFE              1
-#define MARK_CHECK_OFFSET      2
 
 #define ADD_RANGE(reg, count)  ADD_RANGE_MARK(reg, count, MARK_SAFE)
 
@@ -234,6 +232,11 @@ void r300_init_reg_flags(struct drm_device *dev)
        ADD_RANGE(R300_VAP_INPUT_ROUTE_0_0, 8);
        ADD_RANGE(R300_VAP_INPUT_ROUTE_1_0, 8);
 
+       ADD_RANGE(R500_SU_REG_DEST, 1);
+       if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV410) {
+               ADD_RANGE(R300_DST_PIPE_CONFIG, 1);
+       }
+
        if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) {
                ADD_RANGE(R500_VAP_INDEX_OFFSET, 1);
                ADD_RANGE(R500_US_CONFIG, 2);
@@ -243,6 +246,8 @@ void r300_init_reg_flags(struct drm_device *dev)
                ADD_RANGE(R500_RS_INST_0, 16);
                ADD_RANGE(R500_RB3D_COLOR_CLEAR_VALUE_AR, 2);
                ADD_RANGE(R500_RB3D_CONSTANT_COLOR_AR, 2);
+
+               ADD_RANGE(R500_GA_US_VECTOR_INDEX, 2);
        } else {
                ADD_RANGE(R300_PFS_CNTL_0, 3);
                ADD_RANGE(R300_PFS_NODE_0, 4);
@@ -255,9 +260,39 @@ void r300_init_reg_flags(struct drm_device *dev)
                ADD_RANGE(R300_RS_ROUTE_0, 8);
 
        }
+
+       /* add 2d blit engine registers for DDX */
+       ADD_RANGE(RADEON_SRC_Y_X, 3); /* 1434, 1438, 143c, 
+                                        SRC_Y_X, DST_Y_X, DST_HEIGHT_WIDTH
+                                      */
+       ADD_RANGE(RADEON_DP_GUI_MASTER_CNTL, 1); /* 146c */
+       ADD_RANGE(RADEON_DP_BRUSH_BKGD_CLR, 2); /* 1478, 147c */
+       ADD_RANGE(RADEON_DP_SRC_FRGD_CLR, 2); /* 15d8, 15dc */
+       ADD_RANGE(RADEON_DP_CNTL, 1); /* 16c0 */
+       ADD_RANGE(RADEON_DP_WRITE_MASK, 1); /* 16cc */
+       ADD_RANGE(RADEON_DEFAULT_SC_BOTTOM_RIGHT, 1); /* 16e8 */
+
+       ADD_RANGE(RADEON_DSTCACHE_CTLSTAT, 1);
+       ADD_RANGE(RADEON_WAIT_UNTIL, 1);
+
+       ADD_RANGE_MARK(RADEON_DST_OFFSET, 1, MARK_CHECK_OFFSET);
+       ADD_RANGE_MARK(RADEON_SRC_OFFSET, 1, MARK_CHECK_OFFSET);
+
+       ADD_RANGE_MARK(RADEON_DST_PITCH_OFFSET, 1, MARK_CHECK_OFFSET);
+       ADD_RANGE_MARK(RADEON_SRC_PITCH_OFFSET, 1, MARK_CHECK_OFFSET);
+
+       /* TODO SCISSOR */
+       ADD_RANGE_MARK(R300_SC_SCISSOR0, 2, MARK_CHECK_SCISSOR);
+
+       ADD_RANGE(R300_SC_CLIP_0_A, 2);
+       ADD_RANGE(R300_SC_CLIP_RULE, 1);
+       ADD_RANGE(R300_SC_SCREENDOOR, 1);
+
+       ADD_RANGE(R300_VAP_PVS_CODE_CNTL_0, 4);
+       ADD_RANGE(R300_VAP_PVS_VECTOR_INDX_REG, 2);
 }
 
-static __inline__ int r300_check_range(unsigned reg, int count)
+int r300_check_range(unsigned reg, int count)
 {
        int i;
        if (reg & ~0xffff)
@@ -268,6 +303,13 @@ static __inline__ int r300_check_range(unsigned reg, int count)
        return 0;
 }
 
+int r300_get_reg_flags(unsigned reg)
+{
+       if (reg & ~0xffff)
+               return -1;
+       return r300_reg_flags[(reg >> 2)];
+}
+
 static __inline__ int r300_emit_carefully_checked_packet0(drm_radeon_private_t *
                                                          dev_priv,
                                                          drm_radeon_kcmd_buffer_t
index 46f4290..48f72ab 100644 (file)
@@ -2301,6 +2301,8 @@ int radeon_modeset_cp_init(struct drm_device *dev)
 
        dev_priv->new_memmap = 1;
 
+       r300_init_reg_flags(dev);
+               
        radeon_cp_load_microcode(dev_priv);
        
        DRM_DEBUG("ring offset is %x %x\n", dev_priv->mm.ring.bo->offset, dev_priv->mm.ring_read.bo->offset);
index 61fef79..8c2aea8 100644 (file)
@@ -88,11 +88,84 @@ out:
        return r;
 }
 
+int radeon_cs_packet0(struct drm_device *dev, uint32_t *packets,
+                     uint32_t offset_dw)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       int hdr = packets[offset_dw];
+       int num_dw = ((hdr & RADEON_CP_PACKET_COUNT_MASK) >> 16) + 2;
+       int need_reloc = 0;
+       int reg = (hdr & R300_CP_PACKET0_REG_MASK) << 2;
+       int count_dw = 1;
+       int ret;
+
+       while (count_dw < num_dw) {
+               /* need to have something like the r300 validation here - 
+                  list of allowed registers */
+               int flags;
+
+               ret = r300_check_range(reg, 1);
+               switch(ret) {
+               case -1:
+                       DRM_ERROR("Illegal register %x\n", reg);
+                       break;
+               case 0:
+                       break;
+               case 1:
+                       flags = r300_get_reg_flags(reg);
+                       if (flags == MARK_CHECK_OFFSET)
+                               DRM_DEBUG("need to relocate %x %d\n", reg, flags);
+                       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);
+                               return -EINVAL;
+                       }
+                       break;
+               }
+               count_dw++;
+               reg += 4;
+       }
+       return 0;
+}
+
 int radeon_cs_parse(struct drm_device *dev, void *ib,
                    uint32_t *packets, uint32_t dwords)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
        volatile int rb;
+       int size_dw = dwords;
+       /* scan the packet for various things */
+       int count_dw = 0;
+       int ret = 0;
+
+       while (count_dw < size_dw && ret == 0) {
+               int hdr = packets[count_dw];
+               int num_dw = (hdr & RADEON_CP_PACKET_COUNT_MASK) >> 16;
+               int reg;
+
+               switch (hdr & RADEON_CP_PACKET_MASK) {
+               case RADEON_CP_PACKET0:
+                       ret = radeon_cs_packet0(dev, packets, count_dw);
+                       break;
+               case RADEON_CP_PACKET1:
+               case RADEON_CP_PACKET2:
+                       reg = hdr & RADEON_CP_PACKET0_REG_MASK;
+                       DRM_DEBUG("Packet 1/2: %d  %x\n", num_dw, reg);
+                       break;
+
+               case RADEON_CP_PACKET3:
+                       reg = hdr & 0xff00;
+                       DRM_DEBUG("Packet 3: %d  %x\n", num_dw, reg);
+                       break;
+               }
+
+               count_dw += num_dw+2;
+       }
+
+       if (ret)
+               return ret;
+            
 
        /* copy the packet into the IB */
        memcpy(ib, packets, dwords * sizeof(uint32_t));
index c431fe4..232102d 100644 (file)
@@ -1619,4 +1619,11 @@ extern void radeon_master_destroy(struct drm_device *dev, struct drm_master *mas
 extern void radeon_cp_dispatch_flip(struct drm_device * dev, struct drm_master *master);
 extern int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv);
 extern int radeon_cs_init(struct drm_device *dev);
+
+#define MARK_SAFE              1
+#define MARK_CHECK_OFFSET      2
+#define MARK_CHECK_SCISSOR     3
+
+extern int r300_check_range(unsigned reg, int count);
+extern int r300_get_reg_flags(unsigned reg);
 #endif                         /* __RADEON_DRV_H__ */