1 /* radeon_state.c -- State support for Radeon -*- linux-c -*-
2  *
3  * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice (including the next
14  * paragraph) shall be included in all copies or substantial portions of the
15  * Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20  * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23  * DEALINGS IN THE SOFTWARE.
24  *
25  * Authors:
26  *    Gareth Hughes <gareth@valinux.com>
27  *    Kevin E. Martin <martin@valinux.com>
28  */
29 
30 #include "radeon.h"
31 #include "drmP.h"
32 #include "drm.h"
33 #include "drm_sarea.h"
34 #include "radeon_drm.h"
35 #include "radeon_drv.h"
36 #include "drm_os_linux.h"
37 
38 /* ================================================================
39  * CP hardware state programming functions
40  */
41 
radeon_emit_clip_rect(drm_radeon_private_t * dev_priv,drm_clip_rect_t * box)42 static inline void radeon_emit_clip_rect( drm_radeon_private_t *dev_priv,
43 					  drm_clip_rect_t *box )
44 {
45 	RING_LOCALS;
46 
47 	DRM_DEBUG( "   box:  x1=%d y1=%d  x2=%d y2=%d\n",
48 		   box->x1, box->y1, box->x2, box->y2 );
49 
50 	BEGIN_RING( 4 );
51 	OUT_RING( CP_PACKET0( RADEON_RE_TOP_LEFT, 0 ) );
52 	OUT_RING( (box->y1 << 16) | box->x1 );
53 	OUT_RING( CP_PACKET0( RADEON_RE_WIDTH_HEIGHT, 0 ) );
54 	OUT_RING( ((box->y2 - 1) << 16) | (box->x2 - 1) );
55 	ADVANCE_RING();
56 }
57 
58 /* Emit 1.1 state
59  */
radeon_emit_state(drm_radeon_private_t * dev_priv,drm_radeon_context_regs_t * ctx,drm_radeon_texture_regs_t * tex,unsigned int dirty)60 static void radeon_emit_state( drm_radeon_private_t *dev_priv,
61 			       drm_radeon_context_regs_t *ctx,
62 			       drm_radeon_texture_regs_t *tex,
63 			       unsigned int dirty )
64 {
65 	RING_LOCALS;
66 	DRM_DEBUG( "dirty=0x%08x\n", dirty );
67 
68 	if ( dirty & RADEON_UPLOAD_CONTEXT ) {
69 		BEGIN_RING( 14 );
70 		OUT_RING( CP_PACKET0( RADEON_PP_MISC, 6 ) );
71 		OUT_RING( ctx->pp_misc );
72 		OUT_RING( ctx->pp_fog_color );
73 		OUT_RING( ctx->re_solid_color );
74 		OUT_RING( ctx->rb3d_blendcntl );
75 		OUT_RING( ctx->rb3d_depthoffset );
76 		OUT_RING( ctx->rb3d_depthpitch );
77 		OUT_RING( ctx->rb3d_zstencilcntl );
78 		OUT_RING( CP_PACKET0( RADEON_PP_CNTL, 2 ) );
79 		OUT_RING( ctx->pp_cntl );
80 		OUT_RING( ctx->rb3d_cntl );
81 		OUT_RING( ctx->rb3d_coloroffset );
82 		OUT_RING( CP_PACKET0( RADEON_RB3D_COLORPITCH, 0 ) );
83 		OUT_RING( ctx->rb3d_colorpitch );
84 		ADVANCE_RING();
85 	}
86 
87 	if ( dirty & RADEON_UPLOAD_VERTFMT ) {
88 		BEGIN_RING( 2 );
89 		OUT_RING( CP_PACKET0( RADEON_SE_COORD_FMT, 0 ) );
90 		OUT_RING( ctx->se_coord_fmt );
91 		ADVANCE_RING();
92 	}
93 
94 	if ( dirty & RADEON_UPLOAD_LINE ) {
95 		BEGIN_RING( 5 );
96 		OUT_RING( CP_PACKET0( RADEON_RE_LINE_PATTERN, 1 ) );
97 		OUT_RING( ctx->re_line_pattern );
98 		OUT_RING( ctx->re_line_state );
99 		OUT_RING( CP_PACKET0( RADEON_SE_LINE_WIDTH, 0 ) );
100 		OUT_RING( ctx->se_line_width );
101 		ADVANCE_RING();
102 	}
103 
104 	if ( dirty & RADEON_UPLOAD_BUMPMAP ) {
105 		BEGIN_RING( 5 );
106 		OUT_RING( CP_PACKET0( RADEON_PP_LUM_MATRIX, 0 ) );
107 		OUT_RING( ctx->pp_lum_matrix );
108 		OUT_RING( CP_PACKET0( RADEON_PP_ROT_MATRIX_0, 1 ) );
109 		OUT_RING( ctx->pp_rot_matrix_0 );
110 		OUT_RING( ctx->pp_rot_matrix_1 );
111 		ADVANCE_RING();
112 	}
113 
114 	if ( dirty & RADEON_UPLOAD_MASKS ) {
115 		BEGIN_RING( 4 );
116 		OUT_RING( CP_PACKET0( RADEON_RB3D_STENCILREFMASK, 2 ) );
117 		OUT_RING( ctx->rb3d_stencilrefmask );
118 		OUT_RING( ctx->rb3d_ropcntl );
119 		OUT_RING( ctx->rb3d_planemask );
120 		ADVANCE_RING();
121 	}
122 
123 	if ( dirty & RADEON_UPLOAD_VIEWPORT ) {
124 		BEGIN_RING( 7 );
125 		OUT_RING( CP_PACKET0( RADEON_SE_VPORT_XSCALE, 5 ) );
126 		OUT_RING( ctx->se_vport_xscale );
127 		OUT_RING( ctx->se_vport_xoffset );
128 		OUT_RING( ctx->se_vport_yscale );
129 		OUT_RING( ctx->se_vport_yoffset );
130 		OUT_RING( ctx->se_vport_zscale );
131 		OUT_RING( ctx->se_vport_zoffset );
132 		ADVANCE_RING();
133 	}
134 
135 	if ( dirty & RADEON_UPLOAD_SETUP ) {
136 		BEGIN_RING( 4 );
137 		OUT_RING( CP_PACKET0( RADEON_SE_CNTL, 0 ) );
138 		OUT_RING( ctx->se_cntl );
139 		OUT_RING( CP_PACKET0( RADEON_SE_CNTL_STATUS, 0 ) );
140 		OUT_RING( ctx->se_cntl_status );
141 		ADVANCE_RING();
142 	}
143 
144 	if ( dirty & RADEON_UPLOAD_MISC ) {
145 		BEGIN_RING( 2 );
146 		OUT_RING( CP_PACKET0( RADEON_RE_MISC, 0 ) );
147 		OUT_RING( ctx->re_misc );
148 		ADVANCE_RING();
149 	}
150 
151 	if ( dirty & RADEON_UPLOAD_TEX0 ) {
152 		BEGIN_RING( 9 );
153 		OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_0, 5 ) );
154 		OUT_RING( tex[0].pp_txfilter );
155 		OUT_RING( tex[0].pp_txformat );
156 		OUT_RING( tex[0].pp_txoffset );
157 		OUT_RING( tex[0].pp_txcblend );
158 		OUT_RING( tex[0].pp_txablend );
159 		OUT_RING( tex[0].pp_tfactor );
160 		OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_0, 0 ) );
161 		OUT_RING( tex[0].pp_border_color );
162 		ADVANCE_RING();
163 	}
164 
165 	if ( dirty & RADEON_UPLOAD_TEX1 ) {
166 		BEGIN_RING( 9 );
167 		OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_1, 5 ) );
168 		OUT_RING( tex[1].pp_txfilter );
169 		OUT_RING( tex[1].pp_txformat );
170 		OUT_RING( tex[1].pp_txoffset );
171 		OUT_RING( tex[1].pp_txcblend );
172 		OUT_RING( tex[1].pp_txablend );
173 		OUT_RING( tex[1].pp_tfactor );
174 		OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_1, 0 ) );
175 		OUT_RING( tex[1].pp_border_color );
176 		ADVANCE_RING();
177 	}
178 
179 	if ( dirty & RADEON_UPLOAD_TEX2 ) {
180 		BEGIN_RING( 9 );
181 		OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_2, 5 ) );
182 		OUT_RING( tex[2].pp_txfilter );
183 		OUT_RING( tex[2].pp_txformat );
184 		OUT_RING( tex[2].pp_txoffset );
185 		OUT_RING( tex[2].pp_txcblend );
186 		OUT_RING( tex[2].pp_txablend );
187 		OUT_RING( tex[2].pp_tfactor );
188 		OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_2, 0 ) );
189 		OUT_RING( tex[2].pp_border_color );
190 		ADVANCE_RING();
191 	}
192 }
193 
194 /* Emit 1.2 state
195  */
radeon_emit_state2(drm_radeon_private_t * dev_priv,drm_radeon_state_t * state)196 static void radeon_emit_state2( drm_radeon_private_t *dev_priv,
197 				drm_radeon_state_t *state )
198 {
199 	RING_LOCALS;
200 
201 	if (state->dirty & RADEON_UPLOAD_ZBIAS) {
202 		BEGIN_RING( 3 );
203 		OUT_RING( CP_PACKET0( RADEON_SE_ZBIAS_FACTOR, 1 ) );
204 		OUT_RING( state->context2.se_zbias_factor );
205 		OUT_RING( state->context2.se_zbias_constant );
206 		ADVANCE_RING();
207 	}
208 
209 	radeon_emit_state( dev_priv, &state->context,
210 			   state->tex, state->dirty );
211 }
212 
213 /* New (1.3) state mechanism.  3 commands (packet, scalar, vector) in
214  * 1.3 cmdbuffers allow all previous state to be updated as well as
215  * the tcl scalar and vector areas.
216  */
217 static struct {
218 	int start;
219 	int len;
220 	const char *name;
221 } packet[RADEON_MAX_STATE_PACKETS] = {
222 	{ RADEON_PP_MISC,7,"RADEON_PP_MISC" },
223 	{ RADEON_PP_CNTL,3,"RADEON_PP_CNTL" },
224 	{ RADEON_RB3D_COLORPITCH,1,"RADEON_RB3D_COLORPITCH" },
225 	{ RADEON_RE_LINE_PATTERN,2,"RADEON_RE_LINE_PATTERN" },
226 	{ RADEON_SE_LINE_WIDTH,1,"RADEON_SE_LINE_WIDTH" },
227 	{ RADEON_PP_LUM_MATRIX,1,"RADEON_PP_LUM_MATRIX" },
228 	{ RADEON_PP_ROT_MATRIX_0,2,"RADEON_PP_ROT_MATRIX_0" },
229 	{ RADEON_RB3D_STENCILREFMASK,3,"RADEON_RB3D_STENCILREFMASK" },
230 	{ RADEON_SE_VPORT_XSCALE,6,"RADEON_SE_VPORT_XSCALE" },
231 	{ RADEON_SE_CNTL,2,"RADEON_SE_CNTL" },
232 	{ RADEON_SE_CNTL_STATUS,1,"RADEON_SE_CNTL_STATUS" },
233 	{ RADEON_RE_MISC,1,"RADEON_RE_MISC" },
234 	{ RADEON_PP_TXFILTER_0,6,"RADEON_PP_TXFILTER_0" },
235 	{ RADEON_PP_BORDER_COLOR_0,1,"RADEON_PP_BORDER_COLOR_0" },
236 	{ RADEON_PP_TXFILTER_1,6,"RADEON_PP_TXFILTER_1" },
237 	{ RADEON_PP_BORDER_COLOR_1,1,"RADEON_PP_BORDER_COLOR_1" },
238 	{ RADEON_PP_TXFILTER_2,6,"RADEON_PP_TXFILTER_2" },
239 	{ RADEON_PP_BORDER_COLOR_2,1,"RADEON_PP_BORDER_COLOR_2" },
240 	{ RADEON_SE_ZBIAS_FACTOR,2,"RADEON_SE_ZBIAS_FACTOR" },
241 	{ RADEON_SE_TCL_OUTPUT_VTX_FMT,11,"RADEON_SE_TCL_OUTPUT_VTX_FMT" },
242 	{ RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED,17,"RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED" },
243 	{ R200_PP_TXCBLEND_0, 4, "R200_PP_TXCBLEND_0" },
244 	{ R200_PP_TXCBLEND_1, 4, "R200_PP_TXCBLEND_1" },
245 	{ R200_PP_TXCBLEND_2, 4, "R200_PP_TXCBLEND_2" },
246 	{ R200_PP_TXCBLEND_3, 4, "R200_PP_TXCBLEND_3" },
247 	{ R200_PP_TXCBLEND_4, 4, "R200_PP_TXCBLEND_4" },
248 	{ R200_PP_TXCBLEND_5, 4, "R200_PP_TXCBLEND_5" },
249 	{ R200_PP_TXCBLEND_6, 4, "R200_PP_TXCBLEND_6" },
250 	{ R200_PP_TXCBLEND_7, 4, "R200_PP_TXCBLEND_7" },
251 	{ R200_SE_TCL_LIGHT_MODEL_CTL_0, 6, "R200_SE_TCL_LIGHT_MODEL_CTL_0" },
252 	{ R200_PP_TFACTOR_0, 6, "R200_PP_TFACTOR_0" },
253 	{ R200_SE_VTX_FMT_0, 4, "R200_SE_VTX_FMT_0" },
254 	{ R200_SE_VAP_CNTL, 1, "R200_SE_VAP_CNTL" },
255 	{ R200_SE_TCL_MATRIX_SEL_0, 5, "R200_SE_TCL_MATRIX_SEL_0" },
256 	{ R200_SE_TCL_TEX_PROC_CTL_2, 5, "R200_SE_TCL_TEX_PROC_CTL_2" },
257 	{ R200_SE_TCL_UCP_VERT_BLEND_CTL, 1, "R200_SE_TCL_UCP_VERT_BLEND_CTL" },
258 	{ R200_PP_TXFILTER_0, 6, "R200_PP_TXFILTER_0" },
259 	{ R200_PP_TXFILTER_1, 6, "R200_PP_TXFILTER_1" },
260 	{ R200_PP_TXFILTER_2, 6, "R200_PP_TXFILTER_2" },
261 	{ R200_PP_TXFILTER_3, 6, "R200_PP_TXFILTER_3" },
262 	{ R200_PP_TXFILTER_4, 6, "R200_PP_TXFILTER_4" },
263 	{ R200_PP_TXFILTER_5, 6, "R200_PP_TXFILTER_5" },
264 	{ R200_PP_TXOFFSET_0, 1, "R200_PP_TXOFFSET_0" },
265 	{ R200_PP_TXOFFSET_1, 1, "R200_PP_TXOFFSET_1" },
266 	{ R200_PP_TXOFFSET_2, 1, "R200_PP_TXOFFSET_2" },
267 	{ R200_PP_TXOFFSET_3, 1, "R200_PP_TXOFFSET_3" },
268 	{ R200_PP_TXOFFSET_4, 1, "R200_PP_TXOFFSET_4" },
269 	{ R200_PP_TXOFFSET_5, 1, "R200_PP_TXOFFSET_5" },
270 	{ R200_SE_VTE_CNTL, 1, "R200_SE_VTE_CNTL" },
271 	{ R200_SE_TCL_OUTPUT_VTX_COMP_SEL, 1, "R200_SE_TCL_OUTPUT_VTX_COMP_SEL" },
272 	{ R200_PP_TAM_DEBUG3, 1, "R200_PP_TAM_DEBUG3" },
273 	{ R200_PP_CNTL_X, 1, "R200_PP_CNTL_X" },
274 	{ R200_RB3D_DEPTHXY_OFFSET, 1, "R200_RB3D_DEPTHXY_OFFSET" },
275 	{ R200_RE_AUX_SCISSOR_CNTL, 1, "R200_RE_AUX_SCISSOR_CNTL" },
276 	{ R200_RE_SCISSOR_TL_0, 2, "R200_RE_SCISSOR_TL_0" },
277 	{ R200_RE_SCISSOR_TL_1, 2, "R200_RE_SCISSOR_TL_1" },
278 	{ R200_RE_SCISSOR_TL_2, 2, "R200_RE_SCISSOR_TL_2" },
279 	{ R200_SE_VAP_CNTL_STATUS, 1, "R200_SE_VAP_CNTL_STATUS" },
280 	{ R200_SE_VTX_STATE_CNTL, 1, "R200_SE_VTX_STATE_CNTL" },
281 	{ R200_RE_POINTSIZE, 1, "R200_RE_POINTSIZE" },
282 	{ R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0, 4, "R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0" },
283 	{ R200_PP_CUBIC_FACES_0, 1, "R200_PP_CUBIC_FACES_0" }, /* 61 */
284 	{ R200_PP_CUBIC_OFFSET_F1_0, 5, "R200_PP_CUBIC_OFFSET_F1_0" }, /* 62 */
285 	{ R200_PP_CUBIC_FACES_1, 1, "R200_PP_CUBIC_FACES_1" },
286 	{ R200_PP_CUBIC_OFFSET_F1_1, 5, "R200_PP_CUBIC_OFFSET_F1_1" },
287 	{ R200_PP_CUBIC_FACES_2, 1, "R200_PP_CUBIC_FACES_2" },
288 	{ R200_PP_CUBIC_OFFSET_F1_2, 5, "R200_PP_CUBIC_OFFSET_F1_2" },
289 	{ R200_PP_CUBIC_FACES_3, 1, "R200_PP_CUBIC_FACES_3" },
290 	{ R200_PP_CUBIC_OFFSET_F1_3, 5, "R200_PP_CUBIC_OFFSET_F1_3" },
291 	{ R200_PP_CUBIC_FACES_4, 1, "R200_PP_CUBIC_FACES_4" },
292 	{ R200_PP_CUBIC_OFFSET_F1_4, 5, "R200_PP_CUBIC_OFFSET_F1_4" },
293 	{ R200_PP_CUBIC_FACES_5, 1, "R200_PP_CUBIC_FACES_5" },
294 	{ R200_PP_CUBIC_OFFSET_F1_5, 5, "R200_PP_CUBIC_OFFSET_F1_5" },
295 };
296 
297 
298 
299 /* ================================================================
300  * Performance monitoring functions
301  */
302 
radeon_clear_box(drm_radeon_private_t * dev_priv,int x,int y,int w,int h,int r,int g,int b)303 static void radeon_clear_box( drm_radeon_private_t *dev_priv,
304 			      int x, int y, int w, int h,
305 			      int r, int g, int b )
306 {
307 	u32 color;
308 	RING_LOCALS;
309 
310 	x += dev_priv->sarea_priv->boxes[0].x1;
311 	y += dev_priv->sarea_priv->boxes[0].y1;
312 
313 	switch ( dev_priv->color_fmt ) {
314 	case RADEON_COLOR_FORMAT_RGB565:
315 		color = (((r & 0xf8) << 8) |
316 			 ((g & 0xfc) << 3) |
317 			 ((b & 0xf8) >> 3));
318 		break;
319 	case RADEON_COLOR_FORMAT_ARGB8888:
320 	default:
321 		color = (((0xff) << 24) | (r << 16) | (g <<  8) | b);
322 		break;
323 	}
324 
325 	BEGIN_RING( 4 );
326 	RADEON_WAIT_UNTIL_3D_IDLE();
327 	OUT_RING( CP_PACKET0( RADEON_DP_WRITE_MASK, 0 ) );
328 	OUT_RING( 0xffffffff );
329 	ADVANCE_RING();
330 
331 	BEGIN_RING( 6 );
332 
333 	OUT_RING( CP_PACKET3( RADEON_CNTL_PAINT_MULTI, 4 ) );
334 	OUT_RING( RADEON_GMC_DST_PITCH_OFFSET_CNTL |
335 		  RADEON_GMC_BRUSH_SOLID_COLOR |
336 		  (dev_priv->color_fmt << 8) |
337 		  RADEON_GMC_SRC_DATATYPE_COLOR |
338 		  RADEON_ROP3_P |
339 		  RADEON_GMC_CLR_CMP_CNTL_DIS );
340 
341  	if ( dev_priv->page_flipping && dev_priv->current_page == 1 ) {
342 		OUT_RING( dev_priv->front_pitch_offset );
343  	} else {
344 		OUT_RING( dev_priv->back_pitch_offset );
345  	}
346 
347 	OUT_RING( color );
348 
349 	OUT_RING( (x << 16) | y );
350 	OUT_RING( (w << 16) | h );
351 
352 	ADVANCE_RING();
353 }
354 
radeon_cp_performance_boxes(drm_radeon_private_t * dev_priv)355 static void radeon_cp_performance_boxes( drm_radeon_private_t *dev_priv )
356 {
357 	/* Collapse various things into a wait flag -- trying to
358 	 * guess if userspase slept -- better just to have them tell us.
359 	 */
360 	if (dev_priv->stats.last_frame_reads > 1 ||
361 	    dev_priv->stats.last_clear_reads > dev_priv->stats.clears) {
362 		dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
363 	}
364 
365 	if (dev_priv->stats.freelist_loops) {
366 		dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
367 	}
368 
369 	/* Purple box for page flipping
370 	 */
371 	if ( dev_priv->stats.boxes & RADEON_BOX_FLIP )
372 		radeon_clear_box( dev_priv, 4, 4, 8, 8, 255, 0, 255 );
373 
374 	/* Red box if we have to wait for idle at any point
375 	 */
376 	if ( dev_priv->stats.boxes & RADEON_BOX_WAIT_IDLE )
377 		radeon_clear_box( dev_priv, 16, 4, 8, 8, 255, 0, 0 );
378 
379 	/* Blue box: lost context?
380 	 */
381 
382 	/* Yellow box for texture swaps
383 	 */
384 	if ( dev_priv->stats.boxes & RADEON_BOX_TEXTURE_LOAD )
385 		radeon_clear_box( dev_priv, 40, 4, 8, 8, 255, 255, 0 );
386 
387 	/* Green box if hardware never idles (as far as we can tell)
388 	 */
389 	if ( !(dev_priv->stats.boxes & RADEON_BOX_DMA_IDLE) )
390 		radeon_clear_box( dev_priv, 64, 4, 8, 8, 0, 255, 0 );
391 
392 
393 	/* Draw bars indicating number of buffers allocated
394 	 * (not a great measure, easily confused)
395 	 */
396 	if (dev_priv->stats.requested_bufs) {
397 		if (dev_priv->stats.requested_bufs > 100)
398 			dev_priv->stats.requested_bufs = 100;
399 
400 		radeon_clear_box( dev_priv, 4, 16,
401 				  dev_priv->stats.requested_bufs, 4,
402 				  196, 128, 128 );
403 	}
404 
405 	memset( &dev_priv->stats, 0, sizeof(dev_priv->stats) );
406 
407 }
408 /* ================================================================
409  * CP command dispatch functions
410  */
411 
radeon_cp_dispatch_clear(drm_device_t * dev,drm_radeon_clear_t * clear,drm_radeon_clear_rect_t * depth_boxes)412 static void radeon_cp_dispatch_clear( drm_device_t *dev,
413 				      drm_radeon_clear_t *clear,
414 				      drm_radeon_clear_rect_t *depth_boxes )
415 {
416 	drm_radeon_private_t *dev_priv = dev->dev_private;
417 	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
418 	drm_radeon_depth_clear_t *depth_clear = &dev_priv->depth_clear;
419 	int nbox = sarea_priv->nbox;
420 	drm_clip_rect_t *pbox = sarea_priv->boxes;
421 	unsigned int flags = clear->flags;
422 	u32 rb3d_cntl = 0, rb3d_stencilrefmask= 0;
423 	int i;
424 	RING_LOCALS;
425 	DRM_DEBUG( "flags = 0x%x\n", flags );
426 
427 	dev_priv->stats.clears++;
428 
429 	if ( dev_priv->page_flipping && dev_priv->current_page == 1 ) {
430 		unsigned int tmp = flags;
431 
432 		flags &= ~(RADEON_FRONT | RADEON_BACK);
433 		if ( tmp & RADEON_FRONT ) flags |= RADEON_BACK;
434 		if ( tmp & RADEON_BACK )  flags |= RADEON_FRONT;
435 	}
436 
437 	if ( flags & (RADEON_FRONT | RADEON_BACK) ) {
438 
439 		BEGIN_RING( 4 );
440 
441 		/* Ensure the 3D stream is idle before doing a
442 		 * 2D fill to clear the front or back buffer.
443 		 */
444 		RADEON_WAIT_UNTIL_3D_IDLE();
445 
446 		OUT_RING( CP_PACKET0( RADEON_DP_WRITE_MASK, 0 ) );
447 		OUT_RING( clear->color_mask );
448 
449 		ADVANCE_RING();
450 
451 		/* Make sure we restore the 3D state next time.
452 		 */
453 		dev_priv->sarea_priv->ctx_owner = 0;
454 
455 		for ( i = 0 ; i < nbox ; i++ ) {
456 			int x = pbox[i].x1;
457 			int y = pbox[i].y1;
458 			int w = pbox[i].x2 - x;
459 			int h = pbox[i].y2 - y;
460 
461 			DRM_DEBUG( "dispatch clear %d,%d-%d,%d flags 0x%x\n",
462 				   x, y, w, h, flags );
463 
464 			if ( flags & RADEON_FRONT ) {
465 				BEGIN_RING( 6 );
466 
467 				OUT_RING( CP_PACKET3( RADEON_CNTL_PAINT_MULTI, 4 ) );
468 				OUT_RING( RADEON_GMC_DST_PITCH_OFFSET_CNTL |
469 					  RADEON_GMC_BRUSH_SOLID_COLOR |
470 					  (dev_priv->color_fmt << 8) |
471 					  RADEON_GMC_SRC_DATATYPE_COLOR |
472 					  RADEON_ROP3_P |
473 					  RADEON_GMC_CLR_CMP_CNTL_DIS );
474 
475 				OUT_RING( dev_priv->front_pitch_offset );
476 				OUT_RING( clear->clear_color );
477 
478 				OUT_RING( (x << 16) | y );
479 				OUT_RING( (w << 16) | h );
480 
481 				ADVANCE_RING();
482 			}
483 
484 			if ( flags & RADEON_BACK ) {
485 				BEGIN_RING( 6 );
486 
487 				OUT_RING( CP_PACKET3( RADEON_CNTL_PAINT_MULTI, 4 ) );
488 				OUT_RING( RADEON_GMC_DST_PITCH_OFFSET_CNTL |
489 					  RADEON_GMC_BRUSH_SOLID_COLOR |
490 					  (dev_priv->color_fmt << 8) |
491 					  RADEON_GMC_SRC_DATATYPE_COLOR |
492 					  RADEON_ROP3_P |
493 					  RADEON_GMC_CLR_CMP_CNTL_DIS );
494 
495 				OUT_RING( dev_priv->back_pitch_offset );
496 				OUT_RING( clear->clear_color );
497 
498 				OUT_RING( (x << 16) | y );
499 				OUT_RING( (w << 16) | h );
500 
501 				ADVANCE_RING();
502 			}
503 		}
504 	}
505 
506 	/* We have to clear the depth and/or stencil buffers by
507 	 * rendering a quad into just those buffers.  Thus, we have to
508 	 * make sure the 3D engine is configured correctly.
509 	 */
510 	if ( dev_priv->is_r200 &&
511 	     (flags & (RADEON_DEPTH | RADEON_STENCIL)) ) {
512 
513 		int tempPP_CNTL;
514 		int tempRE_CNTL;
515 		int tempRB3D_CNTL;
516 		int tempRB3D_ZSTENCILCNTL;
517 		int tempRB3D_STENCILREFMASK;
518 		int tempRB3D_PLANEMASK;
519 		int tempSE_CNTL;
520 		int tempSE_VTE_CNTL;
521 		int tempSE_VTX_FMT_0;
522 		int tempSE_VTX_FMT_1;
523 		int tempSE_VAP_CNTL;
524 		int tempRE_AUX_SCISSOR_CNTL;
525 
526 		tempPP_CNTL = 0;
527 		tempRE_CNTL = 0;
528 
529 		tempRB3D_CNTL = depth_clear->rb3d_cntl;
530 		tempRB3D_CNTL &= ~(1<<15); /* unset radeon magic flag */
531 
532 		tempRB3D_ZSTENCILCNTL = depth_clear->rb3d_zstencilcntl;
533 		tempRB3D_STENCILREFMASK = 0x0;
534 
535 		tempSE_CNTL = depth_clear->se_cntl;
536 
537 
538 
539 		/* Disable TCL */
540 
541 		tempSE_VAP_CNTL = (/* SE_VAP_CNTL__FORCE_W_TO_ONE_MASK |  */
542 				   (0x9 << SE_VAP_CNTL__VF_MAX_VTX_NUM__SHIFT));
543 
544 		tempRB3D_PLANEMASK = 0x0;
545 
546 		tempRE_AUX_SCISSOR_CNTL = 0x0;
547 
548 		tempSE_VTE_CNTL =
549 			SE_VTE_CNTL__VTX_XY_FMT_MASK |
550 			SE_VTE_CNTL__VTX_Z_FMT_MASK;
551 
552 		/* Vertex format (X, Y, Z, W)*/
553 		tempSE_VTX_FMT_0 =
554 			SE_VTX_FMT_0__VTX_Z0_PRESENT_MASK |
555 			SE_VTX_FMT_0__VTX_W0_PRESENT_MASK;
556 		tempSE_VTX_FMT_1 = 0x0;
557 
558 
559 		/*
560 		 * Depth buffer specific enables
561 		 */
562 		if (flags & RADEON_DEPTH) {
563 			/* Enable depth buffer */
564 			tempRB3D_CNTL |= RADEON_Z_ENABLE;
565 		} else {
566 			/* Disable depth buffer */
567 			tempRB3D_CNTL &= ~RADEON_Z_ENABLE;
568 		}
569 
570 		/*
571 		 * Stencil buffer specific enables
572 		 */
573 		if ( flags & RADEON_STENCIL ) {
574 			tempRB3D_CNTL |=  RADEON_STENCIL_ENABLE;
575 			tempRB3D_STENCILREFMASK = clear->depth_mask;
576 		} else {
577 			tempRB3D_CNTL &= ~RADEON_STENCIL_ENABLE;
578 			tempRB3D_STENCILREFMASK = 0x00000000;
579 		}
580 
581 		BEGIN_RING( 26 );
582 		RADEON_WAIT_UNTIL_2D_IDLE();
583 
584 		OUT_RING_REG( RADEON_PP_CNTL, tempPP_CNTL );
585 		OUT_RING_REG( R200_RE_CNTL, tempRE_CNTL );
586 		OUT_RING_REG( RADEON_RB3D_CNTL, tempRB3D_CNTL );
587 		OUT_RING_REG( RADEON_RB3D_ZSTENCILCNTL,
588 			      tempRB3D_ZSTENCILCNTL );
589 		OUT_RING_REG( RADEON_RB3D_STENCILREFMASK,
590 			      tempRB3D_STENCILREFMASK );
591 		OUT_RING_REG( RADEON_RB3D_PLANEMASK, tempRB3D_PLANEMASK );
592 		OUT_RING_REG( RADEON_SE_CNTL, tempSE_CNTL );
593 		OUT_RING_REG( R200_SE_VTE_CNTL, tempSE_VTE_CNTL );
594 		OUT_RING_REG( R200_SE_VTX_FMT_0, tempSE_VTX_FMT_0 );
595 		OUT_RING_REG( R200_SE_VTX_FMT_1, tempSE_VTX_FMT_1 );
596 		OUT_RING_REG( R200_SE_VAP_CNTL, tempSE_VAP_CNTL );
597 		OUT_RING_REG( R200_RE_AUX_SCISSOR_CNTL,
598 			      tempRE_AUX_SCISSOR_CNTL );
599 		ADVANCE_RING();
600 
601 		/* Make sure we restore the 3D state next time.
602 		 */
603 		dev_priv->sarea_priv->ctx_owner = 0;
604 
605 		for ( i = 0 ; i < nbox ; i++ ) {
606 
607 			/* Funny that this should be required --
608 			 *  sets top-left?
609 			 */
610 			radeon_emit_clip_rect( dev_priv,
611 					       &sarea_priv->boxes[i] );
612 
613 			BEGIN_RING( 14 );
614 			OUT_RING( CP_PACKET3( R200_3D_DRAW_IMMD_2, 12 ) );
615 			OUT_RING( (RADEON_PRIM_TYPE_RECT_LIST |
616 				   RADEON_PRIM_WALK_RING |
617 				   (3 << RADEON_NUM_VERTICES_SHIFT)) );
618 			OUT_RING( depth_boxes[i].ui[CLEAR_X1] );
619 			OUT_RING( depth_boxes[i].ui[CLEAR_Y1] );
620 			OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
621 			OUT_RING( 0x3f800000 );
622 			OUT_RING( depth_boxes[i].ui[CLEAR_X1] );
623 			OUT_RING( depth_boxes[i].ui[CLEAR_Y2] );
624 			OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
625 			OUT_RING( 0x3f800000 );
626 			OUT_RING( depth_boxes[i].ui[CLEAR_X2] );
627 			OUT_RING( depth_boxes[i].ui[CLEAR_Y2] );
628 			OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
629 			OUT_RING( 0x3f800000 );
630 			ADVANCE_RING();
631 		}
632 	}
633 	else if ( (flags & (RADEON_DEPTH | RADEON_STENCIL)) ) {
634 
635 		rb3d_cntl = depth_clear->rb3d_cntl;
636 
637 		if ( flags & RADEON_DEPTH ) {
638 			rb3d_cntl |=  RADEON_Z_ENABLE;
639 		} else {
640 			rb3d_cntl &= ~RADEON_Z_ENABLE;
641 		}
642 
643 		if ( flags & RADEON_STENCIL ) {
644 			rb3d_cntl |=  RADEON_STENCIL_ENABLE;
645 			rb3d_stencilrefmask = clear->depth_mask; /* misnamed field */
646 		} else {
647 			rb3d_cntl &= ~RADEON_STENCIL_ENABLE;
648 			rb3d_stencilrefmask = 0x00000000;
649 		}
650 
651 		BEGIN_RING( 13 );
652 		RADEON_WAIT_UNTIL_2D_IDLE();
653 
654 		OUT_RING( CP_PACKET0( RADEON_PP_CNTL, 1 ) );
655 		OUT_RING( 0x00000000 );
656 		OUT_RING( rb3d_cntl );
657 
658 		OUT_RING_REG( RADEON_RB3D_ZSTENCILCNTL,
659 			      depth_clear->rb3d_zstencilcntl );
660 		OUT_RING_REG( RADEON_RB3D_STENCILREFMASK,
661 			      rb3d_stencilrefmask );
662 		OUT_RING_REG( RADEON_RB3D_PLANEMASK,
663 			      0x00000000 );
664 		OUT_RING_REG( RADEON_SE_CNTL,
665 			      depth_clear->se_cntl );
666 		ADVANCE_RING();
667 
668 		/* Make sure we restore the 3D state next time.
669 		 */
670 		dev_priv->sarea_priv->ctx_owner = 0;
671 
672 		for ( i = 0 ; i < nbox ; i++ ) {
673 
674 			/* Funny that this should be required --
675 			 *  sets top-left?
676 			 */
677 			radeon_emit_clip_rect( dev_priv,
678 					       &sarea_priv->boxes[i] );
679 
680 			BEGIN_RING( 15 );
681 
682 			OUT_RING( CP_PACKET3( RADEON_3D_DRAW_IMMD, 13 ) );
683 			OUT_RING( RADEON_VTX_Z_PRESENT |
684 				  RADEON_VTX_PKCOLOR_PRESENT);
685 			OUT_RING( (RADEON_PRIM_TYPE_RECT_LIST |
686 				   RADEON_PRIM_WALK_RING |
687 				   RADEON_MAOS_ENABLE |
688 				   RADEON_VTX_FMT_RADEON_MODE |
689 				   (3 << RADEON_NUM_VERTICES_SHIFT)) );
690 
691 
692 			OUT_RING( depth_boxes[i].ui[CLEAR_X1] );
693 			OUT_RING( depth_boxes[i].ui[CLEAR_Y1] );
694 			OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
695 			OUT_RING( 0x0 );
696 
697 			OUT_RING( depth_boxes[i].ui[CLEAR_X1] );
698 			OUT_RING( depth_boxes[i].ui[CLEAR_Y2] );
699 			OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
700 			OUT_RING( 0x0 );
701 
702 			OUT_RING( depth_boxes[i].ui[CLEAR_X2] );
703 			OUT_RING( depth_boxes[i].ui[CLEAR_Y2] );
704 			OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
705 			OUT_RING( 0x0 );
706 
707 			ADVANCE_RING();
708 		}
709 	}
710 
711 	/* Increment the clear counter.  The client-side 3D driver must
712 	 * wait on this value before performing the clear ioctl.  We
713 	 * need this because the card's so damned fast...
714 	 */
715 	dev_priv->sarea_priv->last_clear++;
716 
717 	BEGIN_RING( 4 );
718 
719 	RADEON_CLEAR_AGE( dev_priv->sarea_priv->last_clear );
720 	RADEON_WAIT_UNTIL_IDLE();
721 
722 	ADVANCE_RING();
723 }
724 
radeon_cp_dispatch_swap(drm_device_t * dev)725 static void radeon_cp_dispatch_swap( drm_device_t *dev )
726 {
727 	drm_radeon_private_t *dev_priv = dev->dev_private;
728 	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
729 	int nbox = sarea_priv->nbox;
730 	drm_clip_rect_t *pbox = sarea_priv->boxes;
731 	int i;
732 	RING_LOCALS;
733 	DRM_DEBUG( "\n" );
734 
735 	/* Do some trivial performance monitoring...
736 	 */
737 	if (dev_priv->do_boxes)
738 		radeon_cp_performance_boxes( dev_priv );
739 
740 
741 	/* Wait for the 3D stream to idle before dispatching the bitblt.
742 	 * This will prevent data corruption between the two streams.
743 	 */
744 	BEGIN_RING( 2 );
745 
746 	RADEON_WAIT_UNTIL_3D_IDLE();
747 
748 	ADVANCE_RING();
749 
750 	for ( i = 0 ; i < nbox ; i++ ) {
751 		int x = pbox[i].x1;
752 		int y = pbox[i].y1;
753 		int w = pbox[i].x2 - x;
754 		int h = pbox[i].y2 - y;
755 
756 		DRM_DEBUG( "dispatch swap %d,%d-%d,%d\n",
757 			   x, y, w, h );
758 
759 		BEGIN_RING( 7 );
760 
761 		OUT_RING( CP_PACKET3( RADEON_CNTL_BITBLT_MULTI, 5 ) );
762 		OUT_RING( RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
763 			  RADEON_GMC_DST_PITCH_OFFSET_CNTL |
764 			  RADEON_GMC_BRUSH_NONE |
765 			  (dev_priv->color_fmt << 8) |
766 			  RADEON_GMC_SRC_DATATYPE_COLOR |
767 			  RADEON_ROP3_S |
768 			  RADEON_DP_SRC_SOURCE_MEMORY |
769 			  RADEON_GMC_CLR_CMP_CNTL_DIS |
770 			  RADEON_GMC_WR_MSK_DIS );
771 
772 		/* Make this work even if front & back are flipped:
773 		 */
774 		if (dev_priv->current_page == 0) {
775 			OUT_RING( dev_priv->back_pitch_offset );
776 			OUT_RING( dev_priv->front_pitch_offset );
777 		}
778 		else {
779 			OUT_RING( dev_priv->front_pitch_offset );
780 			OUT_RING( dev_priv->back_pitch_offset );
781 		}
782 
783 		OUT_RING( (x << 16) | y );
784 		OUT_RING( (x << 16) | y );
785 		OUT_RING( (w << 16) | h );
786 
787 		ADVANCE_RING();
788 	}
789 
790 	/* Increment the frame counter.  The client-side 3D driver must
791 	 * throttle the framerate by waiting for this value before
792 	 * performing the swapbuffer ioctl.
793 	 */
794 	dev_priv->sarea_priv->last_frame++;
795 
796 	BEGIN_RING( 4 );
797 
798 	RADEON_FRAME_AGE( dev_priv->sarea_priv->last_frame );
799 	RADEON_WAIT_UNTIL_2D_IDLE();
800 
801 	ADVANCE_RING();
802 }
803 
radeon_cp_dispatch_flip(drm_device_t * dev)804 static void radeon_cp_dispatch_flip( drm_device_t *dev )
805 {
806 	drm_radeon_private_t *dev_priv = dev->dev_private;
807 	drm_sarea_t *sarea = (drm_sarea_t *)dev_priv->sarea->handle;
808 	int offset = (dev_priv->current_page == 1)
809 		   ? dev_priv->front_offset : dev_priv->back_offset;
810 	RING_LOCALS;
811 	DRM_DEBUG( "%s: page=%d pfCurrentPage=%d\n",
812 		__FUNCTION__,
813 		dev_priv->current_page,
814 		dev_priv->sarea_priv->pfCurrentPage);
815 
816 	/* Do some trivial performance monitoring...
817 	 */
818 	if (dev_priv->do_boxes) {
819 		dev_priv->stats.boxes |= RADEON_BOX_FLIP;
820 		radeon_cp_performance_boxes( dev_priv );
821 	}
822 
823 	/* Update the frame offsets for both CRTCs
824 	 */
825 	BEGIN_RING( 6 );
826 
827 	RADEON_WAIT_UNTIL_3D_IDLE();
828 	OUT_RING_REG( RADEON_CRTC_OFFSET, ( ( sarea->frame.y * dev_priv->front_pitch
829 					      + sarea->frame.x
830 					      * ( dev_priv->color_fmt - 2 ) ) & ~7 )
831 					  + offset );
832 	OUT_RING_REG( RADEON_CRTC2_OFFSET, dev_priv->sarea_priv->crtc2_base
833 					   + offset );
834 
835 	ADVANCE_RING();
836 
837 	/* Increment the frame counter.  The client-side 3D driver must
838 	 * throttle the framerate by waiting for this value before
839 	 * performing the swapbuffer ioctl.
840 	 */
841 	dev_priv->sarea_priv->last_frame++;
842 	dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page =
843 					      1 - dev_priv->current_page;
844 
845 	BEGIN_RING( 2 );
846 
847 	RADEON_FRAME_AGE( dev_priv->sarea_priv->last_frame );
848 
849 	ADVANCE_RING();
850 }
851 
bad_prim_vertex_nr(int primitive,int nr)852 static int bad_prim_vertex_nr( int primitive, int nr )
853 {
854 	switch (primitive & RADEON_PRIM_TYPE_MASK) {
855 	case RADEON_PRIM_TYPE_NONE:
856 	case RADEON_PRIM_TYPE_POINT:
857 		return nr < 1;
858 	case RADEON_PRIM_TYPE_LINE:
859 		return (nr & 1) || nr == 0;
860 	case RADEON_PRIM_TYPE_LINE_STRIP:
861 		return nr < 2;
862 	case RADEON_PRIM_TYPE_TRI_LIST:
863 	case RADEON_PRIM_TYPE_3VRT_POINT_LIST:
864 	case RADEON_PRIM_TYPE_3VRT_LINE_LIST:
865 	case RADEON_PRIM_TYPE_RECT_LIST:
866 		return nr % 3 || nr == 0;
867 	case RADEON_PRIM_TYPE_TRI_FAN:
868 	case RADEON_PRIM_TYPE_TRI_STRIP:
869 		return nr < 3;
870 	default:
871 		return 1;
872 	}
873 }
874 
875 
876 
877 typedef struct {
878 	unsigned int start;
879 	unsigned int finish;
880 	unsigned int prim;
881 	unsigned int numverts;
882 	unsigned int offset;
883         unsigned int vc_format;
884 } drm_radeon_tcl_prim_t;
885 
radeon_cp_dispatch_vertex(drm_device_t * dev,drm_buf_t * buf,drm_radeon_tcl_prim_t * prim,drm_clip_rect_t * boxes,int nbox)886 static void radeon_cp_dispatch_vertex( drm_device_t *dev,
887 				       drm_buf_t *buf,
888 				       drm_radeon_tcl_prim_t *prim,
889 				       drm_clip_rect_t *boxes,
890 				       int nbox )
891 
892 {
893 	drm_radeon_private_t *dev_priv = dev->dev_private;
894 	drm_clip_rect_t box;
895 	int offset = dev_priv->agp_buffers_offset + buf->offset + prim->start;
896 	int numverts = (int)prim->numverts;
897 	int i = 0;
898 	RING_LOCALS;
899 
900 	DRM_DEBUG("hwprim 0x%x vfmt 0x%x %d..%d %d verts\n",
901 		  prim->prim,
902 		  prim->vc_format,
903 		  prim->start,
904 		  prim->finish,
905 		  prim->numverts);
906 
907 	if (bad_prim_vertex_nr( prim->prim, prim->numverts )) {
908 		DRM_ERROR( "bad prim %x numverts %d\n",
909 			   prim->prim, prim->numverts );
910 		return;
911 	}
912 
913 	do {
914 		/* Emit the next cliprect */
915 		if ( i < nbox ) {
916 			if (__copy_from_user( &box, &boxes[i], sizeof(box) ))
917 				return;
918 
919 			radeon_emit_clip_rect( dev_priv, &box );
920 		}
921 
922 		/* Emit the vertex buffer rendering commands */
923 		BEGIN_RING( 5 );
924 
925 		OUT_RING( CP_PACKET3( RADEON_3D_RNDR_GEN_INDX_PRIM, 3 ) );
926 		OUT_RING( offset );
927 		OUT_RING( numverts );
928 		OUT_RING( prim->vc_format );
929 		OUT_RING( prim->prim | RADEON_PRIM_WALK_LIST |
930 			  RADEON_COLOR_ORDER_RGBA |
931 			  RADEON_VTX_FMT_RADEON_MODE |
932 			  (numverts << RADEON_NUM_VERTICES_SHIFT) );
933 
934 		ADVANCE_RING();
935 
936 		i++;
937 	} while ( i < nbox );
938 }
939 
940 
941 
radeon_cp_discard_buffer(drm_device_t * dev,drm_buf_t * buf)942 static void radeon_cp_discard_buffer( drm_device_t *dev, drm_buf_t *buf )
943 {
944 	drm_radeon_private_t *dev_priv = dev->dev_private;
945 	drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
946 	RING_LOCALS;
947 
948 	buf_priv->age = ++dev_priv->sarea_priv->last_dispatch;
949 
950 	/* Emit the vertex buffer age */
951 	BEGIN_RING( 2 );
952 	RADEON_DISPATCH_AGE( buf_priv->age );
953 	ADVANCE_RING();
954 
955 	buf->pending = 1;
956 	buf->used = 0;
957 }
958 
radeon_cp_dispatch_indirect(drm_device_t * dev,drm_buf_t * buf,int start,int end)959 static void radeon_cp_dispatch_indirect( drm_device_t *dev,
960 					 drm_buf_t *buf,
961 					 int start, int end )
962 {
963 	drm_radeon_private_t *dev_priv = dev->dev_private;
964 	RING_LOCALS;
965 	DRM_DEBUG( "indirect: buf=%d s=0x%x e=0x%x\n",
966 		   buf->idx, start, end );
967 
968 	if ( start != end ) {
969 		int offset = (dev_priv->agp_buffers_offset
970 			      + buf->offset + start);
971 		int dwords = (end - start + 3) / sizeof(u32);
972 
973 		/* Indirect buffer data must be an even number of
974 		 * dwords, so if we've been given an odd number we must
975 		 * pad the data with a Type-2 CP packet.
976 		 */
977 		if ( dwords & 1 ) {
978 			u32 *data = (u32 *)
979 				((char *)dev_priv->buffers->handle
980 				 + buf->offset + start);
981 			data[dwords++] = RADEON_CP_PACKET2;
982 		}
983 
984 		/* Fire off the indirect buffer */
985 		BEGIN_RING( 3 );
986 
987 		OUT_RING( CP_PACKET0( RADEON_CP_IB_BASE, 1 ) );
988 		OUT_RING( offset );
989 		OUT_RING( dwords );
990 
991 		ADVANCE_RING();
992 	}
993 }
994 
995 
radeon_cp_dispatch_indices(drm_device_t * dev,drm_buf_t * elt_buf,drm_radeon_tcl_prim_t * prim,drm_clip_rect_t * boxes,int nbox)996 static void radeon_cp_dispatch_indices( drm_device_t *dev,
997 					drm_buf_t *elt_buf,
998 					drm_radeon_tcl_prim_t *prim,
999 					drm_clip_rect_t *boxes,
1000 					int nbox )
1001 {
1002 	drm_radeon_private_t *dev_priv = dev->dev_private;
1003 	drm_clip_rect_t box;
1004 	int offset = dev_priv->agp_buffers_offset + prim->offset;
1005 	u32 *data;
1006 	int dwords;
1007 	int i = 0;
1008 	int start = prim->start + RADEON_INDEX_PRIM_OFFSET;
1009 	int count = (prim->finish - start) / sizeof(u16);
1010 
1011 	DRM_DEBUG("hwprim 0x%x vfmt 0x%x %d..%d offset: %x nr %d\n",
1012 		  prim->prim,
1013 		  prim->vc_format,
1014 		  prim->start,
1015 		  prim->finish,
1016 		  prim->offset,
1017 		  prim->numverts);
1018 
1019 	if (bad_prim_vertex_nr( prim->prim, count )) {
1020 		DRM_ERROR( "bad prim %x count %d\n",
1021 			   prim->prim, count );
1022 		return;
1023 	}
1024 
1025 
1026 	if ( start >= prim->finish ||
1027 	     (prim->start & 0x7) ) {
1028 		DRM_ERROR( "buffer prim %d\n", prim->prim );
1029 		return;
1030 	}
1031 
1032 	dwords = (prim->finish - prim->start + 3) / sizeof(u32);
1033 
1034 	data = (u32 *)((char *)dev_priv->buffers->handle +
1035 		       elt_buf->offset + prim->start);
1036 
1037 	data[0] = CP_PACKET3( RADEON_3D_RNDR_GEN_INDX_PRIM, dwords-2 );
1038 	data[1] = offset;
1039 	data[2] = prim->numverts;
1040 	data[3] = prim->vc_format;
1041 	data[4] = (prim->prim |
1042 		   RADEON_PRIM_WALK_IND |
1043 		   RADEON_COLOR_ORDER_RGBA |
1044 		   RADEON_VTX_FMT_RADEON_MODE |
1045 		   (count << RADEON_NUM_VERTICES_SHIFT) );
1046 
1047 	do {
1048 		if ( i < nbox ) {
1049 			if (__copy_from_user( &box, &boxes[i], sizeof(box) ))
1050 				return;
1051 
1052 			radeon_emit_clip_rect( dev_priv, &box );
1053 		}
1054 
1055 		radeon_cp_dispatch_indirect( dev, elt_buf,
1056 					     prim->start,
1057 					     prim->finish );
1058 
1059 		i++;
1060 	} while ( i < nbox );
1061 
1062 }
1063 
1064 #define RADEON_MAX_TEXTURE_SIZE (RADEON_BUFFER_SIZE - 8 * sizeof(u32))
1065 
radeon_cp_dispatch_texture(drm_device_t * dev,drm_radeon_texture_t * tex,drm_radeon_tex_image_t * image)1066 static int radeon_cp_dispatch_texture( drm_device_t *dev,
1067 				       drm_radeon_texture_t *tex,
1068 				       drm_radeon_tex_image_t *image )
1069 {
1070 	drm_radeon_private_t *dev_priv = dev->dev_private;
1071 	drm_buf_t *buf;
1072 	u32 format;
1073 	u32 *buffer;
1074 	const u8 *data;
1075 	int size, dwords, tex_width, blit_width;
1076 	u32 height;
1077 	int i;
1078 	RING_LOCALS;
1079 
1080 	dev_priv->stats.boxes |= RADEON_BOX_TEXTURE_LOAD;
1081 
1082 	/* Flush the pixel cache.  This ensures no pixel data gets mixed
1083 	 * up with the texture data from the host data blit, otherwise
1084 	 * part of the texture image may be corrupted.
1085 	 */
1086 	BEGIN_RING( 4 );
1087 	RADEON_FLUSH_CACHE();
1088 	RADEON_WAIT_UNTIL_IDLE();
1089 	ADVANCE_RING();
1090 
1091 #ifdef __BIG_ENDIAN
1092 	/* The Mesa texture functions provide the data in little endian as the
1093 	 * chip wants it, but we need to compensate for the fact that the CP
1094 	 * ring gets byte-swapped
1095 	 */
1096 	BEGIN_RING( 2 );
1097 	OUT_RING_REG( RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_32BIT );
1098 	ADVANCE_RING();
1099 #endif
1100 
1101 
1102 	/* The compiler won't optimize away a division by a variable,
1103 	 * even if the only legal values are powers of two.  Thus, we'll
1104 	 * use a shift instead.
1105 	 */
1106 	switch ( tex->format ) {
1107 	case RADEON_TXFORMAT_ARGB8888:
1108 	case RADEON_TXFORMAT_RGBA8888:
1109 		format = RADEON_COLOR_FORMAT_ARGB8888;
1110 		tex_width = tex->width * 4;
1111 		blit_width = image->width * 4;
1112 		break;
1113 	case RADEON_TXFORMAT_AI88:
1114 	case RADEON_TXFORMAT_ARGB1555:
1115 	case RADEON_TXFORMAT_RGB565:
1116 	case RADEON_TXFORMAT_ARGB4444:
1117 	case RADEON_TXFORMAT_VYUY422:
1118 	case RADEON_TXFORMAT_YVYU422:
1119 		format = RADEON_COLOR_FORMAT_RGB565;
1120 		tex_width = tex->width * 2;
1121 		blit_width = image->width * 2;
1122 		break;
1123 	case RADEON_TXFORMAT_I8:
1124 	case RADEON_TXFORMAT_RGB332:
1125 		format = RADEON_COLOR_FORMAT_CI8;
1126 		tex_width = tex->width * 1;
1127 		blit_width = image->width * 1;
1128 		break;
1129 	default:
1130 		DRM_ERROR( "invalid texture format %d\n", tex->format );
1131 		return -EINVAL;
1132 	}
1133 
1134 	DRM_DEBUG("tex=%dx%d blit=%d\n", tex_width, tex->height, blit_width );
1135 
1136 	do {
1137 		DRM_DEBUG( "tex: ofs=0x%x p=%d f=%d x=%hd y=%hd w=%hd h=%hd\n",
1138 			   tex->offset >> 10, tex->pitch, tex->format,
1139 			   image->x, image->y, image->width, image->height );
1140 
1141 		/* Make a copy of some parameters in case we have to
1142 		 * update them for a multi-pass texture blit.
1143 	 */
1144 	height = image->height;
1145 	data = (const u8 *)image->data;
1146 
1147 	size = height * blit_width;
1148 
1149 	if ( size > RADEON_MAX_TEXTURE_SIZE ) {
1150 		height = RADEON_MAX_TEXTURE_SIZE / blit_width;
1151 		size = height * blit_width;
1152 	} else if ( size < 4 && size > 0 ) {
1153 		size = 4;
1154 		} else if ( size == 0 ) {
1155 			return 0;
1156 		}
1157 
1158 		buf = radeon_freelist_get( dev );
1159 		if ( 0 && !buf ) {
1160 			radeon_do_cp_idle( dev_priv );
1161 			buf = radeon_freelist_get( dev );
1162 		}
1163 		if ( !buf ) {
1164 			DRM_DEBUG("radeon_cp_dispatch_texture: EAGAIN\n");
1165 			copy_to_user( tex->image, image, sizeof(*image) );
1166 			return -EAGAIN;
1167 	}
1168 
1169 
1170 	/* Dispatch the indirect buffer.
1171 	 */
1172 		buffer = (u32*)((char*)dev_priv->buffers->handle + buf->offset);
1173 		dwords = size / 4;
1174 	buffer[0] = CP_PACKET3( RADEON_CNTL_HOSTDATA_BLT, dwords + 6 );
1175 	buffer[1] = (RADEON_GMC_DST_PITCH_OFFSET_CNTL |
1176 		     RADEON_GMC_BRUSH_NONE |
1177 		     (format << 8) |
1178 		     RADEON_GMC_SRC_DATATYPE_COLOR |
1179 		     RADEON_ROP3_S |
1180 		     RADEON_DP_SRC_SOURCE_HOST_DATA |
1181 		     RADEON_GMC_CLR_CMP_CNTL_DIS |
1182 		     RADEON_GMC_WR_MSK_DIS);
1183 
1184 	buffer[2] = (tex->pitch << 22) | (tex->offset >> 10);
1185 	buffer[3] = 0xffffffff;
1186 	buffer[4] = 0xffffffff;
1187 	buffer[5] = (image->y << 16) | image->x;
1188 	buffer[6] = (height << 16) | image->width;
1189 	buffer[7] = dwords;
1190 
1191 	buffer += 8;
1192 
1193 	if ( tex_width >= 32 ) {
1194 		/* Texture image width is larger than the minimum, so we
1195 		 * can upload it directly.
1196 		 */
1197 		if ( copy_from_user( buffer, data, dwords * sizeof(u32) ) ) {
1198 			DRM_ERROR( "EFAULT on data, %d dwords\n", dwords );
1199 			return -EFAULT;
1200 		}
1201 	} else {
1202 		/* Texture image width is less than the minimum, so we
1203 		 * need to pad out each image scanline to the minimum
1204 		 * width.
1205 		 */
1206 		for ( i = 0 ; i < tex->height ; i++ ) {
1207 			if ( copy_from_user( buffer, data, tex_width ) ) {
1208 				DRM_ERROR( "EFAULT on pad, %d bytes\n",
1209 					   tex_width );
1210 				return -EFAULT;
1211 			}
1212 			buffer += 8;
1213 			data += tex_width;
1214 		}
1215 	}
1216 
1217 	buf->pid = current->pid;
1218 	buf->used = (dwords + 8) * sizeof(u32);
1219 
1220 	radeon_cp_dispatch_indirect( dev, buf, 0, buf->used );
1221 	radeon_cp_discard_buffer( dev, buf );
1222 
1223 		/* Update the input parameters for next time */
1224 		image->y += height;
1225 		image->height -= height;
1226 		image->data = (const u8 *)image->data + size;
1227 	} while (image->height > 0);
1228 
1229 	/* Flush the pixel cache after the blit completes.  This ensures
1230 	 * the texture data is written out to memory before rendering
1231 	 * continues.
1232 	 */
1233 	BEGIN_RING( 4 );
1234 	RADEON_FLUSH_CACHE();
1235 	RADEON_WAIT_UNTIL_2D_IDLE();
1236 	ADVANCE_RING();
1237 	return 0;
1238 }
1239 
1240 
radeon_cp_dispatch_stipple(drm_device_t * dev,u32 * stipple)1241 static void radeon_cp_dispatch_stipple( drm_device_t *dev, u32 *stipple )
1242 {
1243 	drm_radeon_private_t *dev_priv = dev->dev_private;
1244 	int i;
1245 	RING_LOCALS;
1246 	DRM_DEBUG( "\n" );
1247 
1248 	BEGIN_RING( 35 );
1249 
1250 	OUT_RING( CP_PACKET0( RADEON_RE_STIPPLE_ADDR, 0 ) );
1251 	OUT_RING( 0x00000000 );
1252 
1253 	OUT_RING( CP_PACKET0_TABLE( RADEON_RE_STIPPLE_DATA, 31 ) );
1254 	for ( i = 0 ; i < 32 ; i++ ) {
1255 		OUT_RING( stipple[i] );
1256 	}
1257 
1258 	ADVANCE_RING();
1259 }
1260 
1261 
1262 /* ================================================================
1263  * IOCTL functions
1264  */
1265 
radeon_cp_clear(struct inode * inode,struct file * filp,unsigned int cmd,unsigned long arg)1266 int radeon_cp_clear( struct inode *inode, struct file *filp,
1267 		     unsigned int cmd, unsigned long arg )
1268 {
1269 	drm_file_t *priv = filp->private_data;
1270 	drm_device_t *dev = priv->dev;
1271 	drm_radeon_private_t *dev_priv = dev->dev_private;
1272 	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
1273 	drm_radeon_clear_t clear;
1274 	drm_radeon_clear_rect_t depth_boxes[RADEON_NR_SAREA_CLIPRECTS];
1275 	DRM_DEBUG( "\n" );
1276 
1277 	LOCK_TEST_WITH_RETURN( dev );
1278 
1279 	if ( copy_from_user( &clear, (drm_radeon_clear_t *)arg,
1280 			     sizeof(clear) ) )
1281 		return -EFAULT;
1282 
1283 	RING_SPACE_TEST_WITH_RETURN( dev_priv );
1284 
1285 	if ( sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS )
1286 		sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
1287 
1288 	if ( copy_from_user( &depth_boxes, clear.depth_boxes,
1289 			     sarea_priv->nbox * sizeof(depth_boxes[0]) ) )
1290 		return -EFAULT;
1291 
1292 	radeon_cp_dispatch_clear( dev, &clear, depth_boxes );
1293 
1294 	COMMIT_RING();
1295 	return 0;
1296 }
1297 
1298 
1299 /* Not sure why this isn't set all the time:
1300  */
radeon_do_init_pageflip(drm_device_t * dev)1301 static int radeon_do_init_pageflip( drm_device_t *dev )
1302 {
1303 	drm_radeon_private_t *dev_priv = dev->dev_private;
1304 	RING_LOCALS;
1305 
1306 	DRM_DEBUG( "\n" );
1307 
1308 	BEGIN_RING( 6 );
1309 	RADEON_WAIT_UNTIL_3D_IDLE();
1310 	OUT_RING( CP_PACKET0( RADEON_CRTC_OFFSET_CNTL, 0 ) );
1311 	OUT_RING( RADEON_READ( RADEON_CRTC_OFFSET_CNTL ) | RADEON_CRTC_OFFSET_FLIP_CNTL );
1312 	OUT_RING( CP_PACKET0( RADEON_CRTC2_OFFSET_CNTL, 0 ) );
1313 	OUT_RING( RADEON_READ( RADEON_CRTC2_OFFSET_CNTL ) | RADEON_CRTC_OFFSET_FLIP_CNTL );
1314 	ADVANCE_RING();
1315 
1316 	dev_priv->page_flipping = 1;
1317 	dev_priv->current_page = 0;
1318 	dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page;
1319 
1320 	return 0;
1321 }
1322 
1323 /* Called whenever a client dies, from DRM(release).
1324  * NOTE:  Lock isn't necessarily held when this is called!
1325  */
radeon_do_cleanup_pageflip(drm_device_t * dev)1326 int radeon_do_cleanup_pageflip( drm_device_t *dev )
1327 {
1328 	drm_radeon_private_t *dev_priv = dev->dev_private;
1329 	DRM_DEBUG( "\n" );
1330 
1331 	if (dev_priv->current_page != 0)
1332 		radeon_cp_dispatch_flip( dev );
1333 
1334 	dev_priv->page_flipping = 0;
1335 	return 0;
1336 }
1337 
1338 /* Swapping and flipping are different operations, need different ioctls.
1339  * They can & should be intermixed to support multiple 3d windows.
1340  */
radeon_cp_flip(struct inode * inode,struct file * filp,unsigned int cmd,unsigned long data)1341 int radeon_cp_flip(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long data )
1342 {
1343         drm_file_t      *priv   = filp->private_data;
1344         drm_device_t    *dev    = priv->dev;
1345 	drm_radeon_private_t *dev_priv = dev->dev_private;
1346 	DRM_DEBUG( "\n" );
1347 
1348 	LOCK_TEST_WITH_RETURN( dev );
1349 
1350 	RING_SPACE_TEST_WITH_RETURN( dev_priv );
1351 
1352 	if (!dev_priv->page_flipping)
1353 		radeon_do_init_pageflip( dev );
1354 
1355 	radeon_cp_dispatch_flip( dev );
1356 
1357 	COMMIT_RING();
1358 	return 0;
1359 }
1360 
radeon_cp_swap(struct inode * inode,struct file * filp,unsigned int cmd,unsigned long arg)1361 int radeon_cp_swap( struct inode *inode, struct file *filp,
1362 		    unsigned int cmd, unsigned long arg )
1363 {
1364 	drm_file_t *priv = filp->private_data;
1365 	drm_device_t *dev = priv->dev;
1366 	drm_radeon_private_t *dev_priv = dev->dev_private;
1367 	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
1368 	DRM_DEBUG( "\n" );
1369 
1370 	LOCK_TEST_WITH_RETURN( dev );
1371 
1372 	RING_SPACE_TEST_WITH_RETURN( dev_priv );
1373 
1374 	if ( sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS )
1375 		sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
1376 
1377 	radeon_cp_dispatch_swap( dev );
1378 	dev_priv->sarea_priv->ctx_owner = 0;
1379 
1380 	COMMIT_RING();
1381 	return 0;
1382 }
1383 
radeon_cp_vertex(struct inode * inode,struct file * filp,unsigned int cmd,unsigned long arg)1384 int radeon_cp_vertex( struct inode *inode, struct file *filp,
1385 		      unsigned int cmd, unsigned long arg )
1386 {
1387 	drm_file_t *priv = filp->private_data;
1388 	drm_device_t *dev = priv->dev;
1389 	drm_radeon_private_t *dev_priv = dev->dev_private;
1390 	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
1391 	drm_device_dma_t *dma = dev->dma;
1392 	drm_buf_t *buf;
1393 	drm_radeon_vertex_t vertex;
1394 	drm_radeon_tcl_prim_t prim;
1395 
1396 	LOCK_TEST_WITH_RETURN( dev );
1397 
1398 	if ( !dev_priv ) {
1399 		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
1400 		return -EINVAL;
1401 	}
1402 
1403 	if ( copy_from_user( &vertex, (drm_radeon_vertex_t *)arg,
1404 			     sizeof(vertex) ) )
1405 		return -EFAULT;
1406 
1407 	DRM_DEBUG( "pid=%d index=%d count=%d discard=%d\n",
1408 		   current->pid,
1409 		   vertex.idx, vertex.count, vertex.discard );
1410 
1411 	if ( vertex.idx < 0 || vertex.idx >= dma->buf_count ) {
1412 		DRM_ERROR( "buffer index %d (of %d max)\n",
1413 			   vertex.idx, dma->buf_count - 1 );
1414 		return -EINVAL;
1415 	}
1416 	if ( vertex.prim < 0 ||
1417 	     vertex.prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST ) {
1418 		DRM_ERROR( "buffer prim %d\n", vertex.prim );
1419 		return -EINVAL;
1420 	}
1421 
1422 	RING_SPACE_TEST_WITH_RETURN( dev_priv );
1423 	VB_AGE_TEST_WITH_RETURN( dev_priv );
1424 
1425 	buf = dma->buflist[vertex.idx];
1426 
1427 	if ( buf->pid != current->pid ) {
1428 		DRM_ERROR( "process %d using buffer owned by %d\n",
1429 			   current->pid, buf->pid );
1430 		return -EINVAL;
1431 	}
1432 	if ( buf->pending ) {
1433 		DRM_ERROR( "sending pending buffer %d\n", vertex.idx );
1434 		return -EINVAL;
1435 	}
1436 
1437 	/* Build up a prim_t record:
1438 	 */
1439 	if (vertex.count) {
1440 		buf->used = vertex.count; /* not used? */
1441 
1442 		if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) {
1443 			radeon_emit_state( dev_priv,
1444 					   &sarea_priv->context_state,
1445 					   sarea_priv->tex_state,
1446 					   sarea_priv->dirty );
1447 
1448 			sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES |
1449 					       RADEON_UPLOAD_TEX1IMAGES |
1450 					       RADEON_UPLOAD_TEX2IMAGES |
1451 					       RADEON_REQUIRE_QUIESCENCE);
1452 		}
1453 
1454 		prim.start = 0;
1455 		prim.finish = vertex.count; /* unused */
1456 		prim.prim = vertex.prim;
1457 		prim.numverts = vertex.count;
1458 		prim.vc_format = dev_priv->sarea_priv->vc_format;
1459 
1460 		radeon_cp_dispatch_vertex( dev, buf, &prim,
1461 					   dev_priv->sarea_priv->boxes,
1462 					   dev_priv->sarea_priv->nbox );
1463 	}
1464 
1465 	if (vertex.discard) {
1466 		radeon_cp_discard_buffer( dev, buf );
1467 	}
1468 
1469 	COMMIT_RING();
1470 	return 0;
1471 }
1472 
radeon_cp_indices(struct inode * inode,struct file * filp,unsigned int cmd,unsigned long arg)1473 int radeon_cp_indices( struct inode *inode, struct file *filp,
1474 		       unsigned int cmd, unsigned long arg )
1475 {
1476 	drm_file_t *priv = filp->private_data;
1477 	drm_device_t *dev = priv->dev;
1478 	drm_radeon_private_t *dev_priv = dev->dev_private;
1479 	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
1480 	drm_device_dma_t *dma = dev->dma;
1481 	drm_buf_t *buf;
1482 	drm_radeon_indices_t elts;
1483 	drm_radeon_tcl_prim_t prim;
1484 	int count;
1485 
1486 	LOCK_TEST_WITH_RETURN( dev );
1487 
1488 	if ( !dev_priv ) {
1489 		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
1490 		return -EINVAL;
1491 	}
1492 
1493 	if ( copy_from_user( &elts, (drm_radeon_indices_t *)arg,
1494 			     sizeof(elts) ) )
1495 		return -EFAULT;
1496 
1497 	DRM_DEBUG( "%s: pid=%d index=%d start=%d end=%d discard=%d\n",
1498 		   __FUNCTION__, current->pid,
1499 		   elts.idx, elts.start, elts.end, elts.discard );
1500 
1501 	if ( elts.idx < 0 || elts.idx >= dma->buf_count ) {
1502 		DRM_ERROR( "buffer index %d (of %d max)\n",
1503 			   elts.idx, dma->buf_count - 1 );
1504 		return -EINVAL;
1505 	}
1506 	if ( elts.prim < 0 ||
1507 	     elts.prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST ) {
1508 		DRM_ERROR( "buffer prim %d\n", elts.prim );
1509 		return -EINVAL;
1510 	}
1511 
1512 	RING_SPACE_TEST_WITH_RETURN( dev_priv );
1513 	VB_AGE_TEST_WITH_RETURN( dev_priv );
1514 
1515 	buf = dma->buflist[elts.idx];
1516 
1517 	if ( buf->pid != current->pid ) {
1518 		DRM_ERROR( "process %d using buffer owned by %d\n",
1519 			   current->pid, buf->pid );
1520 		return -EINVAL;
1521 	}
1522 	if ( buf->pending ) {
1523 		DRM_ERROR( "sending pending buffer %d\n", elts.idx );
1524 		return -EINVAL;
1525 	}
1526 
1527 	count = (elts.end - elts.start) / sizeof(u16);
1528 	elts.start -= RADEON_INDEX_PRIM_OFFSET;
1529 
1530 	if ( elts.start & 0x7 ) {
1531 		DRM_ERROR( "misaligned buffer 0x%x\n", elts.start );
1532 		return -EINVAL;
1533 	}
1534 	if ( elts.start < buf->used ) {
1535 		DRM_ERROR( "no header 0x%x - 0x%x\n", elts.start, buf->used );
1536 		return -EINVAL;
1537 	}
1538 
1539 	buf->used = elts.end;
1540 
1541 	if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) {
1542 		radeon_emit_state( dev_priv,
1543 				   &sarea_priv->context_state,
1544 				   sarea_priv->tex_state,
1545 				   sarea_priv->dirty );
1546 
1547 		sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES |
1548 				       RADEON_UPLOAD_TEX1IMAGES |
1549 				       RADEON_UPLOAD_TEX2IMAGES |
1550 				       RADEON_REQUIRE_QUIESCENCE);
1551 	}
1552 
1553 
1554 	/* Build up a prim_t record:
1555 	 */
1556 	prim.start = elts.start;
1557 	prim.finish = elts.end;
1558 	prim.prim = elts.prim;
1559 	prim.offset = 0;	/* offset from start of dma buffers */
1560 	prim.numverts = RADEON_MAX_VB_VERTS; /* duh */
1561 	prim.vc_format = dev_priv->sarea_priv->vc_format;
1562 
1563 	radeon_cp_dispatch_indices( dev, buf, &prim,
1564 				   dev_priv->sarea_priv->boxes,
1565 				   dev_priv->sarea_priv->nbox );
1566 	if (elts.discard) {
1567 		radeon_cp_discard_buffer( dev, buf );
1568 	}
1569 
1570 	COMMIT_RING();
1571 	return 0;
1572 }
1573 
radeon_cp_texture(struct inode * inode,struct file * filp,unsigned int cmd,unsigned long arg)1574 int radeon_cp_texture( struct inode *inode, struct file *filp,
1575 		       unsigned int cmd, unsigned long arg )
1576 {
1577 	drm_file_t *priv = filp->private_data;
1578 	drm_device_t *dev = priv->dev;
1579 	drm_radeon_private_t *dev_priv = dev->dev_private;
1580 	drm_radeon_texture_t tex;
1581 	drm_radeon_tex_image_t image;
1582 	int ret;
1583 
1584 	LOCK_TEST_WITH_RETURN( dev );
1585 
1586 	if ( copy_from_user( &tex, (drm_radeon_texture_t *)arg, sizeof(tex) ) )
1587 		return -EFAULT;
1588 
1589 	if ( tex.image == NULL ) {
1590 		DRM_ERROR( "null texture image!\n" );
1591 		return -EINVAL;
1592 	}
1593 
1594 	if ( copy_from_user( &image,
1595 			     (drm_radeon_tex_image_t *)tex.image,
1596 			     sizeof(image) ) )
1597 		return -EFAULT;
1598 
1599 	RING_SPACE_TEST_WITH_RETURN( dev_priv );
1600 	VB_AGE_TEST_WITH_RETURN( dev_priv );
1601 
1602 	ret = radeon_cp_dispatch_texture( dev, &tex, &image );
1603 
1604 	COMMIT_RING();
1605 	return ret;
1606 }
1607 
radeon_cp_stipple(struct inode * inode,struct file * filp,unsigned int cmd,unsigned long arg)1608 int radeon_cp_stipple( struct inode *inode, struct file *filp,
1609 		       unsigned int cmd, unsigned long arg )
1610 {
1611 	drm_file_t *priv = filp->private_data;
1612 	drm_device_t *dev = priv->dev;
1613 	drm_radeon_private_t *dev_priv = dev->dev_private;
1614 	drm_radeon_stipple_t stipple;
1615 	u32 mask[32];
1616 
1617 	LOCK_TEST_WITH_RETURN( dev );
1618 
1619 	if ( copy_from_user( &stipple, (drm_radeon_stipple_t *)arg,
1620 			     sizeof(stipple) ) )
1621 		return -EFAULT;
1622 
1623 	if ( copy_from_user( &mask, stipple.mask, 32 * sizeof(u32) ) )
1624 		return -EFAULT;
1625 
1626 	RING_SPACE_TEST_WITH_RETURN( dev_priv );
1627 
1628 	radeon_cp_dispatch_stipple( dev, mask );
1629 
1630 	COMMIT_RING();
1631 	return 0;
1632 }
1633 
radeon_cp_indirect(struct inode * inode,struct file * filp,unsigned int cmd,unsigned long arg)1634 int radeon_cp_indirect( struct inode *inode, struct file *filp,
1635 			unsigned int cmd, unsigned long arg )
1636 {
1637 	drm_file_t *priv = filp->private_data;
1638 	drm_device_t *dev = priv->dev;
1639 	drm_radeon_private_t *dev_priv = dev->dev_private;
1640 	drm_device_dma_t *dma = dev->dma;
1641 	drm_buf_t *buf;
1642 	drm_radeon_indirect_t indirect;
1643 	RING_LOCALS;
1644 
1645 	LOCK_TEST_WITH_RETURN( dev );
1646 
1647 	if ( !dev_priv ) {
1648 		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
1649 		return -EINVAL;
1650 	}
1651 
1652 	if ( copy_from_user( &indirect, (drm_radeon_indirect_t *)arg,
1653 			     sizeof(indirect) ) )
1654 		return -EFAULT;
1655 
1656 	DRM_DEBUG( "indirect: idx=%d s=%d e=%d d=%d\n",
1657 		   indirect.idx, indirect.start,
1658 		   indirect.end, indirect.discard );
1659 
1660 	if ( indirect.idx < 0 || indirect.idx >= dma->buf_count ) {
1661 		DRM_ERROR( "buffer index %d (of %d max)\n",
1662 			   indirect.idx, dma->buf_count - 1 );
1663 		return -EINVAL;
1664 	}
1665 
1666 	buf = dma->buflist[indirect.idx];
1667 
1668 	if ( buf->pid != current->pid ) {
1669 		DRM_ERROR( "process %d using buffer owned by %d\n",
1670 			   current->pid, buf->pid );
1671 		return -EINVAL;
1672 	}
1673 	if ( buf->pending ) {
1674 		DRM_ERROR( "sending pending buffer %d\n", indirect.idx );
1675 		return -EINVAL;
1676 	}
1677 
1678 	if ( indirect.start < buf->used ) {
1679 		DRM_ERROR( "reusing indirect: start=0x%x actual=0x%x\n",
1680 			   indirect.start, buf->used );
1681 		return -EINVAL;
1682 	}
1683 
1684 	RING_SPACE_TEST_WITH_RETURN( dev_priv );
1685 	VB_AGE_TEST_WITH_RETURN( dev_priv );
1686 
1687 	buf->used = indirect.end;
1688 
1689 	/* Wait for the 3D stream to idle before the indirect buffer
1690 	 * containing 2D acceleration commands is processed.
1691 	 */
1692 	BEGIN_RING( 2 );
1693 
1694 	RADEON_WAIT_UNTIL_3D_IDLE();
1695 
1696 	ADVANCE_RING();
1697 
1698 	/* Dispatch the indirect buffer full of commands from the
1699 	 * X server.  This is insecure and is thus only available to
1700 	 * privileged clients.
1701 	 */
1702 	radeon_cp_dispatch_indirect( dev, buf, indirect.start, indirect.end );
1703 	if (indirect.discard) {
1704 		radeon_cp_discard_buffer( dev, buf );
1705 	}
1706 
1707 
1708 	COMMIT_RING();
1709 	return 0;
1710 }
1711 
radeon_cp_vertex2(struct inode * inode,struct file * filp,unsigned int cmd,unsigned long data)1712 int radeon_cp_vertex2(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long data )
1713 {
1714         drm_file_t      *priv   = filp->private_data;
1715         drm_device_t    *dev    = priv->dev;
1716 	drm_radeon_private_t *dev_priv = dev->dev_private;
1717 	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
1718 	drm_device_dma_t *dma = dev->dma;
1719 	drm_buf_t *buf;
1720 	drm_radeon_vertex2_t vertex;
1721 	int i;
1722 	unsigned char laststate;
1723 
1724 	LOCK_TEST_WITH_RETURN( dev );
1725 
1726 	if ( !dev_priv ) {
1727 		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
1728 		return -EINVAL;
1729 	}
1730 
1731 	DRM_COPY_FROM_USER_IOCTL( vertex, (drm_radeon_vertex2_t *)data,
1732 			     sizeof(vertex) );
1733 
1734 	DRM_DEBUG( "pid=%d index=%d discard=%d\n",
1735 		   current->pid,
1736 		   vertex.idx, vertex.discard );
1737 
1738 	if ( vertex.idx < 0 || vertex.idx >= dma->buf_count ) {
1739 		DRM_ERROR( "buffer index %d (of %d max)\n",
1740 			   vertex.idx, dma->buf_count - 1 );
1741 		return -EINVAL;
1742 	}
1743 
1744 	RING_SPACE_TEST_WITH_RETURN( dev_priv );
1745 	VB_AGE_TEST_WITH_RETURN( dev_priv );
1746 
1747 	buf = dma->buflist[vertex.idx];
1748 
1749 	if ( buf->pid != current->pid ) {
1750 		DRM_ERROR( "process %d using buffer owned by %d\n",
1751 			   current->pid, buf->pid );
1752 		return -EINVAL;
1753 	}
1754 
1755 	if ( buf->pending ) {
1756 		DRM_ERROR( "sending pending buffer %d\n", vertex.idx );
1757 		return -EINVAL;
1758 	}
1759 
1760 	if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS)
1761 		return -EINVAL;
1762 
1763 	for (laststate = 0xff, i = 0 ; i < vertex.nr_prims ; i++) {
1764 		drm_radeon_prim_t prim;
1765 		drm_radeon_tcl_prim_t tclprim;
1766 
1767 		if ( copy_from_user( &prim, &vertex.prim[i], sizeof(prim) ) )
1768 			return -EFAULT;
1769 
1770 		if ( prim.stateidx != laststate ) {
1771 			drm_radeon_state_t state;
1772 
1773 			if ( copy_from_user( &state,
1774 					     &vertex.state[prim.stateidx],
1775 					     sizeof(state) ) )
1776 				return -EFAULT;
1777 
1778 			radeon_emit_state2( dev_priv, &state );
1779 
1780 			laststate = prim.stateidx;
1781 		}
1782 
1783 		tclprim.start = prim.start;
1784 		tclprim.finish = prim.finish;
1785 		tclprim.prim = prim.prim;
1786 		tclprim.vc_format = prim.vc_format;
1787 
1788 		if ( prim.prim & RADEON_PRIM_WALK_IND ) {
1789 			tclprim.offset = prim.numverts * 64;
1790 			tclprim.numverts = RADEON_MAX_VB_VERTS; /* duh */
1791 
1792 			radeon_cp_dispatch_indices( dev, buf, &tclprim,
1793 						    sarea_priv->boxes,
1794 						    sarea_priv->nbox);
1795 		} else {
1796 			tclprim.numverts = prim.numverts;
1797 			tclprim.offset = 0; /* not used */
1798 
1799 			radeon_cp_dispatch_vertex( dev, buf, &tclprim,
1800 						   sarea_priv->boxes,
1801 						   sarea_priv->nbox);
1802 		}
1803 
1804 		if (sarea_priv->nbox == 1)
1805 			sarea_priv->nbox = 0;
1806 	}
1807 
1808 	if ( vertex.discard ) {
1809 		radeon_cp_discard_buffer( dev, buf );
1810 	}
1811 
1812 	COMMIT_RING();
1813 	return 0;
1814 }
1815 
1816 
radeon_emit_packets(drm_radeon_private_t * dev_priv,drm_radeon_cmd_header_t header,drm_radeon_cmd_buffer_t * cmdbuf)1817 static int radeon_emit_packets(
1818 	drm_radeon_private_t *dev_priv,
1819 	drm_radeon_cmd_header_t header,
1820 	drm_radeon_cmd_buffer_t *cmdbuf )
1821 {
1822 	int id = (int)header.packet.packet_id;
1823 	int sz, reg;
1824 	int *data = (int *)cmdbuf->buf;
1825 	RING_LOCALS;
1826 
1827 	if (id >= RADEON_MAX_STATE_PACKETS)
1828 		return -EINVAL;
1829 
1830 	sz = packet[id].len;
1831 	reg = packet[id].start;
1832 
1833 	if (sz * sizeof(int) > cmdbuf->bufsz)
1834 		return -EINVAL;
1835 
1836 	BEGIN_RING(sz+1);
1837 	OUT_RING( CP_PACKET0( reg, (sz-1) ) );
1838 	OUT_RING_USER_TABLE( data, sz );
1839 	ADVANCE_RING();
1840 
1841 	cmdbuf->buf += sz * sizeof(int);
1842 	cmdbuf->bufsz -= sz * sizeof(int);
1843 	return 0;
1844 }
1845 
radeon_emit_scalars(drm_radeon_private_t * dev_priv,drm_radeon_cmd_header_t header,drm_radeon_cmd_buffer_t * cmdbuf)1846 static __inline__ int radeon_emit_scalars(
1847 	drm_radeon_private_t *dev_priv,
1848 	drm_radeon_cmd_header_t header,
1849 	drm_radeon_cmd_buffer_t *cmdbuf )
1850 {
1851 	int sz = header.scalars.count;
1852 	int *data = (int *)cmdbuf->buf;
1853 	int start = header.scalars.offset;
1854 	int stride = header.scalars.stride;
1855 	RING_LOCALS;
1856 
1857 	BEGIN_RING( 3+sz );
1858 	OUT_RING( CP_PACKET0( RADEON_SE_TCL_SCALAR_INDX_REG, 0 ) );
1859 	OUT_RING( start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT));
1860 	OUT_RING( CP_PACKET0_TABLE( RADEON_SE_TCL_SCALAR_DATA_REG, sz-1 ) );
1861 	OUT_RING_USER_TABLE( data, sz );
1862 	ADVANCE_RING();
1863 	cmdbuf->buf += sz * sizeof(int);
1864 	cmdbuf->bufsz -= sz * sizeof(int);
1865 	return 0;
1866 }
1867 
1868 /* God this is ugly
1869  */
radeon_emit_scalars2(drm_radeon_private_t * dev_priv,drm_radeon_cmd_header_t header,drm_radeon_cmd_buffer_t * cmdbuf)1870 static __inline__ int radeon_emit_scalars2(
1871 	drm_radeon_private_t *dev_priv,
1872 	drm_radeon_cmd_header_t header,
1873 	drm_radeon_cmd_buffer_t *cmdbuf )
1874 {
1875 	int sz = header.scalars.count;
1876 	int *data = (int *)cmdbuf->buf;
1877 	int start = ((unsigned int)header.scalars.offset) + 0x100;
1878 	int stride = header.scalars.stride;
1879 	RING_LOCALS;
1880 
1881 	BEGIN_RING( 3+sz );
1882 	OUT_RING( CP_PACKET0( RADEON_SE_TCL_SCALAR_INDX_REG, 0 ) );
1883 	OUT_RING( start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT));
1884 	OUT_RING( CP_PACKET0_TABLE( RADEON_SE_TCL_SCALAR_DATA_REG, sz-1 ) );
1885 	OUT_RING_USER_TABLE( data, sz );
1886 	ADVANCE_RING();
1887 	cmdbuf->buf += sz * sizeof(int);
1888 	cmdbuf->bufsz -= sz * sizeof(int);
1889 	return 0;
1890 }
1891 
radeon_emit_vectors(drm_radeon_private_t * dev_priv,drm_radeon_cmd_header_t header,drm_radeon_cmd_buffer_t * cmdbuf)1892 static __inline__ int radeon_emit_vectors(
1893 	drm_radeon_private_t *dev_priv,
1894 	drm_radeon_cmd_header_t header,
1895 	drm_radeon_cmd_buffer_t *cmdbuf )
1896 {
1897 	int sz = header.vectors.count;
1898 	int *data = (int *)cmdbuf->buf;
1899 	int start = header.vectors.offset;
1900 	int stride = header.vectors.stride;
1901 	RING_LOCALS;
1902 
1903 	BEGIN_RING( 3+sz );
1904 	OUT_RING( CP_PACKET0( RADEON_SE_TCL_VECTOR_INDX_REG, 0 ) );
1905 	OUT_RING( start | (stride << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT));
1906 	OUT_RING( CP_PACKET0_TABLE( RADEON_SE_TCL_VECTOR_DATA_REG, (sz-1) ) );
1907 	OUT_RING_USER_TABLE( data, sz );
1908 	ADVANCE_RING();
1909 
1910 	cmdbuf->buf += sz * sizeof(int);
1911 	cmdbuf->bufsz -= sz * sizeof(int);
1912 	return 0;
1913 }
1914 
1915 
radeon_emit_packet3(drm_device_t * dev,drm_radeon_cmd_buffer_t * cmdbuf)1916 static int radeon_emit_packet3( drm_device_t *dev,
1917 				drm_radeon_cmd_buffer_t *cmdbuf )
1918 {
1919 	drm_radeon_private_t *dev_priv = dev->dev_private;
1920 	int cmdsz, tmp;
1921 	int *cmd = (int *)cmdbuf->buf;
1922 	RING_LOCALS;
1923 
1924 
1925 	DRM_DEBUG("\n");
1926 
1927 	if (__get_user( tmp, &cmd[0]))
1928 		return -EFAULT;
1929 
1930 	cmdsz = 2 + ((tmp & RADEON_CP_PACKET_COUNT_MASK) >> 16);
1931 
1932 	if ((tmp & 0xc0000000) != RADEON_CP_PACKET3 ||
1933 	    cmdsz * 4 > cmdbuf->bufsz)
1934 		return -EINVAL;
1935 
1936 	BEGIN_RING( cmdsz );
1937 	OUT_RING_USER_TABLE( cmd, cmdsz );
1938 	ADVANCE_RING();
1939 
1940 	cmdbuf->buf += cmdsz * 4;
1941 	cmdbuf->bufsz -= cmdsz * 4;
1942 	return 0;
1943 }
1944 
1945 
radeon_emit_packet3_cliprect(drm_device_t * dev,drm_radeon_cmd_buffer_t * cmdbuf,int orig_nbox)1946 static int radeon_emit_packet3_cliprect( drm_device_t *dev,
1947 					 drm_radeon_cmd_buffer_t *cmdbuf,
1948 					 int orig_nbox )
1949 {
1950 	drm_radeon_private_t *dev_priv = dev->dev_private;
1951 	drm_clip_rect_t box;
1952 	int cmdsz, tmp;
1953 	int *cmd = (int *)cmdbuf->buf;
1954 	drm_clip_rect_t *boxes = cmdbuf->boxes;
1955 	int i = 0;
1956 	RING_LOCALS;
1957 
1958 	DRM_DEBUG("\n");
1959 
1960 	if (__get_user( tmp, &cmd[0]))
1961 		return -EFAULT;
1962 
1963 	cmdsz = 2 + ((tmp & RADEON_CP_PACKET_COUNT_MASK) >> 16);
1964 
1965 	if ((tmp & 0xc0000000) != RADEON_CP_PACKET3 ||
1966 	    cmdsz * 4 > cmdbuf->bufsz)
1967 		return -EINVAL;
1968 
1969 	if (!orig_nbox)
1970 		goto out;
1971 
1972 	do {
1973 		if ( i < cmdbuf->nbox ) {
1974 			if (__copy_from_user( &box, &boxes[i], sizeof(box) ))
1975 				return -EFAULT;
1976 			/* FIXME The second and subsequent times round
1977 			 * this loop, send a WAIT_UNTIL_3D_IDLE before
1978 			 * calling emit_clip_rect(). This fixes a
1979 			 * lockup on fast machines when sending
1980 			 * several cliprects with a cmdbuf, as when
1981 			 * waving a 2D window over a 3D
1982 			 * window. Something in the commands from user
1983 			 * space seems to hang the card when they're
1984 			 * sent several times in a row. That would be
1985 			 * the correct place to fix it but this works
1986 			 * around it until I can figure that out - Tim
1987 			 * Smith */
1988 			if ( i ) {
1989 				BEGIN_RING( 2 );
1990 				RADEON_WAIT_UNTIL_3D_IDLE();
1991 				ADVANCE_RING();
1992 			}
1993 			radeon_emit_clip_rect( dev_priv, &box );
1994 		}
1995 
1996 		BEGIN_RING( cmdsz );
1997 		OUT_RING_USER_TABLE( cmd, cmdsz );
1998 		ADVANCE_RING();
1999 
2000 	} while ( ++i < cmdbuf->nbox );
2001  	if (cmdbuf->nbox == 1)
2002 		cmdbuf->nbox = 0;
2003 
2004  out:
2005 	cmdbuf->buf += cmdsz * 4;
2006 	cmdbuf->bufsz -= cmdsz * 4;
2007 	return 0;
2008 }
2009 
2010 
radeon_emit_wait(drm_device_t * dev,int flags)2011 static int radeon_emit_wait( drm_device_t *dev, int flags )
2012 {
2013 	drm_radeon_private_t *dev_priv = dev->dev_private;
2014 	RING_LOCALS;
2015 
2016 	DRM_DEBUG("%s: %x\n", __FUNCTION__, flags);
2017 	switch (flags) {
2018 	case RADEON_WAIT_2D:
2019 		BEGIN_RING( 2 );
2020 		RADEON_WAIT_UNTIL_2D_IDLE();
2021 		ADVANCE_RING();
2022 		break;
2023 	case RADEON_WAIT_3D:
2024 		BEGIN_RING( 2 );
2025 		RADEON_WAIT_UNTIL_3D_IDLE();
2026 		ADVANCE_RING();
2027 		break;
2028 	case RADEON_WAIT_2D|RADEON_WAIT_3D:
2029 		BEGIN_RING( 2 );
2030 		RADEON_WAIT_UNTIL_IDLE();
2031 		ADVANCE_RING();
2032 		break;
2033 	default:
2034 		return -EINVAL;
2035 	}
2036 
2037 	return 0;
2038 }
2039 
radeon_cp_cmdbuf(struct inode * inode,struct file * filp,unsigned int cmd,unsigned long data)2040 int radeon_cp_cmdbuf(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long data )
2041 {
2042         drm_file_t      *priv   = filp->private_data;
2043         drm_device_t    *dev    = priv->dev;
2044 	drm_radeon_private_t *dev_priv = dev->dev_private;
2045 	drm_device_dma_t *dma = dev->dma;
2046 	drm_buf_t *buf = 0;
2047 	int idx;
2048 	drm_radeon_cmd_buffer_t cmdbuf;
2049 	drm_radeon_cmd_header_t header;
2050 	int orig_nbox;
2051 
2052 	LOCK_TEST_WITH_RETURN( dev );
2053 
2054 	if ( !dev_priv ) {
2055 		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
2056 		return -EINVAL;
2057 	}
2058 
2059 	DRM_COPY_FROM_USER_IOCTL( cmdbuf, (drm_radeon_cmd_buffer_t *)data,
2060 			     sizeof(cmdbuf) );
2061 
2062 	RING_SPACE_TEST_WITH_RETURN( dev_priv );
2063 	VB_AGE_TEST_WITH_RETURN( dev_priv );
2064 
2065 
2066 	if (verify_area( VERIFY_READ, cmdbuf.buf, cmdbuf.bufsz ))
2067 		return -EFAULT;
2068 
2069 	if (cmdbuf.nbox &&
2070 	    verify_area( VERIFY_READ, cmdbuf.boxes,
2071 			 cmdbuf.nbox * sizeof(drm_clip_rect_t)))
2072 		return -EFAULT;
2073 
2074 	orig_nbox = cmdbuf.nbox;
2075 
2076 	while ( cmdbuf.bufsz >= sizeof(header) ) {
2077 
2078 		if (__get_user( header.i, (int *)cmdbuf.buf )) {
2079 			DRM_ERROR("__get_user %p\n", cmdbuf.buf);
2080 			return -EFAULT;
2081 		}
2082 
2083 		cmdbuf.buf += sizeof(header);
2084 		cmdbuf.bufsz -= sizeof(header);
2085 
2086 		switch (header.header.cmd_type) {
2087 		case RADEON_CMD_PACKET:
2088 			DRM_DEBUG("RADEON_CMD_PACKET\n");
2089 			if (radeon_emit_packets( dev_priv, header, &cmdbuf )) {
2090 				DRM_ERROR("radeon_emit_packets failed\n");
2091 				return -EINVAL;
2092 			}
2093 			break;
2094 
2095 		case RADEON_CMD_SCALARS:
2096 			DRM_DEBUG("RADEON_CMD_SCALARS\n");
2097 			if (radeon_emit_scalars( dev_priv, header, &cmdbuf )) {
2098 				DRM_ERROR("radeon_emit_scalars failed\n");
2099 				return -EINVAL;
2100 			}
2101 			break;
2102 
2103 		case RADEON_CMD_VECTORS:
2104 			DRM_DEBUG("RADEON_CMD_VECTORS\n");
2105 			if (radeon_emit_vectors( dev_priv, header, &cmdbuf )) {
2106 				DRM_ERROR("radeon_emit_vectors failed\n");
2107 				return -EINVAL;
2108 			}
2109 			break;
2110 
2111 		case RADEON_CMD_DMA_DISCARD:
2112 			DRM_DEBUG("RADEON_CMD_DMA_DISCARD\n");
2113 			idx = header.dma.buf_idx;
2114 			if ( idx < 0 || idx >= dma->buf_count ) {
2115 				DRM_ERROR( "buffer index %d (of %d max)\n",
2116 					   idx, dma->buf_count - 1 );
2117 				return -EINVAL;
2118 			}
2119 
2120 			buf = dma->buflist[idx];
2121 			if ( buf->pid != current->pid || buf->pending ) {
2122 				DRM_ERROR( "bad buffer\n" );
2123 				return -EINVAL;
2124 			}
2125 
2126 			radeon_cp_discard_buffer( dev, buf );
2127 			break;
2128 
2129 		case RADEON_CMD_PACKET3:
2130 			DRM_DEBUG("RADEON_CMD_PACKET3\n");
2131 			if (radeon_emit_packet3( dev, &cmdbuf )) {
2132 				DRM_ERROR("radeon_emit_packet3 failed\n");
2133 				return -EINVAL;
2134 			}
2135 			break;
2136 
2137 		case RADEON_CMD_PACKET3_CLIP:
2138 			DRM_DEBUG("RADEON_CMD_PACKET3_CLIP\n");
2139 			if (radeon_emit_packet3_cliprect( dev, &cmdbuf, orig_nbox )) {
2140 				DRM_ERROR("radeon_emit_packet3_clip failed\n");
2141 				return -EINVAL;
2142 			}
2143 			break;
2144 
2145 		case RADEON_CMD_SCALARS2:
2146 			DRM_DEBUG("RADEON_CMD_SCALARS2\n");
2147 			if (radeon_emit_scalars2( dev_priv, header, &cmdbuf )) {
2148 				DRM_ERROR("radeon_emit_scalars2 failed\n");
2149 				return -EINVAL;
2150 			}
2151 			break;
2152 
2153 		case RADEON_CMD_WAIT:
2154 			DRM_DEBUG("RADEON_CMD_WAIT\n");
2155 			if (radeon_emit_wait( dev, header.wait.flags )) {
2156 				DRM_ERROR("radeon_emit_wait failed\n");
2157 				return -EINVAL;
2158 			}
2159 			break;
2160 		default:
2161 			DRM_ERROR("bad cmd_type %d at %p\n",
2162 				  header.header.cmd_type,
2163 				  cmdbuf.buf - sizeof(header));
2164 			return -EINVAL;
2165 		}
2166 	}
2167 
2168 
2169 	DRM_DEBUG("DONE\n");
2170 	COMMIT_RING();
2171 	return 0;
2172 }
2173 
2174 
2175 
radeon_cp_getparam(struct inode * inode,struct file * filp,unsigned int cmd,unsigned long data)2176 int radeon_cp_getparam(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long data)
2177 {
2178         drm_file_t      *priv   = filp->private_data;
2179         drm_device_t    *dev    = priv->dev;
2180 	drm_radeon_private_t *dev_priv = dev->dev_private;
2181 	drm_radeon_getparam_t param;
2182 	int value;
2183 
2184 	if ( !dev_priv ) {
2185 		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
2186 		return -EINVAL;
2187 	}
2188 
2189 	DRM_COPY_FROM_USER_IOCTL( param, (drm_radeon_getparam_t *)data,
2190 			     sizeof(param) );
2191 
2192 	DRM_DEBUG( "pid=%d\n", current->pid );
2193 
2194 	switch( param.param ) {
2195 	case RADEON_PARAM_AGP_BUFFER_OFFSET:
2196 		value = dev_priv->agp_buffers_offset;
2197 		break;
2198 	case RADEON_PARAM_LAST_FRAME:
2199 		dev_priv->stats.last_frame_reads++;
2200 		value = GET_SCRATCH( 0 );
2201 		break;
2202 	case RADEON_PARAM_LAST_DISPATCH:
2203 		value = GET_SCRATCH( 1 );
2204 		break;
2205 	case RADEON_PARAM_LAST_CLEAR:
2206 		dev_priv->stats.last_clear_reads++;
2207 		value = GET_SCRATCH( 2 );
2208 		break;
2209 	case RADEON_PARAM_IRQ_NR:
2210 		value = dev->irq;
2211 		break;
2212 	case RADEON_PARAM_AGP_BASE:
2213 		value = dev_priv->agp_vm_start;
2214 		break;
2215 	default:
2216 		return -EINVAL;
2217 	}
2218 
2219 	if ( copy_to_user( param.value, &value, sizeof(int) ) ) {
2220 		DRM_ERROR( "copy_to_user\n" );
2221 		return -EFAULT;
2222 	}
2223 
2224 	return 0;
2225 }
2226