blob: 42e8ce4dbe99744044da6dcdf2c53bf2c82b64fb [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/* 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
Dave Airlieb5e89ed2005-09-25 14:28:13 +100040static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t *
41 dev_priv,
42 drm_file_t * filp_priv,
43 u32 * offset)
44{
Linus Torvalds1da177e2005-04-16 15:20:36 -070045 u32 off = *offset;
46 struct drm_radeon_driver_file_fields *radeon_priv;
47
Dave Airlieb5e89ed2005-09-25 14:28:13 +100048 if (off >= dev_priv->fb_location &&
49 off < (dev_priv->gart_vm_start + dev_priv->gart_size))
Linus Torvalds1da177e2005-04-16 15:20:36 -070050 return 0;
51
52 radeon_priv = filp_priv->driver_priv;
53 off += radeon_priv->radeon_fb_delta;
54
Dave Airlieb5e89ed2005-09-25 14:28:13 +100055 DRM_DEBUG("offset fixed up to 0x%x\n", off);
Linus Torvalds1da177e2005-04-16 15:20:36 -070056
Dave Airlieb5e89ed2005-09-25 14:28:13 +100057 if (off < dev_priv->fb_location ||
58 off >= (dev_priv->gart_vm_start + dev_priv->gart_size))
59 return DRM_ERR(EINVAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -070060
61 *offset = off;
62
63 return 0;
64}
65
Dave Airlieb5e89ed2005-09-25 14:28:13 +100066static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
67 dev_priv,
68 drm_file_t * filp_priv,
69 int id, u32 __user * data)
70{
71 switch (id) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070072
73 case RADEON_EMIT_PP_MISC:
Dave Airlieb5e89ed2005-09-25 14:28:13 +100074 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);
Linus Torvalds1da177e2005-04-16 15:20:36 -070081 }
82 break;
83
84 case RADEON_EMIT_PP_CNTL:
Dave Airlieb5e89ed2005-09-25 14:28:13 +100085 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);
Linus Torvalds1da177e2005-04-16 15:20:36 -070092 }
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:
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000101 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);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105 }
106 break;
107
108 case RADEON_EMIT_PP_TXFILTER_0:
109 case RADEON_EMIT_PP_TXFILTER_1:
110 case RADEON_EMIT_PP_TXFILTER_2:
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000111 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);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118 }
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:
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000126 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 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135 }
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000136 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138
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:
Dave Airlie9d176012005-09-11 19:55:53 +1000220 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:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229 /* These packets don't contain memory offsets */
230 break;
231
232 default:
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000233 DRM_ERROR("Unknown state packet ID %d\n", id);
234 return DRM_ERR(EINVAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235 }
236
237 return 0;
238}
239
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000240static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
241 dev_priv,
242 drm_file_t * filp_priv,
243 drm_radeon_cmd_buffer_t *
244 cmdbuf,
245 unsigned int *cmdsz)
246{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247 u32 *cmd = (u32 *) cmdbuf->buf;
248
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000249 *cmdsz = 2 + ((cmd[0] & RADEON_CP_PACKET_COUNT_MASK) >> 16);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000251 if ((cmd[0] & 0xc0000000) != RADEON_CP_PACKET3) {
252 DRM_ERROR("Not a type 3 packet\n");
253 return DRM_ERR(EINVAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254 }
255
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000256 if (4 * *cmdsz > cmdbuf->bufsz) {
257 DRM_ERROR("Packet size larger than size of data provided\n");
258 return DRM_ERR(EINVAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259 }
260
261 /* Check client state and fix it up if necessary */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000262 if (cmd[0] & 0x8000) { /* MSB of opcode: next DWORD GUI_CNTL */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263 u32 offset;
264
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000265 if (cmd[1] & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL
266 | RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267 offset = cmd[2] << 10;
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000268 if (radeon_check_and_fixup_offset
269 (dev_priv, filp_priv, &offset)) {
270 DRM_ERROR("Invalid first packet offset\n");
271 return DRM_ERR(EINVAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272 }
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000273 cmd[2] = (cmd[2] & 0xffc00000) | offset >> 10;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274 }
275
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000276 if ((cmd[1] & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) &&
277 (cmd[1] & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278 offset = cmd[3] << 10;
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000279 if (radeon_check_and_fixup_offset
280 (dev_priv, filp_priv, &offset)) {
281 DRM_ERROR("Invalid second packet offset\n");
282 return DRM_ERR(EINVAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283 }
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000284 cmd[3] = (cmd[3] & 0xffc00000) | offset >> 10;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285 }
286 }
287
288 return 0;
289}
290
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291/* ================================================================
292 * CP hardware state programming functions
293 */
294
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000295static __inline__ void radeon_emit_clip_rect(drm_radeon_private_t * dev_priv,
296 drm_clip_rect_t * box)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297{
298 RING_LOCALS;
299
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000300 DRM_DEBUG(" box: x1=%d y1=%d x2=%d y2=%d\n",
301 box->x1, box->y1, box->x2, box->y2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000303 BEGIN_RING(4);
304 OUT_RING(CP_PACKET0(RADEON_RE_TOP_LEFT, 0));
305 OUT_RING((box->y1 << 16) | box->x1);
306 OUT_RING(CP_PACKET0(RADEON_RE_WIDTH_HEIGHT, 0));
307 OUT_RING(((box->y2 - 1) << 16) | (box->x2 - 1));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308 ADVANCE_RING();
309}
310
311/* Emit 1.1 state
312 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000313static int radeon_emit_state(drm_radeon_private_t * dev_priv,
314 drm_file_t * filp_priv,
315 drm_radeon_context_regs_t * ctx,
316 drm_radeon_texture_regs_t * tex,
317 unsigned int dirty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318{
319 RING_LOCALS;
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000320 DRM_DEBUG("dirty=0x%08x\n", dirty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000322 if (dirty & RADEON_UPLOAD_CONTEXT) {
323 if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
324 &ctx->rb3d_depthoffset)) {
325 DRM_ERROR("Invalid depth buffer offset\n");
326 return DRM_ERR(EINVAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327 }
328
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000329 if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
330 &ctx->rb3d_coloroffset)) {
331 DRM_ERROR("Invalid depth buffer offset\n");
332 return DRM_ERR(EINVAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 }
334
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000335 BEGIN_RING(14);
336 OUT_RING(CP_PACKET0(RADEON_PP_MISC, 6));
337 OUT_RING(ctx->pp_misc);
338 OUT_RING(ctx->pp_fog_color);
339 OUT_RING(ctx->re_solid_color);
340 OUT_RING(ctx->rb3d_blendcntl);
341 OUT_RING(ctx->rb3d_depthoffset);
342 OUT_RING(ctx->rb3d_depthpitch);
343 OUT_RING(ctx->rb3d_zstencilcntl);
344 OUT_RING(CP_PACKET0(RADEON_PP_CNTL, 2));
345 OUT_RING(ctx->pp_cntl);
346 OUT_RING(ctx->rb3d_cntl);
347 OUT_RING(ctx->rb3d_coloroffset);
348 OUT_RING(CP_PACKET0(RADEON_RB3D_COLORPITCH, 0));
349 OUT_RING(ctx->rb3d_colorpitch);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350 ADVANCE_RING();
351 }
352
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000353 if (dirty & RADEON_UPLOAD_VERTFMT) {
354 BEGIN_RING(2);
355 OUT_RING(CP_PACKET0(RADEON_SE_COORD_FMT, 0));
356 OUT_RING(ctx->se_coord_fmt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357 ADVANCE_RING();
358 }
359
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000360 if (dirty & RADEON_UPLOAD_LINE) {
361 BEGIN_RING(5);
362 OUT_RING(CP_PACKET0(RADEON_RE_LINE_PATTERN, 1));
363 OUT_RING(ctx->re_line_pattern);
364 OUT_RING(ctx->re_line_state);
365 OUT_RING(CP_PACKET0(RADEON_SE_LINE_WIDTH, 0));
366 OUT_RING(ctx->se_line_width);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367 ADVANCE_RING();
368 }
369
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000370 if (dirty & RADEON_UPLOAD_BUMPMAP) {
371 BEGIN_RING(5);
372 OUT_RING(CP_PACKET0(RADEON_PP_LUM_MATRIX, 0));
373 OUT_RING(ctx->pp_lum_matrix);
374 OUT_RING(CP_PACKET0(RADEON_PP_ROT_MATRIX_0, 1));
375 OUT_RING(ctx->pp_rot_matrix_0);
376 OUT_RING(ctx->pp_rot_matrix_1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377 ADVANCE_RING();
378 }
379
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000380 if (dirty & RADEON_UPLOAD_MASKS) {
381 BEGIN_RING(4);
382 OUT_RING(CP_PACKET0(RADEON_RB3D_STENCILREFMASK, 2));
383 OUT_RING(ctx->rb3d_stencilrefmask);
384 OUT_RING(ctx->rb3d_ropcntl);
385 OUT_RING(ctx->rb3d_planemask);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386 ADVANCE_RING();
387 }
388
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000389 if (dirty & RADEON_UPLOAD_VIEWPORT) {
390 BEGIN_RING(7);
391 OUT_RING(CP_PACKET0(RADEON_SE_VPORT_XSCALE, 5));
392 OUT_RING(ctx->se_vport_xscale);
393 OUT_RING(ctx->se_vport_xoffset);
394 OUT_RING(ctx->se_vport_yscale);
395 OUT_RING(ctx->se_vport_yoffset);
396 OUT_RING(ctx->se_vport_zscale);
397 OUT_RING(ctx->se_vport_zoffset);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398 ADVANCE_RING();
399 }
400
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000401 if (dirty & RADEON_UPLOAD_SETUP) {
402 BEGIN_RING(4);
403 OUT_RING(CP_PACKET0(RADEON_SE_CNTL, 0));
404 OUT_RING(ctx->se_cntl);
405 OUT_RING(CP_PACKET0(RADEON_SE_CNTL_STATUS, 0));
406 OUT_RING(ctx->se_cntl_status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407 ADVANCE_RING();
408 }
409
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000410 if (dirty & RADEON_UPLOAD_MISC) {
411 BEGIN_RING(2);
412 OUT_RING(CP_PACKET0(RADEON_RE_MISC, 0));
413 OUT_RING(ctx->re_misc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414 ADVANCE_RING();
415 }
416
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000417 if (dirty & RADEON_UPLOAD_TEX0) {
418 if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
419 &tex[0].pp_txoffset)) {
420 DRM_ERROR("Invalid texture offset for unit 0\n");
421 return DRM_ERR(EINVAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422 }
423
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000424 BEGIN_RING(9);
425 OUT_RING(CP_PACKET0(RADEON_PP_TXFILTER_0, 5));
426 OUT_RING(tex[0].pp_txfilter);
427 OUT_RING(tex[0].pp_txformat);
428 OUT_RING(tex[0].pp_txoffset);
429 OUT_RING(tex[0].pp_txcblend);
430 OUT_RING(tex[0].pp_txablend);
431 OUT_RING(tex[0].pp_tfactor);
432 OUT_RING(CP_PACKET0(RADEON_PP_BORDER_COLOR_0, 0));
433 OUT_RING(tex[0].pp_border_color);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434 ADVANCE_RING();
435 }
436
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000437 if (dirty & RADEON_UPLOAD_TEX1) {
438 if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
439 &tex[1].pp_txoffset)) {
440 DRM_ERROR("Invalid texture offset for unit 1\n");
441 return DRM_ERR(EINVAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442 }
443
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000444 BEGIN_RING(9);
445 OUT_RING(CP_PACKET0(RADEON_PP_TXFILTER_1, 5));
446 OUT_RING(tex[1].pp_txfilter);
447 OUT_RING(tex[1].pp_txformat);
448 OUT_RING(tex[1].pp_txoffset);
449 OUT_RING(tex[1].pp_txcblend);
450 OUT_RING(tex[1].pp_txablend);
451 OUT_RING(tex[1].pp_tfactor);
452 OUT_RING(CP_PACKET0(RADEON_PP_BORDER_COLOR_1, 0));
453 OUT_RING(tex[1].pp_border_color);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454 ADVANCE_RING();
455 }
456
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000457 if (dirty & RADEON_UPLOAD_TEX2) {
458 if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
459 &tex[2].pp_txoffset)) {
460 DRM_ERROR("Invalid texture offset for unit 2\n");
461 return DRM_ERR(EINVAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462 }
463
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000464 BEGIN_RING(9);
465 OUT_RING(CP_PACKET0(RADEON_PP_TXFILTER_2, 5));
466 OUT_RING(tex[2].pp_txfilter);
467 OUT_RING(tex[2].pp_txformat);
468 OUT_RING(tex[2].pp_txoffset);
469 OUT_RING(tex[2].pp_txcblend);
470 OUT_RING(tex[2].pp_txablend);
471 OUT_RING(tex[2].pp_tfactor);
472 OUT_RING(CP_PACKET0(RADEON_PP_BORDER_COLOR_2, 0));
473 OUT_RING(tex[2].pp_border_color);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474 ADVANCE_RING();
475 }
476
477 return 0;
478}
479
480/* Emit 1.2 state
481 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000482static int radeon_emit_state2(drm_radeon_private_t * dev_priv,
483 drm_file_t * filp_priv,
484 drm_radeon_state_t * state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485{
486 RING_LOCALS;
487
488 if (state->dirty & RADEON_UPLOAD_ZBIAS) {
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000489 BEGIN_RING(3);
490 OUT_RING(CP_PACKET0(RADEON_SE_ZBIAS_FACTOR, 1));
491 OUT_RING(state->context2.se_zbias_factor);
492 OUT_RING(state->context2.se_zbias_constant);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 ADVANCE_RING();
494 }
495
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000496 return radeon_emit_state(dev_priv, filp_priv, &state->context,
497 state->tex, state->dirty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498}
499
500/* New (1.3) state mechanism. 3 commands (packet, scalar, vector) in
501 * 1.3 cmdbuffers allow all previous state to be updated as well as
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000502 * the tcl scalar and vector areas.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000504static struct {
505 int start;
506 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507 const char *name;
508} packet[RADEON_MAX_STATE_PACKETS] = {
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000509 {RADEON_PP_MISC, 7, "RADEON_PP_MISC"},
510 {RADEON_PP_CNTL, 3, "RADEON_PP_CNTL"},
511 {RADEON_RB3D_COLORPITCH, 1, "RADEON_RB3D_COLORPITCH"},
512 {RADEON_RE_LINE_PATTERN, 2, "RADEON_RE_LINE_PATTERN"},
513 {RADEON_SE_LINE_WIDTH, 1, "RADEON_SE_LINE_WIDTH"},
514 {RADEON_PP_LUM_MATRIX, 1, "RADEON_PP_LUM_MATRIX"},
515 {RADEON_PP_ROT_MATRIX_0, 2, "RADEON_PP_ROT_MATRIX_0"},
516 {RADEON_RB3D_STENCILREFMASK, 3, "RADEON_RB3D_STENCILREFMASK"},
517 {RADEON_SE_VPORT_XSCALE, 6, "RADEON_SE_VPORT_XSCALE"},
518 {RADEON_SE_CNTL, 2, "RADEON_SE_CNTL"},
519 {RADEON_SE_CNTL_STATUS, 1, "RADEON_SE_CNTL_STATUS"},
520 {RADEON_RE_MISC, 1, "RADEON_RE_MISC"},
521 {RADEON_PP_TXFILTER_0, 6, "RADEON_PP_TXFILTER_0"},
522 {RADEON_PP_BORDER_COLOR_0, 1, "RADEON_PP_BORDER_COLOR_0"},
523 {RADEON_PP_TXFILTER_1, 6, "RADEON_PP_TXFILTER_1"},
524 {RADEON_PP_BORDER_COLOR_1, 1, "RADEON_PP_BORDER_COLOR_1"},
525 {RADEON_PP_TXFILTER_2, 6, "RADEON_PP_TXFILTER_2"},
526 {RADEON_PP_BORDER_COLOR_2, 1, "RADEON_PP_BORDER_COLOR_2"},
527 {RADEON_SE_ZBIAS_FACTOR, 2, "RADEON_SE_ZBIAS_FACTOR"},
528 {RADEON_SE_TCL_OUTPUT_VTX_FMT, 11, "RADEON_SE_TCL_OUTPUT_VTX_FMT"},
529 {RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED, 17,
530 "RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED"},
531 {R200_PP_TXCBLEND_0, 4, "R200_PP_TXCBLEND_0"},
532 {R200_PP_TXCBLEND_1, 4, "R200_PP_TXCBLEND_1"},
533 {R200_PP_TXCBLEND_2, 4, "R200_PP_TXCBLEND_2"},
534 {R200_PP_TXCBLEND_3, 4, "R200_PP_TXCBLEND_3"},
535 {R200_PP_TXCBLEND_4, 4, "R200_PP_TXCBLEND_4"},
536 {R200_PP_TXCBLEND_5, 4, "R200_PP_TXCBLEND_5"},
537 {R200_PP_TXCBLEND_6, 4, "R200_PP_TXCBLEND_6"},
538 {R200_PP_TXCBLEND_7, 4, "R200_PP_TXCBLEND_7"},
539 {R200_SE_TCL_LIGHT_MODEL_CTL_0, 6, "R200_SE_TCL_LIGHT_MODEL_CTL_0"},
540 {R200_PP_TFACTOR_0, 6, "R200_PP_TFACTOR_0"},
541 {R200_SE_VTX_FMT_0, 4, "R200_SE_VTX_FMT_0"},
542 {R200_SE_VAP_CNTL, 1, "R200_SE_VAP_CNTL"},
543 {R200_SE_TCL_MATRIX_SEL_0, 5, "R200_SE_TCL_MATRIX_SEL_0"},
544 {R200_SE_TCL_TEX_PROC_CTL_2, 5, "R200_SE_TCL_TEX_PROC_CTL_2"},
545 {R200_SE_TCL_UCP_VERT_BLEND_CTL, 1, "R200_SE_TCL_UCP_VERT_BLEND_CTL"},
546 {R200_PP_TXFILTER_0, 6, "R200_PP_TXFILTER_0"},
547 {R200_PP_TXFILTER_1, 6, "R200_PP_TXFILTER_1"},
548 {R200_PP_TXFILTER_2, 6, "R200_PP_TXFILTER_2"},
549 {R200_PP_TXFILTER_3, 6, "R200_PP_TXFILTER_3"},
550 {R200_PP_TXFILTER_4, 6, "R200_PP_TXFILTER_4"},
551 {R200_PP_TXFILTER_5, 6, "R200_PP_TXFILTER_5"},
552 {R200_PP_TXOFFSET_0, 1, "R200_PP_TXOFFSET_0"},
553 {R200_PP_TXOFFSET_1, 1, "R200_PP_TXOFFSET_1"},
554 {R200_PP_TXOFFSET_2, 1, "R200_PP_TXOFFSET_2"},
555 {R200_PP_TXOFFSET_3, 1, "R200_PP_TXOFFSET_3"},
556 {R200_PP_TXOFFSET_4, 1, "R200_PP_TXOFFSET_4"},
557 {R200_PP_TXOFFSET_5, 1, "R200_PP_TXOFFSET_5"},
558 {R200_SE_VTE_CNTL, 1, "R200_SE_VTE_CNTL"},
559 {R200_SE_TCL_OUTPUT_VTX_COMP_SEL, 1, "R200_SE_TCL_OUTPUT_VTX_COMP_SEL"},
560 {R200_PP_TAM_DEBUG3, 1, "R200_PP_TAM_DEBUG3"},
561 {R200_PP_CNTL_X, 1, "R200_PP_CNTL_X"},
562 {R200_RB3D_DEPTHXY_OFFSET, 1, "R200_RB3D_DEPTHXY_OFFSET"},
563 {R200_RE_AUX_SCISSOR_CNTL, 1, "R200_RE_AUX_SCISSOR_CNTL"},
564 {R200_RE_SCISSOR_TL_0, 2, "R200_RE_SCISSOR_TL_0"},
565 {R200_RE_SCISSOR_TL_1, 2, "R200_RE_SCISSOR_TL_1"},
566 {R200_RE_SCISSOR_TL_2, 2, "R200_RE_SCISSOR_TL_2"},
567 {R200_SE_VAP_CNTL_STATUS, 1, "R200_SE_VAP_CNTL_STATUS"},
568 {R200_SE_VTX_STATE_CNTL, 1, "R200_SE_VTX_STATE_CNTL"},
569 {R200_RE_POINTSIZE, 1, "R200_RE_POINTSIZE"},
570 {R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0, 4,
571 "R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0"},
572 {R200_PP_CUBIC_FACES_0, 1, "R200_PP_CUBIC_FACES_0"}, /* 61 */
573 {R200_PP_CUBIC_OFFSET_F1_0, 5, "R200_PP_CUBIC_OFFSET_F1_0"}, /* 62 */
574 {R200_PP_CUBIC_FACES_1, 1, "R200_PP_CUBIC_FACES_1"},
575 {R200_PP_CUBIC_OFFSET_F1_1, 5, "R200_PP_CUBIC_OFFSET_F1_1"},
576 {R200_PP_CUBIC_FACES_2, 1, "R200_PP_CUBIC_FACES_2"},
577 {R200_PP_CUBIC_OFFSET_F1_2, 5, "R200_PP_CUBIC_OFFSET_F1_2"},
578 {R200_PP_CUBIC_FACES_3, 1, "R200_PP_CUBIC_FACES_3"},
579 {R200_PP_CUBIC_OFFSET_F1_3, 5, "R200_PP_CUBIC_OFFSET_F1_3"},
580 {R200_PP_CUBIC_FACES_4, 1, "R200_PP_CUBIC_FACES_4"},
581 {R200_PP_CUBIC_OFFSET_F1_4, 5, "R200_PP_CUBIC_OFFSET_F1_4"},
582 {R200_PP_CUBIC_FACES_5, 1, "R200_PP_CUBIC_FACES_5"},
583 {R200_PP_CUBIC_OFFSET_F1_5, 5, "R200_PP_CUBIC_OFFSET_F1_5"},
584 {RADEON_PP_TEX_SIZE_0, 2, "RADEON_PP_TEX_SIZE_0"},
585 {RADEON_PP_TEX_SIZE_1, 2, "RADEON_PP_TEX_SIZE_1"},
586 {RADEON_PP_TEX_SIZE_2, 2, "RADEON_PP_TEX_SIZE_2"},
587 {R200_RB3D_BLENDCOLOR, 3, "R200_RB3D_BLENDCOLOR"},
588 {R200_SE_TCL_POINT_SPRITE_CNTL, 1, "R200_SE_TCL_POINT_SPRITE_CNTL"},
589 {RADEON_PP_CUBIC_FACES_0, 1, "RADEON_PP_CUBIC_FACES_0"},
590 {RADEON_PP_CUBIC_OFFSET_T0_0, 5, "RADEON_PP_CUBIC_OFFSET_T0_0"},
591 {RADEON_PP_CUBIC_FACES_1, 1, "RADEON_PP_CUBIC_FACES_1"},
592 {RADEON_PP_CUBIC_OFFSET_T1_0, 5, "RADEON_PP_CUBIC_OFFSET_T1_0"},
593 {RADEON_PP_CUBIC_FACES_2, 1, "RADEON_PP_CUBIC_FACES_2"},
594 {RADEON_PP_CUBIC_OFFSET_T2_0, 5, "RADEON_PP_CUBIC_OFFSET_T2_0"},
595 {R200_PP_TRI_PERF, 2, "R200_PP_TRI_PERF"},
596 {R200_PP_AFS_0, 32, "R200_PP_AFS_0"}, /* 85 */
597 {R200_PP_AFS_1, 32, "R200_PP_AFS_1"},
598 {R200_PP_TFACTOR_0, 8, "R200_ATF_TFACTOR"},
599 {R200_PP_TXFILTER_0, 8, "R200_PP_TXCTLALL_0"},
600 {R200_PP_TXFILTER_1, 8, "R200_PP_TXCTLALL_1"},
601 {R200_PP_TXFILTER_2, 8, "R200_PP_TXCTLALL_2"},
602 {R200_PP_TXFILTER_3, 8, "R200_PP_TXCTLALL_3"},
603 {R200_PP_TXFILTER_4, 8, "R200_PP_TXCTLALL_4"},
604 {R200_PP_TXFILTER_5, 8, "R200_PP_TXCTLALL_5"},
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605};
606
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607/* ================================================================
608 * Performance monitoring functions
609 */
610
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000611static void radeon_clear_box(drm_radeon_private_t * dev_priv,
612 int x, int y, int w, int h, int r, int g, int b)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613{
614 u32 color;
615 RING_LOCALS;
616
617 x += dev_priv->sarea_priv->boxes[0].x1;
618 y += dev_priv->sarea_priv->boxes[0].y1;
619
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000620 switch (dev_priv->color_fmt) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621 case RADEON_COLOR_FORMAT_RGB565:
622 color = (((r & 0xf8) << 8) |
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000623 ((g & 0xfc) << 3) | ((b & 0xf8) >> 3));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624 break;
625 case RADEON_COLOR_FORMAT_ARGB8888:
626 default:
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000627 color = (((0xff) << 24) | (r << 16) | (g << 8) | b);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628 break;
629 }
630
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000631 BEGIN_RING(4);
632 RADEON_WAIT_UNTIL_3D_IDLE();
633 OUT_RING(CP_PACKET0(RADEON_DP_WRITE_MASK, 0));
634 OUT_RING(0xffffffff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635 ADVANCE_RING();
636
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000637 BEGIN_RING(6);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000639 OUT_RING(CP_PACKET3(RADEON_CNTL_PAINT_MULTI, 4));
640 OUT_RING(RADEON_GMC_DST_PITCH_OFFSET_CNTL |
641 RADEON_GMC_BRUSH_SOLID_COLOR |
642 (dev_priv->color_fmt << 8) |
643 RADEON_GMC_SRC_DATATYPE_COLOR |
644 RADEON_ROP3_P | RADEON_GMC_CLR_CMP_CNTL_DIS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000646 if (dev_priv->page_flipping && dev_priv->current_page == 1) {
647 OUT_RING(dev_priv->front_pitch_offset);
648 } else {
649 OUT_RING(dev_priv->back_pitch_offset);
650 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000652 OUT_RING(color);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000654 OUT_RING((x << 16) | y);
655 OUT_RING((w << 16) | h);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656
657 ADVANCE_RING();
658}
659
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000660static void radeon_cp_performance_boxes(drm_radeon_private_t * dev_priv)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661{
662 /* Collapse various things into a wait flag -- trying to
663 * guess if userspase slept -- better just to have them tell us.
664 */
665 if (dev_priv->stats.last_frame_reads > 1 ||
666 dev_priv->stats.last_clear_reads > dev_priv->stats.clears) {
667 dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
668 }
669
670 if (dev_priv->stats.freelist_loops) {
671 dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
672 }
673
674 /* Purple box for page flipping
675 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000676 if (dev_priv->stats.boxes & RADEON_BOX_FLIP)
677 radeon_clear_box(dev_priv, 4, 4, 8, 8, 255, 0, 255);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678
679 /* Red box if we have to wait for idle at any point
680 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000681 if (dev_priv->stats.boxes & RADEON_BOX_WAIT_IDLE)
682 radeon_clear_box(dev_priv, 16, 4, 8, 8, 255, 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700683
684 /* Blue box: lost context?
685 */
686
687 /* Yellow box for texture swaps
688 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000689 if (dev_priv->stats.boxes & RADEON_BOX_TEXTURE_LOAD)
690 radeon_clear_box(dev_priv, 40, 4, 8, 8, 255, 255, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691
692 /* Green box if hardware never idles (as far as we can tell)
693 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000694 if (!(dev_priv->stats.boxes & RADEON_BOX_DMA_IDLE))
695 radeon_clear_box(dev_priv, 64, 4, 8, 8, 0, 255, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000697 /* Draw bars indicating number of buffers allocated
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698 * (not a great measure, easily confused)
699 */
700 if (dev_priv->stats.requested_bufs) {
701 if (dev_priv->stats.requested_bufs > 100)
702 dev_priv->stats.requested_bufs = 100;
703
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000704 radeon_clear_box(dev_priv, 4, 16,
705 dev_priv->stats.requested_bufs, 4,
706 196, 128, 128);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707 }
708
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000709 memset(&dev_priv->stats, 0, sizeof(dev_priv->stats));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710
711}
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000712
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713/* ================================================================
714 * CP command dispatch functions
715 */
716
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000717static void radeon_cp_dispatch_clear(drm_device_t * dev,
718 drm_radeon_clear_t * clear,
719 drm_radeon_clear_rect_t * depth_boxes)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720{
721 drm_radeon_private_t *dev_priv = dev->dev_private;
722 drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
723 drm_radeon_depth_clear_t *depth_clear = &dev_priv->depth_clear;
724 int nbox = sarea_priv->nbox;
725 drm_clip_rect_t *pbox = sarea_priv->boxes;
726 unsigned int flags = clear->flags;
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000727 u32 rb3d_cntl = 0, rb3d_stencilrefmask = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728 int i;
729 RING_LOCALS;
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000730 DRM_DEBUG("flags = 0x%x\n", flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731
732 dev_priv->stats.clears++;
733
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000734 if (dev_priv->page_flipping && dev_priv->current_page == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735 unsigned int tmp = flags;
736
737 flags &= ~(RADEON_FRONT | RADEON_BACK);
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000738 if (tmp & RADEON_FRONT)
739 flags |= RADEON_BACK;
740 if (tmp & RADEON_BACK)
741 flags |= RADEON_FRONT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742 }
743
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000744 if (flags & (RADEON_FRONT | RADEON_BACK)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000746 BEGIN_RING(4);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747
748 /* Ensure the 3D stream is idle before doing a
749 * 2D fill to clear the front or back buffer.
750 */
751 RADEON_WAIT_UNTIL_3D_IDLE();
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000752
753 OUT_RING(CP_PACKET0(RADEON_DP_WRITE_MASK, 0));
754 OUT_RING(clear->color_mask);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755
756 ADVANCE_RING();
757
758 /* Make sure we restore the 3D state next time.
759 */
760 dev_priv->sarea_priv->ctx_owner = 0;
761
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000762 for (i = 0; i < nbox; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763 int x = pbox[i].x1;
764 int y = pbox[i].y1;
765 int w = pbox[i].x2 - x;
766 int h = pbox[i].y2 - y;
767
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000768 DRM_DEBUG("dispatch clear %d,%d-%d,%d flags 0x%x\n",
769 x, y, w, h, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000771 if (flags & RADEON_FRONT) {
772 BEGIN_RING(6);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000774 OUT_RING(CP_PACKET3
775 (RADEON_CNTL_PAINT_MULTI, 4));
776 OUT_RING(RADEON_GMC_DST_PITCH_OFFSET_CNTL |
777 RADEON_GMC_BRUSH_SOLID_COLOR |
778 (dev_priv->
779 color_fmt << 8) |
780 RADEON_GMC_SRC_DATATYPE_COLOR |
781 RADEON_ROP3_P |
782 RADEON_GMC_CLR_CMP_CNTL_DIS);
783
784 OUT_RING(dev_priv->front_pitch_offset);
785 OUT_RING(clear->clear_color);
786
787 OUT_RING((x << 16) | y);
788 OUT_RING((w << 16) | h);
789
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 ADVANCE_RING();
791 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000793 if (flags & RADEON_BACK) {
794 BEGIN_RING(6);
795
796 OUT_RING(CP_PACKET3
797 (RADEON_CNTL_PAINT_MULTI, 4));
798 OUT_RING(RADEON_GMC_DST_PITCH_OFFSET_CNTL |
799 RADEON_GMC_BRUSH_SOLID_COLOR |
800 (dev_priv->
801 color_fmt << 8) |
802 RADEON_GMC_SRC_DATATYPE_COLOR |
803 RADEON_ROP3_P |
804 RADEON_GMC_CLR_CMP_CNTL_DIS);
805
806 OUT_RING(dev_priv->back_pitch_offset);
807 OUT_RING(clear->clear_color);
808
809 OUT_RING((x << 16) | y);
810 OUT_RING((w << 16) | h);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811
812 ADVANCE_RING();
813 }
814 }
815 }
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000816
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817 /* hyper z clear */
818 /* no docs available, based on reverse engeneering by Stephane Marchesin */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000819 if ((flags & (RADEON_DEPTH | RADEON_STENCIL))
820 && (flags & RADEON_CLEAR_FASTZ)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821
822 int i;
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000823 int depthpixperline =
824 dev_priv->depth_fmt ==
825 RADEON_DEPTH_FORMAT_16BIT_INT_Z ? (dev_priv->depth_pitch /
826 2) : (dev_priv->
827 depth_pitch / 4);
828
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829 u32 clearmask;
830
831 u32 tempRB3D_DEPTHCLEARVALUE = clear->clear_depth |
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000832 ((clear->depth_mask & 0xff) << 24);
833
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834 /* Make sure we restore the 3D state next time.
835 * we haven't touched any "normal" state - still need this?
836 */
837 dev_priv->sarea_priv->ctx_owner = 0;
838
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000839 if ((dev_priv->flags & CHIP_HAS_HIERZ)
840 && (flags & RADEON_USE_HIERZ)) {
841 /* FIXME : reverse engineer that for Rx00 cards */
842 /* FIXME : the mask supposedly contains low-res z values. So can't set
843 just to the max (0xff? or actually 0x3fff?), need to take z clear
844 value into account? */
845 /* pattern seems to work for r100, though get slight
846 rendering errors with glxgears. If hierz is not enabled for r100,
847 only 4 bits which indicate clear (15,16,31,32, all zero) matter, the
848 other ones are ignored, and the same clear mask can be used. That's
849 very different behaviour than R200 which needs different clear mask
850 and different number of tiles to clear if hierz is enabled or not !?!
851 */
852 clearmask = (0xff << 22) | (0xff << 6) | 0x003f003f;
853 } else {
854 /* clear mask : chooses the clearing pattern.
855 rv250: could be used to clear only parts of macrotiles
856 (but that would get really complicated...)?
857 bit 0 and 1 (either or both of them ?!?!) are used to
858 not clear tile (or maybe one of the bits indicates if the tile is
859 compressed or not), bit 2 and 3 to not clear tile 1,...,.
860 Pattern is as follows:
861 | 0,1 | 4,5 | 8,9 |12,13|16,17|20,21|24,25|28,29|
862 bits -------------------------------------------------
863 | 2,3 | 6,7 |10,11|14,15|18,19|22,23|26,27|30,31|
864 rv100: clearmask covers 2x8 4x1 tiles, but one clear still
865 covers 256 pixels ?!?
866 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867 clearmask = 0x0;
868 }
869
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000870 BEGIN_RING(8);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871 RADEON_WAIT_UNTIL_2D_IDLE();
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000872 OUT_RING_REG(RADEON_RB3D_DEPTHCLEARVALUE,
873 tempRB3D_DEPTHCLEARVALUE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874 /* what offset is this exactly ? */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000875 OUT_RING_REG(RADEON_RB3D_ZMASKOFFSET, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876 /* need ctlstat, otherwise get some strange black flickering */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000877 OUT_RING_REG(RADEON_RB3D_ZCACHE_CTLSTAT,
878 RADEON_RB3D_ZC_FLUSH_ALL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879 ADVANCE_RING();
880
881 for (i = 0; i < nbox; i++) {
882 int tileoffset, nrtilesx, nrtilesy, j;
883 /* it looks like r200 needs rv-style clears, at least if hierz is not enabled? */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000884 if ((dev_priv->flags & CHIP_HAS_HIERZ)
885 && !(dev_priv->microcode_version == UCODE_R200)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886 /* FIXME : figure this out for r200 (when hierz is enabled). Or
887 maybe r200 actually doesn't need to put the low-res z value into
888 the tile cache like r100, but just needs to clear the hi-level z-buffer?
889 Works for R100, both with hierz and without.
890 R100 seems to operate on 2x1 8x8 tiles, but...
891 odd: offset/nrtiles need to be 64 pix (4 block) aligned? Potentially
892 problematic with resolutions which are not 64 pix aligned? */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000893 tileoffset =
894 ((pbox[i].y1 >> 3) * depthpixperline +
895 pbox[i].x1) >> 6;
896 nrtilesx =
897 ((pbox[i].x2 & ~63) -
898 (pbox[i].x1 & ~63)) >> 4;
899 nrtilesy =
900 (pbox[i].y2 >> 3) - (pbox[i].y1 >> 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901 for (j = 0; j <= nrtilesy; j++) {
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000902 BEGIN_RING(4);
903 OUT_RING(CP_PACKET3
904 (RADEON_3D_CLEAR_ZMASK, 2));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905 /* first tile */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000906 OUT_RING(tileoffset * 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907 /* the number of tiles to clear */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000908 OUT_RING(nrtilesx + 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909 /* clear mask : chooses the clearing pattern. */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000910 OUT_RING(clearmask);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911 ADVANCE_RING();
912 tileoffset += depthpixperline >> 6;
913 }
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000914 } else if (dev_priv->microcode_version == UCODE_R200) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915 /* works for rv250. */
916 /* find first macro tile (8x2 4x4 z-pixels on rv250) */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000917 tileoffset =
918 ((pbox[i].y1 >> 3) * depthpixperline +
919 pbox[i].x1) >> 5;
920 nrtilesx =
921 (pbox[i].x2 >> 5) - (pbox[i].x1 >> 5);
922 nrtilesy =
923 (pbox[i].y2 >> 3) - (pbox[i].y1 >> 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924 for (j = 0; j <= nrtilesy; j++) {
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000925 BEGIN_RING(4);
926 OUT_RING(CP_PACKET3
927 (RADEON_3D_CLEAR_ZMASK, 2));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928 /* first tile */
929 /* judging by the first tile offset needed, could possibly
930 directly address/clear 4x4 tiles instead of 8x2 * 4x4
931 macro tiles, though would still need clear mask for
932 right/bottom if truely 4x4 granularity is desired ? */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000933 OUT_RING(tileoffset * 16);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934 /* the number of tiles to clear */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000935 OUT_RING(nrtilesx + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936 /* clear mask : chooses the clearing pattern. */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000937 OUT_RING(clearmask);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938 ADVANCE_RING();
939 tileoffset += depthpixperline >> 5;
940 }
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000941 } else { /* rv 100 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942 /* rv100 might not need 64 pix alignment, who knows */
943 /* offsets are, hmm, weird */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000944 tileoffset =
945 ((pbox[i].y1 >> 4) * depthpixperline +
946 pbox[i].x1) >> 6;
947 nrtilesx =
948 ((pbox[i].x2 & ~63) -
949 (pbox[i].x1 & ~63)) >> 4;
950 nrtilesy =
951 (pbox[i].y2 >> 4) - (pbox[i].y1 >> 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952 for (j = 0; j <= nrtilesy; j++) {
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000953 BEGIN_RING(4);
954 OUT_RING(CP_PACKET3
955 (RADEON_3D_CLEAR_ZMASK, 2));
956 OUT_RING(tileoffset * 128);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957 /* the number of tiles to clear */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000958 OUT_RING(nrtilesx + 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700959 /* clear mask : chooses the clearing pattern. */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000960 OUT_RING(clearmask);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700961 ADVANCE_RING();
962 tileoffset += depthpixperline >> 6;
963 }
964 }
965 }
966
967 /* TODO don't always clear all hi-level z tiles */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000968 if ((dev_priv->flags & CHIP_HAS_HIERZ)
969 && (dev_priv->microcode_version == UCODE_R200)
970 && (flags & RADEON_USE_HIERZ))
971 /* r100 and cards without hierarchical z-buffer have no high-level z-buffer */
972 /* FIXME : the mask supposedly contains low-res z values. So can't set
973 just to the max (0xff? or actually 0x3fff?), need to take z clear
974 value into account? */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975 {
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000976 BEGIN_RING(4);
977 OUT_RING(CP_PACKET3(RADEON_3D_CLEAR_HIZ, 2));
978 OUT_RING(0x0); /* First tile */
979 OUT_RING(0x3cc0);
980 OUT_RING((0xff << 22) | (0xff << 6) | 0x003f003f);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981 ADVANCE_RING();
982 }
983 }
984
985 /* We have to clear the depth and/or stencil buffers by
986 * rendering a quad into just those buffers. Thus, we have to
987 * make sure the 3D engine is configured correctly.
988 */
989 if ((dev_priv->microcode_version == UCODE_R200) &&
990 (flags & (RADEON_DEPTH | RADEON_STENCIL))) {
991
992 int tempPP_CNTL;
993 int tempRE_CNTL;
994 int tempRB3D_CNTL;
995 int tempRB3D_ZSTENCILCNTL;
996 int tempRB3D_STENCILREFMASK;
997 int tempRB3D_PLANEMASK;
998 int tempSE_CNTL;
999 int tempSE_VTE_CNTL;
1000 int tempSE_VTX_FMT_0;
1001 int tempSE_VTX_FMT_1;
1002 int tempSE_VAP_CNTL;
1003 int tempRE_AUX_SCISSOR_CNTL;
1004
1005 tempPP_CNTL = 0;
1006 tempRE_CNTL = 0;
1007
1008 tempRB3D_CNTL = depth_clear->rb3d_cntl;
1009
1010 tempRB3D_ZSTENCILCNTL = depth_clear->rb3d_zstencilcntl;
1011 tempRB3D_STENCILREFMASK = 0x0;
1012
1013 tempSE_CNTL = depth_clear->se_cntl;
1014
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015 /* Disable TCL */
1016
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001017 tempSE_VAP_CNTL = ( /* SE_VAP_CNTL__FORCE_W_TO_ONE_MASK | */
1018 (0x9 <<
1019 SE_VAP_CNTL__VF_MAX_VTX_NUM__SHIFT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020
1021 tempRB3D_PLANEMASK = 0x0;
1022
1023 tempRE_AUX_SCISSOR_CNTL = 0x0;
1024
1025 tempSE_VTE_CNTL =
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001026 SE_VTE_CNTL__VTX_XY_FMT_MASK | SE_VTE_CNTL__VTX_Z_FMT_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001028 /* Vertex format (X, Y, Z, W) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 tempSE_VTX_FMT_0 =
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001030 SE_VTX_FMT_0__VTX_Z0_PRESENT_MASK |
1031 SE_VTX_FMT_0__VTX_W0_PRESENT_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032 tempSE_VTX_FMT_1 = 0x0;
1033
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001034 /*
1035 * Depth buffer specific enables
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036 */
1037 if (flags & RADEON_DEPTH) {
1038 /* Enable depth buffer */
1039 tempRB3D_CNTL |= RADEON_Z_ENABLE;
1040 } else {
1041 /* Disable depth buffer */
1042 tempRB3D_CNTL &= ~RADEON_Z_ENABLE;
1043 }
1044
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001045 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046 * Stencil buffer specific enables
1047 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001048 if (flags & RADEON_STENCIL) {
1049 tempRB3D_CNTL |= RADEON_STENCIL_ENABLE;
1050 tempRB3D_STENCILREFMASK = clear->depth_mask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051 } else {
1052 tempRB3D_CNTL &= ~RADEON_STENCIL_ENABLE;
1053 tempRB3D_STENCILREFMASK = 0x00000000;
1054 }
1055
1056 if (flags & RADEON_USE_COMP_ZBUF) {
1057 tempRB3D_ZSTENCILCNTL |= RADEON_Z_COMPRESSION_ENABLE |
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001058 RADEON_Z_DECOMPRESSION_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059 }
1060 if (flags & RADEON_USE_HIERZ) {
1061 tempRB3D_ZSTENCILCNTL |= RADEON_Z_HIERARCHY_ENABLE;
1062 }
1063
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001064 BEGIN_RING(26);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065 RADEON_WAIT_UNTIL_2D_IDLE();
1066
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001067 OUT_RING_REG(RADEON_PP_CNTL, tempPP_CNTL);
1068 OUT_RING_REG(R200_RE_CNTL, tempRE_CNTL);
1069 OUT_RING_REG(RADEON_RB3D_CNTL, tempRB3D_CNTL);
1070 OUT_RING_REG(RADEON_RB3D_ZSTENCILCNTL, tempRB3D_ZSTENCILCNTL);
1071 OUT_RING_REG(RADEON_RB3D_STENCILREFMASK,
1072 tempRB3D_STENCILREFMASK);
1073 OUT_RING_REG(RADEON_RB3D_PLANEMASK, tempRB3D_PLANEMASK);
1074 OUT_RING_REG(RADEON_SE_CNTL, tempSE_CNTL);
1075 OUT_RING_REG(R200_SE_VTE_CNTL, tempSE_VTE_CNTL);
1076 OUT_RING_REG(R200_SE_VTX_FMT_0, tempSE_VTX_FMT_0);
1077 OUT_RING_REG(R200_SE_VTX_FMT_1, tempSE_VTX_FMT_1);
1078 OUT_RING_REG(R200_SE_VAP_CNTL, tempSE_VAP_CNTL);
1079 OUT_RING_REG(R200_RE_AUX_SCISSOR_CNTL, tempRE_AUX_SCISSOR_CNTL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080 ADVANCE_RING();
1081
1082 /* Make sure we restore the 3D state next time.
1083 */
1084 dev_priv->sarea_priv->ctx_owner = 0;
1085
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001086 for (i = 0; i < nbox; i++) {
1087
1088 /* Funny that this should be required --
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089 * sets top-left?
1090 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001091 radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001093 BEGIN_RING(14);
1094 OUT_RING(CP_PACKET3(R200_3D_DRAW_IMMD_2, 12));
1095 OUT_RING((RADEON_PRIM_TYPE_RECT_LIST |
1096 RADEON_PRIM_WALK_RING |
1097 (3 << RADEON_NUM_VERTICES_SHIFT)));
1098 OUT_RING(depth_boxes[i].ui[CLEAR_X1]);
1099 OUT_RING(depth_boxes[i].ui[CLEAR_Y1]);
1100 OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
1101 OUT_RING(0x3f800000);
1102 OUT_RING(depth_boxes[i].ui[CLEAR_X1]);
1103 OUT_RING(depth_boxes[i].ui[CLEAR_Y2]);
1104 OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
1105 OUT_RING(0x3f800000);
1106 OUT_RING(depth_boxes[i].ui[CLEAR_X2]);
1107 OUT_RING(depth_boxes[i].ui[CLEAR_Y2]);
1108 OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
1109 OUT_RING(0x3f800000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110 ADVANCE_RING();
1111 }
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001112 } else if ((flags & (RADEON_DEPTH | RADEON_STENCIL))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113
1114 int tempRB3D_ZSTENCILCNTL = depth_clear->rb3d_zstencilcntl;
1115
1116 rb3d_cntl = depth_clear->rb3d_cntl;
1117
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001118 if (flags & RADEON_DEPTH) {
1119 rb3d_cntl |= RADEON_Z_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120 } else {
1121 rb3d_cntl &= ~RADEON_Z_ENABLE;
1122 }
1123
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001124 if (flags & RADEON_STENCIL) {
1125 rb3d_cntl |= RADEON_STENCIL_ENABLE;
1126 rb3d_stencilrefmask = clear->depth_mask; /* misnamed field */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127 } else {
1128 rb3d_cntl &= ~RADEON_STENCIL_ENABLE;
1129 rb3d_stencilrefmask = 0x00000000;
1130 }
1131
1132 if (flags & RADEON_USE_COMP_ZBUF) {
1133 tempRB3D_ZSTENCILCNTL |= RADEON_Z_COMPRESSION_ENABLE |
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001134 RADEON_Z_DECOMPRESSION_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135 }
1136 if (flags & RADEON_USE_HIERZ) {
1137 tempRB3D_ZSTENCILCNTL |= RADEON_Z_HIERARCHY_ENABLE;
1138 }
1139
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001140 BEGIN_RING(13);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141 RADEON_WAIT_UNTIL_2D_IDLE();
1142
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001143 OUT_RING(CP_PACKET0(RADEON_PP_CNTL, 1));
1144 OUT_RING(0x00000000);
1145 OUT_RING(rb3d_cntl);
1146
1147 OUT_RING_REG(RADEON_RB3D_ZSTENCILCNTL, tempRB3D_ZSTENCILCNTL);
1148 OUT_RING_REG(RADEON_RB3D_STENCILREFMASK, rb3d_stencilrefmask);
1149 OUT_RING_REG(RADEON_RB3D_PLANEMASK, 0x00000000);
1150 OUT_RING_REG(RADEON_SE_CNTL, depth_clear->se_cntl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151 ADVANCE_RING();
1152
1153 /* Make sure we restore the 3D state next time.
1154 */
1155 dev_priv->sarea_priv->ctx_owner = 0;
1156
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001157 for (i = 0; i < nbox; i++) {
1158
1159 /* Funny that this should be required --
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160 * sets top-left?
1161 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001162 radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001164 BEGIN_RING(15);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001166 OUT_RING(CP_PACKET3(RADEON_3D_DRAW_IMMD, 13));
1167 OUT_RING(RADEON_VTX_Z_PRESENT |
1168 RADEON_VTX_PKCOLOR_PRESENT);
1169 OUT_RING((RADEON_PRIM_TYPE_RECT_LIST |
1170 RADEON_PRIM_WALK_RING |
1171 RADEON_MAOS_ENABLE |
1172 RADEON_VTX_FMT_RADEON_MODE |
1173 (3 << RADEON_NUM_VERTICES_SHIFT)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001175 OUT_RING(depth_boxes[i].ui[CLEAR_X1]);
1176 OUT_RING(depth_boxes[i].ui[CLEAR_Y1]);
1177 OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
1178 OUT_RING(0x0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001180 OUT_RING(depth_boxes[i].ui[CLEAR_X1]);
1181 OUT_RING(depth_boxes[i].ui[CLEAR_Y2]);
1182 OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
1183 OUT_RING(0x0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001185 OUT_RING(depth_boxes[i].ui[CLEAR_X2]);
1186 OUT_RING(depth_boxes[i].ui[CLEAR_Y2]);
1187 OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
1188 OUT_RING(0x0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189
1190 ADVANCE_RING();
1191 }
1192 }
1193
1194 /* Increment the clear counter. The client-side 3D driver must
1195 * wait on this value before performing the clear ioctl. We
1196 * need this because the card's so damned fast...
1197 */
1198 dev_priv->sarea_priv->last_clear++;
1199
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001200 BEGIN_RING(4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001202 RADEON_CLEAR_AGE(dev_priv->sarea_priv->last_clear);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203 RADEON_WAIT_UNTIL_IDLE();
1204
1205 ADVANCE_RING();
1206}
1207
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001208static void radeon_cp_dispatch_swap(drm_device_t * dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209{
1210 drm_radeon_private_t *dev_priv = dev->dev_private;
1211 drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
1212 int nbox = sarea_priv->nbox;
1213 drm_clip_rect_t *pbox = sarea_priv->boxes;
1214 int i;
1215 RING_LOCALS;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001216 DRM_DEBUG("\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217
1218 /* Do some trivial performance monitoring...
1219 */
1220 if (dev_priv->do_boxes)
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001221 radeon_cp_performance_boxes(dev_priv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222
1223 /* Wait for the 3D stream to idle before dispatching the bitblt.
1224 * This will prevent data corruption between the two streams.
1225 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001226 BEGIN_RING(2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227
1228 RADEON_WAIT_UNTIL_3D_IDLE();
1229
1230 ADVANCE_RING();
1231
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001232 for (i = 0; i < nbox; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233 int x = pbox[i].x1;
1234 int y = pbox[i].y1;
1235 int w = pbox[i].x2 - x;
1236 int h = pbox[i].y2 - y;
1237
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001238 DRM_DEBUG("dispatch swap %d,%d-%d,%d\n", x, y, w, h);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001240 BEGIN_RING(7);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001242 OUT_RING(CP_PACKET3(RADEON_CNTL_BITBLT_MULTI, 5));
1243 OUT_RING(RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
1244 RADEON_GMC_DST_PITCH_OFFSET_CNTL |
1245 RADEON_GMC_BRUSH_NONE |
1246 (dev_priv->color_fmt << 8) |
1247 RADEON_GMC_SRC_DATATYPE_COLOR |
1248 RADEON_ROP3_S |
1249 RADEON_DP_SRC_SOURCE_MEMORY |
1250 RADEON_GMC_CLR_CMP_CNTL_DIS | RADEON_GMC_WR_MSK_DIS);
1251
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252 /* Make this work even if front & back are flipped:
1253 */
1254 if (dev_priv->current_page == 0) {
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001255 OUT_RING(dev_priv->back_pitch_offset);
1256 OUT_RING(dev_priv->front_pitch_offset);
1257 } else {
1258 OUT_RING(dev_priv->front_pitch_offset);
1259 OUT_RING(dev_priv->back_pitch_offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260 }
1261
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001262 OUT_RING((x << 16) | y);
1263 OUT_RING((x << 16) | y);
1264 OUT_RING((w << 16) | h);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001265
1266 ADVANCE_RING();
1267 }
1268
1269 /* Increment the frame counter. The client-side 3D driver must
1270 * throttle the framerate by waiting for this value before
1271 * performing the swapbuffer ioctl.
1272 */
1273 dev_priv->sarea_priv->last_frame++;
1274
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001275 BEGIN_RING(4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001277 RADEON_FRAME_AGE(dev_priv->sarea_priv->last_frame);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278 RADEON_WAIT_UNTIL_2D_IDLE();
1279
1280 ADVANCE_RING();
1281}
1282
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001283static void radeon_cp_dispatch_flip(drm_device_t * dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284{
1285 drm_radeon_private_t *dev_priv = dev->dev_private;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001286 drm_sarea_t *sarea = (drm_sarea_t *) dev_priv->sarea->handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287 int offset = (dev_priv->current_page == 1)
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001288 ? dev_priv->front_offset : dev_priv->back_offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289 RING_LOCALS;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001290 DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
1291 __FUNCTION__,
1292 dev_priv->current_page, dev_priv->sarea_priv->pfCurrentPage);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293
1294 /* Do some trivial performance monitoring...
1295 */
1296 if (dev_priv->do_boxes) {
1297 dev_priv->stats.boxes |= RADEON_BOX_FLIP;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001298 radeon_cp_performance_boxes(dev_priv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299 }
1300
1301 /* Update the frame offsets for both CRTCs
1302 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001303 BEGIN_RING(6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304
1305 RADEON_WAIT_UNTIL_3D_IDLE();
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001306 OUT_RING_REG(RADEON_CRTC_OFFSET,
1307 ((sarea->frame.y * dev_priv->front_pitch +
1308 sarea->frame.x * (dev_priv->color_fmt - 2)) & ~7)
1309 + offset);
1310 OUT_RING_REG(RADEON_CRTC2_OFFSET, dev_priv->sarea_priv->crtc2_base
1311 + offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001312
1313 ADVANCE_RING();
1314
1315 /* Increment the frame counter. The client-side 3D driver must
1316 * throttle the framerate by waiting for this value before
1317 * performing the swapbuffer ioctl.
1318 */
1319 dev_priv->sarea_priv->last_frame++;
1320 dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page =
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001321 1 - dev_priv->current_page;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001323 BEGIN_RING(2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001325 RADEON_FRAME_AGE(dev_priv->sarea_priv->last_frame);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326
1327 ADVANCE_RING();
1328}
1329
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001330static int bad_prim_vertex_nr(int primitive, int nr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001331{
1332 switch (primitive & RADEON_PRIM_TYPE_MASK) {
1333 case RADEON_PRIM_TYPE_NONE:
1334 case RADEON_PRIM_TYPE_POINT:
1335 return nr < 1;
1336 case RADEON_PRIM_TYPE_LINE:
1337 return (nr & 1) || nr == 0;
1338 case RADEON_PRIM_TYPE_LINE_STRIP:
1339 return nr < 2;
1340 case RADEON_PRIM_TYPE_TRI_LIST:
1341 case RADEON_PRIM_TYPE_3VRT_POINT_LIST:
1342 case RADEON_PRIM_TYPE_3VRT_LINE_LIST:
1343 case RADEON_PRIM_TYPE_RECT_LIST:
1344 return nr % 3 || nr == 0;
1345 case RADEON_PRIM_TYPE_TRI_FAN:
1346 case RADEON_PRIM_TYPE_TRI_STRIP:
1347 return nr < 3;
1348 default:
1349 return 1;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001350 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351}
1352
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353typedef struct {
1354 unsigned int start;
1355 unsigned int finish;
1356 unsigned int prim;
1357 unsigned int numverts;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001358 unsigned int offset;
1359 unsigned int vc_format;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360} drm_radeon_tcl_prim_t;
1361
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001362static void radeon_cp_dispatch_vertex(drm_device_t * dev,
1363 drm_buf_t * buf,
1364 drm_radeon_tcl_prim_t * prim)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365{
1366 drm_radeon_private_t *dev_priv = dev->dev_private;
1367 drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
1368 int offset = dev_priv->gart_buffers_offset + buf->offset + prim->start;
1369 int numverts = (int)prim->numverts;
1370 int nbox = sarea_priv->nbox;
1371 int i = 0;
1372 RING_LOCALS;
1373
1374 DRM_DEBUG("hwprim 0x%x vfmt 0x%x %d..%d %d verts\n",
1375 prim->prim,
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001376 prim->vc_format, prim->start, prim->finish, prim->numverts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001378 if (bad_prim_vertex_nr(prim->prim, prim->numverts)) {
1379 DRM_ERROR("bad prim %x numverts %d\n",
1380 prim->prim, prim->numverts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381 return;
1382 }
1383
1384 do {
1385 /* Emit the next cliprect */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001386 if (i < nbox) {
1387 radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388 }
1389
1390 /* Emit the vertex buffer rendering commands */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001391 BEGIN_RING(5);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001393 OUT_RING(CP_PACKET3(RADEON_3D_RNDR_GEN_INDX_PRIM, 3));
1394 OUT_RING(offset);
1395 OUT_RING(numverts);
1396 OUT_RING(prim->vc_format);
1397 OUT_RING(prim->prim | RADEON_PRIM_WALK_LIST |
1398 RADEON_COLOR_ORDER_RGBA |
1399 RADEON_VTX_FMT_RADEON_MODE |
1400 (numverts << RADEON_NUM_VERTICES_SHIFT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401
1402 ADVANCE_RING();
1403
1404 i++;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001405 } while (i < nbox);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406}
1407
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001408static void radeon_cp_discard_buffer(drm_device_t * dev, drm_buf_t * buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001409{
1410 drm_radeon_private_t *dev_priv = dev->dev_private;
1411 drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
1412 RING_LOCALS;
1413
1414 buf_priv->age = ++dev_priv->sarea_priv->last_dispatch;
1415
1416 /* Emit the vertex buffer age */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001417 BEGIN_RING(2);
1418 RADEON_DISPATCH_AGE(buf_priv->age);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001419 ADVANCE_RING();
1420
1421 buf->pending = 1;
1422 buf->used = 0;
1423}
1424
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001425static void radeon_cp_dispatch_indirect(drm_device_t * dev,
1426 drm_buf_t * buf, int start, int end)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001427{
1428 drm_radeon_private_t *dev_priv = dev->dev_private;
1429 RING_LOCALS;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001430 DRM_DEBUG("indirect: buf=%d s=0x%x e=0x%x\n", buf->idx, start, end);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001432 if (start != end) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433 int offset = (dev_priv->gart_buffers_offset
1434 + buf->offset + start);
1435 int dwords = (end - start + 3) / sizeof(u32);
1436
1437 /* Indirect buffer data must be an even number of
1438 * dwords, so if we've been given an odd number we must
1439 * pad the data with a Type-2 CP packet.
1440 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001441 if (dwords & 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001442 u32 *data = (u32 *)
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001443 ((char *)dev->agp_buffer_map->handle
1444 + buf->offset + start);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445 data[dwords++] = RADEON_CP_PACKET2;
1446 }
1447
1448 /* Fire off the indirect buffer */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001449 BEGIN_RING(3);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001451 OUT_RING(CP_PACKET0(RADEON_CP_IB_BASE, 1));
1452 OUT_RING(offset);
1453 OUT_RING(dwords);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454
1455 ADVANCE_RING();
1456 }
1457}
1458
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001459static void radeon_cp_dispatch_indices(drm_device_t * dev,
1460 drm_buf_t * elt_buf,
1461 drm_radeon_tcl_prim_t * prim)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001462{
1463 drm_radeon_private_t *dev_priv = dev->dev_private;
1464 drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
1465 int offset = dev_priv->gart_buffers_offset + prim->offset;
1466 u32 *data;
1467 int dwords;
1468 int i = 0;
1469 int start = prim->start + RADEON_INDEX_PRIM_OFFSET;
1470 int count = (prim->finish - start) / sizeof(u16);
1471 int nbox = sarea_priv->nbox;
1472
1473 DRM_DEBUG("hwprim 0x%x vfmt 0x%x %d..%d offset: %x nr %d\n",
1474 prim->prim,
1475 prim->vc_format,
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001476 prim->start, prim->finish, prim->offset, prim->numverts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001478 if (bad_prim_vertex_nr(prim->prim, count)) {
1479 DRM_ERROR("bad prim %x count %d\n", prim->prim, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001480 return;
1481 }
1482
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001483 if (start >= prim->finish || (prim->start & 0x7)) {
1484 DRM_ERROR("buffer prim %d\n", prim->prim);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001485 return;
1486 }
1487
1488 dwords = (prim->finish - prim->start + 3) / sizeof(u32);
1489
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001490 data = (u32 *) ((char *)dev->agp_buffer_map->handle +
1491 elt_buf->offset + prim->start);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001493 data[0] = CP_PACKET3(RADEON_3D_RNDR_GEN_INDX_PRIM, dwords - 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001494 data[1] = offset;
1495 data[2] = prim->numverts;
1496 data[3] = prim->vc_format;
1497 data[4] = (prim->prim |
1498 RADEON_PRIM_WALK_IND |
1499 RADEON_COLOR_ORDER_RGBA |
1500 RADEON_VTX_FMT_RADEON_MODE |
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001501 (count << RADEON_NUM_VERTICES_SHIFT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001502
1503 do {
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001504 if (i < nbox)
1505 radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001506
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001507 radeon_cp_dispatch_indirect(dev, elt_buf,
1508 prim->start, prim->finish);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001509
1510 i++;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001511 } while (i < nbox);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512
1513}
1514
Dave Airlieffbbf7a2005-08-20 17:40:04 +10001515#define RADEON_MAX_TEXTURE_SIZE RADEON_BUFFER_SIZE
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001517static int radeon_cp_dispatch_texture(DRMFILE filp,
1518 drm_device_t * dev,
1519 drm_radeon_texture_t * tex,
1520 drm_radeon_tex_image_t * image)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521{
1522 drm_radeon_private_t *dev_priv = dev->dev_private;
1523 drm_file_t *filp_priv;
1524 drm_buf_t *buf;
1525 u32 format;
1526 u32 *buffer;
1527 const u8 __user *data;
Dave Airlieffbbf7a2005-08-20 17:40:04 +10001528 int size, dwords, tex_width, blit_width, spitch;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001529 u32 height;
1530 int i;
1531 u32 texpitch, microtile;
Dave Airlieffbbf7a2005-08-20 17:40:04 +10001532 u32 offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001533 RING_LOCALS;
1534
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001535 DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001537 if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &tex->offset)) {
1538 DRM_ERROR("Invalid destination offset\n");
1539 return DRM_ERR(EINVAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540 }
1541
1542 dev_priv->stats.boxes |= RADEON_BOX_TEXTURE_LOAD;
1543
1544 /* Flush the pixel cache. This ensures no pixel data gets mixed
1545 * up with the texture data from the host data blit, otherwise
1546 * part of the texture image may be corrupted.
1547 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001548 BEGIN_RING(4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001549 RADEON_FLUSH_CACHE();
1550 RADEON_WAIT_UNTIL_IDLE();
1551 ADVANCE_RING();
1552
Linus Torvalds1da177e2005-04-16 15:20:36 -07001553 /* The compiler won't optimize away a division by a variable,
1554 * even if the only legal values are powers of two. Thus, we'll
1555 * use a shift instead.
1556 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001557 switch (tex->format) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001558 case RADEON_TXFORMAT_ARGB8888:
1559 case RADEON_TXFORMAT_RGBA8888:
1560 format = RADEON_COLOR_FORMAT_ARGB8888;
1561 tex_width = tex->width * 4;
1562 blit_width = image->width * 4;
1563 break;
1564 case RADEON_TXFORMAT_AI88:
1565 case RADEON_TXFORMAT_ARGB1555:
1566 case RADEON_TXFORMAT_RGB565:
1567 case RADEON_TXFORMAT_ARGB4444:
1568 case RADEON_TXFORMAT_VYUY422:
1569 case RADEON_TXFORMAT_YVYU422:
1570 format = RADEON_COLOR_FORMAT_RGB565;
1571 tex_width = tex->width * 2;
1572 blit_width = image->width * 2;
1573 break;
1574 case RADEON_TXFORMAT_I8:
1575 case RADEON_TXFORMAT_RGB332:
1576 format = RADEON_COLOR_FORMAT_CI8;
1577 tex_width = tex->width * 1;
1578 blit_width = image->width * 1;
1579 break;
1580 default:
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001581 DRM_ERROR("invalid texture format %d\n", tex->format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001582 return DRM_ERR(EINVAL);
1583 }
Dave Airlieffbbf7a2005-08-20 17:40:04 +10001584 spitch = blit_width >> 6;
1585 if (spitch == 0 && image->height > 1)
1586 return DRM_ERR(EINVAL);
1587
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588 texpitch = tex->pitch;
1589 if ((texpitch << 22) & RADEON_DST_TILE_MICRO) {
1590 microtile = 1;
1591 if (tex_width < 64) {
1592 texpitch &= ~(RADEON_DST_TILE_MICRO >> 22);
1593 /* we got tiled coordinates, untile them */
1594 image->x *= 2;
1595 }
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001596 } else
1597 microtile = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001598
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001599 DRM_DEBUG("tex=%dx%d blit=%d\n", tex_width, tex->height, blit_width);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001600
1601 do {
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001602 DRM_DEBUG("tex: ofs=0x%x p=%d f=%d x=%hd y=%hd w=%hd h=%hd\n",
1603 tex->offset >> 10, tex->pitch, tex->format,
1604 image->x, image->y, image->width, image->height);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001605
1606 /* Make a copy of some parameters in case we have to
1607 * update them for a multi-pass texture blit.
1608 */
1609 height = image->height;
1610 data = (const u8 __user *)image->data;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001611
Linus Torvalds1da177e2005-04-16 15:20:36 -07001612 size = height * blit_width;
1613
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001614 if (size > RADEON_MAX_TEXTURE_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615 height = RADEON_MAX_TEXTURE_SIZE / blit_width;
1616 size = height * blit_width;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001617 } else if (size < 4 && size > 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001618 size = 4;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001619 } else if (size == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001620 return 0;
1621 }
1622
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001623 buf = radeon_freelist_get(dev);
1624 if (0 && !buf) {
1625 radeon_do_cp_idle(dev_priv);
1626 buf = radeon_freelist_get(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001627 }
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001628 if (!buf) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001629 DRM_DEBUG("radeon_cp_dispatch_texture: EAGAIN\n");
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001630 if (DRM_COPY_TO_USER(tex->image, image, sizeof(*image)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631 return DRM_ERR(EFAULT);
1632 return DRM_ERR(EAGAIN);
1633 }
1634
Linus Torvalds1da177e2005-04-16 15:20:36 -07001635 /* Dispatch the indirect buffer.
1636 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001637 buffer =
1638 (u32 *) ((char *)dev->agp_buffer_map->handle + buf->offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001639 dwords = size / 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640
1641 if (microtile) {
1642 /* texture micro tiling in use, minimum texture width is thus 16 bytes.
1643 however, we cannot use blitter directly for texture width < 64 bytes,
1644 since minimum tex pitch is 64 bytes and we need this to match
1645 the texture width, otherwise the blitter will tile it wrong.
1646 Thus, tiling manually in this case. Additionally, need to special
1647 case tex height = 1, since our actual image will have height 2
1648 and we need to ensure we don't read beyond the texture size
1649 from user space. */
1650 if (tex->height == 1) {
1651 if (tex_width >= 64 || tex_width <= 16) {
1652 if (DRM_COPY_FROM_USER(buffer, data,
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001653 tex_width *
1654 sizeof(u32))) {
1655 DRM_ERROR
1656 ("EFAULT on pad, %d bytes\n",
1657 tex_width);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658 return DRM_ERR(EFAULT);
1659 }
1660 } else if (tex_width == 32) {
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001661 if (DRM_COPY_FROM_USER
1662 (buffer, data, 16)) {
1663 DRM_ERROR
1664 ("EFAULT on pad, %d bytes\n",
1665 tex_width);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001666 return DRM_ERR(EFAULT);
1667 }
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001668 if (DRM_COPY_FROM_USER
1669 (buffer + 8, data + 16, 16)) {
1670 DRM_ERROR
1671 ("EFAULT on pad, %d bytes\n",
1672 tex_width);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673 return DRM_ERR(EFAULT);
1674 }
1675 }
1676 } else if (tex_width >= 64 || tex_width == 16) {
1677 if (DRM_COPY_FROM_USER(buffer, data,
1678 dwords * sizeof(u32))) {
1679 DRM_ERROR("EFAULT on data, %d dwords\n",
1680 dwords);
1681 return DRM_ERR(EFAULT);
1682 }
1683 } else if (tex_width < 16) {
1684 for (i = 0; i < tex->height; i++) {
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001685 if (DRM_COPY_FROM_USER
1686 (buffer, data, tex_width)) {
1687 DRM_ERROR
1688 ("EFAULT on pad, %d bytes\n",
1689 tex_width);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001690 return DRM_ERR(EFAULT);
1691 }
1692 buffer += 4;
1693 data += tex_width;
1694 }
1695 } else if (tex_width == 32) {
1696 /* TODO: make sure this works when not fitting in one buffer
1697 (i.e. 32bytes x 2048...) */
1698 for (i = 0; i < tex->height; i += 2) {
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001699 if (DRM_COPY_FROM_USER
1700 (buffer, data, 16)) {
1701 DRM_ERROR
1702 ("EFAULT on pad, %d bytes\n",
1703 tex_width);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704 return DRM_ERR(EFAULT);
1705 }
1706 data += 16;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001707 if (DRM_COPY_FROM_USER
1708 (buffer + 8, data, 16)) {
1709 DRM_ERROR
1710 ("EFAULT on pad, %d bytes\n",
1711 tex_width);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712 return DRM_ERR(EFAULT);
1713 }
1714 data += 16;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001715 if (DRM_COPY_FROM_USER
1716 (buffer + 4, data, 16)) {
1717 DRM_ERROR
1718 ("EFAULT on pad, %d bytes\n",
1719 tex_width);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001720 return DRM_ERR(EFAULT);
1721 }
1722 data += 16;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001723 if (DRM_COPY_FROM_USER
1724 (buffer + 12, data, 16)) {
1725 DRM_ERROR
1726 ("EFAULT on pad, %d bytes\n",
1727 tex_width);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001728 return DRM_ERR(EFAULT);
1729 }
1730 data += 16;
1731 buffer += 16;
1732 }
1733 }
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001734 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001735 if (tex_width >= 32) {
1736 /* Texture image width is larger than the minimum, so we
1737 * can upload it directly.
1738 */
1739 if (DRM_COPY_FROM_USER(buffer, data,
1740 dwords * sizeof(u32))) {
1741 DRM_ERROR("EFAULT on data, %d dwords\n",
1742 dwords);
1743 return DRM_ERR(EFAULT);
1744 }
1745 } else {
1746 /* Texture image width is less than the minimum, so we
1747 * need to pad out each image scanline to the minimum
1748 * width.
1749 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001750 for (i = 0; i < tex->height; i++) {
1751 if (DRM_COPY_FROM_USER
1752 (buffer, data, tex_width)) {
1753 DRM_ERROR
1754 ("EFAULT on pad, %d bytes\n",
1755 tex_width);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001756 return DRM_ERR(EFAULT);
1757 }
1758 buffer += 8;
1759 data += tex_width;
1760 }
1761 }
1762 }
1763
1764 buf->filp = filp;
Dave Airlieffbbf7a2005-08-20 17:40:04 +10001765 buf->used = size;
1766 offset = dev_priv->gart_buffers_offset + buf->offset;
1767 BEGIN_RING(9);
1768 OUT_RING(CP_PACKET3(RADEON_CNTL_BITBLT_MULTI, 5));
1769 OUT_RING(RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
1770 RADEON_GMC_DST_PITCH_OFFSET_CNTL |
1771 RADEON_GMC_BRUSH_NONE |
1772 (format << 8) |
1773 RADEON_GMC_SRC_DATATYPE_COLOR |
1774 RADEON_ROP3_S |
1775 RADEON_DP_SRC_SOURCE_MEMORY |
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001776 RADEON_GMC_CLR_CMP_CNTL_DIS | RADEON_GMC_WR_MSK_DIS);
Dave Airlieffbbf7a2005-08-20 17:40:04 +10001777 OUT_RING((spitch << 22) | (offset >> 10));
1778 OUT_RING((texpitch << 22) | (tex->offset >> 10));
1779 OUT_RING(0);
1780 OUT_RING((image->x << 16) | image->y);
1781 OUT_RING((image->width << 16) | height);
1782 RADEON_WAIT_UNTIL_2D_IDLE();
1783 ADVANCE_RING();
1784
1785 radeon_cp_discard_buffer(dev, buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001786
1787 /* Update the input parameters for next time */
1788 image->y += height;
1789 image->height -= height;
1790 image->data = (const u8 __user *)image->data + size;
1791 } while (image->height > 0);
1792
1793 /* Flush the pixel cache after the blit completes. This ensures
1794 * the texture data is written out to memory before rendering
1795 * continues.
1796 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001797 BEGIN_RING(4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001798 RADEON_FLUSH_CACHE();
1799 RADEON_WAIT_UNTIL_2D_IDLE();
1800 ADVANCE_RING();
1801 return 0;
1802}
1803
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001804static void radeon_cp_dispatch_stipple(drm_device_t * dev, u32 * stipple)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805{
1806 drm_radeon_private_t *dev_priv = dev->dev_private;
1807 int i;
1808 RING_LOCALS;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001809 DRM_DEBUG("\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001810
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001811 BEGIN_RING(35);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001813 OUT_RING(CP_PACKET0(RADEON_RE_STIPPLE_ADDR, 0));
1814 OUT_RING(0x00000000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001815
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001816 OUT_RING(CP_PACKET0_TABLE(RADEON_RE_STIPPLE_DATA, 31));
1817 for (i = 0; i < 32; i++) {
1818 OUT_RING(stipple[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001819 }
1820
1821 ADVANCE_RING();
1822}
1823
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001824static void radeon_apply_surface_regs(int surf_index,
1825 drm_radeon_private_t * dev_priv)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001826{
1827 if (!dev_priv->mmio)
1828 return;
1829
1830 radeon_do_cp_idle(dev_priv);
1831
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001832 RADEON_WRITE(RADEON_SURFACE0_INFO + 16 * surf_index,
1833 dev_priv->surfaces[surf_index].flags);
1834 RADEON_WRITE(RADEON_SURFACE0_LOWER_BOUND + 16 * surf_index,
1835 dev_priv->surfaces[surf_index].lower);
1836 RADEON_WRITE(RADEON_SURFACE0_UPPER_BOUND + 16 * surf_index,
1837 dev_priv->surfaces[surf_index].upper);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001838}
1839
Linus Torvalds1da177e2005-04-16 15:20:36 -07001840/* Allocates a virtual surface
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001841 * doesn't always allocate a real surface, will stretch an existing
Linus Torvalds1da177e2005-04-16 15:20:36 -07001842 * surface when possible.
1843 *
1844 * Note that refcount can be at most 2, since during a free refcount=3
1845 * might mean we have to allocate a new surface which might not always
1846 * be available.
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001847 * For example : we allocate three contigous surfaces ABC. If B is
Linus Torvalds1da177e2005-04-16 15:20:36 -07001848 * freed, we suddenly need two surfaces to store A and C, which might
1849 * not always be available.
1850 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001851static int alloc_surface(drm_radeon_surface_alloc_t * new,
1852 drm_radeon_private_t * dev_priv, DRMFILE filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001853{
1854 struct radeon_virt_surface *s;
1855 int i;
1856 int virt_surface_index;
1857 uint32_t new_upper, new_lower;
1858
1859 new_lower = new->address;
1860 new_upper = new_lower + new->size - 1;
1861
1862 /* sanity check */
1863 if ((new_lower >= new_upper) || (new->flags == 0) || (new->size == 0) ||
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001864 ((new_upper & RADEON_SURF_ADDRESS_FIXED_MASK) !=
1865 RADEON_SURF_ADDRESS_FIXED_MASK)
1866 || ((new_lower & RADEON_SURF_ADDRESS_FIXED_MASK) != 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001867 return -1;
1868
1869 /* make sure there is no overlap with existing surfaces */
1870 for (i = 0; i < RADEON_MAX_SURFACES; i++) {
1871 if ((dev_priv->surfaces[i].refcount != 0) &&
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001872 (((new_lower >= dev_priv->surfaces[i].lower) &&
1873 (new_lower < dev_priv->surfaces[i].upper)) ||
1874 ((new_lower < dev_priv->surfaces[i].lower) &&
1875 (new_upper > dev_priv->surfaces[i].lower)))) {
1876 return -1;
1877 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001878 }
1879
1880 /* find a virtual surface */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001881 for (i = 0; i < 2 * RADEON_MAX_SURFACES; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001882 if (dev_priv->virt_surfaces[i].filp == 0)
1883 break;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001884 if (i == 2 * RADEON_MAX_SURFACES) {
1885 return -1;
1886 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001887 virt_surface_index = i;
1888
1889 /* try to reuse an existing surface */
1890 for (i = 0; i < RADEON_MAX_SURFACES; i++) {
1891 /* extend before */
1892 if ((dev_priv->surfaces[i].refcount == 1) &&
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001893 (new->flags == dev_priv->surfaces[i].flags) &&
1894 (new_upper + 1 == dev_priv->surfaces[i].lower)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001895 s = &(dev_priv->virt_surfaces[virt_surface_index]);
1896 s->surface_index = i;
1897 s->lower = new_lower;
1898 s->upper = new_upper;
1899 s->flags = new->flags;
1900 s->filp = filp;
1901 dev_priv->surfaces[i].refcount++;
1902 dev_priv->surfaces[i].lower = s->lower;
1903 radeon_apply_surface_regs(s->surface_index, dev_priv);
1904 return virt_surface_index;
1905 }
1906
1907 /* extend after */
1908 if ((dev_priv->surfaces[i].refcount == 1) &&
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001909 (new->flags == dev_priv->surfaces[i].flags) &&
1910 (new_lower == dev_priv->surfaces[i].upper + 1)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001911 s = &(dev_priv->virt_surfaces[virt_surface_index]);
1912 s->surface_index = i;
1913 s->lower = new_lower;
1914 s->upper = new_upper;
1915 s->flags = new->flags;
1916 s->filp = filp;
1917 dev_priv->surfaces[i].refcount++;
1918 dev_priv->surfaces[i].upper = s->upper;
1919 radeon_apply_surface_regs(s->surface_index, dev_priv);
1920 return virt_surface_index;
1921 }
1922 }
1923
1924 /* okay, we need a new one */
1925 for (i = 0; i < RADEON_MAX_SURFACES; i++) {
1926 if (dev_priv->surfaces[i].refcount == 0) {
1927 s = &(dev_priv->virt_surfaces[virt_surface_index]);
1928 s->surface_index = i;
1929 s->lower = new_lower;
1930 s->upper = new_upper;
1931 s->flags = new->flags;
1932 s->filp = filp;
1933 dev_priv->surfaces[i].refcount = 1;
1934 dev_priv->surfaces[i].lower = s->lower;
1935 dev_priv->surfaces[i].upper = s->upper;
1936 dev_priv->surfaces[i].flags = s->flags;
1937 radeon_apply_surface_regs(s->surface_index, dev_priv);
1938 return virt_surface_index;
1939 }
1940 }
1941
1942 /* we didn't find anything */
1943 return -1;
1944}
1945
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001946static int free_surface(DRMFILE filp, drm_radeon_private_t * dev_priv,
1947 int lower)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001948{
1949 struct radeon_virt_surface *s;
1950 int i;
1951 /* find the virtual surface */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001952 for (i = 0; i < 2 * RADEON_MAX_SURFACES; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001953 s = &(dev_priv->virt_surfaces[i]);
1954 if (s->filp) {
1955 if ((lower == s->lower) && (filp == s->filp)) {
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001956 if (dev_priv->surfaces[s->surface_index].
1957 lower == s->lower)
1958 dev_priv->surfaces[s->surface_index].
1959 lower = s->upper;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001960
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001961 if (dev_priv->surfaces[s->surface_index].
1962 upper == s->upper)
1963 dev_priv->surfaces[s->surface_index].
1964 upper = s->lower;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001965
1966 dev_priv->surfaces[s->surface_index].refcount--;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001967 if (dev_priv->surfaces[s->surface_index].
1968 refcount == 0)
1969 dev_priv->surfaces[s->surface_index].
1970 flags = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001971 s->filp = NULL;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001972 radeon_apply_surface_regs(s->surface_index,
1973 dev_priv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001974 return 0;
1975 }
1976 }
1977 }
1978 return 1;
1979}
1980
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001981static void radeon_surfaces_release(DRMFILE filp,
1982 drm_radeon_private_t * dev_priv)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001983{
1984 int i;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001985 for (i = 0; i < 2 * RADEON_MAX_SURFACES; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001986 if (dev_priv->virt_surfaces[i].filp == filp)
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001987 free_surface(filp, dev_priv,
1988 dev_priv->virt_surfaces[i].lower);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001989 }
1990}
1991
1992/* ================================================================
1993 * IOCTL functions
1994 */
1995static int radeon_surface_alloc(DRM_IOCTL_ARGS)
1996{
1997 DRM_DEVICE;
1998 drm_radeon_private_t *dev_priv = dev->dev_private;
1999 drm_radeon_surface_alloc_t alloc;
2000
2001 if (!dev_priv) {
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002002 DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002003 return DRM_ERR(EINVAL);
2004 }
2005
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002006 DRM_COPY_FROM_USER_IOCTL(alloc,
2007 (drm_radeon_surface_alloc_t __user *) data,
2008 sizeof(alloc));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002009
2010 if (alloc_surface(&alloc, dev_priv, filp) == -1)
2011 return DRM_ERR(EINVAL);
2012 else
2013 return 0;
2014}
2015
2016static int radeon_surface_free(DRM_IOCTL_ARGS)
2017{
2018 DRM_DEVICE;
2019 drm_radeon_private_t *dev_priv = dev->dev_private;
2020 drm_radeon_surface_free_t memfree;
2021
2022 if (!dev_priv) {
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002023 DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002024 return DRM_ERR(EINVAL);
2025 }
2026
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002027 DRM_COPY_FROM_USER_IOCTL(memfree, (drm_radeon_mem_free_t __user *) data,
2028 sizeof(memfree));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002029
2030 if (free_surface(filp, dev_priv, memfree.address))
2031 return DRM_ERR(EINVAL);
2032 else
2033 return 0;
2034}
2035
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002036static int radeon_cp_clear(DRM_IOCTL_ARGS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002037{
2038 DRM_DEVICE;
2039 drm_radeon_private_t *dev_priv = dev->dev_private;
2040 drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
2041 drm_radeon_clear_t clear;
2042 drm_radeon_clear_rect_t depth_boxes[RADEON_NR_SAREA_CLIPRECTS];
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002043 DRM_DEBUG("\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002044
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002045 LOCK_TEST_WITH_RETURN(dev, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002046
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002047 DRM_COPY_FROM_USER_IOCTL(clear, (drm_radeon_clear_t __user *) data,
2048 sizeof(clear));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002049
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002050 RING_SPACE_TEST_WITH_RETURN(dev_priv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002051
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002052 if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053 sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
2054
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002055 if (DRM_COPY_FROM_USER(&depth_boxes, clear.depth_boxes,
2056 sarea_priv->nbox * sizeof(depth_boxes[0])))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002057 return DRM_ERR(EFAULT);
2058
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002059 radeon_cp_dispatch_clear(dev, &clear, depth_boxes);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002060
2061 COMMIT_RING();
2062 return 0;
2063}
2064
Linus Torvalds1da177e2005-04-16 15:20:36 -07002065/* Not sure why this isn't set all the time:
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002066 */
2067static int radeon_do_init_pageflip(drm_device_t * dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002068{
2069 drm_radeon_private_t *dev_priv = dev->dev_private;
2070 RING_LOCALS;
2071
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002072 DRM_DEBUG("\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002073
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002074 BEGIN_RING(6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002075 RADEON_WAIT_UNTIL_3D_IDLE();
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002076 OUT_RING(CP_PACKET0(RADEON_CRTC_OFFSET_CNTL, 0));
2077 OUT_RING(RADEON_READ(RADEON_CRTC_OFFSET_CNTL) |
2078 RADEON_CRTC_OFFSET_FLIP_CNTL);
2079 OUT_RING(CP_PACKET0(RADEON_CRTC2_OFFSET_CNTL, 0));
2080 OUT_RING(RADEON_READ(RADEON_CRTC2_OFFSET_CNTL) |
2081 RADEON_CRTC_OFFSET_FLIP_CNTL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002082 ADVANCE_RING();
2083
2084 dev_priv->page_flipping = 1;
2085 dev_priv->current_page = 0;
2086 dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page;
2087
2088 return 0;
2089}
2090
2091/* Called whenever a client dies, from drm_release.
2092 * NOTE: Lock isn't necessarily held when this is called!
2093 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002094static int radeon_do_cleanup_pageflip(drm_device_t * dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002095{
2096 drm_radeon_private_t *dev_priv = dev->dev_private;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002097 DRM_DEBUG("\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002098
2099 if (dev_priv->current_page != 0)
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002100 radeon_cp_dispatch_flip(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002101
2102 dev_priv->page_flipping = 0;
2103 return 0;
2104}
2105
2106/* Swapping and flipping are different operations, need different ioctls.
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002107 * They can & should be intermixed to support multiple 3d windows.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002108 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002109static int radeon_cp_flip(DRM_IOCTL_ARGS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002110{
2111 DRM_DEVICE;
2112 drm_radeon_private_t *dev_priv = dev->dev_private;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002113 DRM_DEBUG("\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002114
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002115 LOCK_TEST_WITH_RETURN(dev, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002116
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002117 RING_SPACE_TEST_WITH_RETURN(dev_priv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002118
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002119 if (!dev_priv->page_flipping)
2120 radeon_do_init_pageflip(dev);
2121
2122 radeon_cp_dispatch_flip(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002123
2124 COMMIT_RING();
2125 return 0;
2126}
2127
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002128static int radeon_cp_swap(DRM_IOCTL_ARGS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002129{
2130 DRM_DEVICE;
2131 drm_radeon_private_t *dev_priv = dev->dev_private;
2132 drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002133 DRM_DEBUG("\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002134
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002135 LOCK_TEST_WITH_RETURN(dev, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002136
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002137 RING_SPACE_TEST_WITH_RETURN(dev_priv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002138
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002139 if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002140 sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
2141
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002142 radeon_cp_dispatch_swap(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002143 dev_priv->sarea_priv->ctx_owner = 0;
2144
2145 COMMIT_RING();
2146 return 0;
2147}
2148
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002149static int radeon_cp_vertex(DRM_IOCTL_ARGS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002150{
2151 DRM_DEVICE;
2152 drm_radeon_private_t *dev_priv = dev->dev_private;
2153 drm_file_t *filp_priv;
2154 drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
2155 drm_device_dma_t *dma = dev->dma;
2156 drm_buf_t *buf;
2157 drm_radeon_vertex_t vertex;
2158 drm_radeon_tcl_prim_t prim;
2159
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002160 LOCK_TEST_WITH_RETURN(dev, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002161
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002162 DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002163
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002164 DRM_COPY_FROM_USER_IOCTL(vertex, (drm_radeon_vertex_t __user *) data,
2165 sizeof(vertex));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002167 DRM_DEBUG("pid=%d index=%d count=%d discard=%d\n",
2168 DRM_CURRENTPID, vertex.idx, vertex.count, vertex.discard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002169
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002170 if (vertex.idx < 0 || vertex.idx >= dma->buf_count) {
2171 DRM_ERROR("buffer index %d (of %d max)\n",
2172 vertex.idx, dma->buf_count - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002173 return DRM_ERR(EINVAL);
2174 }
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002175 if (vertex.prim < 0 || vertex.prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST) {
2176 DRM_ERROR("buffer prim %d\n", vertex.prim);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002177 return DRM_ERR(EINVAL);
2178 }
2179
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002180 RING_SPACE_TEST_WITH_RETURN(dev_priv);
2181 VB_AGE_TEST_WITH_RETURN(dev_priv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002182
2183 buf = dma->buflist[vertex.idx];
2184
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002185 if (buf->filp != filp) {
2186 DRM_ERROR("process %d using buffer owned by %p\n",
2187 DRM_CURRENTPID, buf->filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188 return DRM_ERR(EINVAL);
2189 }
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002190 if (buf->pending) {
2191 DRM_ERROR("sending pending buffer %d\n", vertex.idx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002192 return DRM_ERR(EINVAL);
2193 }
2194
2195 /* Build up a prim_t record:
2196 */
2197 if (vertex.count) {
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002198 buf->used = vertex.count; /* not used? */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002199
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002200 if (sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS) {
2201 if (radeon_emit_state(dev_priv, filp_priv,
2202 &sarea_priv->context_state,
2203 sarea_priv->tex_state,
2204 sarea_priv->dirty)) {
2205 DRM_ERROR("radeon_emit_state failed\n");
2206 return DRM_ERR(EINVAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002207 }
2208
2209 sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES |
2210 RADEON_UPLOAD_TEX1IMAGES |
2211 RADEON_UPLOAD_TEX2IMAGES |
2212 RADEON_REQUIRE_QUIESCENCE);
2213 }
2214
2215 prim.start = 0;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002216 prim.finish = vertex.count; /* unused */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002217 prim.prim = vertex.prim;
2218 prim.numverts = vertex.count;
2219 prim.vc_format = dev_priv->sarea_priv->vc_format;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002220
2221 radeon_cp_dispatch_vertex(dev, buf, &prim);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002222 }
2223
2224 if (vertex.discard) {
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002225 radeon_cp_discard_buffer(dev, buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002226 }
2227
2228 COMMIT_RING();
2229 return 0;
2230}
2231
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002232static int radeon_cp_indices(DRM_IOCTL_ARGS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002233{
2234 DRM_DEVICE;
2235 drm_radeon_private_t *dev_priv = dev->dev_private;
2236 drm_file_t *filp_priv;
2237 drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
2238 drm_device_dma_t *dma = dev->dma;
2239 drm_buf_t *buf;
2240 drm_radeon_indices_t elts;
2241 drm_radeon_tcl_prim_t prim;
2242 int count;
2243
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002244 LOCK_TEST_WITH_RETURN(dev, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002245
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002246 if (!dev_priv) {
2247 DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002248 return DRM_ERR(EINVAL);
2249 }
2250
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002251 DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002252
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002253 DRM_COPY_FROM_USER_IOCTL(elts, (drm_radeon_indices_t __user *) data,
2254 sizeof(elts));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002255
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002256 DRM_DEBUG("pid=%d index=%d start=%d end=%d discard=%d\n",
2257 DRM_CURRENTPID, elts.idx, elts.start, elts.end, elts.discard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002258
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002259 if (elts.idx < 0 || elts.idx >= dma->buf_count) {
2260 DRM_ERROR("buffer index %d (of %d max)\n",
2261 elts.idx, dma->buf_count - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002262 return DRM_ERR(EINVAL);
2263 }
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002264 if (elts.prim < 0 || elts.prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST) {
2265 DRM_ERROR("buffer prim %d\n", elts.prim);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002266 return DRM_ERR(EINVAL);
2267 }
2268
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002269 RING_SPACE_TEST_WITH_RETURN(dev_priv);
2270 VB_AGE_TEST_WITH_RETURN(dev_priv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002271
2272 buf = dma->buflist[elts.idx];
2273
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002274 if (buf->filp != filp) {
2275 DRM_ERROR("process %d using buffer owned by %p\n",
2276 DRM_CURRENTPID, buf->filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002277 return DRM_ERR(EINVAL);
2278 }
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002279 if (buf->pending) {
2280 DRM_ERROR("sending pending buffer %d\n", elts.idx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002281 return DRM_ERR(EINVAL);
2282 }
2283
2284 count = (elts.end - elts.start) / sizeof(u16);
2285 elts.start -= RADEON_INDEX_PRIM_OFFSET;
2286
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002287 if (elts.start & 0x7) {
2288 DRM_ERROR("misaligned buffer 0x%x\n", elts.start);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002289 return DRM_ERR(EINVAL);
2290 }
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002291 if (elts.start < buf->used) {
2292 DRM_ERROR("no header 0x%x - 0x%x\n", elts.start, buf->used);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002293 return DRM_ERR(EINVAL);
2294 }
2295
2296 buf->used = elts.end;
2297
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002298 if (sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS) {
2299 if (radeon_emit_state(dev_priv, filp_priv,
2300 &sarea_priv->context_state,
2301 sarea_priv->tex_state,
2302 sarea_priv->dirty)) {
2303 DRM_ERROR("radeon_emit_state failed\n");
2304 return DRM_ERR(EINVAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002305 }
2306
2307 sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES |
2308 RADEON_UPLOAD_TEX1IMAGES |
2309 RADEON_UPLOAD_TEX2IMAGES |
2310 RADEON_REQUIRE_QUIESCENCE);
2311 }
2312
Linus Torvalds1da177e2005-04-16 15:20:36 -07002313 /* Build up a prim_t record:
2314 */
2315 prim.start = elts.start;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002316 prim.finish = elts.end;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002317 prim.prim = elts.prim;
2318 prim.offset = 0; /* offset from start of dma buffers */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002319 prim.numverts = RADEON_MAX_VB_VERTS; /* duh */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002320 prim.vc_format = dev_priv->sarea_priv->vc_format;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002321
2322 radeon_cp_dispatch_indices(dev, buf, &prim);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002323 if (elts.discard) {
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002324 radeon_cp_discard_buffer(dev, buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002325 }
2326
2327 COMMIT_RING();
2328 return 0;
2329}
2330
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002331static int radeon_cp_texture(DRM_IOCTL_ARGS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002332{
2333 DRM_DEVICE;
2334 drm_radeon_private_t *dev_priv = dev->dev_private;
2335 drm_radeon_texture_t tex;
2336 drm_radeon_tex_image_t image;
2337 int ret;
2338
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002339 LOCK_TEST_WITH_RETURN(dev, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002340
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002341 DRM_COPY_FROM_USER_IOCTL(tex, (drm_radeon_texture_t __user *) data,
2342 sizeof(tex));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002343
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002344 if (tex.image == NULL) {
2345 DRM_ERROR("null texture image!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002346 return DRM_ERR(EINVAL);
2347 }
2348
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002349 if (DRM_COPY_FROM_USER(&image,
2350 (drm_radeon_tex_image_t __user *) tex.image,
2351 sizeof(image)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002352 return DRM_ERR(EFAULT);
2353
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002354 RING_SPACE_TEST_WITH_RETURN(dev_priv);
2355 VB_AGE_TEST_WITH_RETURN(dev_priv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002356
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002357 ret = radeon_cp_dispatch_texture(filp, dev, &tex, &image);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002358
2359 COMMIT_RING();
2360 return ret;
2361}
2362
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002363static int radeon_cp_stipple(DRM_IOCTL_ARGS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002364{
2365 DRM_DEVICE;
2366 drm_radeon_private_t *dev_priv = dev->dev_private;
2367 drm_radeon_stipple_t stipple;
2368 u32 mask[32];
2369
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002370 LOCK_TEST_WITH_RETURN(dev, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002371
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002372 DRM_COPY_FROM_USER_IOCTL(stipple, (drm_radeon_stipple_t __user *) data,
2373 sizeof(stipple));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002374
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002375 if (DRM_COPY_FROM_USER(&mask, stipple.mask, 32 * sizeof(u32)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002376 return DRM_ERR(EFAULT);
2377
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002378 RING_SPACE_TEST_WITH_RETURN(dev_priv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002379
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002380 radeon_cp_dispatch_stipple(dev, mask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002381
2382 COMMIT_RING();
2383 return 0;
2384}
2385
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002386static int radeon_cp_indirect(DRM_IOCTL_ARGS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002387{
2388 DRM_DEVICE;
2389 drm_radeon_private_t *dev_priv = dev->dev_private;
2390 drm_device_dma_t *dma = dev->dma;
2391 drm_buf_t *buf;
2392 drm_radeon_indirect_t indirect;
2393 RING_LOCALS;
2394
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002395 LOCK_TEST_WITH_RETURN(dev, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002396
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002397 if (!dev_priv) {
2398 DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002399 return DRM_ERR(EINVAL);
2400 }
2401
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002402 DRM_COPY_FROM_USER_IOCTL(indirect,
2403 (drm_radeon_indirect_t __user *) data,
2404 sizeof(indirect));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002405
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002406 DRM_DEBUG("indirect: idx=%d s=%d e=%d d=%d\n",
2407 indirect.idx, indirect.start, indirect.end, indirect.discard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002408
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002409 if (indirect.idx < 0 || indirect.idx >= dma->buf_count) {
2410 DRM_ERROR("buffer index %d (of %d max)\n",
2411 indirect.idx, dma->buf_count - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002412 return DRM_ERR(EINVAL);
2413 }
2414
2415 buf = dma->buflist[indirect.idx];
2416
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002417 if (buf->filp != filp) {
2418 DRM_ERROR("process %d using buffer owned by %p\n",
2419 DRM_CURRENTPID, buf->filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002420 return DRM_ERR(EINVAL);
2421 }
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002422 if (buf->pending) {
2423 DRM_ERROR("sending pending buffer %d\n", indirect.idx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002424 return DRM_ERR(EINVAL);
2425 }
2426
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002427 if (indirect.start < buf->used) {
2428 DRM_ERROR("reusing indirect: start=0x%x actual=0x%x\n",
2429 indirect.start, buf->used);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002430 return DRM_ERR(EINVAL);
2431 }
2432
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002433 RING_SPACE_TEST_WITH_RETURN(dev_priv);
2434 VB_AGE_TEST_WITH_RETURN(dev_priv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002435
2436 buf->used = indirect.end;
2437
2438 /* Wait for the 3D stream to idle before the indirect buffer
2439 * containing 2D acceleration commands is processed.
2440 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002441 BEGIN_RING(2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002442
2443 RADEON_WAIT_UNTIL_3D_IDLE();
2444
2445 ADVANCE_RING();
2446
2447 /* Dispatch the indirect buffer full of commands from the
2448 * X server. This is insecure and is thus only available to
2449 * privileged clients.
2450 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002451 radeon_cp_dispatch_indirect(dev, buf, indirect.start, indirect.end);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002452 if (indirect.discard) {
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002453 radeon_cp_discard_buffer(dev, buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002454 }
2455
Linus Torvalds1da177e2005-04-16 15:20:36 -07002456 COMMIT_RING();
2457 return 0;
2458}
2459
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002460static int radeon_cp_vertex2(DRM_IOCTL_ARGS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002461{
2462 DRM_DEVICE;
2463 drm_radeon_private_t *dev_priv = dev->dev_private;
2464 drm_file_t *filp_priv;
2465 drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
2466 drm_device_dma_t *dma = dev->dma;
2467 drm_buf_t *buf;
2468 drm_radeon_vertex2_t vertex;
2469 int i;
2470 unsigned char laststate;
2471
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002472 LOCK_TEST_WITH_RETURN(dev, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002473
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002474 if (!dev_priv) {
2475 DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002476 return DRM_ERR(EINVAL);
2477 }
2478
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002479 DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002480
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002481 DRM_COPY_FROM_USER_IOCTL(vertex, (drm_radeon_vertex2_t __user *) data,
2482 sizeof(vertex));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002483
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002484 DRM_DEBUG("pid=%d index=%d discard=%d\n",
2485 DRM_CURRENTPID, vertex.idx, vertex.discard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002486
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002487 if (vertex.idx < 0 || vertex.idx >= dma->buf_count) {
2488 DRM_ERROR("buffer index %d (of %d max)\n",
2489 vertex.idx, dma->buf_count - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002490 return DRM_ERR(EINVAL);
2491 }
2492
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002493 RING_SPACE_TEST_WITH_RETURN(dev_priv);
2494 VB_AGE_TEST_WITH_RETURN(dev_priv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002495
2496 buf = dma->buflist[vertex.idx];
2497
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002498 if (buf->filp != filp) {
2499 DRM_ERROR("process %d using buffer owned by %p\n",
2500 DRM_CURRENTPID, buf->filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002501 return DRM_ERR(EINVAL);
2502 }
2503
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002504 if (buf->pending) {
2505 DRM_ERROR("sending pending buffer %d\n", vertex.idx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002506 return DRM_ERR(EINVAL);
2507 }
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002508
Linus Torvalds1da177e2005-04-16 15:20:36 -07002509 if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS)
2510 return DRM_ERR(EINVAL);
2511
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002512 for (laststate = 0xff, i = 0; i < vertex.nr_prims; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002513 drm_radeon_prim_t prim;
2514 drm_radeon_tcl_prim_t tclprim;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002515
2516 if (DRM_COPY_FROM_USER(&prim, &vertex.prim[i], sizeof(prim)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002517 return DRM_ERR(EFAULT);
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002518
2519 if (prim.stateidx != laststate) {
2520 drm_radeon_state_t state;
2521
2522 if (DRM_COPY_FROM_USER(&state,
2523 &vertex.state[prim.stateidx],
2524 sizeof(state)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002525 return DRM_ERR(EFAULT);
2526
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002527 if (radeon_emit_state2(dev_priv, filp_priv, &state)) {
2528 DRM_ERROR("radeon_emit_state2 failed\n");
2529 return DRM_ERR(EINVAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002530 }
2531
2532 laststate = prim.stateidx;
2533 }
2534
2535 tclprim.start = prim.start;
2536 tclprim.finish = prim.finish;
2537 tclprim.prim = prim.prim;
2538 tclprim.vc_format = prim.vc_format;
2539
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002540 if (prim.prim & RADEON_PRIM_WALK_IND) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002541 tclprim.offset = prim.numverts * 64;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002542 tclprim.numverts = RADEON_MAX_VB_VERTS; /* duh */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002543
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002544 radeon_cp_dispatch_indices(dev, buf, &tclprim);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002545 } else {
2546 tclprim.numverts = prim.numverts;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002547 tclprim.offset = 0; /* not used */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002548
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002549 radeon_cp_dispatch_vertex(dev, buf, &tclprim);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002550 }
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002551
Linus Torvalds1da177e2005-04-16 15:20:36 -07002552 if (sarea_priv->nbox == 1)
2553 sarea_priv->nbox = 0;
2554 }
2555
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002556 if (vertex.discard) {
2557 radeon_cp_discard_buffer(dev, buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002558 }
2559
2560 COMMIT_RING();
2561 return 0;
2562}
2563
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002564static int radeon_emit_packets(drm_radeon_private_t * dev_priv,
2565 drm_file_t * filp_priv,
2566 drm_radeon_cmd_header_t header,
2567 drm_radeon_cmd_buffer_t * cmdbuf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002568{
2569 int id = (int)header.packet.packet_id;
2570 int sz, reg;
2571 int *data = (int *)cmdbuf->buf;
2572 RING_LOCALS;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002573
Linus Torvalds1da177e2005-04-16 15:20:36 -07002574 if (id >= RADEON_MAX_STATE_PACKETS)
2575 return DRM_ERR(EINVAL);
2576
2577 sz = packet[id].len;
2578 reg = packet[id].start;
2579
2580 if (sz * sizeof(int) > cmdbuf->bufsz) {
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002581 DRM_ERROR("Packet size provided larger than data provided\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002582 return DRM_ERR(EINVAL);
2583 }
2584
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002585 if (radeon_check_and_fixup_packets(dev_priv, filp_priv, id, data)) {
2586 DRM_ERROR("Packet verification failed\n");
2587 return DRM_ERR(EINVAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002588 }
2589
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002590 BEGIN_RING(sz + 1);
2591 OUT_RING(CP_PACKET0(reg, (sz - 1)));
2592 OUT_RING_TABLE(data, sz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002593 ADVANCE_RING();
2594
2595 cmdbuf->buf += sz * sizeof(int);
2596 cmdbuf->bufsz -= sz * sizeof(int);
2597 return 0;
2598}
2599
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002600static __inline__ int radeon_emit_scalars(drm_radeon_private_t * dev_priv,
2601 drm_radeon_cmd_header_t header,
2602 drm_radeon_cmd_buffer_t * cmdbuf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002603{
2604 int sz = header.scalars.count;
2605 int start = header.scalars.offset;
2606 int stride = header.scalars.stride;
2607 RING_LOCALS;
2608
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002609 BEGIN_RING(3 + sz);
2610 OUT_RING(CP_PACKET0(RADEON_SE_TCL_SCALAR_INDX_REG, 0));
2611 OUT_RING(start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT));
2612 OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_SCALAR_DATA_REG, sz - 1));
2613 OUT_RING_TABLE(cmdbuf->buf, sz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002614 ADVANCE_RING();
2615 cmdbuf->buf += sz * sizeof(int);
2616 cmdbuf->bufsz -= sz * sizeof(int);
2617 return 0;
2618}
2619
2620/* God this is ugly
2621 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002622static __inline__ int radeon_emit_scalars2(drm_radeon_private_t * dev_priv,
2623 drm_radeon_cmd_header_t header,
2624 drm_radeon_cmd_buffer_t * cmdbuf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002625{
2626 int sz = header.scalars.count;
2627 int start = ((unsigned int)header.scalars.offset) + 0x100;
2628 int stride = header.scalars.stride;
2629 RING_LOCALS;
2630
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002631 BEGIN_RING(3 + sz);
2632 OUT_RING(CP_PACKET0(RADEON_SE_TCL_SCALAR_INDX_REG, 0));
2633 OUT_RING(start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT));
2634 OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_SCALAR_DATA_REG, sz - 1));
2635 OUT_RING_TABLE(cmdbuf->buf, sz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002636 ADVANCE_RING();
2637 cmdbuf->buf += sz * sizeof(int);
2638 cmdbuf->bufsz -= sz * sizeof(int);
2639 return 0;
2640}
2641
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002642static __inline__ int radeon_emit_vectors(drm_radeon_private_t * dev_priv,
2643 drm_radeon_cmd_header_t header,
2644 drm_radeon_cmd_buffer_t * cmdbuf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002645{
2646 int sz = header.vectors.count;
2647 int start = header.vectors.offset;
2648 int stride = header.vectors.stride;
2649 RING_LOCALS;
2650
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002651 BEGIN_RING(3 + sz);
2652 OUT_RING(CP_PACKET0(RADEON_SE_TCL_VECTOR_INDX_REG, 0));
2653 OUT_RING(start | (stride << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT));
2654 OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1)));
2655 OUT_RING_TABLE(cmdbuf->buf, sz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002656 ADVANCE_RING();
2657
2658 cmdbuf->buf += sz * sizeof(int);
2659 cmdbuf->bufsz -= sz * sizeof(int);
2660 return 0;
2661}
2662
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002663static int radeon_emit_packet3(drm_device_t * dev,
2664 drm_file_t * filp_priv,
2665 drm_radeon_cmd_buffer_t * cmdbuf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002666{
2667 drm_radeon_private_t *dev_priv = dev->dev_private;
2668 unsigned int cmdsz;
2669 int ret;
2670 RING_LOCALS;
2671
2672 DRM_DEBUG("\n");
2673
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002674 if ((ret = radeon_check_and_fixup_packet3(dev_priv, filp_priv,
2675 cmdbuf, &cmdsz))) {
2676 DRM_ERROR("Packet verification failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002677 return ret;
2678 }
2679
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002680 BEGIN_RING(cmdsz);
2681 OUT_RING_TABLE(cmdbuf->buf, cmdsz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002682 ADVANCE_RING();
2683
2684 cmdbuf->buf += cmdsz * 4;
2685 cmdbuf->bufsz -= cmdsz * 4;
2686 return 0;
2687}
2688
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002689static int radeon_emit_packet3_cliprect(drm_device_t * dev,
2690 drm_file_t * filp_priv,
2691 drm_radeon_cmd_buffer_t * cmdbuf,
2692 int orig_nbox)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002693{
2694 drm_radeon_private_t *dev_priv = dev->dev_private;
2695 drm_clip_rect_t box;
2696 unsigned int cmdsz;
2697 int ret;
2698 drm_clip_rect_t __user *boxes = cmdbuf->boxes;
2699 int i = 0;
2700 RING_LOCALS;
2701
2702 DRM_DEBUG("\n");
2703
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002704 if ((ret = radeon_check_and_fixup_packet3(dev_priv, filp_priv,
2705 cmdbuf, &cmdsz))) {
2706 DRM_ERROR("Packet verification failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002707 return ret;
2708 }
2709
2710 if (!orig_nbox)
2711 goto out;
2712
2713 do {
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002714 if (i < cmdbuf->nbox) {
2715 if (DRM_COPY_FROM_USER(&box, &boxes[i], sizeof(box)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002716 return DRM_ERR(EFAULT);
2717 /* FIXME The second and subsequent times round
2718 * this loop, send a WAIT_UNTIL_3D_IDLE before
2719 * calling emit_clip_rect(). This fixes a
2720 * lockup on fast machines when sending
2721 * several cliprects with a cmdbuf, as when
2722 * waving a 2D window over a 3D
2723 * window. Something in the commands from user
2724 * space seems to hang the card when they're
2725 * sent several times in a row. That would be
2726 * the correct place to fix it but this works
2727 * around it until I can figure that out - Tim
2728 * Smith */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002729 if (i) {
2730 BEGIN_RING(2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002731 RADEON_WAIT_UNTIL_3D_IDLE();
2732 ADVANCE_RING();
2733 }
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002734 radeon_emit_clip_rect(dev_priv, &box);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002735 }
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002736
2737 BEGIN_RING(cmdsz);
2738 OUT_RING_TABLE(cmdbuf->buf, cmdsz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002739 ADVANCE_RING();
2740
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002741 } while (++i < cmdbuf->nbox);
2742 if (cmdbuf->nbox == 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002743 cmdbuf->nbox = 0;
2744
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002745 out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002746 cmdbuf->buf += cmdsz * 4;
2747 cmdbuf->bufsz -= cmdsz * 4;
2748 return 0;
2749}
2750
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002751static int radeon_emit_wait(drm_device_t * dev, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002752{
2753 drm_radeon_private_t *dev_priv = dev->dev_private;
2754 RING_LOCALS;
2755
2756 DRM_DEBUG("%s: %x\n", __FUNCTION__, flags);
2757 switch (flags) {
2758 case RADEON_WAIT_2D:
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002759 BEGIN_RING(2);
2760 RADEON_WAIT_UNTIL_2D_IDLE();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002761 ADVANCE_RING();
2762 break;
2763 case RADEON_WAIT_3D:
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002764 BEGIN_RING(2);
2765 RADEON_WAIT_UNTIL_3D_IDLE();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002766 ADVANCE_RING();
2767 break;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002768 case RADEON_WAIT_2D | RADEON_WAIT_3D:
2769 BEGIN_RING(2);
2770 RADEON_WAIT_UNTIL_IDLE();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002771 ADVANCE_RING();
2772 break;
2773 default:
2774 return DRM_ERR(EINVAL);
2775 }
2776
2777 return 0;
2778}
2779
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002780static int radeon_cp_cmdbuf(DRM_IOCTL_ARGS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002781{
2782 DRM_DEVICE;
2783 drm_radeon_private_t *dev_priv = dev->dev_private;
2784 drm_file_t *filp_priv;
2785 drm_device_dma_t *dma = dev->dma;
2786 drm_buf_t *buf = NULL;
2787 int idx;
2788 drm_radeon_cmd_buffer_t cmdbuf;
2789 drm_radeon_cmd_header_t header;
2790 int orig_nbox, orig_bufsz;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002791 char *kbuf = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002792
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002793 LOCK_TEST_WITH_RETURN(dev, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002794
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002795 if (!dev_priv) {
2796 DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002797 return DRM_ERR(EINVAL);
2798 }
2799
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002800 DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002801
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002802 DRM_COPY_FROM_USER_IOCTL(cmdbuf,
2803 (drm_radeon_cmd_buffer_t __user *) data,
2804 sizeof(cmdbuf));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002805
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002806 RING_SPACE_TEST_WITH_RETURN(dev_priv);
2807 VB_AGE_TEST_WITH_RETURN(dev_priv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002808
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002809 if (cmdbuf.bufsz > 64 * 1024 || cmdbuf.bufsz < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002810 return DRM_ERR(EINVAL);
2811 }
2812
2813 /* Allocate an in-kernel area and copy in the cmdbuf. Do this to avoid
2814 * races between checking values and using those values in other code,
2815 * and simply to avoid a lot of function calls to copy in data.
2816 */
2817 orig_bufsz = cmdbuf.bufsz;
2818 if (orig_bufsz != 0) {
2819 kbuf = drm_alloc(cmdbuf.bufsz, DRM_MEM_DRIVER);
2820 if (kbuf == NULL)
2821 return DRM_ERR(ENOMEM);
2822 if (DRM_COPY_FROM_USER(kbuf, cmdbuf.buf, cmdbuf.bufsz)) {
2823 drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
2824 return DRM_ERR(EFAULT);
2825 }
2826 cmdbuf.buf = kbuf;
2827 }
2828
2829 orig_nbox = cmdbuf.nbox;
2830
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002831 if (dev_priv->microcode_version == UCODE_R300) {
Dave Airlie414ed532005-08-16 20:43:16 +10002832 int temp;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002833 temp = r300_do_cp_cmdbuf(dev, filp, filp_priv, &cmdbuf);
2834
Dave Airlie414ed532005-08-16 20:43:16 +10002835 if (orig_bufsz != 0)
2836 drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002837
Dave Airlie414ed532005-08-16 20:43:16 +10002838 return temp;
2839 }
2840
2841 /* microcode_version != r300 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002842 while (cmdbuf.bufsz >= sizeof(header)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002843
2844 header.i = *(int *)cmdbuf.buf;
2845 cmdbuf.buf += sizeof(header);
2846 cmdbuf.bufsz -= sizeof(header);
2847
2848 switch (header.header.cmd_type) {
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002849 case RADEON_CMD_PACKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002850 DRM_DEBUG("RADEON_CMD_PACKET\n");
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002851 if (radeon_emit_packets
2852 (dev_priv, filp_priv, header, &cmdbuf)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002853 DRM_ERROR("radeon_emit_packets failed\n");
2854 goto err;
2855 }
2856 break;
2857
2858 case RADEON_CMD_SCALARS:
2859 DRM_DEBUG("RADEON_CMD_SCALARS\n");
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002860 if (radeon_emit_scalars(dev_priv, header, &cmdbuf)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002861 DRM_ERROR("radeon_emit_scalars failed\n");
2862 goto err;
2863 }
2864 break;
2865
2866 case RADEON_CMD_VECTORS:
2867 DRM_DEBUG("RADEON_CMD_VECTORS\n");
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002868 if (radeon_emit_vectors(dev_priv, header, &cmdbuf)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002869 DRM_ERROR("radeon_emit_vectors failed\n");
2870 goto err;
2871 }
2872 break;
2873
2874 case RADEON_CMD_DMA_DISCARD:
2875 DRM_DEBUG("RADEON_CMD_DMA_DISCARD\n");
2876 idx = header.dma.buf_idx;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002877 if (idx < 0 || idx >= dma->buf_count) {
2878 DRM_ERROR("buffer index %d (of %d max)\n",
2879 idx, dma->buf_count - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002880 goto err;
2881 }
2882
2883 buf = dma->buflist[idx];
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002884 if (buf->filp != filp || buf->pending) {
2885 DRM_ERROR("bad buffer %p %p %d\n",
2886 buf->filp, filp, buf->pending);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002887 goto err;
2888 }
2889
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002890 radeon_cp_discard_buffer(dev, buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002891 break;
2892
2893 case RADEON_CMD_PACKET3:
2894 DRM_DEBUG("RADEON_CMD_PACKET3\n");
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002895 if (radeon_emit_packet3(dev, filp_priv, &cmdbuf)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002896 DRM_ERROR("radeon_emit_packet3 failed\n");
2897 goto err;
2898 }
2899 break;
2900
2901 case RADEON_CMD_PACKET3_CLIP:
2902 DRM_DEBUG("RADEON_CMD_PACKET3_CLIP\n");
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002903 if (radeon_emit_packet3_cliprect
2904 (dev, filp_priv, &cmdbuf, orig_nbox)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002905 DRM_ERROR("radeon_emit_packet3_clip failed\n");
2906 goto err;
2907 }
2908 break;
2909
2910 case RADEON_CMD_SCALARS2:
2911 DRM_DEBUG("RADEON_CMD_SCALARS2\n");
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002912 if (radeon_emit_scalars2(dev_priv, header, &cmdbuf)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002913 DRM_ERROR("radeon_emit_scalars2 failed\n");
2914 goto err;
2915 }
2916 break;
2917
2918 case RADEON_CMD_WAIT:
2919 DRM_DEBUG("RADEON_CMD_WAIT\n");
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002920 if (radeon_emit_wait(dev, header.wait.flags)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002921 DRM_ERROR("radeon_emit_wait failed\n");
2922 goto err;
2923 }
2924 break;
2925 default:
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002926 DRM_ERROR("bad cmd_type %d at %p\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002927 header.header.cmd_type,
2928 cmdbuf.buf - sizeof(header));
2929 goto err;
2930 }
2931 }
2932
2933 if (orig_bufsz != 0)
2934 drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
2935
2936 DRM_DEBUG("DONE\n");
2937 COMMIT_RING();
2938 return 0;
2939
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002940 err:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002941 if (orig_bufsz != 0)
2942 drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
2943 return DRM_ERR(EINVAL);
2944}
2945
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002946static int radeon_cp_getparam(DRM_IOCTL_ARGS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002947{
2948 DRM_DEVICE;
2949 drm_radeon_private_t *dev_priv = dev->dev_private;
2950 drm_radeon_getparam_t param;
2951 int value;
2952
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002953 if (!dev_priv) {
2954 DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002955 return DRM_ERR(EINVAL);
2956 }
2957
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002958 DRM_COPY_FROM_USER_IOCTL(param, (drm_radeon_getparam_t __user *) data,
2959 sizeof(param));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002960
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002961 DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002962
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002963 switch (param.param) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002964 case RADEON_PARAM_GART_BUFFER_OFFSET:
2965 value = dev_priv->gart_buffers_offset;
2966 break;
2967 case RADEON_PARAM_LAST_FRAME:
2968 dev_priv->stats.last_frame_reads++;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002969 value = GET_SCRATCH(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002970 break;
2971 case RADEON_PARAM_LAST_DISPATCH:
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002972 value = GET_SCRATCH(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002973 break;
2974 case RADEON_PARAM_LAST_CLEAR:
2975 dev_priv->stats.last_clear_reads++;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002976 value = GET_SCRATCH(2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002977 break;
2978 case RADEON_PARAM_IRQ_NR:
2979 value = dev->irq;
2980 break;
2981 case RADEON_PARAM_GART_BASE:
2982 value = dev_priv->gart_vm_start;
2983 break;
2984 case RADEON_PARAM_REGISTER_HANDLE:
2985 value = dev_priv->mmio_offset;
2986 break;
2987 case RADEON_PARAM_STATUS_HANDLE:
2988 value = dev_priv->ring_rptr_offset;
2989 break;
2990#if BITS_PER_LONG == 32
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002991 /*
2992 * This ioctl() doesn't work on 64-bit platforms because hw_lock is a
2993 * pointer which can't fit into an int-sized variable. According to
2994 * Michel Dänzer, the ioctl() is only used on embedded platforms, so
2995 * not supporting it shouldn't be a problem. If the same functionality
2996 * is needed on 64-bit platforms, a new ioctl() would have to be added,
2997 * so backwards-compatibility for the embedded platforms can be
2998 * maintained. --davidm 4-Feb-2004.
2999 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003000 case RADEON_PARAM_SAREA_HANDLE:
3001 /* The lock is the first dword in the sarea. */
3002 value = (long)dev->lock.hw_lock;
3003 break;
3004#endif
3005 case RADEON_PARAM_GART_TEX_HANDLE:
3006 value = dev_priv->gart_textures_offset;
3007 break;
3008 default:
3009 return DRM_ERR(EINVAL);
3010 }
3011
Dave Airlieb5e89ed2005-09-25 14:28:13 +10003012 if (DRM_COPY_TO_USER(param.value, &value, sizeof(int))) {
3013 DRM_ERROR("copy_to_user\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003014 return DRM_ERR(EFAULT);
3015 }
Dave Airlieb5e89ed2005-09-25 14:28:13 +10003016
Linus Torvalds1da177e2005-04-16 15:20:36 -07003017 return 0;
3018}
3019
Dave Airlieb5e89ed2005-09-25 14:28:13 +10003020static int radeon_cp_setparam(DRM_IOCTL_ARGS)
3021{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003022 DRM_DEVICE;
3023 drm_radeon_private_t *dev_priv = dev->dev_private;
3024 drm_file_t *filp_priv;
3025 drm_radeon_setparam_t sp;
3026 struct drm_radeon_driver_file_fields *radeon_priv;
3027
Dave Airlieb5e89ed2005-09-25 14:28:13 +10003028 if (!dev_priv) {
3029 DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
3030 return DRM_ERR(EINVAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003031 }
3032
Dave Airlieb5e89ed2005-09-25 14:28:13 +10003033 DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003034
Dave Airlieb5e89ed2005-09-25 14:28:13 +10003035 DRM_COPY_FROM_USER_IOCTL(sp, (drm_radeon_setparam_t __user *) data,
3036 sizeof(sp));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003037
Dave Airlieb5e89ed2005-09-25 14:28:13 +10003038 switch (sp.param) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003039 case RADEON_SETPARAM_FB_LOCATION:
3040 radeon_priv = filp_priv->driver_priv;
3041 radeon_priv->radeon_fb_delta = dev_priv->fb_location - sp.value;
3042 break;
3043 case RADEON_SETPARAM_SWITCH_TILING:
3044 if (sp.value == 0) {
Dave Airlieb5e89ed2005-09-25 14:28:13 +10003045 DRM_DEBUG("color tiling disabled\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003046 dev_priv->front_pitch_offset &= ~RADEON_DST_TILE_MACRO;
3047 dev_priv->back_pitch_offset &= ~RADEON_DST_TILE_MACRO;
3048 dev_priv->sarea_priv->tiling_enabled = 0;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10003049 } else if (sp.value == 1) {
3050 DRM_DEBUG("color tiling enabled\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003051 dev_priv->front_pitch_offset |= RADEON_DST_TILE_MACRO;
3052 dev_priv->back_pitch_offset |= RADEON_DST_TILE_MACRO;
3053 dev_priv->sarea_priv->tiling_enabled = 1;
3054 }
Dave Airlieb5e89ed2005-09-25 14:28:13 +10003055 break;
Dave Airlieea98a922005-09-11 20:28:11 +10003056 case RADEON_SETPARAM_PCIGART_LOCATION:
3057 dev_priv->pcigart_offset = sp.value;
3058 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003059 default:
Dave Airlieb5e89ed2005-09-25 14:28:13 +10003060 DRM_DEBUG("Invalid parameter %d\n", sp.param);
3061 return DRM_ERR(EINVAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003062 }
3063
3064 return 0;
3065}
3066
3067/* When a client dies:
3068 * - Check for and clean up flipped page state
3069 * - Free any alloced GART memory.
3070 *
3071 * DRM infrastructure takes care of reclaiming dma buffers.
3072 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10003073void radeon_driver_prerelease(drm_device_t * dev, DRMFILE filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003074{
Dave Airlieb5e89ed2005-09-25 14:28:13 +10003075 if (dev->dev_private) {
3076 drm_radeon_private_t *dev_priv = dev->dev_private;
3077 if (dev_priv->page_flipping) {
3078 radeon_do_cleanup_pageflip(dev);
3079 }
3080 radeon_mem_release(filp, dev_priv->gart_heap);
3081 radeon_mem_release(filp, dev_priv->fb_heap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003082 radeon_surfaces_release(filp, dev_priv);
Dave Airlieb5e89ed2005-09-25 14:28:13 +10003083 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003084}
3085
Dave Airlieb5e89ed2005-09-25 14:28:13 +10003086void radeon_driver_pretakedown(drm_device_t * dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003087{
3088 radeon_do_release(dev);
3089}
3090
Dave Airlieb5e89ed2005-09-25 14:28:13 +10003091int radeon_driver_open_helper(drm_device_t * dev, drm_file_t * filp_priv)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003092{
3093 drm_radeon_private_t *dev_priv = dev->dev_private;
3094 struct drm_radeon_driver_file_fields *radeon_priv;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10003095
3096 radeon_priv =
3097 (struct drm_radeon_driver_file_fields *)
3098 drm_alloc(sizeof(*radeon_priv), DRM_MEM_FILES);
3099
Linus Torvalds1da177e2005-04-16 15:20:36 -07003100 if (!radeon_priv)
3101 return -ENOMEM;
3102
3103 filp_priv->driver_priv = radeon_priv;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10003104 if (dev_priv)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003105 radeon_priv->radeon_fb_delta = dev_priv->fb_location;
3106 else
3107 radeon_priv->radeon_fb_delta = 0;
3108 return 0;
3109}
3110
Dave Airlieb5e89ed2005-09-25 14:28:13 +10003111void radeon_driver_free_filp_priv(drm_device_t * dev, drm_file_t * filp_priv)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003112{
Dave Airlieb5e89ed2005-09-25 14:28:13 +10003113 struct drm_radeon_driver_file_fields *radeon_priv =
3114 filp_priv->driver_priv;
3115
3116 drm_free(radeon_priv, sizeof(*radeon_priv), DRM_MEM_FILES);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003117}
3118
3119drm_ioctl_desc_t radeon_ioctls[] = {
Dave Airlieb5e89ed2005-09-25 14:28:13 +10003120 [DRM_IOCTL_NR(DRM_RADEON_CP_INIT)] = {radeon_cp_init, 1, 1}
3121 ,
3122 [DRM_IOCTL_NR(DRM_RADEON_CP_START)] = {radeon_cp_start, 1, 1}
3123 ,
3124 [DRM_IOCTL_NR(DRM_RADEON_CP_STOP)] = {radeon_cp_stop, 1, 1}
3125 ,
3126 [DRM_IOCTL_NR(DRM_RADEON_CP_RESET)] = {radeon_cp_reset, 1, 1}
3127 ,
3128 [DRM_IOCTL_NR(DRM_RADEON_CP_IDLE)] = {radeon_cp_idle, 1, 0}
3129 ,
3130 [DRM_IOCTL_NR(DRM_RADEON_CP_RESUME)] = {radeon_cp_resume, 1, 0}
3131 ,
3132 [DRM_IOCTL_NR(DRM_RADEON_RESET)] = {radeon_engine_reset, 1, 0}
3133 ,
3134 [DRM_IOCTL_NR(DRM_RADEON_FULLSCREEN)] = {radeon_fullscreen, 1, 0}
3135 ,
3136 [DRM_IOCTL_NR(DRM_RADEON_SWAP)] = {radeon_cp_swap, 1, 0}
3137 ,
3138 [DRM_IOCTL_NR(DRM_RADEON_CLEAR)] = {radeon_cp_clear, 1, 0}
3139 ,
3140 [DRM_IOCTL_NR(DRM_RADEON_VERTEX)] = {radeon_cp_vertex, 1, 0}
3141 ,
3142 [DRM_IOCTL_NR(DRM_RADEON_INDICES)] = {radeon_cp_indices, 1, 0}
3143 ,
3144 [DRM_IOCTL_NR(DRM_RADEON_TEXTURE)] = {radeon_cp_texture, 1, 0}
3145 ,
3146 [DRM_IOCTL_NR(DRM_RADEON_STIPPLE)] = {radeon_cp_stipple, 1, 0}
3147 ,
3148 [DRM_IOCTL_NR(DRM_RADEON_INDIRECT)] = {radeon_cp_indirect, 1, 1}
3149 ,
3150 [DRM_IOCTL_NR(DRM_RADEON_VERTEX2)] = {radeon_cp_vertex2, 1, 0}
3151 ,
3152 [DRM_IOCTL_NR(DRM_RADEON_CMDBUF)] = {radeon_cp_cmdbuf, 1, 0}
3153 ,
3154 [DRM_IOCTL_NR(DRM_RADEON_GETPARAM)] = {radeon_cp_getparam, 1, 0}
3155 ,
3156 [DRM_IOCTL_NR(DRM_RADEON_FLIP)] = {radeon_cp_flip, 1, 0}
3157 ,
3158 [DRM_IOCTL_NR(DRM_RADEON_ALLOC)] = {radeon_mem_alloc, 1, 0}
3159 ,
3160 [DRM_IOCTL_NR(DRM_RADEON_FREE)] = {radeon_mem_free, 1, 0}
3161 ,
3162 [DRM_IOCTL_NR(DRM_RADEON_INIT_HEAP)] = {radeon_mem_init_heap, 1, 1}
3163 ,
3164 [DRM_IOCTL_NR(DRM_RADEON_IRQ_EMIT)] = {radeon_irq_emit, 1, 0}
3165 ,
3166 [DRM_IOCTL_NR(DRM_RADEON_IRQ_WAIT)] = {radeon_irq_wait, 1, 0}
3167 ,
3168 [DRM_IOCTL_NR(DRM_RADEON_SETPARAM)] = {radeon_cp_setparam, 1, 0}
3169 ,
3170 [DRM_IOCTL_NR(DRM_RADEON_SURF_ALLOC)] = {radeon_surface_alloc, 1, 0}
3171 ,
3172 [DRM_IOCTL_NR(DRM_RADEON_SURF_FREE)] = {radeon_surface_free, 1, 0}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003173};
3174
3175int radeon_max_ioctl = DRM_ARRAY_SIZE(radeon_ioctls);