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