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