r300_cmdbuf.c 31.7 KB
Newer Older
D
Dave Airlie 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
/* r300_cmdbuf.c -- Command buffer emission for R300 -*- linux-c -*-
 *
 * Copyright (C) The Weather Channel, Inc.  2002.
 * Copyright (C) 2004 Nicolai Haehnle.
 * All Rights Reserved.
 *
 * The Weather Channel (TM) funded Tungsten Graphics to develop the
 * initial release of the Radeon 8500 driver under the XFree86 license.
 * This notice must be preserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 * Authors:
 *    Nicolai Haehnle <prefect_@gmx.net>
 */

#include "drmP.h"
#include "drm.h"
36
#include "drm_buffer.h"
D
Dave Airlie 已提交
37 38 39 40
#include "radeon_drm.h"
#include "radeon_drv.h"
#include "r300_reg.h"

41 42
#include <asm/unaligned.h>

D
Dave Airlie 已提交
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
#define R300_SIMULTANEOUS_CLIPRECTS		4

/* Values for R300_RE_CLIPRECT_CNTL depending on the number of cliprects
 */
static const int r300_cliprect_cntl[4] = {
	0xAAAA,
	0xEEEE,
	0xFEFE,
	0xFFFE
};

/**
 * Emit up to R300_SIMULTANEOUS_CLIPRECTS cliprects from the given command
 * buffer, starting with index n.
 */
58 59
static int r300_emit_cliprects(drm_radeon_private_t *dev_priv,
			       drm_radeon_kcmd_buffer_t *cmdbuf, int n)
D
Dave Airlie 已提交
60
{
61
	struct drm_clip_rect box;
D
Dave Airlie 已提交
62 63 64 65 66 67 68 69 70 71 72
	int nr;
	int i;
	RING_LOCALS;

	nr = cmdbuf->nbox - n;
	if (nr > R300_SIMULTANEOUS_CLIPRECTS)
		nr = R300_SIMULTANEOUS_CLIPRECTS;

	DRM_DEBUG("%i cliprects\n", nr);

	if (nr) {
D
Dave Airlie 已提交
73 74
		BEGIN_RING(6 + nr * 2);
		OUT_RING(CP_PACKET0(R300_RE_CLIPRECT_TL_0, nr * 2 - 1));
D
Dave Airlie 已提交
75

D
Dave Airlie 已提交
76 77 78
		for (i = 0; i < nr; ++i) {
			if (DRM_COPY_FROM_USER_UNCHECKED
			    (&box, &cmdbuf->boxes[n + i], sizeof(box))) {
D
Dave Airlie 已提交
79
				DRM_ERROR("copy cliprect faulted\n");
E
Eric Anholt 已提交
80
				return -EFAULT;
D
Dave Airlie 已提交
81 82
			}

N
Nicolai Haehnle 已提交
83 84 85
			box.x2--; /* Hardware expects inclusive bottom-right corner */
			box.y2--;

D
Dave Airlie 已提交
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
			if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) {
				box.x1 = (box.x1) &
					R300_CLIPRECT_MASK;
				box.y1 = (box.y1) &
					R300_CLIPRECT_MASK;
				box.x2 = (box.x2) &
					R300_CLIPRECT_MASK;
				box.y2 = (box.y2) &
					R300_CLIPRECT_MASK;
			} else {
				box.x1 = (box.x1 + R300_CLIPRECT_OFFSET) &
					R300_CLIPRECT_MASK;
				box.y1 = (box.y1 + R300_CLIPRECT_OFFSET) &
					R300_CLIPRECT_MASK;
				box.x2 = (box.x2 + R300_CLIPRECT_OFFSET) &
					R300_CLIPRECT_MASK;
				box.y2 = (box.y2 + R300_CLIPRECT_OFFSET) &
					R300_CLIPRECT_MASK;
			}
N
Nicolai Haehnle 已提交
105

D
Dave Airlie 已提交
106
			OUT_RING((box.x1 << R300_CLIPRECT_X_SHIFT) |
D
Dave Airlie 已提交
107
				 (box.y1 << R300_CLIPRECT_Y_SHIFT));
D
Dave Airlie 已提交
108
			OUT_RING((box.x2 << R300_CLIPRECT_X_SHIFT) |
D
Dave Airlie 已提交
109
				 (box.y2 << R300_CLIPRECT_Y_SHIFT));
D
Dave Airlie 已提交
110

D
Dave Airlie 已提交
111 112
		}

D
Dave Airlie 已提交
113
		OUT_RING_REG(R300_RE_CLIPRECT_CNTL, r300_cliprect_cntl[nr - 1]);
D
Dave Airlie 已提交
114 115

		/* TODO/SECURITY: Force scissors to a safe value, otherwise the
D
Dave Airlie 已提交
116 117 118 119 120 121 122
		 * client might be able to trample over memory.
		 * The impact should be very limited, but I'd rather be safe than
		 * sorry.
		 */
		OUT_RING(CP_PACKET0(R300_RE_SCISSORS_TL, 1));
		OUT_RING(0);
		OUT_RING(R300_SCISSORS_X_MASK | R300_SCISSORS_Y_MASK);
D
Dave Airlie 已提交
123
		ADVANCE_RING();
D
Dave Airlie 已提交
124
	} else {
D
Dave Airlie 已提交
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
		/* Why we allow zero cliprect rendering:
		 * There are some commands in a command buffer that must be submitted
		 * even when there are no cliprects, e.g. DMA buffer discard
		 * or state setting (though state setting could be avoided by
		 * simulating a loss of context).
		 *
		 * Now since the cmdbuf interface is so chaotic right now (and is
		 * bound to remain that way for a bit until things settle down),
		 * it is basically impossible to filter out the commands that are
		 * necessary and those that aren't.
		 *
		 * So I choose the safe way and don't do any filtering at all;
		 * instead, I simply set up the engine so that all rendering
		 * can't produce any fragments.
		 */
		BEGIN_RING(2);
D
Dave Airlie 已提交
141
		OUT_RING_REG(R300_RE_CLIPRECT_CNTL, 0);
D
Dave Airlie 已提交
142
		ADVANCE_RING();
D
Dave Airlie 已提交
143
	}
D
Dave Airlie 已提交
144

145 146 147 148 149 150 151 152 153 154 155 156
	/* flus cache and wait idle clean after cliprect change */
	BEGIN_RING(2);
	OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
	OUT_RING(R300_RB3D_DC_FLUSH);
	ADVANCE_RING();
	BEGIN_RING(2);
	OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
	OUT_RING(RADEON_WAIT_3D_IDLECLEAN);
	ADVANCE_RING();
	/* set flush flag */
	dev_priv->track_flush |= RADEON_FLUSH_EMITED;

D
Dave Airlie 已提交
157 158 159
	return 0;
}

160
static u8 r300_reg_flags[0x10000 >> 2];
D
Dave Airlie 已提交
161

