blob: 4b3bd6303daf59ad90f20f2f75bcc0cb7d1626f0 [file] [log] [blame]
Dave Airlie414ed532005-08-16 20:43:16 +10001/* r300_cmdbuf.c -- Command buffer emission for R300 -*- linux-c -*-
2 *
3 * Copyright (C) The Weather Channel, Inc. 2002.
4 * Copyright (C) 2004 Nicolai Haehnle.
5 * All Rights Reserved.
6 *
7 * The Weather Channel (TM) funded Tungsten Graphics to develop the
8 * initial release of the Radeon 8500 driver under the XFree86 license.
9 * This notice must be preserved.
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a
12 * copy of this software and associated documentation files (the "Software"),
13 * to deal in the Software without restriction, including without limitation
14 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 * and/or sell copies of the Software, and to permit persons to whom the
16 * Software is furnished to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice (including the next
19 * paragraph) shall be included in all copies or substantial portions of the
20 * Software.
21 *
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
26 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
27 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 * DEALINGS IN THE SOFTWARE.
29 *
30 * Authors:
31 * Nicolai Haehnle <prefect_@gmx.net>
32 */
33
34#include "drmP.h"
35#include "drm.h"
36#include "radeon_drm.h"
37#include "radeon_drv.h"
38#include "r300_reg.h"
39
Dave Airlie414ed532005-08-16 20:43:16 +100040#define R300_SIMULTANEOUS_CLIPRECTS 4
41
42/* Values for R300_RE_CLIPRECT_CNTL depending on the number of cliprects
43 */
44static const int r300_cliprect_cntl[4] = {
45 0xAAAA,
46 0xEEEE,
47 0xFEFE,
48 0xFFFE
49};
50
Dave Airlie414ed532005-08-16 20:43:16 +100051/**
52 * Emit up to R300_SIMULTANEOUS_CLIPRECTS cliprects from the given command
53 * buffer, starting with index n.
54 */
Dave Airlied985c102006-01-02 21:32:48 +110055static int r300_emit_cliprects(drm_radeon_private_t *dev_priv,
56 drm_radeon_kcmd_buffer_t *cmdbuf, int n)
Dave Airlie414ed532005-08-16 20:43:16 +100057{
Dave Airliec60ce622007-07-11 15:27:12 +100058 struct drm_clip_rect box;
Dave Airlie414ed532005-08-16 20:43:16 +100059 int nr;
60 int i;
61 RING_LOCALS;
62
63 nr = cmdbuf->nbox - n;
64 if (nr > R300_SIMULTANEOUS_CLIPRECTS)
65 nr = R300_SIMULTANEOUS_CLIPRECTS;
66
67 DRM_DEBUG("%i cliprects\n", nr);
68
69 if (nr) {
Dave Airlieb5e89ed2005-09-25 14:28:13 +100070 BEGIN_RING(6 + nr * 2);
71 OUT_RING(CP_PACKET0(R300_RE_CLIPRECT_TL_0, nr * 2 - 1));
Dave Airlie414ed532005-08-16 20:43:16 +100072
Dave Airlieb5e89ed2005-09-25 14:28:13 +100073 for (i = 0; i < nr; ++i) {
74 if (DRM_COPY_FROM_USER_UNCHECKED
75 (&box, &cmdbuf->boxes[n + i], sizeof(box))) {
Dave Airlie414ed532005-08-16 20:43:16 +100076 DRM_ERROR("copy cliprect faulted\n");
Eric Anholt20caafa2007-08-25 19:22:43 +100077 return -EFAULT;
Dave Airlie414ed532005-08-16 20:43:16 +100078 }
79
Dave Airlie3d5e2c12008-02-07 15:01:05 +100080 if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) {
81 box.x1 = (box.x1) &
82 R300_CLIPRECT_MASK;
83 box.y1 = (box.y1) &
84 R300_CLIPRECT_MASK;
85 box.x2 = (box.x2) &
86 R300_CLIPRECT_MASK;
87 box.y2 = (box.y2) &
88 R300_CLIPRECT_MASK;
89 } else {
90 box.x1 = (box.x1 + R300_CLIPRECT_OFFSET) &
91 R300_CLIPRECT_MASK;
92 box.y1 = (box.y1 + R300_CLIPRECT_OFFSET) &
93 R300_CLIPRECT_MASK;
94 box.x2 = (box.x2 + R300_CLIPRECT_OFFSET) &
95 R300_CLIPRECT_MASK;
96 box.y2 = (box.y2 + R300_CLIPRECT_OFFSET) &
97 R300_CLIPRECT_MASK;
Dave Airlie414ed532005-08-16 20:43:16 +100098
Dave Airlie3d5e2c12008-02-07 15:01:05 +100099 }
Dave Airlie414ed532005-08-16 20:43:16 +1000100 OUT_RING((box.x1 << R300_CLIPRECT_X_SHIFT) |
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000101 (box.y1 << R300_CLIPRECT_Y_SHIFT));
Dave Airlie414ed532005-08-16 20:43:16 +1000102 OUT_RING((box.x2 << R300_CLIPRECT_X_SHIFT) |
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000103 (box.y2 << R300_CLIPRECT_Y_SHIFT));
Dave Airlie3d5e2c12008-02-07 15:01:05 +1000104
Dave Airlie414ed532005-08-16 20:43:16 +1000105 }
106
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000107 OUT_RING_REG(R300_RE_CLIPRECT_CNTL, r300_cliprect_cntl[nr - 1]);
Dave Airlie414ed532005-08-16 20:43:16 +1000108
109 /* TODO/SECURITY: Force scissors to a safe value, otherwise the
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000110 * client might be able to trample over memory.
111 * The impact should be very limited, but I'd rather be safe than
112 * sorry.
113 */
114 OUT_RING(CP_PACKET0(R300_RE_SCISSORS_TL, 1));
115 OUT_RING(0);
116 OUT_RING(R300_SCISSORS_X_MASK | R300_SCISSORS_Y_MASK);
Dave Airlie414ed532005-08-16 20:43:16 +1000117 ADVANCE_RING();
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000118 } else {
Dave Airlie414ed532005-08-16 20:43:16 +1000119 /* Why we allow zero cliprect rendering:
120 * There are some commands in a command buffer that must be submitted
121 * even when there are no cliprects, e.g. DMA buffer discard
122 * or state setting (though state setting could be avoided by
123 * simulating a loss of context).
124 *
125 * Now since the cmdbuf interface is so chaotic right now (and is
126 * bound to remain that way for a bit until things settle down),
127 * it is basically impossible to filter out the commands that are
128 * necessary and those that aren't.
129 *
130 * So I choose the safe way and don't do any filtering at all;
131 * instead, I simply set up the engine so that all rendering
132 * can't produce any fragments.
133 */
134 BEGIN_RING(2);
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000135 OUT_RING_REG(R300_RE_CLIPRECT_CNTL, 0);
Dave Airlie414ed532005-08-16 20:43:16 +1000136 ADVANCE_RING();
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000137 }
Dave Airlie414ed532005-08-16 20:43:16 +1000138
Jerome Glisse54f961a2008-08-13 09:46:31 +1000139 /* flus cache and wait idle clean after cliprect change */
140 BEGIN_RING(2);
141 OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
142 OUT_RING(R300_RB3D_DC_FLUSH);
143 ADVANCE_RING();
144 BEGIN_RING(2);
145 OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
146 OUT_RING(RADEON_WAIT_3D_IDLECLEAN);
147 ADVANCE_RING();
148 /* set flush flag */
149 dev_priv->track_flush |= RADEON_FLUSH_EMITED;
150
Dave Airlie414ed532005-08-16 20:43:16 +1000151 return 0;
152}
153
Dave Airlieb3a83632005-09-30 18:37:36 +1000154static u8 r300_reg_flags[0x10000 >> 2];
Dave Airlie414ed532005-08-16 20:43:16 +1000155
Dave Airlie3d5e2c12008-02-07 15:01:05 +1000156void r300_init_reg_flags(struct drm_device *dev)
Dave Airlie414ed532005-08-16 20:43:16 +1000157{
158 int i;
Dave Airlie3d5e2c12008-02-07 15:01:05 +1000159 drm_radeon_private_t *dev_priv = dev->dev_private;
160
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000161 memset(r300_reg_flags, 0, 0x10000 >> 2);
162#define ADD_RANGE_MARK(reg, count,mark) \
Dave Airlie414ed532005-08-16 20:43:16 +1000163 for(i=((reg)>>2);i<((reg)>>2)+(count);i++)\
164 r300_reg_flags[i]|=(mark);
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000165
166#define MARK_SAFE 1
167#define MARK_CHECK_OFFSET 2
168
169#define ADD_RANGE(reg, count) ADD_RANGE_MARK(reg, count, MARK_SAFE)
Dave Airlie414ed532005-08-16 20:43:16 +1000170
171 /* these match cmducs() command in r300_driver/r300/r300_cmdbuf.c */
172 ADD_RANGE(R300_SE_VPORT_XSCALE, 6);
Oliver McFaddenc6c656b2007-07-11 12:24:10 +1000173 ADD_RANGE(R300_VAP_CNTL, 1);
Dave Airlie414ed532005-08-16 20:43:16 +1000174 ADD_RANGE(R300_SE_VTE_CNTL, 2);
175 ADD_RANGE(0x2134, 2);
Oliver McFaddenc6c656b2007-07-11 12:24:10 +1000176 ADD_RANGE(R300_VAP_CNTL_STATUS, 1);
Dave Airlie414ed532005-08-16 20:43:16 +1000177 ADD_RANGE(R300_VAP_INPUT_CNTL_0, 2);
178 ADD_RANGE(0x21DC, 1);
Oliver McFaddenc6c656b2007-07-11 12:24:10 +1000179 ADD_RANGE(R300_VAP_UNKNOWN_221C, 1);
180 ADD_RANGE(R300_VAP_CLIP_X_0, 4);
Jerome Glisse54f961a2008-08-13 09:46:31 +1000181 ADD_RANGE(R300_VAP_PVS_STATE_FLUSH_REG, 1);
Oliver McFaddenc6c656b2007-07-11 12:24:10 +1000182 ADD_RANGE(R300_VAP_UNKNOWN_2288, 1);
Dave Airlie414ed532005-08-16 20:43:16 +1000183 ADD_RANGE(R300_VAP_OUTPUT_VTX_FMT_0, 2);
184 ADD_RANGE(R300_VAP_PVS_CNTL_1, 3);
185 ADD_RANGE(R300_GB_ENABLE, 1);
186 ADD_RANGE(R300_GB_MSPOS0, 5);
Jerome Glisse54f961a2008-08-13 09:46:31 +1000187 ADD_RANGE(R300_TX_INVALTAGS, 1);
Dave Airlie414ed532005-08-16 20:43:16 +1000188 ADD_RANGE(R300_TX_ENABLE, 1);
189 ADD_RANGE(0x4200, 4);
190 ADD_RANGE(0x4214, 1);
191 ADD_RANGE(R300_RE_POINTSIZE, 1);
192 ADD_RANGE(0x4230, 3);
193 ADD_RANGE(R300_RE_LINE_CNT, 1);
Oliver McFaddenc6c656b2007-07-11 12:24:10 +1000194 ADD_RANGE(R300_RE_UNK4238, 1);
Dave Airlie414ed532005-08-16 20:43:16 +1000195 ADD_RANGE(0x4260, 3);
Oliver McFaddenc6c656b2007-07-11 12:24:10 +1000196 ADD_RANGE(R300_RE_SHADE, 4);
197 ADD_RANGE(R300_RE_POLYGON_MODE, 5);
198 ADD_RANGE(R300_RE_ZBIAS_CNTL, 1);
Dave Airlie414ed532005-08-16 20:43:16 +1000199 ADD_RANGE(R300_RE_ZBIAS_T_FACTOR, 4);
Oliver McFaddenc6c656b2007-07-11 12:24:10 +1000200 ADD_RANGE(R300_RE_OCCLUSION_CNTL, 1);
Dave Airlie414ed532005-08-16 20:43:16 +1000201 ADD_RANGE(R300_RE_CULL_CNTL, 1);
202 ADD_RANGE(0x42C0, 2);
203 ADD_RANGE(R300_RS_CNTL_0, 2);
Dave Airliec0beb2a2008-05-28 13:52:28 +1000204
Dave Airlie21efa2b2008-06-19 13:01:58 +1000205 ADD_RANGE(R300_SC_HYPERZ, 2);
Dave Airlie414ed532005-08-16 20:43:16 +1000206 ADD_RANGE(0x43E8, 1);
Dave Airliec0beb2a2008-05-28 13:52:28 +1000207
Dave Airlie414ed532005-08-16 20:43:16 +1000208 ADD_RANGE(0x46A4, 5);
Dave Airliec0beb2a2008-05-28 13:52:28 +1000209
Oliver McFaddenc6c656b2007-07-11 12:24:10 +1000210 ADD_RANGE(R300_RE_FOG_STATE, 1);
211 ADD_RANGE(R300_FOG_COLOR_R, 3);
Dave Airlie414ed532005-08-16 20:43:16 +1000212 ADD_RANGE(R300_PP_ALPHA_TEST, 2);
213 ADD_RANGE(0x4BD8, 1);
214 ADD_RANGE(R300_PFS_PARAM_0_X, 64);
215 ADD_RANGE(0x4E00, 1);
216 ADD_RANGE(R300_RB3D_CBLEND, 2);
217 ADD_RANGE(R300_RB3D_COLORMASK, 1);
Oliver McFaddenc6c656b2007-07-11 12:24:10 +1000218 ADD_RANGE(R300_RB3D_BLEND_COLOR, 3);
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000219 ADD_RANGE_MARK(R300_RB3D_COLOROFFSET0, 1, MARK_CHECK_OFFSET); /* check offset */
Dave Airlie414ed532005-08-16 20:43:16 +1000220 ADD_RANGE(R300_RB3D_COLORPITCH0, 1);
221 ADD_RANGE(0x4E50, 9);
222 ADD_RANGE(0x4E88, 1);
223 ADD_RANGE(0x4EA0, 2);
Dave Airlie21efa2b2008-06-19 13:01:58 +1000224 ADD_RANGE(R300_ZB_CNTL, 3);
225 ADD_RANGE(R300_ZB_FORMAT, 4);
226 ADD_RANGE_MARK(R300_ZB_DEPTHOFFSET, 1, MARK_CHECK_OFFSET); /* check offset */
227 ADD_RANGE(R300_ZB_DEPTHPITCH, 1);
228 ADD_RANGE(R300_ZB_DEPTHCLEARVALUE, 1);
229 ADD_RANGE(R300_ZB_ZMASK_OFFSET, 13);
Dave Airlie414ed532005-08-16 20:43:16 +1000230
231 ADD_RANGE(R300_TX_FILTER_0, 16);
Dave Airlie45f17102006-03-19 19:12:10 +1100232 ADD_RANGE(R300_TX_FILTER1_0, 16);
Dave Airlie414ed532005-08-16 20:43:16 +1000233 ADD_RANGE(R300_TX_SIZE_0, 16);
234 ADD_RANGE(R300_TX_FORMAT_0, 16);
Dave Airlied985c102006-01-02 21:32:48 +1100235 ADD_RANGE(R300_TX_PITCH_0, 16);
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000236 /* Texture offset is dangerous and needs more checking */
Dave Airlie414ed532005-08-16 20:43:16 +1000237 ADD_RANGE_MARK(R300_TX_OFFSET_0, 16, MARK_CHECK_OFFSET);
Dave Airlie45f17102006-03-19 19:12:10 +1100238 ADD_RANGE(R300_TX_CHROMA_KEY_0, 16);
Dave Airlie414ed532005-08-16 20:43:16 +1000239 ADD_RANGE(R300_TX_BORDER_COLOR_0, 16);
240
241 /* Sporadic registers used as primitives are emitted */
Dave Airlie21efa2b2008-06-19 13:01:58 +1000242 ADD_RANGE(R300_ZB_ZCACHE_CTLSTAT, 1);
Dave Airlie414ed532005-08-16 20:43:16 +1000243 ADD_RANGE(R300_RB3D_DSTCACHE_CTLSTAT, 1);
244 ADD_RANGE(R300_VAP_INPUT_ROUTE_0_0, 8);
245 ADD_RANGE(R300_VAP_INPUT_ROUTE_1_0, 8);
246
Dave Airlie3d5e2c12008-02-07 15:01:05 +1000247 if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) {
Dave Airliec0beb2a2008-05-28 13:52:28 +1000248 ADD_RANGE(R500_VAP_INDEX_OFFSET, 1);
249 ADD_RANGE(R500_US_CONFIG, 2);
250 ADD_RANGE(R500_US_CODE_ADDR, 3);
251 ADD_RANGE(R500_US_FC_CTRL, 1);
252 ADD_RANGE(R500_RS_IP_0, 16);
253 ADD_RANGE(R500_RS_INST_0, 16);
254 ADD_RANGE(R500_RB3D_COLOR_CLEAR_VALUE_AR, 2);
255 ADD_RANGE(R500_RB3D_CONSTANT_COLOR_AR, 2);
Dave Airlie21efa2b2008-06-19 13:01:58 +1000256 ADD_RANGE(R500_ZB_FIFO_SIZE, 2);
Dave Airliec0beb2a2008-05-28 13:52:28 +1000257 } else {
258 ADD_RANGE(R300_PFS_CNTL_0, 3);
259 ADD_RANGE(R300_PFS_NODE_0, 4);
260 ADD_RANGE(R300_PFS_TEXI_0, 64);
261 ADD_RANGE(R300_PFS_INSTR0_0, 64);
262 ADD_RANGE(R300_PFS_INSTR1_0, 64);
263 ADD_RANGE(R300_PFS_INSTR2_0, 64);
264 ADD_RANGE(R300_PFS_INSTR3_0, 64);
265 ADD_RANGE(R300_RS_INTERP_0, 8);
266 ADD_RANGE(R300_RS_ROUTE_0, 8);
267
Dave Airlie3d5e2c12008-02-07 15:01:05 +1000268 }
Dave Airlie414ed532005-08-16 20:43:16 +1000269}
270
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000271static __inline__ int r300_check_range(unsigned reg, int count)
Dave Airlie414ed532005-08-16 20:43:16 +1000272{
273 int i;
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000274 if (reg & ~0xffff)
275 return -1;
276 for (i = (reg >> 2); i < (reg >> 2) + count; i++)
277 if (r300_reg_flags[i] != MARK_SAFE)
278 return 1;
Dave Airlie414ed532005-08-16 20:43:16 +1000279 return 0;
280}
281
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000282static __inline__ int r300_emit_carefully_checked_packet0(drm_radeon_private_t *
283 dev_priv,
Dave Airlieb3a83632005-09-30 18:37:36 +1000284 drm_radeon_kcmd_buffer_t
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000285 * cmdbuf,
286 drm_r300_cmd_header_t
287 header)
Dave Airlie414ed532005-08-16 20:43:16 +1000288{
289 int reg;
290 int sz;
291 int i;
292 int values[64];
293 RING_LOCALS;
294
295 sz = header.packet0.count;
296 reg = (header.packet0.reghi << 8) | header.packet0.reglo;
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000297
298 if ((sz > 64) || (sz < 0)) {
299 DRM_ERROR
300 ("Cannot emit more than 64 values at a time (reg=%04x sz=%d)\n",
301 reg, sz);
Eric Anholt20caafa2007-08-25 19:22:43 +1000302 return -EINVAL;
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000303 }
304 for (i = 0; i < sz; i++) {
Dave Airlieb3a83632005-09-30 18:37:36 +1000305 values[i] = ((int *)cmdbuf->buf)[i];
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000306 switch (r300_reg_flags[(reg >> 2) + i]) {
Dave Airlie414ed532005-08-16 20:43:16 +1000307 case MARK_SAFE:
308 break;
309 case MARK_CHECK_OFFSET:
=?utf-8?q?Michel_D=C3=A4nzer?=1d6bb8e2006-12-15 18:54:35 +1100310 if (!radeon_check_offset(dev_priv, (u32) values[i])) {
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000311 DRM_ERROR
312 ("Offset failed range check (reg=%04x sz=%d)\n",
313 reg, sz);
Eric Anholt20caafa2007-08-25 19:22:43 +1000314 return -EINVAL;
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000315 }
Dave Airlie414ed532005-08-16 20:43:16 +1000316 break;
317 default:
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000318 DRM_ERROR("Register %04x failed check as flag=%02x\n",
319 reg + i * 4, r300_reg_flags[(reg >> 2) + i]);
Eric Anholt20caafa2007-08-25 19:22:43 +1000320 return -EINVAL;
Dave Airlie414ed532005-08-16 20:43:16 +1000321 }
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000322 }
323
324 BEGIN_RING(1 + sz);
325 OUT_RING(CP_PACKET0(reg, sz - 1));
326 OUT_RING_TABLE(values, sz);
Dave Airlie414ed532005-08-16 20:43:16 +1000327 ADVANCE_RING();
328
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000329 cmdbuf->buf += sz * 4;
330 cmdbuf->bufsz -= sz * 4;
Dave Airlie414ed532005-08-16 20:43:16 +1000331
332 return 0;
333}
334
335/**
336 * Emits a packet0 setting arbitrary registers.
337 * Called by r300_do_cp_cmdbuf.
338 *
339 * Note that checks are performed on contents and addresses of the registers
340 */
Dave Airlied985c102006-01-02 21:32:48 +1100341static __inline__ int r300_emit_packet0(drm_radeon_private_t *dev_priv,
342 drm_radeon_kcmd_buffer_t *cmdbuf,
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000343 drm_r300_cmd_header_t header)
Dave Airlie414ed532005-08-16 20:43:16 +1000344{
345 int reg;
346 int sz;
347 RING_LOCALS;
348
349 sz = header.packet0.count;
350 reg = (header.packet0.reghi << 8) | header.packet0.reglo;
351
352 if (!sz)
353 return 0;
354
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000355 if (sz * 4 > cmdbuf->bufsz)
Eric Anholt20caafa2007-08-25 19:22:43 +1000356 return -EINVAL;
Dave Airlie414ed532005-08-16 20:43:16 +1000357
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000358 if (reg + sz * 4 >= 0x10000) {
359 DRM_ERROR("No such registers in hardware reg=%04x sz=%d\n", reg,
360 sz);
Eric Anholt20caafa2007-08-25 19:22:43 +1000361 return -EINVAL;
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000362 }
363
364 if (r300_check_range(reg, sz)) {
Dave Airlie414ed532005-08-16 20:43:16 +1000365 /* go and check everything */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000366 return r300_emit_carefully_checked_packet0(dev_priv, cmdbuf,
367 header);
368 }
Dave Airlie414ed532005-08-16 20:43:16 +1000369 /* the rest of the data is safe to emit, whatever the values the user passed */
370
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000371 BEGIN_RING(1 + sz);
372 OUT_RING(CP_PACKET0(reg, sz - 1));
Dave Airlieb3a83632005-09-30 18:37:36 +1000373 OUT_RING_TABLE((int *)cmdbuf->buf, sz);
Dave Airlie414ed532005-08-16 20:43:16 +1000374 ADVANCE_RING();
375
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000376 cmdbuf->buf += sz * 4;
377 cmdbuf->bufsz -= sz * 4;
Dave Airlie414ed532005-08-16 20:43:16 +1000378
379 return 0;
380}
381
Dave Airlie414ed532005-08-16 20:43:16 +1000382/**
383 * Uploads user-supplied vertex program instructions or parameters onto
384 * the graphics card.
385 * Called by r300_do_cp_cmdbuf.
386 */
Dave Airlied985c102006-01-02 21:32:48 +1100387static __inline__ int r300_emit_vpu(drm_radeon_private_t *dev_priv,
388 drm_radeon_kcmd_buffer_t *cmdbuf,
Dave Airlie414ed532005-08-16 20:43:16 +1000389 drm_r300_cmd_header_t header)
390{
391 int sz;
392 int addr;
393 RING_LOCALS;
394
395 sz = header.vpu.count;
396 addr = (header.vpu.adrhi << 8) | header.vpu.adrlo;
397
398 if (!sz)
399 return 0;
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000400 if (sz * 16 > cmdbuf->bufsz)
Eric Anholt20caafa2007-08-25 19:22:43 +1000401 return -EINVAL;
Dave Airlie414ed532005-08-16 20:43:16 +1000402
Jerome Glisse54f961a2008-08-13 09:46:31 +1000403 /* VAP is very sensitive so we purge cache before we program it
404 * and we also flush its state before & after */
405 BEGIN_RING(6);
406 OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
407 OUT_RING(R300_RB3D_DC_FLUSH);
408 OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
409 OUT_RING(RADEON_WAIT_3D_IDLECLEAN);
410 OUT_RING(CP_PACKET0(R300_VAP_PVS_STATE_FLUSH_REG, 0));
411 OUT_RING(0);
412 ADVANCE_RING();
413 /* set flush flag */
414 dev_priv->track_flush |= RADEON_FLUSH_EMITED;
415
416 BEGIN_RING(3 + sz * 4);
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000417 OUT_RING_REG(R300_VAP_PVS_UPLOAD_ADDRESS, addr);
418 OUT_RING(CP_PACKET0_TABLE(R300_VAP_PVS_UPLOAD_DATA, sz * 4 - 1));
Dave Airlieb3a83632005-09-30 18:37:36 +1000419 OUT_RING_TABLE((int *)cmdbuf->buf, sz * 4);
Jerome Glisse54f961a2008-08-13 09:46:31 +1000420 ADVANCE_RING();
Dave Airlie414ed532005-08-16 20:43:16 +1000421
Jerome Glisse54f961a2008-08-13 09:46:31 +1000422 BEGIN_RING(2);
423 OUT_RING(CP_PACKET0(R300_VAP_PVS_STATE_FLUSH_REG, 0));
424 OUT_RING(0);
Dave Airlie414ed532005-08-16 20:43:16 +1000425 ADVANCE_RING();
426
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000427 cmdbuf->buf += sz * 16;
428 cmdbuf->bufsz -= sz * 16;
Dave Airlie414ed532005-08-16 20:43:16 +1000429
430 return 0;
431}
432
Dave Airlie414ed532005-08-16 20:43:16 +1000433/**
434 * Emit a clear packet from userspace.
435 * Called by r300_emit_packet3.
436 */
Dave Airlied985c102006-01-02 21:32:48 +1100437static __inline__ int r300_emit_clear(drm_radeon_private_t *dev_priv,
438 drm_radeon_kcmd_buffer_t *cmdbuf)
Dave Airlie414ed532005-08-16 20:43:16 +1000439{
440 RING_LOCALS;
441
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000442 if (8 * 4 > cmdbuf->bufsz)
Eric Anholt20caafa2007-08-25 19:22:43 +1000443 return -EINVAL;
Dave Airlie414ed532005-08-16 20:43:16 +1000444
445 BEGIN_RING(10);
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000446 OUT_RING(CP_PACKET3(R200_3D_DRAW_IMMD_2, 8));
447 OUT_RING(R300_PRIM_TYPE_POINT | R300_PRIM_WALK_RING |
448 (1 << R300_PRIM_NUM_VERTICES_SHIFT));
Dave Airlieb3a83632005-09-30 18:37:36 +1000449 OUT_RING_TABLE((int *)cmdbuf->buf, 8);
Dave Airlie414ed532005-08-16 20:43:16 +1000450 ADVANCE_RING();
451
Jerome Glisse54f961a2008-08-13 09:46:31 +1000452 BEGIN_RING(4);
453 OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
454 OUT_RING(R300_RB3D_DC_FLUSH);
455 OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
456 OUT_RING(RADEON_WAIT_3D_IDLECLEAN);
457 ADVANCE_RING();
458 /* set flush flag */
459 dev_priv->track_flush |= RADEON_FLUSH_EMITED;
460
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000461 cmdbuf->buf += 8 * 4;
462 cmdbuf->bufsz -= 8 * 4;
Dave Airlie414ed532005-08-16 20:43:16 +1000463
464 return 0;
465}
466
Dave Airlied985c102006-01-02 21:32:48 +1100467static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t *dev_priv,
468 drm_radeon_kcmd_buffer_t *cmdbuf,
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000469 u32 header)
Dave Airlie414ed532005-08-16 20:43:16 +1000470{
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000471 int count, i, k;
472#define MAX_ARRAY_PACKET 64
Dave Airlie414ed532005-08-16 20:43:16 +1000473 u32 payload[MAX_ARRAY_PACKET];
474 u32 narrays;
475 RING_LOCALS;
476
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000477 count = (header >> 16) & 0x3fff;
478
479 if ((count + 1) > MAX_ARRAY_PACKET) {
480 DRM_ERROR("Too large payload in 3D_LOAD_VBPNTR (count=%d)\n",
481 count);
Eric Anholt20caafa2007-08-25 19:22:43 +1000482 return -EINVAL;
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000483 }
484 memset(payload, 0, MAX_ARRAY_PACKET * 4);
485 memcpy(payload, cmdbuf->buf + 4, (count + 1) * 4);
486
Dave Airlie414ed532005-08-16 20:43:16 +1000487 /* carefully check packet contents */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000488
489 narrays = payload[0];
490 k = 0;
491 i = 1;
492 while ((k < narrays) && (i < (count + 1))) {
493 i++; /* skip attribute field */
=?utf-8?q?Michel_D=C3=A4nzer?=1d6bb8e2006-12-15 18:54:35 +1100494 if (!radeon_check_offset(dev_priv, payload[i])) {
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000495 DRM_ERROR
496 ("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n",
497 k, i);
Eric Anholt20caafa2007-08-25 19:22:43 +1000498 return -EINVAL;
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000499 }
Dave Airlie414ed532005-08-16 20:43:16 +1000500 k++;
501 i++;
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000502 if (k == narrays)
503 break;
Dave Airlie414ed532005-08-16 20:43:16 +1000504 /* have one more to process, they come in pairs */
=?utf-8?q?Michel_D=C3=A4nzer?=1d6bb8e2006-12-15 18:54:35 +1100505 if (!radeon_check_offset(dev_priv, payload[i])) {
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000506 DRM_ERROR
507 ("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n",
508 k, i);
Eric Anholt20caafa2007-08-25 19:22:43 +1000509 return -EINVAL;
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000510 }
Dave Airlie414ed532005-08-16 20:43:16 +1000511 k++;
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000512 i++;
513 }
Dave Airlie414ed532005-08-16 20:43:16 +1000514 /* do the counts match what we expect ? */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000515 if ((k != narrays) || (i != (count + 1))) {
516 DRM_ERROR
517 ("Malformed 3D_LOAD_VBPNTR packet (k=%d i=%d narrays=%d count+1=%d).\n",
518 k, i, narrays, count + 1);
Eric Anholt20caafa2007-08-25 19:22:43 +1000519 return -EINVAL;
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000520 }
Dave Airlie414ed532005-08-16 20:43:16 +1000521
522 /* all clear, output packet */
523
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000524 BEGIN_RING(count + 2);
Dave Airlie414ed532005-08-16 20:43:16 +1000525 OUT_RING(header);
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000526 OUT_RING_TABLE(payload, count + 1);
Dave Airlie414ed532005-08-16 20:43:16 +1000527 ADVANCE_RING();
528
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000529 cmdbuf->buf += (count + 2) * 4;
530 cmdbuf->bufsz -= (count + 2) * 4;
Dave Airlie414ed532005-08-16 20:43:16 +1000531
532 return 0;
533}
Dave Airlied5ea7022006-03-19 19:37:55 +1100534
Dave Airlie4e5e2e22006-02-18 15:51:35 +1100535static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv,
536 drm_radeon_kcmd_buffer_t *cmdbuf)
537{
538 u32 *cmd = (u32 *) cmdbuf->buf;
539 int count, ret;
540 RING_LOCALS;
541
542 count=(cmd[0]>>16) & 0x3fff;
543
544 if (cmd[0] & 0x8000) {
545 u32 offset;
546
Dave Airliebc5f4522007-11-05 12:50:58 +1000547 if (cmd[1] & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL
Dave Airlie4e5e2e22006-02-18 15:51:35 +1100548 | RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
549 offset = cmd[2] << 10;
=?utf-8?q?Michel_D=C3=A4nzer?=1d6bb8e2006-12-15 18:54:35 +1100550 ret = !radeon_check_offset(dev_priv, offset);
Dave Airlie73d72cf2006-02-18 16:30:54 +1100551 if (ret) {
Dave Airlie4e5e2e22006-02-18 15:51:35 +1100552 DRM_ERROR("Invalid bitblt first offset is %08X\n", offset);
Eric Anholt20caafa2007-08-25 19:22:43 +1000553 return -EINVAL;
Dave Airlie4e5e2e22006-02-18 15:51:35 +1100554 }
555 }
556
557 if ((cmd[1] & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) &&
558 (cmd[1] & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
559 offset = cmd[3] << 10;
=?utf-8?q?Michel_D=C3=A4nzer?=1d6bb8e2006-12-15 18:54:35 +1100560 ret = !radeon_check_offset(dev_priv, offset);
Dave Airlie73d72cf2006-02-18 16:30:54 +1100561 if (ret) {
Dave Airlie4e5e2e22006-02-18 15:51:35 +1100562 DRM_ERROR("Invalid bitblt second offset is %08X\n", offset);
Eric Anholt20caafa2007-08-25 19:22:43 +1000563 return -EINVAL;
Dave Airlie4e5e2e22006-02-18 15:51:35 +1100564 }
Dave Airliebc5f4522007-11-05 12:50:58 +1000565
Dave Airlie4e5e2e22006-02-18 15:51:35 +1100566 }
567 }
568
569 BEGIN_RING(count+2);
570 OUT_RING(cmd[0]);
571 OUT_RING_TABLE((int *)(cmdbuf->buf + 4), count + 1);
572 ADVANCE_RING();
573
574 cmdbuf->buf += (count+2)*4;
575 cmdbuf->bufsz -= (count+2)*4;
576
577 return 0;
578}
Dave Airlie414ed532005-08-16 20:43:16 +1000579
Roland Scheideggera1aa2892006-10-24 21:45:00 +1000580static __inline__ int r300_emit_indx_buffer(drm_radeon_private_t *dev_priv,
581 drm_radeon_kcmd_buffer_t *cmdbuf)
582{
583 u32 *cmd = (u32 *) cmdbuf->buf;
584 int count, ret;
585 RING_LOCALS;
586
587 count=(cmd[0]>>16) & 0x3fff;
588
589 if ((cmd[1] & 0x8000ffff) != 0x80000810) {
590 DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]);
Eric Anholt20caafa2007-08-25 19:22:43 +1000591 return -EINVAL;
Roland Scheideggera1aa2892006-10-24 21:45:00 +1000592 }
=?utf-8?q?Michel_D=C3=A4nzer?=1d6bb8e2006-12-15 18:54:35 +1100593 ret = !radeon_check_offset(dev_priv, cmd[2]);
Roland Scheideggera1aa2892006-10-24 21:45:00 +1000594 if (ret) {
595 DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]);
Eric Anholt20caafa2007-08-25 19:22:43 +1000596 return -EINVAL;
Roland Scheideggera1aa2892006-10-24 21:45:00 +1000597 }
598
599 BEGIN_RING(count+2);
600 OUT_RING(cmd[0]);
601 OUT_RING_TABLE((int *)(cmdbuf->buf + 4), count + 1);
602 ADVANCE_RING();
603
604 cmdbuf->buf += (count+2)*4;
605 cmdbuf->bufsz -= (count+2)*4;
606
607 return 0;
608}
609
Dave Airlied985c102006-01-02 21:32:48 +1100610static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv,
611 drm_radeon_kcmd_buffer_t *cmdbuf)
Dave Airlie414ed532005-08-16 20:43:16 +1000612{
613 u32 header;
614 int count;
615 RING_LOCALS;
616
617 if (4 > cmdbuf->bufsz)
Eric Anholt20caafa2007-08-25 19:22:43 +1000618 return -EINVAL;
Dave Airlie414ed532005-08-16 20:43:16 +1000619
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000620 /* Fixme !! This simply emits a packet without much checking.
Dave Airlie414ed532005-08-16 20:43:16 +1000621 We need to be smarter. */
622
623 /* obtain first word - actual packet3 header */
Dave Airlieb3a83632005-09-30 18:37:36 +1000624 header = *(u32 *) cmdbuf->buf;
Dave Airlie414ed532005-08-16 20:43:16 +1000625
626 /* Is it packet 3 ? */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000627 if ((header >> 30) != 0x3) {
Dave Airlie414ed532005-08-16 20:43:16 +1000628 DRM_ERROR("Not a packet3 header (0x%08x)\n", header);
Eric Anholt20caafa2007-08-25 19:22:43 +1000629 return -EINVAL;
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000630 }
Dave Airlie414ed532005-08-16 20:43:16 +1000631
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000632 count = (header >> 16) & 0x3fff;
Dave Airlie414ed532005-08-16 20:43:16 +1000633
634 /* Check again now that we know how much data to expect */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000635 if ((count + 2) * 4 > cmdbuf->bufsz) {
636 DRM_ERROR
637 ("Expected packet3 of length %d but have only %d bytes left\n",
638 (count + 2) * 4, cmdbuf->bufsz);
Eric Anholt20caafa2007-08-25 19:22:43 +1000639 return -EINVAL;
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000640 }
Dave Airlie414ed532005-08-16 20:43:16 +1000641
642 /* Is it a packet type we know about ? */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000643 switch (header & 0xff00) {
644 case RADEON_3D_LOAD_VBPNTR: /* load vertex array pointers */
Dave Airlie414ed532005-08-16 20:43:16 +1000645 return r300_emit_3d_load_vbpntr(dev_priv, cmdbuf, header);
646
Dave Airlie4e5e2e22006-02-18 15:51:35 +1100647 case RADEON_CNTL_BITBLT_MULTI:
648 return r300_emit_bitblt_multi(dev_priv, cmdbuf);
649
Jerome Glisse54f961a2008-08-13 09:46:31 +1000650 case RADEON_CP_INDX_BUFFER:
651 /* DRAW_INDX_2 without INDX_BUFFER seems to lock up the gpu */
Roland Scheideggera1aa2892006-10-24 21:45:00 +1000652 return r300_emit_indx_buffer(dev_priv, cmdbuf);
Jerome Glisse54f961a2008-08-13 09:46:31 +1000653 case RADEON_CP_3D_DRAW_IMMD_2:
654 /* triggers drawing using in-packet vertex data */
655 case RADEON_CP_3D_DRAW_VBUF_2:
656 /* triggers drawing of vertex buffers setup elsewhere */
657 case RADEON_CP_3D_DRAW_INDX_2:
658 /* triggers drawing using indices to vertex buffer */
659 /* whenever we send vertex we clear flush & purge */
660 dev_priv->track_flush &= ~(RADEON_FLUSH_EMITED |
661 RADEON_PURGE_EMITED);
662 break;
Dave Airlie414ed532005-08-16 20:43:16 +1000663 case RADEON_WAIT_FOR_IDLE:
664 case RADEON_CP_NOP:
665 /* these packets are safe */
666 break;
667 default:
668 DRM_ERROR("Unknown packet3 header (0x%08x)\n", header);
Eric Anholt20caafa2007-08-25 19:22:43 +1000669 return -EINVAL;
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000670 }
Dave Airlie414ed532005-08-16 20:43:16 +1000671
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000672 BEGIN_RING(count + 2);
Dave Airlie414ed532005-08-16 20:43:16 +1000673 OUT_RING(header);
Dave Airlieb3a83632005-09-30 18:37:36 +1000674 OUT_RING_TABLE((int *)(cmdbuf->buf + 4), count + 1);
Dave Airlie414ed532005-08-16 20:43:16 +1000675 ADVANCE_RING();
676
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000677 cmdbuf->buf += (count + 2) * 4;
678 cmdbuf->bufsz -= (count + 2) * 4;
Dave Airlie414ed532005-08-16 20:43:16 +1000679
680 return 0;
681}
682
Dave Airlie414ed532005-08-16 20:43:16 +1000683/**
684 * Emit a rendering packet3 from userspace.
685 * Called by r300_do_cp_cmdbuf.
686 */
Dave Airlied985c102006-01-02 21:32:48 +1100687static __inline__ int r300_emit_packet3(drm_radeon_private_t *dev_priv,
688 drm_radeon_kcmd_buffer_t *cmdbuf,
Dave Airlie414ed532005-08-16 20:43:16 +1000689 drm_r300_cmd_header_t header)
690{
691 int n;
692 int ret;
Dave Airlieb3a83632005-09-30 18:37:36 +1000693 char *orig_buf = cmdbuf->buf;
Dave Airlie414ed532005-08-16 20:43:16 +1000694 int orig_bufsz = cmdbuf->bufsz;
695
696 /* This is a do-while-loop so that we run the interior at least once,
697 * even if cmdbuf->nbox is 0. Compare r300_emit_cliprects for rationale.
698 */
699 n = 0;
700 do {
701 if (cmdbuf->nbox > R300_SIMULTANEOUS_CLIPRECTS) {
702 ret = r300_emit_cliprects(dev_priv, cmdbuf, n);
703 if (ret)
704 return ret;
705
706 cmdbuf->buf = orig_buf;
707 cmdbuf->bufsz = orig_bufsz;
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000708 }
Dave Airlie414ed532005-08-16 20:43:16 +1000709
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000710 switch (header.packet3.packet) {
Dave Airlie414ed532005-08-16 20:43:16 +1000711 case R300_CMD_PACKET3_CLEAR:
712 DRM_DEBUG("R300_CMD_PACKET3_CLEAR\n");
713 ret = r300_emit_clear(dev_priv, cmdbuf);
714 if (ret) {
715 DRM_ERROR("r300_emit_clear failed\n");
716 return ret;
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000717 }
Dave Airlie414ed532005-08-16 20:43:16 +1000718 break;
719
720 case R300_CMD_PACKET3_RAW:
721 DRM_DEBUG("R300_CMD_PACKET3_RAW\n");
722 ret = r300_emit_raw_packet3(dev_priv, cmdbuf);
723 if (ret) {
724 DRM_ERROR("r300_emit_raw_packet3 failed\n");
725 return ret;
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000726 }
Dave Airlie414ed532005-08-16 20:43:16 +1000727 break;
728
729 default:
730 DRM_ERROR("bad packet3 type %i at %p\n",
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000731 header.packet3.packet,
732 cmdbuf->buf - sizeof(header));
Eric Anholt20caafa2007-08-25 19:22:43 +1000733 return -EINVAL;
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000734 }
Dave Airlie414ed532005-08-16 20:43:16 +1000735
736 n += R300_SIMULTANEOUS_CLIPRECTS;
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000737 } while (n < cmdbuf->nbox);
Dave Airlie414ed532005-08-16 20:43:16 +1000738
739 return 0;
740}
741
742/* Some of the R300 chips seem to be extremely touchy about the two registers
743 * that are configured in r300_pacify.
744 * Among the worst offenders seems to be the R300 ND (0x4E44): When userspace
745 * sends a command buffer that contains only state setting commands and a
746 * vertex program/parameter upload sequence, this will eventually lead to a
747 * lockup, unless the sequence is bracketed by calls to r300_pacify.
748 * So we should take great care to *always* call r300_pacify before
749 * *anything* 3D related, and again afterwards. This is what the
750 * call bracket in r300_do_cp_cmdbuf is for.
751 */
752
753/**
754 * Emit the sequence to pacify R300.
755 */
Dave Airlied985c102006-01-02 21:32:48 +1100756static __inline__ void r300_pacify(drm_radeon_private_t *dev_priv)
Dave Airlie414ed532005-08-16 20:43:16 +1000757{
Jerome Glisse54f961a2008-08-13 09:46:31 +1000758 uint32_t cache_z, cache_3d, cache_2d;
Dave Airlie414ed532005-08-16 20:43:16 +1000759 RING_LOCALS;
Jerome Glisse54f961a2008-08-13 09:46:31 +1000760
761 cache_z = R300_ZC_FLUSH;
762 cache_2d = R300_RB2D_DC_FLUSH;
763 cache_3d = R300_RB3D_DC_FLUSH;
764 if (!(dev_priv->track_flush & RADEON_PURGE_EMITED)) {
765 /* we can purge, primitive where draw since last purge */
766 cache_z |= R300_ZC_FREE;
767 cache_2d |= R300_RB2D_DC_FREE;
768 cache_3d |= R300_RB3D_DC_FREE;
769 }
Dave Airlie414ed532005-08-16 20:43:16 +1000770
Jerome Glisse54f961a2008-08-13 09:46:31 +1000771 /* flush & purge zbuffer */
772 BEGIN_RING(2);
Dave Airlie21efa2b2008-06-19 13:01:58 +1000773 OUT_RING(CP_PACKET0(R300_ZB_ZCACHE_CTLSTAT, 0));
Jerome Glisse54f961a2008-08-13 09:46:31 +1000774 OUT_RING(cache_z);
Dave Airlie414ed532005-08-16 20:43:16 +1000775 ADVANCE_RING();
Jerome Glisse54f961a2008-08-13 09:46:31 +1000776 /* flush & purge 3d */
777 BEGIN_RING(2);
778 OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
779 OUT_RING(cache_3d);
780 ADVANCE_RING();
781 /* flush & purge texture */
782 BEGIN_RING(2);
783 OUT_RING(CP_PACKET0(R300_TX_INVALTAGS, 0));
784 OUT_RING(0);
785 ADVANCE_RING();
786 /* FIXME: is this one really needed ? */
787 BEGIN_RING(2);
788 OUT_RING(CP_PACKET0(R300_RB3D_AARESOLVE_CTL, 0));
789 OUT_RING(0);
790 ADVANCE_RING();
791 BEGIN_RING(2);
792 OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
793 OUT_RING(RADEON_WAIT_3D_IDLECLEAN);
794 ADVANCE_RING();
795 /* flush & purge 2d through E2 as RB2D will trigger lockup */
796 BEGIN_RING(4);
797 OUT_RING(CP_PACKET0(R300_DSTCACHE_CTLSTAT, 0));
798 OUT_RING(cache_2d);
799 OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
800 OUT_RING(RADEON_WAIT_2D_IDLECLEAN |
801 RADEON_WAIT_HOST_IDLECLEAN);
802 ADVANCE_RING();
803 /* set flush & purge flags */
804 dev_priv->track_flush |= RADEON_FLUSH_EMITED | RADEON_PURGE_EMITED;
Dave Airlie414ed532005-08-16 20:43:16 +1000805}
806
Dave Airlie414ed532005-08-16 20:43:16 +1000807/**
808 * Called by r300_do_cp_cmdbuf to update the internal buffer age and state.
809 * The actual age emit is done by r300_do_cp_cmdbuf, which is why you must
810 * be careful about how this function is called.
811 */
Dave Airlie056219e2007-07-11 16:17:42 +1000812static void r300_discard_buffer(struct drm_device * dev, struct drm_buf * buf)
Dave Airlie414ed532005-08-16 20:43:16 +1000813{
814 drm_radeon_private_t *dev_priv = dev->dev_private;
815 drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
816
817 buf_priv->age = ++dev_priv->sarea_priv->last_dispatch;
818 buf->pending = 1;
819 buf->used = 0;
820}
821
Dave Airlie0c76be32008-03-30 07:51:49 +1000822static void r300_cmd_wait(drm_radeon_private_t * dev_priv,
823 drm_r300_cmd_header_t header)
824{
825 u32 wait_until;
826 RING_LOCALS;
827
828 if (!header.wait.flags)
829 return;
830
831 wait_until = 0;
832
833 switch(header.wait.flags) {
834 case R300_WAIT_2D:
835 wait_until = RADEON_WAIT_2D_IDLE;
836 break;
837 case R300_WAIT_3D:
838 wait_until = RADEON_WAIT_3D_IDLE;
839 break;
840 case R300_NEW_WAIT_2D_3D:
841 wait_until = RADEON_WAIT_2D_IDLE|RADEON_WAIT_3D_IDLE;
842 break;
843 case R300_NEW_WAIT_2D_2D_CLEAN:
844 wait_until = RADEON_WAIT_2D_IDLE|RADEON_WAIT_2D_IDLECLEAN;
845 break;
846 case R300_NEW_WAIT_3D_3D_CLEAN:
847 wait_until = RADEON_WAIT_3D_IDLE|RADEON_WAIT_3D_IDLECLEAN;
848 break;
849 case R300_NEW_WAIT_2D_2D_CLEAN_3D_3D_CLEAN:
850 wait_until = RADEON_WAIT_2D_IDLE|RADEON_WAIT_2D_IDLECLEAN;
851 wait_until |= RADEON_WAIT_3D_IDLE|RADEON_WAIT_3D_IDLECLEAN;
852 break;
853 default:
854 return;
855 }
856
857 BEGIN_RING(2);
858 OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
859 OUT_RING(wait_until);
860 ADVANCE_RING();
861}
862
Dave Airlieee4621f2006-03-19 19:45:26 +1100863static int r300_scratch(drm_radeon_private_t *dev_priv,
864 drm_radeon_kcmd_buffer_t *cmdbuf,
865 drm_r300_cmd_header_t header)
866{
867 u32 *ref_age_base;
868 u32 i, buf_idx, h_pending;
869 RING_LOCALS;
Dave Airliebc5f4522007-11-05 12:50:58 +1000870
871 if (cmdbuf->bufsz <
Dave Airlieee4621f2006-03-19 19:45:26 +1100872 (sizeof(u64) + header.scratch.n_bufs * sizeof(buf_idx))) {
Eric Anholt20caafa2007-08-25 19:22:43 +1000873 return -EINVAL;
Dave Airlieee4621f2006-03-19 19:45:26 +1100874 }
Dave Airliebc5f4522007-11-05 12:50:58 +1000875
Dave Airlieee4621f2006-03-19 19:45:26 +1100876 if (header.scratch.reg >= 5) {
Eric Anholt20caafa2007-08-25 19:22:43 +1000877 return -EINVAL;
Dave Airlieee4621f2006-03-19 19:45:26 +1100878 }
Dave Airliebc5f4522007-11-05 12:50:58 +1000879
Dave Airlieee4621f2006-03-19 19:45:26 +1100880 dev_priv->scratch_ages[header.scratch.reg]++;
Dave Airliebc5f4522007-11-05 12:50:58 +1000881
Dave Airliecaa98c42006-04-23 18:14:00 +1000882 ref_age_base = (u32 *)(unsigned long)*((uint64_t *)cmdbuf->buf);
Dave Airliebc5f4522007-11-05 12:50:58 +1000883
Dave Airlieee4621f2006-03-19 19:45:26 +1100884 cmdbuf->buf += sizeof(u64);
885 cmdbuf->bufsz -= sizeof(u64);
Dave Airliebc5f4522007-11-05 12:50:58 +1000886
Dave Airlieee4621f2006-03-19 19:45:26 +1100887 for (i=0; i < header.scratch.n_bufs; i++) {
888 buf_idx = *(u32 *)cmdbuf->buf;
889 buf_idx *= 2; /* 8 bytes per buf */
Dave Airliebc5f4522007-11-05 12:50:58 +1000890
Dave Airlieee4621f2006-03-19 19:45:26 +1100891 if (DRM_COPY_TO_USER(ref_age_base + buf_idx, &dev_priv->scratch_ages[header.scratch.reg], sizeof(u32))) {
Eric Anholt20caafa2007-08-25 19:22:43 +1000892 return -EINVAL;
Dave Airlieee4621f2006-03-19 19:45:26 +1100893 }
Dave Airliebc5f4522007-11-05 12:50:58 +1000894
Dave Airlieee4621f2006-03-19 19:45:26 +1100895 if (DRM_COPY_FROM_USER(&h_pending, ref_age_base + buf_idx + 1, sizeof(u32))) {
Eric Anholt20caafa2007-08-25 19:22:43 +1000896 return -EINVAL;
Dave Airlieee4621f2006-03-19 19:45:26 +1100897 }
Dave Airliebc5f4522007-11-05 12:50:58 +1000898
Dave Airlieee4621f2006-03-19 19:45:26 +1100899 if (h_pending == 0) {
Eric Anholt20caafa2007-08-25 19:22:43 +1000900 return -EINVAL;
Dave Airlieee4621f2006-03-19 19:45:26 +1100901 }
Dave Airliebc5f4522007-11-05 12:50:58 +1000902
Dave Airlieee4621f2006-03-19 19:45:26 +1100903 h_pending--;
Dave Airliebc5f4522007-11-05 12:50:58 +1000904
Dave Airlieee4621f2006-03-19 19:45:26 +1100905 if (DRM_COPY_TO_USER(ref_age_base + buf_idx + 1, &h_pending, sizeof(u32))) {
Eric Anholt20caafa2007-08-25 19:22:43 +1000906 return -EINVAL;
Dave Airlieee4621f2006-03-19 19:45:26 +1100907 }
Dave Airliebc5f4522007-11-05 12:50:58 +1000908
Dave Airlieee4621f2006-03-19 19:45:26 +1100909 cmdbuf->buf += sizeof(buf_idx);
910 cmdbuf->bufsz -= sizeof(buf_idx);
911 }
Dave Airliebc5f4522007-11-05 12:50:58 +1000912
Dave Airlieee4621f2006-03-19 19:45:26 +1100913 BEGIN_RING(2);
Oliver McFaddenc6c656b2007-07-11 12:24:10 +1000914 OUT_RING( CP_PACKET0( RADEON_SCRATCH_REG0 + header.scratch.reg * 4, 0 ) );
915 OUT_RING( dev_priv->scratch_ages[header.scratch.reg] );
Dave Airlieee4621f2006-03-19 19:45:26 +1100916 ADVANCE_RING();
Dave Airliebc5f4522007-11-05 12:50:58 +1000917
Dave Airlieee4621f2006-03-19 19:45:26 +1100918 return 0;
919}
920
Dave Airlie414ed532005-08-16 20:43:16 +1000921/**
Dave Airliec0beb2a2008-05-28 13:52:28 +1000922 * Uploads user-supplied vertex program instructions or parameters onto
923 * the graphics card.
924 * Called by r300_do_cp_cmdbuf.
925 */
926static inline int r300_emit_r500fp(drm_radeon_private_t *dev_priv,
927 drm_radeon_kcmd_buffer_t *cmdbuf,
928 drm_r300_cmd_header_t header)
929{
930 int sz;
931 int addr;
932 int type;
933 int clamp;
934 int stride;
935 RING_LOCALS;
936
937 sz = header.r500fp.count;
938 /* address is 9 bits 0 - 8, bit 1 of flags is part of address */
939 addr = ((header.r500fp.adrhi_flags & 1) << 8) | header.r500fp.adrlo;
940
941 type = !!(header.r500fp.adrhi_flags & R500FP_CONSTANT_TYPE);
942 clamp = !!(header.r500fp.adrhi_flags & R500FP_CONSTANT_CLAMP);
943
944 addr |= (type << 16);
945 addr |= (clamp << 17);
946
947 stride = type ? 4 : 6;
948
949 DRM_DEBUG("r500fp %d %d type: %d\n", sz, addr, type);
950 if (!sz)
951 return 0;
952 if (sz * stride * 4 > cmdbuf->bufsz)
953 return -EINVAL;
954
955 BEGIN_RING(3 + sz * stride);
956 OUT_RING_REG(R500_GA_US_VECTOR_INDEX, addr);
957 OUT_RING(CP_PACKET0_TABLE(R500_GA_US_VECTOR_DATA, sz * stride - 1));
958 OUT_RING_TABLE((int *)cmdbuf->buf, sz * stride);
959
960 ADVANCE_RING();
961
962 cmdbuf->buf += sz * stride * 4;
963 cmdbuf->bufsz -= sz * stride * 4;
964
965 return 0;
966}
967
968
969/**
Dave Airlie414ed532005-08-16 20:43:16 +1000970 * Parses and validates a user-supplied command buffer and emits appropriate
971 * commands on the DMA ring buffer.
972 * Called by the ioctl handler function radeon_cp_cmdbuf.
973 */
Dave Airlie84b1fd12007-07-11 15:53:27 +1000974int r300_do_cp_cmdbuf(struct drm_device *dev,
Eric Anholt6c340ea2007-08-25 20:23:09 +1000975 struct drm_file *file_priv,
Dave Airlied985c102006-01-02 21:32:48 +1100976 drm_radeon_kcmd_buffer_t *cmdbuf)
Dave Airlie414ed532005-08-16 20:43:16 +1000977{
978 drm_radeon_private_t *dev_priv = dev->dev_private;
Dave Airliecdd55a22007-07-11 16:32:08 +1000979 struct drm_device_dma *dma = dev->dma;
Dave Airlie056219e2007-07-11 16:17:42 +1000980 struct drm_buf *buf = NULL;
Dave Airlie414ed532005-08-16 20:43:16 +1000981 int emit_dispatch_age = 0;
982 int ret = 0;
983
984 DRM_DEBUG("\n");
985
Jerome Glisse54f961a2008-08-13 09:46:31 +1000986 /* pacify */
Dave Airlie414ed532005-08-16 20:43:16 +1000987 r300_pacify(dev_priv);
988
989 if (cmdbuf->nbox <= R300_SIMULTANEOUS_CLIPRECTS) {
990 ret = r300_emit_cliprects(dev_priv, cmdbuf, 0);
991 if (ret)
992 goto cleanup;
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000993 }
Dave Airlie414ed532005-08-16 20:43:16 +1000994
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000995 while (cmdbuf->bufsz >= sizeof(drm_r300_cmd_header_t)) {
Dave Airlie414ed532005-08-16 20:43:16 +1000996 int idx;
997 drm_r300_cmd_header_t header;
998
999 header.u = *(unsigned int *)cmdbuf->buf;
1000
1001 cmdbuf->buf += sizeof(header);
1002 cmdbuf->bufsz -= sizeof(header);
1003
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001004 switch (header.header.cmd_type) {
1005 case R300_CMD_PACKET0:
Dave Airlie414ed532005-08-16 20:43:16 +10001006 DRM_DEBUG("R300_CMD_PACKET0\n");
1007 ret = r300_emit_packet0(dev_priv, cmdbuf, header);
1008 if (ret) {
1009 DRM_ERROR("r300_emit_packet0 failed\n");
1010 goto cleanup;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001011 }
Dave Airlie414ed532005-08-16 20:43:16 +10001012 break;
1013
1014 case R300_CMD_VPU:
1015 DRM_DEBUG("R300_CMD_VPU\n");
1016 ret = r300_emit_vpu(dev_priv, cmdbuf, header);
1017 if (ret) {
1018 DRM_ERROR("r300_emit_vpu failed\n");
1019 goto cleanup;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001020 }
Dave Airlie414ed532005-08-16 20:43:16 +10001021 break;
1022
1023 case R300_CMD_PACKET3:
1024 DRM_DEBUG("R300_CMD_PACKET3\n");
1025 ret = r300_emit_packet3(dev_priv, cmdbuf, header);
1026 if (ret) {
1027 DRM_ERROR("r300_emit_packet3 failed\n");
1028 goto cleanup;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001029 }
Dave Airlie414ed532005-08-16 20:43:16 +10001030 break;
1031
1032 case R300_CMD_END3D:
1033 DRM_DEBUG("R300_CMD_END3D\n");
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001034 /* TODO:
1035 Ideally userspace driver should not need to issue this call,
1036 i.e. the drm driver should issue it automatically and prevent
1037 lockups.
Dave Airlie414ed532005-08-16 20:43:16 +10001038
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001039 In practice, we do not understand why this call is needed and what
1040 it does (except for some vague guesses that it has to do with cache
1041 coherence) and so the user space driver does it.
1042
1043 Once we are sure which uses prevent lockups the code could be moved
1044 into the kernel and the userspace driver will not
1045 need to use this command.
1046
1047 Note that issuing this command does not hurt anything
1048 except, possibly, performance */
Dave Airlie414ed532005-08-16 20:43:16 +10001049 r300_pacify(dev_priv);
1050 break;
1051
1052 case R300_CMD_CP_DELAY:
1053 /* simple enough, we can do it here */
1054 DRM_DEBUG("R300_CMD_CP_DELAY\n");
1055 {
1056 int i;
1057 RING_LOCALS;
1058
1059 BEGIN_RING(header.delay.count);
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001060 for (i = 0; i < header.delay.count; i++)
Dave Airlie414ed532005-08-16 20:43:16 +10001061 OUT_RING(RADEON_CP_PACKET2);
1062 ADVANCE_RING();
1063 }
1064 break;
1065
1066 case R300_CMD_DMA_DISCARD:
1067 DRM_DEBUG("RADEON_CMD_DMA_DISCARD\n");
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001068 idx = header.dma.buf_idx;
1069 if (idx < 0 || idx >= dma->buf_count) {
1070 DRM_ERROR("buffer index %d (of %d max)\n",
1071 idx, dma->buf_count - 1);
Eric Anholt20caafa2007-08-25 19:22:43 +10001072 ret = -EINVAL;
Dave Airlie414ed532005-08-16 20:43:16 +10001073 goto cleanup;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001074 }
1075
1076 buf = dma->buflist[idx];
Eric Anholt6c340ea2007-08-25 20:23:09 +10001077 if (buf->file_priv != file_priv || buf->pending) {
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001078 DRM_ERROR("bad buffer %p %p %d\n",
Eric Anholt6c340ea2007-08-25 20:23:09 +10001079 buf->file_priv, file_priv,
1080 buf->pending);
Eric Anholt20caafa2007-08-25 19:22:43 +10001081 ret = -EINVAL;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001082 goto cleanup;
1083 }
Dave Airlie414ed532005-08-16 20:43:16 +10001084
1085 emit_dispatch_age = 1;
1086 r300_discard_buffer(dev, buf);
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001087 break;
Dave Airlie414ed532005-08-16 20:43:16 +10001088
1089 case R300_CMD_WAIT:
Dave Airlie414ed532005-08-16 20:43:16 +10001090 DRM_DEBUG("R300_CMD_WAIT\n");
Dave Airlie0c76be32008-03-30 07:51:49 +10001091 r300_cmd_wait(dev_priv, header);
Dave Airlie414ed532005-08-16 20:43:16 +10001092 break;
1093
Dave Airlieee4621f2006-03-19 19:45:26 +11001094 case R300_CMD_SCRATCH:
1095 DRM_DEBUG("R300_CMD_SCRATCH\n");
1096 ret = r300_scratch(dev_priv, cmdbuf, header);
1097 if (ret) {
1098 DRM_ERROR("r300_scratch failed\n");
1099 goto cleanup;
1100 }
1101 break;
Dave Airliebc5f4522007-11-05 12:50:58 +10001102
Dave Airliec0beb2a2008-05-28 13:52:28 +10001103 case R300_CMD_R500FP:
1104 if ((dev_priv->flags & RADEON_FAMILY_MASK) < CHIP_RV515) {
1105 DRM_ERROR("Calling r500 command on r300 card\n");
1106 ret = -EINVAL;
1107 goto cleanup;
1108 }
1109 DRM_DEBUG("R300_CMD_R500FP\n");
1110 ret = r300_emit_r500fp(dev_priv, cmdbuf, header);
1111 if (ret) {
1112 DRM_ERROR("r300_emit_r500fp failed\n");
1113 goto cleanup;
1114 }
1115 break;
Dave Airlie414ed532005-08-16 20:43:16 +10001116 default:
1117 DRM_ERROR("bad cmd_type %i at %p\n",
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001118 header.header.cmd_type,
Dave Airlie414ed532005-08-16 20:43:16 +10001119 cmdbuf->buf - sizeof(header));
Eric Anholt20caafa2007-08-25 19:22:43 +10001120 ret = -EINVAL;
Dave Airlie414ed532005-08-16 20:43:16 +10001121 goto cleanup;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001122 }
Dave Airlie414ed532005-08-16 20:43:16 +10001123 }
1124
1125 DRM_DEBUG("END\n");
1126
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001127 cleanup:
Dave Airlie414ed532005-08-16 20:43:16 +10001128 r300_pacify(dev_priv);
1129
1130 /* We emit the vertex buffer age here, outside the pacifier "brackets"
1131 * for two reasons:
1132 * (1) This may coalesce multiple age emissions into a single one and
1133 * (2) more importantly, some chips lock up hard when scratch registers
1134 * are written inside the pacifier bracket.
1135 */
1136 if (emit_dispatch_age) {
1137 RING_LOCALS;
1138
1139 /* Emit the vertex buffer age */
1140 BEGIN_RING(2);
1141 RADEON_DISPATCH_AGE(dev_priv->sarea_priv->last_dispatch);
1142 ADVANCE_RING();
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001143 }
Dave Airlie414ed532005-08-16 20:43:16 +10001144
1145 COMMIT_RING();
1146
1147 return ret;
1148}