Ejemplo n.º 1
0
static int radeon_emit_irq(struct drm_device * dev)
{
	drm_radeon_private_t *dev_priv = dev->dev_private;
	unsigned int ret;
	RING_LOCALS;

	atomic_inc(&dev_priv->swi_emitted);
	ret = atomic_read(&dev_priv->swi_emitted);

	BEGIN_RING(4);
	OUT_RING_REG(RADEON_LAST_SWI_REG, ret);
	OUT_RING_REG(RADEON_GEN_INT_STATUS, RADEON_SW_INT_FIRE);
	ADVANCE_RING();
	COMMIT_RING();

	return ret;
}
Ejemplo n.º 2
0
/**
 * Parses and validates a user-supplied command buffer and emits appropriate
 * commands on the DMA ring buffer.
 * Called by the ioctl handler function radeon_cp_cmdbuf.
 */
int r300_do_cp_cmdbuf(drm_device_t* dev,
			  DRMFILE filp,
		      drm_file_t* filp_priv,
		      drm_radeon_cmd_buffer_t* cmdbuf)
{
	drm_radeon_private_t *dev_priv = dev->dev_private;
        drm_device_dma_t *dma = dev->dma;
        drm_buf_t *buf = NULL;
	int emit_dispatch_age = 0;
	int ret = 0;

	DRM_DEBUG("\n");

	/* See the comment above r300_emit_begin3d for why this call must be here,
	 * and what the cleanup gotos are for. */
	r300_pacify(dev_priv);

	if (cmdbuf->nbox <= R300_SIMULTANEOUS_CLIPRECTS) {
		ret = r300_emit_cliprects(dev_priv, cmdbuf, 0);
		if (ret)
			goto cleanup;
		}

	while(cmdbuf->bufsz >= sizeof(drm_r300_cmd_header_t)) {
		int idx;
		drm_r300_cmd_header_t header;

		header.u = *(unsigned int *)cmdbuf->buf;

		cmdbuf->buf += sizeof(header);
		cmdbuf->bufsz -= sizeof(header);

		switch(header.header.cmd_type) {
		case R300_CMD_PACKET0: 
			DRM_DEBUG("R300_CMD_PACKET0\n");
			ret = r300_emit_packet0(dev_priv, cmdbuf, header);
			if (ret) {
				DRM_ERROR("r300_emit_packet0 failed\n");
				goto cleanup;
				}
			break;

		case R300_CMD_VPU:
			DRM_DEBUG("R300_CMD_VPU\n");
			ret = r300_emit_vpu(dev_priv, cmdbuf, header);
			if (ret) {
				DRM_ERROR("r300_emit_vpu failed\n");
				goto cleanup;
				}
			break;

		case R300_CMD_PACKET3:
			DRM_DEBUG("R300_CMD_PACKET3\n");
			ret = r300_emit_packet3(dev_priv, cmdbuf, header);
			if (ret) {
				DRM_ERROR("r300_emit_packet3 failed\n");
				goto cleanup;
				}
			break;

		case R300_CMD_END3D:
			DRM_DEBUG("R300_CMD_END3D\n");
			/* TODO: 
				Ideally userspace driver should not need to issue this call, 
				i.e. the drm driver should issue it automatically and prevent
				lockups.
				
				In practice, we do not understand why this call is needed and what
				it does (except for some vague guesses that it has to do with cache
				coherence) and so the user space driver does it. 
				
				Once we are sure which uses prevent lockups the code could be moved
				into the kernel and the userspace driver will not
				need to use this command.

				Note that issuing this command does not hurt anything
				except, possibly, performance */
			r300_pacify(dev_priv);
			break;

		case R300_CMD_CP_DELAY:
			/* simple enough, we can do it here */
			DRM_DEBUG("R300_CMD_CP_DELAY\n");
			{
				int i;
				RING_LOCALS;

				BEGIN_RING(header.delay.count);
				for(i=0;i<header.delay.count;i++)
					OUT_RING(RADEON_CP_PACKET2);
				ADVANCE_RING();
			}
			break;

		case R300_CMD_DMA_DISCARD:
			DRM_DEBUG("RADEON_CMD_DMA_DISCARD\n");
            		idx = header.dma.buf_idx;
            		if (idx < 0 || idx >= dma->buf_count) {
                		DRM_ERROR("buffer index %d (of %d max)\n",
                      			idx, dma->buf_count - 1);
				ret = DRM_ERR(EINVAL);
                		goto cleanup;
            			}

	                buf = dma->buflist[idx];
            		if (buf->filp != filp || buf->pending) {
                		DRM_ERROR("bad buffer %p %p %d\n",
                      		buf->filp, filp, buf->pending);
                		ret = DRM_ERR(EINVAL);
				goto cleanup;
            			}

			emit_dispatch_age = 1;
			r300_discard_buffer(dev, buf);
            		break;

		case R300_CMD_WAIT:
			/* simple enough, we can do it here */
			DRM_DEBUG("R300_CMD_WAIT\n");
			if(header.wait.flags==0)break; /* nothing to do */

			{
				RING_LOCALS;

				BEGIN_RING(2);
				OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) );
				OUT_RING( (header.wait.flags & 0xf)<<14 );
				ADVANCE_RING();
			}
			break;

		default:
			DRM_ERROR("bad cmd_type %i at %p\n",
			          header.header.cmd_type,
				  cmdbuf->buf - sizeof(header));
			ret = DRM_ERR(EINVAL);
			goto cleanup;
			}
	}

	DRM_DEBUG("END\n");

cleanup:
	r300_pacify(dev_priv);

	/* We emit the vertex buffer age here, outside the pacifier "brackets"
	 * for two reasons:
	 *  (1) This may coalesce multiple age emissions into a single one and
	 *  (2) more importantly, some chips lock up hard when scratch registers
	 *      are written inside the pacifier bracket.
	 */
	if (emit_dispatch_age) {
		RING_LOCALS;

		/* Emit the vertex buffer age */
		BEGIN_RING(2);
		RADEON_DISPATCH_AGE(dev_priv->sarea_priv->last_dispatch);
		ADVANCE_RING();
		}

	COMMIT_RING();

	return ret;
}