D
Dave Airlie 已提交
162
void r300_init_reg_flags(struct drm_device *dev)
D
Dave Airlie 已提交
163 164
{
	int i;
D
Dave Airlie 已提交
165 166
	drm_radeon_private_t *dev_priv = dev->dev_private;

D
Dave Airlie 已提交
167 168
	memset(r300_reg_flags, 0, 0x10000 >> 2);
#define ADD_RANGE_MARK(reg, count,mark) \
D
Dave Airlie 已提交
169 170
		for(i=((reg)>>2);i<((reg)>>2)+(count);i++)\
			r300_reg_flags[i]|=(mark);
D
Dave Airlie 已提交
171 172 173 174 175

#define MARK_SAFE		1
#define MARK_CHECK_OFFSET	2

#define ADD_RANGE(reg, count)	ADD_RANGE_MARK(reg, count, MARK_SAFE)
D
Dave Airlie 已提交
176 177 178

	/* these match cmducs() command in r300_driver/r300/r300_cmdbuf.c */
	ADD_RANGE(R300_SE_VPORT_XSCALE, 6);
O
Oliver McFadden 已提交
179
	ADD_RANGE(R300_VAP_CNTL, 1);
D
Dave Airlie 已提交
180 181
	ADD_RANGE(R300_SE_VTE_CNTL, 2);
	ADD_RANGE(0x2134, 2);
O
Oliver McFadden 已提交
182
	ADD_RANGE(R300_VAP_CNTL_STATUS, 1);
D
Dave Airlie 已提交
183 184
	ADD_RANGE(R300_VAP_INPUT_CNTL_0, 2);
	ADD_RANGE(0x21DC, 1);
O
Oliver McFadden 已提交
185 186
	ADD_RANGE(R300_VAP_UNKNOWN_221C, 1);
	ADD_RANGE(R300_VAP_CLIP_X_0, 4);
187
	ADD_RANGE(R300_VAP_PVS_STATE_FLUSH_REG, 1);
O
Oliver McFadden 已提交
188
	ADD_RANGE(R300_VAP_UNKNOWN_2288, 1);
D
Dave Airlie 已提交
189 190 191 192
	ADD_RANGE(R300_VAP_OUTPUT_VTX_FMT_0, 2);
	ADD_RANGE(R300_VAP_PVS_CNTL_1, 3);
	ADD_RANGE(R300_GB_ENABLE, 1);
	ADD_RANGE(R300_GB_MSPOS0, 5);
193
	ADD_RANGE(R300_TX_INVALTAGS, 1);
D
Dave Airlie 已提交
194 195 196 197 198 199
	ADD_RANGE(R300_TX_ENABLE, 1);
	ADD_RANGE(0x4200, 4);
	ADD_RANGE(0x4214, 1);
	ADD_RANGE(R300_RE_POINTSIZE, 1);
	ADD_RANGE(0x4230, 3);
	ADD_RANGE(R300_RE_LINE_CNT, 1);
O
Oliver McFadden 已提交
200
	ADD_RANGE(R300_RE_UNK4238, 1);
D
Dave Airlie 已提交
201
	ADD_RANGE(0x4260, 3);
O
Oliver McFadden 已提交
202 203 204
	ADD_RANGE(R300_RE_SHADE, 4);
	ADD_RANGE(R300_RE_POLYGON_MODE, 5);
	ADD_RANGE(R300_RE_ZBIAS_CNTL, 1);
D
Dave Airlie 已提交
205
	ADD_RANGE(R300_RE_ZBIAS_T_FACTOR, 4);
O
Oliver McFadden 已提交
206
	ADD_RANGE(R300_RE_OCCLUSION_CNTL, 1);
D
Dave Airlie 已提交
207 208 209
	ADD_RANGE(R300_RE_CULL_CNTL, 1);
	ADD_RANGE(0x42C0, 2);
	ADD_RANGE(R300_RS_CNTL_0, 2);
210

211 212 213 214
	ADD_RANGE(R300_SU_REG_DEST, 1);
	if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV530)
		ADD_RANGE(RV530_FG_ZBREG_DEST, 1);

215
	ADD_RANGE(R300_SC_HYPERZ, 2);
D
Dave Airlie 已提交
216
	ADD_RANGE(0x43E8, 1);
217

D
Dave Airlie 已提交
218
	ADD_RANGE(0x46A4, 5);
219

O
Oliver McFadden 已提交
220 221
	ADD_RANGE(R300_RE_FOG_STATE, 1);
	ADD_RANGE(R300_FOG_COLOR_R, 3);
D
Dave Airlie 已提交
222 223 224 225 226 227
	ADD_RANGE(R300_PP_ALPHA_TEST, 2);
	ADD_RANGE(0x4BD8, 1);
	ADD_RANGE(R300_PFS_PARAM_0_X, 64);
	ADD_RANGE(0x4E00, 1);
	ADD_RANGE(R300_RB3D_CBLEND, 2);
	ADD_RANGE(R300_RB3D_COLORMASK, 1);
O
Oliver McFadden 已提交
228
	ADD_RANGE(R300_RB3D_BLEND_COLOR, 3);
D
Dave Airlie 已提交
229
	ADD_RANGE_MARK(R300_RB3D_COLOROFFSET0, 1, MARK_CHECK_OFFSET);	/* check offset */
D
Dave Airlie 已提交
230 231 232 233
	ADD_RANGE(R300_RB3D_COLORPITCH0, 1);
	ADD_RANGE(0x4E50, 9);
	ADD_RANGE(0x4E88, 1);
	ADD_RANGE(0x4EA0, 2);
234 235 236 237 238 239
	ADD_RANGE(R300_ZB_CNTL, 3);
	ADD_RANGE(R300_ZB_FORMAT, 4);
	ADD_RANGE_MARK(R300_ZB_DEPTHOFFSET, 1, MARK_CHECK_OFFSET);	/* check offset */
	ADD_RANGE(R300_ZB_DEPTHPITCH, 1);
	ADD_RANGE(R300_ZB_DEPTHCLEARVALUE, 1);
	ADD_RANGE(R300_ZB_ZMASK_OFFSET, 13);
240
	ADD_RANGE(R300_ZB_ZPASS_DATA, 2); /* ZB_ZPASS_DATA, ZB_ZPASS_ADDR */
D
Dave Airlie 已提交
241 242

	ADD_RANGE(R300_TX_FILTER_0, 16);
D
Dave Airlie 已提交
243
	ADD_RANGE(R300_TX_FILTER1_0, 16);
D
Dave Airlie 已提交
244 245
	ADD_RANGE(R300_TX_SIZE_0, 16);
	ADD_RANGE(R300_TX_FORMAT_0, 16);
246
	ADD_RANGE(R300_TX_PITCH_0, 16);
D
Dave Airlie 已提交
247
	/* Texture offset is dangerous and needs more checking */
D
Dave Airlie 已提交
248
	ADD_RANGE_MARK(R300_TX_OFFSET_0, 16, MARK_CHECK_OFFSET);
D
Dave Airlie 已提交
249
	ADD_RANGE(R300_TX_CHROMA_KEY_0, 16);
D
Dave Airlie 已提交
250 251 252
	ADD_RANGE(R300_TX_BORDER_COLOR_0, 16);

	/* Sporadic registers used as primitives are emitted */
253
	ADD_RANGE(R300_ZB_ZCACHE_CTLSTAT, 1);
