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