buf->filp is a pointer, so make printf format args be %p not %d
[platform/upstream/libdrm.git] / shared-core / 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
30 #include "r128.h"
31 #include "drmP.h"
32 #include "drm.h"
33 #include "r128_drm.h"
34 #include "r128_drv.h"
35
36
37 /* ================================================================
38  * CCE hardware state programming functions
39  */
40
41 static 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
84 static __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
99 static __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
125 static __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
141 static __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
160 static __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
175 static __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
202 static __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
226 static __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
280 static 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
330 static 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
346 static 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
362 static 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
467 static 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
527 static 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( "page=%d\n", 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
568 static 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( "buf=%d nbox=%d\n", buf->idx, sarea_priv->nbox );
581
582         if ( 0 )
583                 r128_print_dirty( "dispatch_vertex", sarea_priv->dirty );
584
585         if ( buf->used ) {
586                 buf_priv->dispatched = 1;
587
588                 if ( sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS ) {
589                         r128_emit_state( dev_priv );
590                 }
591
592                 do {
593                         /* Emit the next set of up to three cliprects */
594                         if ( i < sarea_priv->nbox ) {
595                                 r128_emit_clip_rects( dev_priv,
596                                                       &sarea_priv->boxes[i],
597                                                       sarea_priv->nbox - i );
598                         }
599
600                         /* Emit the vertex buffer rendering commands */
601                         BEGIN_RING( 5 );
602
603                         OUT_RING( CCE_PACKET3( R128_3D_RNDR_GEN_INDX_PRIM, 3 ) );
604                         OUT_RING( offset );
605                         OUT_RING( size );
606                         OUT_RING( format );
607                         OUT_RING( prim | R128_CCE_VC_CNTL_PRIM_WALK_LIST |
608                                   (size << R128_CCE_VC_CNTL_NUM_SHIFT) );
609
610                         ADVANCE_RING();
611
612                         i += 3;
613                 } while ( i < sarea_priv->nbox );
614         }
615
616         if ( buf_priv->discard ) {
617                 buf_priv->age = dev_priv->sarea_priv->last_dispatch;
618
619                 /* Emit the vertex buffer age */
620                 BEGIN_RING( 2 );
621
622                 OUT_RING( CCE_PACKET0( R128_LAST_DISPATCH_REG, 0 ) );
623                 OUT_RING( buf_priv->age );
624
625                 ADVANCE_RING();
626
627                 buf->pending = 1;
628                 buf->used = 0;
629                 /* FIXME: Check dispatched field */
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
639 static 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                 /* FIXME: Check dispatched field */
690                 buf_priv->dispatched = 0;
691         }
692
693         dev_priv->sarea_priv->last_dispatch++;
694 }
695
696 static void r128_cce_dispatch_indices( drm_device_t *dev,
697                                        drm_buf_t *buf,
698                                        int start, int end,
699                                        int count )
700 {
701         drm_r128_private_t *dev_priv = dev->dev_private;
702         drm_r128_buf_priv_t *buf_priv = buf->dev_private;
703         drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
704         int format = sarea_priv->vc_format;
705         int offset = dev_priv->buffers->offset - dev_priv->cce_buffers_offset;
706         int prim = buf_priv->prim;
707         u32 *data;
708         int dwords;
709         int i = 0;
710         RING_LOCALS;
711         DRM_DEBUG( "indices: s=%d e=%d c=%d\n", start, end, count );
712
713         if ( 0 )
714                 r128_print_dirty( "dispatch_indices", sarea_priv->dirty );
715
716         if ( start != end ) {
717                 buf_priv->dispatched = 1;
718
719                 if ( sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS ) {
720                         r128_emit_state( dev_priv );
721                 }
722
723                 dwords = (end - start + 3) / sizeof(u32);
724
725                 data = (u32 *)((char *)dev_priv->buffers->handle
726                                + buf->offset + start);
727
728                 data[0] = cpu_to_le32( CCE_PACKET3( R128_3D_RNDR_GEN_INDX_PRIM,
729                                                     dwords-2 ) );
730
731                 data[1] = cpu_to_le32( offset );
732                 data[2] = cpu_to_le32( R128_MAX_VB_VERTS );
733                 data[3] = cpu_to_le32( format );
734                 data[4] = cpu_to_le32( (prim | R128_CCE_VC_CNTL_PRIM_WALK_IND |
735                                         (count << 16)) );
736
737                 if ( count & 0x1 ) {
738 #ifdef __LITTLE_ENDIAN
739                         data[dwords-1] &= 0x0000ffff;
740 #else
741                         data[dwords-1] &= 0xffff0000;
742 #endif
743                 }
744
745                 do {
746                         /* Emit the next set of up to three cliprects */
747                         if ( i < sarea_priv->nbox ) {
748                                 r128_emit_clip_rects( dev_priv,
749                                                       &sarea_priv->boxes[i],
750                                                       sarea_priv->nbox - i );
751                         }
752
753                         r128_cce_dispatch_indirect( dev, buf, start, end );
754
755                         i += 3;
756                 } while ( i < sarea_priv->nbox );
757         }
758
759         if ( buf_priv->discard ) {
760                 buf_priv->age = dev_priv->sarea_priv->last_dispatch;
761
762                 /* Emit the vertex buffer age */
763                 BEGIN_RING( 2 );
764
765                 OUT_RING( CCE_PACKET0( R128_LAST_DISPATCH_REG, 0 ) );
766                 OUT_RING( buf_priv->age );
767
768                 ADVANCE_RING();
769
770                 buf->pending = 1;
771                 /* FIXME: Check dispatched field */
772                 buf_priv->dispatched = 0;
773         }
774
775         dev_priv->sarea_priv->last_dispatch++;
776
777         sarea_priv->dirty &= ~R128_UPLOAD_CLIPRECTS;
778         sarea_priv->nbox = 0;
779 }
780
781 static int r128_cce_dispatch_blit( DRMFILE filp,
782                                    drm_device_t *dev,
783                                    drm_r128_blit_t *blit )
784 {
785         drm_r128_private_t *dev_priv = dev->dev_private;
786         drm_device_dma_t *dma = dev->dma;
787         drm_buf_t *buf;
788         drm_r128_buf_priv_t *buf_priv;
789         u32 *data;
790         int dword_shift, dwords;
791         RING_LOCALS;
792         DRM_DEBUG( "\n" );
793
794         /* The compiler won't optimize away a division by a variable,
795          * even if the only legal values are powers of two.  Thus, we'll
796          * use a shift instead.
797          */
798         switch ( blit->format ) {
799         case R128_DATATYPE_ARGB8888:
800                 dword_shift = 0;
801                 break;
802         case R128_DATATYPE_ARGB1555:
803         case R128_DATATYPE_RGB565:
804         case R128_DATATYPE_ARGB4444:
805                 dword_shift = 1;
806                 break;
807         case R128_DATATYPE_CI8:
808         case R128_DATATYPE_RGB8:
809                 dword_shift = 2;
810                 break;
811         default:
812                 DRM_ERROR( "invalid blit format %d\n", blit->format );
813                 return DRM_ERR(EINVAL);
814         }
815
816         /* Flush the pixel cache, and mark the contents as Read Invalid.
817          * This ensures no pixel data gets mixed up with the texture
818          * data from the host data blit, otherwise part of the texture
819          * image may be corrupted.
820          */
821         BEGIN_RING( 2 );
822
823         OUT_RING( CCE_PACKET0( R128_PC_GUI_CTLSTAT, 0 ) );
824         OUT_RING( R128_PC_RI_GUI | R128_PC_FLUSH_GUI );
825
826         ADVANCE_RING();
827
828         /* Dispatch the indirect buffer.
829          */
830         buf = dma->buflist[blit->idx];
831         buf_priv = buf->dev_private;
832
833         if ( buf->filp != filp ) {
834                 DRM_ERROR( "process %d using buffer owned by %p\n",
835                            DRM_CURRENTPID, buf->filp );
836                 return DRM_ERR(EINVAL);
837         }
838         if ( buf->pending ) {
839                 DRM_ERROR( "sending pending buffer %d\n", blit->idx );
840                 return DRM_ERR(EINVAL);
841         }
842
843         buf_priv->discard = 1;
844
845         dwords = (blit->width * blit->height) >> dword_shift;
846
847         data = (u32 *)((char *)dev_priv->buffers->handle + buf->offset);
848
849         data[0] = cpu_to_le32( CCE_PACKET3( R128_CNTL_HOSTDATA_BLT, dwords + 6 ) );
850         data[1] = cpu_to_le32( (R128_GMC_DST_PITCH_OFFSET_CNTL |
851                                 R128_GMC_BRUSH_NONE |
852                                 (blit->format << 8) |
853                                 R128_GMC_SRC_DATATYPE_COLOR |
854                                 R128_ROP3_S |
855                                 R128_DP_SRC_SOURCE_HOST_DATA |
856                                 R128_GMC_CLR_CMP_CNTL_DIS |
857                                 R128_GMC_AUX_CLIP_DIS |
858                                 R128_GMC_WR_MSK_DIS) );
859
860         data[2] = cpu_to_le32( (blit->pitch << 21) | (blit->offset >> 5) );
861         data[3] = cpu_to_le32( 0xffffffff );
862         data[4] = cpu_to_le32( 0xffffffff );
863         data[5] = cpu_to_le32( (blit->y << 16) | blit->x );
864         data[6] = cpu_to_le32( (blit->height << 16) | blit->width );
865         data[7] = cpu_to_le32( dwords );
866
867         buf->used = (dwords + 8) * sizeof(u32);
868
869         r128_cce_dispatch_indirect( dev, buf, 0, buf->used );
870
871         /* Flush the pixel cache after the blit completes.  This ensures
872          * the texture data is written out to memory before rendering
873          * continues.
874          */
875         BEGIN_RING( 2 );
876
877         OUT_RING( CCE_PACKET0( R128_PC_GUI_CTLSTAT, 0 ) );
878         OUT_RING( R128_PC_FLUSH_GUI );
879
880         ADVANCE_RING();
881
882         return 0;
883 }
884
885
886 /* ================================================================
887  * Tiled depth buffer management
888  *
889  * FIXME: These should all set the destination write mask for when we
890  * have hardware stencil support.
891  */
892
893 static int r128_cce_dispatch_write_span( drm_device_t *dev,
894                                          drm_r128_depth_t *depth )
895 {
896         drm_r128_private_t *dev_priv = dev->dev_private;
897         int count, x, y;
898         u32 *buffer;
899         u8 *mask;
900         int i, buffer_size, mask_size;
901         RING_LOCALS;
902         DRM_DEBUG( "\n" );
903
904         count = depth->n;
905         if ( DRM_COPY_FROM_USER( &x, depth->x, sizeof(x) ) ) {
906                 return DRM_ERR(EFAULT);
907         }
908         if ( DRM_COPY_FROM_USER( &y, depth->y, sizeof(y) ) ) {
909                 return DRM_ERR(EFAULT);
910         }
911
912         buffer_size = depth->n * sizeof(u32);
913         buffer = DRM_MALLOC( buffer_size );
914         if ( buffer == NULL )
915                 return DRM_ERR(ENOMEM);
916         if ( DRM_COPY_FROM_USER( buffer, depth->buffer, buffer_size ) ) {
917                 DRM_FREE( buffer, buffer_size);
918                 return DRM_ERR(EFAULT);
919         }
920
921         mask_size = depth->n * sizeof(u8);
922         if ( depth->mask ) {
923                 mask = DRM_MALLOC( mask_size );
924                 if ( mask == NULL ) {
925                         DRM_FREE( buffer, buffer_size );
926                         return DRM_ERR(ENOMEM);
927                 }
928                 if ( DRM_COPY_FROM_USER( mask, depth->mask, mask_size ) ) {
929                         DRM_FREE( buffer, buffer_size );
930                         DRM_FREE( mask, mask_size );
931                         return DRM_ERR(EFAULT);
932                 }
933
934                 for ( i = 0 ; i < count ; i++, x++ ) {
935                         if ( mask[i] ) {
936                                 BEGIN_RING( 6 );
937
938                                 OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
939                                 OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
940                                           R128_GMC_BRUSH_SOLID_COLOR |
941                                           (dev_priv->depth_fmt << 8) |
942                                           R128_GMC_SRC_DATATYPE_COLOR |
943                                           R128_ROP3_P |
944                                           R128_GMC_CLR_CMP_CNTL_DIS |
945                                           R128_GMC_WR_MSK_DIS );
946
947                                 OUT_RING( dev_priv->depth_pitch_offset_c );
948                                 OUT_RING( buffer[i] );
949
950                                 OUT_RING( (x << 16) | y );
951                                 OUT_RING( (1 << 16) | 1 );
952
953                                 ADVANCE_RING();
954                         }
955                 }
956
957                 DRM_FREE( mask, mask_size );
958         } else {
959                 for ( i = 0 ; i < count ; i++, x++ ) {
960                         BEGIN_RING( 6 );
961
962                         OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
963                         OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
964                                   R128_GMC_BRUSH_SOLID_COLOR |
965                                   (dev_priv->depth_fmt << 8) |
966                                   R128_GMC_SRC_DATATYPE_COLOR |
967                                   R128_ROP3_P |
968                                   R128_GMC_CLR_CMP_CNTL_DIS |
969                                   R128_GMC_WR_MSK_DIS );
970
971                         OUT_RING( dev_priv->depth_pitch_offset_c );
972                         OUT_RING( buffer[i] );
973
974                         OUT_RING( (x << 16) | y );
975                         OUT_RING( (1 << 16) | 1 );
976
977                         ADVANCE_RING();
978                 }
979         }
980
981         DRM_FREE( buffer, buffer_size );
982
983         return 0;
984 }
985
986 static int r128_cce_dispatch_write_pixels( drm_device_t *dev,
987                                            drm_r128_depth_t *depth )
988 {
989         drm_r128_private_t *dev_priv = dev->dev_private;
990         int count, *x, *y;
991         u32 *buffer;
992         u8 *mask;
993         int i, xbuf_size, ybuf_size, buffer_size, mask_size;
994         RING_LOCALS;
995         DRM_DEBUG( "\n" );
996
997         count = depth->n;
998
999         xbuf_size = count * sizeof(*x);
1000         ybuf_size = count * sizeof(*y);
1001         x = DRM_MALLOC( xbuf_size );
1002         if ( x == NULL ) {
1003                 return DRM_ERR(ENOMEM);
1004         }
1005         y = DRM_MALLOC( ybuf_size );
1006         if ( y == NULL ) {
1007                 DRM_FREE( x, xbuf_size );
1008                 return DRM_ERR(ENOMEM);
1009         }
1010         if ( DRM_COPY_FROM_USER( x, depth->x, xbuf_size ) ) {
1011                 DRM_FREE( x, xbuf_size );
1012                 DRM_FREE( y, ybuf_size );
1013                 return DRM_ERR(EFAULT);
1014         }
1015         if ( DRM_COPY_FROM_USER( y, depth->y, xbuf_size ) ) {
1016                 DRM_FREE( x, xbuf_size );
1017                 DRM_FREE( y, ybuf_size );
1018                 return DRM_ERR(EFAULT);
1019         }
1020
1021         buffer_size = depth->n * sizeof(u32);
1022         buffer = DRM_MALLOC( buffer_size );
1023         if ( buffer == NULL ) {
1024                 DRM_FREE( x, xbuf_size );
1025                 DRM_FREE( y, ybuf_size );
1026                 return DRM_ERR(ENOMEM);
1027         }
1028         if ( DRM_COPY_FROM_USER( buffer, depth->buffer, buffer_size ) ) {
1029                 DRM_FREE( x, xbuf_size );
1030                 DRM_FREE( y, ybuf_size );
1031                 DRM_FREE( buffer, buffer_size );
1032                 return DRM_ERR(EFAULT);
1033         }
1034
1035         if ( depth->mask ) {
1036                 mask_size = depth->n * sizeof(u8);
1037                 mask = DRM_MALLOC( mask_size );
1038                 if ( mask == NULL ) {
1039                         DRM_FREE( x, xbuf_size );
1040                         DRM_FREE( y, ybuf_size );
1041                         DRM_FREE( buffer, buffer_size );
1042                         return DRM_ERR(ENOMEM);
1043                 }
1044                 if ( DRM_COPY_FROM_USER( mask, depth->mask, mask_size ) ) {
1045                         DRM_FREE( x, xbuf_size );
1046                         DRM_FREE( y, ybuf_size );
1047                         DRM_FREE( buffer, buffer_size );
1048                         DRM_FREE( mask, mask_size );
1049                         return DRM_ERR(EFAULT);
1050                 }
1051
1052                 for ( i = 0 ; i < count ; i++ ) {
1053                         if ( mask[i] ) {
1054                                 BEGIN_RING( 6 );
1055
1056                                 OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
1057                                 OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
1058                                           R128_GMC_BRUSH_SOLID_COLOR |
1059                                           (dev_priv->depth_fmt << 8) |
1060                                           R128_GMC_SRC_DATATYPE_COLOR |
1061                                           R128_ROP3_P |
1062                                           R128_GMC_CLR_CMP_CNTL_DIS |
1063                                           R128_GMC_WR_MSK_DIS );
1064
1065                                 OUT_RING( dev_priv->depth_pitch_offset_c );
1066                                 OUT_RING( buffer[i] );
1067
1068                                 OUT_RING( (x[i] << 16) | y[i] );
1069                                 OUT_RING( (1 << 16) | 1 );
1070
1071                                 ADVANCE_RING();
1072                         }
1073                 }
1074
1075                 DRM_FREE( mask, mask_size );
1076         } else {
1077                 for ( i = 0 ; i < count ; i++ ) {
1078                         BEGIN_RING( 6 );
1079
1080                         OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
1081                         OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
1082                                   R128_GMC_BRUSH_SOLID_COLOR |
1083                                   (dev_priv->depth_fmt << 8) |
1084                                   R128_GMC_SRC_DATATYPE_COLOR |
1085                                   R128_ROP3_P |
1086                                   R128_GMC_CLR_CMP_CNTL_DIS |
1087                                   R128_GMC_WR_MSK_DIS );
1088
1089                         OUT_RING( dev_priv->depth_pitch_offset_c );
1090                         OUT_RING( buffer[i] );
1091
1092                         OUT_RING( (x[i] << 16) | y[i] );
1093                         OUT_RING( (1 << 16) | 1 );
1094
1095                         ADVANCE_RING();
1096                 }
1097         }
1098
1099         DRM_FREE( x, xbuf_size );
1100         DRM_FREE( y, ybuf_size );
1101         DRM_FREE( buffer, buffer_size );
1102
1103         return 0;
1104 }
1105
1106 static int r128_cce_dispatch_read_span( drm_device_t *dev,
1107                                         drm_r128_depth_t *depth )
1108 {
1109         drm_r128_private_t *dev_priv = dev->dev_private;
1110         int count, x, y;
1111         RING_LOCALS;
1112         DRM_DEBUG( "\n" );
1113
1114         count = depth->n;
1115         if ( DRM_COPY_FROM_USER( &x, depth->x, sizeof(x) ) ) {
1116                 return DRM_ERR(EFAULT);
1117         }
1118         if ( DRM_COPY_FROM_USER( &y, depth->y, sizeof(y) ) ) {
1119                 return DRM_ERR(EFAULT);
1120         }
1121
1122         BEGIN_RING( 7 );
1123
1124         OUT_RING( CCE_PACKET3( R128_CNTL_BITBLT_MULTI, 5 ) );
1125         OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL |
1126                   R128_GMC_DST_PITCH_OFFSET_CNTL |
1127                   R128_GMC_BRUSH_NONE |
1128                   (dev_priv->depth_fmt << 8) |
1129                   R128_GMC_SRC_DATATYPE_COLOR |
1130                   R128_ROP3_S |
1131                   R128_DP_SRC_SOURCE_MEMORY |
1132                   R128_GMC_CLR_CMP_CNTL_DIS |
1133                   R128_GMC_WR_MSK_DIS );
1134
1135         OUT_RING( dev_priv->depth_pitch_offset_c );
1136         OUT_RING( dev_priv->span_pitch_offset_c );
1137
1138         OUT_RING( (x << 16) | y );
1139         OUT_RING( (0 << 16) | 0 );
1140         OUT_RING( (count << 16) | 1 );
1141
1142         ADVANCE_RING();
1143
1144         return 0;
1145 }
1146
1147 static int r128_cce_dispatch_read_pixels( drm_device_t *dev,
1148                                           drm_r128_depth_t *depth )
1149 {
1150         drm_r128_private_t *dev_priv = dev->dev_private;
1151         int count, *x, *y;
1152         int i, xbuf_size, ybuf_size;
1153         RING_LOCALS;
1154         DRM_DEBUG( "%s\n", __FUNCTION__ );
1155
1156         count = depth->n;
1157         if ( count > dev_priv->depth_pitch ) {
1158                 count = dev_priv->depth_pitch;
1159         }
1160
1161         xbuf_size = count * sizeof(*x);
1162         ybuf_size = count * sizeof(*y);
1163         x = DRM_MALLOC( xbuf_size );
1164         if ( x == NULL ) {
1165                 return DRM_ERR(ENOMEM);
1166         }
1167         y = DRM_MALLOC( ybuf_size );
1168         if ( y == NULL ) {
1169                 DRM_FREE( x, xbuf_size );
1170                 return DRM_ERR(ENOMEM);
1171         }
1172         if ( DRM_COPY_FROM_USER( x, depth->x, xbuf_size ) ) {
1173                 DRM_FREE( x, xbuf_size );
1174                 DRM_FREE( y, ybuf_size );
1175                 return DRM_ERR(EFAULT);
1176         }
1177         if ( DRM_COPY_FROM_USER( y, depth->y, ybuf_size ) ) {
1178                 DRM_FREE( x, xbuf_size );
1179                 DRM_FREE( y, ybuf_size );
1180                 return DRM_ERR(EFAULT);
1181         }
1182
1183         for ( i = 0 ; i < count ; i++ ) {
1184                 BEGIN_RING( 7 );
1185
1186                 OUT_RING( CCE_PACKET3( R128_CNTL_BITBLT_MULTI, 5 ) );
1187                 OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL |
1188                           R128_GMC_DST_PITCH_OFFSET_CNTL |
1189                           R128_GMC_BRUSH_NONE |
1190                           (dev_priv->depth_fmt << 8) |
1191                           R128_GMC_SRC_DATATYPE_COLOR |
1192                           R128_ROP3_S |
1193                           R128_DP_SRC_SOURCE_MEMORY |
1194                           R128_GMC_CLR_CMP_CNTL_DIS |
1195                           R128_GMC_WR_MSK_DIS );
1196
1197                 OUT_RING( dev_priv->depth_pitch_offset_c );
1198                 OUT_RING( dev_priv->span_pitch_offset_c );
1199
1200                 OUT_RING( (x[i] << 16) | y[i] );
1201                 OUT_RING( (i << 16) | 0 );
1202                 OUT_RING( (1 << 16) | 1 );
1203
1204                 ADVANCE_RING();
1205         }
1206
1207         DRM_FREE( x, xbuf_size );
1208         DRM_FREE( y, ybuf_size );
1209
1210         return 0;
1211 }
1212
1213
1214 /* ================================================================
1215  * Polygon stipple
1216  */
1217
1218 static void r128_cce_dispatch_stipple( drm_device_t *dev, u32 *stipple )
1219 {
1220         drm_r128_private_t *dev_priv = dev->dev_private;
1221         int i;
1222         RING_LOCALS;
1223         DRM_DEBUG( "%s\n", __FUNCTION__ );
1224
1225         BEGIN_RING( 33 );
1226
1227         OUT_RING( CCE_PACKET0( R128_BRUSH_DATA0, 31 ) );
1228         for ( i = 0 ; i < 32 ; i++ ) {
1229                 OUT_RING( stipple[i] );
1230         }
1231
1232         ADVANCE_RING();
1233 }
1234
1235
1236 /* ================================================================
1237  * IOCTL functions
1238  */
1239
1240 int r128_cce_clear( DRM_IOCTL_ARGS )
1241 {
1242         DRM_DEVICE;
1243         drm_r128_private_t *dev_priv = dev->dev_private;
1244         drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
1245         drm_r128_clear_t clear;
1246         DRM_DEBUG( "\n" );
1247
1248         LOCK_TEST_WITH_RETURN( dev, filp );
1249
1250         DRM_COPY_FROM_USER_IOCTL( clear, (drm_r128_clear_t *) data,
1251                              sizeof(clear) );
1252
1253         RING_SPACE_TEST_WITH_RETURN( dev_priv );
1254
1255         if ( sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS )
1256                 sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS;
1257
1258         r128_cce_dispatch_clear( dev, &clear );
1259
1260         /* Make sure we restore the 3D state next time.
1261          */
1262         dev_priv->sarea_priv->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_MASKS;
1263
1264         return 0;
1265 }
1266
1267 int r128_cce_swap( DRM_IOCTL_ARGS )
1268 {
1269         DRM_DEVICE;
1270         drm_r128_private_t *dev_priv = dev->dev_private;
1271         drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
1272         DRM_DEBUG( "%s\n", __FUNCTION__ );
1273
1274         LOCK_TEST_WITH_RETURN( dev, filp );
1275
1276         RING_SPACE_TEST_WITH_RETURN( dev_priv );
1277
1278         if ( sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS )
1279                 sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS;
1280
1281         if ( !dev_priv->page_flipping ) {
1282                 r128_cce_dispatch_swap( dev );
1283                 dev_priv->sarea_priv->dirty |= (R128_UPLOAD_CONTEXT |
1284                                                 R128_UPLOAD_MASKS);
1285         } else {
1286                 r128_cce_dispatch_flip( dev );
1287         }
1288
1289         return 0;
1290 }
1291
1292 int r128_cce_vertex( DRM_IOCTL_ARGS )
1293 {
1294         DRM_DEVICE;
1295         drm_r128_private_t *dev_priv = dev->dev_private;
1296         drm_device_dma_t *dma = dev->dma;
1297         drm_buf_t *buf;
1298         drm_r128_buf_priv_t *buf_priv;
1299         drm_r128_vertex_t vertex;
1300
1301         LOCK_TEST_WITH_RETURN( dev, filp );
1302
1303         if ( !dev_priv ) {
1304                 DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
1305                 return DRM_ERR(EINVAL);
1306         }
1307
1308         DRM_COPY_FROM_USER_IOCTL( vertex, (drm_r128_vertex_t *) data,
1309                              sizeof(vertex) );
1310
1311         DRM_DEBUG( "pid=%d index=%d count=%d discard=%d\n",
1312                    DRM_CURRENTPID,
1313                    vertex.idx, vertex.count, vertex.discard );
1314
1315         if ( vertex.idx < 0 || vertex.idx >= dma->buf_count ) {
1316                 DRM_ERROR( "buffer index %d (of %d max)\n",
1317                            vertex.idx, dma->buf_count - 1 );
1318                 return DRM_ERR(EINVAL);
1319         }
1320         if ( vertex.prim < 0 ||
1321              vertex.prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2 ) {
1322                 DRM_ERROR( "buffer prim %d\n", vertex.prim );
1323                 return DRM_ERR(EINVAL);
1324         }
1325
1326         RING_SPACE_TEST_WITH_RETURN( dev_priv );
1327         VB_AGE_TEST_WITH_RETURN( dev_priv );
1328
1329         buf = dma->buflist[vertex.idx];
1330         buf_priv = buf->dev_private;
1331
1332         if ( buf->filp != filp ) {
1333                 DRM_ERROR( "process %d using buffer owned by %p\n",
1334                            DRM_CURRENTPID, buf->filp );
1335                 return DRM_ERR(EINVAL);
1336         }
1337         if ( buf->pending ) {
1338                 DRM_ERROR( "sending pending buffer %d\n", vertex.idx );
1339                 return DRM_ERR(EINVAL);
1340         }
1341
1342         buf->used = vertex.count;
1343         buf_priv->prim = vertex.prim;
1344         buf_priv->discard = vertex.discard;
1345
1346         r128_cce_dispatch_vertex( dev, buf );
1347
1348         return 0;
1349 }
1350
1351 int r128_cce_indices( DRM_IOCTL_ARGS )
1352 {
1353         DRM_DEVICE;
1354         drm_r128_private_t *dev_priv = dev->dev_private;
1355         drm_device_dma_t *dma = dev->dma;
1356         drm_buf_t *buf;
1357         drm_r128_buf_priv_t *buf_priv;
1358         drm_r128_indices_t elts;
1359         int count;
1360
1361         LOCK_TEST_WITH_RETURN( dev, filp );
1362
1363         if ( !dev_priv ) {
1364                 DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
1365                 return DRM_ERR(EINVAL);
1366         }
1367
1368         DRM_COPY_FROM_USER_IOCTL( elts, (drm_r128_indices_t *) data,
1369                              sizeof(elts) );
1370
1371         DRM_DEBUG( "pid=%d buf=%d s=%d e=%d d=%d\n", DRM_CURRENTPID,
1372                    elts.idx, elts.start, elts.end, elts.discard );
1373
1374         if ( elts.idx < 0 || elts.idx >= dma->buf_count ) {
1375                 DRM_ERROR( "buffer index %d (of %d max)\n",
1376                            elts.idx, dma->buf_count - 1 );
1377                 return DRM_ERR(EINVAL);
1378         }
1379         if ( elts.prim < 0 ||
1380              elts.prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2 ) {
1381                 DRM_ERROR( "buffer prim %d\n", elts.prim );
1382                 return DRM_ERR(EINVAL);
1383         }
1384
1385         RING_SPACE_TEST_WITH_RETURN( dev_priv );
1386         VB_AGE_TEST_WITH_RETURN( dev_priv );
1387
1388         buf = dma->buflist[elts.idx];
1389         buf_priv = buf->dev_private;
1390
1391         if ( buf->filp != filp ) {
1392                 DRM_ERROR( "process %d using buffer owned by %p\n",
1393                            DRM_CURRENTPID, buf->filp );
1394                 return DRM_ERR(EINVAL);
1395         }
1396         if ( buf->pending ) {
1397                 DRM_ERROR( "sending pending buffer %d\n", elts.idx );
1398                 return DRM_ERR(EINVAL);
1399         }
1400
1401         count = (elts.end - elts.start) / sizeof(u16);
1402         elts.start -= R128_INDEX_PRIM_OFFSET;
1403
1404         if ( elts.start & 0x7 ) {
1405                 DRM_ERROR( "misaligned buffer 0x%x\n", elts.start );
1406                 return DRM_ERR(EINVAL);
1407         }
1408         if ( elts.start < buf->used ) {
1409                 DRM_ERROR( "no header 0x%x - 0x%x\n", elts.start, buf->used );
1410                 return DRM_ERR(EINVAL);
1411         }
1412
1413         buf->used = elts.end;
1414         buf_priv->prim = elts.prim;
1415         buf_priv->discard = elts.discard;
1416
1417         r128_cce_dispatch_indices( dev, buf, elts.start, elts.end, count );
1418
1419         return 0;
1420 }
1421
1422 int r128_cce_blit( DRM_IOCTL_ARGS )
1423 {
1424         DRM_DEVICE;
1425         drm_device_dma_t *dma = dev->dma;
1426         drm_r128_private_t *dev_priv = dev->dev_private;
1427         drm_r128_blit_t blit;
1428
1429         LOCK_TEST_WITH_RETURN( dev, filp );
1430
1431         DRM_COPY_FROM_USER_IOCTL( blit, (drm_r128_blit_t *) data,
1432                              sizeof(blit) );
1433
1434         DRM_DEBUG( "pid=%d index=%d\n", DRM_CURRENTPID, blit.idx );
1435
1436         if ( blit.idx < 0 || blit.idx >= dma->buf_count ) {
1437                 DRM_ERROR( "buffer index %d (of %d max)\n",
1438                            blit.idx, dma->buf_count - 1 );
1439                 return DRM_ERR(EINVAL);
1440         }
1441
1442         RING_SPACE_TEST_WITH_RETURN( dev_priv );
1443         VB_AGE_TEST_WITH_RETURN( dev_priv );
1444
1445         return r128_cce_dispatch_blit( filp, dev, &blit );
1446 }
1447
1448 int r128_cce_depth( DRM_IOCTL_ARGS )
1449 {
1450         DRM_DEVICE;
1451         drm_r128_private_t *dev_priv = dev->dev_private;
1452         drm_r128_depth_t depth;
1453
1454         LOCK_TEST_WITH_RETURN( dev, filp );
1455
1456         DRM_COPY_FROM_USER_IOCTL( depth, (drm_r128_depth_t *) data,
1457                              sizeof(depth) );
1458
1459         RING_SPACE_TEST_WITH_RETURN( dev_priv );
1460
1461         switch ( depth.func ) {
1462         case R128_WRITE_SPAN:
1463                 return r128_cce_dispatch_write_span( dev, &depth );
1464         case R128_WRITE_PIXELS:
1465                 return r128_cce_dispatch_write_pixels( dev, &depth );
1466         case R128_READ_SPAN:
1467                 return r128_cce_dispatch_read_span( dev, &depth );
1468         case R128_READ_PIXELS:
1469                 return r128_cce_dispatch_read_pixels( dev, &depth );
1470         }
1471
1472         return DRM_ERR(EINVAL);
1473 }
1474
1475 int r128_cce_stipple( DRM_IOCTL_ARGS )
1476 {
1477         DRM_DEVICE;
1478         drm_r128_private_t *dev_priv = dev->dev_private;
1479         drm_r128_stipple_t stipple;
1480         u32 mask[32];
1481
1482         LOCK_TEST_WITH_RETURN( dev, filp );
1483
1484         DRM_COPY_FROM_USER_IOCTL( stipple, (drm_r128_stipple_t *) data,
1485                              sizeof(stipple) );
1486
1487         if ( DRM_COPY_FROM_USER( &mask, stipple.mask,
1488                              32 * sizeof(u32) ) )
1489                 return DRM_ERR( EFAULT );
1490
1491         RING_SPACE_TEST_WITH_RETURN( dev_priv );
1492
1493         r128_cce_dispatch_stipple( dev, mask );
1494
1495         return 0;
1496 }
1497
1498 int r128_cce_indirect( DRM_IOCTL_ARGS )
1499 {
1500         DRM_DEVICE;
1501         drm_r128_private_t *dev_priv = dev->dev_private;
1502         drm_device_dma_t *dma = dev->dma;
1503         drm_buf_t *buf;
1504         drm_r128_buf_priv_t *buf_priv;
1505         drm_r128_indirect_t indirect;
1506 #if 0
1507         RING_LOCALS;
1508 #endif
1509
1510         LOCK_TEST_WITH_RETURN( dev, filp );
1511
1512         if ( !dev_priv ) {
1513                 DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
1514                 return DRM_ERR(EINVAL);
1515         }
1516
1517         DRM_COPY_FROM_USER_IOCTL( indirect, (drm_r128_indirect_t *) data,
1518                              sizeof(indirect) );
1519
1520         DRM_DEBUG( "indirect: idx=%d s=%d e=%d d=%d\n",
1521                    indirect.idx, indirect.start,
1522                    indirect.end, indirect.discard );
1523
1524         if ( indirect.idx < 0 || indirect.idx >= dma->buf_count ) {
1525                 DRM_ERROR( "buffer index %d (of %d max)\n",
1526                            indirect.idx, dma->buf_count - 1 );
1527                 return DRM_ERR(EINVAL);
1528         }
1529
1530         buf = dma->buflist[indirect.idx];
1531         buf_priv = buf->dev_private;
1532
1533         if ( buf->filp != filp ) {
1534                 DRM_ERROR( "process %d using buffer owned by %p\n",
1535                            DRM_CURRENTPID, buf->filp );
1536                 return DRM_ERR(EINVAL);
1537         }
1538         if ( buf->pending ) {
1539                 DRM_ERROR( "sending pending buffer %d\n", indirect.idx );
1540                 return DRM_ERR(EINVAL);
1541         }
1542
1543         if ( indirect.start < buf->used ) {
1544                 DRM_ERROR( "reusing indirect: start=0x%x actual=0x%x\n",
1545                            indirect.start, buf->used );
1546                 return DRM_ERR(EINVAL);
1547         }
1548
1549         RING_SPACE_TEST_WITH_RETURN( dev_priv );
1550         VB_AGE_TEST_WITH_RETURN( dev_priv );
1551
1552         buf->used = indirect.end;
1553         buf_priv->discard = indirect.discard;
1554
1555 #if 0
1556         /* Wait for the 3D stream to idle before the indirect buffer
1557          * containing 2D acceleration commands is processed.
1558          */
1559         BEGIN_RING( 2 );
1560         RADEON_WAIT_UNTIL_3D_IDLE();
1561         ADVANCE_RING();
1562 #endif
1563
1564         /* Dispatch the indirect buffer full of commands from the
1565          * X server.  This is insecure and is thus only available to
1566          * privileged clients.
1567          */
1568         r128_cce_dispatch_indirect( dev, buf, indirect.start, indirect.end );
1569
1570         return 0;
1571 }
1572
1573 int r128_getparam( DRM_IOCTL_ARGS )
1574 {
1575         DRM_DEVICE;
1576         drm_r128_private_t *dev_priv = dev->dev_private;
1577         drm_r128_getparam_t param;
1578         int value;
1579
1580         if ( !dev_priv ) {
1581                 DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
1582                 return DRM_ERR(EINVAL);
1583         }
1584
1585         DRM_COPY_FROM_USER_IOCTL( param, (drm_r128_getparam_t *)data,
1586                              sizeof(param) );
1587
1588         DRM_DEBUG( "pid=%d\n", DRM_CURRENTPID );
1589
1590         switch( param.param ) {
1591         case R128_PARAM_IRQ_NR:
1592                 value = dev->irq;
1593                 break;
1594         default:
1595                 return DRM_ERR(EINVAL);
1596         }
1597
1598         if ( DRM_COPY_TO_USER( param.value, &value, sizeof(int) ) ) {
1599                 DRM_ERROR( "copy_to_user\n" );
1600                 return DRM_ERR(EFAULT);
1601         }
1602         
1603         return 0;
1604 }