D
Dave Airlie 已提交
254 255 256 257
	ADD_RANGE(R300_RB3D_DSTCACHE_CTLSTAT, 1);
	ADD_RANGE(R300_VAP_INPUT_ROUTE_0_0, 8);
	ADD_RANGE(R300_VAP_INPUT_ROUTE_1_0, 8);

D
Dave Airlie 已提交
258
	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) {
259 260 261 262 263 264 265 266
		ADD_RANGE(R500_VAP_INDEX_OFFSET, 1);
		ADD_RANGE(R500_US_CONFIG, 2);
		ADD_RANGE(R500_US_CODE_ADDR, 3);
		ADD_RANGE(R500_US_FC_CTRL, 1);
		ADD_RANGE(R500_RS_IP_0, 16);
		ADD_RANGE(R500_RS_INST_0, 16);
		ADD_RANGE(R500_RB3D_COLOR_CLEAR_VALUE_AR, 2);
		ADD_RANGE(R500_RB3D_CONSTANT_COLOR_AR, 2);
267
		ADD_RANGE(R500_ZB_FIFO_SIZE, 2);
268 269 270 271 272 273 274 275 276 277 278
	} else {
		ADD_RANGE(R300_PFS_CNTL_0, 3);
		ADD_RANGE(R300_PFS_NODE_0, 4);
		ADD_RANGE(R300_PFS_TEXI_0, 64);
		ADD_RANGE(R300_PFS_INSTR0_0, 64);
		ADD_RANGE(R300_PFS_INSTR1_0, 64);
		ADD_RANGE(R300_PFS_INSTR2_0, 64);
		ADD_RANGE(R300_PFS_INSTR3_0, 64);
		ADD_RANGE(R300_RS_INTERP_0, 8);
		ADD_RANGE(R300_RS_ROUTE_0, 8);

D
Dave Airlie 已提交
279
	}
D
Dave Airlie 已提交
280 281
}

D
Dave Airlie 已提交
282
static __inline__ int r300_check_range(unsigned reg, int count)
D
Dave Airlie 已提交
283 284
{
	int i;
D
Dave Airlie 已提交
285 286 287 288 289
	if (reg & ~0xffff)
		return -1;
	for (i = (reg >> 2); i < (reg >> 2) + count; i++)
		if (r300_reg_flags[i] != MARK_SAFE)
			return 1;
D
Dave Airlie 已提交
290 291 292
	return 0;
}

D
Dave Airlie 已提交
293 294
static __inline__ int r300_emit_carefully_checked_packet0(drm_radeon_private_t *
							  dev_priv,
295
							  drm_radeon_kcmd_buffer_t
D
Dave Airlie 已提交
296 297 298
							  * cmdbuf,
							  drm_r300_cmd_header_t
							  header)
D
Dave Airlie 已提交
299 300 301 302
{
	int reg;
	int sz;
	int i;
303
	u32 *value;
D
Dave Airlie 已提交
304 305 306 307
	RING_LOCALS;

	sz = header.packet0.count;
	reg = (header.packet0.reghi << 8) | header.packet0.reglo;
D
Dave Airlie 已提交
308 309

	if ((sz > 64) || (sz < 0)) {
310 311
		DRM_ERROR("Cannot emit more than 64 values at a time (reg=%04x sz=%d)\n",
			 reg, sz);
E
Eric Anholt 已提交
312
		return -EINVAL;
D
Dave Airlie 已提交
313
	}
314

D
Dave Airlie 已提交
315 316
	for (i = 0; i < sz; i++) {
		switch (r300_reg_flags[(reg >> 2) + i]) {
D
Dave Airlie 已提交
317 318 319
		case MARK_SAFE:
			break;
		case MARK_CHECK_OFFSET:
320 321 322 323
			value = drm_buffer_pointer_to_dword(cmdbuf->buffer, i);
			if (!radeon_check_offset(dev_priv, *value)) {
				DRM_ERROR("Offset failed range check (reg=%04x sz=%d)\n",
					 reg, sz);
E
Eric Anholt 已提交
324
				return -EINVAL;
D
Dave Airlie 已提交
325
			}
D
Dave Airlie 已提交
326 327
			break;
		default:
D
Dave Airlie 已提交
328
			DRM_ERROR("Register %04x failed check as flag=%02x\n",
329
				reg + i * 4, r300_reg_flags[(reg >> 2) + i]);
E
Eric Anholt 已提交
330
			return -EINVAL;
D
Dave Airlie 已提交
331
		}
D
Dave Airlie 已提交
332 333 334 335
	}

	BEGIN_RING(1 + sz);
	OUT_RING(CP_PACKET0(reg, sz - 1));
336
	OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz);
D
Dave Airlie 已提交
337 338 339 340 341 342 343 344 345 346 347
	ADVANCE_RING();

	return 0;
}

/**
 * Emits a packet0 setting arbitrary registers.
 * Called by r300_do_cp_cmdbuf.
 *
 * Note that checks are performed on contents and addresses of the registers
 */
348 349
static __inline__ int r300_emit_packet0(drm_radeon_private_t *dev_priv,
					drm_radeon_kcmd_buffer_t *cmdbuf,
D
Dave Airlie 已提交
350
					drm_r300_cmd_header_t header)
D
Dave Airlie 已提交
351 352 353 354 355 356 357 358 359 360 361
{
	int reg;
	int sz;
	RING_LOCALS;

	sz = header.packet0.count;
	reg = (header.packet0.reghi << 8) | header.packet0.reglo;

	if (!sz)
		return 0;

362
	if (sz * 4 > drm_buffer_unprocessed(cmdbuf->buffer))
E
Eric Anholt 已提交
363
		return -EINVAL;
D
Dave Airlie 已提交
364 365 366 367

	if (reg + sz * 4 >= 0x10000) {
		DRM_ERROR("No such registers in hardware reg=%04x sz=%d\n", reg,
			  sz);
E
Eric Anholt 已提交
368
		return -EINVAL;
D
Dave Airlie 已提交
369
	}
D
Dave Airlie 已提交
370

D
Dave Airlie 已提交
371
	if (r300_check_range(reg, sz)) {
D
Dave Airlie 已提交
372
		/* go and check everything */
D
Dave Airlie 已提交
373 374 375
		return r300_emit_carefully_checked_packet0(dev_priv, cmdbuf,
							   header);
	}
D
Dave Airlie 已提交
376 377
	/* the rest of the data is safe to emit, whatever the values the user passed */

D
Dave Airlie 已提交
378 379
	BEGIN_RING(1 + sz);
	OUT_RING(CP_PACKET0(reg, sz - 1));
380
	OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz);
D
Dave Airlie 已提交
381 382 383 384 385 386 387 388 389 390
	ADVANCE_RING();

	return 0;
}

/**
 * Uploads user-supplied vertex program instructions or parameters onto
 * the graphics card.
 * Called by r300_do_cp_cmdbuf.
 */
