1/* r128_state.c -- State support for r128 -*- linux-c -*-
2 * Created: Thu Jan 27 02:53:43 2000 by gareth@valinux.com
3 *
4 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
5 * All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
16 * Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
25 *
26 * Authors:
27 *    Gareth Hughes <gareth@valinux.com>
28 */
29
30#include "r128.h"
31#include "drmP.h"
32#include "r128_drv.h"
33#include "drm.h"
34#include <linux/delay.h>
35
36
37/* ================================================================
38 * CCE hardware state programming functions
39 */
40
41static void r128_emit_clip_rects( drm_r128_private_t *dev_priv,
42				  drm_clip_rect_t *boxes, int count )
43{
44	u32 aux_sc_cntl = 0x00000000;
45	RING_LOCALS;
46	DRM_DEBUG( "    %s\n", __FUNCTION__ );
47
48	BEGIN_RING( 17 );
49
50	if ( count >= 1 ) {
51		OUT_RING( CCE_PACKET0( R128_AUX1_SC_LEFT, 3 ) );
52		OUT_RING( boxes[0].x1 );
53		OUT_RING( boxes[0].x2 - 1 );
54		OUT_RING( boxes[0].y1 );
55		OUT_RING( boxes[0].y2 - 1 );
56
57		aux_sc_cntl |= (R128_AUX1_SC_EN | R128_AUX1_SC_MODE_OR);
58	}
59	if ( count >= 2 ) {
60		OUT_RING( CCE_PACKET0( R128_AUX2_SC_LEFT, 3 ) );
61		OUT_RING( boxes[1].x1 );
62		OUT_RING( boxes[1].x2 - 1 );
63		OUT_RING( boxes[1].y1 );
64		OUT_RING( boxes[1].y2 - 1 );
65
66		aux_sc_cntl |= (R128_AUX2_SC_EN | R128_AUX2_SC_MODE_OR);
67	}
68	if ( count >= 3 ) {
69		OUT_RING( CCE_PACKET0( R128_AUX3_SC_LEFT, 3 ) );
70		OUT_RING( boxes[2].x1 );
71		OUT_RING( boxes[2].x2 - 1 );
72		OUT_RING( boxes[2].y1 );
73		OUT_RING( boxes[2].y2 - 1 );
74
75		aux_sc_cntl |= (R128_AUX3_SC_EN | R128_AUX3_SC_MODE_OR);
76	}
77
78	OUT_RING( CCE_PACKET0( R128_AUX_SC_CNTL, 0 ) );
79	OUT_RING( aux_sc_cntl );
80
81	ADVANCE_RING();
82}
83
84static inline void r128_emit_core( drm_r128_private_t *dev_priv )
85{
86	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
87	drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
88	RING_LOCALS;
89	DRM_DEBUG( "    %s\n", __FUNCTION__ );
90
91	BEGIN_RING( 2 );
92
93	OUT_RING( CCE_PACKET0( R128_SCALE_3D_CNTL, 0 ) );
94	OUT_RING( ctx->scale_3d_cntl );
95
96	ADVANCE_RING();
97}
98
99static inline void r128_emit_context( drm_r128_private_t *dev_priv )
100{
101	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
102	drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
103	RING_LOCALS;
104	DRM_DEBUG( "    %s\n", __FUNCTION__ );
105
106	BEGIN_RING( 13 );
107
108	OUT_RING( CCE_PACKET0( R128_DST_PITCH_OFFSET_C, 11 ) );
109	OUT_RING( ctx->dst_pitch_offset_c );
110	OUT_RING( ctx->dp_gui_master_cntl_c );
111	OUT_RING( ctx->sc_top_left_c );
112	OUT_RING( ctx->sc_bottom_right_c );
113	OUT_RING( ctx->z_offset_c );
114	OUT_RING( ctx->z_pitch_c );
115	OUT_RING( ctx->z_sten_cntl_c );
116	OUT_RING( ctx->tex_cntl_c );
117	OUT_RING( ctx->misc_3d_state_cntl_reg );
118	OUT_RING( ctx->texture_clr_cmp_clr_c );
119	OUT_RING( ctx->texture_clr_cmp_msk_c );
120	OUT_RING( ctx->fog_color_c );
121
122	ADVANCE_RING();
123}
124
125static inline void r128_emit_setup( drm_r128_private_t *dev_priv )
126{
127	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
128	drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
129	RING_LOCALS;
130	DRM_DEBUG( "    %s\n", __FUNCTION__ );
131
132	BEGIN_RING( 3 );
133
134	OUT_RING( CCE_PACKET1( R128_SETUP_CNTL, R128_PM4_VC_FPU_SETUP ) );
135	OUT_RING( ctx->setup_cntl );
136	OUT_RING( ctx->pm4_vc_fpu_setup );
137
138	ADVANCE_RING();
139}
140
141static inline void r128_emit_masks( drm_r128_private_t *dev_priv )
142{
143	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
144	drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
145	RING_LOCALS;
146	DRM_DEBUG( "    %s\n", __FUNCTION__ );
147
148	BEGIN_RING( 5 );
149
150	OUT_RING( CCE_PACKET0( R128_DP_WRITE_MASK, 0 ) );
151	OUT_RING( ctx->dp_write_mask );
152
153	OUT_RING( CCE_PACKET0( R128_STEN_REF_MASK_C, 1 ) );
154	OUT_RING( ctx->sten_ref_mask_c );
155	OUT_RING( ctx->plane_3d_mask_c );
156
157	ADVANCE_RING();
158}
159
160static inline void r128_emit_window( drm_r128_private_t *dev_priv )
161{
162	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
163	drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
164	RING_LOCALS;
165	DRM_DEBUG( "    %s\n", __FUNCTION__ );
166
167	BEGIN_RING( 2 );
168
169	OUT_RING( CCE_PACKET0( R128_WINDOW_XY_OFFSET, 0 ) );
170	OUT_RING( ctx->window_xy_offset );
171
172	ADVANCE_RING();
173}
174
175static inline void r128_emit_tex0( drm_r128_private_t *dev_priv )
176{
177	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
178	drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
179	drm_r128_texture_regs_t *tex = &sarea_priv->tex_state[0];
180	int i;
181	RING_LOCALS;
182	DRM_DEBUG( "    %s\n", __FUNCTION__ );
183
184	BEGIN_RING( 7 + R128_MAX_TEXTURE_LEVELS );
185
186	OUT_RING( CCE_PACKET0( R128_PRIM_TEX_CNTL_C,
187			       2 + R128_MAX_TEXTURE_LEVELS ) );
188	OUT_RING( tex->tex_cntl );
189	OUT_RING( tex->tex_combine_cntl );
190	OUT_RING( ctx->tex_size_pitch_c );
191	for ( i = 0 ; i < R128_MAX_TEXTURE_LEVELS ; i++ ) {
192		OUT_RING( tex->tex_offset[i] );
193	}
194
195	OUT_RING( CCE_PACKET0( R128_CONSTANT_COLOR_C, 1 ) );
196	OUT_RING( ctx->constant_color_c );
197	OUT_RING( tex->tex_border_color );
198
199	ADVANCE_RING();
200}
201
202static inline void r128_emit_tex1( drm_r128_private_t *dev_priv )
203{
204	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
205	drm_r128_texture_regs_t *tex = &sarea_priv->tex_state[1];
206	int i;
207	RING_LOCALS;
208	DRM_DEBUG( "    %s\n", __FUNCTION__ );
209
210	BEGIN_RING( 5 + R128_MAX_TEXTURE_LEVELS );
211
212	OUT_RING( CCE_PACKET0( R128_SEC_TEX_CNTL_C,
213			       1 + R128_MAX_TEXTURE_LEVELS ) );
214	OUT_RING( tex->tex_cntl );
215	OUT_RING( tex->tex_combine_cntl );
216	for ( i = 0 ; i < R128_MAX_TEXTURE_LEVELS ; i++ ) {
217		OUT_RING( tex->tex_offset[i] );
218	}
219
220	OUT_RING( CCE_PACKET0( R128_SEC_TEXTURE_BORDER_COLOR_C, 0 ) );
221	OUT_RING( tex->tex_border_color );
222
223	ADVANCE_RING();
224}
225
226static inline void r128_emit_state( drm_r128_private_t *dev_priv )
227{
228	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
229	unsigned int dirty = sarea_priv->dirty;
230
231	DRM_DEBUG( "%s: dirty=0x%08x\n", __FUNCTION__, dirty );
232
233	if ( dirty & R128_UPLOAD_CORE ) {
234		r128_emit_core( dev_priv );
235		sarea_priv->dirty &= ~R128_UPLOAD_CORE;
236	}
237
238	if ( dirty & R128_UPLOAD_CONTEXT ) {
239		r128_emit_context( dev_priv );
240		sarea_priv->dirty &= ~R128_UPLOAD_CONTEXT;
241	}
242
243	if ( dirty & R128_UPLOAD_SETUP ) {
244		r128_emit_setup( dev_priv );
245		sarea_priv->dirty &= ~R128_UPLOAD_SETUP;
246	}
247
248	if ( dirty & R128_UPLOAD_MASKS ) {
249		r128_emit_masks( dev_priv );
250		sarea_priv->dirty &= ~R128_UPLOAD_MASKS;
251	}
252
253	if ( dirty & R128_UPLOAD_WINDOW ) {
254		r128_emit_window( dev_priv );
255		sarea_priv->dirty &= ~R128_UPLOAD_WINDOW;
256	}
257
258	if ( dirty & R128_UPLOAD_TEX0 ) {
259		r128_emit_tex0( dev_priv );
260		sarea_priv->dirty &= ~R128_UPLOAD_TEX0;
261	}
262
263	if ( dirty & R128_UPLOAD_TEX1 ) {
264		r128_emit_tex1( dev_priv );
265		sarea_priv->dirty &= ~R128_UPLOAD_TEX1;
266	}
267
268	/* Turn off the texture cache flushing */
269	sarea_priv->context_state.tex_cntl_c &= ~R128_TEX_CACHE_FLUSH;
270
271	sarea_priv->dirty &= ~R128_REQUIRE_QUIESCENCE;
272}
273
274
275#if R128_PERFORMANCE_BOXES
276/* ================================================================
277 * Performance monitoring functions
278 */
279
280static void r128_clear_box( drm_r128_private_t *dev_priv,
281			    int x, int y, int w, int h,
282			    int r, int g, int b )
283{
284	u32 pitch, offset;
285	u32 fb_bpp, color;
286	RING_LOCALS;
287
288	switch ( dev_priv->fb_bpp ) {
289	case 16:
290		fb_bpp = R128_GMC_DST_16BPP;
291		color = (((r & 0xf8) << 8) |
292			 ((g & 0xfc) << 3) |
293			 ((b & 0xf8) >> 3));
294		break;
295	case 24:
296		fb_bpp = R128_GMC_DST_24BPP;
297		color = ((r << 16) | (g << 8) | b);
298		break;
299	case 32:
300		fb_bpp = R128_GMC_DST_32BPP;
301		color = (((0xff) << 24) | (r << 16) | (g <<  8) | b);
302		break;
303	default:
304		return;
305	}
306
307	offset = dev_priv->back_offset;
308	pitch = dev_priv->back_pitch >> 3;
309
310	BEGIN_RING( 6 );
311
312	OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
313	OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
314		  R128_GMC_BRUSH_SOLID_COLOR |
315		  fb_bpp |
316		  R128_GMC_SRC_DATATYPE_COLOR |
317		  R128_ROP3_P |
318		  R128_GMC_CLR_CMP_CNTL_DIS |
319		  R128_GMC_AUX_CLIP_DIS );
320
321	OUT_RING( (pitch << 21) | (offset >> 5) );
322	OUT_RING( color );
323
324	OUT_RING( (x << 16) | y );
325	OUT_RING( (w << 16) | h );
326
327	ADVANCE_RING();
328}
329
330static void r128_cce_performance_boxes( drm_r128_private_t *dev_priv )
331{
332	if ( atomic_read( &dev_priv->idle_count ) == 0 ) {
333		r128_clear_box( dev_priv, 64, 4, 8, 8, 0, 255, 0 );
334	} else {
335		atomic_set( &dev_priv->idle_count, 0 );
336	}
337}
338
339#endif
340
341
342/* ================================================================
343 * CCE command dispatch functions
344 */
345
346static void r128_print_dirty( const char *msg, unsigned int flags )
347{
348	DRM_INFO( "%s: (0x%x) %s%s%s%s%s%s%s%s%s\n",
349		  msg,
350		  flags,
351		  (flags & R128_UPLOAD_CORE)        ? "core, " : "",
352		  (flags & R128_UPLOAD_CONTEXT)     ? "context, " : "",
353		  (flags & R128_UPLOAD_SETUP)       ? "setup, " : "",
354		  (flags & R128_UPLOAD_TEX0)        ? "tex0, " : "",
355		  (flags & R128_UPLOAD_TEX1)        ? "tex1, " : "",
356		  (flags & R128_UPLOAD_MASKS)       ? "masks, " : "",
357		  (flags & R128_UPLOAD_WINDOW)      ? "window, " : "",
358		  (flags & R128_UPLOAD_CLIPRECTS)   ? "cliprects, " : "",
359		  (flags & R128_REQUIRE_QUIESCENCE) ? "quiescence, " : "" );
360}
361
362static void r128_cce_dispatch_clear( drm_device_t *dev,
363				     drm_r128_clear_t *clear )
364{
365	drm_r128_private_t *dev_priv = dev->dev_private;
366	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
367	int nbox = sarea_priv->nbox;
368	drm_clip_rect_t *pbox = sarea_priv->boxes;
369	unsigned int flags = clear->flags;
370	int i;
371	RING_LOCALS;
372	DRM_DEBUG( "%s\n", __FUNCTION__ );
373
374	if ( dev_priv->page_flipping && dev_priv->current_page == 1 ) {
375		unsigned int tmp = flags;
376
377		flags &= ~(R128_FRONT | R128_BACK);
378		if ( tmp & R128_FRONT ) flags |= R128_BACK;
379		if ( tmp & R128_BACK )  flags |= R128_FRONT;
380	}
381
382	for ( i = 0 ; i < nbox ; i++ ) {
383		int x = pbox[i].x1;
384		int y = pbox[i].y1;
385		int w = pbox[i].x2 - x;
386		int h = pbox[i].y2 - y;
387
388		DRM_DEBUG( "dispatch clear %d,%d-%d,%d flags 0x%x\n",
389			   pbox[i].x1, pbox[i].y1, pbox[i].x2,
390			   pbox[i].y2, flags );
391
392		if ( flags & (R128_FRONT | R128_BACK) ) {
393			BEGIN_RING( 2 );
394
395			OUT_RING( CCE_PACKET0( R128_DP_WRITE_MASK, 0 ) );
396			OUT_RING( clear->color_mask );
397
398			ADVANCE_RING();
399		}
400
401		if ( flags & R128_FRONT ) {
402			BEGIN_RING( 6 );
403
404			OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
405			OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
406				  R128_GMC_BRUSH_SOLID_COLOR |
407				  (dev_priv->color_fmt << 8) |
408				  R128_GMC_SRC_DATATYPE_COLOR |
409				  R128_ROP3_P |
410				  R128_GMC_CLR_CMP_CNTL_DIS |
411				  R128_GMC_AUX_CLIP_DIS );
412
413			OUT_RING( dev_priv->front_pitch_offset_c );
414			OUT_RING( clear->clear_color );
415
416			OUT_RING( (x << 16) | y );
417			OUT_RING( (w << 16) | h );
418
419			ADVANCE_RING();
420		}
421
422		if ( flags & R128_BACK ) {
423			BEGIN_RING( 6 );
424
425			OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
426			OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
427				  R128_GMC_BRUSH_SOLID_COLOR |
428				  (dev_priv->color_fmt << 8) |
429				  R128_GMC_SRC_DATATYPE_COLOR |
430				  R128_ROP3_P |
431				  R128_GMC_CLR_CMP_CNTL_DIS |
432				  R128_GMC_AUX_CLIP_DIS );
433
434			OUT_RING( dev_priv->back_pitch_offset_c );
435			OUT_RING( clear->clear_color );
436
437			OUT_RING( (x << 16) | y );
438			OUT_RING( (w << 16) | h );
439
440			ADVANCE_RING();
441		}
442
443		if ( flags & R128_DEPTH ) {
444			BEGIN_RING( 6 );
445
446			OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
447			OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
448				  R128_GMC_BRUSH_SOLID_COLOR |
449				  (dev_priv->depth_fmt << 8) |
450				  R128_GMC_SRC_DATATYPE_COLOR |
451				  R128_ROP3_P |
452				  R128_GMC_CLR_CMP_CNTL_DIS |
453				  R128_GMC_AUX_CLIP_DIS |
454				  R128_GMC_WR_MSK_DIS );
455
456			OUT_RING( dev_priv->depth_pitch_offset_c );
457			OUT_RING( clear->clear_depth );
458
459			OUT_RING( (x << 16) | y );
460			OUT_RING( (w << 16) | h );
461
462			ADVANCE_RING();
463		}
464	}
465}
466
467static void r128_cce_dispatch_swap( drm_device_t *dev )
468{
469	drm_r128_private_t *dev_priv = dev->dev_private;
470	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
471	int nbox = sarea_priv->nbox;
472	drm_clip_rect_t *pbox = sarea_priv->boxes;
473	int i;
474	RING_LOCALS;
475	DRM_DEBUG( "%s\n", __FUNCTION__ );
476
477#if R128_PERFORMANCE_BOXES
478	/* Do some trivial performance monitoring...
479	 */
480	r128_cce_performance_boxes( dev_priv );
481#endif
482
483	for ( i = 0 ; i < nbox ; i++ ) {
484		int x = pbox[i].x1;
485		int y = pbox[i].y1;
486		int w = pbox[i].x2 - x;
487		int h = pbox[i].y2 - y;
488
489		BEGIN_RING( 7 );
490
491		OUT_RING( CCE_PACKET3( R128_CNTL_BITBLT_MULTI, 5 ) );
492		OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL |
493			  R128_GMC_DST_PITCH_OFFSET_CNTL |
494			  R128_GMC_BRUSH_NONE |
495			  (dev_priv->color_fmt << 8) |
496			  R128_GMC_SRC_DATATYPE_COLOR |
497			  R128_ROP3_S |
498			  R128_DP_SRC_SOURCE_MEMORY |
499			  R128_GMC_CLR_CMP_CNTL_DIS |
500			  R128_GMC_AUX_CLIP_DIS |
501			  R128_GMC_WR_MSK_DIS );
502
503		OUT_RING( dev_priv->back_pitch_offset_c );
504		OUT_RING( dev_priv->front_pitch_offset_c );
505
506		OUT_RING( (x << 16) | y );
507		OUT_RING( (x << 16) | y );
508		OUT_RING( (w << 16) | h );
509
510		ADVANCE_RING();
511	}
512
513	/* Increment the frame counter.  The client-side 3D driver must
514	 * throttle the framerate by waiting for this value before
515	 * performing the swapbuffer ioctl.
516	 */
517	dev_priv->sarea_priv->last_frame++;
518
519	BEGIN_RING( 2 );
520
521	OUT_RING( CCE_PACKET0( R128_LAST_FRAME_REG, 0 ) );
522	OUT_RING( dev_priv->sarea_priv->last_frame );
523
524	ADVANCE_RING();
525}
526
527static void r128_cce_dispatch_flip( drm_device_t *dev )
528{
529	drm_r128_private_t *dev_priv = dev->dev_private;
530	RING_LOCALS;
531	DRM_DEBUG( "%s: page=%d\n", __FUNCTION__, dev_priv->current_page );
532
533#if R128_PERFORMANCE_BOXES
534	/* Do some trivial performance monitoring...
535	 */
536	r128_cce_performance_boxes( dev_priv );
537#endif
538
539	BEGIN_RING( 4 );
540
541	R128_WAIT_UNTIL_PAGE_FLIPPED();
542	OUT_RING( CCE_PACKET0( R128_CRTC_OFFSET, 0 ) );
543
544	if ( dev_priv->current_page == 0 ) {
545		OUT_RING( dev_priv->back_offset );
546		dev_priv->current_page = 1;
547	} else {
548		OUT_RING( dev_priv->front_offset );
549		dev_priv->current_page = 0;
550	}
551
552	ADVANCE_RING();
553
554	/* Increment the frame counter.  The client-side 3D driver must
555	 * throttle the framerate by waiting for this value before
556	 * performing the swapbuffer ioctl.
557	 */
558	dev_priv->sarea_priv->last_frame++;
559
560	BEGIN_RING( 2 );
561
562	OUT_RING( CCE_PACKET0( R128_LAST_FRAME_REG, 0 ) );
563	OUT_RING( dev_priv->sarea_priv->last_frame );
564
565	ADVANCE_RING();
566}
567
568static void r128_cce_dispatch_vertex( drm_device_t *dev,
569				      drm_buf_t *buf )
570{
571	drm_r128_private_t *dev_priv = dev->dev_private;
572	drm_r128_buf_priv_t *buf_priv = buf->dev_private;
573	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
574	int format = sarea_priv->vc_format;
575	int offset = buf->bus_address;
576	int size = buf->used;
577	int prim = buf_priv->prim;
578	int i = 0;
579	RING_LOCALS;
580	DRM_DEBUG( "%s: buf=%d nbox=%d\n",
581		   __FUNCTION__, buf->idx, sarea_priv->nbox );
582
583	if ( 0 )
584		r128_print_dirty( "dispatch_vertex", sarea_priv->dirty );
585
586	if ( buf->used ) {
587		buf_priv->dispatched = 1;
588
589		if ( sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS ) {
590			r128_emit_state( dev_priv );
591		}
592
593		do {
594			/* Emit the next set of up to three cliprects */
595			if ( i < sarea_priv->nbox ) {
596				r128_emit_clip_rects( dev_priv,
597						      &sarea_priv->boxes[i],
598						      sarea_priv->nbox - i );
599			}
600
601			/* Emit the vertex buffer rendering commands */
602			BEGIN_RING( 5 );
603
604			OUT_RING( CCE_PACKET3( R128_3D_RNDR_GEN_INDX_PRIM, 3 ) );
605			OUT_RING( offset );
606			OUT_RING( size );
607			OUT_RING( format );
608			OUT_RING( prim | R128_CCE_VC_CNTL_PRIM_WALK_LIST |
609				  (size << R128_CCE_VC_CNTL_NUM_SHIFT) );
610
611			ADVANCE_RING();
612
613			i += 3;
614		} while ( i < sarea_priv->nbox );
615	}
616
617	if ( buf_priv->discard ) {
618		buf_priv->age = dev_priv->sarea_priv->last_dispatch;
619
620		/* Emit the vertex buffer age */
621		BEGIN_RING( 2 );
622
623		OUT_RING( CCE_PACKET0( R128_LAST_DISPATCH_REG, 0 ) );
624		OUT_RING( buf_priv->age );
625
626		ADVANCE_RING();
627
628		buf->pending = 1;
629		buf->used = 0;
630		buf_priv->dispatched = 0;
631	}
632
633	dev_priv->sarea_priv->last_dispatch++;
634
635	sarea_priv->dirty &= ~R128_UPLOAD_CLIPRECTS;
636	sarea_priv->nbox = 0;
637}
638
639static void r128_cce_dispatch_indirect( drm_device_t *dev,
640					drm_buf_t *buf,
641					int start, int end )
642{
643	drm_r128_private_t *dev_priv = dev->dev_private;
644	drm_r128_buf_priv_t *buf_priv = buf->dev_private;
645	RING_LOCALS;
646	DRM_DEBUG( "indirect: buf=%d s=0x%x e=0x%x\n",
647		   buf->idx, start, end );
648
649	if ( start != end ) {
650		int offset = buf->bus_address + start;
651		int dwords = (end - start + 3) / sizeof(u32);
652
653		/* Indirect buffer data must be an even number of
654		 * dwords, so if we've been given an odd number we must
655		 * pad the data with a Type-2 CCE packet.
656		 */
657		if ( dwords & 1 ) {
658			u32 *data = (u32 *)
659				((char *)dev_priv->buffers->handle
660				 + buf->offset + start);
661			data[dwords++] = cpu_to_le32( R128_CCE_PACKET2 );
662		}
663
664		buf_priv->dispatched = 1;
665
666		/* Fire off the indirect buffer */
667		BEGIN_RING( 3 );
668
669		OUT_RING( CCE_PACKET0( R128_PM4_IW_INDOFF, 1 ) );
670		OUT_RING( offset );
671		OUT_RING( dwords );
672
673		ADVANCE_RING();
674	}
675
676	if ( buf_priv->discard ) {
677		buf_priv->age = dev_priv->sarea_priv->last_dispatch;
678
679		/* Emit the indirect buffer age */
680		BEGIN_RING( 2 );
681
682		OUT_RING( CCE_PACKET0( R128_LAST_DISPATCH_REG, 0 ) );
683		OUT_RING( buf_priv->age );
684
685		ADVANCE_RING();
686
687		buf->pending = 1;
688		buf->used = 0;
689		buf_priv->dispatched = 0;
690	}
691
692	dev_priv->sarea_priv->last_dispatch++;
693}
694
695static void r128_cce_dispatch_indices( drm_device_t *dev,
696				       drm_buf_t *buf,
697				       int start, int end,
698				       int count )
699{
700	drm_r128_private_t *dev_priv = dev->dev_private;
701	drm_r128_buf_priv_t *buf_priv = buf->dev_private;
702	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
703	int format = sarea_priv->vc_format;
704	int offset = dev_priv->buffers->offset - dev_priv->cce_buffers_offset;
705	int prim = buf_priv->prim;
706	u32 *data;
707	int dwords;
708	int i = 0;
709	RING_LOCALS;
710	DRM_DEBUG( "indices: s=%d e=%d c=%d\n", start, end, count );
711
712	if ( 0 )
713		r128_print_dirty( "dispatch_indices", sarea_priv->dirty );
714
715	if ( start != end ) {
716		buf_priv->dispatched = 1;
717
718		if ( sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS ) {
719			r128_emit_state( dev_priv );
720		}
721
722		dwords = (end - start + 3) / sizeof(u32);
723
724		data = (u32 *)((char *)dev_priv->buffers->handle
725			       + buf->offset + start);
726
727		data[0] = cpu_to_le32( CCE_PACKET3( R128_3D_RNDR_GEN_INDX_PRIM,
728						    dwords-2 ) );
729
730		data[1] = cpu_to_le32( offset );
731		data[2] = cpu_to_le32( R128_MAX_VB_VERTS );
732		data[3] = cpu_to_le32( format );
733		data[4] = cpu_to_le32( (prim | R128_CCE_VC_CNTL_PRIM_WALK_IND |
734					(count << 16)) );
735
736		if ( count & 0x1 ) {
737#ifdef __LITTLE_ENDIAN
738			data[dwords-1] &= 0x0000ffff;
739#else
740			data[dwords-1] &= 0xffff0000;
741#endif
742		}
743
744		do {
745			/* Emit the next set of up to three cliprects */
746			if ( i < sarea_priv->nbox ) {
747				r128_emit_clip_rects( dev_priv,
748						      &sarea_priv->boxes[i],
749						      sarea_priv->nbox - i );
750			}
751
752			r128_cce_dispatch_indirect( dev, buf, start, end );
753
754			i += 3;
755		} while ( i < sarea_priv->nbox );
756	}
757
758	if ( buf_priv->discard ) {
759		buf_priv->age = dev_priv->sarea_priv->last_dispatch;
760
761		/* Emit the vertex buffer age */
762		BEGIN_RING( 2 );
763
764		OUT_RING( CCE_PACKET0( R128_LAST_DISPATCH_REG, 0 ) );
765		OUT_RING( buf_priv->age );
766
767		ADVANCE_RING();
768
769		buf->pending = 1;
770		buf_priv->dispatched = 0;
771	}
772
773	dev_priv->sarea_priv->last_dispatch++;
774
775	sarea_priv->dirty &= ~R128_UPLOAD_CLIPRECTS;
776	sarea_priv->nbox = 0;
777}
778
779static int r128_cce_dispatch_blit( drm_device_t *dev,
780				   drm_r128_blit_t *blit )
781{
782	drm_r128_private_t *dev_priv = dev->dev_private;
783	drm_device_dma_t *dma = dev->dma;
784	drm_buf_t *buf;
785	drm_r128_buf_priv_t *buf_priv;
786	u32 *data;
787	int dword_shift, dwords;
788	RING_LOCALS;
789	DRM_DEBUG( "%s\n", __FUNCTION__ );
790
791	/* The compiler won't optimize away a division by a variable,
792	 * even if the only legal values are powers of two.  Thus, we'll
793	 * use a shift instead.
794	 */
795	switch ( blit->format ) {
796	case R128_DATATYPE_ARGB8888:
797		dword_shift = 0;
798		break;
799	case R128_DATATYPE_ARGB1555:
800	case R128_DATATYPE_RGB565:
801	case R128_DATATYPE_ARGB4444:
802		dword_shift = 1;
803		break;
804	case R128_DATATYPE_CI8:
805	case R128_DATATYPE_RGB8:
806		dword_shift = 2;
807		break;
808	default:
809		DRM_ERROR( "invalid blit format %d\n", blit->format );
810		return -EINVAL;
811	}
812
813	/* Flush the pixel cache, and mark the contents as Read Invalid.
814	 * This ensures no pixel data gets mixed up with the texture
815	 * data from the host data blit, otherwise part of the texture
816	 * image may be corrupted.
817	 */
818	BEGIN_RING( 2 );
819
820	OUT_RING( CCE_PACKET0( R128_PC_GUI_CTLSTAT, 0 ) );
821	OUT_RING( R128_PC_RI_GUI | R128_PC_FLUSH_GUI );
822
823	ADVANCE_RING();
824
825	/* Dispatch the indirect buffer.
826	 */
827	buf = dma->buflist[blit->idx];
828	buf_priv = buf->dev_private;
829
830	if ( buf->pid != current->pid ) {
831		DRM_ERROR( "process %d using buffer owned by %d\n",
832			   current->pid, buf->pid );
833		return -EINVAL;
834	}
835	if ( buf->pending ) {
836		DRM_ERROR( "sending pending buffer %d\n", blit->idx );
837		return -EINVAL;
838	}
839
840	buf_priv->discard = 1;
841
842	dwords = (blit->width * blit->height) >> dword_shift;
843
844	data = (u32 *)((char *)dev_priv->buffers->handle + buf->offset);
845
846	data[0] = cpu_to_le32( CCE_PACKET3( R128_CNTL_HOSTDATA_BLT, dwords + 6 ) );
847	data[1] = cpu_to_le32( (R128_GMC_DST_PITCH_OFFSET_CNTL |
848				R128_GMC_BRUSH_NONE |
849				(blit->format << 8) |
850				R128_GMC_SRC_DATATYPE_COLOR |
851				R128_ROP3_S |
852				R128_DP_SRC_SOURCE_HOST_DATA |
853				R128_GMC_CLR_CMP_CNTL_DIS |
854				R128_GMC_AUX_CLIP_DIS |
855				R128_GMC_WR_MSK_DIS) );
856
857	data[2] = cpu_to_le32( (blit->pitch << 21) | (blit->offset >> 5) );
858	data[3] = cpu_to_le32( 0xffffffff );
859	data[4] = cpu_to_le32( 0xffffffff );
860	data[5] = cpu_to_le32( (blit->y << 16) | blit->x );
861	data[6] = cpu_to_le32( (blit->height << 16) | blit->width );
862	data[7] = cpu_to_le32( dwords );
863
864	buf->used = (dwords + 8) * sizeof(u32);
865
866	r128_cce_dispatch_indirect( dev, buf, 0, buf->used );
867
868	/* Flush the pixel cache after the blit completes.  This ensures
869	 * the texture data is written out to memory before rendering
870	 * continues.
871	 */
872	BEGIN_RING( 2 );
873
874	OUT_RING( CCE_PACKET0( R128_PC_GUI_CTLSTAT, 0 ) );
875	OUT_RING( R128_PC_FLUSH_GUI );
876
877	ADVANCE_RING();
878
879	return 0;
880}
881
882
883
884static int r128_cce_dispatch_write_span( drm_device_t *dev,
885					 drm_r128_depth_t *depth )
886{
887	drm_r128_private_t *dev_priv = dev->dev_private;
888	int count, x, y;
889	u32 *buffer;
890	u8 *mask;
891	int i;
892	RING_LOCALS;
893	DRM_DEBUG( "%s\n", __FUNCTION__ );
894
895	count = depth->n;
896	if ( copy_from_user( &x, depth->x, sizeof(x) ) ) {
897		return -EFAULT;
898	}
899	if ( copy_from_user( &y, depth->y, sizeof(y) ) ) {
900		return -EFAULT;
901	}
902
903	buffer = kmalloc( depth->n * sizeof(u32), GFP_KERNEL );
904	if ( buffer == NULL )
905		return -ENOMEM;
906	if ( copy_from_user( buffer, depth->buffer,
907			     depth->n * sizeof(u32) ) ) {
908		kfree( buffer );
909		return -EFAULT;
910	}
911
912	if ( depth->mask ) {
913		mask = kmalloc( depth->n * sizeof(u8), GFP_KERNEL );
914		if ( mask == NULL ) {
915			kfree( buffer );
916			return -ENOMEM;
917		}
918		if ( copy_from_user( mask, depth->mask,
919				     depth->n * sizeof(u8) ) ) {
920			kfree( buffer );
921			kfree( mask );
922			return -EFAULT;
923		}
924
925		for ( i = 0 ; i < count ; i++, x++ ) {
926			if ( mask[i] ) {
927				BEGIN_RING( 6 );
928
929				OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
930				OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
931					  R128_GMC_BRUSH_SOLID_COLOR |
932					  (dev_priv->depth_fmt << 8) |
933					  R128_GMC_SRC_DATATYPE_COLOR |
934					  R128_ROP3_P |
935					  R128_GMC_CLR_CMP_CNTL_DIS |
936					  R128_GMC_WR_MSK_DIS );
937
938				OUT_RING( dev_priv->depth_pitch_offset_c );
939				OUT_RING( buffer[i] );
940
941				OUT_RING( (x << 16) | y );
942				OUT_RING( (1 << 16) | 1 );
943
944				ADVANCE_RING();
945			}
946		}
947
948		kfree( mask );
949	} else {
950		for ( i = 0 ; i < count ; i++, x++ ) {
951			BEGIN_RING( 6 );
952
953			OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
954			OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
955				  R128_GMC_BRUSH_SOLID_COLOR |
956				  (dev_priv->depth_fmt << 8) |
957				  R128_GMC_SRC_DATATYPE_COLOR |
958				  R128_ROP3_P |
959				  R128_GMC_CLR_CMP_CNTL_DIS |
960				  R128_GMC_WR_MSK_DIS );
961
962			OUT_RING( dev_priv->depth_pitch_offset_c );
963			OUT_RING( buffer[i] );
964
965			OUT_RING( (x << 16) | y );
966			OUT_RING( (1 << 16) | 1 );
967
968			ADVANCE_RING();
969		}
970	}
971
972	kfree( buffer );
973
974	return 0;
975}
976
977static int r128_cce_dispatch_write_pixels( drm_device_t *dev,
978					   drm_r128_depth_t *depth )
979{
980	drm_r128_private_t *dev_priv = dev->dev_private;
981	int count, *x, *y;
982	u32 *buffer;
983	u8 *mask;
984	int i;
985	RING_LOCALS;
986	DRM_DEBUG( "%s\n", __FUNCTION__ );
987
988	count = depth->n;
989
990	x = kmalloc( count * sizeof(*x), GFP_KERNEL );
991	if ( x == NULL ) {
992		return -ENOMEM;
993	}
994	y = kmalloc( count * sizeof(*y), GFP_KERNEL );
995	if ( y == NULL ) {
996		kfree( x );
997		return -ENOMEM;
998	}
999	if ( copy_from_user( x, depth->x, count * sizeof(int) ) ) {
1000		kfree( x );
1001		kfree( y );
1002		return -EFAULT;
1003	}
1004	if ( copy_from_user( y, depth->y, count * sizeof(int) ) ) {
1005		kfree( x );
1006		kfree( y );
1007		return -EFAULT;
1008	}
1009
1010	buffer = kmalloc( depth->n * sizeof(u32), GFP_KERNEL );
1011	if ( buffer == NULL ) {
1012		kfree( x );
1013		kfree( y );
1014		return -ENOMEM;
1015	}
1016	if ( copy_from_user( buffer, depth->buffer,
1017			     depth->n * sizeof(u32) ) ) {
1018		kfree( x );
1019		kfree( y );
1020		kfree( buffer );
1021		return -EFAULT;
1022	}
1023
1024	if ( depth->mask ) {
1025		mask = kmalloc( depth->n * sizeof(u8), GFP_KERNEL );
1026		if ( mask == NULL ) {
1027			kfree( x );
1028			kfree( y );
1029			kfree( buffer );
1030			return -ENOMEM;
1031		}
1032		if ( copy_from_user( mask, depth->mask,
1033				     depth->n * sizeof(u8) ) ) {
1034			kfree( x );
1035			kfree( y );
1036			kfree( buffer );
1037			kfree( mask );
1038			return -EFAULT;
1039		}
1040
1041		for ( i = 0 ; i < count ; i++ ) {
1042			if ( mask[i] ) {
1043				BEGIN_RING( 6 );
1044
1045				OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
1046				OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
1047					  R128_GMC_BRUSH_SOLID_COLOR |
1048					  (dev_priv->depth_fmt << 8) |
1049					  R128_GMC_SRC_DATATYPE_COLOR |
1050					  R128_ROP3_P |
1051					  R128_GMC_CLR_CMP_CNTL_DIS |
1052					  R128_GMC_WR_MSK_DIS );
1053
1054				OUT_RING( dev_priv->depth_pitch_offset_c );
1055				OUT_RING( buffer[i] );
1056
1057				OUT_RING( (x[i] << 16) | y[i] );
1058				OUT_RING( (1 << 16) | 1 );
1059
1060				ADVANCE_RING();
1061			}
1062		}
1063
1064		kfree( mask );
1065	} else {
1066		for ( i = 0 ; i < count ; i++ ) {
1067			BEGIN_RING( 6 );
1068
1069			OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
1070			OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
1071				  R128_GMC_BRUSH_SOLID_COLOR |
1072				  (dev_priv->depth_fmt << 8) |
1073				  R128_GMC_SRC_DATATYPE_COLOR |
1074				  R128_ROP3_P |
1075				  R128_GMC_CLR_CMP_CNTL_DIS |
1076				  R128_GMC_WR_MSK_DIS );
1077
1078			OUT_RING( dev_priv->depth_pitch_offset_c );
1079			OUT_RING( buffer[i] );
1080
1081			OUT_RING( (x[i] << 16) | y[i] );
1082			OUT_RING( (1 << 16) | 1 );
1083
1084			ADVANCE_RING();
1085		}
1086	}
1087
1088	kfree( x );
1089	kfree( y );
1090	kfree( buffer );
1091
1092	return 0;
1093}
1094
1095static int r128_cce_dispatch_read_span( drm_device_t *dev,
1096					drm_r128_depth_t *depth )
1097{
1098	drm_r128_private_t *dev_priv = dev->dev_private;
1099	int count, x, y;
1100	RING_LOCALS;
1101	DRM_DEBUG( "%s\n", __FUNCTION__ );
1102
1103	count = depth->n;
1104	if ( copy_from_user( &x, depth->x, sizeof(x) ) ) {
1105		return -EFAULT;
1106	}
1107	if ( copy_from_user( &y, depth->y, sizeof(y) ) ) {
1108		return -EFAULT;
1109	}
1110
1111	BEGIN_RING( 7 );
1112
1113	OUT_RING( CCE_PACKET3( R128_CNTL_BITBLT_MULTI, 5 ) );
1114	OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL |
1115		  R128_GMC_DST_PITCH_OFFSET_CNTL |
1116		  R128_GMC_BRUSH_NONE |
1117		  (dev_priv->depth_fmt << 8) |
1118		  R128_GMC_SRC_DATATYPE_COLOR |
1119		  R128_ROP3_S |
1120		  R128_DP_SRC_SOURCE_MEMORY |
1121		  R128_GMC_CLR_CMP_CNTL_DIS |
1122		  R128_GMC_WR_MSK_DIS );
1123
1124	OUT_RING( dev_priv->depth_pitch_offset_c );
1125	OUT_RING( dev_priv->span_pitch_offset_c );
1126
1127	OUT_RING( (x << 16) | y );
1128	OUT_RING( (0 << 16) | 0 );
1129	OUT_RING( (count << 16) | 1 );
1130
1131	ADVANCE_RING();
1132
1133	return 0;
1134}
1135
1136static int r128_cce_dispatch_read_pixels( drm_device_t *dev,
1137					  drm_r128_depth_t *depth )
1138{
1139	drm_r128_private_t *dev_priv = dev->dev_private;
1140	int count, *x, *y;
1141	int i;
1142	RING_LOCALS;
1143	DRM_DEBUG( "%s\n", __FUNCTION__ );
1144
1145	count = depth->n;
1146	if ( count > dev_priv->depth_pitch ) {
1147		count = dev_priv->depth_pitch;
1148	}
1149
1150	x = kmalloc( count * sizeof(*x), GFP_KERNEL );
1151	if ( x == NULL ) {
1152		return -ENOMEM;
1153	}
1154	y = kmalloc( count * sizeof(*y), GFP_KERNEL );
1155	if ( y == NULL ) {
1156		kfree( x );
1157		return -ENOMEM;
1158	}
1159	if ( copy_from_user( x, depth->x, count * sizeof(int) ) ) {
1160		kfree( x );
1161		kfree( y );
1162		return -EFAULT;
1163	}
1164	if ( copy_from_user( y, depth->y, count * sizeof(int) ) ) {
1165		kfree( x );
1166		kfree( y );
1167		return -EFAULT;
1168	}
1169
1170	for ( i = 0 ; i < count ; i++ ) {
1171		BEGIN_RING( 7 );
1172
1173		OUT_RING( CCE_PACKET3( R128_CNTL_BITBLT_MULTI, 5 ) );
1174		OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL |
1175			  R128_GMC_DST_PITCH_OFFSET_CNTL |
1176			  R128_GMC_BRUSH_NONE |
1177			  (dev_priv->depth_fmt << 8) |
1178			  R128_GMC_SRC_DATATYPE_COLOR |
1179			  R128_ROP3_S |
1180			  R128_DP_SRC_SOURCE_MEMORY |
1181			  R128_GMC_CLR_CMP_CNTL_DIS |
1182			  R128_GMC_WR_MSK_DIS );
1183
1184		OUT_RING( dev_priv->depth_pitch_offset_c );
1185		OUT_RING( dev_priv->span_pitch_offset_c );
1186
1187		OUT_RING( (x[i] << 16) | y[i] );
1188		OUT_RING( (i << 16) | 0 );
1189		OUT_RING( (1 << 16) | 1 );
1190
1191		ADVANCE_RING();
1192	}
1193
1194	kfree( x );
1195	kfree( y );
1196
1197	return 0;
1198}
1199
1200
1201/* ================================================================
1202 * Polygon stipple
1203 */
1204
1205static void r128_cce_dispatch_stipple( drm_device_t *dev, u32 *stipple )
1206{
1207	drm_r128_private_t *dev_priv = dev->dev_private;
1208	int i;
1209	RING_LOCALS;
1210	DRM_DEBUG( "%s\n", __FUNCTION__ );
1211
1212	BEGIN_RING( 33 );
1213
1214	OUT_RING( CCE_PACKET0( R128_BRUSH_DATA0, 31 ) );
1215	for ( i = 0 ; i < 32 ; i++ ) {
1216		OUT_RING( stipple[i] );
1217	}
1218
1219	ADVANCE_RING();
1220}
1221
1222
1223/* ================================================================
1224 * IOCTL functions
1225 */
1226
1227int r128_cce_clear( struct inode *inode, struct file *filp,
1228		    unsigned int cmd, unsigned long arg )
1229{
1230	drm_file_t *priv = filp->private_data;
1231	drm_device_t *dev = priv->dev;
1232	drm_r128_private_t *dev_priv = dev->dev_private;
1233	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
1234	drm_r128_clear_t clear;
1235	DRM_DEBUG( "%s\n", __FUNCTION__ );
1236
1237	LOCK_TEST_WITH_RETURN( dev );
1238
1239	if ( copy_from_user( &clear, (drm_r128_clear_t *) arg,
1240			     sizeof(clear) ) )
1241		return -EFAULT;
1242
1243	RING_SPACE_TEST_WITH_RETURN( dev_priv );
1244
1245	if ( sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS )
1246		sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS;
1247
1248	r128_cce_dispatch_clear( dev, &clear );
1249
1250	/* Make sure we restore the 3D state next time.
1251	 */
1252	dev_priv->sarea_priv->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_MASKS;
1253
1254	return 0;
1255}
1256
1257int r128_cce_swap( struct inode *inode, struct file *filp,
1258		   unsigned int cmd, unsigned long arg )
1259{
1260	drm_file_t *priv = filp->private_data;
1261	drm_device_t *dev = priv->dev;
1262	drm_r128_private_t *dev_priv = dev->dev_private;
1263	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
1264	DRM_DEBUG( "%s\n", __FUNCTION__ );
1265
1266	LOCK_TEST_WITH_RETURN( dev );
1267
1268	RING_SPACE_TEST_WITH_RETURN( dev_priv );
1269
1270	if ( sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS )
1271		sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS;
1272
1273	if ( !dev_priv->page_flipping ) {
1274		r128_cce_dispatch_swap( dev );
1275		dev_priv->sarea_priv->dirty |= (R128_UPLOAD_CONTEXT |
1276						R128_UPLOAD_MASKS);
1277	} else {
1278		r128_cce_dispatch_flip( dev );
1279	}
1280
1281	return 0;
1282}
1283
1284int r128_cce_vertex( struct inode *inode, struct file *filp,
1285		     unsigned int cmd, unsigned long arg )
1286{
1287	drm_file_t *priv = filp->private_data;
1288	drm_device_t *dev = priv->dev;
1289	drm_r128_private_t *dev_priv = dev->dev_private;
1290	drm_device_dma_t *dma = dev->dma;
1291	drm_buf_t *buf;
1292	drm_r128_buf_priv_t *buf_priv;
1293	drm_r128_vertex_t vertex;
1294
1295	LOCK_TEST_WITH_RETURN( dev );
1296
1297	if ( !dev_priv ) {
1298		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
1299		return -EINVAL;
1300	}
1301
1302	if ( copy_from_user( &vertex, (drm_r128_vertex_t *)arg,
1303			     sizeof(vertex) ) )
1304		return -EFAULT;
1305
1306	DRM_DEBUG( "%s: pid=%d index=%d count=%d discard=%d\n",
1307		   __FUNCTION__, current->pid,
1308		   vertex.idx, vertex.count, vertex.discard );
1309
1310	if ( vertex.idx < 0 || vertex.idx >= dma->buf_count ) {
1311		DRM_ERROR( "buffer index %d (of %d max)\n",
1312			   vertex.idx, dma->buf_count - 1 );
1313		return -EINVAL;
1314	}
1315	if ( vertex.prim < 0 ||
1316	     vertex.prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2 ) {
1317		DRM_ERROR( "buffer prim %d\n", vertex.prim );
1318		return -EINVAL;
1319	}
1320
1321	RING_SPACE_TEST_WITH_RETURN( dev_priv );
1322	VB_AGE_TEST_WITH_RETURN( dev_priv );
1323
1324	buf = dma->buflist[vertex.idx];
1325	buf_priv = buf->dev_private;
1326
1327	if ( buf->pid != current->pid ) {
1328		DRM_ERROR( "process %d using buffer owned by %d\n",
1329			   current->pid, buf->pid );
1330		return -EINVAL;
1331	}
1332	if ( buf->pending ) {
1333		DRM_ERROR( "sending pending buffer %d\n", vertex.idx );
1334		return -EINVAL;
1335	}
1336
1337	buf->used = vertex.count;
1338	buf_priv->prim = vertex.prim;
1339	buf_priv->discard = vertex.discard;
1340
1341	r128_cce_dispatch_vertex( dev, buf );
1342
1343	return 0;
1344}
1345
1346int r128_cce_indices( struct inode *inode, struct file *filp,
1347		      unsigned int cmd, unsigned long arg )
1348{
1349	drm_file_t *priv = filp->private_data;
1350	drm_device_t *dev = priv->dev;
1351	drm_r128_private_t *dev_priv = dev->dev_private;
1352	drm_device_dma_t *dma = dev->dma;
1353	drm_buf_t *buf;
1354	drm_r128_buf_priv_t *buf_priv;
1355	drm_r128_indices_t elts;
1356	int count;
1357
1358	LOCK_TEST_WITH_RETURN( dev );
1359
1360	if ( !dev_priv ) {
1361		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
1362		return -EINVAL;
1363	}
1364
1365	if ( copy_from_user( &elts, (drm_r128_indices_t *)arg,
1366			     sizeof(elts) ) )
1367		return -EFAULT;
1368
1369	DRM_DEBUG( "%s: pid=%d buf=%d s=%d e=%d d=%d\n",
1370		   __FUNCTION__, current->pid,
1371		   elts.idx, elts.start, elts.end, elts.discard );
1372
1373	if ( elts.idx < 0 || elts.idx >= dma->buf_count ) {
1374		DRM_ERROR( "buffer index %d (of %d max)\n",
1375			   elts.idx, dma->buf_count - 1 );
1376		return -EINVAL;
1377	}
1378	if ( elts.prim < 0 ||
1379	     elts.prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2 ) {
1380		DRM_ERROR( "buffer prim %d\n", elts.prim );
1381		return -EINVAL;
1382	}
1383
1384	RING_SPACE_TEST_WITH_RETURN( dev_priv );
1385	VB_AGE_TEST_WITH_RETURN( dev_priv );
1386
1387	buf = dma->buflist[elts.idx];
1388	buf_priv = buf->dev_private;
1389
1390	if ( buf->pid != current->pid ) {
1391		DRM_ERROR( "process %d using buffer owned by %d\n",
1392			   current->pid, buf->pid );
1393		return -EINVAL;
1394	}
1395	if ( buf->pending ) {
1396		DRM_ERROR( "sending pending buffer %d\n", elts.idx );
1397		return -EINVAL;
1398	}
1399
1400	count = (elts.end - elts.start) / sizeof(u16);
1401	elts.start -= R128_INDEX_PRIM_OFFSET;
1402
1403	if ( elts.start & 0x7 ) {
1404		DRM_ERROR( "misaligned buffer 0x%x\n", elts.start );
1405		return -EINVAL;
1406	}
1407	if ( elts.start < buf->used ) {
1408		DRM_ERROR( "no header 0x%x - 0x%x\n", elts.start, buf->used );
1409		return -EINVAL;
1410	}
1411
1412	buf->used = elts.end;
1413	buf_priv->prim = elts.prim;
1414	buf_priv->discard = elts.discard;
1415
1416	r128_cce_dispatch_indices( dev, buf, elts.start, elts.end, count );
1417
1418	return 0;
1419}
1420
1421int r128_cce_blit( struct inode *inode, struct file *filp,
1422		   unsigned int cmd, unsigned long arg )
1423{
1424	drm_file_t *priv = filp->private_data;
1425	drm_device_t *dev = priv->dev;
1426	drm_device_dma_t *dma = dev->dma;
1427	drm_r128_private_t *dev_priv = dev->dev_private;
1428	drm_r128_blit_t blit;
1429
1430	LOCK_TEST_WITH_RETURN( dev );
1431
1432	if ( copy_from_user( &blit, (drm_r128_blit_t *)arg,
1433			     sizeof(blit) ) )
1434		return -EFAULT;
1435
1436	DRM_DEBUG( "%s: pid=%d index=%d\n",
1437		   __FUNCTION__, current->pid, blit.idx );
1438
1439	if ( blit.idx < 0 || blit.idx >= dma->buf_count ) {
1440		DRM_ERROR( "buffer index %d (of %d max)\n",
1441			   blit.idx, dma->buf_count - 1 );
1442		return -EINVAL;
1443	}
1444
1445	RING_SPACE_TEST_WITH_RETURN( dev_priv );
1446	VB_AGE_TEST_WITH_RETURN( dev_priv );
1447
1448	return r128_cce_dispatch_blit( dev, &blit );
1449}
1450
1451int r128_cce_depth( struct inode *inode, struct file *filp,
1452		    unsigned int cmd, unsigned long arg )
1453{
1454	drm_file_t *priv = filp->private_data;
1455	drm_device_t *dev = priv->dev;
1456	drm_r128_private_t *dev_priv = dev->dev_private;
1457	drm_r128_depth_t depth;
1458
1459	LOCK_TEST_WITH_RETURN( dev );
1460
1461	if ( copy_from_user( &depth, (drm_r128_depth_t *)arg,
1462			     sizeof(depth) ) )
1463		return -EFAULT;
1464
1465	RING_SPACE_TEST_WITH_RETURN( dev_priv );
1466
1467	switch ( depth.func ) {
1468	case R128_WRITE_SPAN:
1469		return r128_cce_dispatch_write_span( dev, &depth );
1470	case R128_WRITE_PIXELS:
1471		return r128_cce_dispatch_write_pixels( dev, &depth );
1472	case R128_READ_SPAN:
1473		return r128_cce_dispatch_read_span( dev, &depth );
1474	case R128_READ_PIXELS:
1475		return r128_cce_dispatch_read_pixels( dev, &depth );
1476	}
1477
1478	return -EINVAL;
1479}
1480
1481int r128_cce_stipple( struct inode *inode, struct file *filp,
1482		      unsigned int cmd, unsigned long arg )
1483{
1484	drm_file_t *priv = filp->private_data;
1485	drm_device_t *dev = priv->dev;
1486	drm_r128_private_t *dev_priv = dev->dev_private;
1487	drm_r128_stipple_t stipple;
1488	u32 mask[32];
1489
1490	LOCK_TEST_WITH_RETURN( dev );
1491
1492	if ( copy_from_user( &stipple, (drm_r128_stipple_t *)arg,
1493			     sizeof(stipple) ) )
1494		return -EFAULT;
1495
1496	if ( copy_from_user( &mask, stipple.mask,
1497			     32 * sizeof(u32) ) )
1498		return -EFAULT;
1499
1500	RING_SPACE_TEST_WITH_RETURN( dev_priv );
1501
1502	r128_cce_dispatch_stipple( dev, mask );
1503
1504	return 0;
1505}
1506
1507int r128_cce_indirect( struct inode *inode, struct file *filp,
1508		       unsigned int cmd, unsigned long arg )
1509{
1510	drm_file_t *priv = filp->private_data;
1511	drm_device_t *dev = priv->dev;
1512	drm_r128_private_t *dev_priv = dev->dev_private;
1513	drm_device_dma_t *dma = dev->dma;
1514	drm_buf_t *buf;
1515	drm_r128_buf_priv_t *buf_priv;
1516	drm_r128_indirect_t indirect;
1517
1518	LOCK_TEST_WITH_RETURN( dev );
1519
1520	if ( !dev_priv ) {
1521		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
1522		return -EINVAL;
1523	}
1524
1525	if ( copy_from_user( &indirect, (drm_r128_indirect_t *)arg,
1526			     sizeof(indirect) ) )
1527		return -EFAULT;
1528
1529	DRM_DEBUG( "indirect: idx=%d s=%d e=%d d=%d\n",
1530		   indirect.idx, indirect.start,
1531		   indirect.end, indirect.discard );
1532
1533	if ( indirect.idx < 0 || indirect.idx >= dma->buf_count ) {
1534		DRM_ERROR( "buffer index %d (of %d max)\n",
1535			   indirect.idx, dma->buf_count - 1 );
1536		return -EINVAL;
1537	}
1538
1539	buf = dma->buflist[indirect.idx];
1540	buf_priv = buf->dev_private;
1541
1542	if ( buf->pid != current->pid ) {
1543		DRM_ERROR( "process %d using buffer owned by %d\n",
1544			   current->pid, buf->pid );
1545		return -EINVAL;
1546	}
1547	if ( buf->pending ) {
1548		DRM_ERROR( "sending pending buffer %d\n", indirect.idx );
1549		return -EINVAL;
1550	}
1551
1552	if ( indirect.start < buf->used ) {
1553		DRM_ERROR( "reusing indirect: start=0x%x actual=0x%x\n",
1554			   indirect.start, buf->used );
1555		return -EINVAL;
1556	}
1557
1558	RING_SPACE_TEST_WITH_RETURN( dev_priv );
1559	VB_AGE_TEST_WITH_RETURN( dev_priv );
1560
1561	buf->used = indirect.end;
1562	buf_priv->discard = indirect.discard;
1563
1564
1565	/* Dispatch the indirect buffer full of commands from the
1566	 * X server.  This is insecure and is thus only available to
1567	 * privileged clients.
1568	 */
1569	r128_cce_dispatch_indirect( dev, buf, indirect.start, indirect.end );
1570
1571	return 0;
1572}
1573