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