391 392
static __inline__ int r300_emit_vpu(drm_radeon_private_t *dev_priv,
				    drm_radeon_kcmd_buffer_t *cmdbuf,
D
Dave Airlie 已提交
393 394 395 396 397 398 399 400 401 402 403
				    drm_r300_cmd_header_t header)
{
	int sz;
	int addr;
	RING_LOCALS;

	sz = header.vpu.count;
	addr = (header.vpu.adrhi << 8) | header.vpu.adrlo;

	if (!sz)
		return 0;
404
	if (sz * 16 > drm_buffer_unprocessed(cmdbuf->buffer))
E
Eric Anholt 已提交
405
		return -EINVAL;
D
Dave Airlie 已提交
406

407 408 409 410 411 412 413 414 415 416 417 418 419 420
	/* VAP is very sensitive so we purge cache before we program it
	 * and we also flush its state before & after */
	BEGIN_RING(6);
	OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
	OUT_RING(R300_RB3D_DC_FLUSH);
	OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
	OUT_RING(RADEON_WAIT_3D_IDLECLEAN);
	OUT_RING(CP_PACKET0(R300_VAP_PVS_STATE_FLUSH_REG, 0));
	OUT_RING(0);
	ADVANCE_RING();
	/* set flush flag */
	dev_priv->track_flush |= RADEON_FLUSH_EMITED;

	BEGIN_RING(3 + sz * 4);
D
Dave Airlie 已提交
421 422
	OUT_RING_REG(R300_VAP_PVS_UPLOAD_ADDRESS, addr);
	OUT_RING(CP_PACKET0_TABLE(R300_VAP_PVS_UPLOAD_DATA, sz * 4 - 1));
423
	OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz * 4);
424
	ADVANCE_RING();
D
Dave Airlie 已提交
425

426 427 428
	BEGIN_RING(2);
	OUT_RING(CP_PACKET0(R300_VAP_PVS_STATE_FLUSH_REG, 0));
	OUT_RING(0);
D
Dave Airlie 已提交
429 430 431 432 433 434 435 436 437
	ADVANCE_RING();

	return 0;
}

/**
 * Emit a clear packet from userspace.
 * Called by r300_emit_packet3.
 */
438 439
static __inline__ int r300_emit_clear(drm_radeon_private_t *dev_priv,
				      drm_radeon_kcmd_buffer_t *cmdbuf)
D
Dave Airlie 已提交
440 441 442
{
	RING_LOCALS;

443
	if (8 * 4 > drm_buffer_unprocessed(cmdbuf->buffer))
E
Eric Anholt 已提交
444
		return -EINVAL;
D
Dave Airlie 已提交
445 446

	BEGIN_RING(10);
D
Dave Airlie 已提交
447 448 449
	OUT_RING(CP_PACKET3(R200_3D_DRAW_IMMD_2, 8));
	OUT_RING(R300_PRIM_TYPE_POINT | R300_PRIM_WALK_RING |
		 (1 << R300_PRIM_NUM_VERTICES_SHIFT));
450
	OUT_RING_DRM_BUFFER(cmdbuf->buffer, 8);
D
Dave Airlie 已提交
451 452
	ADVANCE_RING();

453 454 455 456 457 458 459 460 461
	BEGIN_RING(4);
	OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
	OUT_RING(R300_RB3D_DC_FLUSH);
	OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
	OUT_RING(RADEON_WAIT_3D_IDLECLEAN);
	ADVANCE_RING();
	/* set flush flag */
	dev_priv->track_flush |= RADEON_FLUSH_EMITED;

D
Dave Airlie 已提交
462 463 464
	return 0;
}

465 466
static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t *dev_priv,
					       drm_radeon_kcmd_buffer_t *cmdbuf,
D
Dave Airlie 已提交
467
					       u32 header)
D
Dave Airlie 已提交
468
{
D
Dave Airlie 已提交
469 470
	int count, i, k;
#define MAX_ARRAY_PACKET  64
471
	u32 *data;
D
Dave Airlie 已提交
472 473 474
	u32 narrays;
	RING_LOCALS;

475
	count = (header & RADEON_CP_PACKET_COUNT_MASK) >> 16;
D
Dave Airlie 已提交
476 477 478 479

	if ((count + 1) > MAX_ARRAY_PACKET) {
		DRM_ERROR("Too large payload in 3D_LOAD_VBPNTR (count=%d)\n",
			  count);
E
Eric Anholt 已提交
480
		return -EINVAL;
D
Dave Airlie 已提交
481
	}
D
Dave Airlie 已提交
482
	/* carefully check packet contents */
D
Dave Airlie 已提交
483

484 485 486 487
	/* We have already read the header so advance the buffer. */
	drm_buffer_advance(cmdbuf->buffer, 4);

	narrays = *(u32 *)drm_buffer_pointer_to_dword(cmdbuf->buffer, 0);
D
Dave Airlie 已提交
488 489 490 491
	k = 0;
	i = 1;
	while ((k < narrays) && (i < (count + 1))) {
		i++;		/* skip attribute field */
492 493
		data = drm_buffer_pointer_to_dword(cmdbuf->buffer, i);
		if (!radeon_check_offset(dev_priv, *data)) {
D
Dave Airlie 已提交
494 495 496
			DRM_ERROR
			    ("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n",
			     k, i);
E
Eric Anholt 已提交
497
			return -EINVAL;
D
Dave Airlie 已提交
498
		}
D
Dave Airlie 已提交
499 500
		k++;
		i++;
D
Dave Airlie 已提交
501 502
		if (k == narrays)
			break;
D
Dave Airlie 已提交
503
		/* have one more to process, they come in pairs */
504 505
		data = drm_buffer_pointer_to_dword(cmdbuf->buffer, i);
		if (!radeon_check_offset(dev_priv, *data)) {
D
Dave Airlie 已提交
506 507 508
			DRM_ERROR
			    ("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n",
			     k, i);
E
Eric Anholt 已提交
509
			return -EINVAL;
D
Dave Airlie 已提交
510
		}
D
Dave Airlie 已提交
511 512 513
		k++;
		i++;
	}
D
Dave Airlie 已提交
514
	/* do the counts match what we expect ? */
D
Dave Airlie 已提交
515 516 517 518
	if ((k != narrays) || (i != (count + 1))) {
		DRM_ERROR
		    ("Malformed 3D_LOAD_VBPNTR packet (k=%d i=%d narrays=%d count+1=%d).\n",
		     k, i, narrays, count + 1);
E
Eric Anholt 已提交
519
		return -EINVAL;
D
Dave Airlie 已提交
520
	}
D
Dave Airlie 已提交
521 522 523

	/* all clear, output packet */

D
Dave Airlie 已提交
524
	BEGIN_RING(count + 2);
D
Dave Airlie 已提交
525
	OUT_RING(header);
526
	OUT_RING_DRM_BUFFER(cmdbuf->buffer, count + 1);
D
Dave Airlie 已提交
527 528 529 530
	ADVANCE_RING();

	return 0;
}
531

532 533 534
static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv,
					     drm_radeon_kcmd_buffer_t *cmdbuf)
{
535
	u32 *cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 0);
536 537 538 539
	int count, ret;
	RING_LOCALS;


540
	count = (*cmd & RADEON_CP_PACKET_COUNT_MASK) >> 16;
541

542 543 544 545
	if (*cmd & 0x8000) {
		u32 offset;
		u32 *cmd1 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1);
		if (*cmd1 & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL
546
			      | RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
547 548 549

			u32 *cmd2 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 2);
			offset = *cmd2 << 10;
