vserver 1.9.3
[linux-2.6.git] / drivers / char / drm / radeon_state.c
1 /* radeon_state.c -- State support for Radeon -*- linux-c -*-
2  *
3  * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice (including the next
14  * paragraph) shall be included in all copies or substantial portions of the
15  * Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20  * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23  * DEALINGS IN THE SOFTWARE.
24  *
25  * Authors:
26  *    Gareth Hughes <gareth@valinux.com>
27  *    Kevin E. Martin <martin@valinux.com>
28  */
29
30 #include "radeon.h"
31 #include "drmP.h"
32 #include "drm.h"
33 #include "drm_sarea.h"
34 #include "radeon_drm.h"
35 #include "radeon_drv.h"
36
37
38 /* ================================================================
39  * Helper functions for client state checking and fixup
40  */
41
42 static __inline__ int radeon_check_and_fixup_offset( drm_radeon_private_t *dev_priv,
43                                                      drm_file_t *filp_priv,
44                                                      u32 *offset ) {
45         u32 off = *offset;
46         struct drm_radeon_driver_file_fields *radeon_priv;
47
48         if ( off >= dev_priv->fb_location &&
49              off < ( dev_priv->gart_vm_start + dev_priv->gart_size ) )
50                 return 0;
51
52         radeon_priv = filp_priv->driver_priv;
53         off += radeon_priv->radeon_fb_delta;
54
55         DRM_DEBUG( "offset fixed up to 0x%x\n", off );
56
57         if ( off < dev_priv->fb_location ||
58              off >= ( dev_priv->gart_vm_start + dev_priv->gart_size ) )
59                 return DRM_ERR( EINVAL );
60
61         *offset = off;
62
63         return 0;
64 }
65
66 static __inline__ int radeon_check_and_fixup_offset_user( drm_radeon_private_t *dev_priv,
67                                                           drm_file_t *filp_priv,
68                                                           u32 __user *offset ) {
69         u32 off;
70
71         DRM_GET_USER_UNCHECKED( off, offset );
72
73         if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, &off ) )
74                 return DRM_ERR( EINVAL );
75
76         DRM_PUT_USER_UNCHECKED( offset, off );
77
78         return 0;
79 }
80
81 static __inline__ int radeon_check_and_fixup_packets( drm_radeon_private_t *dev_priv,
82                                                       drm_file_t *filp_priv,
83                                                       int id,
84                                                       u32 __user *data ) {
85         switch ( id ) {
86
87         case RADEON_EMIT_PP_MISC:
88                 if ( radeon_check_and_fixup_offset_user( dev_priv, filp_priv,
89                                                          &data[( RADEON_RB3D_DEPTHOFFSET
90                                                                  - RADEON_PP_MISC ) / 4] ) ) {
91                         DRM_ERROR( "Invalid depth buffer offset\n" );
92                         return DRM_ERR( EINVAL );
93                 }
94                 break;
95
96         case RADEON_EMIT_PP_CNTL:
97                 if ( radeon_check_and_fixup_offset_user( dev_priv, filp_priv,
98                                                          &data[( RADEON_RB3D_COLOROFFSET
99                                                                  - RADEON_PP_CNTL ) / 4] ) ) {
100                         DRM_ERROR( "Invalid colour buffer offset\n" );
101                         return DRM_ERR( EINVAL );
102                 }
103                 break;
104
105         case R200_EMIT_PP_TXOFFSET_0:
106         case R200_EMIT_PP_TXOFFSET_1:
107         case R200_EMIT_PP_TXOFFSET_2:
108         case R200_EMIT_PP_TXOFFSET_3:
109         case R200_EMIT_PP_TXOFFSET_4:
110         case R200_EMIT_PP_TXOFFSET_5:
111                 if ( radeon_check_and_fixup_offset_user( dev_priv, filp_priv,
112                                                          &data[0] ) ) {
113                         DRM_ERROR( "Invalid R200 texture offset\n" );
114                         return DRM_ERR( EINVAL );
115                 }
116                 break;
117
118         case RADEON_EMIT_PP_TXFILTER_0:
119         case RADEON_EMIT_PP_TXFILTER_1:
120         case RADEON_EMIT_PP_TXFILTER_2:
121                 if ( radeon_check_and_fixup_offset_user( dev_priv, filp_priv,
122                                                          &data[( RADEON_PP_TXOFFSET_0
123                                                                  - RADEON_PP_TXFILTER_0 ) / 4] ) ) {
124                         DRM_ERROR( "Invalid R100 texture offset\n" );
125                         return DRM_ERR( EINVAL );
126                 }
127                 break;
128
129         case R200_EMIT_PP_CUBIC_OFFSETS_0:
130         case R200_EMIT_PP_CUBIC_OFFSETS_1:
131         case R200_EMIT_PP_CUBIC_OFFSETS_2:
132         case R200_EMIT_PP_CUBIC_OFFSETS_3:
133         case R200_EMIT_PP_CUBIC_OFFSETS_4:
134         case R200_EMIT_PP_CUBIC_OFFSETS_5: {
135                 int i;
136                 for ( i = 0; i < 5; i++ ) {
137                         if ( radeon_check_and_fixup_offset_user( dev_priv,
138                                                                  filp_priv,
139                                                                  &data[i] ) ) {
140                                 DRM_ERROR( "Invalid R200 cubic texture offset\n" );
141                                 return DRM_ERR( EINVAL );
142                         }
143                 }
144                 break;
145         }
146
147         case RADEON_EMIT_RB3D_COLORPITCH:
148         case RADEON_EMIT_RE_LINE_PATTERN:
149         case RADEON_EMIT_SE_LINE_WIDTH:
150         case RADEON_EMIT_PP_LUM_MATRIX:
151         case RADEON_EMIT_PP_ROT_MATRIX_0:
152         case RADEON_EMIT_RB3D_STENCILREFMASK:
153         case RADEON_EMIT_SE_VPORT_XSCALE:
154         case RADEON_EMIT_SE_CNTL:
155         case RADEON_EMIT_SE_CNTL_STATUS:
156         case RADEON_EMIT_RE_MISC:
157         case RADEON_EMIT_PP_BORDER_COLOR_0:
158         case RADEON_EMIT_PP_BORDER_COLOR_1:
159         case RADEON_EMIT_PP_BORDER_COLOR_2:
160         case RADEON_EMIT_SE_ZBIAS_FACTOR:
161         case RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT:
162         case RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED:
163         case R200_EMIT_PP_TXCBLEND_0:
164         case R200_EMIT_PP_TXCBLEND_1:
165         case R200_EMIT_PP_TXCBLEND_2:
166         case R200_EMIT_PP_TXCBLEND_3:
167         case R200_EMIT_PP_TXCBLEND_4:
168         case R200_EMIT_PP_TXCBLEND_5:
169         case R200_EMIT_PP_TXCBLEND_6:
170         case R200_EMIT_PP_TXCBLEND_7:
171         case R200_EMIT_TCL_LIGHT_MODEL_CTL_0:
172         case R200_EMIT_TFACTOR_0:
173         case R200_EMIT_VTX_FMT_0:
174         case R200_EMIT_VAP_CTL:
175         case R200_EMIT_MATRIX_SELECT_0:
176         case R200_EMIT_TEX_PROC_CTL_2:
177         case R200_EMIT_TCL_UCP_VERT_BLEND_CTL:
178         case R200_EMIT_PP_TXFILTER_0:
179         case R200_EMIT_PP_TXFILTER_1:
180         case R200_EMIT_PP_TXFILTER_2:
181         case R200_EMIT_PP_TXFILTER_3:
182         case R200_EMIT_PP_TXFILTER_4:
183         case R200_EMIT_PP_TXFILTER_5:
184         case R200_EMIT_VTE_CNTL:
185         case R200_EMIT_OUTPUT_VTX_COMP_SEL:
186         case R200_EMIT_PP_TAM_DEBUG3:
187         case R200_EMIT_PP_CNTL_X:
188         case R200_EMIT_RB3D_DEPTHXY_OFFSET:
189         case R200_EMIT_RE_AUX_SCISSOR_CNTL:
190         case R200_EMIT_RE_SCISSOR_TL_0:
191         case R200_EMIT_RE_SCISSOR_TL_1:
192         case R200_EMIT_RE_SCISSOR_TL_2:
193         case R200_EMIT_SE_VAP_CNTL_STATUS:
194         case R200_EMIT_SE_VTX_STATE_CNTL:
195         case R200_EMIT_RE_POINTSIZE:
196         case R200_EMIT_TCL_INPUT_VTX_VECTOR_ADDR_0:
197         case R200_EMIT_PP_CUBIC_FACES_0:
198         case R200_EMIT_PP_CUBIC_FACES_1:
199         case R200_EMIT_PP_CUBIC_FACES_2:
200         case R200_EMIT_PP_CUBIC_FACES_3:
201         case R200_EMIT_PP_CUBIC_FACES_4:
202         case R200_EMIT_PP_CUBIC_FACES_5:
203         case RADEON_EMIT_PP_TEX_SIZE_0:
204         case RADEON_EMIT_PP_TEX_SIZE_1:
205         case RADEON_EMIT_PP_TEX_SIZE_2:
206         case R200_EMIT_RB3D_BLENDCOLOR:
207                 /* These packets don't contain memory offsets */
208                 break;
209
210         default:
211                 DRM_ERROR( "Unknown state packet ID %d\n", id );
212                 return DRM_ERR( EINVAL );
213         }
214
215         return 0;
216 }
217
218 static __inline__ int radeon_check_and_fixup_packet3( drm_radeon_private_t *dev_priv,
219                                                       drm_file_t *filp_priv,
220                                                       drm_radeon_cmd_buffer_t *cmdbuf,
221                                                       unsigned int *cmdsz ) {
222         u32 tmp[4];
223         u32 __user *cmd = (u32 __user *)cmdbuf->buf;
224
225         if ( DRM_COPY_FROM_USER_UNCHECKED( tmp, cmd, sizeof( tmp ) ) ) {
226                 DRM_ERROR( "Failed to copy data from user space\n" );
227                 return DRM_ERR( EFAULT );
228         }
229
230         *cmdsz = 2 + ( ( tmp[0] & RADEON_CP_PACKET_COUNT_MASK ) >> 16 );
231
232         if ( ( tmp[0] & 0xc0000000 ) != RADEON_CP_PACKET3 ) {
233                 DRM_ERROR( "Not a type 3 packet\n" );
234                 return DRM_ERR( EINVAL );
235         }
236
237         if ( 4 * *cmdsz > cmdbuf->bufsz ) {
238                 DRM_ERROR( "Packet size larger than size of data provided\n" );
239                 return DRM_ERR( EINVAL );
240         }
241
242         /* Check client state and fix it up if necessary */
243         if ( tmp[0] & 0x8000 ) { /* MSB of opcode: next DWORD GUI_CNTL */
244                 u32 offset;
245
246                 if ( tmp[1] & ( RADEON_GMC_SRC_PITCH_OFFSET_CNTL
247                               | RADEON_GMC_DST_PITCH_OFFSET_CNTL ) ) {
248                         offset = tmp[2] << 10;
249                         if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, &offset ) ) {
250                                 DRM_ERROR( "Invalid first packet offset\n" );
251                                 return DRM_ERR( EINVAL );
252                         }
253                         tmp[2] = ( tmp[2] & 0xffc00000 ) | offset >> 10;
254                 }
255
256                 if ( ( tmp[1] & RADEON_GMC_SRC_PITCH_OFFSET_CNTL ) &&
257                      ( tmp[1] & RADEON_GMC_DST_PITCH_OFFSET_CNTL ) ) {
258                         offset = tmp[3] << 10;
259                         if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, &offset ) ) {
260                                 DRM_ERROR( "Invalid second packet offset\n" );
261                                 return DRM_ERR( EINVAL );
262                         }
263                         tmp[3] = ( tmp[3] & 0xffc00000 ) | offset >> 10;
264                 }
265
266                 if ( DRM_COPY_TO_USER_UNCHECKED( cmd, tmp, sizeof( tmp ) ) ) {
267                         DRM_ERROR( "Failed to copy data to user space\n" );
268                         return DRM_ERR( EFAULT );
269                 }
270         }
271
272         return 0;
273 }
274
275
276 /* ================================================================
277  * CP hardware state programming functions
278  */
279
280 static __inline__ void radeon_emit_clip_rect( drm_radeon_private_t *dev_priv,
281                                           drm_clip_rect_t *box )
282 {
283         RING_LOCALS;
284
285         DRM_DEBUG( "   box:  x1=%d y1=%d  x2=%d y2=%d\n",
286                    box->x1, box->y1, box->x2, box->y2 );
287
288         BEGIN_RING( 4 );
289         OUT_RING( CP_PACKET0( RADEON_RE_TOP_LEFT, 0 ) );
290         OUT_RING( (box->y1 << 16) | box->x1 );
291         OUT_RING( CP_PACKET0( RADEON_RE_WIDTH_HEIGHT, 0 ) );
292         OUT_RING( ((box->y2 - 1) << 16) | (box->x2 - 1) );
293         ADVANCE_RING();
294 }
295
296 /* Emit 1.1 state
297  */
298 static int radeon_emit_state( drm_radeon_private_t *dev_priv,
299                               drm_file_t *filp_priv,
300                               drm_radeon_context_regs_t *ctx,
301                               drm_radeon_texture_regs_t *tex,
302                               unsigned int dirty )
303 {
304         RING_LOCALS;
305         DRM_DEBUG( "dirty=0x%08x\n", dirty );
306
307         if ( dirty & RADEON_UPLOAD_CONTEXT ) {
308                 if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
309                                                     &ctx->rb3d_depthoffset ) ) {
310                         DRM_ERROR( "Invalid depth buffer offset\n" );
311                         return DRM_ERR( EINVAL );
312                 }
313
314                 if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
315                                                     &ctx->rb3d_coloroffset ) ) {
316                         DRM_ERROR( "Invalid depth buffer offset\n" );
317                         return DRM_ERR( EINVAL );
318                 }
319
320                 BEGIN_RING( 14 );
321                 OUT_RING( CP_PACKET0( RADEON_PP_MISC, 6 ) );
322                 OUT_RING( ctx->pp_misc );
323                 OUT_RING( ctx->pp_fog_color );
324                 OUT_RING( ctx->re_solid_color );
325                 OUT_RING( ctx->rb3d_blendcntl );
326                 OUT_RING( ctx->rb3d_depthoffset );
327                 OUT_RING( ctx->rb3d_depthpitch );
328                 OUT_RING( ctx->rb3d_zstencilcntl );
329                 OUT_RING( CP_PACKET0( RADEON_PP_CNTL, 2 ) );
330                 OUT_RING( ctx->pp_cntl );
331                 OUT_RING( ctx->rb3d_cntl );
332                 OUT_RING( ctx->rb3d_coloroffset );
333                 OUT_RING( CP_PACKET0( RADEON_RB3D_COLORPITCH, 0 ) );
334                 OUT_RING( ctx->rb3d_colorpitch );
335                 ADVANCE_RING();
336         }
337
338         if ( dirty & RADEON_UPLOAD_VERTFMT ) {
339                 BEGIN_RING( 2 );
340                 OUT_RING( CP_PACKET0( RADEON_SE_COORD_FMT, 0 ) );
341                 OUT_RING( ctx->se_coord_fmt );
342                 ADVANCE_RING();
343         }
344
345         if ( dirty & RADEON_UPLOAD_LINE ) {
346                 BEGIN_RING( 5 );
347                 OUT_RING( CP_PACKET0( RADEON_RE_LINE_PATTERN, 1 ) );
348                 OUT_RING( ctx->re_line_pattern );
349                 OUT_RING( ctx->re_line_state );
350                 OUT_RING( CP_PACKET0( RADEON_SE_LINE_WIDTH, 0 ) );
351                 OUT_RING( ctx->se_line_width );
352                 ADVANCE_RING();
353         }
354
355         if ( dirty & RADEON_UPLOAD_BUMPMAP ) {
356                 BEGIN_RING( 5 );
357                 OUT_RING( CP_PACKET0( RADEON_PP_LUM_MATRIX, 0 ) );
358                 OUT_RING( ctx->pp_lum_matrix );
359                 OUT_RING( CP_PACKET0( RADEON_PP_ROT_MATRIX_0, 1 ) );
360                 OUT_RING( ctx->pp_rot_matrix_0 );
361                 OUT_RING( ctx->pp_rot_matrix_1 );
362                 ADVANCE_RING();
363         }
364
365         if ( dirty & RADEON_UPLOAD_MASKS ) {
366                 BEGIN_RING( 4 );
367                 OUT_RING( CP_PACKET0( RADEON_RB3D_STENCILREFMASK, 2 ) );
368                 OUT_RING( ctx->rb3d_stencilrefmask );
369                 OUT_RING( ctx->rb3d_ropcntl );
370                 OUT_RING( ctx->rb3d_planemask );
371                 ADVANCE_RING();
372         }
373
374         if ( dirty & RADEON_UPLOAD_VIEWPORT ) {
375                 BEGIN_RING( 7 );
376                 OUT_RING( CP_PACKET0( RADEON_SE_VPORT_XSCALE, 5 ) );
377                 OUT_RING( ctx->se_vport_xscale );
378                 OUT_RING( ctx->se_vport_xoffset );
379                 OUT_RING( ctx->se_vport_yscale );
380                 OUT_RING( ctx->se_vport_yoffset );
381                 OUT_RING( ctx->se_vport_zscale );
382                 OUT_RING( ctx->se_vport_zoffset );
383                 ADVANCE_RING();
384         }
385
386         if ( dirty & RADEON_UPLOAD_SETUP ) {
387                 BEGIN_RING( 4 );
388                 OUT_RING( CP_PACKET0( RADEON_SE_CNTL, 0 ) );
389                 OUT_RING( ctx->se_cntl );
390                 OUT_RING( CP_PACKET0( RADEON_SE_CNTL_STATUS, 0 ) );
391                 OUT_RING( ctx->se_cntl_status );
392                 ADVANCE_RING();
393         }
394
395         if ( dirty & RADEON_UPLOAD_MISC ) {
396                 BEGIN_RING( 2 );
397                 OUT_RING( CP_PACKET0( RADEON_RE_MISC, 0 ) );
398                 OUT_RING( ctx->re_misc );
399                 ADVANCE_RING();
400         }
401
402         if ( dirty & RADEON_UPLOAD_TEX0 ) {
403                 if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
404                                                     &tex[0].pp_txoffset ) ) {
405                         DRM_ERROR( "Invalid texture offset for unit 0\n" );
406                         return DRM_ERR( EINVAL );
407                 }
408
409                 BEGIN_RING( 9 );
410                 OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_0, 5 ) );
411                 OUT_RING( tex[0].pp_txfilter );
412                 OUT_RING( tex[0].pp_txformat );
413                 OUT_RING( tex[0].pp_txoffset );
414                 OUT_RING( tex[0].pp_txcblend );
415                 OUT_RING( tex[0].pp_txablend );
416                 OUT_RING( tex[0].pp_tfactor );
417                 OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_0, 0 ) );
418                 OUT_RING( tex[0].pp_border_color );
419                 ADVANCE_RING();
420         }
421
422         if ( dirty & RADEON_UPLOAD_TEX1 ) {
423                 if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
424                                                     &tex[1].pp_txoffset ) ) {
425                         DRM_ERROR( "Invalid texture offset for unit 1\n" );
426                         return DRM_ERR( EINVAL );
427                 }
428
429                 BEGIN_RING( 9 );
430                 OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_1, 5 ) );
431                 OUT_RING( tex[1].pp_txfilter );
432                 OUT_RING( tex[1].pp_txformat );
433                 OUT_RING( tex[1].pp_txoffset );
434                 OUT_RING( tex[1].pp_txcblend );
435                 OUT_RING( tex[1].pp_txablend );
436                 OUT_RING( tex[1].pp_tfactor );
437                 OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_1, 0 ) );
438                 OUT_RING( tex[1].pp_border_color );
439                 ADVANCE_RING();
440         }
441
442         if ( dirty & RADEON_UPLOAD_TEX2 ) {
443                 if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
444                                                     &tex[2].pp_txoffset ) ) {
445                         DRM_ERROR( "Invalid texture offset for unit 2\n" );
446                         return DRM_ERR( EINVAL );
447                 }
448
449                 BEGIN_RING( 9 );
450                 OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_2, 5 ) );
451                 OUT_RING( tex[2].pp_txfilter );
452                 OUT_RING( tex[2].pp_txformat );
453                 OUT_RING( tex[2].pp_txoffset );
454                 OUT_RING( tex[2].pp_txcblend );
455                 OUT_RING( tex[2].pp_txablend );
456                 OUT_RING( tex[2].pp_tfactor );
457                 OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_2, 0 ) );
458                 OUT_RING( tex[2].pp_border_color );
459                 ADVANCE_RING();
460         }
461
462         return 0;
463 }
464
465 /* Emit 1.2 state
466  */
467 static int radeon_emit_state2( drm_radeon_private_t *dev_priv,
468                                drm_file_t *filp_priv,
469                                drm_radeon_state_t *state )
470 {
471         RING_LOCALS;
472
473         if (state->dirty & RADEON_UPLOAD_ZBIAS) {
474                 BEGIN_RING( 3 );
475                 OUT_RING( CP_PACKET0( RADEON_SE_ZBIAS_FACTOR, 1 ) );
476                 OUT_RING( state->context2.se_zbias_factor ); 
477                 OUT_RING( state->context2.se_zbias_constant ); 
478                 ADVANCE_RING();
479         }
480
481         return radeon_emit_state( dev_priv, filp_priv, &state->context,
482                            state->tex, state->dirty );
483 }
484
485 /* New (1.3) state mechanism.  3 commands (packet, scalar, vector) in
486  * 1.3 cmdbuffers allow all previous state to be updated as well as
487  * the tcl scalar and vector areas.  
488  */
489 static struct { 
490         int start; 
491         int len; 
492         const char *name;
493 } packet[RADEON_MAX_STATE_PACKETS] = {
494         { RADEON_PP_MISC,7,"RADEON_PP_MISC" },
495         { RADEON_PP_CNTL,3,"RADEON_PP_CNTL" },
496         { RADEON_RB3D_COLORPITCH,1,"RADEON_RB3D_COLORPITCH" },
497         { RADEON_RE_LINE_PATTERN,2,"RADEON_RE_LINE_PATTERN" },
498         { RADEON_SE_LINE_WIDTH,1,"RADEON_SE_LINE_WIDTH" },
499         { RADEON_PP_LUM_MATRIX,1,"RADEON_PP_LUM_MATRIX" },
500         { RADEON_PP_ROT_MATRIX_0,2,"RADEON_PP_ROT_MATRIX_0" },
501         { RADEON_RB3D_STENCILREFMASK,3,"RADEON_RB3D_STENCILREFMASK" },
502         { RADEON_SE_VPORT_XSCALE,6,"RADEON_SE_VPORT_XSCALE" },
503         { RADEON_SE_CNTL,2,"RADEON_SE_CNTL" },
504         { RADEON_SE_CNTL_STATUS,1,"RADEON_SE_CNTL_STATUS" },
505         { RADEON_RE_MISC,1,"RADEON_RE_MISC" },
506         { RADEON_PP_TXFILTER_0,6,"RADEON_PP_TXFILTER_0" },
507         { RADEON_PP_BORDER_COLOR_0,1,"RADEON_PP_BORDER_COLOR_0" },
508         { RADEON_PP_TXFILTER_1,6,"RADEON_PP_TXFILTER_1" },
509         { RADEON_PP_BORDER_COLOR_1,1,"RADEON_PP_BORDER_COLOR_1" },
510         { RADEON_PP_TXFILTER_2,6,"RADEON_PP_TXFILTER_2" },
511         { RADEON_PP_BORDER_COLOR_2,1,"RADEON_PP_BORDER_COLOR_2" },
512         { RADEON_SE_ZBIAS_FACTOR,2,"RADEON_SE_ZBIAS_FACTOR" },
513         { RADEON_SE_TCL_OUTPUT_VTX_FMT,11,"RADEON_SE_TCL_OUTPUT_VTX_FMT" },
514         { RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED,17,"RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED" },
515         { R200_PP_TXCBLEND_0, 4, "R200_PP_TXCBLEND_0" },
516         { R200_PP_TXCBLEND_1, 4, "R200_PP_TXCBLEND_1" },
517         { R200_PP_TXCBLEND_2, 4, "R200_PP_TXCBLEND_2" },
518         { R200_PP_TXCBLEND_3, 4, "R200_PP_TXCBLEND_3" },
519         { R200_PP_TXCBLEND_4, 4, "R200_PP_TXCBLEND_4" },
520         { R200_PP_TXCBLEND_5, 4, "R200_PP_TXCBLEND_5" },
521         { R200_PP_TXCBLEND_6, 4, "R200_PP_TXCBLEND_6" },
522         { R200_PP_TXCBLEND_7, 4, "R200_PP_TXCBLEND_7" },
523         { R200_SE_TCL_LIGHT_MODEL_CTL_0, 6, "R200_SE_TCL_LIGHT_MODEL_CTL_0" },
524         { R200_PP_TFACTOR_0, 6, "R200_PP_TFACTOR_0" },
525         { R200_SE_VTX_FMT_0, 4, "R200_SE_VTX_FMT_0" },
526         { R200_SE_VAP_CNTL, 1, "R200_SE_VAP_CNTL" },
527         { R200_SE_TCL_MATRIX_SEL_0, 5, "R200_SE_TCL_MATRIX_SEL_0" },
528         { R200_SE_TCL_TEX_PROC_CTL_2, 5, "R200_SE_TCL_TEX_PROC_CTL_2" },
529         { R200_SE_TCL_UCP_VERT_BLEND_CTL, 1, "R200_SE_TCL_UCP_VERT_BLEND_CTL" },
530         { R200_PP_TXFILTER_0, 6, "R200_PP_TXFILTER_0" },
531         { R200_PP_TXFILTER_1, 6, "R200_PP_TXFILTER_1" },
532         { R200_PP_TXFILTER_2, 6, "R200_PP_TXFILTER_2" },
533         { R200_PP_TXFILTER_3, 6, "R200_PP_TXFILTER_3" },
534         { R200_PP_TXFILTER_4, 6, "R200_PP_TXFILTER_4" },
535         { R200_PP_TXFILTER_5, 6, "R200_PP_TXFILTER_5" },
536         { R200_PP_TXOFFSET_0, 1, "R200_PP_TXOFFSET_0" },
537         { R200_PP_TXOFFSET_1, 1, "R200_PP_TXOFFSET_1" },
538         { R200_PP_TXOFFSET_2, 1, "R200_PP_TXOFFSET_2" },
539         { R200_PP_TXOFFSET_3, 1, "R200_PP_TXOFFSET_3" },
540         { R200_PP_TXOFFSET_4, 1, "R200_PP_TXOFFSET_4" },
541         { R200_PP_TXOFFSET_5, 1, "R200_PP_TXOFFSET_5" },
542         { R200_SE_VTE_CNTL, 1, "R200_SE_VTE_CNTL" },
543         { R200_SE_TCL_OUTPUT_VTX_COMP_SEL, 1, "R200_SE_TCL_OUTPUT_VTX_COMP_SEL" },
544         { R200_PP_TAM_DEBUG3, 1, "R200_PP_TAM_DEBUG3" },
545         { R200_PP_CNTL_X, 1, "R200_PP_CNTL_X" }, 
546         { R200_RB3D_DEPTHXY_OFFSET, 1, "R200_RB3D_DEPTHXY_OFFSET" }, 
547         { R200_RE_AUX_SCISSOR_CNTL, 1, "R200_RE_AUX_SCISSOR_CNTL" }, 
548         { R200_RE_SCISSOR_TL_0, 2, "R200_RE_SCISSOR_TL_0" }, 
549         { R200_RE_SCISSOR_TL_1, 2, "R200_RE_SCISSOR_TL_1" }, 
550         { R200_RE_SCISSOR_TL_2, 2, "R200_RE_SCISSOR_TL_2" }, 
551         { R200_SE_VAP_CNTL_STATUS, 1, "R200_SE_VAP_CNTL_STATUS" }, 
552         { R200_SE_VTX_STATE_CNTL, 1, "R200_SE_VTX_STATE_CNTL" }, 
553         { R200_RE_POINTSIZE, 1, "R200_RE_POINTSIZE" }, 
554         { R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0, 4, "R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0" },
555         { R200_PP_CUBIC_FACES_0, 1, "R200_PP_CUBIC_FACES_0" }, /* 61 */
556         { R200_PP_CUBIC_OFFSET_F1_0, 5, "R200_PP_CUBIC_OFFSET_F1_0" }, /* 62 */
557         { R200_PP_CUBIC_FACES_1, 1, "R200_PP_CUBIC_FACES_1" },
558         { R200_PP_CUBIC_OFFSET_F1_1, 5, "R200_PP_CUBIC_OFFSET_F1_1" },
559         { R200_PP_CUBIC_FACES_2, 1, "R200_PP_CUBIC_FACES_2" },
560         { R200_PP_CUBIC_OFFSET_F1_2, 5, "R200_PP_CUBIC_OFFSET_F1_2" },
561         { R200_PP_CUBIC_FACES_3, 1, "R200_PP_CUBIC_FACES_3" },
562         { R200_PP_CUBIC_OFFSET_F1_3, 5, "R200_PP_CUBIC_OFFSET_F1_3" },
563         { R200_PP_CUBIC_FACES_4, 1, "R200_PP_CUBIC_FACES_4" },
564         { R200_PP_CUBIC_OFFSET_F1_4, 5, "R200_PP_CUBIC_OFFSET_F1_4" },
565         { R200_PP_CUBIC_FACES_5, 1, "R200_PP_CUBIC_FACES_5" },
566         { R200_PP_CUBIC_OFFSET_F1_5, 5, "R200_PP_CUBIC_OFFSET_F1_5" },
567         { RADEON_PP_TEX_SIZE_0, 2, "RADEON_PP_TEX_SIZE_0" },
568         { RADEON_PP_TEX_SIZE_1, 2, "RADEON_PP_TEX_SIZE_1" },
569         { RADEON_PP_TEX_SIZE_2, 2, "RADEON_PP_TEX_SIZE_2" },
570         { R200_RB3D_BLENDCOLOR, 3, "R200_RB3D_BLENDCOLOR" },
571 };
572
573
574
575 /* ================================================================
576  * Performance monitoring functions
577  */
578
579 static void radeon_clear_box( drm_radeon_private_t *dev_priv,
580                               int x, int y, int w, int h,
581                               int r, int g, int b )
582 {
583         u32 color;
584         RING_LOCALS;
585
586         x += dev_priv->sarea_priv->boxes[0].x1;
587         y += dev_priv->sarea_priv->boxes[0].y1;
588
589         switch ( dev_priv->color_fmt ) {
590         case RADEON_COLOR_FORMAT_RGB565:
591                 color = (((r & 0xf8) << 8) |
592                          ((g & 0xfc) << 3) |
593                          ((b & 0xf8) >> 3));
594                 break;
595         case RADEON_COLOR_FORMAT_ARGB8888:
596         default:
597                 color = (((0xff) << 24) | (r << 16) | (g <<  8) | b);
598                 break;
599         }
600
601         BEGIN_RING( 4 );
602         RADEON_WAIT_UNTIL_3D_IDLE();            
603         OUT_RING( CP_PACKET0( RADEON_DP_WRITE_MASK, 0 ) );
604         OUT_RING( 0xffffffff );
605         ADVANCE_RING();
606
607         BEGIN_RING( 6 );
608
609         OUT_RING( CP_PACKET3( RADEON_CNTL_PAINT_MULTI, 4 ) );
610         OUT_RING( RADEON_GMC_DST_PITCH_OFFSET_CNTL |
611                   RADEON_GMC_BRUSH_SOLID_COLOR |
612                   (dev_priv->color_fmt << 8) |
613                   RADEON_GMC_SRC_DATATYPE_COLOR |
614                   RADEON_ROP3_P |
615                   RADEON_GMC_CLR_CMP_CNTL_DIS );
616
617         if ( dev_priv->page_flipping && dev_priv->current_page == 1 ) { 
618                 OUT_RING( dev_priv->front_pitch_offset );
619         } else {         
620                 OUT_RING( dev_priv->back_pitch_offset );
621         } 
622
623         OUT_RING( color );
624
625         OUT_RING( (x << 16) | y );
626         OUT_RING( (w << 16) | h );
627
628         ADVANCE_RING();
629 }
630
631 static void radeon_cp_performance_boxes( drm_radeon_private_t *dev_priv )
632 {
633         /* Collapse various things into a wait flag -- trying to
634          * guess if userspase slept -- better just to have them tell us.
635          */
636         if (dev_priv->stats.last_frame_reads > 1 ||
637             dev_priv->stats.last_clear_reads > dev_priv->stats.clears) {
638                 dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
639         }
640
641         if (dev_priv->stats.freelist_loops) {
642                 dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
643         }
644
645         /* Purple box for page flipping
646          */
647         if ( dev_priv->stats.boxes & RADEON_BOX_FLIP ) 
648                 radeon_clear_box( dev_priv, 4, 4, 8, 8, 255, 0, 255 );
649
650         /* Red box if we have to wait for idle at any point
651          */
652         if ( dev_priv->stats.boxes & RADEON_BOX_WAIT_IDLE ) 
653                 radeon_clear_box( dev_priv, 16, 4, 8, 8, 255, 0, 0 );
654
655         /* Blue box: lost context?
656          */
657
658         /* Yellow box for texture swaps
659          */
660         if ( dev_priv->stats.boxes & RADEON_BOX_TEXTURE_LOAD ) 
661                 radeon_clear_box( dev_priv, 40, 4, 8, 8, 255, 255, 0 );
662
663         /* Green box if hardware never idles (as far as we can tell)
664          */
665         if ( !(dev_priv->stats.boxes & RADEON_BOX_DMA_IDLE) ) 
666                 radeon_clear_box( dev_priv, 64, 4, 8, 8, 0, 255, 0 );
667
668
669         /* Draw bars indicating number of buffers allocated 
670          * (not a great measure, easily confused)
671          */
672         if (dev_priv->stats.requested_bufs) {
673                 if (dev_priv->stats.requested_bufs > 100)
674                         dev_priv->stats.requested_bufs = 100;
675
676                 radeon_clear_box( dev_priv, 4, 16,  
677                                   dev_priv->stats.requested_bufs, 4,
678                                   196, 128, 128 );
679         }
680
681         memset( &dev_priv->stats, 0, sizeof(dev_priv->stats) );
682
683 }
684 /* ================================================================
685  * CP command dispatch functions
686  */
687
688 static void radeon_cp_dispatch_clear( drm_device_t *dev,
689                                       drm_radeon_clear_t *clear,
690                                       drm_radeon_clear_rect_t *depth_boxes )
691 {
692         drm_radeon_private_t *dev_priv = dev->dev_private;
693         drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
694         drm_radeon_depth_clear_t *depth_clear = &dev_priv->depth_clear;
695         int nbox = sarea_priv->nbox;
696         drm_clip_rect_t *pbox = sarea_priv->boxes;
697         unsigned int flags = clear->flags;
698         u32 rb3d_cntl = 0, rb3d_stencilrefmask= 0;
699         int i;
700         RING_LOCALS;
701         DRM_DEBUG( "flags = 0x%x\n", flags );
702
703         dev_priv->stats.clears++;
704
705         if ( dev_priv->page_flipping && dev_priv->current_page == 1 ) {
706                 unsigned int tmp = flags;
707
708                 flags &= ~(RADEON_FRONT | RADEON_BACK);
709                 if ( tmp & RADEON_FRONT ) flags |= RADEON_BACK;
710                 if ( tmp & RADEON_BACK )  flags |= RADEON_FRONT;
711         }
712
713         if ( flags & (RADEON_FRONT | RADEON_BACK) ) {
714
715                 BEGIN_RING( 4 );
716
717                 /* Ensure the 3D stream is idle before doing a
718                  * 2D fill to clear the front or back buffer.
719                  */
720                 RADEON_WAIT_UNTIL_3D_IDLE();
721                 
722                 OUT_RING( CP_PACKET0( RADEON_DP_WRITE_MASK, 0 ) );
723                 OUT_RING( clear->color_mask );
724
725                 ADVANCE_RING();
726
727                 /* Make sure we restore the 3D state next time.
728                  */
729                 dev_priv->sarea_priv->ctx_owner = 0;
730
731                 for ( i = 0 ; i < nbox ; i++ ) {
732                         int x = pbox[i].x1;
733                         int y = pbox[i].y1;
734                         int w = pbox[i].x2 - x;
735                         int h = pbox[i].y2 - y;
736
737                         DRM_DEBUG( "dispatch clear %d,%d-%d,%d flags 0x%x\n",
738                                    x, y, w, h, flags );
739
740                         if ( flags & RADEON_FRONT ) {
741                                 BEGIN_RING( 6 );
742                                 
743                                 OUT_RING( CP_PACKET3( RADEON_CNTL_PAINT_MULTI, 4 ) );
744                                 OUT_RING( RADEON_GMC_DST_PITCH_OFFSET_CNTL |
745                                           RADEON_GMC_BRUSH_SOLID_COLOR |
746                                           (dev_priv->color_fmt << 8) |
747                                           RADEON_GMC_SRC_DATATYPE_COLOR |
748                                           RADEON_ROP3_P |
749                                           RADEON_GMC_CLR_CMP_CNTL_DIS );
750
751                                 OUT_RING( dev_priv->front_pitch_offset );
752                                 OUT_RING( clear->clear_color );
753                                 
754                                 OUT_RING( (x << 16) | y );
755                                 OUT_RING( (w << 16) | h );
756                                 
757                                 ADVANCE_RING();
758                         }
759                         
760                         if ( flags & RADEON_BACK ) {
761                                 BEGIN_RING( 6 );
762                                 
763                                 OUT_RING( CP_PACKET3( RADEON_CNTL_PAINT_MULTI, 4 ) );
764                                 OUT_RING( RADEON_GMC_DST_PITCH_OFFSET_CNTL |
765                                           RADEON_GMC_BRUSH_SOLID_COLOR |
766                                           (dev_priv->color_fmt << 8) |
767                                           RADEON_GMC_SRC_DATATYPE_COLOR |
768                                           RADEON_ROP3_P |
769                                           RADEON_GMC_CLR_CMP_CNTL_DIS );
770                                 
771                                 OUT_RING( dev_priv->back_pitch_offset );
772                                 OUT_RING( clear->clear_color );
773
774                                 OUT_RING( (x << 16) | y );
775                                 OUT_RING( (w << 16) | h );
776
777                                 ADVANCE_RING();
778                         }
779                 }
780         }
781
782         /* We have to clear the depth and/or stencil buffers by
783          * rendering a quad into just those buffers.  Thus, we have to
784          * make sure the 3D engine is configured correctly.
785          */
786         if ( dev_priv->is_r200 &&
787              (flags & (RADEON_DEPTH | RADEON_STENCIL)) ) {
788
789                 int tempPP_CNTL;
790                 int tempRE_CNTL;
791                 int tempRB3D_CNTL;
792                 int tempRB3D_ZSTENCILCNTL;
793                 int tempRB3D_STENCILREFMASK;
794                 int tempRB3D_PLANEMASK;
795                 int tempSE_CNTL;
796                 int tempSE_VTE_CNTL;
797                 int tempSE_VTX_FMT_0;
798                 int tempSE_VTX_FMT_1;
799                 int tempSE_VAP_CNTL;
800                 int tempRE_AUX_SCISSOR_CNTL;
801
802                 tempPP_CNTL = 0;
803                 tempRE_CNTL = 0;
804
805                 tempRB3D_CNTL = depth_clear->rb3d_cntl;
806                 tempRB3D_CNTL &= ~(1<<15); /* unset radeon magic flag */
807
808                 tempRB3D_ZSTENCILCNTL = depth_clear->rb3d_zstencilcntl;
809                 tempRB3D_STENCILREFMASK = 0x0;
810
811                 tempSE_CNTL = depth_clear->se_cntl;
812
813
814
815                 /* Disable TCL */
816
817                 tempSE_VAP_CNTL = (/* SE_VAP_CNTL__FORCE_W_TO_ONE_MASK |  */
818                                    (0x9 << SE_VAP_CNTL__VF_MAX_VTX_NUM__SHIFT));
819
820                 tempRB3D_PLANEMASK = 0x0;
821
822                 tempRE_AUX_SCISSOR_CNTL = 0x0;
823
824                 tempSE_VTE_CNTL =
825                         SE_VTE_CNTL__VTX_XY_FMT_MASK |
826                         SE_VTE_CNTL__VTX_Z_FMT_MASK;
827
828                 /* Vertex format (X, Y, Z, W)*/
829                 tempSE_VTX_FMT_0 =
830                         SE_VTX_FMT_0__VTX_Z0_PRESENT_MASK |
831                         SE_VTX_FMT_0__VTX_W0_PRESENT_MASK;
832                 tempSE_VTX_FMT_1 = 0x0;
833
834
835                 /* 
836                  * Depth buffer specific enables 
837                  */
838                 if (flags & RADEON_DEPTH) {
839                         /* Enable depth buffer */
840                         tempRB3D_CNTL |= RADEON_Z_ENABLE;
841                 } else {
842                         /* Disable depth buffer */
843                         tempRB3D_CNTL &= ~RADEON_Z_ENABLE;
844                 }
845
846                 /* 
847                  * Stencil buffer specific enables
848                  */
849                 if ( flags & RADEON_STENCIL ) {
850                         tempRB3D_CNTL |=  RADEON_STENCIL_ENABLE;
851                         tempRB3D_STENCILREFMASK = clear->depth_mask; 
852                 } else {
853                         tempRB3D_CNTL &= ~RADEON_STENCIL_ENABLE;
854                         tempRB3D_STENCILREFMASK = 0x00000000;
855                 }
856
857                 BEGIN_RING( 26 );
858                 RADEON_WAIT_UNTIL_2D_IDLE();
859
860                 OUT_RING_REG( RADEON_PP_CNTL, tempPP_CNTL );
861                 OUT_RING_REG( R200_RE_CNTL, tempRE_CNTL );
862                 OUT_RING_REG( RADEON_RB3D_CNTL, tempRB3D_CNTL );
863                 OUT_RING_REG( RADEON_RB3D_ZSTENCILCNTL,
864                               tempRB3D_ZSTENCILCNTL );
865                 OUT_RING_REG( RADEON_RB3D_STENCILREFMASK, 
866                               tempRB3D_STENCILREFMASK );
867                 OUT_RING_REG( RADEON_RB3D_PLANEMASK, tempRB3D_PLANEMASK );
868                 OUT_RING_REG( RADEON_SE_CNTL, tempSE_CNTL );
869                 OUT_RING_REG( R200_SE_VTE_CNTL, tempSE_VTE_CNTL );
870                 OUT_RING_REG( R200_SE_VTX_FMT_0, tempSE_VTX_FMT_0 );
871                 OUT_RING_REG( R200_SE_VTX_FMT_1, tempSE_VTX_FMT_1 );
872                 OUT_RING_REG( R200_SE_VAP_CNTL, tempSE_VAP_CNTL );
873                 OUT_RING_REG( R200_RE_AUX_SCISSOR_CNTL, 
874                               tempRE_AUX_SCISSOR_CNTL );
875                 ADVANCE_RING();
876
877                 /* Make sure we restore the 3D state next time.
878                  */
879                 dev_priv->sarea_priv->ctx_owner = 0;
880
881                 for ( i = 0 ; i < nbox ; i++ ) {
882                         
883                         /* Funny that this should be required -- 
884                          *  sets top-left?
885                          */
886                         radeon_emit_clip_rect( dev_priv,
887                                                &sarea_priv->boxes[i] );
888
889                         BEGIN_RING( 14 );
890                         OUT_RING( CP_PACKET3( R200_3D_DRAW_IMMD_2, 12 ) );
891                         OUT_RING( (RADEON_PRIM_TYPE_RECT_LIST |
892                                    RADEON_PRIM_WALK_RING |
893                                    (3 << RADEON_NUM_VERTICES_SHIFT)) );
894                         OUT_RING( depth_boxes[i].ui[CLEAR_X1] );
895                         OUT_RING( depth_boxes[i].ui[CLEAR_Y1] );
896                         OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
897                         OUT_RING( 0x3f800000 );
898                         OUT_RING( depth_boxes[i].ui[CLEAR_X1] );
899                         OUT_RING( depth_boxes[i].ui[CLEAR_Y2] );
900                         OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
901                         OUT_RING( 0x3f800000 );
902                         OUT_RING( depth_boxes[i].ui[CLEAR_X2] );
903                         OUT_RING( depth_boxes[i].ui[CLEAR_Y2] );
904                         OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
905                         OUT_RING( 0x3f800000 );
906                         ADVANCE_RING();
907                 }
908         } 
909         else if ( (flags & (RADEON_DEPTH | RADEON_STENCIL)) ) {
910
911                 rb3d_cntl = depth_clear->rb3d_cntl;
912
913                 if ( flags & RADEON_DEPTH ) {
914                         rb3d_cntl |=  RADEON_Z_ENABLE;
915                 } else {
916                         rb3d_cntl &= ~RADEON_Z_ENABLE;
917                 }
918
919                 if ( flags & RADEON_STENCIL ) {
920                         rb3d_cntl |=  RADEON_STENCIL_ENABLE;
921                         rb3d_stencilrefmask = clear->depth_mask; /* misnamed field */
922                 } else {
923                         rb3d_cntl &= ~RADEON_STENCIL_ENABLE;
924                         rb3d_stencilrefmask = 0x00000000;
925                 }
926
927                 BEGIN_RING( 13 );
928                 RADEON_WAIT_UNTIL_2D_IDLE();
929
930                 OUT_RING( CP_PACKET0( RADEON_PP_CNTL, 1 ) );
931                 OUT_RING( 0x00000000 );
932                 OUT_RING( rb3d_cntl );
933                 
934                 OUT_RING_REG( RADEON_RB3D_ZSTENCILCNTL,
935                               depth_clear->rb3d_zstencilcntl );
936                 OUT_RING_REG( RADEON_RB3D_STENCILREFMASK,
937                               rb3d_stencilrefmask );
938                 OUT_RING_REG( RADEON_RB3D_PLANEMASK,
939                               0x00000000 );
940                 OUT_RING_REG( RADEON_SE_CNTL,
941                               depth_clear->se_cntl );
942                 ADVANCE_RING();
943
944                 /* Make sure we restore the 3D state next time.
945                  */
946                 dev_priv->sarea_priv->ctx_owner = 0;
947
948                 for ( i = 0 ; i < nbox ; i++ ) {
949                         
950                         /* Funny that this should be required -- 
951                          *  sets top-left?
952                          */
953                         radeon_emit_clip_rect( dev_priv,
954                                                &sarea_priv->boxes[i] );
955
956                         BEGIN_RING( 15 );
957
958                         OUT_RING( CP_PACKET3( RADEON_3D_DRAW_IMMD, 13 ) );
959                         OUT_RING( RADEON_VTX_Z_PRESENT |
960                                   RADEON_VTX_PKCOLOR_PRESENT);
961                         OUT_RING( (RADEON_PRIM_TYPE_RECT_LIST |
962                                    RADEON_PRIM_WALK_RING |
963                                    RADEON_MAOS_ENABLE |
964                                    RADEON_VTX_FMT_RADEON_MODE |
965                                    (3 << RADEON_NUM_VERTICES_SHIFT)) );
966
967
968                         OUT_RING( depth_boxes[i].ui[CLEAR_X1] );
969                         OUT_RING( depth_boxes[i].ui[CLEAR_Y1] );
970                         OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
971                         OUT_RING( 0x0 );
972
973                         OUT_RING( depth_boxes[i].ui[CLEAR_X1] );
974                         OUT_RING( depth_boxes[i].ui[CLEAR_Y2] );
975                         OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
976                         OUT_RING( 0x0 );
977
978                         OUT_RING( depth_boxes[i].ui[CLEAR_X2] );
979                         OUT_RING( depth_boxes[i].ui[CLEAR_Y2] );
980                         OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
981                         OUT_RING( 0x0 );
982
983                         ADVANCE_RING();
984                 }
985         }
986
987         /* Increment the clear counter.  The client-side 3D driver must
988          * wait on this value before performing the clear ioctl.  We
989          * need this because the card's so damned fast...
990          */
991         dev_priv->sarea_priv->last_clear++;
992
993         BEGIN_RING( 4 );
994
995         RADEON_CLEAR_AGE( dev_priv->sarea_priv->last_clear );
996         RADEON_WAIT_UNTIL_IDLE();
997
998         ADVANCE_RING();
999 }
1000
1001 static void radeon_cp_dispatch_swap( drm_device_t *dev )
1002 {
1003         drm_radeon_private_t *dev_priv = dev->dev_private;
1004         drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
1005         int nbox = sarea_priv->nbox;
1006         drm_clip_rect_t *pbox = sarea_priv->boxes;
1007         int i;
1008         RING_LOCALS;
1009         DRM_DEBUG( "\n" );
1010
1011         /* Do some trivial performance monitoring...
1012          */
1013         if (dev_priv->do_boxes)
1014                 radeon_cp_performance_boxes( dev_priv );
1015
1016
1017         /* Wait for the 3D stream to idle before dispatching the bitblt.
1018          * This will prevent data corruption between the two streams.
1019          */
1020         BEGIN_RING( 2 );
1021
1022         RADEON_WAIT_UNTIL_3D_IDLE();
1023
1024         ADVANCE_RING();
1025
1026         for ( i = 0 ; i < nbox ; i++ ) {
1027                 int x = pbox[i].x1;
1028                 int y = pbox[i].y1;
1029                 int w = pbox[i].x2 - x;
1030                 int h = pbox[i].y2 - y;
1031
1032                 DRM_DEBUG( "dispatch swap %d,%d-%d,%d\n",
1033                            x, y, w, h );
1034
1035                 BEGIN_RING( 7 );
1036
1037                 OUT_RING( CP_PACKET3( RADEON_CNTL_BITBLT_MULTI, 5 ) );
1038                 OUT_RING( RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
1039                           RADEON_GMC_DST_PITCH_OFFSET_CNTL |
1040                           RADEON_GMC_BRUSH_NONE |
1041                           (dev_priv->color_fmt << 8) |
1042                           RADEON_GMC_SRC_DATATYPE_COLOR |
1043                           RADEON_ROP3_S |
1044                           RADEON_DP_SRC_SOURCE_MEMORY |
1045                           RADEON_GMC_CLR_CMP_CNTL_DIS |
1046                           RADEON_GMC_WR_MSK_DIS );
1047                 
1048                 /* Make this work even if front & back are flipped:
1049                  */
1050                 if (dev_priv->current_page == 0) {
1051                         OUT_RING( dev_priv->back_pitch_offset );
1052                         OUT_RING( dev_priv->front_pitch_offset );
1053                 } 
1054                 else {
1055                         OUT_RING( dev_priv->front_pitch_offset );
1056                         OUT_RING( dev_priv->back_pitch_offset );
1057                 }
1058
1059                 OUT_RING( (x << 16) | y );
1060                 OUT_RING( (x << 16) | y );
1061                 OUT_RING( (w << 16) | h );
1062
1063                 ADVANCE_RING();
1064         }
1065
1066         /* Increment the frame counter.  The client-side 3D driver must
1067          * throttle the framerate by waiting for this value before
1068          * performing the swapbuffer ioctl.
1069          */
1070         dev_priv->sarea_priv->last_frame++;
1071
1072         BEGIN_RING( 4 );
1073
1074         RADEON_FRAME_AGE( dev_priv->sarea_priv->last_frame );
1075         RADEON_WAIT_UNTIL_2D_IDLE();
1076
1077         ADVANCE_RING();
1078 }
1079
1080 static void radeon_cp_dispatch_flip( drm_device_t *dev )
1081 {
1082         drm_radeon_private_t *dev_priv = dev->dev_private;
1083         drm_sarea_t *sarea = (drm_sarea_t *)dev_priv->sarea->handle;
1084         int offset = (dev_priv->current_page == 1)
1085                    ? dev_priv->front_offset : dev_priv->back_offset;
1086         RING_LOCALS;
1087         DRM_DEBUG( "%s: page=%d pfCurrentPage=%d\n", 
1088                 __FUNCTION__, 
1089                 dev_priv->current_page,
1090                 dev_priv->sarea_priv->pfCurrentPage);
1091
1092         /* Do some trivial performance monitoring...
1093          */
1094         if (dev_priv->do_boxes) {
1095                 dev_priv->stats.boxes |= RADEON_BOX_FLIP;
1096                 radeon_cp_performance_boxes( dev_priv );
1097         }
1098
1099         /* Update the frame offsets for both CRTCs
1100          */
1101         BEGIN_RING( 6 );
1102
1103         RADEON_WAIT_UNTIL_3D_IDLE();
1104         OUT_RING_REG( RADEON_CRTC_OFFSET, ( ( sarea->frame.y * dev_priv->front_pitch
1105                                               + sarea->frame.x 
1106                                               * ( dev_priv->color_fmt - 2 ) ) & ~7 )
1107                                           + offset );
1108         OUT_RING_REG( RADEON_CRTC2_OFFSET, dev_priv->sarea_priv->crtc2_base
1109                                            + offset );
1110
1111         ADVANCE_RING();
1112
1113         /* Increment the frame counter.  The client-side 3D driver must
1114          * throttle the framerate by waiting for this value before
1115          * performing the swapbuffer ioctl.
1116          */
1117         dev_priv->sarea_priv->last_frame++;
1118         dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page =
1119                                               1 - dev_priv->current_page;
1120
1121         BEGIN_RING( 2 );
1122
1123         RADEON_FRAME_AGE( dev_priv->sarea_priv->last_frame );
1124
1125         ADVANCE_RING();
1126 }
1127
1128 static int bad_prim_vertex_nr( int primitive, int nr )
1129 {
1130         switch (primitive & RADEON_PRIM_TYPE_MASK) {
1131         case RADEON_PRIM_TYPE_NONE:
1132         case RADEON_PRIM_TYPE_POINT:
1133                 return nr < 1;
1134         case RADEON_PRIM_TYPE_LINE:
1135                 return (nr & 1) || nr == 0;
1136         case RADEON_PRIM_TYPE_LINE_STRIP:
1137                 return nr < 2;
1138         case RADEON_PRIM_TYPE_TRI_LIST:
1139         case RADEON_PRIM_TYPE_3VRT_POINT_LIST:
1140         case RADEON_PRIM_TYPE_3VRT_LINE_LIST:
1141         case RADEON_PRIM_TYPE_RECT_LIST:
1142                 return nr % 3 || nr == 0;
1143         case RADEON_PRIM_TYPE_TRI_FAN:
1144         case RADEON_PRIM_TYPE_TRI_STRIP:
1145                 return nr < 3;
1146         default:
1147                 return 1;
1148         }       
1149 }
1150
1151
1152
1153 typedef struct {
1154         unsigned int start;
1155         unsigned int finish;
1156         unsigned int prim;
1157         unsigned int numverts;
1158         unsigned int offset;   
1159         unsigned int vc_format;
1160 } drm_radeon_tcl_prim_t;
1161
1162 static void radeon_cp_dispatch_vertex( drm_device_t *dev,
1163                                        drm_buf_t *buf,
1164                                        drm_radeon_tcl_prim_t *prim )
1165
1166 {
1167         drm_radeon_private_t *dev_priv = dev->dev_private;
1168         drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
1169         int offset = dev_priv->gart_buffers_offset + buf->offset + prim->start;
1170         int numverts = (int)prim->numverts;
1171         int nbox = sarea_priv->nbox;
1172         int i = 0;
1173         RING_LOCALS;
1174
1175         DRM_DEBUG("hwprim 0x%x vfmt 0x%x %d..%d %d verts\n",
1176                   prim->prim,
1177                   prim->vc_format,
1178                   prim->start,
1179                   prim->finish,
1180                   prim->numverts);
1181
1182         if (bad_prim_vertex_nr( prim->prim, prim->numverts )) {
1183                 DRM_ERROR( "bad prim %x numverts %d\n", 
1184                            prim->prim, prim->numverts );
1185                 return;
1186         }
1187
1188         do {
1189                 /* Emit the next cliprect */
1190                 if ( i < nbox ) {
1191                         radeon_emit_clip_rect( dev_priv, 
1192                                                &sarea_priv->boxes[i] );
1193                 }
1194
1195                 /* Emit the vertex buffer rendering commands */
1196                 BEGIN_RING( 5 );
1197
1198                 OUT_RING( CP_PACKET3( RADEON_3D_RNDR_GEN_INDX_PRIM, 3 ) );
1199                 OUT_RING( offset );
1200                 OUT_RING( numverts );
1201                 OUT_RING( prim->vc_format );
1202                 OUT_RING( prim->prim | RADEON_PRIM_WALK_LIST |
1203                           RADEON_COLOR_ORDER_RGBA |
1204                           RADEON_VTX_FMT_RADEON_MODE |
1205                           (numverts << RADEON_NUM_VERTICES_SHIFT) );
1206
1207                 ADVANCE_RING();
1208
1209                 i++;
1210         } while ( i < nbox );
1211 }
1212
1213
1214
1215 static void radeon_cp_discard_buffer( drm_device_t *dev, drm_buf_t *buf )
1216 {
1217         drm_radeon_private_t *dev_priv = dev->dev_private;
1218         drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
1219         RING_LOCALS;
1220
1221         buf_priv->age = ++dev_priv->sarea_priv->last_dispatch;
1222
1223         /* Emit the vertex buffer age */
1224         BEGIN_RING( 2 );
1225         RADEON_DISPATCH_AGE( buf_priv->age );
1226         ADVANCE_RING();
1227
1228         buf->pending = 1;
1229         buf->used = 0;
1230 }
1231
1232 static void radeon_cp_dispatch_indirect( drm_device_t *dev,
1233                                          drm_buf_t *buf,
1234                                          int start, int end )
1235 {
1236         drm_radeon_private_t *dev_priv = dev->dev_private;
1237         RING_LOCALS;
1238         DRM_DEBUG( "indirect: buf=%d s=0x%x e=0x%x\n",
1239                    buf->idx, start, end );
1240
1241         if ( start != end ) {
1242                 int offset = (dev_priv->gart_buffers_offset
1243                               + buf->offset + start);
1244                 int dwords = (end - start + 3) / sizeof(u32);
1245
1246                 /* Indirect buffer data must be an even number of
1247                  * dwords, so if we've been given an odd number we must
1248                  * pad the data with a Type-2 CP packet.
1249                  */
1250                 if ( dwords & 1 ) {
1251                         u32 *data = (u32 *)
1252                                 ((char *)dev->agp_buffer_map->handle
1253                                  + buf->offset + start);
1254                         data[dwords++] = RADEON_CP_PACKET2;
1255                 }
1256
1257                 /* Fire off the indirect buffer */
1258                 BEGIN_RING( 3 );
1259
1260                 OUT_RING( CP_PACKET0( RADEON_CP_IB_BASE, 1 ) );
1261                 OUT_RING( offset );
1262                 OUT_RING( dwords );
1263
1264                 ADVANCE_RING();
1265         }
1266 }
1267
1268
1269 static void radeon_cp_dispatch_indices( drm_device_t *dev,
1270                                         drm_buf_t *elt_buf,
1271                                         drm_radeon_tcl_prim_t *prim )
1272 {
1273         drm_radeon_private_t *dev_priv = dev->dev_private;
1274         drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
1275         int offset = dev_priv->gart_buffers_offset + prim->offset;
1276         u32 *data;
1277         int dwords;
1278         int i = 0;
1279         int start = prim->start + RADEON_INDEX_PRIM_OFFSET;
1280         int count = (prim->finish - start) / sizeof(u16);
1281         int nbox = sarea_priv->nbox;
1282
1283         DRM_DEBUG("hwprim 0x%x vfmt 0x%x %d..%d offset: %x nr %d\n",
1284                   prim->prim,
1285                   prim->vc_format,
1286                   prim->start,
1287                   prim->finish,
1288                   prim->offset,
1289                   prim->numverts);
1290
1291         if (bad_prim_vertex_nr( prim->prim, count )) {
1292                 DRM_ERROR( "bad prim %x count %d\n", 
1293                            prim->prim, count );
1294                 return;
1295         }
1296
1297
1298         if ( start >= prim->finish ||
1299              (prim->start & 0x7) ) {
1300                 DRM_ERROR( "buffer prim %d\n", prim->prim );
1301                 return;
1302         }
1303
1304         dwords = (prim->finish - prim->start + 3) / sizeof(u32);
1305
1306         data = (u32 *)((char *)dev->agp_buffer_map->handle +
1307                        elt_buf->offset + prim->start);
1308
1309         data[0] = CP_PACKET3( RADEON_3D_RNDR_GEN_INDX_PRIM, dwords-2 );
1310         data[1] = offset;
1311         data[2] = prim->numverts;
1312         data[3] = prim->vc_format;
1313         data[4] = (prim->prim |
1314                    RADEON_PRIM_WALK_IND |
1315                    RADEON_COLOR_ORDER_RGBA |
1316                    RADEON_VTX_FMT_RADEON_MODE |
1317                    (count << RADEON_NUM_VERTICES_SHIFT) );
1318
1319         do {
1320                 if ( i < nbox ) 
1321                         radeon_emit_clip_rect( dev_priv, 
1322                                                &sarea_priv->boxes[i] );
1323
1324                 radeon_cp_dispatch_indirect( dev, elt_buf,
1325                                              prim->start,
1326                                              prim->finish );
1327
1328                 i++;
1329         } while ( i < nbox );
1330
1331 }
1332
1333 #define RADEON_MAX_TEXTURE_SIZE (RADEON_BUFFER_SIZE - 8 * sizeof(u32))
1334
1335 static int radeon_cp_dispatch_texture( DRMFILE filp,
1336                                        drm_device_t *dev,
1337                                        drm_radeon_texture_t *tex,
1338                                        drm_radeon_tex_image_t *image )
1339 {
1340         drm_radeon_private_t *dev_priv = dev->dev_private;
1341         drm_file_t *filp_priv;
1342         drm_buf_t *buf;
1343         u32 format;
1344         u32 *buffer;
1345         const u8 __user *data;
1346         int size, dwords, tex_width, blit_width;
1347         u32 height;
1348         int i;
1349         RING_LOCALS;
1350
1351         DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
1352
1353         if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, &tex->offset ) ) {
1354                 DRM_ERROR( "Invalid destination offset\n" );
1355                 return DRM_ERR( EINVAL );
1356         }
1357
1358         dev_priv->stats.boxes |= RADEON_BOX_TEXTURE_LOAD;
1359
1360         /* Flush the pixel cache.  This ensures no pixel data gets mixed
1361          * up with the texture data from the host data blit, otherwise
1362          * part of the texture image may be corrupted.
1363          */
1364         BEGIN_RING( 4 );
1365         RADEON_FLUSH_CACHE();
1366         RADEON_WAIT_UNTIL_IDLE();
1367         ADVANCE_RING();
1368
1369 #ifdef __BIG_ENDIAN
1370         /* The Mesa texture functions provide the data in little endian as the
1371          * chip wants it, but we need to compensate for the fact that the CP
1372          * ring gets byte-swapped
1373          */
1374         BEGIN_RING( 2 );
1375         OUT_RING_REG( RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_32BIT );
1376         ADVANCE_RING();
1377 #endif
1378
1379
1380         /* The compiler won't optimize away a division by a variable,
1381          * even if the only legal values are powers of two.  Thus, we'll
1382          * use a shift instead.
1383          */
1384         switch ( tex->format ) {
1385         case RADEON_TXFORMAT_ARGB8888:
1386         case RADEON_TXFORMAT_RGBA8888:
1387                 format = RADEON_COLOR_FORMAT_ARGB8888;
1388                 tex_width = tex->width * 4;
1389                 blit_width = image->width * 4;
1390                 break;
1391         case RADEON_TXFORMAT_AI88:
1392         case RADEON_TXFORMAT_ARGB1555:
1393         case RADEON_TXFORMAT_RGB565:
1394         case RADEON_TXFORMAT_ARGB4444:
1395         case RADEON_TXFORMAT_VYUY422:
1396         case RADEON_TXFORMAT_YVYU422:
1397                 format = RADEON_COLOR_FORMAT_RGB565;
1398                 tex_width = tex->width * 2;
1399                 blit_width = image->width * 2;
1400                 break;
1401         case RADEON_TXFORMAT_I8:
1402         case RADEON_TXFORMAT_RGB332:
1403                 format = RADEON_COLOR_FORMAT_CI8;
1404                 tex_width = tex->width * 1;
1405                 blit_width = image->width * 1;
1406                 break;
1407         default:
1408                 DRM_ERROR( "invalid texture format %d\n", tex->format );
1409                 return DRM_ERR(EINVAL);
1410         }
1411
1412         DRM_DEBUG("tex=%dx%d blit=%d\n", tex_width, tex->height, blit_width );
1413
1414         do {
1415                 DRM_DEBUG( "tex: ofs=0x%x p=%d f=%d x=%hd y=%hd w=%hd h=%hd\n",
1416                            tex->offset >> 10, tex->pitch, tex->format,
1417                            image->x, image->y, image->width, image->height );
1418
1419                 /* Make a copy of some parameters in case we have to
1420                  * update them for a multi-pass texture blit.
1421                  */
1422                 height = image->height;
1423                 data = (const u8 __user *)image->data;
1424                 
1425                 size = height * blit_width;
1426
1427                 if ( size > RADEON_MAX_TEXTURE_SIZE ) {
1428                         height = RADEON_MAX_TEXTURE_SIZE / blit_width;
1429                         size = height * blit_width;
1430                 } else if ( size < 4 && size > 0 ) {
1431                         size = 4;
1432                 } else if ( size == 0 ) {
1433                         return 0;
1434                 }
1435
1436                 buf = radeon_freelist_get( dev );
1437                 if ( 0 && !buf ) {
1438                         radeon_do_cp_idle( dev_priv );
1439                         buf = radeon_freelist_get( dev );
1440                 }
1441                 if ( !buf ) {
1442                         DRM_DEBUG("radeon_cp_dispatch_texture: EAGAIN\n");
1443                         DRM_COPY_TO_USER( tex->image, image, sizeof(*image) );
1444                         return DRM_ERR(EAGAIN);
1445                 }
1446
1447
1448                 /* Dispatch the indirect buffer.
1449                  */
1450                 buffer = (u32*)((char*)dev->agp_buffer_map->handle + buf->offset);
1451                 dwords = size / 4;
1452                 buffer[0] = CP_PACKET3( RADEON_CNTL_HOSTDATA_BLT, dwords + 6 );
1453                 buffer[1] = (RADEON_GMC_DST_PITCH_OFFSET_CNTL |
1454                              RADEON_GMC_BRUSH_NONE |
1455                              (format << 8) |
1456                              RADEON_GMC_SRC_DATATYPE_COLOR |
1457                              RADEON_ROP3_S |
1458                              RADEON_DP_SRC_SOURCE_HOST_DATA |
1459                              RADEON_GMC_CLR_CMP_CNTL_DIS |
1460                              RADEON_GMC_WR_MSK_DIS);
1461                 
1462                 buffer[2] = (tex->pitch << 22) | (tex->offset >> 10);
1463                 buffer[3] = 0xffffffff;
1464                 buffer[4] = 0xffffffff;
1465                 buffer[5] = (image->y << 16) | image->x;
1466                 buffer[6] = (height << 16) | image->width;
1467                 buffer[7] = dwords;
1468                 buffer += 8;
1469
1470                 if ( tex_width >= 32 ) {
1471                         /* Texture image width is larger than the minimum, so we
1472                          * can upload it directly.
1473                          */
1474                         if ( DRM_COPY_FROM_USER( buffer, data, 
1475                                                  dwords * sizeof(u32) ) ) {
1476                                 DRM_ERROR( "EFAULT on data, %d dwords\n", 
1477                                            dwords );
1478                                 return DRM_ERR(EFAULT);
1479                         }
1480                 } else {
1481                         /* Texture image width is less than the minimum, so we
1482                          * need to pad out each image scanline to the minimum
1483                          * width.
1484                          */
1485                         for ( i = 0 ; i < tex->height ; i++ ) {
1486                                 if ( DRM_COPY_FROM_USER( buffer, data, 
1487                                                          tex_width ) ) {
1488                                         DRM_ERROR( "EFAULT on pad, %d bytes\n",
1489                                                    tex_width );
1490                                         return DRM_ERR(EFAULT);
1491                                 }
1492                                 buffer += 8;
1493                                 data += tex_width;
1494                         }
1495                 }
1496
1497                 buf->filp = filp;
1498                 buf->used = (dwords + 8) * sizeof(u32);
1499                 radeon_cp_dispatch_indirect( dev, buf, 0, buf->used );
1500                 radeon_cp_discard_buffer( dev, buf );
1501
1502                 /* Update the input parameters for next time */
1503                 image->y += height;
1504                 image->height -= height;
1505                 image->data = (const u8 __user *)image->data + size;
1506         } while (image->height > 0);
1507
1508         /* Flush the pixel cache after the blit completes.  This ensures
1509          * the texture data is written out to memory before rendering
1510          * continues.
1511          */
1512         BEGIN_RING( 4 );
1513         RADEON_FLUSH_CACHE();
1514         RADEON_WAIT_UNTIL_2D_IDLE();
1515         ADVANCE_RING();
1516         return 0;
1517 }
1518
1519
1520 static void radeon_cp_dispatch_stipple( drm_device_t *dev, u32 *stipple )
1521 {
1522         drm_radeon_private_t *dev_priv = dev->dev_private;
1523         int i;
1524         RING_LOCALS;
1525         DRM_DEBUG( "\n" );
1526
1527         BEGIN_RING( 35 );
1528
1529         OUT_RING( CP_PACKET0( RADEON_RE_STIPPLE_ADDR, 0 ) );
1530         OUT_RING( 0x00000000 );
1531
1532         OUT_RING( CP_PACKET0_TABLE( RADEON_RE_STIPPLE_DATA, 31 ) );
1533         for ( i = 0 ; i < 32 ; i++ ) {
1534                 OUT_RING( stipple[i] );
1535         }
1536
1537         ADVANCE_RING();
1538 }
1539
1540
1541 /* ================================================================
1542  * IOCTL functions
1543  */
1544
1545 int radeon_cp_clear( DRM_IOCTL_ARGS )
1546 {
1547         DRM_DEVICE;
1548         drm_radeon_private_t *dev_priv = dev->dev_private;
1549         drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
1550         drm_radeon_clear_t clear;
1551         drm_radeon_clear_rect_t depth_boxes[RADEON_NR_SAREA_CLIPRECTS];
1552         DRM_DEBUG( "\n" );
1553
1554         LOCK_TEST_WITH_RETURN( dev, filp );
1555
1556         DRM_COPY_FROM_USER_IOCTL( clear, (drm_radeon_clear_t __user *)data,
1557                              sizeof(clear) );
1558
1559         RING_SPACE_TEST_WITH_RETURN( dev_priv );
1560
1561         if ( sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS )
1562                 sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
1563
1564         if ( DRM_COPY_FROM_USER( &depth_boxes, clear.depth_boxes,
1565                              sarea_priv->nbox * sizeof(depth_boxes[0]) ) )
1566                 return DRM_ERR(EFAULT);
1567
1568         radeon_cp_dispatch_clear( dev, &clear, depth_boxes );
1569
1570         COMMIT_RING();
1571         return 0;
1572 }
1573
1574
1575 /* Not sure why this isn't set all the time:
1576  */ 
1577 static int radeon_do_init_pageflip( drm_device_t *dev )
1578 {
1579         drm_radeon_private_t *dev_priv = dev->dev_private;
1580         RING_LOCALS;
1581
1582         DRM_DEBUG( "\n" );
1583
1584         BEGIN_RING( 6 );
1585         RADEON_WAIT_UNTIL_3D_IDLE();
1586         OUT_RING( CP_PACKET0( RADEON_CRTC_OFFSET_CNTL, 0 ) );
1587         OUT_RING( RADEON_READ( RADEON_CRTC_OFFSET_CNTL ) | RADEON_CRTC_OFFSET_FLIP_CNTL );
1588         OUT_RING( CP_PACKET0( RADEON_CRTC2_OFFSET_CNTL, 0 ) );
1589         OUT_RING( RADEON_READ( RADEON_CRTC2_OFFSET_CNTL ) | RADEON_CRTC_OFFSET_FLIP_CNTL );
1590         ADVANCE_RING();
1591
1592         dev_priv->page_flipping = 1;
1593         dev_priv->current_page = 0;
1594         dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page;
1595
1596         return 0;
1597 }
1598
1599 /* Called whenever a client dies, from DRM(release).
1600  * NOTE:  Lock isn't necessarily held when this is called!
1601  */
1602 int radeon_do_cleanup_pageflip( drm_device_t *dev )
1603 {
1604         drm_radeon_private_t *dev_priv = dev->dev_private;
1605         DRM_DEBUG( "\n" );
1606
1607         if (dev_priv->current_page != 0)
1608                 radeon_cp_dispatch_flip( dev );
1609
1610         dev_priv->page_flipping = 0;
1611         return 0;
1612 }
1613
1614 /* Swapping and flipping are different operations, need different ioctls.
1615  * They can & should be intermixed to support multiple 3d windows.  
1616  */
1617 int radeon_cp_flip( DRM_IOCTL_ARGS )
1618 {
1619         DRM_DEVICE;
1620         drm_radeon_private_t *dev_priv = dev->dev_private;
1621         DRM_DEBUG( "\n" );
1622
1623         LOCK_TEST_WITH_RETURN( dev, filp );
1624
1625         RING_SPACE_TEST_WITH_RETURN( dev_priv );
1626
1627         if (!dev_priv->page_flipping) 
1628                 radeon_do_init_pageflip( dev );
1629                 
1630         radeon_cp_dispatch_flip( dev );
1631
1632         COMMIT_RING();
1633         return 0;
1634 }
1635
1636 int radeon_cp_swap( DRM_IOCTL_ARGS )
1637 {
1638         DRM_DEVICE;
1639         drm_radeon_private_t *dev_priv = dev->dev_private;
1640         drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
1641         DRM_DEBUG( "\n" );
1642
1643         LOCK_TEST_WITH_RETURN( dev, filp );
1644
1645         RING_SPACE_TEST_WITH_RETURN( dev_priv );
1646
1647         if ( sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS )
1648                 sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
1649
1650         radeon_cp_dispatch_swap( dev );
1651         dev_priv->sarea_priv->ctx_owner = 0;
1652
1653         COMMIT_RING();
1654         return 0;
1655 }
1656
1657 int radeon_cp_vertex( DRM_IOCTL_ARGS )
1658 {
1659         DRM_DEVICE;
1660         drm_radeon_private_t *dev_priv = dev->dev_private;
1661         drm_file_t *filp_priv;
1662         drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
1663         drm_device_dma_t *dma = dev->dma;
1664         drm_buf_t *buf;
1665         drm_radeon_vertex_t vertex;
1666         drm_radeon_tcl_prim_t prim;
1667
1668         LOCK_TEST_WITH_RETURN( dev, filp );
1669
1670         DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
1671
1672         DRM_COPY_FROM_USER_IOCTL( vertex, (drm_radeon_vertex_t __user *)data,
1673                              sizeof(vertex) );
1674
1675         DRM_DEBUG( "pid=%d index=%d count=%d discard=%d\n",
1676                    DRM_CURRENTPID,
1677                    vertex.idx, vertex.count, vertex.discard );
1678
1679         if ( vertex.idx < 0 || vertex.idx >= dma->buf_count ) {
1680                 DRM_ERROR( "buffer index %d (of %d max)\n",
1681                            vertex.idx, dma->buf_count - 1 );
1682                 return DRM_ERR(EINVAL);
1683         }
1684         if ( vertex.prim < 0 ||
1685              vertex.prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST ) {
1686                 DRM_ERROR( "buffer prim %d\n", vertex.prim );
1687                 return DRM_ERR(EINVAL);
1688         }
1689
1690         RING_SPACE_TEST_WITH_RETURN( dev_priv );
1691         VB_AGE_TEST_WITH_RETURN( dev_priv );
1692
1693         buf = dma->buflist[vertex.idx];
1694
1695         if ( buf->filp != filp ) {
1696                 DRM_ERROR( "process %d using buffer owned by %p\n",
1697                            DRM_CURRENTPID, buf->filp );
1698                 return DRM_ERR(EINVAL);
1699         }
1700         if ( buf->pending ) {
1701                 DRM_ERROR( "sending pending buffer %d\n", vertex.idx );
1702                 return DRM_ERR(EINVAL);
1703         }
1704
1705         /* Build up a prim_t record:
1706          */
1707         if (vertex.count) {
1708                 buf->used = vertex.count; /* not used? */
1709
1710                 if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) {
1711                         if ( radeon_emit_state( dev_priv, filp_priv,
1712                                                 &sarea_priv->context_state,
1713                                                 sarea_priv->tex_state,
1714                                                 sarea_priv->dirty ) ) {
1715                                 DRM_ERROR( "radeon_emit_state failed\n" );
1716                                 return DRM_ERR( EINVAL );
1717                         }
1718
1719                         sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES |
1720                                                RADEON_UPLOAD_TEX1IMAGES |
1721                                                RADEON_UPLOAD_TEX2IMAGES |
1722                                                RADEON_REQUIRE_QUIESCENCE);
1723                 }
1724
1725                 prim.start = 0;
1726                 prim.finish = vertex.count; /* unused */
1727                 prim.prim = vertex.prim;
1728                 prim.numverts = vertex.count;
1729                 prim.vc_format = dev_priv->sarea_priv->vc_format;
1730                 
1731                 radeon_cp_dispatch_vertex( dev, buf, &prim );
1732         }
1733
1734         if (vertex.discard) {
1735                 radeon_cp_discard_buffer( dev, buf );
1736         }
1737
1738         COMMIT_RING();
1739         return 0;
1740 }
1741
1742 int radeon_cp_indices( DRM_IOCTL_ARGS )
1743 {
1744         DRM_DEVICE;
1745         drm_radeon_private_t *dev_priv = dev->dev_private;
1746         drm_file_t *filp_priv;
1747         drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
1748         drm_device_dma_t *dma = dev->dma;
1749         drm_buf_t *buf;
1750         drm_radeon_indices_t elts;
1751         drm_radeon_tcl_prim_t prim;
1752         int count;
1753
1754         LOCK_TEST_WITH_RETURN( dev, filp );
1755
1756         if ( !dev_priv ) {
1757                 DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
1758                 return DRM_ERR(EINVAL);
1759         }
1760
1761         DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
1762
1763         DRM_COPY_FROM_USER_IOCTL( elts, (drm_radeon_indices_t __user *)data,
1764                              sizeof(elts) );
1765
1766         DRM_DEBUG( "pid=%d index=%d start=%d end=%d discard=%d\n",
1767                    DRM_CURRENTPID,
1768                    elts.idx, elts.start, elts.end, elts.discard );
1769
1770         if ( elts.idx < 0 || elts.idx >= dma->buf_count ) {
1771                 DRM_ERROR( "buffer index %d (of %d max)\n",
1772                            elts.idx, dma->buf_count - 1 );
1773                 return DRM_ERR(EINVAL);
1774         }
1775         if ( elts.prim < 0 ||
1776              elts.prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST ) {
1777                 DRM_ERROR( "buffer prim %d\n", elts.prim );
1778                 return DRM_ERR(EINVAL);
1779         }
1780
1781         RING_SPACE_TEST_WITH_RETURN( dev_priv );
1782         VB_AGE_TEST_WITH_RETURN( dev_priv );
1783
1784         buf = dma->buflist[elts.idx];
1785
1786         if ( buf->filp != filp ) {
1787                 DRM_ERROR( "process %d using buffer owned by %p\n",
1788                            DRM_CURRENTPID, buf->filp );
1789                 return DRM_ERR(EINVAL);
1790         }
1791         if ( buf->pending ) {
1792                 DRM_ERROR( "sending pending buffer %d\n", elts.idx );
1793                 return DRM_ERR(EINVAL);
1794         }
1795
1796         count = (elts.end - elts.start) / sizeof(u16);
1797         elts.start -= RADEON_INDEX_PRIM_OFFSET;
1798
1799         if ( elts.start & 0x7 ) {
1800                 DRM_ERROR( "misaligned buffer 0x%x\n", elts.start );
1801                 return DRM_ERR(EINVAL);
1802         }
1803         if ( elts.start < buf->used ) {
1804                 DRM_ERROR( "no header 0x%x - 0x%x\n", elts.start, buf->used );
1805                 return DRM_ERR(EINVAL);
1806         }
1807
1808         buf->used = elts.end;
1809
1810         if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) {
1811                 if ( radeon_emit_state( dev_priv, filp_priv,
1812                                         &sarea_priv->context_state,
1813                                         sarea_priv->tex_state,
1814                                         sarea_priv->dirty ) ) {
1815                         DRM_ERROR( "radeon_emit_state failed\n" );
1816                         return DRM_ERR( EINVAL );
1817                 }
1818
1819                 sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES |
1820                                        RADEON_UPLOAD_TEX1IMAGES |
1821                                        RADEON_UPLOAD_TEX2IMAGES |
1822                                        RADEON_REQUIRE_QUIESCENCE);
1823         }
1824
1825
1826         /* Build up a prim_t record:
1827          */
1828         prim.start = elts.start;
1829         prim.finish = elts.end; 
1830         prim.prim = elts.prim;
1831         prim.offset = 0;        /* offset from start of dma buffers */
1832         prim.numverts = RADEON_MAX_VB_VERTS; /* duh */
1833         prim.vc_format = dev_priv->sarea_priv->vc_format;
1834         
1835         radeon_cp_dispatch_indices( dev, buf, &prim );
1836         if (elts.discard) {
1837                 radeon_cp_discard_buffer( dev, buf );
1838         }
1839
1840         COMMIT_RING();
1841         return 0;
1842 }
1843
1844 int radeon_cp_texture( DRM_IOCTL_ARGS )
1845 {
1846         DRM_DEVICE;
1847         drm_radeon_private_t *dev_priv = dev->dev_private;
1848         drm_radeon_texture_t tex;
1849         drm_radeon_tex_image_t image;
1850         int ret;
1851
1852         LOCK_TEST_WITH_RETURN( dev, filp );
1853
1854         DRM_COPY_FROM_USER_IOCTL( tex, (drm_radeon_texture_t __user *)data, sizeof(tex) );
1855
1856         if ( tex.image == NULL ) {
1857                 DRM_ERROR( "null texture image!\n" );
1858                 return DRM_ERR(EINVAL);
1859         }
1860
1861         if ( DRM_COPY_FROM_USER( &image,
1862                              (drm_radeon_tex_image_t __user *)tex.image,
1863                              sizeof(image) ) )
1864                 return DRM_ERR(EFAULT);
1865
1866         RING_SPACE_TEST_WITH_RETURN( dev_priv );
1867         VB_AGE_TEST_WITH_RETURN( dev_priv );
1868
1869         ret = radeon_cp_dispatch_texture( filp, dev, &tex, &image );
1870
1871         COMMIT_RING();
1872         return ret;
1873 }
1874
1875 int radeon_cp_stipple( DRM_IOCTL_ARGS )
1876 {
1877         DRM_DEVICE;
1878         drm_radeon_private_t *dev_priv = dev->dev_private;
1879         drm_radeon_stipple_t stipple;
1880         u32 mask[32];
1881
1882         LOCK_TEST_WITH_RETURN( dev, filp );
1883
1884         DRM_COPY_FROM_USER_IOCTL( stipple, (drm_radeon_stipple_t __user *)data,
1885                              sizeof(stipple) );
1886
1887         if ( DRM_COPY_FROM_USER( &mask, stipple.mask, 32 * sizeof(u32) ) )
1888                 return DRM_ERR(EFAULT);
1889
1890         RING_SPACE_TEST_WITH_RETURN( dev_priv );
1891
1892         radeon_cp_dispatch_stipple( dev, mask );
1893
1894         COMMIT_RING();
1895         return 0;
1896 }
1897
1898 int radeon_cp_indirect( DRM_IOCTL_ARGS )
1899 {
1900         DRM_DEVICE;
1901         drm_radeon_private_t *dev_priv = dev->dev_private;
1902         drm_device_dma_t *dma = dev->dma;
1903         drm_buf_t *buf;
1904         drm_radeon_indirect_t indirect;
1905         RING_LOCALS;
1906
1907         LOCK_TEST_WITH_RETURN( dev, filp );
1908
1909         if ( !dev_priv ) {
1910                 DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
1911                 return DRM_ERR(EINVAL);
1912         }
1913
1914         DRM_COPY_FROM_USER_IOCTL( indirect, (drm_radeon_indirect_t __user *)data,
1915                              sizeof(indirect) );
1916
1917         DRM_DEBUG( "indirect: idx=%d s=%d e=%d d=%d\n",
1918                    indirect.idx, indirect.start,
1919                    indirect.end, indirect.discard );
1920
1921         if ( indirect.idx < 0 || indirect.idx >= dma->buf_count ) {
1922                 DRM_ERROR( "buffer index %d (of %d max)\n",
1923                            indirect.idx, dma->buf_count - 1 );
1924                 return DRM_ERR(EINVAL);
1925         }
1926
1927         buf = dma->buflist[indirect.idx];
1928
1929         if ( buf->filp != filp ) {
1930                 DRM_ERROR( "process %d using buffer owned by %p\n",
1931                            DRM_CURRENTPID, buf->filp );
1932                 return DRM_ERR(EINVAL);
1933         }
1934         if ( buf->pending ) {
1935                 DRM_ERROR( "sending pending buffer %d\n", indirect.idx );
1936                 return DRM_ERR(EINVAL);
1937         }
1938
1939         if ( indirect.start < buf->used ) {
1940                 DRM_ERROR( "reusing indirect: start=0x%x actual=0x%x\n",
1941                            indirect.start, buf->used );
1942                 return DRM_ERR(EINVAL);
1943         }
1944
1945         RING_SPACE_TEST_WITH_RETURN( dev_priv );
1946         VB_AGE_TEST_WITH_RETURN( dev_priv );
1947
1948         buf->used = indirect.end;
1949
1950         /* Wait for the 3D stream to idle before the indirect buffer
1951          * containing 2D acceleration commands is processed.
1952          */
1953         BEGIN_RING( 2 );
1954
1955         RADEON_WAIT_UNTIL_3D_IDLE();
1956
1957         ADVANCE_RING();
1958
1959         /* Dispatch the indirect buffer full of commands from the
1960          * X server.  This is insecure and is thus only available to
1961          * privileged clients.
1962          */
1963         radeon_cp_dispatch_indirect( dev, buf, indirect.start, indirect.end );
1964         if (indirect.discard) {
1965                 radeon_cp_discard_buffer( dev, buf );
1966         }
1967
1968
1969         COMMIT_RING();
1970         return 0;
1971 }
1972
1973 int radeon_cp_vertex2( DRM_IOCTL_ARGS )
1974 {
1975         DRM_DEVICE;
1976         drm_radeon_private_t *dev_priv = dev->dev_private;
1977         drm_file_t *filp_priv;
1978         drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
1979         drm_device_dma_t *dma = dev->dma;
1980         drm_buf_t *buf;
1981         drm_radeon_vertex2_t vertex;
1982         int i;
1983         unsigned char laststate;
1984
1985         LOCK_TEST_WITH_RETURN( dev, filp );
1986
1987         if ( !dev_priv ) {
1988                 DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
1989                 return DRM_ERR(EINVAL);
1990         }
1991
1992         DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
1993
1994         DRM_COPY_FROM_USER_IOCTL( vertex, (drm_radeon_vertex2_t __user *)data,
1995                              sizeof(vertex) );
1996
1997         DRM_DEBUG( "pid=%d index=%d discard=%d\n",
1998                    DRM_CURRENTPID,
1999                    vertex.idx, vertex.discard );
2000
2001         if ( vertex.idx < 0 || vertex.idx >= dma->buf_count ) {
2002                 DRM_ERROR( "buffer index %d (of %d max)\n",
2003                            vertex.idx, dma->buf_count - 1 );
2004                 return DRM_ERR(EINVAL);
2005         }
2006
2007         RING_SPACE_TEST_WITH_RETURN( dev_priv );
2008         VB_AGE_TEST_WITH_RETURN( dev_priv );
2009
2010         buf = dma->buflist[vertex.idx];
2011
2012         if ( buf->filp != filp ) {
2013                 DRM_ERROR( "process %d using buffer owned by %p\n",
2014                            DRM_CURRENTPID, buf->filp );
2015                 return DRM_ERR(EINVAL);
2016         }
2017
2018         if ( buf->pending ) {
2019                 DRM_ERROR( "sending pending buffer %d\n", vertex.idx );
2020                 return DRM_ERR(EINVAL);
2021         }
2022         
2023         if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS)
2024                 return DRM_ERR(EINVAL);
2025
2026         for (laststate = 0xff, i = 0 ; i < vertex.nr_prims ; i++) {
2027                 drm_radeon_prim_t prim;
2028                 drm_radeon_tcl_prim_t tclprim;
2029                 
2030                 if ( DRM_COPY_FROM_USER( &prim, &vertex.prim[i], sizeof(prim) ) )
2031                         return DRM_ERR(EFAULT);
2032                 
2033                 if ( prim.stateidx != laststate ) {
2034                         drm_radeon_state_t state;                              
2035                                 
2036                         if ( DRM_COPY_FROM_USER( &state, 
2037                                              &vertex.state[prim.stateidx], 
2038                                              sizeof(state) ) )
2039                                 return DRM_ERR(EFAULT);
2040
2041                         if ( radeon_emit_state2( dev_priv, filp_priv, &state ) ) {
2042                                 DRM_ERROR( "radeon_emit_state2 failed\n" );
2043                                 return DRM_ERR( EINVAL );
2044                         }
2045
2046                         laststate = prim.stateidx;
2047                 }
2048
2049                 tclprim.start = prim.start;
2050                 tclprim.finish = prim.finish;
2051                 tclprim.prim = prim.prim;
2052                 tclprim.vc_format = prim.vc_format;
2053
2054                 if ( prim.prim & RADEON_PRIM_WALK_IND ) {
2055                         tclprim.offset = prim.numverts * 64;
2056                         tclprim.numverts = RADEON_MAX_VB_VERTS; /* duh */
2057
2058                         radeon_cp_dispatch_indices( dev, buf, &tclprim );
2059                 } else {
2060                         tclprim.numverts = prim.numverts;
2061                         tclprim.offset = 0; /* not used */
2062
2063                         radeon_cp_dispatch_vertex( dev, buf, &tclprim );
2064                 }
2065                 
2066                 if (sarea_priv->nbox == 1)
2067                         sarea_priv->nbox = 0;
2068         }
2069
2070         if ( vertex.discard ) {
2071                 radeon_cp_discard_buffer( dev, buf );
2072         }
2073
2074         COMMIT_RING();
2075         return 0;
2076 }
2077
2078
2079 static int radeon_emit_packets( 
2080         drm_radeon_private_t *dev_priv,
2081         drm_file_t *filp_priv,
2082         drm_radeon_cmd_header_t header,
2083         drm_radeon_cmd_buffer_t *cmdbuf )
2084 {
2085         int id = (int)header.packet.packet_id;
2086         int sz, reg;
2087         int __user *data = (int __user *)cmdbuf->buf;
2088         RING_LOCALS;
2089    
2090         if (id >= RADEON_MAX_STATE_PACKETS)
2091                 return DRM_ERR(EINVAL);
2092
2093         sz = packet[id].len;
2094         reg = packet[id].start;
2095
2096         if (sz * sizeof(int) > cmdbuf->bufsz) {
2097                 DRM_ERROR( "Packet size provided larger than data provided\n" );
2098                 return DRM_ERR(EINVAL);
2099         }
2100
2101         if ( radeon_check_and_fixup_packets( dev_priv, filp_priv, id, data ) ) {
2102                 DRM_ERROR( "Packet verification failed\n" );
2103                 return DRM_ERR( EINVAL );
2104         }
2105
2106         BEGIN_RING(sz+1);
2107         OUT_RING( CP_PACKET0( reg, (sz-1) ) );
2108         OUT_RING_USER_TABLE( data, sz );
2109         ADVANCE_RING();
2110
2111         cmdbuf->buf += sz * sizeof(int);
2112         cmdbuf->bufsz -= sz * sizeof(int);
2113         return 0;
2114 }
2115
2116 static __inline__ int radeon_emit_scalars( 
2117         drm_radeon_private_t *dev_priv,
2118         drm_radeon_cmd_header_t header,
2119         drm_radeon_cmd_buffer_t *cmdbuf )
2120 {
2121         int sz = header.scalars.count;
2122         int __user *data = (int __user *)cmdbuf->buf;
2123         int start = header.scalars.offset;
2124         int stride = header.scalars.stride;
2125         RING_LOCALS;
2126
2127         BEGIN_RING( 3+sz );
2128         OUT_RING( CP_PACKET0( RADEON_SE_TCL_SCALAR_INDX_REG, 0 ) );
2129         OUT_RING( start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT));
2130         OUT_RING( CP_PACKET0_TABLE( RADEON_SE_TCL_SCALAR_DATA_REG, sz-1 ) );
2131         OUT_RING_USER_TABLE( data, sz );
2132         ADVANCE_RING();
2133         cmdbuf->buf += sz * sizeof(int);
2134         cmdbuf->bufsz -= sz * sizeof(int);
2135         return 0;
2136 }
2137
2138 /* God this is ugly
2139  */
2140 static __inline__ int radeon_emit_scalars2( 
2141         drm_radeon_private_t *dev_priv,
2142         drm_radeon_cmd_header_t header,
2143         drm_radeon_cmd_buffer_t *cmdbuf )
2144 {
2145         int sz = header.scalars.count;
2146         int __user *data = (int __user *)cmdbuf->buf;
2147         int start = ((unsigned int)header.scalars.offset) + 0x100;
2148         int stride = header.scalars.stride;
2149         RING_LOCALS;
2150
2151         BEGIN_RING( 3+sz );
2152         OUT_RING( CP_PACKET0( RADEON_SE_TCL_SCALAR_INDX_REG, 0 ) );
2153         OUT_RING( start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT));
2154         OUT_RING( CP_PACKET0_TABLE( RADEON_SE_TCL_SCALAR_DATA_REG, sz-1 ) );
2155         OUT_RING_USER_TABLE( data, sz );
2156         ADVANCE_RING();
2157         cmdbuf->buf += sz * sizeof(int);
2158         cmdbuf->bufsz -= sz * sizeof(int);
2159         return 0;
2160 }
2161
2162 static __inline__ int radeon_emit_vectors( 
2163         drm_radeon_private_t *dev_priv,
2164         drm_radeon_cmd_header_t header,
2165         drm_radeon_cmd_buffer_t *cmdbuf )
2166 {
2167         int sz = header.vectors.count;
2168         int __user *data = (int __user *)cmdbuf->buf;
2169         int start = header.vectors.offset;
2170         int stride = header.vectors.stride;
2171         RING_LOCALS;
2172
2173         BEGIN_RING( 3+sz );
2174         OUT_RING( CP_PACKET0( RADEON_SE_TCL_VECTOR_INDX_REG, 0 ) );
2175         OUT_RING( start | (stride << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT));
2176         OUT_RING( CP_PACKET0_TABLE( RADEON_SE_TCL_VECTOR_DATA_REG, (sz-1) ) );
2177         OUT_RING_USER_TABLE( data, sz );
2178         ADVANCE_RING();
2179
2180         cmdbuf->buf += sz * sizeof(int);
2181         cmdbuf->bufsz -= sz * sizeof(int);
2182         return 0;
2183 }
2184
2185
2186 static int radeon_emit_packet3( drm_device_t *dev,
2187                                 drm_file_t *filp_priv,
2188                                 drm_radeon_cmd_buffer_t *cmdbuf )
2189 {
2190         drm_radeon_private_t *dev_priv = dev->dev_private;
2191         unsigned int cmdsz;
2192         int __user *cmd = (int __user *)cmdbuf->buf;
2193         int ret;
2194         RING_LOCALS;
2195
2196         DRM_DEBUG("\n");
2197
2198         if ( ( ret = radeon_check_and_fixup_packet3( dev_priv, filp_priv,
2199                                                      cmdbuf, &cmdsz ) ) ) {
2200                 DRM_ERROR( "Packet verification failed\n" );
2201                 return ret;
2202         }
2203
2204         BEGIN_RING( cmdsz );
2205         OUT_RING_USER_TABLE( cmd, cmdsz );
2206         ADVANCE_RING();
2207
2208         cmdbuf->buf += cmdsz * 4;
2209         cmdbuf->bufsz -= cmdsz * 4;
2210         return 0;
2211 }
2212
2213
2214 static int radeon_emit_packet3_cliprect( drm_device_t *dev,
2215                                          drm_file_t *filp_priv,
2216                                          drm_radeon_cmd_buffer_t *cmdbuf,
2217                                          int orig_nbox )
2218 {
2219         drm_radeon_private_t *dev_priv = dev->dev_private;
2220         drm_clip_rect_t box;
2221         unsigned int cmdsz;
2222         int __user *cmd = (int __user *)cmdbuf->buf;
2223         int ret;
2224         drm_clip_rect_t __user *boxes = cmdbuf->boxes;
2225         int i = 0;
2226         RING_LOCALS;
2227
2228         DRM_DEBUG("\n");
2229
2230         if ( ( ret = radeon_check_and_fixup_packet3( dev_priv, filp_priv,
2231                                                      cmdbuf, &cmdsz ) ) ) {
2232                 DRM_ERROR( "Packet verification failed\n" );
2233                 return ret;
2234         }
2235
2236         if (!orig_nbox)
2237                 goto out;
2238
2239         do {
2240                 if ( i < cmdbuf->nbox ) {
2241                         if (DRM_COPY_FROM_USER_UNCHECKED( &box, &boxes[i], sizeof(box) ))
2242                                 return DRM_ERR(EFAULT);
2243                         /* FIXME The second and subsequent times round
2244                          * this loop, send a WAIT_UNTIL_3D_IDLE before
2245                          * calling emit_clip_rect(). This fixes a
2246                          * lockup on fast machines when sending
2247                          * several cliprects with a cmdbuf, as when
2248                          * waving a 2D window over a 3D
2249                          * window. Something in the commands from user
2250                          * space seems to hang the card when they're
2251                          * sent several times in a row. That would be
2252                          * the correct place to fix it but this works
2253                          * around it until I can figure that out - Tim
2254                          * Smith */
2255                         if ( i ) {
2256                                 BEGIN_RING( 2 );
2257                                 RADEON_WAIT_UNTIL_3D_IDLE();
2258                                 ADVANCE_RING();
2259                         }
2260                         radeon_emit_clip_rect( dev_priv, &box );
2261                 }
2262                 
2263                 BEGIN_RING( cmdsz );
2264                 OUT_RING_USER_TABLE( cmd, cmdsz );
2265                 ADVANCE_RING();
2266
2267         } while ( ++i < cmdbuf->nbox );
2268         if (cmdbuf->nbox == 1)
2269                 cmdbuf->nbox = 0;
2270
2271  out:
2272         cmdbuf->buf += cmdsz * 4;
2273         cmdbuf->bufsz -= cmdsz * 4;
2274         return 0;
2275 }
2276
2277
2278 static int radeon_emit_wait( drm_device_t *dev, int flags )
2279 {
2280         drm_radeon_private_t *dev_priv = dev->dev_private;
2281         RING_LOCALS;
2282
2283         DRM_DEBUG("%s: %x\n", __FUNCTION__, flags);
2284         switch (flags) {
2285         case RADEON_WAIT_2D:
2286                 BEGIN_RING( 2 );
2287                 RADEON_WAIT_UNTIL_2D_IDLE(); 
2288                 ADVANCE_RING();
2289                 break;
2290         case RADEON_WAIT_3D:
2291                 BEGIN_RING( 2 );
2292                 RADEON_WAIT_UNTIL_3D_IDLE(); 
2293                 ADVANCE_RING();
2294                 break;
2295         case RADEON_WAIT_2D|RADEON_WAIT_3D:
2296                 BEGIN_RING( 2 );
2297                 RADEON_WAIT_UNTIL_IDLE(); 
2298                 ADVANCE_RING();
2299                 break;
2300         default:
2301                 return DRM_ERR(EINVAL);
2302         }
2303
2304         return 0;
2305 }
2306
2307 int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
2308 {
2309         DRM_DEVICE;
2310         drm_radeon_private_t *dev_priv = dev->dev_private;
2311         drm_file_t *filp_priv;
2312         drm_device_dma_t *dma = dev->dma;
2313         drm_buf_t *buf = NULL;
2314         int idx;
2315         drm_radeon_cmd_buffer_t cmdbuf;
2316         drm_radeon_cmd_header_t header;
2317         int orig_nbox;
2318
2319         LOCK_TEST_WITH_RETURN( dev, filp );
2320
2321         if ( !dev_priv ) {
2322                 DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
2323                 return DRM_ERR(EINVAL);
2324         }
2325
2326         DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
2327
2328         DRM_COPY_FROM_USER_IOCTL( cmdbuf, (drm_radeon_cmd_buffer_t __user *)data,
2329                              sizeof(cmdbuf) );
2330
2331         RING_SPACE_TEST_WITH_RETURN( dev_priv );
2332         VB_AGE_TEST_WITH_RETURN( dev_priv );
2333
2334
2335         if (DRM_VERIFYAREA_READ( cmdbuf.buf, cmdbuf.bufsz ))
2336                 return DRM_ERR(EFAULT);
2337
2338         if (cmdbuf.nbox &&
2339             DRM_VERIFYAREA_READ(cmdbuf.boxes, 
2340                          cmdbuf.nbox * sizeof(drm_clip_rect_t)))
2341                 return DRM_ERR(EFAULT);
2342
2343         orig_nbox = cmdbuf.nbox;
2344
2345         while ( cmdbuf.bufsz >= sizeof(header) ) {
2346                 
2347                 if (DRM_GET_USER_UNCHECKED( header.i, (int __user *)cmdbuf.buf )) {
2348                         DRM_ERROR("__get_user %p\n", cmdbuf.buf);
2349                         return DRM_ERR(EFAULT);
2350                 }
2351
2352                 cmdbuf.buf += sizeof(header);
2353                 cmdbuf.bufsz -= sizeof(header);
2354
2355                 switch (header.header.cmd_type) {
2356                 case RADEON_CMD_PACKET: 
2357                         DRM_DEBUG("RADEON_CMD_PACKET\n");
2358                         if (radeon_emit_packets( dev_priv, filp_priv, header, &cmdbuf )) {
2359                                 DRM_ERROR("radeon_emit_packets failed\n");
2360                                 return DRM_ERR(EINVAL);
2361                         }
2362                         break;
2363
2364                 case RADEON_CMD_SCALARS:
2365                         DRM_DEBUG("RADEON_CMD_SCALARS\n");
2366                         if (radeon_emit_scalars( dev_priv, header, &cmdbuf )) {
2367                                 DRM_ERROR("radeon_emit_scalars failed\n");
2368                                 return DRM_ERR(EINVAL);
2369                         }
2370                         break;
2371
2372                 case RADEON_CMD_VECTORS:
2373                         DRM_DEBUG("RADEON_CMD_VECTORS\n");
2374                         if (radeon_emit_vectors( dev_priv, header, &cmdbuf )) {
2375                                 DRM_ERROR("radeon_emit_vectors failed\n");
2376                                 return DRM_ERR(EINVAL);
2377                         }
2378                         break;
2379
2380                 case RADEON_CMD_DMA_DISCARD:
2381                         DRM_DEBUG("RADEON_CMD_DMA_DISCARD\n");
2382                         idx = header.dma.buf_idx;
2383                         if ( idx < 0 || idx >= dma->buf_count ) {
2384                                 DRM_ERROR( "buffer index %d (of %d max)\n",
2385                                            idx, dma->buf_count - 1 );
2386                                 return DRM_ERR(EINVAL);
2387                         }
2388
2389                         buf = dma->buflist[idx];
2390                         if ( buf->filp != filp || buf->pending ) {
2391                                 DRM_ERROR( "bad buffer %p %p %d\n",
2392                                            buf->filp, filp, buf->pending);
2393                                 return DRM_ERR(EINVAL);
2394                         }
2395
2396                         radeon_cp_discard_buffer( dev, buf );
2397                         break;
2398
2399                 case RADEON_CMD_PACKET3:
2400                         DRM_DEBUG("RADEON_CMD_PACKET3\n");
2401                         if (radeon_emit_packet3( dev, filp_priv, &cmdbuf )) {
2402                                 DRM_ERROR("radeon_emit_packet3 failed\n");
2403                                 return DRM_ERR(EINVAL);
2404                         }
2405                         break;
2406
2407                 case RADEON_CMD_PACKET3_CLIP:
2408                         DRM_DEBUG("RADEON_CMD_PACKET3_CLIP\n");
2409                         if (radeon_emit_packet3_cliprect( dev, filp_priv, &cmdbuf, orig_nbox )) {
2410                                 DRM_ERROR("radeon_emit_packet3_clip failed\n");
2411                                 return DRM_ERR(EINVAL);
2412                         }
2413                         break;
2414
2415                 case RADEON_CMD_SCALARS2:
2416                         DRM_DEBUG("RADEON_CMD_SCALARS2\n");
2417                         if (radeon_emit_scalars2( dev_priv, header, &cmdbuf )) {
2418                                 DRM_ERROR("radeon_emit_scalars2 failed\n");
2419                                 return DRM_ERR(EINVAL);
2420                         }
2421                         break;
2422
2423                 case RADEON_CMD_WAIT:
2424                         DRM_DEBUG("RADEON_CMD_WAIT\n");
2425                         if (radeon_emit_wait( dev, header.wait.flags )) {
2426                                 DRM_ERROR("radeon_emit_wait failed\n");
2427                                 return DRM_ERR(EINVAL);
2428                         }
2429                         break;
2430                 default:
2431                         DRM_ERROR("bad cmd_type %d at %p\n", 
2432                                   header.header.cmd_type,
2433                                   cmdbuf.buf - sizeof(header));
2434                         return DRM_ERR(EINVAL);
2435                 }
2436         }
2437
2438
2439         DRM_DEBUG("DONE\n");
2440         COMMIT_RING();
2441         return 0;
2442 }
2443
2444
2445
2446 int radeon_cp_getparam( DRM_IOCTL_ARGS )
2447 {
2448         DRM_DEVICE;
2449         drm_radeon_private_t *dev_priv = dev->dev_private;
2450         drm_radeon_getparam_t param;
2451         int value;
2452
2453         if ( !dev_priv ) {
2454                 DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
2455                 return DRM_ERR(EINVAL);
2456         }
2457
2458         DRM_COPY_FROM_USER_IOCTL( param, (drm_radeon_getparam_t __user *)data,
2459                              sizeof(param) );
2460
2461         DRM_DEBUG( "pid=%d\n", DRM_CURRENTPID );
2462
2463         switch( param.param ) {
2464         case RADEON_PARAM_GART_BUFFER_OFFSET:
2465                 value = dev_priv->gart_buffers_offset;
2466                 break;
2467         case RADEON_PARAM_LAST_FRAME:
2468                 dev_priv->stats.last_frame_reads++;
2469                 value = GET_SCRATCH( 0 );
2470                 break;
2471         case RADEON_PARAM_LAST_DISPATCH:
2472                 value = GET_SCRATCH( 1 );
2473                 break;
2474         case RADEON_PARAM_LAST_CLEAR:
2475                 dev_priv->stats.last_clear_reads++;
2476                 value = GET_SCRATCH( 2 );
2477                 break;
2478         case RADEON_PARAM_IRQ_NR:
2479                 value = dev->irq;
2480                 break;
2481         case RADEON_PARAM_GART_BASE:
2482                 value = dev_priv->gart_vm_start;
2483                 break;
2484         case RADEON_PARAM_REGISTER_HANDLE:
2485                 value = dev_priv->mmio_offset;
2486                 break;
2487         case RADEON_PARAM_STATUS_HANDLE:
2488                 value = dev_priv->ring_rptr_offset;
2489                 break;
2490 #if BITS_PER_LONG == 32
2491         /*
2492          * This ioctl() doesn't work on 64-bit platforms because hw_lock is a
2493          * pointer which can't fit into an int-sized variable.  According to
2494          * Michel Dänzer, the ioctl() is only used on embedded platforms, so
2495          * not supporting it shouldn't be a problem.  If the same functionality
2496          * is needed on 64-bit platforms, a new ioctl() would have to be added,
2497          * so backwards-compatibility for the embedded platforms can be
2498          * maintained.  --davidm 4-Feb-2004.
2499          */
2500         case RADEON_PARAM_SAREA_HANDLE:
2501                 /* The lock is the first dword in the sarea. */
2502                 value = (long)dev->lock.hw_lock;
2503                 break;
2504 #endif
2505         case RADEON_PARAM_GART_TEX_HANDLE:
2506                 value = dev_priv->gart_textures_offset;
2507                 break;
2508         default:
2509                 return DRM_ERR(EINVAL);
2510         }
2511
2512         if ( DRM_COPY_TO_USER( param.value, &value, sizeof(int) ) ) {
2513                 DRM_ERROR( "copy_to_user\n" );
2514                 return DRM_ERR(EFAULT);
2515         }
2516         
2517         return 0;
2518 }
2519
2520 int radeon_cp_setparam( DRM_IOCTL_ARGS ) {
2521         DRM_DEVICE;
2522         drm_radeon_private_t *dev_priv = dev->dev_private;
2523         drm_file_t *filp_priv;
2524         drm_radeon_setparam_t sp;
2525         struct drm_radeon_driver_file_fields *radeon_priv;
2526
2527         if ( !dev_priv ) {
2528                 DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
2529                 return DRM_ERR( EINVAL );
2530         }
2531
2532         DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
2533
2534         DRM_COPY_FROM_USER_IOCTL( sp, ( drm_radeon_setparam_t __user * )data,
2535                                   sizeof( sp ) );
2536
2537         switch( sp.param ) {
2538         case RADEON_SETPARAM_FB_LOCATION:
2539                 radeon_priv = filp_priv->driver_priv;
2540                 radeon_priv->radeon_fb_delta = dev_priv->fb_location - sp.value;
2541                 break;
2542         default:
2543                 DRM_DEBUG( "Invalid parameter %d\n", sp.param );
2544                 return DRM_ERR( EINVAL );
2545         }
2546
2547         return 0;
2548 }
2549
2550 /* When a client dies:
2551  *    - Check for and clean up flipped page state
2552  *    - Free any alloced GART memory.
2553  *
2554  * DRM infrastructure takes care of reclaiming dma buffers.
2555  */
2556 static void radeon_driver_prerelease(drm_device_t *dev, DRMFILE filp)
2557 {
2558         if ( dev->dev_private ) {                               
2559                 drm_radeon_private_t *dev_priv = dev->dev_private; 
2560                 if ( dev_priv->page_flipping ) {                
2561                         radeon_do_cleanup_pageflip( dev );      
2562                 }                                               
2563                 radeon_mem_release( filp, dev_priv->gart_heap ); 
2564                 radeon_mem_release( filp, dev_priv->fb_heap );  
2565         }                               
2566 }
2567
2568 static void radeon_driver_pretakedown(drm_device_t *dev)
2569 {
2570         radeon_do_release(dev);
2571 }
2572
2573 static int radeon_driver_open_helper(drm_device_t *dev, drm_file_t *filp_priv)
2574 {
2575         drm_radeon_private_t *dev_priv = dev->dev_private;
2576         struct drm_radeon_driver_file_fields *radeon_priv;
2577         
2578         radeon_priv = (struct drm_radeon_driver_file_fields *)DRM(alloc)(sizeof(*radeon_priv), DRM_MEM_FILES);
2579         
2580         if (!radeon_priv)
2581                 return -ENOMEM;
2582
2583         filp_priv->driver_priv = radeon_priv;
2584         if ( dev_priv )
2585                 radeon_priv->radeon_fb_delta = dev_priv->fb_location;
2586         else
2587                 radeon_priv->radeon_fb_delta = 0;
2588         return 0;
2589 }
2590
2591
2592 static void radeon_driver_free_filp_priv(drm_device_t *dev, drm_file_t *filp_priv)
2593 {
2594          struct drm_radeon_driver_file_fields *radeon_priv = filp_priv->driver_priv;
2595          
2596          DRM(free)(radeon_priv, sizeof(*radeon_priv), DRM_MEM_FILES);
2597 }
2598
2599 void radeon_driver_register_fns(struct drm_device *dev)
2600 {       
2601         dev->driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG | DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL;
2602         dev->dev_priv_size = sizeof(drm_radeon_buf_priv_t);
2603         dev->fn_tbl.prerelease = radeon_driver_prerelease;
2604         dev->fn_tbl.pretakedown = radeon_driver_pretakedown;
2605         dev->fn_tbl.open_helper = radeon_driver_open_helper;
2606         dev->fn_tbl.free_filp_priv = radeon_driver_free_filp_priv;
2607         dev->fn_tbl.vblank_wait = radeon_driver_vblank_wait;
2608         dev->fn_tbl.irq_preinstall = radeon_driver_irq_preinstall;
2609         dev->fn_tbl.irq_postinstall = radeon_driver_irq_postinstall;
2610         dev->fn_tbl.irq_uninstall = radeon_driver_irq_uninstall;
2611         dev->fn_tbl.irq_handler = radeon_driver_irq_handler;
2612 }