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