550
			ret = !radeon_check_offset(dev_priv, offset);
D
Dave Airlie 已提交
551
			if (ret) {
552
				DRM_ERROR("Invalid bitblt first offset is %08X\n", offset);
E
Eric Anholt 已提交
553
				return -EINVAL;
554 555 556
			}
		}

557 558 559 560
		if ((*cmd1 & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) &&
		    (*cmd1 & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
			u32 *cmd3 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 3);
			offset = *cmd3 << 10;
561
			ret = !radeon_check_offset(dev_priv, offset);
D
Dave Airlie 已提交
562
			if (ret) {
563
				DRM_ERROR("Invalid bitblt second offset is %08X\n", offset);
E
Eric Anholt 已提交
564
				return -EINVAL;
565
			}
D
Dave Airlie 已提交
566

567 568 569 570
		}
	}

	BEGIN_RING(count+2);
571
	OUT_RING_DRM_BUFFER(cmdbuf->buffer, count + 2);
572 573 574 575
	ADVANCE_RING();

	return 0;
}
D
Dave Airlie 已提交
576

577 578
static __inline__ int r300_emit_draw_indx_2(drm_radeon_private_t *dev_priv,
					    drm_radeon_kcmd_buffer_t *cmdbuf)
579
{
580 581
	u32 *cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 0);
	u32 *cmd1 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1);
582 583
	int count;
	int expected_count;
584 585
	RING_LOCALS;

586 587 588 589
	count = (*cmd & RADEON_CP_PACKET_COUNT_MASK) >> 16;

	expected_count = *cmd1 >> 16;
	if (!(*cmd1 & R300_VAP_VF_CNTL__INDEX_SIZE_32bit))
590
		expected_count = (expected_count+1)/2;
591

592 593 594
	if (count && count != expected_count) {
		DRM_ERROR("3D_DRAW_INDX_2: packet size %i, expected %i\n",
			count, expected_count);
E
Eric Anholt 已提交
595
		return -EINVAL;
596 597 598
	}

	BEGIN_RING(count+2);
599
	OUT_RING_DRM_BUFFER(cmdbuf->buffer, count + 2);
600 601
	ADVANCE_RING();

602
	if (!count) {
603 604
		drm_r300_cmd_header_t stack_header, *header;
		u32 *cmd1, *cmd2, *cmd3;
605

606 607
		if (drm_buffer_unprocessed(cmdbuf->buffer)
				< 4*4 + sizeof(stack_header)) {
608 609 610 611
			DRM_ERROR("3D_DRAW_INDX_2: expect subsequent INDX_BUFFER, but stream is too short.\n");
			return -EINVAL;
		}

612 613
		header = drm_buffer_read_object(cmdbuf->buffer,
				sizeof(stack_header), &stack_header);
614

615 616 617 618
		cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 0);
		cmd1 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1);
		cmd2 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 2);
		cmd3 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 3);
619

620 621 622
		if (header->header.cmd_type != R300_CMD_PACKET3 ||
		    header->packet3.packet != R300_CMD_PACKET3_RAW ||
		    *cmd != CP_PACKET3(RADEON_CP_INDX_BUFFER, 2)) {
623 624 625 626
			DRM_ERROR("3D_DRAW_INDX_2: expect subsequent INDX_BUFFER.\n");
			return -EINVAL;
		}

627 628 629
		if ((*cmd1 & 0x8000ffff) != 0x80000810) {
			DRM_ERROR("Invalid indx_buffer reg address %08X\n",
					*cmd1);
630 631
			return -EINVAL;
		}
632 633 634
		if (!radeon_check_offset(dev_priv, *cmd2)) {
			DRM_ERROR("Invalid indx_buffer offset is %08X\n",
					*cmd2);
635 636
			return -EINVAL;
		}
637
		if (*cmd3 != expected_count) {
638
			DRM_ERROR("INDX_BUFFER: buffer size %i, expected %i\n",
639
				*cmd3, expected_count);
640 641 642 643
			return -EINVAL;
		}

		BEGIN_RING(4);
644
		OUT_RING_DRM_BUFFER(cmdbuf->buffer, 4);
645 646 647
		ADVANCE_RING();
	}

648 649 650
	return 0;
}

651 652
static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv,
					    drm_radeon_kcmd_buffer_t *cmdbuf)
D
Dave Airlie 已提交
653
{
654
	u32 *header;
D
Dave Airlie 已提交
655 656 657
	int count;
	RING_LOCALS;

658
	if (4 > drm_buffer_unprocessed(cmdbuf->buffer))
E
Eric Anholt 已提交
659
		return -EINVAL;
D
Dave Airlie 已提交
660

D
Dave Airlie 已提交
661
	/* Fixme !! This simply emits a packet without much checking.
D
Dave Airlie 已提交
662 663 664
	   We need to be smarter. */

	/* obtain first word - actual packet3 header */
665
	header = drm_buffer_pointer_to_dword(cmdbuf->buffer, 0);
D
Dave Airlie 已提交
666 667

	/* Is it packet 3 ? */
668 669
	if ((*header >> 30) != 0x3) {
		DRM_ERROR("Not a packet3 header (0x%08x)\n", *header);
E
Eric Anholt 已提交
670
		return -EINVAL;
D
Dave Airlie 已提交
671
	}
D
Dave Airlie 已提交
672

673
	count = (*header >> 16) & 0x3fff;
D
Dave Airlie 已提交
674 675

	/* Check again now that we know how much data to expect */
676
	if ((count + 2) * 4 > drm_buffer_unprocessed(cmdbuf->buffer)) {
D
Dave Airlie 已提交
677 678
		DRM_ERROR
		    ("Expected packet3 of length %d but have only %d bytes left\n",
679
		     (count + 2) * 4, drm_buffer_unprocessed(cmdbuf->buffer));
E
Eric Anholt 已提交
680
		return -EINVAL;
D
Dave Airlie 已提交
681
	}
D
Dave Airlie 已提交
682 683

	/* Is it a packet type we know about ? */
684
	switch (*header & 0xff00) {
D
Dave Airlie 已提交
685
	case RADEON_3D_LOAD_VBPNTR:	/* load vertex array pointers */
686
		return r300_emit_3d_load_vbpntr(dev_priv, cmdbuf, *header);
D
Dave Airlie 已提交
687

688 689 690
	case RADEON_CNTL_BITBLT_MULTI:
		return r300_emit_bitblt_multi(dev_priv, cmdbuf);

691
	case RADEON_CP_INDX_BUFFER:
692 693
		DRM_ERROR("packet3 INDX_BUFFER without preceding 3D_DRAW_INDX_2 is illegal.\n");
		return -EINVAL;
694 695 696 697
	case RADEON_CP_3D_DRAW_IMMD_2:
		/* triggers drawing using in-packet vertex data */
	case RADEON_CP_3D_DRAW_VBUF_2:
		/* triggers drawing of vertex buffers setup elsewhere */
698 699 700
		dev_priv->track_flush &= ~(RADEON_FLUSH_EMITED |
					   RADEON_PURGE_EMITED);
		break;
701 702 703 704 705
	case RADEON_CP_3D_DRAW_INDX_2:
		/* triggers drawing using indices to vertex buffer */
		/* whenever we send vertex we clear flush & purge */
		dev_priv->track_flush &= ~(RADEON_FLUSH_EMITED |
					   RADEON_PURGE_EMITED);
706
		return r300_emit_draw_indx_2(dev_priv, cmdbuf);
D
Dave Airlie 已提交
707 708 709 710 711
	case RADEON_WAIT_FOR_IDLE:
	case RADEON_CP_NOP:
		/* these packets are safe */
		break;
	default:
712
		DRM_ERROR("Unknown packet3 header (0x%08x)\n", *header);
E
Eric Anholt 已提交
713
		return -EINVAL;
D
Dave Airlie 已提交
714
	}
D
Dave Airlie 已提交
715

D
Dave Airlie 已提交
716
	BEGIN_RING(count + 2);
717
	OUT_RING_DRM_BUFFER(cmdbuf->buffer, count + 2);
D
Dave Airlie 已提交
718 719 720 721 722 723 724 725 726
	ADVANCE_RING();

	return 0;
}

