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