drm: Add general-purpose packet for manipulating scratch registers (r300)
authorDave Airlie <airlied@linux.ie>
Sun, 19 Mar 2006 08:45:26 +0000 (19:45 +1100)
committerDave Airlie <airlied@linux.ie>
Sun, 19 Mar 2006 08:45:26 +0000 (19:45 +1100)
From: Aapo Tahkola (via DRM CVS)
Signed-off-by: Dave Airlie <airlied@linux.ie>
drivers/char/drm/r300_cmdbuf.c
drivers/char/drm/radeon_drm.h
drivers/char/drm/radeon_drv.h

index 20b6cb39213d2a66baebd40a4208cd5cc9f29bfd..b108c7f913b2cb75ef93924f00845bd40f1bc778 100644 (file)
@@ -704,6 +704,64 @@ static void r300_discard_buffer(drm_device_t * dev, drm_buf_t * buf)
        buf->used = 0;
 }
 
+static 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(u64) + 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(u64);
+       cmdbuf->bufsz -= sizeof(u64);
+       
+       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.
@@ -841,6 +899,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,
index bb63e6806fd13637927e08438a772398d2dff308..c8e279e89c2e51d43ff2c92c1bd6a8483f12c461 100644 (file)
@@ -222,6 +222,7 @@ typedef union {
 #      define R300_WAIT_3D             0x2
 #      define R300_WAIT_2D_CLEAN       0x3
 #      define R300_WAIT_3D_CLEAN       0x4
+#define R300_CMD_SCRATCH               8
 
 typedef union {
        unsigned int u;
@@ -247,6 +248,9 @@ typedef union {
        struct {
                unsigned char cmd_type, flags, pad0, pad1;
        } wait;
+       struct {
+               unsigned char cmd_type, reg, n_bufs, flags;
+       } scratch;
 } drm_r300_cmd_header_t;
 
 #define RADEON_FRONT                   0x1
index a0c198895a27da13896401f873bcebc0f31334c8..5cf555e4637bf0983580e83d9fc8840ceb61bb42 100644 (file)
  * 1.21- Add support for card type getparam
  * 1.22- Add support for texture cache flushes (R300_TX_CNTL)
  * 1.23- Add new radeon memory map work from benh
+ * 1.24- Add general-purpose packet for manipulating scratch registers (r300)
  */
 #define DRIVER_MAJOR           1
-#define DRIVER_MINOR           23
+#define DRIVER_MINOR           24
 #define DRIVER_PATCHLEVEL      0
 
 /*
@@ -276,6 +277,8 @@ typedef struct drm_radeon_private {
        unsigned long pcigart_offset;
        drm_ati_pcigart_info gart_info;
 
+       u32 scratch_ages[5];
+
        /* starting from here on, data is preserved accross an open */
        uint32_t flags;         /* see radeon_chip_flags */
 } drm_radeon_private_t;