/**
 * Emit a rendering packet3 from userspace.
 * Called by r300_do_cp_cmdbuf.
 */
727 728
static __inline__ int r300_emit_packet3(drm_radeon_private_t *dev_priv,
					drm_radeon_kcmd_buffer_t *cmdbuf,
D
Dave Airlie 已提交
729 730 731 732
					drm_r300_cmd_header_t header)
{
	int n;
	int ret;
733
	int orig_iter = cmdbuf->buffer->iterator;
D
Dave Airlie 已提交
734 735 736 737 738 739 740 741 742 743 744

	/* This is a do-while-loop so that we run the interior at least once,
	 * even if cmdbuf->nbox is 0. Compare r300_emit_cliprects for rationale.
	 */
	n = 0;
	do {
		if (cmdbuf->nbox > R300_SIMULTANEOUS_CLIPRECTS) {
			ret = r300_emit_cliprects(dev_priv, cmdbuf, n);
			if (ret)
				return ret;

745
			cmdbuf->buffer->iterator = orig_iter;
D
Dave Airlie 已提交
746
		}
D
Dave Airlie 已提交
747

D
Dave Airlie 已提交
748
		switch (header.packet3.packet) {
D
Dave Airlie 已提交
749 750 751 752 753 754
		case R300_CMD_PACKET3_CLEAR:
			DRM_DEBUG("R300_CMD_PACKET3_CLEAR\n");
			ret = r300_emit_clear(dev_priv, cmdbuf);
			if (ret) {
				DRM_ERROR("r300_emit_clear failed\n");
				return ret;
D
Dave Airlie 已提交
755
			}
D
Dave Airlie 已提交
756 757 758 759 760 761 762 763
			break;

		case R300_CMD_PACKET3_RAW:
			DRM_DEBUG("R300_CMD_PACKET3_RAW\n");
			ret = r300_emit_raw_packet3(dev_priv, cmdbuf);
			if (ret) {
				DRM_ERROR("r300_emit_raw_packet3 failed\n");
				return ret;
D
Dave Airlie 已提交
764
			}
D
Dave Airlie 已提交
765 766 767
			break;

		default:
768
			DRM_ERROR("bad packet3 type %i at byte %d\n",
D
Dave Airlie 已提交
769
				  header.packet3.packet,
770
				  cmdbuf->buffer->iterator - (int)sizeof(header));
E
Eric Anholt 已提交
771
			return -EINVAL;
D
Dave Airlie 已提交
772
		}
D
Dave Airlie 已提交
773 774

		n += R300_SIMULTANEOUS_CLIPRECTS;
D
Dave Airlie 已提交
775
	} while (n < cmdbuf->nbox);
D
Dave Airlie 已提交
776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793

	return 0;
}

/* Some of the R300 chips seem to be extremely touchy about the two registers
 * that are configured in r300_pacify.
 * Among the worst offenders seems to be the R300 ND (0x4E44): When userspace
 * sends a command buffer that contains only state setting commands and a
 * vertex program/parameter upload sequence, this will eventually lead to a
 * lockup, unless the sequence is bracketed by calls to r300_pacify.
 * So we should take great care to *always* call r300_pacify before
 * *anything* 3D related, and again afterwards. This is what the
 * call bracket in r300_do_cp_cmdbuf is for.
 */

/**
 * Emit the sequence to pacify R300.
 */
794
static __inline__ void r300_pacify(drm_radeon_private_t *dev_priv)
D
Dave Airlie 已提交
795
{
796
	uint32_t cache_z, cache_3d, cache_2d;
D
Dave Airlie 已提交
797
	RING_LOCALS;
798

799 800 801 802 803 804 805 806 807
	cache_z = R300_ZC_FLUSH;
	cache_2d = R300_RB2D_DC_FLUSH;
	cache_3d = R300_RB3D_DC_FLUSH;
	if (!(dev_priv->track_flush & RADEON_PURGE_EMITED)) {
		/* we can purge, primitive where draw since last purge */
		cache_z |= R300_ZC_FREE;
		cache_2d |= R300_RB2D_DC_FREE;
		cache_3d |= R300_RB3D_DC_FREE;
	}
D
Dave Airlie 已提交
808

809 810
	/* flush & purge zbuffer */
	BEGIN_RING(2);
811
	OUT_RING(CP_PACKET0(R300_ZB_ZCACHE_CTLSTAT, 0));
812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839
	OUT_RING(cache_z);
	ADVANCE_RING();
	/* flush & purge 3d */
	BEGIN_RING(2);
	OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
	OUT_RING(cache_3d);
	ADVANCE_RING();
	/* flush & purge texture */
	BEGIN_RING(2);
	OUT_RING(CP_PACKET0(R300_TX_INVALTAGS, 0));
	OUT_RING(0);
	ADVANCE_RING();
	/* FIXME: is this one really needed ? */
	BEGIN_RING(2);
	OUT_RING(CP_PACKET0(R300_RB3D_AARESOLVE_CTL, 0));
	OUT_RING(0);
	ADVANCE_RING();
	BEGIN_RING(2);
	OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
	OUT_RING(RADEON_WAIT_3D_IDLECLEAN);
	ADVANCE_RING();
	/* flush & purge 2d through E2 as RB2D will trigger lockup */
	BEGIN_RING(4);
	OUT_RING(CP_PACKET0(R300_DSTCACHE_CTLSTAT, 0));
	OUT_RING(cache_2d);
	OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
	OUT_RING(RADEON_WAIT_2D_IDLECLEAN |
		 RADEON_WAIT_HOST_IDLECLEAN);
D
Dave Airlie 已提交
840
	ADVANCE_RING();
841 842
	/* set flush & purge flags */
	dev_priv->track_flush |= RADEON_FLUSH_EMITED | RADEON_PURGE_EMITED;
D
Dave Airlie 已提交
843 844 845 846 847 848 849
}

/**
 * Called by r300_do_cp_cmdbuf to update the internal buffer age and state.
 * The actual age emit is done by r300_do_cp_cmdbuf, which is why you must
 * be careful about how this function is called.
 */
