blob: 231ac1438c699c4a6323b108af1e8c9f160bb51c [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,
Dave Airlieb3a83632005-09-30 18:37:36 +100043 u32 *offset)
Dave Airlieb5e89ed2005-09-25 14:28:13 +100044{
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,
Dave Airlieb3a83632005-09-30 18:37:36 +100069 int id, u32 *data)
Dave Airlieb5e89ed2005-09-25 14:28:13 +100070{
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,
Dave Airlieb3a83632005-09-30 18:37:36 +1000243 drm_radeon_kcmd_buffer_t *cmdbuf,
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000244 unsigned int *cmdsz)
245{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246 u32 *cmd = (u32 *) cmdbuf->buf;
247
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000248 *cmdsz = 2 + ((cmd[0] & RADEON_CP_PACKET_COUNT_MASK) >> 16);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000250 if ((cmd[0] & 0xc0000000) != RADEON_CP_PACKET3) {
251 DRM_ERROR("Not a type 3 packet\n");
252 return DRM_ERR(EINVAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253 }
254
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000255 if (4 * *cmdsz > cmdbuf->bufsz) {
256 DRM_ERROR("Packet size larger than size of data provided\n");
257 return DRM_ERR(EINVAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258 }
259
260 /* Check client state and fix it up if necessary */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000261 if (cmd[0] & 0x8000) { /* MSB of opcode: next DWORD GUI_CNTL */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262 u32 offset;
263
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000264 if (cmd[1] & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL
265 | RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266 offset = cmd[2] << 10;
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000267 if (radeon_check_and_fixup_offset
268 (dev_priv, filp_priv, &offset)) {
269 DRM_ERROR("Invalid first packet offset\n");
270 return DRM_ERR(EINVAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271 }
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000272 cmd[2] = (cmd[2] & 0xffc00000) | offset >> 10;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273 }
274
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000275 if ((cmd[1] & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) &&
276 (cmd[1] & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277 offset = cmd[3] << 10;
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000278 if (radeon_check_and_fixup_offset
279 (dev_priv, filp_priv, &offset)) {
280 DRM_ERROR("Invalid second packet offset\n");
281 return DRM_ERR(EINVAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282 }
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000283 cmd[3] = (cmd[3] & 0xffc00000) | offset >> 10;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284 }
285 }
286
287 return 0;
288}
289
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290/* ================================================================
291 * CP hardware state programming functions
292 */
293
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000294static __inline__ void radeon_emit_clip_rect(drm_radeon_private_t * dev_priv,
295 drm_clip_rect_t * box)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296{
297 RING_LOCALS;
298
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000299 DRM_DEBUG(" box: x1=%d y1=%d x2=%d y2=%d\n",
300 box->x1, box->y1, box->x2, box->y2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000302 BEGIN_RING(4);
303 OUT_RING(CP_PACKET0(RADEON_RE_TOP_LEFT, 0));
304 OUT_RING((box->y1 << 16) | box->x1);
305 OUT_RING(CP_PACKET0(RADEON_RE_WIDTH_HEIGHT, 0));
306 OUT_RING(((box->y2 - 1) << 16) | (box->x2 - 1));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307 ADVANCE_RING();
308}
309
310/* Emit 1.1 state
311 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000312static int radeon_emit_state(drm_radeon_private_t * dev_priv,
313 drm_file_t * filp_priv,
314 drm_radeon_context_regs_t * ctx,
315 drm_radeon_texture_regs_t * tex,
316 unsigned int dirty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317{
318 RING_LOCALS;
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000319 DRM_DEBUG("dirty=0x%08x\n", dirty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000321 if (dirty & RADEON_UPLOAD_CONTEXT) {
322 if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
323 &ctx->rb3d_depthoffset)) {
324 DRM_ERROR("Invalid depth buffer offset\n");
325 return DRM_ERR(EINVAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326 }
327
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000328 if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
329 &ctx->rb3d_coloroffset)) {
330 DRM_ERROR("Invalid depth buffer offset\n");
331 return DRM_ERR(EINVAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332 }
333
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000334 BEGIN_RING(14);
335 OUT_RING(CP_PACKET0(RADEON_PP_MISC, 6));
336 OUT_RING(ctx->pp_misc);
337 OUT_RING(ctx->pp_fog_color);
338 OUT_RING(ctx->re_solid_color);
339 OUT_RING(ctx->rb3d_blendcntl);
340 OUT_RING(ctx->rb3d_depthoffset);
341 OUT_RING(ctx->rb3d_depthpitch);
342 OUT_RING(ctx->rb3d_zstencilcntl);
343 OUT_RING(CP_PACKET0(RADEON_PP_CNTL, 2));
344 OUT_RING(ctx->pp_cntl);
345 OUT_RING(ctx->rb3d_cntl);
346 OUT_RING(ctx->rb3d_coloroffset);
347 OUT_RING(CP_PACKET0(RADEON_RB3D_COLORPITCH, 0));
348 OUT_RING(ctx->rb3d_colorpitch);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349 ADVANCE_RING();
350 }
351
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000352 if (dirty & RADEON_UPLOAD_VERTFMT) {
353 BEGIN_RING(2);
354 OUT_RING(CP_PACKET0(RADEON_SE_COORD_FMT, 0));
355 OUT_RING(ctx->se_coord_fmt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356 ADVANCE_RING();
357 }
358
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000359 if (dirty & RADEON_UPLOAD_LINE) {
360 BEGIN_RING(5);
361 OUT_RING(CP_PACKET0(RADEON_RE_LINE_PATTERN, 1));
362 OUT_RING(ctx->re_line_pattern);
363 OUT_RING(ctx->re_line_state);
364 OUT_RING(CP_PACKET0(RADEON_SE_LINE_WIDTH, 0));
365 OUT_RING(ctx->se_line_width);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366 ADVANCE_RING();
367 }
368
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000369 if (dirty & RADEON_UPLOAD_BUMPMAP) {
370 BEGIN_RING(5);
371 OUT_RING(CP_PACKET0(RADEON_PP_LUM_MATRIX, 0));
372 OUT_RING(ctx->pp_lum_matrix);
373 OUT_RING(CP_PACKET0(RADEON_PP_ROT_MATRIX_0, 1));
374 OUT_RING(ctx->pp_rot_matrix_0);
375 OUT_RING(ctx->pp_rot_matrix_1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376 ADVANCE_RING();
377 }
378
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000379 if (dirty & RADEON_UPLOAD_MASKS) {
380 BEGIN_RING(4);
381 OUT_RING(CP_PACKET0(RADEON_RB3D_STENCILREFMASK, 2));
382 OUT_RING(ctx->rb3d_stencilrefmask);
383 OUT_RING(ctx->rb3d_ropcntl);
384 OUT_RING(ctx->rb3d_planemask);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385 ADVANCE_RING();
386 }
387
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000388 if (dirty & RADEON_UPLOAD_VIEWPORT) {
389 BEGIN_RING(7);
390 OUT_RING(CP_PACKET0(RADEON_SE_VPORT_XSCALE, 5));
391 OUT_RING(ctx->se_vport_xscale);
392 OUT_RING(ctx->se_vport_xoffset);
393 OUT_RING(ctx->se_vport_yscale);
394 OUT_RING(ctx->se_vport_yoffset);
395 OUT_RING(ctx->se_vport_zscale);
396 OUT_RING(ctx->se_vport_zoffset);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397 ADVANCE_RING();
398 }
399
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000400 if (dirty & RADEON_UPLOAD_SETUP) {
401 BEGIN_RING(4);
402 OUT_RING(CP_PACKET0(RADEON_SE_CNTL, 0));
403 OUT_RING(ctx->se_cntl);
404 OUT_RING(CP_PACKET0(RADEON_SE_CNTL_STATUS, 0));
405 OUT_RING(ctx->se_cntl_status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406 ADVANCE_RING();
407 }
408
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000409 if (dirty & RADEON_UPLOAD_MISC) {
410 BEGIN_RING(2);
411 OUT_RING(CP_PACKET0(RADEON_RE_MISC, 0));
412 OUT_RING(ctx->re_misc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 ADVANCE_RING();
414 }
415
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000416 if (dirty & RADEON_UPLOAD_TEX0) {
417 if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
418 &tex[0].pp_txoffset)) {
419 DRM_ERROR("Invalid texture offset for unit 0\n");
420 return DRM_ERR(EINVAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421 }
422
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000423 BEGIN_RING(9);
424 OUT_RING(CP_PACKET0(RADEON_PP_TXFILTER_0, 5));
425 OUT_RING(tex[0].pp_txfilter);
426 OUT_RING(tex[0].pp_txformat);
427 OUT_RING(tex[0].pp_txoffset);
428 OUT_RING(tex[0].pp_txcblend);
429 OUT_RING(tex[0].pp_txablend);
430 OUT_RING(tex[0].pp_tfactor);
431 OUT_RING(CP_PACKET0(RADEON_PP_BORDER_COLOR_0, 0));
432 OUT_RING(tex[0].pp_border_color);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433 ADVANCE_RING();
434 }
435
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000436 if (dirty & RADEON_UPLOAD_TEX1) {
437 if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
438 &tex[1].pp_txoffset)) {
439 DRM_ERROR("Invalid texture offset for unit 1\n");
440 return DRM_ERR(EINVAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441 }
442
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000443 BEGIN_RING(9);
444 OUT_RING(CP_PACKET0(RADEON_PP_TXFILTER_1, 5));
445 OUT_RING(tex[1].pp_txfilter);
446 OUT_RING(tex[1].pp_txformat);
447 OUT_RING(tex[1].pp_txoffset);
448 OUT_RING(tex[1].pp_txcblend);
449 OUT_RING(tex[1].pp_txablend);
450 OUT_RING(tex[1].pp_tfactor);
451 OUT_RING(CP_PACKET0(RADEON_PP_BORDER_COLOR_1, 0));
452 OUT_RING(tex[1].pp_border_color);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453 ADVANCE_RING();
454 }
455
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000456 if (dirty & RADEON_UPLOAD_TEX2) {
457 if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
458 &tex[2].pp_txoffset)) {
459 DRM_ERROR("Invalid texture offset for unit 2\n");
460 return DRM_ERR(EINVAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461 }
462
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000463 BEGIN_RING(9);
464 OUT_RING(CP_PACKET0(RADEON_PP_TXFILTER_2, 5));
465 OUT_RING(tex[2].pp_txfilter);
466 OUT_RING(tex[2].pp_txformat);
467 OUT_RING(tex[2].pp_txoffset);
468 OUT_RING(tex[2].pp_txcblend);
469 OUT_RING(tex[2].pp_txablend);
470 OUT_RING(tex[2].pp_tfactor);
471 OUT_RING(CP_PACKET0(RADEON_PP_BORDER_COLOR_2, 0));
472 OUT_RING(tex[2].pp_border_color);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473 ADVANCE_RING();
474 }
475
476 return 0;
477}
478
479/* Emit 1.2 state
480 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000481static int radeon_emit_state2(drm_radeon_private_t * dev_priv,
482 drm_file_t * filp_priv,
483 drm_radeon_state_t * state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484{
485 RING_LOCALS;
486
487 if (state->dirty & RADEON_UPLOAD_ZBIAS) {
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000488 BEGIN_RING(3);
489 OUT_RING(CP_PACKET0(RADEON_SE_ZBIAS_FACTOR, 1));
490 OUT_RING(state->context2.se_zbias_factor);
491 OUT_RING(state->context2.se_zbias_constant);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492 ADVANCE_RING();
493 }
494
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000495 return radeon_emit_state(dev_priv, filp_priv, &state->context,
496 state->tex, state->dirty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497}
498
499/* New (1.3) state mechanism. 3 commands (packet, scalar, vector) in
500 * 1.3 cmdbuffers allow all previous state to be updated as well as
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000501 * the tcl scalar and vector areas.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000503static struct {
504 int start;
505 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506 const char *name;
507} packet[RADEON_MAX_STATE_PACKETS] = {
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000508 {RADEON_PP_MISC, 7, "RADEON_PP_MISC"},
509 {RADEON_PP_CNTL, 3, "RADEON_PP_CNTL"},
510 {RADEON_RB3D_COLORPITCH, 1, "RADEON_RB3D_COLORPITCH"},
511 {RADEON_RE_LINE_PATTERN, 2, "RADEON_RE_LINE_PATTERN"},
512 {RADEON_SE_LINE_WIDTH, 1, "RADEON_SE_LINE_WIDTH"},
513 {RADEON_PP_LUM_MATRIX, 1, "RADEON_PP_LUM_MATRIX"},
514 {RADEON_PP_ROT_MATRIX_0, 2, "RADEON_PP_ROT_MATRIX_0"},
515 {RADEON_RB3D_STENCILREFMASK, 3, "RADEON_RB3D_STENCILREFMASK"},
516 {RADEON_SE_VPORT_XSCALE, 6, "RADEON_SE_VPORT_XSCALE"},
517 {RADEON_SE_CNTL, 2, "RADEON_SE_CNTL"},
518 {RADEON_SE_CNTL_STATUS, 1, "RADEON_SE_CNTL_STATUS"},
519 {RADEON_RE_MISC, 1, "RADEON_RE_MISC"},
520 {RADEON_PP_TXFILTER_0, 6, "RADEON_PP_TXFILTER_0"},
521 {RADEON_PP_BORDER_COLOR_0, 1, "RADEON_PP_BORDER_COLOR_0"},
522 {RADEON_PP_TXFILTER_1, 6, "RADEON_PP_TXFILTER_1"},
523 {RADEON_PP_BORDER_COLOR_1, 1, "RADEON_PP_BORDER_COLOR_1"},
524 {RADEON_PP_TXFILTER_2, 6, "RADEON_PP_TXFILTER_2"},
525 {RADEON_PP_BORDER_COLOR_2, 1, "RADEON_PP_BORDER_COLOR_2"},
526 {RADEON_SE_ZBIAS_FACTOR, 2, "RADEON_SE_ZBIAS_FACTOR"},
527 {RADEON_SE_TCL_OUTPUT_VTX_FMT, 11, "RADEON_SE_TCL_OUTPUT_VTX_FMT"},
528 {RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED, 17,
529 "RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED"},
530 {R200_PP_TXCBLEND_0, 4, "R200_PP_TXCBLEND_0"},
531 {R200_PP_TXCBLEND_1, 4, "R200_PP_TXCBLEND_1"},
532 {R200_PP_TXCBLEND_2, 4, "R200_PP_TXCBLEND_2"},
533 {R200_PP_TXCBLEND_3, 4, "R200_PP_TXCBLEND_3"},
534 {R200_PP_TXCBLEND_4, 4, "R200_PP_TXCBLEND_4"},
535 {R200_PP_TXCBLEND_5, 4, "R200_PP_TXCBLEND_5"},
536 {R200_PP_TXCBLEND_6, 4, "R200_PP_TXCBLEND_6"},
537 {R200_PP_TXCBLEND_7, 4, "R200_PP_TXCBLEND_7"},
538 {R200_SE_TCL_LIGHT_MODEL_CTL_0, 6, "R200_SE_TCL_LIGHT_MODEL_CTL_0"},
539 {R200_PP_TFACTOR_0, 6, "R200_PP_TFACTOR_0"},
540 {R200_SE_VTX_FMT_0, 4, "R200_SE_VTX_FMT_0"},
541 {R200_SE_VAP_CNTL, 1, "R200_SE_VAP_CNTL"},
542 {R200_SE_TCL_MATRIX_SEL_0, 5, "R200_SE_TCL_MATRIX_SEL_0"},
543 {R200_SE_TCL_TEX_PROC_CTL_2, 5, "R200_SE_TCL_TEX_PROC_CTL_2"},
544 {R200_SE_TCL_UCP_VERT_BLEND_CTL, 1, "R200_SE_TCL_UCP_VERT_BLEND_CTL"},
545 {R200_PP_TXFILTER_0, 6, "R200_PP_TXFILTER_0"},
546 {R200_PP_TXFILTER_1, 6, "R200_PP_TXFILTER_1"},
547 {R200_PP_TXFILTER_2, 6, "R200_PP_TXFILTER_2"},
548 {R200_PP_TXFILTER_3, 6, "R200_PP_TXFILTER_3"},
549 {R200_PP_TXFILTER_4, 6, "R200_PP_TXFILTER_4"},
550 {R200_PP_TXFILTER_5, 6, "R200_PP_TXFILTER_5"},
551 {R200_PP_TXOFFSET_0, 1, "R200_PP_TXOFFSET_0"},
552 {R200_PP_TXOFFSET_1, 1, "R200_PP_TXOFFSET_1"},
553 {R200_PP_TXOFFSET_2, 1, "R200_PP_TXOFFSET_2"},
554 {R200_PP_TXOFFSET_3, 1, "R200_PP_TXOFFSET_3"},
555 {R200_PP_TXOFFSET_4, 1, "R200_PP_TXOFFSET_4"},
556 {R200_PP_TXOFFSET_5, 1, "R200_PP_TXOFFSET_5"},
557 {R200_SE_VTE_CNTL, 1, "R200_SE_VTE_CNTL"},
558 {R200_SE_TCL_OUTPUT_VTX_COMP_SEL, 1, "R200_SE_TCL_OUTPUT_VTX_COMP_SEL"},
559 {R200_PP_TAM_DEBUG3, 1, "R200_PP_TAM_DEBUG3"},
560 {R200_PP_CNTL_X, 1, "R200_PP_CNTL_X"},
561 {R200_RB3D_DEPTHXY_OFFSET, 1, "R200_RB3D_DEPTHXY_OFFSET"},
562 {R200_RE_AUX_SCISSOR_CNTL, 1, "R200_RE_AUX_SCISSOR_CNTL"},
563 {R200_RE_SCISSOR_TL_0, 2, "R200_RE_SCISSOR_TL_0"},
564 {R200_RE_SCISSOR_TL_1, 2, "R200_RE_SCISSOR_TL_1"},
565 {R200_RE_SCISSOR_TL_2, 2, "R200_RE_SCISSOR_TL_2"},
566 {R200_SE_VAP_CNTL_STATUS, 1, "R200_SE_VAP_CNTL_STATUS"},
567 {R200_SE_VTX_STATE_CNTL, 1, "R200_SE_VTX_STATE_CNTL"},
568 {R200_RE_POINTSIZE, 1, "R200_RE_POINTSIZE"},
569 {R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0, 4,
570 "R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0"},
571 {R200_PP_CUBIC_FACES_0, 1, "R200_PP_CUBIC_FACES_0"}, /* 61 */
572 {R200_PP_CUBIC_OFFSET_F1_0, 5, "R200_PP_CUBIC_OFFSET_F1_0"}, /* 62 */
573 {R200_PP_CUBIC_FACES_1, 1, "R200_PP_CUBIC_FACES_1"},
574 {R200_PP_CUBIC_OFFSET_F1_1, 5, "R200_PP_CUBIC_OFFSET_F1_1"},
575 {R200_PP_CUBIC_FACES_2, 1, "R200_PP_CUBIC_FACES_2"},
576 {R200_PP_CUBIC_OFFSET_F1_2, 5, "R200_PP_CUBIC_OFFSET_F1_2"},
577 {R200_PP_CUBIC_FACES_3, 1, "R200_PP_CUBIC_FACES_3"},
578 {R200_PP_CUBIC_OFFSET_F1_3, 5, "R200_PP_CUBIC_OFFSET_F1_3"},
579 {R200_PP_CUBIC_FACES_4, 1, "R200_PP_CUBIC_FACES_4"},
580 {R200_PP_CUBIC_OFFSET_F1_4, 5, "R200_PP_CUBIC_OFFSET_F1_4"},
581 {R200_PP_CUBIC_FACES_5, 1, "R200_PP_CUBIC_FACES_5"},
582 {R200_PP_CUBIC_OFFSET_F1_5, 5, "R200_PP_CUBIC_OFFSET_F1_5"},
583 {RADEON_PP_TEX_SIZE_0, 2, "RADEON_PP_TEX_SIZE_0"},
584 {RADEON_PP_TEX_SIZE_1, 2, "RADEON_PP_TEX_SIZE_1"},
585 {RADEON_PP_TEX_SIZE_2, 2, "RADEON_PP_TEX_SIZE_2"},
586 {R200_RB3D_BLENDCOLOR, 3, "R200_RB3D_BLENDCOLOR"},
587 {R200_SE_TCL_POINT_SPRITE_CNTL, 1, "R200_SE_TCL_POINT_SPRITE_CNTL"},
588 {RADEON_PP_CUBIC_FACES_0, 1, "RADEON_PP_CUBIC_FACES_0"},
589 {RADEON_PP_CUBIC_OFFSET_T0_0, 5, "RADEON_PP_CUBIC_OFFSET_T0_0"},
590 {RADEON_PP_CUBIC_FACES_1, 1, "RADEON_PP_CUBIC_FACES_1"},
591 {RADEON_PP_CUBIC_OFFSET_T1_0, 5, "RADEON_PP_CUBIC_OFFSET_T1_0"},
592 {RADEON_PP_CUBIC_FACES_2, 1, "RADEON_PP_CUBIC_FACES_2"},
593 {RADEON_PP_CUBIC_OFFSET_T2_0, 5, "RADEON_PP_CUBIC_OFFSET_T2_0"},
594 {R200_PP_TRI_PERF, 2, "R200_PP_TRI_PERF"},
595 {R200_PP_AFS_0, 32, "R200_PP_AFS_0"}, /* 85 */
596 {R200_PP_AFS_1, 32, "R200_PP_AFS_1"},
597 {R200_PP_TFACTOR_0, 8, "R200_ATF_TFACTOR"},
598 {R200_PP_TXFILTER_0, 8, "R200_PP_TXCTLALL_0"},
599 {R200_PP_TXFILTER_1, 8, "R200_PP_TXCTLALL_1"},
600 {R200_PP_TXFILTER_2, 8, "R200_PP_TXCTLALL_2"},
601 {R200_PP_TXFILTER_3, 8, "R200_PP_TXCTLALL_3"},
602 {R200_PP_TXFILTER_4, 8, "R200_PP_TXCTLALL_4"},
603 {R200_PP_TXFILTER_5, 8, "R200_PP_TXCTLALL_5"},
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604};
605
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606/* ================================================================
607 * Performance monitoring functions
608 */
609
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000610static void radeon_clear_box(drm_radeon_private_t * dev_priv,
611 int x, int y, int w, int h, int r, int g, int b)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612{
613 u32 color;
614 RING_LOCALS;
615
616 x += dev_priv->sarea_priv->boxes[0].x1;
617 y += dev_priv->sarea_priv->boxes[0].y1;
618
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000619 switch (dev_priv->color_fmt) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620 case RADEON_COLOR_FORMAT_RGB565:
621 color = (((r & 0xf8) << 8) |
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000622 ((g & 0xfc) << 3) | ((b & 0xf8) >> 3));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623 break;
624 case RADEON_COLOR_FORMAT_ARGB8888:
625 default:
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000626 color = (((0xff) << 24) | (r << 16) | (g << 8) | b);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627 break;
628 }
629
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000630 BEGIN_RING(4);
631 RADEON_WAIT_UNTIL_3D_IDLE();
632 OUT_RING(CP_PACKET0(RADEON_DP_WRITE_MASK, 0));
633 OUT_RING(0xffffffff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634 ADVANCE_RING();
635
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000636 BEGIN_RING(6);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000638 OUT_RING(CP_PACKET3(RADEON_CNTL_PAINT_MULTI, 4));
639 OUT_RING(RADEON_GMC_DST_PITCH_OFFSET_CNTL |
640 RADEON_GMC_BRUSH_SOLID_COLOR |
641 (dev_priv->color_fmt << 8) |
642 RADEON_GMC_SRC_DATATYPE_COLOR |
643 RADEON_ROP3_P | RADEON_GMC_CLR_CMP_CNTL_DIS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000645 if (dev_priv->page_flipping && dev_priv->current_page == 1) {
646 OUT_RING(dev_priv->front_pitch_offset);
647 } else {
648 OUT_RING(dev_priv->back_pitch_offset);
649 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000651 OUT_RING(color);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000653 OUT_RING((x << 16) | y);
654 OUT_RING((w << 16) | h);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655
656 ADVANCE_RING();
657}
658
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000659static void radeon_cp_performance_boxes(drm_radeon_private_t * dev_priv)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660{
661 /* Collapse various things into a wait flag -- trying to
662 * guess if userspase slept -- better just to have them tell us.
663 */
664 if (dev_priv->stats.last_frame_reads > 1 ||
665 dev_priv->stats.last_clear_reads > dev_priv->stats.clears) {
666 dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
667 }
668
669 if (dev_priv->stats.freelist_loops) {
670 dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
671 }
672
673 /* Purple box for page flipping
674 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000675 if (dev_priv->stats.boxes & RADEON_BOX_FLIP)
676 radeon_clear_box(dev_priv, 4, 4, 8, 8, 255, 0, 255);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677
678 /* Red box if we have to wait for idle at any point
679 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000680 if (dev_priv->stats.boxes & RADEON_BOX_WAIT_IDLE)
681 radeon_clear_box(dev_priv, 16, 4, 8, 8, 255, 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682
683 /* Blue box: lost context?
684 */
685
686 /* Yellow box for texture swaps
687 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000688 if (dev_priv->stats.boxes & RADEON_BOX_TEXTURE_LOAD)
689 radeon_clear_box(dev_priv, 40, 4, 8, 8, 255, 255, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690
691 /* Green box if hardware never idles (as far as we can tell)
692 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000693 if (!(dev_priv->stats.boxes & RADEON_BOX_DMA_IDLE))
694 radeon_clear_box(dev_priv, 64, 4, 8, 8, 0, 255, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000696 /* Draw bars indicating number of buffers allocated
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697 * (not a great measure, easily confused)
698 */
699 if (dev_priv->stats.requested_bufs) {
700 if (dev_priv->stats.requested_bufs > 100)
701 dev_priv->stats.requested_bufs = 100;
702
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000703 radeon_clear_box(dev_priv, 4, 16,
704 dev_priv->stats.requested_bufs, 4,
705 196, 128, 128);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706 }
707
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000708 memset(&dev_priv->stats, 0, sizeof(dev_priv->stats));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709
710}
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000711
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712/* ================================================================
713 * CP command dispatch functions
714 */
715
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000716static void radeon_cp_dispatch_clear(drm_device_t * dev,
717 drm_radeon_clear_t * clear,
718 drm_radeon_clear_rect_t * depth_boxes)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719{
720 drm_radeon_private_t *dev_priv = dev->dev_private;
721 drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
722 drm_radeon_depth_clear_t *depth_clear = &dev_priv->depth_clear;
723 int nbox = sarea_priv->nbox;
724 drm_clip_rect_t *pbox = sarea_priv->boxes;
725 unsigned int flags = clear->flags;
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000726 u32 rb3d_cntl = 0, rb3d_stencilrefmask = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727 int i;
728 RING_LOCALS;
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000729 DRM_DEBUG("flags = 0x%x\n", flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730
731 dev_priv->stats.clears++;
732
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000733 if (dev_priv->page_flipping && dev_priv->current_page == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734 unsigned int tmp = flags;
735
736 flags &= ~(RADEON_FRONT | RADEON_BACK);
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000737 if (tmp & RADEON_FRONT)
738 flags |= RADEON_BACK;
739 if (tmp & RADEON_BACK)
740 flags |= RADEON_FRONT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741 }
742
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000743 if (flags & (RADEON_FRONT | RADEON_BACK)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000745 BEGIN_RING(4);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746
747 /* Ensure the 3D stream is idle before doing a
748 * 2D fill to clear the front or back buffer.
749 */
750 RADEON_WAIT_UNTIL_3D_IDLE();
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000751
752 OUT_RING(CP_PACKET0(RADEON_DP_WRITE_MASK, 0));
753 OUT_RING(clear->color_mask);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754
755 ADVANCE_RING();
756
757 /* Make sure we restore the 3D state next time.
758 */
759 dev_priv->sarea_priv->ctx_owner = 0;
760
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000761 for (i = 0; i < nbox; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762 int x = pbox[i].x1;
763 int y = pbox[i].y1;
764 int w = pbox[i].x2 - x;
765 int h = pbox[i].y2 - y;
766
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000767 DRM_DEBUG("dispatch clear %d,%d-%d,%d flags 0x%x\n",
768 x, y, w, h, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000770 if (flags & RADEON_FRONT) {
771 BEGIN_RING(6);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000773 OUT_RING(CP_PACKET3
774 (RADEON_CNTL_PAINT_MULTI, 4));
775 OUT_RING(RADEON_GMC_DST_PITCH_OFFSET_CNTL |
776 RADEON_GMC_BRUSH_SOLID_COLOR |
777 (dev_priv->
778 color_fmt << 8) |
779 RADEON_GMC_SRC_DATATYPE_COLOR |
780 RADEON_ROP3_P |
781 RADEON_GMC_CLR_CMP_CNTL_DIS);
782
783 OUT_RING(dev_priv->front_pitch_offset);
784 OUT_RING(clear->clear_color);
785
786 OUT_RING((x << 16) | y);
787 OUT_RING((w << 16) | h);
788
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789 ADVANCE_RING();
790 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000792 if (flags & RADEON_BACK) {
793 BEGIN_RING(6);
794
795 OUT_RING(CP_PACKET3
796 (RADEON_CNTL_PAINT_MULTI, 4));
797 OUT_RING(RADEON_GMC_DST_PITCH_OFFSET_CNTL |
798 RADEON_GMC_BRUSH_SOLID_COLOR |
799 (dev_priv->
800 color_fmt << 8) |
801 RADEON_GMC_SRC_DATATYPE_COLOR |
802 RADEON_ROP3_P |
803 RADEON_GMC_CLR_CMP_CNTL_DIS);
804
805 OUT_RING(dev_priv->back_pitch_offset);
806 OUT_RING(clear->clear_color);
807
808 OUT_RING((x << 16) | y);
809 OUT_RING((w << 16) | h);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810
811 ADVANCE_RING();
812 }
813 }
814 }
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000815
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816 /* hyper z clear */
817 /* no docs available, based on reverse engeneering by Stephane Marchesin */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000818 if ((flags & (RADEON_DEPTH | RADEON_STENCIL))
819 && (flags & RADEON_CLEAR_FASTZ)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820
821 int i;
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000822 int depthpixperline =
823 dev_priv->depth_fmt ==
824 RADEON_DEPTH_FORMAT_16BIT_INT_Z ? (dev_priv->depth_pitch /
825 2) : (dev_priv->
826 depth_pitch / 4);
827
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828 u32 clearmask;
829
830 u32 tempRB3D_DEPTHCLEARVALUE = clear->clear_depth |
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000831 ((clear->depth_mask & 0xff) << 24);
832
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833 /* Make sure we restore the 3D state next time.
834 * we haven't touched any "normal" state - still need this?
835 */
836 dev_priv->sarea_priv->ctx_owner = 0;
837
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000838 if ((dev_priv->flags & CHIP_HAS_HIERZ)
839 && (flags & RADEON_USE_HIERZ)) {
840 /* FIXME : reverse engineer that for Rx00 cards */
841 /* FIXME : the mask supposedly contains low-res z values. So can't set
842 just to the max (0xff? or actually 0x3fff?), need to take z clear
843 value into account? */
844 /* pattern seems to work for r100, though get slight
845 rendering errors with glxgears. If hierz is not enabled for r100,
846 only 4 bits which indicate clear (15,16,31,32, all zero) matter, the
847 other ones are ignored, and the same clear mask can be used. That's
848 very different behaviour than R200 which needs different clear mask
849 and different number of tiles to clear if hierz is enabled or not !?!
850 */
851 clearmask = (0xff << 22) | (0xff << 6) | 0x003f003f;
852 } else {
853 /* clear mask : chooses the clearing pattern.
854 rv250: could be used to clear only parts of macrotiles
855 (but that would get really complicated...)?
856 bit 0 and 1 (either or both of them ?!?!) are used to
857 not clear tile (or maybe one of the bits indicates if the tile is
858 compressed or not), bit 2 and 3 to not clear tile 1,...,.
859 Pattern is as follows:
860 | 0,1 | 4,5 | 8,9 |12,13|16,17|20,21|24,25|28,29|
861 bits -------------------------------------------------
862 | 2,3 | 6,7 |10,11|14,15|18,19|22,23|26,27|30,31|
863 rv100: clearmask covers 2x8 4x1 tiles, but one clear still
864 covers 256 pixels ?!?
865 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866 clearmask = 0x0;
867 }
868
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000869 BEGIN_RING(8);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870 RADEON_WAIT_UNTIL_2D_IDLE();
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000871 OUT_RING_REG(RADEON_RB3D_DEPTHCLEARVALUE,
872 tempRB3D_DEPTHCLEARVALUE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873 /* what offset is this exactly ? */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000874 OUT_RING_REG(RADEON_RB3D_ZMASKOFFSET, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875 /* need ctlstat, otherwise get some strange black flickering */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000876 OUT_RING_REG(RADEON_RB3D_ZCACHE_CTLSTAT,
877 RADEON_RB3D_ZC_FLUSH_ALL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878 ADVANCE_RING();
879
880 for (i = 0; i < nbox; i++) {
881 int tileoffset, nrtilesx, nrtilesy, j;
882 /* it looks like r200 needs rv-style clears, at least if hierz is not enabled? */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000883 if ((dev_priv->flags & CHIP_HAS_HIERZ)
884 && !(dev_priv->microcode_version == UCODE_R200)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885 /* FIXME : figure this out for r200 (when hierz is enabled). Or
886 maybe r200 actually doesn't need to put the low-res z value into
887 the tile cache like r100, but just needs to clear the hi-level z-buffer?
888 Works for R100, both with hierz and without.
889 R100 seems to operate on 2x1 8x8 tiles, but...
890 odd: offset/nrtiles need to be 64 pix (4 block) aligned? Potentially
891 problematic with resolutions which are not 64 pix aligned? */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000892 tileoffset =
893 ((pbox[i].y1 >> 3) * depthpixperline +
894 pbox[i].x1) >> 6;
895 nrtilesx =
896 ((pbox[i].x2 & ~63) -
897 (pbox[i].x1 & ~63)) >> 4;
898 nrtilesy =
899 (pbox[i].y2 >> 3) - (pbox[i].y1 >> 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900 for (j = 0; j <= nrtilesy; j++) {
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000901 BEGIN_RING(4);
902 OUT_RING(CP_PACKET3
903 (RADEON_3D_CLEAR_ZMASK, 2));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904 /* first tile */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000905 OUT_RING(tileoffset * 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906 /* the number of tiles to clear */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000907 OUT_RING(nrtilesx + 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908 /* clear mask : chooses the clearing pattern. */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000909 OUT_RING(clearmask);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 ADVANCE_RING();
911 tileoffset += depthpixperline >> 6;
912 }
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000913 } else if (dev_priv->microcode_version == UCODE_R200) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914 /* works for rv250. */
915 /* find first macro tile (8x2 4x4 z-pixels on rv250) */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000916 tileoffset =
917 ((pbox[i].y1 >> 3) * depthpixperline +
918 pbox[i].x1) >> 5;
919 nrtilesx =
920 (pbox[i].x2 >> 5) - (pbox[i].x1 >> 5);
921 nrtilesy =
922 (pbox[i].y2 >> 3) - (pbox[i].y1 >> 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923 for (j = 0; j <= nrtilesy; j++) {
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000924 BEGIN_RING(4);
925 OUT_RING(CP_PACKET3
926 (RADEON_3D_CLEAR_ZMASK, 2));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927 /* first tile */
928 /* judging by the first tile offset needed, could possibly
929 directly address/clear 4x4 tiles instead of 8x2 * 4x4
930 macro tiles, though would still need clear mask for
931 right/bottom if truely 4x4 granularity is desired ? */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000932 OUT_RING(tileoffset * 16);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933 /* the number of tiles to clear */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000934 OUT_RING(nrtilesx + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935 /* clear mask : chooses the clearing pattern. */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000936 OUT_RING(clearmask);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937 ADVANCE_RING();
938 tileoffset += depthpixperline >> 5;
939 }
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000940 } else { /* rv 100 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941 /* rv100 might not need 64 pix alignment, who knows */
942 /* offsets are, hmm, weird */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000943 tileoffset =
944 ((pbox[i].y1 >> 4) * depthpixperline +
945 pbox[i].x1) >> 6;
946 nrtilesx =
947 ((pbox[i].x2 & ~63) -
948 (pbox[i].x1 & ~63)) >> 4;
949 nrtilesy =
950 (pbox[i].y2 >> 4) - (pbox[i].y1 >> 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951 for (j = 0; j <= nrtilesy; j++) {
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000952 BEGIN_RING(4);
953 OUT_RING(CP_PACKET3
954 (RADEON_3D_CLEAR_ZMASK, 2));
955 OUT_RING(tileoffset * 128);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956 /* the number of tiles to clear */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000957 OUT_RING(nrtilesx + 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958 /* clear mask : chooses the clearing pattern. */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000959 OUT_RING(clearmask);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960 ADVANCE_RING();
961 tileoffset += depthpixperline >> 6;
962 }
963 }
964 }
965
966 /* TODO don't always clear all hi-level z tiles */
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000967 if ((dev_priv->flags & CHIP_HAS_HIERZ)
968 && (dev_priv->microcode_version == UCODE_R200)
969 && (flags & RADEON_USE_HIERZ))
970 /* r100 and cards without hierarchical z-buffer have no high-level z-buffer */
971 /* FIXME : the mask supposedly contains low-res z values. So can't set
972 just to the max (0xff? or actually 0x3fff?), need to take z clear
973 value into account? */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974 {
Dave Airlieb5e89ed2005-09-25 14:28:13 +1000975 BEGIN_RING(4);
976 OUT_RING(CP_PACKET3(RADEON_3D_CLEAR_HIZ, 2));
977 OUT_RING(0x0); /* First tile */
978 OUT_RING(0x3cc0);
979 OUT_RING((0xff << 22) | (0xff << 6) | 0x003f003f);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980 ADVANCE_RING();
981 }
982 }
983
984 /* We have to clear the depth and/or stencil buffers by
985 * rendering a quad into just those buffers. Thus, we have to
986 * make sure the 3D engine is configured correctly.
987 */
988 if ((dev_priv->microcode_version == UCODE_R200) &&
989 (flags & (RADEON_DEPTH | RADEON_STENCIL))) {
990
991 int tempPP_CNTL;
992 int tempRE_CNTL;
993 int tempRB3D_CNTL;
994 int tempRB3D_ZSTENCILCNTL;
995 int tempRB3D_STENCILREFMASK;
996 int tempRB3D_PLANEMASK;
997 int tempSE_CNTL;
998 int tempSE_VTE_CNTL;
999 int tempSE_VTX_FMT_0;
1000 int tempSE_VTX_FMT_1;
1001 int tempSE_VAP_CNTL;
1002 int tempRE_AUX_SCISSOR_CNTL;
1003
1004 tempPP_CNTL = 0;
1005 tempRE_CNTL = 0;
1006
1007 tempRB3D_CNTL = depth_clear->rb3d_cntl;
1008
1009 tempRB3D_ZSTENCILCNTL = depth_clear->rb3d_zstencilcntl;
1010 tempRB3D_STENCILREFMASK = 0x0;
1011
1012 tempSE_CNTL = depth_clear->se_cntl;
1013
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014 /* Disable TCL */
1015
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001016 tempSE_VAP_CNTL = ( /* SE_VAP_CNTL__FORCE_W_TO_ONE_MASK | */
1017 (0x9 <<
1018 SE_VAP_CNTL__VF_MAX_VTX_NUM__SHIFT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019
1020 tempRB3D_PLANEMASK = 0x0;
1021
1022 tempRE_AUX_SCISSOR_CNTL = 0x0;
1023
1024 tempSE_VTE_CNTL =
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001025 SE_VTE_CNTL__VTX_XY_FMT_MASK | SE_VTE_CNTL__VTX_Z_FMT_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001027 /* Vertex format (X, Y, Z, W) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028 tempSE_VTX_FMT_0 =
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001029 SE_VTX_FMT_0__VTX_Z0_PRESENT_MASK |
1030 SE_VTX_FMT_0__VTX_W0_PRESENT_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031 tempSE_VTX_FMT_1 = 0x0;
1032
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001033 /*
1034 * Depth buffer specific enables
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 */
1036 if (flags & RADEON_DEPTH) {
1037 /* Enable depth buffer */
1038 tempRB3D_CNTL |= RADEON_Z_ENABLE;
1039 } else {
1040 /* Disable depth buffer */
1041 tempRB3D_CNTL &= ~RADEON_Z_ENABLE;
1042 }
1043
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001044 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045 * Stencil buffer specific enables
1046 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001047 if (flags & RADEON_STENCIL) {
1048 tempRB3D_CNTL |= RADEON_STENCIL_ENABLE;
1049 tempRB3D_STENCILREFMASK = clear->depth_mask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050 } else {
1051 tempRB3D_CNTL &= ~RADEON_STENCIL_ENABLE;
1052 tempRB3D_STENCILREFMASK = 0x00000000;
1053 }
1054
1055 if (flags & RADEON_USE_COMP_ZBUF) {
1056 tempRB3D_ZSTENCILCNTL |= RADEON_Z_COMPRESSION_ENABLE |
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001057 RADEON_Z_DECOMPRESSION_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058 }
1059 if (flags & RADEON_USE_HIERZ) {
1060 tempRB3D_ZSTENCILCNTL |= RADEON_Z_HIERARCHY_ENABLE;
1061 }
1062
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001063 BEGIN_RING(26);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064 RADEON_WAIT_UNTIL_2D_IDLE();
1065
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001066 OUT_RING_REG(RADEON_PP_CNTL, tempPP_CNTL);
1067 OUT_RING_REG(R200_RE_CNTL, tempRE_CNTL);
1068 OUT_RING_REG(RADEON_RB3D_CNTL, tempRB3D_CNTL);
1069 OUT_RING_REG(RADEON_RB3D_ZSTENCILCNTL, tempRB3D_ZSTENCILCNTL);
1070 OUT_RING_REG(RADEON_RB3D_STENCILREFMASK,
1071 tempRB3D_STENCILREFMASK);
1072 OUT_RING_REG(RADEON_RB3D_PLANEMASK, tempRB3D_PLANEMASK);
1073 OUT_RING_REG(RADEON_SE_CNTL, tempSE_CNTL);
1074 OUT_RING_REG(R200_SE_VTE_CNTL, tempSE_VTE_CNTL);
1075 OUT_RING_REG(R200_SE_VTX_FMT_0, tempSE_VTX_FMT_0);
1076 OUT_RING_REG(R200_SE_VTX_FMT_1, tempSE_VTX_FMT_1);
1077 OUT_RING_REG(R200_SE_VAP_CNTL, tempSE_VAP_CNTL);
1078 OUT_RING_REG(R200_RE_AUX_SCISSOR_CNTL, tempRE_AUX_SCISSOR_CNTL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079 ADVANCE_RING();
1080
1081 /* Make sure we restore the 3D state next time.
1082 */
1083 dev_priv->sarea_priv->ctx_owner = 0;
1084
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001085 for (i = 0; i < nbox; i++) {
1086
1087 /* Funny that this should be required --
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088 * sets top-left?
1089 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001090 radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001092 BEGIN_RING(14);
1093 OUT_RING(CP_PACKET3(R200_3D_DRAW_IMMD_2, 12));
1094 OUT_RING((RADEON_PRIM_TYPE_RECT_LIST |
1095 RADEON_PRIM_WALK_RING |
1096 (3 << RADEON_NUM_VERTICES_SHIFT)));
1097 OUT_RING(depth_boxes[i].ui[CLEAR_X1]);
1098 OUT_RING(depth_boxes[i].ui[CLEAR_Y1]);
1099 OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
1100 OUT_RING(0x3f800000);
1101 OUT_RING(depth_boxes[i].ui[CLEAR_X1]);
1102 OUT_RING(depth_boxes[i].ui[CLEAR_Y2]);
1103 OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
1104 OUT_RING(0x3f800000);
1105 OUT_RING(depth_boxes[i].ui[CLEAR_X2]);
1106 OUT_RING(depth_boxes[i].ui[CLEAR_Y2]);
1107 OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
1108 OUT_RING(0x3f800000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109 ADVANCE_RING();
1110 }
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001111 } else if ((flags & (RADEON_DEPTH | RADEON_STENCIL))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112
1113 int tempRB3D_ZSTENCILCNTL = depth_clear->rb3d_zstencilcntl;
1114
1115 rb3d_cntl = depth_clear->rb3d_cntl;
1116
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001117 if (flags & RADEON_DEPTH) {
1118 rb3d_cntl |= RADEON_Z_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119 } else {
1120 rb3d_cntl &= ~RADEON_Z_ENABLE;
1121 }
1122
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001123 if (flags & RADEON_STENCIL) {
1124 rb3d_cntl |= RADEON_STENCIL_ENABLE;
1125 rb3d_stencilrefmask = clear->depth_mask; /* misnamed field */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126 } else {
1127 rb3d_cntl &= ~RADEON_STENCIL_ENABLE;
1128 rb3d_stencilrefmask = 0x00000000;
1129 }
1130
1131 if (flags & RADEON_USE_COMP_ZBUF) {
1132 tempRB3D_ZSTENCILCNTL |= RADEON_Z_COMPRESSION_ENABLE |
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001133 RADEON_Z_DECOMPRESSION_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134 }
1135 if (flags & RADEON_USE_HIERZ) {
1136 tempRB3D_ZSTENCILCNTL |= RADEON_Z_HIERARCHY_ENABLE;
1137 }
1138
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001139 BEGIN_RING(13);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140 RADEON_WAIT_UNTIL_2D_IDLE();
1141
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001142 OUT_RING(CP_PACKET0(RADEON_PP_CNTL, 1));
1143 OUT_RING(0x00000000);
1144 OUT_RING(rb3d_cntl);
1145
1146 OUT_RING_REG(RADEON_RB3D_ZSTENCILCNTL, tempRB3D_ZSTENCILCNTL);
1147 OUT_RING_REG(RADEON_RB3D_STENCILREFMASK, rb3d_stencilrefmask);
1148 OUT_RING_REG(RADEON_RB3D_PLANEMASK, 0x00000000);
1149 OUT_RING_REG(RADEON_SE_CNTL, depth_clear->se_cntl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150 ADVANCE_RING();
1151
1152 /* Make sure we restore the 3D state next time.
1153 */
1154 dev_priv->sarea_priv->ctx_owner = 0;
1155
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001156 for (i = 0; i < nbox; i++) {
1157
1158 /* Funny that this should be required --
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159 * sets top-left?
1160 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001161 radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001163 BEGIN_RING(15);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001165 OUT_RING(CP_PACKET3(RADEON_3D_DRAW_IMMD, 13));
1166 OUT_RING(RADEON_VTX_Z_PRESENT |
1167 RADEON_VTX_PKCOLOR_PRESENT);
1168 OUT_RING((RADEON_PRIM_TYPE_RECT_LIST |
1169 RADEON_PRIM_WALK_RING |
1170 RADEON_MAOS_ENABLE |
1171 RADEON_VTX_FMT_RADEON_MODE |
1172 (3 << RADEON_NUM_VERTICES_SHIFT)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001173
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001174 OUT_RING(depth_boxes[i].ui[CLEAR_X1]);
1175 OUT_RING(depth_boxes[i].ui[CLEAR_Y1]);
1176 OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
1177 OUT_RING(0x0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001179 OUT_RING(depth_boxes[i].ui[CLEAR_X1]);
1180 OUT_RING(depth_boxes[i].ui[CLEAR_Y2]);
1181 OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
1182 OUT_RING(0x0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001184 OUT_RING(depth_boxes[i].ui[CLEAR_X2]);
1185 OUT_RING(depth_boxes[i].ui[CLEAR_Y2]);
1186 OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
1187 OUT_RING(0x0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188
1189 ADVANCE_RING();
1190 }
1191 }
1192
1193 /* Increment the clear counter. The client-side 3D driver must
1194 * wait on this value before performing the clear ioctl. We
1195 * need this because the card's so damned fast...
1196 */
1197 dev_priv->sarea_priv->last_clear++;
1198
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001199 BEGIN_RING(4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001201 RADEON_CLEAR_AGE(dev_priv->sarea_priv->last_clear);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202 RADEON_WAIT_UNTIL_IDLE();
1203
1204 ADVANCE_RING();
1205}
1206
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001207static void radeon_cp_dispatch_swap(drm_device_t * dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208{
1209 drm_radeon_private_t *dev_priv = dev->dev_private;
1210 drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
1211 int nbox = sarea_priv->nbox;
1212 drm_clip_rect_t *pbox = sarea_priv->boxes;
1213 int i;
1214 RING_LOCALS;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001215 DRM_DEBUG("\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216
1217 /* Do some trivial performance monitoring...
1218 */
1219 if (dev_priv->do_boxes)
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001220 radeon_cp_performance_boxes(dev_priv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221
1222 /* Wait for the 3D stream to idle before dispatching the bitblt.
1223 * This will prevent data corruption between the two streams.
1224 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001225 BEGIN_RING(2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226
1227 RADEON_WAIT_UNTIL_3D_IDLE();
1228
1229 ADVANCE_RING();
1230
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001231 for (i = 0; i < nbox; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232 int x = pbox[i].x1;
1233 int y = pbox[i].y1;
1234 int w = pbox[i].x2 - x;
1235 int h = pbox[i].y2 - y;
1236
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001237 DRM_DEBUG("dispatch swap %d,%d-%d,%d\n", x, y, w, h);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001239 BEGIN_RING(7);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001241 OUT_RING(CP_PACKET3(RADEON_CNTL_BITBLT_MULTI, 5));
1242 OUT_RING(RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
1243 RADEON_GMC_DST_PITCH_OFFSET_CNTL |
1244 RADEON_GMC_BRUSH_NONE |
1245 (dev_priv->color_fmt << 8) |
1246 RADEON_GMC_SRC_DATATYPE_COLOR |
1247 RADEON_ROP3_S |
1248 RADEON_DP_SRC_SOURCE_MEMORY |
1249 RADEON_GMC_CLR_CMP_CNTL_DIS | RADEON_GMC_WR_MSK_DIS);
1250
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251 /* Make this work even if front & back are flipped:
1252 */
1253 if (dev_priv->current_page == 0) {
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001254 OUT_RING(dev_priv->back_pitch_offset);
1255 OUT_RING(dev_priv->front_pitch_offset);
1256 } else {
1257 OUT_RING(dev_priv->front_pitch_offset);
1258 OUT_RING(dev_priv->back_pitch_offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259 }
1260
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001261 OUT_RING((x << 16) | y);
1262 OUT_RING((x << 16) | y);
1263 OUT_RING((w << 16) | h);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264
1265 ADVANCE_RING();
1266 }
1267
1268 /* Increment the frame counter. The client-side 3D driver must
1269 * throttle the framerate by waiting for this value before
1270 * performing the swapbuffer ioctl.
1271 */
1272 dev_priv->sarea_priv->last_frame++;
1273
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001274 BEGIN_RING(4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001276 RADEON_FRAME_AGE(dev_priv->sarea_priv->last_frame);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277 RADEON_WAIT_UNTIL_2D_IDLE();
1278
1279 ADVANCE_RING();
1280}
1281
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001282static void radeon_cp_dispatch_flip(drm_device_t * dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001283{
1284 drm_radeon_private_t *dev_priv = dev->dev_private;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001285 drm_sarea_t *sarea = (drm_sarea_t *) dev_priv->sarea->handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286 int offset = (dev_priv->current_page == 1)
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001287 ? dev_priv->front_offset : dev_priv->back_offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288 RING_LOCALS;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001289 DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
1290 __FUNCTION__,
1291 dev_priv->current_page, dev_priv->sarea_priv->pfCurrentPage);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292
1293 /* Do some trivial performance monitoring...
1294 */
1295 if (dev_priv->do_boxes) {
1296 dev_priv->stats.boxes |= RADEON_BOX_FLIP;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001297 radeon_cp_performance_boxes(dev_priv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298 }
1299
1300 /* Update the frame offsets for both CRTCs
1301 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001302 BEGIN_RING(6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303
1304 RADEON_WAIT_UNTIL_3D_IDLE();
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001305 OUT_RING_REG(RADEON_CRTC_OFFSET,
1306 ((sarea->frame.y * dev_priv->front_pitch +
1307 sarea->frame.x * (dev_priv->color_fmt - 2)) & ~7)
1308 + offset);
1309 OUT_RING_REG(RADEON_CRTC2_OFFSET, dev_priv->sarea_priv->crtc2_base
1310 + offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311
1312 ADVANCE_RING();
1313
1314 /* Increment the frame counter. The client-side 3D driver must
1315 * throttle the framerate by waiting for this value before
1316 * performing the swapbuffer ioctl.
1317 */
1318 dev_priv->sarea_priv->last_frame++;
1319 dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page =
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001320 1 - dev_priv->current_page;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001322 BEGIN_RING(2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001324 RADEON_FRAME_AGE(dev_priv->sarea_priv->last_frame);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325
1326 ADVANCE_RING();
1327}
1328
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001329static int bad_prim_vertex_nr(int primitive, int nr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330{
1331 switch (primitive & RADEON_PRIM_TYPE_MASK) {
1332 case RADEON_PRIM_TYPE_NONE:
1333 case RADEON_PRIM_TYPE_POINT:
1334 return nr < 1;
1335 case RADEON_PRIM_TYPE_LINE:
1336 return (nr & 1) || nr == 0;
1337 case RADEON_PRIM_TYPE_LINE_STRIP:
1338 return nr < 2;
1339 case RADEON_PRIM_TYPE_TRI_LIST:
1340 case RADEON_PRIM_TYPE_3VRT_POINT_LIST:
1341 case RADEON_PRIM_TYPE_3VRT_LINE_LIST:
1342 case RADEON_PRIM_TYPE_RECT_LIST:
1343 return nr % 3 || nr == 0;
1344 case RADEON_PRIM_TYPE_TRI_FAN:
1345 case RADEON_PRIM_TYPE_TRI_STRIP:
1346 return nr < 3;
1347 default:
1348 return 1;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001349 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001350}
1351
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352typedef struct {
1353 unsigned int start;
1354 unsigned int finish;
1355 unsigned int prim;
1356 unsigned int numverts;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001357 unsigned int offset;
1358 unsigned int vc_format;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359} drm_radeon_tcl_prim_t;
1360
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001361static void radeon_cp_dispatch_vertex(drm_device_t * dev,
1362 drm_buf_t * buf,
1363 drm_radeon_tcl_prim_t * prim)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364{
1365 drm_radeon_private_t *dev_priv = dev->dev_private;
1366 drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
1367 int offset = dev_priv->gart_buffers_offset + buf->offset + prim->start;
1368 int numverts = (int)prim->numverts;
1369 int nbox = sarea_priv->nbox;
1370 int i = 0;
1371 RING_LOCALS;
1372
1373 DRM_DEBUG("hwprim 0x%x vfmt 0x%x %d..%d %d verts\n",
1374 prim->prim,
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001375 prim->vc_format, prim->start, prim->finish, prim->numverts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001377 if (bad_prim_vertex_nr(prim->prim, prim->numverts)) {
1378 DRM_ERROR("bad prim %x numverts %d\n",
1379 prim->prim, prim->numverts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380 return;
1381 }
1382
1383 do {
1384 /* Emit the next cliprect */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001385 if (i < nbox) {
1386 radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387 }
1388
1389 /* Emit the vertex buffer rendering commands */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001390 BEGIN_RING(5);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001392 OUT_RING(CP_PACKET3(RADEON_3D_RNDR_GEN_INDX_PRIM, 3));
1393 OUT_RING(offset);
1394 OUT_RING(numverts);
1395 OUT_RING(prim->vc_format);
1396 OUT_RING(prim->prim | RADEON_PRIM_WALK_LIST |
1397 RADEON_COLOR_ORDER_RGBA |
1398 RADEON_VTX_FMT_RADEON_MODE |
1399 (numverts << RADEON_NUM_VERTICES_SHIFT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400
1401 ADVANCE_RING();
1402
1403 i++;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001404 } while (i < nbox);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405}
1406
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001407static void radeon_cp_discard_buffer(drm_device_t * dev, drm_buf_t * buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408{
1409 drm_radeon_private_t *dev_priv = dev->dev_private;
1410 drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
1411 RING_LOCALS;
1412
1413 buf_priv->age = ++dev_priv->sarea_priv->last_dispatch;
1414
1415 /* Emit the vertex buffer age */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001416 BEGIN_RING(2);
1417 RADEON_DISPATCH_AGE(buf_priv->age);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418 ADVANCE_RING();
1419
1420 buf->pending = 1;
1421 buf->used = 0;
1422}
1423
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001424static void radeon_cp_dispatch_indirect(drm_device_t * dev,
1425 drm_buf_t * buf, int start, int end)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426{
1427 drm_radeon_private_t *dev_priv = dev->dev_private;
1428 RING_LOCALS;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001429 DRM_DEBUG("indirect: buf=%d s=0x%x e=0x%x\n", buf->idx, start, end);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001431 if (start != end) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432 int offset = (dev_priv->gart_buffers_offset
1433 + buf->offset + start);
1434 int dwords = (end - start + 3) / sizeof(u32);
1435
1436 /* Indirect buffer data must be an even number of
1437 * dwords, so if we've been given an odd number we must
1438 * pad the data with a Type-2 CP packet.
1439 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001440 if (dwords & 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441 u32 *data = (u32 *)
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001442 ((char *)dev->agp_buffer_map->handle
1443 + buf->offset + start);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444 data[dwords++] = RADEON_CP_PACKET2;
1445 }
1446
1447 /* Fire off the indirect buffer */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001448 BEGIN_RING(3);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001450 OUT_RING(CP_PACKET0(RADEON_CP_IB_BASE, 1));
1451 OUT_RING(offset);
1452 OUT_RING(dwords);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453
1454 ADVANCE_RING();
1455 }
1456}
1457
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001458static void radeon_cp_dispatch_indices(drm_device_t * dev,
1459 drm_buf_t * elt_buf,
1460 drm_radeon_tcl_prim_t * prim)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461{
1462 drm_radeon_private_t *dev_priv = dev->dev_private;
1463 drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
1464 int offset = dev_priv->gart_buffers_offset + prim->offset;
1465 u32 *data;
1466 int dwords;
1467 int i = 0;
1468 int start = prim->start + RADEON_INDEX_PRIM_OFFSET;
1469 int count = (prim->finish - start) / sizeof(u16);
1470 int nbox = sarea_priv->nbox;
1471
1472 DRM_DEBUG("hwprim 0x%x vfmt 0x%x %d..%d offset: %x nr %d\n",
1473 prim->prim,
1474 prim->vc_format,
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001475 prim->start, prim->finish, prim->offset, prim->numverts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001476
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001477 if (bad_prim_vertex_nr(prim->prim, count)) {
1478 DRM_ERROR("bad prim %x count %d\n", prim->prim, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479 return;
1480 }
1481
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001482 if (start >= prim->finish || (prim->start & 0x7)) {
1483 DRM_ERROR("buffer prim %d\n", prim->prim);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484 return;
1485 }
1486
1487 dwords = (prim->finish - prim->start + 3) / sizeof(u32);
1488
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001489 data = (u32 *) ((char *)dev->agp_buffer_map->handle +
1490 elt_buf->offset + prim->start);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001492 data[0] = CP_PACKET3(RADEON_3D_RNDR_GEN_INDX_PRIM, dwords - 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493 data[1] = offset;
1494 data[2] = prim->numverts;
1495 data[3] = prim->vc_format;
1496 data[4] = (prim->prim |
1497 RADEON_PRIM_WALK_IND |
1498 RADEON_COLOR_ORDER_RGBA |
1499 RADEON_VTX_FMT_RADEON_MODE |
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001500 (count << RADEON_NUM_VERTICES_SHIFT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001501
1502 do {
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001503 if (i < nbox)
1504 radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001505
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001506 radeon_cp_dispatch_indirect(dev, elt_buf,
1507 prim->start, prim->finish);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001508
1509 i++;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001510 } while (i < nbox);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511
1512}
1513
Dave Airlieffbbf7a2005-08-20 17:40:04 +10001514#define RADEON_MAX_TEXTURE_SIZE RADEON_BUFFER_SIZE
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001516static int radeon_cp_dispatch_texture(DRMFILE filp,
1517 drm_device_t * dev,
1518 drm_radeon_texture_t * tex,
1519 drm_radeon_tex_image_t * image)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001520{
1521 drm_radeon_private_t *dev_priv = dev->dev_private;
1522 drm_file_t *filp_priv;
1523 drm_buf_t *buf;
1524 u32 format;
1525 u32 *buffer;
1526 const u8 __user *data;
Dave Airlieffbbf7a2005-08-20 17:40:04 +10001527 int size, dwords, tex_width, blit_width, spitch;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528 u32 height;
1529 int i;
1530 u32 texpitch, microtile;
Dave Airlieffbbf7a2005-08-20 17:40:04 +10001531 u32 offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532 RING_LOCALS;
1533
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001534 DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001535
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001536 if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &tex->offset)) {
1537 DRM_ERROR("Invalid destination offset\n");
1538 return DRM_ERR(EINVAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001539 }
1540
1541 dev_priv->stats.boxes |= RADEON_BOX_TEXTURE_LOAD;
1542
1543 /* Flush the pixel cache. This ensures no pixel data gets mixed
1544 * up with the texture data from the host data blit, otherwise
1545 * part of the texture image may be corrupted.
1546 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001547 BEGIN_RING(4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548 RADEON_FLUSH_CACHE();
1549 RADEON_WAIT_UNTIL_IDLE();
1550 ADVANCE_RING();
1551
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552 /* The compiler won't optimize away a division by a variable,
1553 * even if the only legal values are powers of two. Thus, we'll
1554 * use a shift instead.
1555 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001556 switch (tex->format) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001557 case RADEON_TXFORMAT_ARGB8888:
1558 case RADEON_TXFORMAT_RGBA8888:
1559 format = RADEON_COLOR_FORMAT_ARGB8888;
1560 tex_width = tex->width * 4;
1561 blit_width = image->width * 4;
1562 break;
1563 case RADEON_TXFORMAT_AI88:
1564 case RADEON_TXFORMAT_ARGB1555:
1565 case RADEON_TXFORMAT_RGB565:
1566 case RADEON_TXFORMAT_ARGB4444:
1567 case RADEON_TXFORMAT_VYUY422:
1568 case RADEON_TXFORMAT_YVYU422:
1569 format = RADEON_COLOR_FORMAT_RGB565;
1570 tex_width = tex->width * 2;
1571 blit_width = image->width * 2;
1572 break;
1573 case RADEON_TXFORMAT_I8:
1574 case RADEON_TXFORMAT_RGB332:
1575 format = RADEON_COLOR_FORMAT_CI8;
1576 tex_width = tex->width * 1;
1577 blit_width = image->width * 1;
1578 break;
1579 default:
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001580 DRM_ERROR("invalid texture format %d\n", tex->format);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001581 return DRM_ERR(EINVAL);
1582 }
Dave Airlieffbbf7a2005-08-20 17:40:04 +10001583 spitch = blit_width >> 6;
1584 if (spitch == 0 && image->height > 1)
1585 return DRM_ERR(EINVAL);
1586
Linus Torvalds1da177e2005-04-16 15:20:36 -07001587 texpitch = tex->pitch;
1588 if ((texpitch << 22) & RADEON_DST_TILE_MICRO) {
1589 microtile = 1;
1590 if (tex_width < 64) {
1591 texpitch &= ~(RADEON_DST_TILE_MICRO >> 22);
1592 /* we got tiled coordinates, untile them */
1593 image->x *= 2;
1594 }
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001595 } else
1596 microtile = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001597
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001598 DRM_DEBUG("tex=%dx%d blit=%d\n", tex_width, tex->height, blit_width);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001599
1600 do {
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001601 DRM_DEBUG("tex: ofs=0x%x p=%d f=%d x=%hd y=%hd w=%hd h=%hd\n",
1602 tex->offset >> 10, tex->pitch, tex->format,
1603 image->x, image->y, image->width, image->height);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604
1605 /* Make a copy of some parameters in case we have to
1606 * update them for a multi-pass texture blit.
1607 */
1608 height = image->height;
1609 data = (const u8 __user *)image->data;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001610
Linus Torvalds1da177e2005-04-16 15:20:36 -07001611 size = height * blit_width;
1612
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001613 if (size > RADEON_MAX_TEXTURE_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001614 height = RADEON_MAX_TEXTURE_SIZE / blit_width;
1615 size = height * blit_width;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001616 } else if (size < 4 && size > 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617 size = 4;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001618 } else if (size == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001619 return 0;
1620 }
1621
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001622 buf = radeon_freelist_get(dev);
1623 if (0 && !buf) {
1624 radeon_do_cp_idle(dev_priv);
1625 buf = radeon_freelist_get(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626 }
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001627 if (!buf) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628 DRM_DEBUG("radeon_cp_dispatch_texture: EAGAIN\n");
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001629 if (DRM_COPY_TO_USER(tex->image, image, sizeof(*image)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001630 return DRM_ERR(EFAULT);
1631 return DRM_ERR(EAGAIN);
1632 }
1633
Linus Torvalds1da177e2005-04-16 15:20:36 -07001634 /* Dispatch the indirect buffer.
1635 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001636 buffer =
1637 (u32 *) ((char *)dev->agp_buffer_map->handle + buf->offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638 dwords = size / 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001639
1640 if (microtile) {
1641 /* texture micro tiling in use, minimum texture width is thus 16 bytes.
1642 however, we cannot use blitter directly for texture width < 64 bytes,
1643 since minimum tex pitch is 64 bytes and we need this to match
1644 the texture width, otherwise the blitter will tile it wrong.
1645 Thus, tiling manually in this case. Additionally, need to special
1646 case tex height = 1, since our actual image will have height 2
1647 and we need to ensure we don't read beyond the texture size
1648 from user space. */
1649 if (tex->height == 1) {
1650 if (tex_width >= 64 || tex_width <= 16) {
1651 if (DRM_COPY_FROM_USER(buffer, data,
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001652 tex_width *
1653 sizeof(u32))) {
1654 DRM_ERROR
1655 ("EFAULT on pad, %d bytes\n",
1656 tex_width);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657 return DRM_ERR(EFAULT);
1658 }
1659 } else if (tex_width == 32) {
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001660 if (DRM_COPY_FROM_USER
1661 (buffer, data, 16)) {
1662 DRM_ERROR
1663 ("EFAULT on pad, %d bytes\n",
1664 tex_width);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665 return DRM_ERR(EFAULT);
1666 }
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001667 if (DRM_COPY_FROM_USER
1668 (buffer + 8, data + 16, 16)) {
1669 DRM_ERROR
1670 ("EFAULT on pad, %d bytes\n",
1671 tex_width);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001672 return DRM_ERR(EFAULT);
1673 }
1674 }
1675 } else if (tex_width >= 64 || tex_width == 16) {
1676 if (DRM_COPY_FROM_USER(buffer, data,
1677 dwords * sizeof(u32))) {
1678 DRM_ERROR("EFAULT on data, %d dwords\n",
1679 dwords);
1680 return DRM_ERR(EFAULT);
1681 }
1682 } else if (tex_width < 16) {
1683 for (i = 0; i < tex->height; i++) {
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001684 if (DRM_COPY_FROM_USER
1685 (buffer, data, tex_width)) {
1686 DRM_ERROR
1687 ("EFAULT on pad, %d bytes\n",
1688 tex_width);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689 return DRM_ERR(EFAULT);
1690 }
1691 buffer += 4;
1692 data += tex_width;
1693 }
1694 } else if (tex_width == 32) {
1695 /* TODO: make sure this works when not fitting in one buffer
1696 (i.e. 32bytes x 2048...) */
1697 for (i = 0; i < tex->height; i += 2) {
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001698 if (DRM_COPY_FROM_USER
1699 (buffer, data, 16)) {
1700 DRM_ERROR
1701 ("EFAULT on pad, %d bytes\n",
1702 tex_width);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001703 return DRM_ERR(EFAULT);
1704 }
1705 data += 16;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001706 if (DRM_COPY_FROM_USER
1707 (buffer + 8, data, 16)) {
1708 DRM_ERROR
1709 ("EFAULT on pad, %d bytes\n",
1710 tex_width);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711 return DRM_ERR(EFAULT);
1712 }
1713 data += 16;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001714 if (DRM_COPY_FROM_USER
1715 (buffer + 4, data, 16)) {
1716 DRM_ERROR
1717 ("EFAULT on pad, %d bytes\n",
1718 tex_width);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001719 return DRM_ERR(EFAULT);
1720 }
1721 data += 16;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001722 if (DRM_COPY_FROM_USER
1723 (buffer + 12, data, 16)) {
1724 DRM_ERROR
1725 ("EFAULT on pad, %d bytes\n",
1726 tex_width);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001727 return DRM_ERR(EFAULT);
1728 }
1729 data += 16;
1730 buffer += 16;
1731 }
1732 }
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001733 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001734 if (tex_width >= 32) {
1735 /* Texture image width is larger than the minimum, so we
1736 * can upload it directly.
1737 */
1738 if (DRM_COPY_FROM_USER(buffer, data,
1739 dwords * sizeof(u32))) {
1740 DRM_ERROR("EFAULT on data, %d dwords\n",
1741 dwords);
1742 return DRM_ERR(EFAULT);
1743 }
1744 } else {
1745 /* Texture image width is less than the minimum, so we
1746 * need to pad out each image scanline to the minimum
1747 * width.
1748 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001749 for (i = 0; i < tex->height; i++) {
1750 if (DRM_COPY_FROM_USER
1751 (buffer, data, tex_width)) {
1752 DRM_ERROR
1753 ("EFAULT on pad, %d bytes\n",
1754 tex_width);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001755 return DRM_ERR(EFAULT);
1756 }
1757 buffer += 8;
1758 data += tex_width;
1759 }
1760 }
1761 }
1762
1763 buf->filp = filp;
Dave Airlieffbbf7a2005-08-20 17:40:04 +10001764 buf->used = size;
1765 offset = dev_priv->gart_buffers_offset + buf->offset;
1766 BEGIN_RING(9);
1767 OUT_RING(CP_PACKET3(RADEON_CNTL_BITBLT_MULTI, 5));
1768 OUT_RING(RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
1769 RADEON_GMC_DST_PITCH_OFFSET_CNTL |
1770 RADEON_GMC_BRUSH_NONE |
1771 (format << 8) |
1772 RADEON_GMC_SRC_DATATYPE_COLOR |
1773 RADEON_ROP3_S |
1774 RADEON_DP_SRC_SOURCE_MEMORY |
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001775 RADEON_GMC_CLR_CMP_CNTL_DIS | RADEON_GMC_WR_MSK_DIS);
Dave Airlieffbbf7a2005-08-20 17:40:04 +10001776 OUT_RING((spitch << 22) | (offset >> 10));
1777 OUT_RING((texpitch << 22) | (tex->offset >> 10));
1778 OUT_RING(0);
1779 OUT_RING((image->x << 16) | image->y);
1780 OUT_RING((image->width << 16) | height);
1781 RADEON_WAIT_UNTIL_2D_IDLE();
1782 ADVANCE_RING();
1783
1784 radeon_cp_discard_buffer(dev, buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001785
1786 /* Update the input parameters for next time */
1787 image->y += height;
1788 image->height -= height;
1789 image->data = (const u8 __user *)image->data + size;
1790 } while (image->height > 0);
1791
1792 /* Flush the pixel cache after the blit completes. This ensures
1793 * the texture data is written out to memory before rendering
1794 * continues.
1795 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001796 BEGIN_RING(4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001797 RADEON_FLUSH_CACHE();
1798 RADEON_WAIT_UNTIL_2D_IDLE();
1799 ADVANCE_RING();
1800 return 0;
1801}
1802
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001803static void radeon_cp_dispatch_stipple(drm_device_t * dev, u32 * stipple)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001804{
1805 drm_radeon_private_t *dev_priv = dev->dev_private;
1806 int i;
1807 RING_LOCALS;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001808 DRM_DEBUG("\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001809
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001810 BEGIN_RING(35);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001811
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001812 OUT_RING(CP_PACKET0(RADEON_RE_STIPPLE_ADDR, 0));
1813 OUT_RING(0x00000000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001814
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001815 OUT_RING(CP_PACKET0_TABLE(RADEON_RE_STIPPLE_DATA, 31));
1816 for (i = 0; i < 32; i++) {
1817 OUT_RING(stipple[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001818 }
1819
1820 ADVANCE_RING();
1821}
1822
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001823static void radeon_apply_surface_regs(int surf_index,
1824 drm_radeon_private_t * dev_priv)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001825{
1826 if (!dev_priv->mmio)
1827 return;
1828
1829 radeon_do_cp_idle(dev_priv);
1830
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001831 RADEON_WRITE(RADEON_SURFACE0_INFO + 16 * surf_index,
1832 dev_priv->surfaces[surf_index].flags);
1833 RADEON_WRITE(RADEON_SURFACE0_LOWER_BOUND + 16 * surf_index,
1834 dev_priv->surfaces[surf_index].lower);
1835 RADEON_WRITE(RADEON_SURFACE0_UPPER_BOUND + 16 * surf_index,
1836 dev_priv->surfaces[surf_index].upper);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001837}
1838
Linus Torvalds1da177e2005-04-16 15:20:36 -07001839/* Allocates a virtual surface
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001840 * doesn't always allocate a real surface, will stretch an existing
Linus Torvalds1da177e2005-04-16 15:20:36 -07001841 * surface when possible.
1842 *
1843 * Note that refcount can be at most 2, since during a free refcount=3
1844 * might mean we have to allocate a new surface which might not always
1845 * be available.
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001846 * For example : we allocate three contigous surfaces ABC. If B is
Linus Torvalds1da177e2005-04-16 15:20:36 -07001847 * freed, we suddenly need two surfaces to store A and C, which might
1848 * not always be available.
1849 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001850static int alloc_surface(drm_radeon_surface_alloc_t * new,
1851 drm_radeon_private_t * dev_priv, DRMFILE filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852{
1853 struct radeon_virt_surface *s;
1854 int i;
1855 int virt_surface_index;
1856 uint32_t new_upper, new_lower;
1857
1858 new_lower = new->address;
1859 new_upper = new_lower + new->size - 1;
1860
1861 /* sanity check */
1862 if ((new_lower >= new_upper) || (new->flags == 0) || (new->size == 0) ||
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001863 ((new_upper & RADEON_SURF_ADDRESS_FIXED_MASK) !=
1864 RADEON_SURF_ADDRESS_FIXED_MASK)
1865 || ((new_lower & RADEON_SURF_ADDRESS_FIXED_MASK) != 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001866 return -1;
1867
1868 /* make sure there is no overlap with existing surfaces */
1869 for (i = 0; i < RADEON_MAX_SURFACES; i++) {
1870 if ((dev_priv->surfaces[i].refcount != 0) &&
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001871 (((new_lower >= dev_priv->surfaces[i].lower) &&
1872 (new_lower < dev_priv->surfaces[i].upper)) ||
1873 ((new_lower < dev_priv->surfaces[i].lower) &&
1874 (new_upper > dev_priv->surfaces[i].lower)))) {
1875 return -1;
1876 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001877 }
1878
1879 /* find a virtual surface */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001880 for (i = 0; i < 2 * RADEON_MAX_SURFACES; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001881 if (dev_priv->virt_surfaces[i].filp == 0)
1882 break;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001883 if (i == 2 * RADEON_MAX_SURFACES) {
1884 return -1;
1885 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001886 virt_surface_index = i;
1887
1888 /* try to reuse an existing surface */
1889 for (i = 0; i < RADEON_MAX_SURFACES; i++) {
1890 /* extend before */
1891 if ((dev_priv->surfaces[i].refcount == 1) &&
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001892 (new->flags == dev_priv->surfaces[i].flags) &&
1893 (new_upper + 1 == dev_priv->surfaces[i].lower)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001894 s = &(dev_priv->virt_surfaces[virt_surface_index]);
1895 s->surface_index = i;
1896 s->lower = new_lower;
1897 s->upper = new_upper;
1898 s->flags = new->flags;
1899 s->filp = filp;
1900 dev_priv->surfaces[i].refcount++;
1901 dev_priv->surfaces[i].lower = s->lower;
1902 radeon_apply_surface_regs(s->surface_index, dev_priv);
1903 return virt_surface_index;
1904 }
1905
1906 /* extend after */
1907 if ((dev_priv->surfaces[i].refcount == 1) &&
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001908 (new->flags == dev_priv->surfaces[i].flags) &&
1909 (new_lower == dev_priv->surfaces[i].upper + 1)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001910 s = &(dev_priv->virt_surfaces[virt_surface_index]);
1911 s->surface_index = i;
1912 s->lower = new_lower;
1913 s->upper = new_upper;
1914 s->flags = new->flags;
1915 s->filp = filp;
1916 dev_priv->surfaces[i].refcount++;
1917 dev_priv->surfaces[i].upper = s->upper;
1918 radeon_apply_surface_regs(s->surface_index, dev_priv);
1919 return virt_surface_index;
1920 }
1921 }
1922
1923 /* okay, we need a new one */
1924 for (i = 0; i < RADEON_MAX_SURFACES; i++) {
1925 if (dev_priv->surfaces[i].refcount == 0) {
1926 s = &(dev_priv->virt_surfaces[virt_surface_index]);
1927 s->surface_index = i;
1928 s->lower = new_lower;
1929 s->upper = new_upper;
1930 s->flags = new->flags;
1931 s->filp = filp;
1932 dev_priv->surfaces[i].refcount = 1;
1933 dev_priv->surfaces[i].lower = s->lower;
1934 dev_priv->surfaces[i].upper = s->upper;
1935 dev_priv->surfaces[i].flags = s->flags;
1936 radeon_apply_surface_regs(s->surface_index, dev_priv);
1937 return virt_surface_index;
1938 }
1939 }
1940
1941 /* we didn't find anything */
1942 return -1;
1943}
1944
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001945static int free_surface(DRMFILE filp, drm_radeon_private_t * dev_priv,
1946 int lower)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001947{
1948 struct radeon_virt_surface *s;
1949 int i;
1950 /* find the virtual surface */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001951 for (i = 0; i < 2 * RADEON_MAX_SURFACES; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001952 s = &(dev_priv->virt_surfaces[i]);
1953 if (s->filp) {
1954 if ((lower == s->lower) && (filp == s->filp)) {
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001955 if (dev_priv->surfaces[s->surface_index].
1956 lower == s->lower)
1957 dev_priv->surfaces[s->surface_index].
1958 lower = s->upper;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001959
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001960 if (dev_priv->surfaces[s->surface_index].
1961 upper == s->upper)
1962 dev_priv->surfaces[s->surface_index].
1963 upper = s->lower;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001964
1965 dev_priv->surfaces[s->surface_index].refcount--;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001966 if (dev_priv->surfaces[s->surface_index].
1967 refcount == 0)
1968 dev_priv->surfaces[s->surface_index].
1969 flags = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001970 s->filp = NULL;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001971 radeon_apply_surface_regs(s->surface_index,
1972 dev_priv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001973 return 0;
1974 }
1975 }
1976 }
1977 return 1;
1978}
1979
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001980static void radeon_surfaces_release(DRMFILE filp,
1981 drm_radeon_private_t * dev_priv)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001982{
1983 int i;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001984 for (i = 0; i < 2 * RADEON_MAX_SURFACES; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985 if (dev_priv->virt_surfaces[i].filp == filp)
Dave Airlieb5e89ed2005-09-25 14:28:13 +10001986 free_surface(filp, dev_priv,
1987 dev_priv->virt_surfaces[i].lower);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001988 }
1989}
1990
1991/* ================================================================
1992 * IOCTL functions
1993 */
1994static int radeon_surface_alloc(DRM_IOCTL_ARGS)
1995{
1996 DRM_DEVICE;
1997 drm_radeon_private_t *dev_priv = dev->dev_private;
1998 drm_radeon_surface_alloc_t alloc;
1999
2000 if (!dev_priv) {
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002001 DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002002 return DRM_ERR(EINVAL);
2003 }
2004
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002005 DRM_COPY_FROM_USER_IOCTL(alloc,
2006 (drm_radeon_surface_alloc_t __user *) data,
2007 sizeof(alloc));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002008
2009 if (alloc_surface(&alloc, dev_priv, filp) == -1)
2010 return DRM_ERR(EINVAL);
2011 else
2012 return 0;
2013}
2014
2015static int radeon_surface_free(DRM_IOCTL_ARGS)
2016{
2017 DRM_DEVICE;
2018 drm_radeon_private_t *dev_priv = dev->dev_private;
2019 drm_radeon_surface_free_t memfree;
2020
2021 if (!dev_priv) {
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002022 DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002023 return DRM_ERR(EINVAL);
2024 }
2025
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002026 DRM_COPY_FROM_USER_IOCTL(memfree, (drm_radeon_mem_free_t __user *) data,
2027 sizeof(memfree));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002028
2029 if (free_surface(filp, dev_priv, memfree.address))
2030 return DRM_ERR(EINVAL);
2031 else
2032 return 0;
2033}
2034
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002035static int radeon_cp_clear(DRM_IOCTL_ARGS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002036{
2037 DRM_DEVICE;
2038 drm_radeon_private_t *dev_priv = dev->dev_private;
2039 drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
2040 drm_radeon_clear_t clear;
2041 drm_radeon_clear_rect_t depth_boxes[RADEON_NR_SAREA_CLIPRECTS];
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002042 DRM_DEBUG("\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002043
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002044 LOCK_TEST_WITH_RETURN(dev, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002045
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002046 DRM_COPY_FROM_USER_IOCTL(clear, (drm_radeon_clear_t __user *) data,
2047 sizeof(clear));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002048
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002049 RING_SPACE_TEST_WITH_RETURN(dev_priv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002050
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002051 if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002052 sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
2053
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002054 if (DRM_COPY_FROM_USER(&depth_boxes, clear.depth_boxes,
2055 sarea_priv->nbox * sizeof(depth_boxes[0])))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002056 return DRM_ERR(EFAULT);
2057
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002058 radeon_cp_dispatch_clear(dev, &clear, depth_boxes);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002059
2060 COMMIT_RING();
2061 return 0;
2062}
2063
Linus Torvalds1da177e2005-04-16 15:20:36 -07002064/* Not sure why this isn't set all the time:
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002065 */
2066static int radeon_do_init_pageflip(drm_device_t * dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002067{
2068 drm_radeon_private_t *dev_priv = dev->dev_private;
2069 RING_LOCALS;
2070
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002071 DRM_DEBUG("\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002072
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002073 BEGIN_RING(6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002074 RADEON_WAIT_UNTIL_3D_IDLE();
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002075 OUT_RING(CP_PACKET0(RADEON_CRTC_OFFSET_CNTL, 0));
2076 OUT_RING(RADEON_READ(RADEON_CRTC_OFFSET_CNTL) |
2077 RADEON_CRTC_OFFSET_FLIP_CNTL);
2078 OUT_RING(CP_PACKET0(RADEON_CRTC2_OFFSET_CNTL, 0));
2079 OUT_RING(RADEON_READ(RADEON_CRTC2_OFFSET_CNTL) |
2080 RADEON_CRTC_OFFSET_FLIP_CNTL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002081 ADVANCE_RING();
2082
2083 dev_priv->page_flipping = 1;
2084 dev_priv->current_page = 0;
2085 dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page;
2086
2087 return 0;
2088}
2089
2090/* Called whenever a client dies, from drm_release.
2091 * NOTE: Lock isn't necessarily held when this is called!
2092 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002093static int radeon_do_cleanup_pageflip(drm_device_t * dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002094{
2095 drm_radeon_private_t *dev_priv = dev->dev_private;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002096 DRM_DEBUG("\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002097
2098 if (dev_priv->current_page != 0)
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002099 radeon_cp_dispatch_flip(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002100
2101 dev_priv->page_flipping = 0;
2102 return 0;
2103}
2104
2105/* Swapping and flipping are different operations, need different ioctls.
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002106 * They can & should be intermixed to support multiple 3d windows.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002107 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002108static int radeon_cp_flip(DRM_IOCTL_ARGS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002109{
2110 DRM_DEVICE;
2111 drm_radeon_private_t *dev_priv = dev->dev_private;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002112 DRM_DEBUG("\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002113
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002114 LOCK_TEST_WITH_RETURN(dev, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002115
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002116 RING_SPACE_TEST_WITH_RETURN(dev_priv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002117
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002118 if (!dev_priv->page_flipping)
2119 radeon_do_init_pageflip(dev);
2120
2121 radeon_cp_dispatch_flip(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002122
2123 COMMIT_RING();
2124 return 0;
2125}
2126
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002127static int radeon_cp_swap(DRM_IOCTL_ARGS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002128{
2129 DRM_DEVICE;
2130 drm_radeon_private_t *dev_priv = dev->dev_private;
2131 drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002132 DRM_DEBUG("\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002133
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002134 LOCK_TEST_WITH_RETURN(dev, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002135
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002136 RING_SPACE_TEST_WITH_RETURN(dev_priv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002137
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002138 if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002139 sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
2140
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002141 radeon_cp_dispatch_swap(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002142 dev_priv->sarea_priv->ctx_owner = 0;
2143
2144 COMMIT_RING();
2145 return 0;
2146}
2147
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002148static int radeon_cp_vertex(DRM_IOCTL_ARGS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002149{
2150 DRM_DEVICE;
2151 drm_radeon_private_t *dev_priv = dev->dev_private;
2152 drm_file_t *filp_priv;
2153 drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
2154 drm_device_dma_t *dma = dev->dma;
2155 drm_buf_t *buf;
2156 drm_radeon_vertex_t vertex;
2157 drm_radeon_tcl_prim_t prim;
2158
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002159 LOCK_TEST_WITH_RETURN(dev, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002160
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002161 DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002162
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002163 DRM_COPY_FROM_USER_IOCTL(vertex, (drm_radeon_vertex_t __user *) data,
2164 sizeof(vertex));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002165
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002166 DRM_DEBUG("pid=%d index=%d count=%d discard=%d\n",
2167 DRM_CURRENTPID, vertex.idx, vertex.count, vertex.discard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002168
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002169 if (vertex.idx < 0 || vertex.idx >= dma->buf_count) {
2170 DRM_ERROR("buffer index %d (of %d max)\n",
2171 vertex.idx, dma->buf_count - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002172 return DRM_ERR(EINVAL);
2173 }
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002174 if (vertex.prim < 0 || vertex.prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST) {
2175 DRM_ERROR("buffer prim %d\n", vertex.prim);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002176 return DRM_ERR(EINVAL);
2177 }
2178
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002179 RING_SPACE_TEST_WITH_RETURN(dev_priv);
2180 VB_AGE_TEST_WITH_RETURN(dev_priv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002181
2182 buf = dma->buflist[vertex.idx];
2183
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002184 if (buf->filp != filp) {
2185 DRM_ERROR("process %d using buffer owned by %p\n",
2186 DRM_CURRENTPID, buf->filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002187 return DRM_ERR(EINVAL);
2188 }
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002189 if (buf->pending) {
2190 DRM_ERROR("sending pending buffer %d\n", vertex.idx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002191 return DRM_ERR(EINVAL);
2192 }
2193
2194 /* Build up a prim_t record:
2195 */
2196 if (vertex.count) {
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002197 buf->used = vertex.count; /* not used? */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002198
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002199 if (sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS) {
2200 if (radeon_emit_state(dev_priv, filp_priv,
2201 &sarea_priv->context_state,
2202 sarea_priv->tex_state,
2203 sarea_priv->dirty)) {
2204 DRM_ERROR("radeon_emit_state failed\n");
2205 return DRM_ERR(EINVAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002206 }
2207
2208 sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES |
2209 RADEON_UPLOAD_TEX1IMAGES |
2210 RADEON_UPLOAD_TEX2IMAGES |
2211 RADEON_REQUIRE_QUIESCENCE);
2212 }
2213
2214 prim.start = 0;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002215 prim.finish = vertex.count; /* unused */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002216 prim.prim = vertex.prim;
2217 prim.numverts = vertex.count;
2218 prim.vc_format = dev_priv->sarea_priv->vc_format;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002219
2220 radeon_cp_dispatch_vertex(dev, buf, &prim);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002221 }
2222
2223 if (vertex.discard) {
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002224 radeon_cp_discard_buffer(dev, buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002225 }
2226
2227 COMMIT_RING();
2228 return 0;
2229}
2230
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002231static int radeon_cp_indices(DRM_IOCTL_ARGS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002232{
2233 DRM_DEVICE;
2234 drm_radeon_private_t *dev_priv = dev->dev_private;
2235 drm_file_t *filp_priv;
2236 drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
2237 drm_device_dma_t *dma = dev->dma;
2238 drm_buf_t *buf;
2239 drm_radeon_indices_t elts;
2240 drm_radeon_tcl_prim_t prim;
2241 int count;
2242
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002243 LOCK_TEST_WITH_RETURN(dev, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002244
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002245 if (!dev_priv) {
2246 DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002247 return DRM_ERR(EINVAL);
2248 }
2249
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002250 DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002251
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002252 DRM_COPY_FROM_USER_IOCTL(elts, (drm_radeon_indices_t __user *) data,
2253 sizeof(elts));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002254
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002255 DRM_DEBUG("pid=%d index=%d start=%d end=%d discard=%d\n",
2256 DRM_CURRENTPID, elts.idx, elts.start, elts.end, elts.discard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002257
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002258 if (elts.idx < 0 || elts.idx >= dma->buf_count) {
2259 DRM_ERROR("buffer index %d (of %d max)\n",
2260 elts.idx, dma->buf_count - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002261 return DRM_ERR(EINVAL);
2262 }
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002263 if (elts.prim < 0 || elts.prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST) {
2264 DRM_ERROR("buffer prim %d\n", elts.prim);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002265 return DRM_ERR(EINVAL);
2266 }
2267
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002268 RING_SPACE_TEST_WITH_RETURN(dev_priv);
2269 VB_AGE_TEST_WITH_RETURN(dev_priv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002270
2271 buf = dma->buflist[elts.idx];
2272
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002273 if (buf->filp != filp) {
2274 DRM_ERROR("process %d using buffer owned by %p\n",
2275 DRM_CURRENTPID, buf->filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002276 return DRM_ERR(EINVAL);
2277 }
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002278 if (buf->pending) {
2279 DRM_ERROR("sending pending buffer %d\n", elts.idx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002280 return DRM_ERR(EINVAL);
2281 }
2282
2283 count = (elts.end - elts.start) / sizeof(u16);
2284 elts.start -= RADEON_INDEX_PRIM_OFFSET;
2285
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002286 if (elts.start & 0x7) {
2287 DRM_ERROR("misaligned buffer 0x%x\n", elts.start);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002288 return DRM_ERR(EINVAL);
2289 }
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002290 if (elts.start < buf->used) {
2291 DRM_ERROR("no header 0x%x - 0x%x\n", elts.start, buf->used);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002292 return DRM_ERR(EINVAL);
2293 }
2294
2295 buf->used = elts.end;
2296
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002297 if (sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS) {
2298 if (radeon_emit_state(dev_priv, filp_priv,
2299 &sarea_priv->context_state,
2300 sarea_priv->tex_state,
2301 sarea_priv->dirty)) {
2302 DRM_ERROR("radeon_emit_state failed\n");
2303 return DRM_ERR(EINVAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002304 }
2305
2306 sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES |
2307 RADEON_UPLOAD_TEX1IMAGES |
2308 RADEON_UPLOAD_TEX2IMAGES |
2309 RADEON_REQUIRE_QUIESCENCE);
2310 }
2311
Linus Torvalds1da177e2005-04-16 15:20:36 -07002312 /* Build up a prim_t record:
2313 */
2314 prim.start = elts.start;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002315 prim.finish = elts.end;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002316 prim.prim = elts.prim;
2317 prim.offset = 0; /* offset from start of dma buffers */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002318 prim.numverts = RADEON_MAX_VB_VERTS; /* duh */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002319 prim.vc_format = dev_priv->sarea_priv->vc_format;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002320
2321 radeon_cp_dispatch_indices(dev, buf, &prim);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002322 if (elts.discard) {
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002323 radeon_cp_discard_buffer(dev, buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002324 }
2325
2326 COMMIT_RING();
2327 return 0;
2328}
2329
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002330static int radeon_cp_texture(DRM_IOCTL_ARGS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002331{
2332 DRM_DEVICE;
2333 drm_radeon_private_t *dev_priv = dev->dev_private;
2334 drm_radeon_texture_t tex;
2335 drm_radeon_tex_image_t image;
2336 int ret;
2337
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002338 LOCK_TEST_WITH_RETURN(dev, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002339
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002340 DRM_COPY_FROM_USER_IOCTL(tex, (drm_radeon_texture_t __user *) data,
2341 sizeof(tex));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002342
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002343 if (tex.image == NULL) {
2344 DRM_ERROR("null texture image!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002345 return DRM_ERR(EINVAL);
2346 }
2347
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002348 if (DRM_COPY_FROM_USER(&image,
2349 (drm_radeon_tex_image_t __user *) tex.image,
2350 sizeof(image)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002351 return DRM_ERR(EFAULT);
2352
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002353 RING_SPACE_TEST_WITH_RETURN(dev_priv);
2354 VB_AGE_TEST_WITH_RETURN(dev_priv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002355
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002356 ret = radeon_cp_dispatch_texture(filp, dev, &tex, &image);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002357
2358 COMMIT_RING();
2359 return ret;
2360}
2361
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002362static int radeon_cp_stipple(DRM_IOCTL_ARGS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002363{
2364 DRM_DEVICE;
2365 drm_radeon_private_t *dev_priv = dev->dev_private;
2366 drm_radeon_stipple_t stipple;
2367 u32 mask[32];
2368
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002369 LOCK_TEST_WITH_RETURN(dev, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002370
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002371 DRM_COPY_FROM_USER_IOCTL(stipple, (drm_radeon_stipple_t __user *) data,
2372 sizeof(stipple));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002373
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002374 if (DRM_COPY_FROM_USER(&mask, stipple.mask, 32 * sizeof(u32)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002375 return DRM_ERR(EFAULT);
2376
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002377 RING_SPACE_TEST_WITH_RETURN(dev_priv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002378
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002379 radeon_cp_dispatch_stipple(dev, mask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002380
2381 COMMIT_RING();
2382 return 0;
2383}
2384
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002385static int radeon_cp_indirect(DRM_IOCTL_ARGS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002386{
2387 DRM_DEVICE;
2388 drm_radeon_private_t *dev_priv = dev->dev_private;
2389 drm_device_dma_t *dma = dev->dma;
2390 drm_buf_t *buf;
2391 drm_radeon_indirect_t indirect;
2392 RING_LOCALS;
2393
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002394 LOCK_TEST_WITH_RETURN(dev, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002395
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002396 if (!dev_priv) {
2397 DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002398 return DRM_ERR(EINVAL);
2399 }
2400
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002401 DRM_COPY_FROM_USER_IOCTL(indirect,
2402 (drm_radeon_indirect_t __user *) data,
2403 sizeof(indirect));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002404
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002405 DRM_DEBUG("indirect: idx=%d s=%d e=%d d=%d\n",
2406 indirect.idx, indirect.start, indirect.end, indirect.discard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002407
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002408 if (indirect.idx < 0 || indirect.idx >= dma->buf_count) {
2409 DRM_ERROR("buffer index %d (of %d max)\n",
2410 indirect.idx, dma->buf_count - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002411 return DRM_ERR(EINVAL);
2412 }
2413
2414 buf = dma->buflist[indirect.idx];
2415
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002416 if (buf->filp != filp) {
2417 DRM_ERROR("process %d using buffer owned by %p\n",
2418 DRM_CURRENTPID, buf->filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002419 return DRM_ERR(EINVAL);
2420 }
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002421 if (buf->pending) {
2422 DRM_ERROR("sending pending buffer %d\n", indirect.idx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002423 return DRM_ERR(EINVAL);
2424 }
2425
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002426 if (indirect.start < buf->used) {
2427 DRM_ERROR("reusing indirect: start=0x%x actual=0x%x\n",
2428 indirect.start, buf->used);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002429 return DRM_ERR(EINVAL);
2430 }
2431
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002432 RING_SPACE_TEST_WITH_RETURN(dev_priv);
2433 VB_AGE_TEST_WITH_RETURN(dev_priv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002434
2435 buf->used = indirect.end;
2436
2437 /* Wait for the 3D stream to idle before the indirect buffer
2438 * containing 2D acceleration commands is processed.
2439 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002440 BEGIN_RING(2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002441
2442 RADEON_WAIT_UNTIL_3D_IDLE();
2443
2444 ADVANCE_RING();
2445
2446 /* Dispatch the indirect buffer full of commands from the
2447 * X server. This is insecure and is thus only available to
2448 * privileged clients.
2449 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002450 radeon_cp_dispatch_indirect(dev, buf, indirect.start, indirect.end);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002451 if (indirect.discard) {
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002452 radeon_cp_discard_buffer(dev, buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002453 }
2454
Linus Torvalds1da177e2005-04-16 15:20:36 -07002455 COMMIT_RING();
2456 return 0;
2457}
2458
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002459static int radeon_cp_vertex2(DRM_IOCTL_ARGS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002460{
2461 DRM_DEVICE;
2462 drm_radeon_private_t *dev_priv = dev->dev_private;
2463 drm_file_t *filp_priv;
2464 drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
2465 drm_device_dma_t *dma = dev->dma;
2466 drm_buf_t *buf;
2467 drm_radeon_vertex2_t vertex;
2468 int i;
2469 unsigned char laststate;
2470
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002471 LOCK_TEST_WITH_RETURN(dev, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002472
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002473 if (!dev_priv) {
2474 DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002475 return DRM_ERR(EINVAL);
2476 }
2477
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002478 DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002479
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002480 DRM_COPY_FROM_USER_IOCTL(vertex, (drm_radeon_vertex2_t __user *) data,
2481 sizeof(vertex));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002482
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002483 DRM_DEBUG("pid=%d index=%d discard=%d\n",
2484 DRM_CURRENTPID, vertex.idx, vertex.discard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002485
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002486 if (vertex.idx < 0 || vertex.idx >= dma->buf_count) {
2487 DRM_ERROR("buffer index %d (of %d max)\n",
2488 vertex.idx, dma->buf_count - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002489 return DRM_ERR(EINVAL);
2490 }
2491
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002492 RING_SPACE_TEST_WITH_RETURN(dev_priv);
2493 VB_AGE_TEST_WITH_RETURN(dev_priv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002494
2495 buf = dma->buflist[vertex.idx];
2496
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002497 if (buf->filp != filp) {
2498 DRM_ERROR("process %d using buffer owned by %p\n",
2499 DRM_CURRENTPID, buf->filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002500 return DRM_ERR(EINVAL);
2501 }
2502
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002503 if (buf->pending) {
2504 DRM_ERROR("sending pending buffer %d\n", vertex.idx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002505 return DRM_ERR(EINVAL);
2506 }
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002507
Linus Torvalds1da177e2005-04-16 15:20:36 -07002508 if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS)
2509 return DRM_ERR(EINVAL);
2510
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002511 for (laststate = 0xff, i = 0; i < vertex.nr_prims; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002512 drm_radeon_prim_t prim;
2513 drm_radeon_tcl_prim_t tclprim;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002514
2515 if (DRM_COPY_FROM_USER(&prim, &vertex.prim[i], sizeof(prim)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002516 return DRM_ERR(EFAULT);
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002517
2518 if (prim.stateidx != laststate) {
2519 drm_radeon_state_t state;
2520
2521 if (DRM_COPY_FROM_USER(&state,
2522 &vertex.state[prim.stateidx],
2523 sizeof(state)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002524 return DRM_ERR(EFAULT);
2525
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002526 if (radeon_emit_state2(dev_priv, filp_priv, &state)) {
2527 DRM_ERROR("radeon_emit_state2 failed\n");
2528 return DRM_ERR(EINVAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002529 }
2530
2531 laststate = prim.stateidx;
2532 }
2533
2534 tclprim.start = prim.start;
2535 tclprim.finish = prim.finish;
2536 tclprim.prim = prim.prim;
2537 tclprim.vc_format = prim.vc_format;
2538
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002539 if (prim.prim & RADEON_PRIM_WALK_IND) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002540 tclprim.offset = prim.numverts * 64;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002541 tclprim.numverts = RADEON_MAX_VB_VERTS; /* duh */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002542
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002543 radeon_cp_dispatch_indices(dev, buf, &tclprim);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002544 } else {
2545 tclprim.numverts = prim.numverts;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002546 tclprim.offset = 0; /* not used */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002547
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002548 radeon_cp_dispatch_vertex(dev, buf, &tclprim);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002549 }
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002550
Linus Torvalds1da177e2005-04-16 15:20:36 -07002551 if (sarea_priv->nbox == 1)
2552 sarea_priv->nbox = 0;
2553 }
2554
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002555 if (vertex.discard) {
2556 radeon_cp_discard_buffer(dev, buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002557 }
2558
2559 COMMIT_RING();
2560 return 0;
2561}
2562
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002563static int radeon_emit_packets(drm_radeon_private_t * dev_priv,
2564 drm_file_t * filp_priv,
2565 drm_radeon_cmd_header_t header,
Dave Airlieb3a83632005-09-30 18:37:36 +10002566 drm_radeon_kcmd_buffer_t *cmdbuf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002567{
2568 int id = (int)header.packet.packet_id;
2569 int sz, reg;
2570 int *data = (int *)cmdbuf->buf;
2571 RING_LOCALS;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002572
Linus Torvalds1da177e2005-04-16 15:20:36 -07002573 if (id >= RADEON_MAX_STATE_PACKETS)
2574 return DRM_ERR(EINVAL);
2575
2576 sz = packet[id].len;
2577 reg = packet[id].start;
2578
2579 if (sz * sizeof(int) > cmdbuf->bufsz) {
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002580 DRM_ERROR("Packet size provided larger than data provided\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002581 return DRM_ERR(EINVAL);
2582 }
2583
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002584 if (radeon_check_and_fixup_packets(dev_priv, filp_priv, id, data)) {
2585 DRM_ERROR("Packet verification failed\n");
2586 return DRM_ERR(EINVAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002587 }
2588
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002589 BEGIN_RING(sz + 1);
2590 OUT_RING(CP_PACKET0(reg, (sz - 1)));
2591 OUT_RING_TABLE(data, sz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002592 ADVANCE_RING();
2593
2594 cmdbuf->buf += sz * sizeof(int);
2595 cmdbuf->bufsz -= sz * sizeof(int);
2596 return 0;
2597}
2598
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002599static __inline__ int radeon_emit_scalars(drm_radeon_private_t * dev_priv,
2600 drm_radeon_cmd_header_t header,
Dave Airlieb3a83632005-09-30 18:37:36 +10002601 drm_radeon_kcmd_buffer_t * cmdbuf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002602{
2603 int sz = header.scalars.count;
2604 int start = header.scalars.offset;
2605 int stride = header.scalars.stride;
2606 RING_LOCALS;
2607
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002608 BEGIN_RING(3 + sz);
2609 OUT_RING(CP_PACKET0(RADEON_SE_TCL_SCALAR_INDX_REG, 0));
2610 OUT_RING(start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT));
2611 OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_SCALAR_DATA_REG, sz - 1));
2612 OUT_RING_TABLE(cmdbuf->buf, sz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002613 ADVANCE_RING();
2614 cmdbuf->buf += sz * sizeof(int);
2615 cmdbuf->bufsz -= sz * sizeof(int);
2616 return 0;
2617}
2618
2619/* God this is ugly
2620 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002621static __inline__ int radeon_emit_scalars2(drm_radeon_private_t * dev_priv,
2622 drm_radeon_cmd_header_t header,
Dave Airlieb3a83632005-09-30 18:37:36 +10002623 drm_radeon_kcmd_buffer_t * cmdbuf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002624{
2625 int sz = header.scalars.count;
2626 int start = ((unsigned int)header.scalars.offset) + 0x100;
2627 int stride = header.scalars.stride;
2628 RING_LOCALS;
2629
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002630 BEGIN_RING(3 + sz);
2631 OUT_RING(CP_PACKET0(RADEON_SE_TCL_SCALAR_INDX_REG, 0));
2632 OUT_RING(start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT));
2633 OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_SCALAR_DATA_REG, sz - 1));
2634 OUT_RING_TABLE(cmdbuf->buf, sz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002635 ADVANCE_RING();
2636 cmdbuf->buf += sz * sizeof(int);
2637 cmdbuf->bufsz -= sz * sizeof(int);
2638 return 0;
2639}
2640
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002641static __inline__ int radeon_emit_vectors(drm_radeon_private_t * dev_priv,
2642 drm_radeon_cmd_header_t header,
Dave Airlieb3a83632005-09-30 18:37:36 +10002643 drm_radeon_kcmd_buffer_t * cmdbuf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002644{
2645 int sz = header.vectors.count;
2646 int start = header.vectors.offset;
2647 int stride = header.vectors.stride;
2648 RING_LOCALS;
2649
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002650 BEGIN_RING(3 + sz);
2651 OUT_RING(CP_PACKET0(RADEON_SE_TCL_VECTOR_INDX_REG, 0));
2652 OUT_RING(start | (stride << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT));
2653 OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1)));
2654 OUT_RING_TABLE(cmdbuf->buf, sz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002655 ADVANCE_RING();
2656
2657 cmdbuf->buf += sz * sizeof(int);
2658 cmdbuf->bufsz -= sz * sizeof(int);
2659 return 0;
2660}
2661
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002662static int radeon_emit_packet3(drm_device_t * dev,
2663 drm_file_t * filp_priv,
Dave Airlieb3a83632005-09-30 18:37:36 +10002664 drm_radeon_kcmd_buffer_t *cmdbuf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002665{
2666 drm_radeon_private_t *dev_priv = dev->dev_private;
2667 unsigned int cmdsz;
2668 int ret;
2669 RING_LOCALS;
2670
2671 DRM_DEBUG("\n");
2672
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002673 if ((ret = radeon_check_and_fixup_packet3(dev_priv, filp_priv,
2674 cmdbuf, &cmdsz))) {
2675 DRM_ERROR("Packet verification failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002676 return ret;
2677 }
2678
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002679 BEGIN_RING(cmdsz);
2680 OUT_RING_TABLE(cmdbuf->buf, cmdsz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002681 ADVANCE_RING();
2682
2683 cmdbuf->buf += cmdsz * 4;
2684 cmdbuf->bufsz -= cmdsz * 4;
2685 return 0;
2686}
2687
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002688static int radeon_emit_packet3_cliprect(drm_device_t * dev,
2689 drm_file_t * filp_priv,
Dave Airlieb3a83632005-09-30 18:37:36 +10002690 drm_radeon_kcmd_buffer_t *cmdbuf,
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002691 int orig_nbox)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002692{
2693 drm_radeon_private_t *dev_priv = dev->dev_private;
2694 drm_clip_rect_t box;
2695 unsigned int cmdsz;
2696 int ret;
2697 drm_clip_rect_t __user *boxes = cmdbuf->boxes;
2698 int i = 0;
2699 RING_LOCALS;
2700
2701 DRM_DEBUG("\n");
2702
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002703 if ((ret = radeon_check_and_fixup_packet3(dev_priv, filp_priv,
2704 cmdbuf, &cmdsz))) {
2705 DRM_ERROR("Packet verification failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002706 return ret;
2707 }
2708
2709 if (!orig_nbox)
2710 goto out;
2711
2712 do {
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002713 if (i < cmdbuf->nbox) {
2714 if (DRM_COPY_FROM_USER(&box, &boxes[i], sizeof(box)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002715 return DRM_ERR(EFAULT);
2716 /* FIXME The second and subsequent times round
2717 * this loop, send a WAIT_UNTIL_3D_IDLE before
2718 * calling emit_clip_rect(). This fixes a
2719 * lockup on fast machines when sending
2720 * several cliprects with a cmdbuf, as when
2721 * waving a 2D window over a 3D
2722 * window. Something in the commands from user
2723 * space seems to hang the card when they're
2724 * sent several times in a row. That would be
2725 * the correct place to fix it but this works
2726 * around it until I can figure that out - Tim
2727 * Smith */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002728 if (i) {
2729 BEGIN_RING(2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002730 RADEON_WAIT_UNTIL_3D_IDLE();
2731 ADVANCE_RING();
2732 }
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002733 radeon_emit_clip_rect(dev_priv, &box);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002734 }
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002735
2736 BEGIN_RING(cmdsz);
2737 OUT_RING_TABLE(cmdbuf->buf, cmdsz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002738 ADVANCE_RING();
2739
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002740 } while (++i < cmdbuf->nbox);
2741 if (cmdbuf->nbox == 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002742 cmdbuf->nbox = 0;
2743
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002744 out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002745 cmdbuf->buf += cmdsz * 4;
2746 cmdbuf->bufsz -= cmdsz * 4;
2747 return 0;
2748}
2749
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002750static int radeon_emit_wait(drm_device_t * dev, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002751{
2752 drm_radeon_private_t *dev_priv = dev->dev_private;
2753 RING_LOCALS;
2754
2755 DRM_DEBUG("%s: %x\n", __FUNCTION__, flags);
2756 switch (flags) {
2757 case RADEON_WAIT_2D:
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002758 BEGIN_RING(2);
2759 RADEON_WAIT_UNTIL_2D_IDLE();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002760 ADVANCE_RING();
2761 break;
2762 case RADEON_WAIT_3D:
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002763 BEGIN_RING(2);
2764 RADEON_WAIT_UNTIL_3D_IDLE();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002765 ADVANCE_RING();
2766 break;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002767 case RADEON_WAIT_2D | RADEON_WAIT_3D:
2768 BEGIN_RING(2);
2769 RADEON_WAIT_UNTIL_IDLE();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002770 ADVANCE_RING();
2771 break;
2772 default:
2773 return DRM_ERR(EINVAL);
2774 }
2775
2776 return 0;
2777}
2778
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002779static int radeon_cp_cmdbuf(DRM_IOCTL_ARGS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002780{
2781 DRM_DEVICE;
2782 drm_radeon_private_t *dev_priv = dev->dev_private;
2783 drm_file_t *filp_priv;
2784 drm_device_dma_t *dma = dev->dma;
2785 drm_buf_t *buf = NULL;
2786 int idx;
Dave Airlieb3a83632005-09-30 18:37:36 +10002787 drm_radeon_kcmd_buffer_t cmdbuf;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002788 drm_radeon_cmd_header_t header;
2789 int orig_nbox, orig_bufsz;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002790 char *kbuf = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002791
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002792 LOCK_TEST_WITH_RETURN(dev, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002793
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002794 if (!dev_priv) {
2795 DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002796 return DRM_ERR(EINVAL);
2797 }
2798
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002799 DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002800
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002801 DRM_COPY_FROM_USER_IOCTL(cmdbuf,
2802 (drm_radeon_cmd_buffer_t __user *) data,
2803 sizeof(cmdbuf));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002804
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002805 RING_SPACE_TEST_WITH_RETURN(dev_priv);
2806 VB_AGE_TEST_WITH_RETURN(dev_priv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002807
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002808 if (cmdbuf.bufsz > 64 * 1024 || cmdbuf.bufsz < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002809 return DRM_ERR(EINVAL);
2810 }
2811
2812 /* Allocate an in-kernel area and copy in the cmdbuf. Do this to avoid
2813 * races between checking values and using those values in other code,
2814 * and simply to avoid a lot of function calls to copy in data.
2815 */
2816 orig_bufsz = cmdbuf.bufsz;
2817 if (orig_bufsz != 0) {
2818 kbuf = drm_alloc(cmdbuf.bufsz, DRM_MEM_DRIVER);
2819 if (kbuf == NULL)
2820 return DRM_ERR(ENOMEM);
Dave Airlieb3a83632005-09-30 18:37:36 +10002821 if (DRM_COPY_FROM_USER(kbuf, (void __user *)cmdbuf.buf, cmdbuf.bufsz)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002822 drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
2823 return DRM_ERR(EFAULT);
2824 }
2825 cmdbuf.buf = kbuf;
2826 }
2827
2828 orig_nbox = cmdbuf.nbox;
2829
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002830 if (dev_priv->microcode_version == UCODE_R300) {
Dave Airlie414ed532005-08-16 20:43:16 +10002831 int temp;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002832 temp = r300_do_cp_cmdbuf(dev, filp, filp_priv, &cmdbuf);
2833
Dave Airlie414ed532005-08-16 20:43:16 +10002834 if (orig_bufsz != 0)
2835 drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002836
Dave Airlie414ed532005-08-16 20:43:16 +10002837 return temp;
2838 }
2839
2840 /* microcode_version != r300 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002841 while (cmdbuf.bufsz >= sizeof(header)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002842
2843 header.i = *(int *)cmdbuf.buf;
2844 cmdbuf.buf += sizeof(header);
2845 cmdbuf.bufsz -= sizeof(header);
2846
2847 switch (header.header.cmd_type) {
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002848 case RADEON_CMD_PACKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002849 DRM_DEBUG("RADEON_CMD_PACKET\n");
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002850 if (radeon_emit_packets
2851 (dev_priv, filp_priv, header, &cmdbuf)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002852 DRM_ERROR("radeon_emit_packets failed\n");
2853 goto err;
2854 }
2855 break;
2856
2857 case RADEON_CMD_SCALARS:
2858 DRM_DEBUG("RADEON_CMD_SCALARS\n");
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002859 if (radeon_emit_scalars(dev_priv, header, &cmdbuf)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002860 DRM_ERROR("radeon_emit_scalars failed\n");
2861 goto err;
2862 }
2863 break;
2864
2865 case RADEON_CMD_VECTORS:
2866 DRM_DEBUG("RADEON_CMD_VECTORS\n");
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002867 if (radeon_emit_vectors(dev_priv, header, &cmdbuf)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002868 DRM_ERROR("radeon_emit_vectors failed\n");
2869 goto err;
2870 }
2871 break;
2872
2873 case RADEON_CMD_DMA_DISCARD:
2874 DRM_DEBUG("RADEON_CMD_DMA_DISCARD\n");
2875 idx = header.dma.buf_idx;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002876 if (idx < 0 || idx >= dma->buf_count) {
2877 DRM_ERROR("buffer index %d (of %d max)\n",
2878 idx, dma->buf_count - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002879 goto err;
2880 }
2881
2882 buf = dma->buflist[idx];
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002883 if (buf->filp != filp || buf->pending) {
2884 DRM_ERROR("bad buffer %p %p %d\n",
2885 buf->filp, filp, buf->pending);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002886 goto err;
2887 }
2888
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002889 radeon_cp_discard_buffer(dev, buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002890 break;
2891
2892 case RADEON_CMD_PACKET3:
2893 DRM_DEBUG("RADEON_CMD_PACKET3\n");
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002894 if (radeon_emit_packet3(dev, filp_priv, &cmdbuf)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002895 DRM_ERROR("radeon_emit_packet3 failed\n");
2896 goto err;
2897 }
2898 break;
2899
2900 case RADEON_CMD_PACKET3_CLIP:
2901 DRM_DEBUG("RADEON_CMD_PACKET3_CLIP\n");
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002902 if (radeon_emit_packet3_cliprect
2903 (dev, filp_priv, &cmdbuf, orig_nbox)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002904 DRM_ERROR("radeon_emit_packet3_clip failed\n");
2905 goto err;
2906 }
2907 break;
2908
2909 case RADEON_CMD_SCALARS2:
2910 DRM_DEBUG("RADEON_CMD_SCALARS2\n");
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002911 if (radeon_emit_scalars2(dev_priv, header, &cmdbuf)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002912 DRM_ERROR("radeon_emit_scalars2 failed\n");
2913 goto err;
2914 }
2915 break;
2916
2917 case RADEON_CMD_WAIT:
2918 DRM_DEBUG("RADEON_CMD_WAIT\n");
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002919 if (radeon_emit_wait(dev, header.wait.flags)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002920 DRM_ERROR("radeon_emit_wait failed\n");
2921 goto err;
2922 }
2923 break;
2924 default:
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002925 DRM_ERROR("bad cmd_type %d at %p\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002926 header.header.cmd_type,
2927 cmdbuf.buf - sizeof(header));
2928 goto err;
2929 }
2930 }
2931
2932 if (orig_bufsz != 0)
2933 drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
2934
2935 DRM_DEBUG("DONE\n");
2936 COMMIT_RING();
2937 return 0;
2938
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002939 err:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002940 if (orig_bufsz != 0)
2941 drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
2942 return DRM_ERR(EINVAL);
2943}
2944
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002945static int radeon_cp_getparam(DRM_IOCTL_ARGS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002946{
2947 DRM_DEVICE;
2948 drm_radeon_private_t *dev_priv = dev->dev_private;
2949 drm_radeon_getparam_t param;
2950 int value;
2951
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002952 if (!dev_priv) {
2953 DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002954 return DRM_ERR(EINVAL);
2955 }
2956
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002957 DRM_COPY_FROM_USER_IOCTL(param, (drm_radeon_getparam_t __user *) data,
2958 sizeof(param));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002959
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002960 DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002961
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002962 switch (param.param) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002963 case RADEON_PARAM_GART_BUFFER_OFFSET:
2964 value = dev_priv->gart_buffers_offset;
2965 break;
2966 case RADEON_PARAM_LAST_FRAME:
2967 dev_priv->stats.last_frame_reads++;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002968 value = GET_SCRATCH(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002969 break;
2970 case RADEON_PARAM_LAST_DISPATCH:
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002971 value = GET_SCRATCH(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002972 break;
2973 case RADEON_PARAM_LAST_CLEAR:
2974 dev_priv->stats.last_clear_reads++;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002975 value = GET_SCRATCH(2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002976 break;
2977 case RADEON_PARAM_IRQ_NR:
2978 value = dev->irq;
2979 break;
2980 case RADEON_PARAM_GART_BASE:
2981 value = dev_priv->gart_vm_start;
2982 break;
2983 case RADEON_PARAM_REGISTER_HANDLE:
2984 value = dev_priv->mmio_offset;
2985 break;
2986 case RADEON_PARAM_STATUS_HANDLE:
2987 value = dev_priv->ring_rptr_offset;
2988 break;
2989#if BITS_PER_LONG == 32
Dave Airlieb5e89ed2005-09-25 14:28:13 +10002990 /*
2991 * This ioctl() doesn't work on 64-bit platforms because hw_lock is a
2992 * pointer which can't fit into an int-sized variable. According to
2993 * Michel Dänzer, the ioctl() is only used on embedded platforms, so
2994 * not supporting it shouldn't be a problem. If the same functionality
2995 * is needed on 64-bit platforms, a new ioctl() would have to be added,
2996 * so backwards-compatibility for the embedded platforms can be
2997 * maintained. --davidm 4-Feb-2004.
2998 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002999 case RADEON_PARAM_SAREA_HANDLE:
3000 /* The lock is the first dword in the sarea. */
3001 value = (long)dev->lock.hw_lock;
3002 break;
3003#endif
3004 case RADEON_PARAM_GART_TEX_HANDLE:
3005 value = dev_priv->gart_textures_offset;
3006 break;
3007 default:
3008 return DRM_ERR(EINVAL);
3009 }
3010
Dave Airlieb5e89ed2005-09-25 14:28:13 +10003011 if (DRM_COPY_TO_USER(param.value, &value, sizeof(int))) {
3012 DRM_ERROR("copy_to_user\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003013 return DRM_ERR(EFAULT);
3014 }
Dave Airlieb5e89ed2005-09-25 14:28:13 +10003015
Linus Torvalds1da177e2005-04-16 15:20:36 -07003016 return 0;
3017}
3018
Dave Airlieb5e89ed2005-09-25 14:28:13 +10003019static int radeon_cp_setparam(DRM_IOCTL_ARGS)
3020{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003021 DRM_DEVICE;
3022 drm_radeon_private_t *dev_priv = dev->dev_private;
3023 drm_file_t *filp_priv;
3024 drm_radeon_setparam_t sp;
3025 struct drm_radeon_driver_file_fields *radeon_priv;
3026
Dave Airlieb5e89ed2005-09-25 14:28:13 +10003027 if (!dev_priv) {
3028 DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
3029 return DRM_ERR(EINVAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003030 }
3031
Dave Airlieb5e89ed2005-09-25 14:28:13 +10003032 DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003033
Dave Airlieb5e89ed2005-09-25 14:28:13 +10003034 DRM_COPY_FROM_USER_IOCTL(sp, (drm_radeon_setparam_t __user *) data,
3035 sizeof(sp));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003036
Dave Airlieb5e89ed2005-09-25 14:28:13 +10003037 switch (sp.param) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003038 case RADEON_SETPARAM_FB_LOCATION:
3039 radeon_priv = filp_priv->driver_priv;
3040 radeon_priv->radeon_fb_delta = dev_priv->fb_location - sp.value;
3041 break;
3042 case RADEON_SETPARAM_SWITCH_TILING:
3043 if (sp.value == 0) {
Dave Airlieb5e89ed2005-09-25 14:28:13 +10003044 DRM_DEBUG("color tiling disabled\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003045 dev_priv->front_pitch_offset &= ~RADEON_DST_TILE_MACRO;
3046 dev_priv->back_pitch_offset &= ~RADEON_DST_TILE_MACRO;
3047 dev_priv->sarea_priv->tiling_enabled = 0;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10003048 } else if (sp.value == 1) {
3049 DRM_DEBUG("color tiling enabled\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003050 dev_priv->front_pitch_offset |= RADEON_DST_TILE_MACRO;
3051 dev_priv->back_pitch_offset |= RADEON_DST_TILE_MACRO;
3052 dev_priv->sarea_priv->tiling_enabled = 1;
3053 }
Dave Airlieb5e89ed2005-09-25 14:28:13 +10003054 break;
Dave Airlieea98a922005-09-11 20:28:11 +10003055 case RADEON_SETPARAM_PCIGART_LOCATION:
3056 dev_priv->pcigart_offset = sp.value;
3057 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003058 default:
Dave Airlieb5e89ed2005-09-25 14:28:13 +10003059 DRM_DEBUG("Invalid parameter %d\n", sp.param);
3060 return DRM_ERR(EINVAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003061 }
3062
3063 return 0;
3064}
3065
3066/* When a client dies:
3067 * - Check for and clean up flipped page state
3068 * - Free any alloced GART memory.
3069 *
3070 * DRM infrastructure takes care of reclaiming dma buffers.
3071 */
Dave Airlieb5e89ed2005-09-25 14:28:13 +10003072void radeon_driver_prerelease(drm_device_t * dev, DRMFILE filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003073{
Dave Airlieb5e89ed2005-09-25 14:28:13 +10003074 if (dev->dev_private) {
3075 drm_radeon_private_t *dev_priv = dev->dev_private;
3076 if (dev_priv->page_flipping) {
3077 radeon_do_cleanup_pageflip(dev);
3078 }
3079 radeon_mem_release(filp, dev_priv->gart_heap);
3080 radeon_mem_release(filp, dev_priv->fb_heap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003081 radeon_surfaces_release(filp, dev_priv);
Dave Airlieb5e89ed2005-09-25 14:28:13 +10003082 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003083}
3084
Dave Airlieb5e89ed2005-09-25 14:28:13 +10003085void radeon_driver_pretakedown(drm_device_t * dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003086{
3087 radeon_do_release(dev);
3088}
3089
Dave Airlieb5e89ed2005-09-25 14:28:13 +10003090int radeon_driver_open_helper(drm_device_t * dev, drm_file_t * filp_priv)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003091{
3092 drm_radeon_private_t *dev_priv = dev->dev_private;
3093 struct drm_radeon_driver_file_fields *radeon_priv;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10003094
3095 radeon_priv =
3096 (struct drm_radeon_driver_file_fields *)
3097 drm_alloc(sizeof(*radeon_priv), DRM_MEM_FILES);
3098
Linus Torvalds1da177e2005-04-16 15:20:36 -07003099 if (!radeon_priv)
3100 return -ENOMEM;
3101
3102 filp_priv->driver_priv = radeon_priv;
Dave Airlieb5e89ed2005-09-25 14:28:13 +10003103 if (dev_priv)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003104 radeon_priv->radeon_fb_delta = dev_priv->fb_location;
3105 else
3106 radeon_priv->radeon_fb_delta = 0;
3107 return 0;
3108}
3109
Dave Airlieb5e89ed2005-09-25 14:28:13 +10003110void radeon_driver_free_filp_priv(drm_device_t * dev, drm_file_t * filp_priv)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003111{
Dave Airlieb5e89ed2005-09-25 14:28:13 +10003112 struct drm_radeon_driver_file_fields *radeon_priv =
3113 filp_priv->driver_priv;
3114
3115 drm_free(radeon_priv, sizeof(*radeon_priv), DRM_MEM_FILES);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003116}
3117
3118drm_ioctl_desc_t radeon_ioctls[] = {
Dave Airlieb6ce1562005-09-25 15:07:24 +10003119 [DRM_IOCTL_NR(DRM_RADEON_CP_INIT)] = {radeon_cp_init, 1, 1},
3120 [DRM_IOCTL_NR(DRM_RADEON_CP_START)] = {radeon_cp_start, 1, 1},
3121 [DRM_IOCTL_NR(DRM_RADEON_CP_STOP)] = {radeon_cp_stop, 1, 1},
3122 [DRM_IOCTL_NR(DRM_RADEON_CP_RESET)] = {radeon_cp_reset, 1, 1},
3123 [DRM_IOCTL_NR(DRM_RADEON_CP_IDLE)] = {radeon_cp_idle, 1, 0},
3124 [DRM_IOCTL_NR(DRM_RADEON_CP_RESUME)] = {radeon_cp_resume, 1, 0},
3125 [DRM_IOCTL_NR(DRM_RADEON_RESET)] = {radeon_engine_reset, 1, 0},
3126 [DRM_IOCTL_NR(DRM_RADEON_FULLSCREEN)] = {radeon_fullscreen, 1, 0},
3127 [DRM_IOCTL_NR(DRM_RADEON_SWAP)] = {radeon_cp_swap, 1, 0},
3128 [DRM_IOCTL_NR(DRM_RADEON_CLEAR)] = {radeon_cp_clear, 1, 0},
3129 [DRM_IOCTL_NR(DRM_RADEON_VERTEX)] = {radeon_cp_vertex, 1, 0},
3130 [DRM_IOCTL_NR(DRM_RADEON_INDICES)] = {radeon_cp_indices, 1, 0},
3131 [DRM_IOCTL_NR(DRM_RADEON_TEXTURE)] = {radeon_cp_texture, 1, 0},
3132 [DRM_IOCTL_NR(DRM_RADEON_STIPPLE)] = {radeon_cp_stipple, 1, 0},
3133 [DRM_IOCTL_NR(DRM_RADEON_INDIRECT)] = {radeon_cp_indirect, 1, 1},
3134 [DRM_IOCTL_NR(DRM_RADEON_VERTEX2)] = {radeon_cp_vertex2, 1, 0},
3135 [DRM_IOCTL_NR(DRM_RADEON_CMDBUF)] = {radeon_cp_cmdbuf, 1, 0},
3136 [DRM_IOCTL_NR(DRM_RADEON_GETPARAM)] = {radeon_cp_getparam, 1, 0},
3137 [DRM_IOCTL_NR(DRM_RADEON_FLIP)] = {radeon_cp_flip, 1, 0},
3138 [DRM_IOCTL_NR(DRM_RADEON_ALLOC)] = {radeon_mem_alloc, 1, 0},
3139 [DRM_IOCTL_NR(DRM_RADEON_FREE)] = {radeon_mem_free, 1, 0},
3140 [DRM_IOCTL_NR(DRM_RADEON_INIT_HEAP)] = {radeon_mem_init_heap, 1, 1},
3141 [DRM_IOCTL_NR(DRM_RADEON_IRQ_EMIT)] = {radeon_irq_emit, 1, 0},
3142 [DRM_IOCTL_NR(DRM_RADEON_IRQ_WAIT)] = {radeon_irq_wait, 1, 0},
3143 [DRM_IOCTL_NR(DRM_RADEON_SETPARAM)] = {radeon_cp_setparam, 1, 0},
3144 [DRM_IOCTL_NR(DRM_RADEON_SURF_ALLOC)] = {radeon_surface_alloc, 1, 0},
Dave Airlieb5e89ed2005-09-25 14:28:13 +10003145 [DRM_IOCTL_NR(DRM_RADEON_SURF_FREE)] = {radeon_surface_free, 1, 0}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003146};
3147
3148int radeon_max_ioctl = DRM_ARRAY_SIZE(radeon_ioctls);