Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ee4621f0 authored by Dave Airlie's avatar Dave Airlie
Browse files

drm: Add general-purpose packet for manipulating scratch registers (r300)



From: Aapo Tahkola (via DRM CVS)
Signed-off-by: default avatarDave Airlie <airlied@linux.ie>
parent d5ea702f
Loading
Loading
Loading
Loading
+67 −0
Original line number Diff line number Diff line
@@ -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,
+4 −0
Original line number Diff line number Diff line
@@ -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
+4 −1
Original line number Diff line number Diff line
@@ -92,9 +92,10 @@
 * 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;