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
1549void 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 if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
2217 r600_cp_dispatch_swap(dev, file_priv);
2218 else
2219 radeon_cp_dispatch_swap(dev, file_priv->master);
2220 sarea_priv->ctx_owner = 0;
2221
2222 COMMIT_RING();
2223 return 0;
2224}
2225
2226static int radeon_cp_vertex(struct drm_device *dev, void *data, struct drm_file *file_priv)
2227{
2228 drm_radeon_private_t *dev_priv = dev->dev_private;
2229 struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
2230 drm_radeon_sarea_t *sarea_priv;
2231 struct drm_device_dma *dma = dev->dma;
2232 struct drm_buf *buf;
2233 drm_radeon_vertex_t *vertex = data;
2234 drm_radeon_tcl_prim_t prim;
2235
2236 LOCK_TEST_WITH_RETURN(dev, file_priv);
2237
2238 sarea_priv = master_priv->sarea_priv;
2239
2240 DRM_DEBUG("pid=%d index=%d count=%d discard=%d\n",
2241 DRM_CURRENTPID, vertex->idx, vertex->count, vertex->discard);
2242
2243 if (vertex->idx < 0 || vertex->idx >= dma->buf_count) {
2244 DRM_ERROR("buffer index %d (of %d max)\n",
2245 vertex->idx, dma->buf_count - 1);
2246 return -EINVAL;
2247 }
2248 if (vertex->prim < 0 || vertex->prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST) {
2249 DRM_ERROR("buffer prim %d\n", vertex->prim);
2250 return -EINVAL;
2251 }
2252
2253 RING_SPACE_TEST_WITH_RETURN(dev_priv);
2254 VB_AGE_TEST_WITH_RETURN(dev_priv);
2255
2256 buf = dma->buflist[vertex->idx];
2257
2258 if (buf->file_priv != file_priv) {
2259 DRM_ERROR("process %d using buffer owned by %p\n",
2260 DRM_CURRENTPID, buf->file_priv);
2261 return -EINVAL;
2262 }
2263 if (buf->pending) {
2264 DRM_ERROR("sending pending buffer %d\n", vertex->idx);
2265 return -EINVAL;
2266 }
2267
2268
2269
2270 if (vertex->count) {
2271 buf->used = vertex->count;
2272
2273 if (sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS) {
2274 if (radeon_emit_state(dev_priv, file_priv,
2275 &sarea_priv->context_state,
2276 sarea_priv->tex_state,
2277 sarea_priv->dirty)) {
2278 DRM_ERROR("radeon_emit_state failed\n");
2279 return -EINVAL;
2280 }
2281
2282 sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES |
2283 RADEON_UPLOAD_TEX1IMAGES |
2284 RADEON_UPLOAD_TEX2IMAGES |
2285 RADEON_REQUIRE_QUIESCENCE);
2286 }
2287
2288 prim.start = 0;
2289 prim.finish = vertex->count;
2290 prim.prim = vertex->prim;
2291 prim.numverts = vertex->count;
2292 prim.vc_format = sarea_priv->vc_format;
2293
2294 radeon_cp_dispatch_vertex(dev, file_priv, buf, &prim);
2295 }
2296
2297 if (vertex->discard) {
2298 radeon_cp_discard_buffer(dev, file_priv->master, buf);
2299 }
2300
2301 COMMIT_RING();
2302 return 0;
2303}
2304
2305static int radeon_cp_indices(struct drm_device *dev, void *data, struct drm_file *file_priv)
2306{
2307 drm_radeon_private_t *dev_priv = dev->dev_private;
2308 struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
2309 drm_radeon_sarea_t *sarea_priv;
2310 struct drm_device_dma *dma = dev->dma;
2311 struct drm_buf *buf;
2312 drm_radeon_indices_t *elts = data;
2313 drm_radeon_tcl_prim_t prim;
2314 int count;
2315
2316 LOCK_TEST_WITH_RETURN(dev, file_priv);
2317
2318 sarea_priv = master_priv->sarea_priv;
2319
2320 DRM_DEBUG("pid=%d index=%d start=%d end=%d discard=%d\n",
2321 DRM_CURRENTPID, elts->idx, elts->start, elts->end,
2322 elts->discard);
2323
2324 if (elts->idx < 0 || elts->idx >= dma->buf_count) {
2325 DRM_ERROR("buffer index %d (of %d max)\n",
2326 elts->idx, dma->buf_count - 1);
2327 return -EINVAL;
2328 }
2329 if (elts->prim < 0 || elts->prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST) {
2330 DRM_ERROR("buffer prim %d\n", elts->prim);
2331 return -EINVAL;
2332 }
2333
2334 RING_SPACE_TEST_WITH_RETURN(dev_priv);
2335 VB_AGE_TEST_WITH_RETURN(dev_priv);
2336
2337 buf = dma->buflist[elts->idx];
2338
2339 if (buf->file_priv != file_priv) {
2340 DRM_ERROR("process %d using buffer owned by %p\n",
2341 DRM_CURRENTPID, buf->file_priv);
2342 return -EINVAL;
2343 }
2344 if (buf->pending) {
2345 DRM_ERROR("sending pending buffer %d\n", elts->idx);
2346 return -EINVAL;
2347 }
2348
2349 count = (elts->end - elts->start) / sizeof(u16);
2350 elts->start -= RADEON_INDEX_PRIM_OFFSET;
2351
2352 if (elts->start & 0x7) {
2353 DRM_ERROR("misaligned buffer 0x%x\n", elts->start);
2354 return -EINVAL;
2355 }
2356 if (elts->start < buf->used) {
2357 DRM_ERROR("no header 0x%x - 0x%x\n", elts->start, buf->used);
2358 return -EINVAL;
2359 }
2360
2361 buf->used = elts->end;
2362
2363 if (sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS) {
2364 if (radeon_emit_state(dev_priv, file_priv,
2365 &sarea_priv->context_state,
2366 sarea_priv->tex_state,
2367 sarea_priv->dirty)) {
2368 DRM_ERROR("radeon_emit_state failed\n");
2369 return -EINVAL;
2370 }
2371
2372 sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES |
2373 RADEON_UPLOAD_TEX1IMAGES |
2374 RADEON_UPLOAD_TEX2IMAGES |
2375 RADEON_REQUIRE_QUIESCENCE);
2376 }
2377
2378
2379
2380 prim.start = elts->start;
2381 prim.finish = elts->end;
2382 prim.prim = elts->prim;
2383 prim.offset = 0;
2384 prim.numverts = RADEON_MAX_VB_VERTS;
2385 prim.vc_format = sarea_priv->vc_format;
2386
2387 radeon_cp_dispatch_indices(dev, file_priv->master, buf, &prim);
2388 if (elts->discard) {
2389 radeon_cp_discard_buffer(dev, file_priv->master, buf);
2390 }
2391
2392 COMMIT_RING();
2393 return 0;
2394}
2395
2396static int radeon_cp_texture(struct drm_device *dev, void *data, struct drm_file *file_priv)
2397{
2398 drm_radeon_private_t *dev_priv = dev->dev_private;
2399 drm_radeon_texture_t *tex = data;
2400 drm_radeon_tex_image_t image;
2401 int ret;
2402
2403 LOCK_TEST_WITH_RETURN(dev, file_priv);
2404
2405 if (tex->image == NULL) {
2406 DRM_ERROR("null texture image!\n");
2407 return -EINVAL;
2408 }
2409
2410 if (DRM_COPY_FROM_USER(&image,
2411 (drm_radeon_tex_image_t __user *) tex->image,
2412 sizeof(image)))
2413 return -EFAULT;
2414
2415 RING_SPACE_TEST_WITH_RETURN(dev_priv);
2416 VB_AGE_TEST_WITH_RETURN(dev_priv);
2417
2418 if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
2419 ret = r600_cp_dispatch_texture(dev, file_priv, tex, &image);
2420 else
2421 ret = radeon_cp_dispatch_texture(dev, file_priv, tex, &image);
2422
2423 return ret;
2424}
2425
2426static int radeon_cp_stipple(struct drm_device *dev, void *data, struct drm_file *file_priv)
2427{
2428 drm_radeon_private_t *dev_priv = dev->dev_private;
2429 drm_radeon_stipple_t *stipple = data;
2430 u32 mask[32];
2431
2432 LOCK_TEST_WITH_RETURN(dev, file_priv);
2433
2434 if (DRM_COPY_FROM_USER(&mask, stipple->mask, 32 * sizeof(u32)))
2435 return -EFAULT;
2436
2437 RING_SPACE_TEST_WITH_RETURN(dev_priv);
2438
2439 radeon_cp_dispatch_stipple(dev, mask);
2440
2441 COMMIT_RING();
2442 return 0;
2443}
2444
2445static int radeon_cp_indirect(struct drm_device *dev, void *data, struct drm_file *file_priv)
2446{
2447 drm_radeon_private_t *dev_priv = dev->dev_private;
2448 struct drm_device_dma *dma = dev->dma;
2449 struct drm_buf *buf;
2450 drm_radeon_indirect_t *indirect = data;
2451 RING_LOCALS;
2452
2453 LOCK_TEST_WITH_RETURN(dev, file_priv);
2454
2455 DRM_DEBUG("idx=%d s=%d e=%d d=%d\n",
2456 indirect->idx, indirect->start, indirect->end,
2457 indirect->discard);
2458
2459 if (indirect->idx < 0 || indirect->idx >= dma->buf_count) {
2460 DRM_ERROR("buffer index %d (of %d max)\n",
2461 indirect->idx, dma->buf_count - 1);
2462 return -EINVAL;
2463 }
2464
2465 buf = dma->buflist[indirect->idx];
2466
2467 if (buf->file_priv != file_priv) {
2468 DRM_ERROR("process %d using buffer owned by %p\n",
2469 DRM_CURRENTPID, buf->file_priv);
2470 return -EINVAL;
2471 }
2472 if (buf->pending) {
2473 DRM_ERROR("sending pending buffer %d\n", indirect->idx);
2474 return -EINVAL;
2475 }
2476
2477 if (indirect->start < buf->used) {
2478 DRM_ERROR("reusing indirect: start=0x%x actual=0x%x\n",
2479 indirect->start, buf->used);
2480 return -EINVAL;
2481 }
2482
2483 RING_SPACE_TEST_WITH_RETURN(dev_priv);
2484 VB_AGE_TEST_WITH_RETURN(dev_priv);
2485
2486 buf->used = indirect->end;
2487
2488
2489
2490
2491
2492 if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
2493 r600_cp_dispatch_indirect(dev, buf, indirect->start, indirect->end);
2494 else {
2495
2496
2497
2498 BEGIN_RING(2);
2499 RADEON_WAIT_UNTIL_3D_IDLE();
2500 ADVANCE_RING();
2501 radeon_cp_dispatch_indirect(dev, buf, indirect->start, indirect->end);
2502 }
2503
2504 if (indirect->discard) {
2505 radeon_cp_discard_buffer(dev, file_priv->master, buf);
2506 }
2507
2508 COMMIT_RING();
2509 return 0;
2510}
2511
2512static int radeon_cp_vertex2(struct drm_device *dev, void *data, struct drm_file *file_priv)
2513{
2514 drm_radeon_private_t *dev_priv = dev->dev_private;
2515 struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
2516 drm_radeon_sarea_t *sarea_priv;
2517 struct drm_device_dma *dma = dev->dma;
2518 struct drm_buf *buf;
2519 drm_radeon_vertex2_t *vertex = data;
2520 int i;
2521 unsigned char laststate;
2522
2523 LOCK_TEST_WITH_RETURN(dev, file_priv);
2524
2525 sarea_priv = master_priv->sarea_priv;
2526
2527 DRM_DEBUG("pid=%d index=%d discard=%d\n",
2528 DRM_CURRENTPID, vertex->idx, vertex->discard);
2529
2530 if (vertex->idx < 0 || vertex->idx >= dma->buf_count) {
2531 DRM_ERROR("buffer index %d (of %d max)\n",
2532 vertex->idx, dma->buf_count - 1);
2533 return -EINVAL;
2534 }
2535
2536 RING_SPACE_TEST_WITH_RETURN(dev_priv);
2537 VB_AGE_TEST_WITH_RETURN(dev_priv);
2538
2539 buf = dma->buflist[vertex->idx];
2540
2541 if (buf->file_priv != file_priv) {
2542 DRM_ERROR("process %d using buffer owned by %p\n",
2543 DRM_CURRENTPID, buf->file_priv);
2544 return -EINVAL;
2545 }
2546
2547 if (buf->pending) {
2548 DRM_ERROR("sending pending buffer %d\n", vertex->idx);
2549 return -EINVAL;
2550 }
2551
2552 if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS)
2553 return -EINVAL;
2554
2555 for (laststate = 0xff, i = 0; i < vertex->nr_prims; i++) {
2556 drm_radeon_prim_t prim;
2557 drm_radeon_tcl_prim_t tclprim;
2558
2559 if (DRM_COPY_FROM_USER(&prim, &vertex->prim[i], sizeof(prim)))
2560 return -EFAULT;
2561
2562 if (prim.stateidx != laststate) {
2563 drm_radeon_state_t state;
2564
2565 if (DRM_COPY_FROM_USER(&state,
2566 &vertex->state[prim.stateidx],
2567 sizeof(state)))
2568 return -EFAULT;
2569
2570 if (radeon_emit_state2(dev_priv, file_priv, &state)) {
2571 DRM_ERROR("radeon_emit_state2 failed\n");
2572 return -EINVAL;
2573 }
2574
2575 laststate = prim.stateidx;
2576 }
2577
2578 tclprim.start = prim.start;
2579 tclprim.finish = prim.finish;
2580 tclprim.prim = prim.prim;
2581 tclprim.vc_format = prim.vc_format;
2582
2583 if (prim.prim & RADEON_PRIM_WALK_IND) {
2584 tclprim.offset = prim.numverts * 64;
2585 tclprim.numverts = RADEON_MAX_VB_VERTS;
2586
2587 radeon_cp_dispatch_indices(dev, file_priv->master, buf, &tclprim);
2588 } else {
2589 tclprim.numverts = prim.numverts;
2590 tclprim.offset = 0;
2591
2592 radeon_cp_dispatch_vertex(dev, file_priv, buf, &tclprim);
2593 }
2594
2595 if (sarea_priv->nbox == 1)
2596 sarea_priv->nbox = 0;
2597 }
2598
2599 if (vertex->discard) {
2600 radeon_cp_discard_buffer(dev, file_priv->master, buf);
2601 }
2602
2603 COMMIT_RING();
2604 return 0;
2605}
2606
2607static int radeon_emit_packets(drm_radeon_private_t * dev_priv,
2608 struct drm_file *file_priv,
2609 drm_radeon_cmd_header_t header,
2610 drm_radeon_kcmd_buffer_t *cmdbuf)
2611{
2612 int id = (int)header.packet.packet_id;
2613 int sz, reg;
2614 int *data = (int *)cmdbuf->buf;
2615 RING_LOCALS;
2616
2617 if (id >= RADEON_MAX_STATE_PACKETS)
2618 return -EINVAL;
2619
2620 sz = packet[id].len;
2621 reg = packet[id].start;
2622
2623 if (sz * sizeof(int) > cmdbuf->bufsz) {
2624 DRM_ERROR("Packet size provided larger than data provided\n");
2625 return -EINVAL;
2626 }
2627
2628 if (radeon_check_and_fixup_packets(dev_priv, file_priv, id, data)) {
2629 DRM_ERROR("Packet verification failed\n");
2630 return -EINVAL;
2631 }
2632
2633 BEGIN_RING(sz + 1);
2634 OUT_RING(CP_PACKET0(reg, (sz - 1)));
2635 OUT_RING_TABLE(data, sz);
2636 ADVANCE_RING();
2637
2638 cmdbuf->buf += sz * sizeof(int);
2639 cmdbuf->bufsz -= sz * sizeof(int);
2640 return 0;
2641}
2642
2643static __inline__ int radeon_emit_scalars(drm_radeon_private_t *dev_priv,
2644 drm_radeon_cmd_header_t header,
2645 drm_radeon_kcmd_buffer_t *cmdbuf)
2646{
2647 int sz = header.scalars.count;
2648 int start = header.scalars.offset;
2649 int stride = header.scalars.stride;
2650 RING_LOCALS;
2651
2652 BEGIN_RING(3 + sz);
2653 OUT_RING(CP_PACKET0(RADEON_SE_TCL_SCALAR_INDX_REG, 0));
2654 OUT_RING(start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT));
2655 OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_SCALAR_DATA_REG, sz - 1));
2656 OUT_RING_TABLE(cmdbuf->buf, sz);
2657 ADVANCE_RING();
2658 cmdbuf->buf += sz * sizeof(int);
2659 cmdbuf->bufsz -= sz * sizeof(int);
2660 return 0;
2661}
2662
2663
2664
2665static __inline__ int radeon_emit_scalars2(drm_radeon_private_t *dev_priv,
2666 drm_radeon_cmd_header_t header,
2667 drm_radeon_kcmd_buffer_t *cmdbuf)
2668{
2669 int sz = header.scalars.count;
2670 int start = ((unsigned int)header.scalars.offset) + 0x100;
2671 int stride = header.scalars.stride;
2672 RING_LOCALS;
2673
2674 BEGIN_RING(3 + sz);
2675 OUT_RING(CP_PACKET0(RADEON_SE_TCL_SCALAR_INDX_REG, 0));
2676 OUT_RING(start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT));
2677 OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_SCALAR_DATA_REG, sz - 1));
2678 OUT_RING_TABLE(cmdbuf->buf, sz);
2679 ADVANCE_RING();
2680 cmdbuf->buf += sz * sizeof(int);
2681 cmdbuf->bufsz -= sz * sizeof(int);
2682 return 0;
2683}
2684
2685static __inline__ int radeon_emit_vectors(drm_radeon_private_t *dev_priv,
2686 drm_radeon_cmd_header_t header,
2687 drm_radeon_kcmd_buffer_t *cmdbuf)
2688{
2689 int sz = header.vectors.count;
2690 int start = header.vectors.offset;
2691 int stride = header.vectors.stride;
2692 RING_LOCALS;
2693
2694 BEGIN_RING(5 + sz);
2695 OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0);
2696 OUT_RING(CP_PACKET0(RADEON_SE_TCL_VECTOR_INDX_REG, 0));
2697 OUT_RING(start | (stride << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT));
2698 OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1)));
2699 OUT_RING_TABLE(cmdbuf->buf, sz);
2700 ADVANCE_RING();
2701
2702 cmdbuf->buf += sz * sizeof(int);
2703 cmdbuf->bufsz -= sz * sizeof(int);
2704 return 0;
2705}
2706
2707static __inline__ int radeon_emit_veclinear(drm_radeon_private_t *dev_priv,
2708 drm_radeon_cmd_header_t header,
2709 drm_radeon_kcmd_buffer_t *cmdbuf)
2710{
2711 int sz = header.veclinear.count * 4;
2712 int start = header.veclinear.addr_lo | (header.veclinear.addr_hi << 8);
2713 RING_LOCALS;
2714
2715 if (!sz)
2716 return 0;
2717 if (sz * 4 > cmdbuf->bufsz)
2718 return -EINVAL;
2719
2720 BEGIN_RING(5 + sz);
2721 OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0);
2722 OUT_RING(CP_PACKET0(RADEON_SE_TCL_VECTOR_INDX_REG, 0));
2723 OUT_RING(start | (1 << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT));
2724 OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1)));
2725 OUT_RING_TABLE(cmdbuf->buf, sz);
2726 ADVANCE_RING();
2727
2728 cmdbuf->buf += sz * sizeof(int);
2729 cmdbuf->bufsz -= sz * sizeof(int);
2730 return 0;
2731}
2732
2733static int radeon_emit_packet3(struct drm_device * dev,
2734 struct drm_file *file_priv,
2735 drm_radeon_kcmd_buffer_t *cmdbuf)
2736{
2737 drm_radeon_private_t *dev_priv = dev->dev_private;
2738 unsigned int cmdsz;
2739 int ret;
2740 RING_LOCALS;
2741
2742 DRM_DEBUG("\n");
2743
2744 if ((ret = radeon_check_and_fixup_packet3(dev_priv, file_priv,
2745 cmdbuf, &cmdsz))) {
2746 DRM_ERROR("Packet verification failed\n");
2747 return ret;
2748 }
2749
2750 BEGIN_RING(cmdsz);
2751 OUT_RING_TABLE(cmdbuf->buf, cmdsz);
2752 ADVANCE_RING();
2753
2754 cmdbuf->buf += cmdsz * 4;
2755 cmdbuf->bufsz -= cmdsz * 4;
2756 return 0;
2757}
2758
2759static int radeon_emit_packet3_cliprect(struct drm_device *dev,
2760 struct drm_file *file_priv,
2761 drm_radeon_kcmd_buffer_t *cmdbuf,
2762 int orig_nbox)
2763{
2764 drm_radeon_private_t *dev_priv = dev->dev_private;
2765 struct drm_clip_rect box;
2766 unsigned int cmdsz;
2767 int ret;
2768 struct drm_clip_rect __user *boxes = cmdbuf->boxes;
2769 int i = 0;
2770 RING_LOCALS;
2771
2772 DRM_DEBUG("\n");
2773
2774 if ((ret = radeon_check_and_fixup_packet3(dev_priv, file_priv,
2775 cmdbuf, &cmdsz))) {
2776 DRM_ERROR("Packet verification failed\n");
2777 return ret;
2778 }
2779
2780 if (!orig_nbox)
2781 goto out;
2782
2783 do {
2784 if (i < cmdbuf->nbox) {
2785 if (DRM_COPY_FROM_USER(&box, &boxes[i], sizeof(box)))
2786 return -EFAULT;
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799 if (i) {
2800 BEGIN_RING(2);
2801 RADEON_WAIT_UNTIL_3D_IDLE();
2802 ADVANCE_RING();
2803 }
2804 radeon_emit_clip_rect(dev_priv, &box);
2805 }
2806
2807 BEGIN_RING(cmdsz);
2808 OUT_RING_TABLE(cmdbuf->buf, cmdsz);
2809 ADVANCE_RING();
2810
2811 } while (++i < cmdbuf->nbox);
2812 if (cmdbuf->nbox == 1)
2813 cmdbuf->nbox = 0;
2814
2815 out:
2816 cmdbuf->buf += cmdsz * 4;
2817 cmdbuf->bufsz -= cmdsz * 4;
2818 return 0;
2819}
2820
2821static int radeon_emit_wait(struct drm_device * dev, int flags)
2822{
2823 drm_radeon_private_t *dev_priv = dev->dev_private;
2824 RING_LOCALS;
2825
2826 DRM_DEBUG("%x\n", flags);
2827 switch (flags) {
2828 case RADEON_WAIT_2D:
2829 BEGIN_RING(2);
2830 RADEON_WAIT_UNTIL_2D_IDLE();
2831 ADVANCE_RING();
2832 break;
2833 case RADEON_WAIT_3D:
2834 BEGIN_RING(2);
2835 RADEON_WAIT_UNTIL_3D_IDLE();
2836 ADVANCE_RING();
2837 break;
2838 case RADEON_WAIT_2D | RADEON_WAIT_3D:
2839 BEGIN_RING(2);
2840 RADEON_WAIT_UNTIL_IDLE();
2841 ADVANCE_RING();
2842 break;
2843 default:
2844 return -EINVAL;
2845 }
2846
2847 return 0;
2848}
2849
2850static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_priv)
2851{
2852 drm_radeon_private_t *dev_priv = dev->dev_private;
2853 struct drm_device_dma *dma = dev->dma;
2854 struct drm_buf *buf = NULL;
2855 int idx;
2856 drm_radeon_kcmd_buffer_t *cmdbuf = data;
2857 drm_radeon_cmd_header_t header;
2858 int orig_nbox, orig_bufsz;
2859 char *kbuf = NULL;
2860
2861 LOCK_TEST_WITH_RETURN(dev, file_priv);
2862
2863 RING_SPACE_TEST_WITH_RETURN(dev_priv);
2864 VB_AGE_TEST_WITH_RETURN(dev_priv);
2865
2866 if (cmdbuf->bufsz > 64 * 1024 || cmdbuf->bufsz < 0) {
2867 return -EINVAL;
2868 }
2869
2870
2871
2872
2873
2874 orig_bufsz = cmdbuf->bufsz;
2875 if (orig_bufsz != 0) {
2876 kbuf = kmalloc(cmdbuf->bufsz, GFP_KERNEL);
2877 if (kbuf == NULL)
2878 return -ENOMEM;
2879 if (DRM_COPY_FROM_USER(kbuf, (void __user *)cmdbuf->buf,
2880 cmdbuf->bufsz)) {
2881 kfree(kbuf);
2882 return -EFAULT;
2883 }
2884 cmdbuf->buf = kbuf;
2885 }
2886
2887 orig_nbox = cmdbuf->nbox;
2888
2889 if (dev_priv->microcode_version == UCODE_R300) {
2890 int temp;
2891 temp = r300_do_cp_cmdbuf(dev, file_priv, cmdbuf);
2892
2893 if (orig_bufsz != 0)
2894 kfree(kbuf);
2895
2896 return temp;
2897 }
2898
2899
2900 while (cmdbuf->bufsz >= sizeof(header)) {
2901
2902 header.i = *(int *)cmdbuf->buf;
2903 cmdbuf->buf += sizeof(header);
2904 cmdbuf->bufsz -= sizeof(header);
2905
2906 switch (header.header.cmd_type) {
2907 case RADEON_CMD_PACKET:
2908 DRM_DEBUG("RADEON_CMD_PACKET\n");
2909 if (radeon_emit_packets
2910 (dev_priv, file_priv, header, cmdbuf)) {
2911 DRM_ERROR("radeon_emit_packets failed\n");
2912 goto err;
2913 }
2914 break;
2915
2916 case RADEON_CMD_SCALARS:
2917 DRM_DEBUG("RADEON_CMD_SCALARS\n");
2918 if (radeon_emit_scalars(dev_priv, header, cmdbuf)) {
2919 DRM_ERROR("radeon_emit_scalars failed\n");
2920 goto err;
2921 }
2922 break;
2923
2924 case RADEON_CMD_VECTORS:
2925 DRM_DEBUG("RADEON_CMD_VECTORS\n");
2926 if (radeon_emit_vectors(dev_priv, header, cmdbuf)) {
2927 DRM_ERROR("radeon_emit_vectors failed\n");
2928 goto err;
2929 }
2930 break;
2931
2932 case RADEON_CMD_DMA_DISCARD:
2933 DRM_DEBUG("RADEON_CMD_DMA_DISCARD\n");
2934 idx = header.dma.buf_idx;
2935 if (idx < 0 || idx >= dma->buf_count) {
2936 DRM_ERROR("buffer index %d (of %d max)\n",
2937 idx, dma->buf_count - 1);
2938 goto err;
2939 }
2940
2941 buf = dma->buflist[idx];
2942 if (buf->file_priv != file_priv || buf->pending) {
2943 DRM_ERROR("bad buffer %p %p %d\n",
2944 buf->file_priv, file_priv,
2945 buf->pending);
2946 goto err;
2947 }
2948
2949 radeon_cp_discard_buffer(dev, file_priv->master, buf);
2950 break;
2951
2952 case RADEON_CMD_PACKET3:
2953 DRM_DEBUG("RADEON_CMD_PACKET3\n");
2954 if (radeon_emit_packet3(dev, file_priv, cmdbuf)) {
2955 DRM_ERROR("radeon_emit_packet3 failed\n");
2956 goto err;
2957 }
2958 break;
2959
2960 case RADEON_CMD_PACKET3_CLIP:
2961 DRM_DEBUG("RADEON_CMD_PACKET3_CLIP\n");
2962 if (radeon_emit_packet3_cliprect
2963 (dev, file_priv, cmdbuf, orig_nbox)) {
2964 DRM_ERROR("radeon_emit_packet3_clip failed\n");
2965 goto err;
2966 }
2967 break;
2968
2969 case RADEON_CMD_SCALARS2:
2970 DRM_DEBUG("RADEON_CMD_SCALARS2\n");
2971 if (radeon_emit_scalars2(dev_priv, header, cmdbuf)) {
2972 DRM_ERROR("radeon_emit_scalars2 failed\n");
2973 goto err;
2974 }
2975 break;
2976
2977 case RADEON_CMD_WAIT:
2978 DRM_DEBUG("RADEON_CMD_WAIT\n");
2979 if (radeon_emit_wait(dev, header.wait.flags)) {
2980 DRM_ERROR("radeon_emit_wait failed\n");
2981 goto err;
2982 }
2983 break;
2984 case RADEON_CMD_VECLINEAR:
2985 DRM_DEBUG("RADEON_CMD_VECLINEAR\n");
2986 if (radeon_emit_veclinear(dev_priv, header, cmdbuf)) {
2987 DRM_ERROR("radeon_emit_veclinear failed\n");
2988 goto err;
2989 }
2990 break;
2991
2992 default:
2993 DRM_ERROR("bad cmd_type %d at %p\n",
2994 header.header.cmd_type,
2995 cmdbuf->buf - sizeof(header));
2996 goto err;
2997 }
2998 }
2999
3000 if (orig_bufsz != 0)
3001 kfree(kbuf);
3002
3003 DRM_DEBUG("DONE\n");
3004 COMMIT_RING();
3005 return 0;
3006
3007 err:
3008 if (orig_bufsz != 0)
3009 kfree(kbuf);
3010 return -EINVAL;
3011}
3012
3013static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv)
3014{
3015 drm_radeon_private_t *dev_priv = dev->dev_private;
3016 drm_radeon_getparam_t *param = data;
3017 int value;
3018
3019 DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
3020
3021 switch (param->param) {
3022 case RADEON_PARAM_GART_BUFFER_OFFSET:
3023 value = dev_priv->gart_buffers_offset;
3024 break;
3025 case RADEON_PARAM_LAST_FRAME:
3026 dev_priv->stats.last_frame_reads++;
3027 value = GET_SCRATCH(dev_priv, 0);
3028 break;
3029 case RADEON_PARAM_LAST_DISPATCH:
3030 value = GET_SCRATCH(dev_priv, 1);
3031 break;
3032 case RADEON_PARAM_LAST_CLEAR:
3033 dev_priv->stats.last_clear_reads++;
3034 value = GET_SCRATCH(dev_priv, 2);
3035 break;
3036 case RADEON_PARAM_IRQ_NR:
3037 if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
3038 value = 0;
3039 else
3040 value = drm_dev_to_irq(dev);
3041 break;
3042 case RADEON_PARAM_GART_BASE:
3043 value = dev_priv->gart_vm_start;
3044 break;
3045 case RADEON_PARAM_REGISTER_HANDLE:
3046 value = dev_priv->mmio->offset;
3047 break;
3048 case RADEON_PARAM_STATUS_HANDLE:
3049 value = dev_priv->ring_rptr_offset;
3050 break;
3051#if BITS_PER_LONG == 32
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061 case RADEON_PARAM_SAREA_HANDLE:
3062
3063
3064 break;
3065#endif
3066 case RADEON_PARAM_GART_TEX_HANDLE:
3067 value = dev_priv->gart_textures_offset;
3068 break;
3069 case RADEON_PARAM_SCRATCH_OFFSET:
3070 if (!dev_priv->writeback_works)
3071 return -EINVAL;
3072 if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
3073 value = R600_SCRATCH_REG_OFFSET;
3074 else
3075 value = RADEON_SCRATCH_REG_OFFSET;
3076 break;
3077 case RADEON_PARAM_CARD_TYPE:
3078 if (dev_priv->flags & RADEON_IS_PCIE)
3079 value = RADEON_CARD_PCIE;
3080 else if (dev_priv->flags & RADEON_IS_AGP)
3081 value = RADEON_CARD_AGP;
3082 else
3083 value = RADEON_CARD_PCI;
3084 break;
3085 case RADEON_PARAM_VBLANK_CRTC:
3086 value = radeon_vblank_crtc_get(dev);
3087 break;
3088 case RADEON_PARAM_FB_LOCATION:
3089 value = radeon_read_fb_location(dev_priv);
3090 break;
3091 case RADEON_PARAM_NUM_GB_PIPES:
3092 value = dev_priv->num_gb_pipes;
3093 break;
3094 case RADEON_PARAM_NUM_Z_PIPES:
3095 value = dev_priv->num_z_pipes;
3096 break;
3097 default:
3098 DRM_DEBUG("Invalid parameter %d\n", param->param);
3099 return -EINVAL;
3100 }
3101
3102 if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) {
3103 DRM_ERROR("copy_to_user\n");
3104 return -EFAULT;
3105 }
3106
3107 return 0;
3108}
3109
3110static int radeon_cp_setparam(struct drm_device *dev, void *data, struct drm_file *file_priv)
3111{
3112 drm_radeon_private_t *dev_priv = dev->dev_private;
3113 struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
3114 drm_radeon_setparam_t *sp = data;
3115 struct drm_radeon_driver_file_fields *radeon_priv;
3116
3117 switch (sp->param) {
3118 case RADEON_SETPARAM_FB_LOCATION:
3119 radeon_priv = file_priv->driver_priv;
3120 radeon_priv->radeon_fb_delta = dev_priv->fb_location -
3121 sp->value;
3122 break;
3123 case RADEON_SETPARAM_SWITCH_TILING:
3124 if (sp->value == 0) {
3125 DRM_DEBUG("color tiling disabled\n");
3126 dev_priv->front_pitch_offset &= ~RADEON_DST_TILE_MACRO;
3127 dev_priv->back_pitch_offset &= ~RADEON_DST_TILE_MACRO;
3128 if (master_priv->sarea_priv)
3129 master_priv->sarea_priv->tiling_enabled = 0;
3130 } else if (sp->value == 1) {
3131 DRM_DEBUG("color tiling enabled\n");
3132 dev_priv->front_pitch_offset |= RADEON_DST_TILE_MACRO;
3133 dev_priv->back_pitch_offset |= RADEON_DST_TILE_MACRO;
3134 if (master_priv->sarea_priv)
3135 master_priv->sarea_priv->tiling_enabled = 1;
3136 }
3137 break;
3138 case RADEON_SETPARAM_PCIGART_LOCATION:
3139 dev_priv->pcigart_offset = sp->value;
3140 dev_priv->pcigart_offset_set = 1;
3141 break;
3142 case RADEON_SETPARAM_NEW_MEMMAP:
3143 dev_priv->new_memmap = sp->value;
3144 break;
3145 case RADEON_SETPARAM_PCIGART_TABLE_SIZE:
3146 dev_priv->gart_info.table_size = sp->value;
3147 if (dev_priv->gart_info.table_size < RADEON_PCIGART_TABLE_SIZE)
3148 dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE;
3149 break;
3150 case RADEON_SETPARAM_VBLANK_CRTC:
3151 return radeon_vblank_crtc_set(dev, sp->value);
3152 break;
3153 default:
3154 DRM_DEBUG("Invalid parameter %d\n", sp->param);
3155 return -EINVAL;
3156 }
3157
3158 return 0;
3159}
3160
3161
3162
3163
3164
3165
3166
3167
3168void radeon_driver_preclose(struct drm_device *dev, struct drm_file *file_priv)
3169{
3170 if (dev->dev_private) {
3171 drm_radeon_private_t *dev_priv = dev->dev_private;
3172 dev_priv->page_flipping = 0;
3173 radeon_mem_release(file_priv, dev_priv->gart_heap);
3174 radeon_mem_release(file_priv, dev_priv->fb_heap);
3175 radeon_surfaces_release(file_priv, dev_priv);
3176 }
3177}
3178
3179void radeon_driver_lastclose(struct drm_device *dev)
3180{
3181 radeon_surfaces_release(PCIGART_FILE_PRIV, dev->dev_private);
3182 radeon_do_release(dev);
3183}
3184
3185int radeon_driver_open(struct drm_device *dev, struct drm_file *file_priv)
3186{
3187 drm_radeon_private_t *dev_priv = dev->dev_private;
3188 struct drm_radeon_driver_file_fields *radeon_priv;
3189
3190 DRM_DEBUG("\n");
3191 radeon_priv = kmalloc(sizeof(*radeon_priv), GFP_KERNEL);
3192
3193 if (!radeon_priv)
3194 return -ENOMEM;
3195
3196 file_priv->driver_priv = radeon_priv;
3197
3198 if (dev_priv)
3199 radeon_priv->radeon_fb_delta = dev_priv->fb_location;
3200 else
3201 radeon_priv->radeon_fb_delta = 0;
3202 return 0;
3203}
3204
3205void radeon_driver_postclose(struct drm_device *dev, struct drm_file *file_priv)
3206{
3207 struct drm_radeon_driver_file_fields *radeon_priv =
3208 file_priv->driver_priv;
3209
3210 kfree(radeon_priv);
3211}
3212
3213struct drm_ioctl_desc radeon_ioctls[] = {
3214 DRM_IOCTL_DEF(DRM_RADEON_CP_INIT, radeon_cp_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
3215 DRM_IOCTL_DEF(DRM_RADEON_CP_START, radeon_cp_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
3216 DRM_IOCTL_DEF(DRM_RADEON_CP_STOP, radeon_cp_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
3217 DRM_IOCTL_DEF(DRM_RADEON_CP_RESET, radeon_cp_reset, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
3218 DRM_IOCTL_DEF(DRM_RADEON_CP_IDLE, radeon_cp_idle, DRM_AUTH),
3219 DRM_IOCTL_DEF(DRM_RADEON_CP_RESUME, radeon_cp_resume, DRM_AUTH),
3220 DRM_IOCTL_DEF(DRM_RADEON_RESET, radeon_engine_reset, DRM_AUTH),
3221 DRM_IOCTL_DEF(DRM_RADEON_FULLSCREEN, radeon_fullscreen, DRM_AUTH),
3222 DRM_IOCTL_DEF(DRM_RADEON_SWAP, radeon_cp_swap, DRM_AUTH),
3223 DRM_IOCTL_DEF(DRM_RADEON_CLEAR, radeon_cp_clear, DRM_AUTH),
3224 DRM_IOCTL_DEF(DRM_RADEON_VERTEX, radeon_cp_vertex, DRM_AUTH),
3225 DRM_IOCTL_DEF(DRM_RADEON_INDICES, radeon_cp_indices, DRM_AUTH),
3226 DRM_IOCTL_DEF(DRM_RADEON_TEXTURE, radeon_cp_texture, DRM_AUTH),
3227 DRM_IOCTL_DEF(DRM_RADEON_STIPPLE, radeon_cp_stipple, DRM_AUTH),
3228 DRM_IOCTL_DEF(DRM_RADEON_INDIRECT, radeon_cp_indirect, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
3229 DRM_IOCTL_DEF(DRM_RADEON_VERTEX2, radeon_cp_vertex2, DRM_AUTH),
3230 DRM_IOCTL_DEF(DRM_RADEON_CMDBUF, radeon_cp_cmdbuf, DRM_AUTH),
3231 DRM_IOCTL_DEF(DRM_RADEON_GETPARAM, radeon_cp_getparam, DRM_AUTH),
3232 DRM_IOCTL_DEF(DRM_RADEON_FLIP, radeon_cp_flip, DRM_AUTH),
3233 DRM_IOCTL_DEF(DRM_RADEON_ALLOC, radeon_mem_alloc, DRM_AUTH),
3234 DRM_IOCTL_DEF(DRM_RADEON_FREE, radeon_mem_free, DRM_AUTH),
3235 DRM_IOCTL_DEF(DRM_RADEON_INIT_HEAP, radeon_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
3236 DRM_IOCTL_DEF(DRM_RADEON_IRQ_EMIT, radeon_irq_emit, DRM_AUTH),
3237 DRM_IOCTL_DEF(DRM_RADEON_IRQ_WAIT, radeon_irq_wait, DRM_AUTH),
3238 DRM_IOCTL_DEF(DRM_RADEON_SETPARAM, radeon_cp_setparam, DRM_AUTH),
3239 DRM_IOCTL_DEF(DRM_RADEON_SURF_ALLOC, radeon_surface_alloc, DRM_AUTH),
3240 DRM_IOCTL_DEF(DRM_RADEON_SURF_FREE, radeon_surface_free, DRM_AUTH),
3241 DRM_IOCTL_DEF(DRM_RADEON_CS, r600_cs_legacy_ioctl, DRM_AUTH)
3242};
3243
3244int radeon_max_ioctl = DRM_ARRAY_SIZE(radeon_ioctls);
3245