850
static void r300_discard_buffer(struct drm_device *dev, struct drm_master *master, struct drm_buf *buf)
D
Dave Airlie 已提交
851 852
{
	drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
853
	struct drm_radeon_master_private *master_priv = master->driver_priv;
D
Dave Airlie 已提交
854

855
	buf_priv->age = ++master_priv->sarea_priv->last_dispatch;
D
Dave Airlie 已提交
856 857 858 859
	buf->pending = 1;
	buf->used = 0;
}

860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900
static void r300_cmd_wait(drm_radeon_private_t * dev_priv,
			  drm_r300_cmd_header_t header)
{
	u32 wait_until;
	RING_LOCALS;

	if (!header.wait.flags)
		return;

	wait_until = 0;

	switch(header.wait.flags) {
	case R300_WAIT_2D:
		wait_until = RADEON_WAIT_2D_IDLE;
		break;
	case R300_WAIT_3D:
		wait_until = RADEON_WAIT_3D_IDLE;
		break;
	case R300_NEW_WAIT_2D_3D:
		wait_until = RADEON_WAIT_2D_IDLE|RADEON_WAIT_3D_IDLE;
		break;
	case R300_NEW_WAIT_2D_2D_CLEAN:
		wait_until = RADEON_WAIT_2D_IDLE|RADEON_WAIT_2D_IDLECLEAN;
		break;
	case R300_NEW_WAIT_3D_3D_CLEAN:
		wait_until = RADEON_WAIT_3D_IDLE|RADEON_WAIT_3D_IDLECLEAN;
		break;
	case R300_NEW_WAIT_2D_2D_CLEAN_3D_3D_CLEAN:
		wait_until = RADEON_WAIT_2D_IDLE|RADEON_WAIT_2D_IDLECLEAN;
		wait_until |= RADEON_WAIT_3D_IDLE|RADEON_WAIT_3D_IDLECLEAN;
		break;
	default:
		return;
	}

	BEGIN_RING(2);
	OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
	OUT_RING(wait_until);
	ADVANCE_RING();
}

901 902 903 904 905
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;
906 907 908
	u32 i, *buf_idx, h_pending;
	u64 *ptr_addr;
	u64 stack_ptr_addr;
909
	RING_LOCALS;
D
Dave Airlie 已提交
910

911 912
	if (drm_buffer_unprocessed(cmdbuf->buffer) <
	    (sizeof(u64) + header.scratch.n_bufs * sizeof(*buf_idx))) {
E
Eric Anholt 已提交
913
		return -EINVAL;
914
	}
D
Dave Airlie 已提交
915

916
	if (header.scratch.reg >= 5) {
E
Eric Anholt 已提交
917
		return -EINVAL;
918
	}
D
Dave Airlie 已提交
919

920
	dev_priv->scratch_ages[header.scratch.reg]++;
D
Dave Airlie 已提交
921

922 923 924
	ptr_addr = drm_buffer_read_object(cmdbuf->buffer,
			sizeof(stack_ptr_addr), &stack_ptr_addr);
	ref_age_base = (u32 *)(unsigned long)*ptr_addr;
D
Dave Airlie 已提交
925

926
	for (i=0; i < header.scratch.n_bufs; i++) {
927 928
		buf_idx = drm_buffer_pointer_to_dword(cmdbuf->buffer, 0);
		*buf_idx *= 2; /* 8 bytes per buf */
D
Dave Airlie 已提交
929

930 931 932
		if (DRM_COPY_TO_USER(ref_age_base + *buf_idx,
				&dev_priv->scratch_ages[header.scratch.reg],
				sizeof(u32)))
E
Eric Anholt 已提交
933
			return -EINVAL;
D
Dave Airlie 已提交
934

935 936 937
		if (DRM_COPY_FROM_USER(&h_pending,
				ref_age_base + *buf_idx + 1,
				sizeof(u32)))
E
Eric Anholt 已提交
938
			return -EINVAL;
D
Dave Airlie 已提交
939

940
		if (h_pending == 0)
E
Eric Anholt 已提交
941
			return -EINVAL;
D
Dave Airlie 已提交
942

943
		h_pending--;
D
Dave Airlie 已提交
944

945 946 947
		if (DRM_COPY_TO_USER(ref_age_base + *buf_idx + 1,
					&h_pending,
					sizeof(u32)))
E
Eric Anholt 已提交
948
			return -EINVAL;
D
Dave Airlie 已提交
949

950
		drm_buffer_advance(cmdbuf->buffer, sizeof(*buf_idx));
951
	}
D
Dave Airlie 已提交
952

953
	BEGIN_RING(2);
O
Oliver McFadden 已提交
954 955
	OUT_RING( CP_PACKET0( RADEON_SCRATCH_REG0 + header.scratch.reg * 4, 0 ) );
	OUT_RING( dev_priv->scratch_ages[header.scratch.reg] );
956
	ADVANCE_RING();
D
Dave Airlie 已提交
957

958 959 960
	return 0;
}

961 962 963 964 965 966 967 968 969 970 971 972
/**
 * Uploads user-supplied vertex program instructions or parameters onto
 * the graphics card.
 * Called by r300_do_cp_cmdbuf.
 */
static inline int r300_emit_r500fp(drm_radeon_private_t *dev_priv,
				       drm_radeon_kcmd_buffer_t *cmdbuf,
				       drm_r300_cmd_header_t header)
{
	int sz;
	int addr;
	int type;
A
Andi Kleen 已提交
973
	int isclamp;
974 975 976 977 978 979 980 981
	int stride;
	RING_LOCALS;

	sz = header.r500fp.count;
	/* address is 9 bits 0 - 8, bit 1 of flags is part of address */
	addr = ((header.r500fp.adrhi_flags & 1) << 8) | header.r500fp.adrlo;

	type = !!(header.r500fp.adrhi_flags & R500FP_CONSTANT_TYPE);
A
Andi Kleen 已提交
982
	isclamp = !!(header.r500fp.adrhi_flags & R500FP_CONSTANT_CLAMP);
983 984

	addr |= (type << 16);
A
Andi Kleen 已提交
985
	addr |= (isclamp << 17);
986 987 988 989 990 991

	stride = type ? 4 : 6;

	DRM_DEBUG("r500fp %d %d type: %d\n", sz, addr, type);
	if (!sz)
		return 0;
992
	if (sz * stride * 4 > drm_buffer_unprocessed(cmdbuf->buffer))
993 994 995 996 997
		return -EINVAL;

	BEGIN_RING(3 + sz * stride);
	OUT_RING_REG(R500_GA_US_VECTOR_INDEX, addr);
	OUT_RING(CP_PACKET0_TABLE(R500_GA_US_VECTOR_DATA, sz * stride - 1));
998
	OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz * stride);
999 1000 1001 1002 1003 1004 1005

	ADVANCE_RING();

	return 0;
}


D
Dave Airlie 已提交
1006 1007 1008 1009 1010
/**
 * 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.
 */
1011
int r300_do_cp_cmdbuf(struct drm_device *dev,
1012
		      struct drm_file *file_priv,
1013
		      drm_radeon_kcmd_buffer_t *cmdbuf)
