summaryrefslogtreecommitdiff
path: root/shared-core
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2008-07-29 18:05:11 +1000
committerDave Airlie <airlied@redhat.com>2008-07-29 18:05:11 +1000
commit0452be882607f2d1601f4e592a11ccf543f5f9ca (patch)
tree1009f88f5969147114374224b12b3d7548d829fd /shared-core
parent4234f82acc70f41e005d8cc301da56634352425c (diff)
radeon: move code around putting emit into cs
Diffstat (limited to 'shared-core')
-rw-r--r--shared-core/radeon_cs.c76
-rw-r--r--shared-core/radeon_drv.h4
2 files changed, 59 insertions, 21 deletions
diff --git a/shared-core/radeon_cs.c b/shared-core/radeon_cs.c
index f01334bc..33a8ccd4 100644
--- a/shared-core/radeon_cs.c
+++ b/shared-core/radeon_cs.c
@@ -31,19 +31,21 @@
int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv)
{
- struct drm_radeon_private *radeon = dev->dev_private;
+ struct drm_radeon_private *dev_priv = dev->dev_private;
struct drm_radeon_cs *cs = data;
uint32_t *packets = NULL;
uint32_t cs_id;
+ uint32_t card_offset;
void *ib = NULL;
long size;
int r;
+ RING_LOCALS;
/* set command stream id to 0 which is fake id */
cs_id = 0;
DRM_COPY_TO_USER(&cs->cs_id, &cs_id, sizeof(uint32_t));
- if (radeon == NULL) {
+ if (dev_priv == NULL) {
DRM_ERROR("called with no initialization\n");
return -EINVAL;
}
@@ -68,22 +70,31 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv)
goto out;
}
/* get ib */
- r = radeon->cs.ib_get(dev, &ib, cs->dwords);
+ r = dev_priv->cs.ib_get(dev, &ib, cs->dwords, &card_offset);
if (r) {
goto out;
}
/* now parse command stream */
- r = radeon->cs.parse(dev, fpriv, ib, packets, cs->dwords);
+ r = dev_priv->cs.parse(dev, fpriv, ib, packets, cs->dwords);
if (r) {
goto out;
}
+ BEGIN_RING(4);
+ OUT_RING(CP_PACKET0(RADEON_CP_IB_BASE, 1));
+ OUT_RING(card_offset);
+ OUT_RING(cs->dwords);
+ OUT_RING(CP_PACKET2());
+ ADVANCE_RING();
+
/* emit cs id sequence */
- radeon->cs.id_emit(dev, &cs_id);
+ dev_priv->cs.id_emit(dev, &cs_id);
+ COMMIT_RING();
+
DRM_COPY_TO_USER(&cs->cs_id, &cs_id, sizeof(uint32_t));
out:
- radeon->cs.ib_free(dev, ib, cs->dwords);
+ dev_priv->cs.ib_free(dev, ib, cs->dwords);
drm_free(packets, size, DRM_MEM_DRIVER);
return r;
}
@@ -97,8 +108,8 @@ static int radeon_nomm_relocate(struct drm_device *dev, struct drm_file *file_pr
#define RELOC_SIZE 2
#define RADEON_2D_OFFSET_MASK 0x3fffff
-static __inline__ int radeon_cs_relocate_offset(struct drm_device *dev, struct drm_file *file_priv,
- uint32_t *packets, uint32_t offset_dw)
+static __inline__ int radeon_cs_relocate_packet0(struct drm_device *dev, struct drm_file *file_priv,
+ uint32_t *packets, uint32_t offset_dw)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
uint32_t hdr = packets[offset_dw];
@@ -107,7 +118,7 @@ static __inline__ int radeon_cs_relocate_offset(struct drm_device *dev, struct d
uint32_t packet3_hdr = packets[offset_dw+2];
uint32_t tmp, offset;
int ret;
-
+
/* this is too strict we may want to expand the length in the future and have
old kernels ignore it. */
if (packet3_hdr != (RADEON_CP_PACKET3 | RADEON_CP_NOP | (RELOC_SIZE << 16))) {
@@ -132,8 +143,6 @@ static __inline__ int radeon_cs_relocate_offset(struct drm_device *dev, struct d
case R300_RB3D_DEPTHOFFSET:
case R300_TX_OFFSET_0:
case R300_TX_OFFSET_0+4:
- offset = packets[offset_dw + 3];
-
ret = dev_priv->cs.relocate(dev, file_priv, packets + offset_dw + 2, &offset);
if (ret)
return ret;
@@ -151,6 +160,40 @@ static __inline__ int radeon_cs_relocate_offset(struct drm_device *dev, struct d
return 0;
}
+
+static int radeon_cs_relocate_packet3(struct drm_device *dev, struct drm_file *file_priv,
+ uint32_t *packets, uint32_t offset_dw)
+{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ uint32_t hdr = packets[offset_dw];
+ int num_dw = (hdr & RADEON_CP_PACKET_COUNT_MASK) >> 16;
+ uint32_t reg = hdr & 0xff00;
+ uint32_t offset, val, tmp;
+ int ret;
+
+ switch(reg) {
+ case RADEON_CNTL_HOSTDATA_BLT:
+ {
+ val = packets[offset_dw + 2];
+ ret = dev_priv->cs.relocate(dev, file_priv, packets + offset_dw + num_dw + 2, &offset);
+ if (ret)
+ return ret;
+
+ tmp = (val & RADEON_2D_OFFSET_MASK) << 10;
+ val &= ~RADEON_2D_OFFSET_MASK;
+ offset += tmp;
+ offset >>= 10;
+ val |= offset;
+
+ DRM_ERROR("New offset %x %x %x\n", packets[offset_dw+2], val, offset);
+ packets[offset_dw + 2] = val;
+ }
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
static __inline__ int radeon_cs_check_offset(struct drm_device *dev,
uint32_t reg, uint32_t val)
{
@@ -207,7 +250,7 @@ int radeon_cs_packet0(struct drm_device *dev, struct drm_file *file_priv,
return -EINVAL;
}
- ret = radeon_cs_relocate_offset(dev, file_priv, packets, offset_dw);
+ ret = radeon_cs_relocate_packet0(dev, file_priv, packets, offset_dw);
if (ret)
return ret;
DRM_DEBUG("need to relocate %x %d\n", reg, flags);
@@ -256,14 +299,9 @@ int radeon_cs_parse(struct drm_device *dev, struct drm_file *file_priv,
switch(reg) {
case RADEON_CNTL_HOSTDATA_BLT:
- {
- uint32_t offset;
- offset = packets[count_dw+2] & ((1 << 22) - 1);
- offset <<= 10;
- DRM_ERROR("Offset check for Packet 3 %x %x\n", reg, offset);
- /* okay it should be followed by a NOP */
+ radeon_cs_relocate_packet3(dev, file_priv, packets, count_dw);
break;
- }
+
case RADEON_CNTL_BITBLT_MULTI:
case RADEON_3D_LOAD_VBPNTR: /* load vertex array pointers */
case RADEON_CP_INDX_BUFFER:
diff --git a/shared-core/radeon_drv.h b/shared-core/radeon_drv.h
index f79eade5..e55a9697 100644
--- a/shared-core/radeon_drv.h
+++ b/shared-core/radeon_drv.h
@@ -300,11 +300,11 @@ struct drm_radeon_cs_priv {
/* this ib handling callback are for hidding memory manager drm
* from memory manager less drm, free have to emit ib discard
* sequence into the ring */
- int (*ib_get)(struct drm_device *dev, void **ib, uint32_t dwords);
+ int (*ib_get)(struct drm_device *dev, void **ib, uint32_t dwords, uint32_t *card_offset);
uint32_t (*ib_get_ptr)(struct drm_device *dev, void *ib);
void (*ib_free)(struct drm_device *dev, void *ib, uint32_t dwords);
/* do a relocation either MM or non-MM */
- bool (*relocate)(struct drm_device *dev, struct drm_file *file_priv,
+ int (*relocate)(struct drm_device *dev, struct drm_file *file_priv,
uint32_t *reloc, uint32_t *offset);
};