D
Dave Airlie 已提交
1014 1015
{
	drm_radeon_private_t *dev_priv = dev->dev_private;
1016
	struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
1017
	struct drm_device_dma *dma = dev->dma;
D
Dave Airlie 已提交
1018
	struct drm_buf *buf = NULL;
D
Dave Airlie 已提交
1019 1020 1021 1022 1023
	int emit_dispatch_age = 0;
	int ret = 0;

	DRM_DEBUG("\n");

1024
	/* pacify */
D
Dave Airlie 已提交
1025 1026 1027 1028 1029 1030
	r300_pacify(dev_priv);

	if (cmdbuf->nbox <= R300_SIMULTANEOUS_CLIPRECTS) {
		ret = r300_emit_cliprects(dev_priv, cmdbuf, 0);
		if (ret)
			goto cleanup;
D
Dave Airlie 已提交
1031
	}
D
Dave Airlie 已提交
1032

1033 1034
	while (drm_buffer_unprocessed(cmdbuf->buffer)
			>= sizeof(drm_r300_cmd_header_t)) {
D
Dave Airlie 已提交
1035
		int idx;
1036
		drm_r300_cmd_header_t *header, stack_header;
D
Dave Airlie 已提交
1037

1038 1039
		header = drm_buffer_read_object(cmdbuf->buffer,
				sizeof(stack_header), &stack_header);
D
Dave Airlie 已提交
1040

1041
		switch (header->header.cmd_type) {
D
Dave Airlie 已提交
1042
		case R300_CMD_PACKET0:
D
Dave Airlie 已提交
1043
			DRM_DEBUG("R300_CMD_PACKET0\n");
1044
			ret = r300_emit_packet0(dev_priv, cmdbuf, *header);
D
Dave Airlie 已提交
1045 1046 1047
			if (ret) {
				DRM_ERROR("r300_emit_packet0 failed\n");
				goto cleanup;
D
Dave Airlie 已提交
1048
			}
D
Dave Airlie 已提交
1049 1050 1051 1052
			break;

		case R300_CMD_VPU:
			DRM_DEBUG("R300_CMD_VPU\n");
1053
			ret = r300_emit_vpu(dev_priv, cmdbuf, *header);
D
Dave Airlie 已提交
1054 1055 1056
			if (ret) {
				DRM_ERROR("r300_emit_vpu failed\n");
				goto cleanup;
D
Dave Airlie 已提交
1057
			}
D
Dave Airlie 已提交
1058 1059 1060 1061
			break;

		case R300_CMD_PACKET3:
			DRM_DEBUG("R300_CMD_PACKET3\n");
1062
			ret = r300_emit_packet3(dev_priv, cmdbuf, *header);
D
Dave Airlie 已提交
1063 1064 1065
			if (ret) {
				DRM_ERROR("r300_emit_packet3 failed\n");
				goto cleanup;
D
Dave Airlie 已提交
1066
			}
D
Dave Airlie 已提交
1067 1068 1069 1070
			break;

		case R300_CMD_END3D:
			DRM_DEBUG("R300_CMD_END3D\n");
D
Dave Airlie 已提交
1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085
			/* 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 */
D
Dave Airlie 已提交
1086 1087 1088 1089 1090 1091 1092 1093 1094 1095
			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;

1096 1097
				BEGIN_RING(header->delay.count);
				for (i = 0; i < header->delay.count; i++)
D
Dave Airlie 已提交
1098 1099 1100 1101 1102 1103 1104
					OUT_RING(RADEON_CP_PACKET2);
				ADVANCE_RING();
			}
			break;

		case R300_CMD_DMA_DISCARD:
			DRM_DEBUG("RADEON_CMD_DMA_DISCARD\n");
1105
			idx = header->dma.buf_idx;
D
Dave Airlie 已提交
1106 1107 1108
			if (idx < 0 || idx >= dma->buf_count) {
				DRM_ERROR("buffer index %d (of %d max)\n",
					  idx, dma->buf_count - 1);
E
Eric Anholt 已提交
1109
				ret = -EINVAL;
D
Dave Airlie 已提交
1110
				goto cleanup;
D
Dave Airlie 已提交
1111 1112 1113
			}

			buf = dma->buflist[idx];
1114
			if (buf->file_priv != file_priv || buf->pending) {
D
Dave Airlie 已提交
1115
				DRM_ERROR("bad buffer %p %p %d\n",
1116 1117
					  buf->file_priv, file_priv,
					  buf->pending);
E
Eric Anholt 已提交
1118
				ret = -EINVAL;
D
Dave Airlie 已提交
1119 1120
				goto cleanup;
			}
D
Dave Airlie 已提交
1121 1122

			emit_dispatch_age = 1;
1123
			r300_discard_buffer(dev, file_priv->master, buf);
D
Dave Airlie 已提交
1124
			break;
D
Dave Airlie 已提交
1125 1126 1127

		case R300_CMD_WAIT:
			DRM_DEBUG("R300_CMD_WAIT\n");
1128
			r300_cmd_wait(dev_priv, *header);
D
Dave Airlie 已提交
1129 1130
			break;

1131 1132
		case R300_CMD_SCRATCH:
			DRM_DEBUG("R300_CMD_SCRATCH\n");
1133
			ret = r300_scratch(dev_priv, cmdbuf, *header);
1134 1135 1136 1137 1138
			if (ret) {
				DRM_ERROR("r300_scratch failed\n");
				goto cleanup;
			}
			break;
D
Dave Airlie 已提交
1139

1140 1141 1142 1143 1144 1145 1146
		case R300_CMD_R500FP:
			if ((dev_priv->flags & RADEON_FAMILY_MASK) < CHIP_RV515) {
				DRM_ERROR("Calling r500 command on r300 card\n");
				ret = -EINVAL;
				goto cleanup;
			}
			DRM_DEBUG("R300_CMD_R500FP\n");
1147
			ret = r300_emit_r500fp(dev_priv, cmdbuf, *header);
1148 1149 1150 1151 1152
			if (ret) {
				DRM_ERROR("r300_emit_r500fp failed\n");
				goto cleanup;
			}
			break;
D
Dave Airlie 已提交
1153
		default:
1154 1155
			DRM_ERROR("bad cmd_type %i at byte %d\n",
				  header->header.cmd_type,
1156
				  cmdbuf->buffer->iterator - (int)sizeof(*header));
E
Eric Anholt 已提交
1157
			ret = -EINVAL;
D
Dave Airlie 已提交
1158
			goto cleanup;
D
Dave Airlie 已提交
1159
		}
D
Dave Airlie 已提交
1160 1161 1162 1163
	}

	DRM_DEBUG("END\n");

D
Dave Airlie 已提交
1164
      cleanup:
D
Dave Airlie 已提交
1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177
	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);
1178
		RADEON_DISPATCH_AGE(master_priv->sarea_priv->last_dispatch);
D
Dave Airlie 已提交
1179
		ADVANCE_RING();
D
Dave Airlie 已提交
1180
	}
D
Dave Airlie 已提交
1181 1182 1183 1184 1185

	COMMIT_RING();

	return ret;
}