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
31
32
33
34#include "drmP.h"
35#include "drm.h"
36#include "radeon_drm.h"
37#include "radeon_drv.h"
38#include "r300_reg.h"
39
40#include <asm/unaligned.h>
41
42#define R300_SIMULTANEOUS_CLIPRECTS 4
43
44
45
46static const int r300_cliprect_cntl[4] = {
47 0xAAAA,
48 0xEEEE,
49 0xFEFE,
50 0xFFFE
51};
52
53
54
55
56
57static int r300_emit_cliprects(drm_radeon_private_t *dev_priv,
58 drm_radeon_kcmd_buffer_t *cmdbuf, int n)
59{
60 struct drm_clip_rect box;
61 int nr;
62 int i;
63 RING_LOCALS;
64
65 nr = cmdbuf->nbox - n;
66 if (nr > R300_SIMULTANEOUS_CLIPRECTS)
67 nr = R300_SIMULTANEOUS_CLIPRECTS;
68
69 DRM_DEBUG("%i cliprects\n", nr);
70
71 if (nr) {
72 BEGIN_RING(6 + nr * 2);
73 OUT_RING(CP_PACKET0(R300_RE_CLIPRECT_TL_0, nr * 2 - 1));
74
75 for (i = 0; i < nr; ++i) {
76 if (DRM_COPY_FROM_USER_UNCHECKED
77 (&box, &cmdbuf->boxes[n + i], sizeof(box))) {
78 DRM_ERROR("copy cliprect faulted\n");
79 return -EFAULT;
80 }
81
82 box.x2--;
83 box.y2--;
84
85 if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) {
86 box.x1 = (box.x1) &
87 R300_CLIPRECT_MASK;
88 box.y1 = (box.y1) &
89 R300_CLIPRECT_MASK;
90 box.x2 = (box.x2) &
91 R300_CLIPRECT_MASK;
92 box.y2 = (box.y2) &
93 R300_CLIPRECT_MASK;
94 } else {
95 box.x1 = (box.x1 + R300_CLIPRECT_OFFSET) &
96 R300_CLIPRECT_MASK;
97 box.y1 = (box.y1 + R300_CLIPRECT_OFFSET) &
98 R300_CLIPRECT_MASK;
99 box.x2 = (box.x2 + R300_CLIPRECT_OFFSET) &
100 R300_CLIPRECT_MASK;
101 box.y2 = (box.y2 + R300_CLIPRECT_OFFSET) &
102 R300_CLIPRECT_MASK;
103 }
104
105 OUT_RING((box.x1 << R300_CLIPRECT_X_SHIFT) |
106 (box.y1 << R300_CLIPRECT_Y_SHIFT));
107 OUT_RING((box.x2 << R300_CLIPRECT_X_SHIFT) |
108 (box.y2 << R300_CLIPRECT_Y_SHIFT));
109
110 }
111
112 OUT_RING_REG(R300_RE_CLIPRECT_CNTL, r300_cliprect_cntl[nr - 1]);
113
114
115
116
117
118
119 OUT_RING(CP_PACKET0(R300_RE_SCISSORS_TL, 1));
120 OUT_RING(0);
121 OUT_RING(R300_SCISSORS_X_MASK | R300_SCISSORS_Y_MASK);
122 ADVANCE_RING();
123 } else {
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139 BEGIN_RING(2);
140 OUT_RING_REG(R300_RE_CLIPRECT_CNTL, 0);
141 ADVANCE_RING();
142 }
143
144
145 BEGIN_RING(2);
146 OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
147 OUT_RING(R300_RB3D_DC_FLUSH);
148 ADVANCE_RING();
149 BEGIN_RING(2);
150 OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
151 OUT_RING(RADEON_WAIT_3D_IDLECLEAN);
152 ADVANCE_RING();
153
154 dev_priv->track_flush |= RADEON_FLUSH_EMITED;
155
156 return 0;
157}
158
159static u8 r300_reg_flags[0x10000 >> 2];
160
161void r300_init_reg_flags(struct drm_device *dev)
162{
163 int i;
164 drm_radeon_private_t *dev_priv = dev->dev_private;
165
166 memset(r300_reg_flags, 0, 0x10000 >> 2);
167#define ADD_RANGE_MARK(reg, count,mark) \
168 for(i=((reg)>>2);i<((reg)>>2)+(count);i++)\
169 r300_reg_flags[i]|=(mark);
170
171#define MARK_SAFE 1
172#define MARK_CHECK_OFFSET 2
173
174#define ADD_RANGE(reg, count) ADD_RANGE_MARK(reg, count, MARK_SAFE)
175
176
177 ADD_RANGE(R300_SE_VPORT_XSCALE, 6);
178 ADD_RANGE(R300_VAP_CNTL, 1);
179 ADD_RANGE(R300_SE_VTE_CNTL, 2);
180 ADD_RANGE(0x2134, 2);
181 ADD_RANGE(R300_VAP_CNTL_STATUS, 1);
182 ADD_RANGE(R300_VAP_INPUT_CNTL_0, 2);
183 ADD_RANGE(0x21DC, 1);
184 ADD_RANGE(R300_VAP_UNKNOWN_221C, 1);
185 ADD_RANGE(R300_VAP_CLIP_X_0, 4);
186 ADD_RANGE(R300_VAP_PVS_STATE_FLUSH_REG, 1);
187 ADD_RANGE(R300_VAP_UNKNOWN_2288, 1);
188 ADD_RANGE(R300_VAP_OUTPUT_VTX_FMT_0, 2);
189 ADD_RANGE(R300_VAP_PVS_CNTL_1, 3);
190 ADD_RANGE(R300_GB_ENABLE, 1);
191 ADD_RANGE(R300_GB_MSPOS0, 5);
192 ADD_RANGE(R300_TX_INVALTAGS, 1);
193 ADD_RANGE(R300_TX_ENABLE, 1);
194 ADD_RANGE(0x4200, 4);
195 ADD_RANGE(0x4214, 1);
196 ADD_RANGE(R300_RE_POINTSIZE, 1);
197 ADD_RANGE(0x4230, 3);
198 ADD_RANGE(R300_RE_LINE_CNT, 1);
199 ADD_RANGE(R300_RE_UNK4238, 1);
200 ADD_RANGE(0x4260, 3);
201 ADD_RANGE(R300_RE_SHADE, 4);
202 ADD_RANGE(R300_RE_POLYGON_MODE, 5);
203 ADD_RANGE(R300_RE_ZBIAS_CNTL, 1);
204 ADD_RANGE(R300_RE_ZBIAS_T_FACTOR, 4);
205 ADD_RANGE(R300_RE_OCCLUSION_CNTL, 1);
206 ADD_RANGE(R300_RE_CULL_CNTL, 1);
207 ADD_RANGE(0x42C0, 2);
208 ADD_RANGE(R300_RS_CNTL_0, 2);
209
210 ADD_RANGE(R300_SU_REG_DEST, 1);
211 if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV530)
212 ADD_RANGE(RV530_FG_ZBREG_DEST, 1);
213
214 ADD_RANGE(R300_SC_HYPERZ, 2);
215 ADD_RANGE(0x43E8, 1);
216
217 ADD_RANGE(0x46A4, 5);
218
219 ADD_RANGE(R300_RE_FOG_STATE, 1);
220 ADD_RANGE(R300_FOG_COLOR_R, 3);
221 ADD_RANGE(R300_PP_ALPHA_TEST, 2);
222 ADD_RANGE(0x4BD8, 1);
223 ADD_RANGE(R300_PFS_PARAM_0_X, 64);
224 ADD_RANGE(0x4E00, 1);
225 ADD_RANGE(R300_RB3D_CBLEND, 2);
226 ADD_RANGE(R300_RB3D_COLORMASK, 1);
227 ADD_RANGE(R300_RB3D_BLEND_COLOR, 3);
228 ADD_RANGE_MARK(R300_RB3D_COLOROFFSET0, 1, MARK_CHECK_OFFSET);
229 ADD_RANGE(R300_RB3D_COLORPITCH0, 1);
230 ADD_RANGE(0x4E50, 9);
231 ADD_RANGE(0x4E88, 1);
232 ADD_RANGE(0x4EA0, 2);
233 ADD_RANGE(R300_ZB_CNTL, 3);
234 ADD_RANGE(R300_ZB_FORMAT, 4);
235 ADD_RANGE_MARK(R300_ZB_DEPTHOFFSET, 1, MARK_CHECK_OFFSET);
236 ADD_RANGE(R300_ZB_DEPTHPITCH, 1);
237 ADD_RANGE(R300_ZB_DEPTHCLEARVALUE, 1);
238 ADD_RANGE(R300_ZB_ZMASK_OFFSET, 13);
239 ADD_RANGE(R300_ZB_ZPASS_DATA, 2);
240
241 ADD_RANGE(R300_TX_FILTER_0, 16);
242 ADD_RANGE(R300_TX_FILTER1_0, 16);
243 ADD_RANGE(R300_TX_SIZE_0, 16);
244 ADD_RANGE(R300_TX_FORMAT_0, 16);
245 ADD_RANGE(R300_TX_PITCH_0, 16);
246
247 ADD_RANGE_MARK(R300_TX_OFFSET_0, 16, MARK_CHECK_OFFSET);
248 ADD_RANGE(R300_TX_CHROMA_KEY_0, 16);
249 ADD_RANGE(R300_TX_BORDER_COLOR_0, 16);
250
251
252 ADD_RANGE(R300_ZB_ZCACHE_CTLSTAT, 1);
253 ADD_RANGE(R300_RB3D_DSTCACHE_CTLSTAT, 1);
254 ADD_RANGE(R300_VAP_INPUT_ROUTE_0_0, 8);
255 ADD_RANGE(R300_VAP_INPUT_ROUTE_1_0, 8);
256
257 if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) {
258 ADD_RANGE(R500_VAP_INDEX_OFFSET, 1);
259 ADD_RANGE(R500_US_CONFIG, 2);
260 ADD_RANGE(R500_US_CODE_ADDR, 3);
261 ADD_RANGE(R500_US_FC_CTRL, 1);
262 ADD_RANGE(R500_RS_IP_0, 16);
263 ADD_RANGE(R500_RS_INST_0, 16);
264 ADD_RANGE(R500_RB3D_COLOR_CLEAR_VALUE_AR, 2);
265 ADD_RANGE(R500_RB3D_CONSTANT_COLOR_AR, 2);
266 ADD_RANGE(R500_ZB_FIFO_SIZE, 2);
267 } else {
268 ADD_RANGE(R300_PFS_CNTL_0, 3);
269 ADD_RANGE(R300_PFS_NODE_0, 4);
270 ADD_RANGE(R300_PFS_TEXI_0, 64);
271 ADD_RANGE(R300_PFS_INSTR0_0, 64);
272 ADD_RANGE(R300_PFS_INSTR1_0, 64);
273 ADD_RANGE(R300_PFS_INSTR2_0, 64);
274 ADD_RANGE(R300_PFS_INSTR3_0, 64);
275 ADD_RANGE(R300_RS_INTERP_0, 8);
276 ADD_RANGE(R300_RS_ROUTE_0, 8);
277
278 }
279}
280
281static __inline__ int r300_check_range(unsigned reg, int count)
282{
283 int i;
284 if (reg & ~0xffff)
285 return -1;
286 for (i = (reg >> 2); i < (reg >> 2) + count; i++)
287 if (r300_reg_flags[i] != MARK_SAFE)
288 return 1;
289 return 0;
290}
291
292static __inline__ int r300_emit_carefully_checked_packet0(drm_radeon_private_t *
293 dev_priv,
294 drm_radeon_kcmd_buffer_t
295 * cmdbuf,
296 drm_r300_cmd_header_t
297 header)
298{
299 int reg;
300 int sz;
301 int i;
302 int values[64];
303 RING_LOCALS;
304
305 sz = header.packet0.count;
306 reg = (header.packet0.reghi << 8) | header.packet0.reglo;
307
308 if ((sz > 64) || (sz < 0)) {
309 DRM_ERROR
310 ("Cannot emit more than 64 values at a time (reg=%04x sz=%d)\n",
311 reg, sz);
312 return -EINVAL;
313 }
314 for (i = 0; i < sz; i++) {
315 values[i] = ((int *)cmdbuf->buf)[i];
316 switch (r300_reg_flags[(reg >> 2) + i]) {
317 case MARK_SAFE:
318 break;
319 case MARK_CHECK_OFFSET:
320 if (!radeon_check_offset(dev_priv, (u32) values[i])) {
321 DRM_ERROR
322 ("Offset failed range check (reg=%04x sz=%d)\n",
323 reg, sz);
324 return -EINVAL;
325 }
326 break;
327 default:
328 DRM_ERROR("Register %04x failed check as flag=%02x\n",
329 reg + i * 4, r300_reg_flags[(reg >> 2) + i]);
330 return -EINVAL;
331 }
332 }
333
334 BEGIN_RING(1 + sz);
335 OUT_RING(CP_PACKET0(reg, sz - 1));
336 OUT_RING_TABLE(values, sz);
337 ADVANCE_RING();
338
339 cmdbuf->buf += sz * 4;
340 cmdbuf->bufsz -= sz * 4;
341
342 return 0;
343}
344
345
346
347
348
349
350
351static __inline__ int r300_emit_packet0(drm_radeon_private_t *dev_priv,
352 drm_radeon_kcmd_buffer_t *cmdbuf,
353 drm_r300_cmd_header_t header)
354{
355 int reg;
356 int sz;
357 RING_LOCALS;
358
359 sz = header.packet0.count;
360 reg = (header.packet0.reghi << 8) | header.packet0.reglo;
361
362 if (!sz)
363 return 0;
364
365 if (sz * 4 > cmdbuf->bufsz)
366 return -EINVAL;
367
368 if (reg + sz * 4 >= 0x10000) {
369 DRM_ERROR("No such registers in hardware reg=%04x sz=%d\n", reg,
370 sz);
371 return -EINVAL;
372 }
373
374 if (r300_check_range(reg, sz)) {
375
376 return r300_emit_carefully_checked_packet0(dev_priv, cmdbuf,
377 header);
378 }
379
380
381 BEGIN_RING(1 + sz);
382 OUT_RING(CP_PACKET0(reg, sz - 1));
383 OUT_RING_TABLE((int *)cmdbuf->buf, sz);
384 ADVANCE_RING();
385
386 cmdbuf->buf += sz * 4;
387 cmdbuf->bufsz -= sz * 4;
388
389 return 0;
390}
391
392
393
394
395
396
397static __inline__ int r300_emit_vpu(drm_radeon_private_t *dev_priv,
398 drm_radeon_kcmd_buffer_t *cmdbuf,
399 drm_r300_cmd_header_t header)
400{
401 int sz;
402 int addr;
403 RING_LOCALS;
404
405 sz = header.vpu.count;
406 addr = (header.vpu.adrhi << 8) | header.vpu.adrlo;
407
408 if (!sz)
409 return 0;
410 if (sz * 16 > cmdbuf->bufsz)
411 return -EINVAL;
412
413
414
415 BEGIN_RING(6);
416 OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
417 OUT_RING(R300_RB3D_DC_FLUSH);
418 OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
419 OUT_RING(RADEON_WAIT_3D_IDLECLEAN);
420 OUT_RING(CP_PACKET0(R300_VAP_PVS_STATE_FLUSH_REG, 0));
421 OUT_RING(0);
422 ADVANCE_RING();
423
424 dev_priv->track_flush |= RADEON_FLUSH_EMITED;
425
426 BEGIN_RING(3 + sz * 4);
427 OUT_RING_REG(R300_VAP_PVS_UPLOAD_ADDRESS, addr);
428 OUT_RING(CP_PACKET0_TABLE(R300_VAP_PVS_UPLOAD_DATA, sz * 4 - 1));
429 OUT_RING_TABLE((int *)cmdbuf->buf, sz * 4);
430 ADVANCE_RING();
431
432 BEGIN_RING(2);
433 OUT_RING(CP_PACKET0(R300_VAP_PVS_STATE_FLUSH_REG, 0));
434 OUT_RING(0);
435 ADVANCE_RING();
436
437 cmdbuf->buf += sz * 16;
438 cmdbuf->bufsz -= sz * 16;
439
440 return 0;
441}
442
443
444
445
446
447static __inline__ int r300_emit_clear(drm_radeon_private_t *dev_priv,
448 drm_radeon_kcmd_buffer_t *cmdbuf)
449{
450 RING_LOCALS;
451
452 if (8 * 4 > cmdbuf->bufsz)
453 return -EINVAL;
454
455 BEGIN_RING(10);
456 OUT_RING(CP_PACKET3(R200_3D_DRAW_IMMD_2, 8));
457 OUT_RING(R300_PRIM_TYPE_POINT | R300_PRIM_WALK_RING |
458 (1 << R300_PRIM_NUM_VERTICES_SHIFT));
459 OUT_RING_TABLE((int *)cmdbuf->buf, 8);
460 ADVANCE_RING();
461
462 BEGIN_RING(4);
463 OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
464 OUT_RING(R300_RB3D_DC_FLUSH);
465 OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
466 OUT_RING(RADEON_WAIT_3D_IDLECLEAN);
467 ADVANCE_RING();
468
469 dev_priv->track_flush |= RADEON_FLUSH_EMITED;
470
471 cmdbuf->buf += 8 * 4;
472 cmdbuf->bufsz -= 8 * 4;
473
474 return 0;
475}
476
477static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t *dev_priv,
478 drm_radeon_kcmd_buffer_t *cmdbuf,
479 u32 header)
480{
481 int count, i, k;
482#define MAX_ARRAY_PACKET 64
483 u32 payload[MAX_ARRAY_PACKET];
484 u32 narrays;
485 RING_LOCALS;
486
487 count = (header >> 16) & 0x3fff;
488
489 if ((count + 1) > MAX_ARRAY_PACKET) {
490 DRM_ERROR("Too large payload in 3D_LOAD_VBPNTR (count=%d)\n",
491 count);
492 return -EINVAL;
493 }
494 memset(payload, 0, MAX_ARRAY_PACKET * 4);
495 memcpy(payload, cmdbuf->buf + 4, (count + 1) * 4);
496
497
498
499 narrays = payload[0];
500 k = 0;
501 i = 1;
502 while ((k < narrays) && (i < (count + 1))) {
503 i++;
504 if (!radeon_check_offset(dev_priv, payload[i])) {
505 DRM_ERROR
506 ("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n",
507 k, i);
508 return -EINVAL;
509 }
510 k++;
511 i++;
512 if (k == narrays)
513 break;
514
515 if (!radeon_check_offset(dev_priv, payload[i])) {
516 DRM_ERROR
517 ("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n",
518 k, i);
519 return -EINVAL;
520 }
521 k++;
522 i++;
523 }
524
525 if ((k != narrays) || (i != (count + 1))) {
526 DRM_ERROR
527 ("Malformed 3D_LOAD_VBPNTR packet (k=%d i=%d narrays=%d count+1=%d).\n",
528 k, i, narrays, count + 1);
529 return -EINVAL;
530 }
531
532
533
534 BEGIN_RING(count + 2);
535 OUT_RING(header);
536 OUT_RING_TABLE(payload, count + 1);
537 ADVANCE_RING();
538
539 cmdbuf->buf += (count + 2) * 4;
540 cmdbuf->bufsz -= (count + 2) * 4;
541
542 return 0;
543}
544
545static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv,
546 drm_radeon_kcmd_buffer_t *cmdbuf)
547{
548 u32 *cmd = (u32 *) cmdbuf->buf;
549 int count, ret;
550 RING_LOCALS;
551
552 count=(cmd[0]>>16) & 0x3fff;
553
554 if (cmd[0] & 0x8000) {
555 u32 offset;
556
557 if (cmd[1] & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL
558 | RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
559 offset = cmd[2] << 10;
560 ret = !radeon_check_offset(dev_priv, offset);
561 if (ret) {
562 DRM_ERROR("Invalid bitblt first offset is %08X\n", offset);
563 return -EINVAL;
564 }
565 }
566
567 if ((cmd[1] & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) &&
568 (cmd[1] & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
569 offset = cmd[3] << 10;
570 ret = !radeon_check_offset(dev_priv, offset);
571 if (ret) {
572 DRM_ERROR("Invalid bitblt second offset is %08X\n", offset);
573 return -EINVAL;
574 }
575
576 }
577 }
578
579 BEGIN_RING(count+2);
580 OUT_RING(cmd[0]);
581 OUT_RING_TABLE((int *)(cmdbuf->buf + 4), count + 1);
582 ADVANCE_RING();
583
584 cmdbuf->buf += (count+2)*4;
585 cmdbuf->bufsz -= (count+2)*4;
586
587 return 0;
588}
589
590static __inline__ int r300_emit_draw_indx_2(drm_radeon_private_t *dev_priv,
591 drm_radeon_kcmd_buffer_t *cmdbuf)
592{
593 u32 *cmd;
594 int count;
595 int expected_count;
596 RING_LOCALS;
597
598 cmd = (u32 *) cmdbuf->buf;
599 count = (cmd[0]>>16) & 0x3fff;
600 expected_count = cmd[1] >> 16;
601 if (!(cmd[1] & R300_VAP_VF_CNTL__INDEX_SIZE_32bit))
602 expected_count = (expected_count+1)/2;
603
604 if (count && count != expected_count) {
605 DRM_ERROR("3D_DRAW_INDX_2: packet size %i, expected %i\n",
606 count, expected_count);
607 return -EINVAL;
608 }
609
610 BEGIN_RING(count+2);
611 OUT_RING(cmd[0]);
612 OUT_RING_TABLE((int *)(cmdbuf->buf + 4), count + 1);
613 ADVANCE_RING();
614
615 cmdbuf->buf += (count+2)*4;
616 cmdbuf->bufsz -= (count+2)*4;
617
618 if (!count) {
619 drm_r300_cmd_header_t header;
620
621 if (cmdbuf->bufsz < 4*4 + sizeof(header)) {
622 DRM_ERROR("3D_DRAW_INDX_2: expect subsequent INDX_BUFFER, but stream is too short.\n");
623 return -EINVAL;
624 }
625
626 header.u = *(unsigned int *)cmdbuf->buf;
627
628 cmdbuf->buf += sizeof(header);
629 cmdbuf->bufsz -= sizeof(header);
630 cmd = (u32 *) cmdbuf->buf;
631
632 if (header.header.cmd_type != R300_CMD_PACKET3 ||
633 header.packet3.packet != R300_CMD_PACKET3_RAW ||
634 cmd[0] != CP_PACKET3(RADEON_CP_INDX_BUFFER, 2)) {
635 DRM_ERROR("3D_DRAW_INDX_2: expect subsequent INDX_BUFFER.\n");
636 return -EINVAL;
637 }
638
639 if ((cmd[1] & 0x8000ffff) != 0x80000810) {
640 DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]);
641 return -EINVAL;
642 }
643 if (!radeon_check_offset(dev_priv, cmd[2])) {
644 DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]);
645 return -EINVAL;
646 }
647 if (cmd[3] != expected_count) {
648 DRM_ERROR("INDX_BUFFER: buffer size %i, expected %i\n",
649 cmd[3], expected_count);
650 return -EINVAL;
651 }
652
653 BEGIN_RING(4);
654 OUT_RING(cmd[0]);
655 OUT_RING_TABLE((int *)(cmdbuf->buf + 4), 3);
656 ADVANCE_RING();
657
658 cmdbuf->buf += 4*4;
659 cmdbuf->bufsz -= 4*4;
660 }
661
662 return 0;
663}
664
665static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv,
666 drm_radeon_kcmd_buffer_t *cmdbuf)
667{
668 u32 header;
669 int count;
670 RING_LOCALS;
671
672 if (4 > cmdbuf->bufsz)
673 return -EINVAL;
674
675
676
677
678
679 header = *(u32 *) cmdbuf->buf;
680
681
682 if ((header >> 30) != 0x3) {
683 DRM_ERROR("Not a packet3 header (0x%08x)\n", header);
684 return -EINVAL;
685 }
686
687 count = (header >> 16) & 0x3fff;
688
689
690 if ((count + 2) * 4 > cmdbuf->bufsz) {
691 DRM_ERROR
692 ("Expected packet3 of length %d but have only %d bytes left\n",
693 (count + 2) * 4, cmdbuf->bufsz);
694 return -EINVAL;
695 }
696
697
698 switch (header & 0xff00) {
699 case RADEON_3D_LOAD_VBPNTR:
700 return r300_emit_3d_load_vbpntr(dev_priv, cmdbuf, header);
701
702 case RADEON_CNTL_BITBLT_MULTI:
703 return r300_emit_bitblt_multi(dev_priv, cmdbuf);
704
705 case RADEON_CP_INDX_BUFFER:
706 DRM_ERROR("packet3 INDX_BUFFER without preceding 3D_DRAW_INDX_2 is illegal.\n");
707 return -EINVAL;
708 case RADEON_CP_3D_DRAW_IMMD_2:
709
710 case RADEON_CP_3D_DRAW_VBUF_2:
711
712 dev_priv->track_flush &= ~(RADEON_FLUSH_EMITED |
713 RADEON_PURGE_EMITED);
714 break;
715 case RADEON_CP_3D_DRAW_INDX_2:
716
717
718 dev_priv->track_flush &= ~(RADEON_FLUSH_EMITED |
719 RADEON_PURGE_EMITED);
720 return r300_emit_draw_indx_2(dev_priv, cmdbuf);
721 case RADEON_WAIT_FOR_IDLE:
722 case RADEON_CP_NOP:
723
724 break;
725 default:
726 DRM_ERROR("Unknown packet3 header (0x%08x)\n", header);
727 return -EINVAL;
728 }
729
730 BEGIN_RING(count + 2);
731 OUT_RING(header);
732 OUT_RING_TABLE((int *)(cmdbuf->buf + 4), count + 1);
733 ADVANCE_RING();
734
735 cmdbuf->buf += (count + 2) * 4;
736 cmdbuf->bufsz -= (count + 2) * 4;
737
738 return 0;
739}
740
741
742
743
744
745static __inline__ int r300_emit_packet3(drm_radeon_private_t *dev_priv,
746 drm_radeon_kcmd_buffer_t *cmdbuf,
747 drm_r300_cmd_header_t header)
748{
749 int n;
750 int ret;
751 char *orig_buf = cmdbuf->buf;
752 int orig_bufsz = cmdbuf->bufsz;
753
754
755
756
757 n = 0;
758 do {
759 if (cmdbuf->nbox > R300_SIMULTANEOUS_CLIPRECTS) {
760 ret = r300_emit_cliprects(dev_priv, cmdbuf, n);
761 if (ret)
762 return ret;
763
764 cmdbuf->buf = orig_buf;
765 cmdbuf->bufsz = orig_bufsz;
766 }
767
768 switch (header.packet3.packet) {
769 case R300_CMD_PACKET3_CLEAR:
770 DRM_DEBUG("R300_CMD_PACKET3_CLEAR\n");
771 ret = r300_emit_clear(dev_priv, cmdbuf);
772 if (ret) {
773 DRM_ERROR("r300_emit_clear failed\n");
774 return ret;
775 }
776 break;
777
778 case R300_CMD_PACKET3_RAW:
779 DRM_DEBUG("R300_CMD_PACKET3_RAW\n");
780 ret = r300_emit_raw_packet3(dev_priv, cmdbuf);
781 if (ret) {
782 DRM_ERROR("r300_emit_raw_packet3 failed\n");
783 return ret;
784 }
785 break;
786
787 default:
788 DRM_ERROR("bad packet3 type %i at %p\n",
789 header.packet3.packet,
790 cmdbuf->buf - sizeof(header));
791 return -EINVAL;
792 }
793
794 n += R300_SIMULTANEOUS_CLIPRECTS;
795 } while (n < cmdbuf->nbox);
796
797 return 0;
798}
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814static __inline__ void r300_pacify(drm_radeon_private_t *dev_priv)
815{
816 uint32_t cache_z, cache_3d, cache_2d;
817 RING_LOCALS;
818
819 cache_z = R300_ZC_FLUSH;
820 cache_2d = R300_RB2D_DC_FLUSH;
821 cache_3d = R300_RB3D_DC_FLUSH;
822 if (!(dev_priv->track_flush & RADEON_PURGE_EMITED)) {
823
824 cache_z |= R300_ZC_FREE;
825 cache_2d |= R300_RB2D_DC_FREE;
826 cache_3d |= R300_RB3D_DC_FREE;
827 }
828
829
830 BEGIN_RING(2);
831 OUT_RING(CP_PACKET0(R300_ZB_ZCACHE_CTLSTAT, 0));
832 OUT_RING(cache_z);
833 ADVANCE_RING();
834
835 BEGIN_RING(2);
836 OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
837 OUT_RING(cache_3d);
838 ADVANCE_RING();
839
840 BEGIN_RING(2);
841 OUT_RING(CP_PACKET0(R300_TX_INVALTAGS, 0));
842 OUT_RING(0);
843 ADVANCE_RING();
844
845 BEGIN_RING(2);
846 OUT_RING(CP_PACKET0(R300_RB3D_AARESOLVE_CTL, 0));
847 OUT_RING(0);
848 ADVANCE_RING();
849 BEGIN_RING(2);
850 OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
851 OUT_RING(RADEON_WAIT_3D_IDLECLEAN);
852 ADVANCE_RING();
853
854 BEGIN_RING(4);
855 OUT_RING(CP_PACKET0(R300_DSTCACHE_CTLSTAT, 0));
856 OUT_RING(cache_2d);
857 OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
858 OUT_RING(RADEON_WAIT_2D_IDLECLEAN |
859 RADEON_WAIT_HOST_IDLECLEAN);
860 ADVANCE_RING();
861
862 dev_priv->track_flush |= RADEON_FLUSH_EMITED | RADEON_PURGE_EMITED;
863}
864
865
866
867
868
869
870static void r300_discard_buffer(struct drm_device *dev, struct drm_master *master, struct drm_buf *buf)
871{
872 drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
873 struct drm_radeon_master_private *master_priv = master->driver_priv;
874
875 buf_priv->age = ++master_priv->sarea_priv->last_dispatch;
876 buf->pending = 1;
877 buf->used = 0;
878}
879
880static void r300_cmd_wait(drm_radeon_private_t * dev_priv,
881 drm_r300_cmd_header_t header)
882{
883 u32 wait_until;
884 RING_LOCALS;
885
886 if (!header.wait.flags)
887 return;
888
889 wait_until = 0;
890
891 switch(header.wait.flags) {
892 case R300_WAIT_2D:
893 wait_until = RADEON_WAIT_2D_IDLE;
894 break;
895 case R300_WAIT_3D:
896 wait_until = RADEON_WAIT_3D_IDLE;
897 break;
898 case R300_NEW_WAIT_2D_3D:
899 wait_until = RADEON_WAIT_2D_IDLE|RADEON_WAIT_3D_IDLE;
900 break;
901 case R300_NEW_WAIT_2D_2D_CLEAN:
902 wait_until = RADEON_WAIT_2D_IDLE|RADEON_WAIT_2D_IDLECLEAN;
903 break;
904 case R300_NEW_WAIT_3D_3D_CLEAN:
905 wait_until = RADEON_WAIT_3D_IDLE|RADEON_WAIT_3D_IDLECLEAN;
906 break;
907 case R300_NEW_WAIT_2D_2D_CLEAN_3D_3D_CLEAN:
908 wait_until = RADEON_WAIT_2D_IDLE|RADEON_WAIT_2D_IDLECLEAN;
909 wait_until |= RADEON_WAIT_3D_IDLE|RADEON_WAIT_3D_IDLECLEAN;
910 break;
911 default:
912 return;
913 }
914
915 BEGIN_RING(2);
916 OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
917 OUT_RING(wait_until);
918 ADVANCE_RING();
919}
920
921static int r300_scratch(drm_radeon_private_t *dev_priv,
922 drm_radeon_kcmd_buffer_t *cmdbuf,
923 drm_r300_cmd_header_t header)
924{
925 u32 *ref_age_base;
926 u32 i, buf_idx, h_pending;
927 u64 ptr_addr;
928 RING_LOCALS;
929
930 if (cmdbuf->bufsz <
931 (sizeof(u64) + header.scratch.n_bufs * sizeof(buf_idx))) {
932 return -EINVAL;
933 }
934
935 if (header.scratch.reg >= 5) {
936 return -EINVAL;
937 }
938
939 dev_priv->scratch_ages[header.scratch.reg]++;
940
941 ptr_addr = get_unaligned((u64 *)cmdbuf->buf);
942 ref_age_base = (u32 *)(unsigned long)ptr_addr;
943
944 cmdbuf->buf += sizeof(u64);
945 cmdbuf->bufsz -= sizeof(u64);
946
947 for (i=0; i < header.scratch.n_bufs; i++) {
948 buf_idx = *(u32 *)cmdbuf->buf;
949 buf_idx *= 2;
950
951 if (DRM_COPY_TO_USER(ref_age_base + buf_idx, &dev_priv->scratch_ages[header.scratch.reg], sizeof(u32))) {
952 return -EINVAL;
953 }
954
955 if (DRM_COPY_FROM_USER(&h_pending, ref_age_base + buf_idx + 1, sizeof(u32))) {
956 return -EINVAL;
957 }
958
959 if (h_pending == 0) {
960 return -EINVAL;
961 }
962
963 h_pending--;
964
965 if (DRM_COPY_TO_USER(ref_age_base + buf_idx + 1, &h_pending, sizeof(u32))) {
966 return -EINVAL;
967 }
968
969 cmdbuf->buf += sizeof(buf_idx);
970 cmdbuf->bufsz -= sizeof(buf_idx);
971 }
972
973 BEGIN_RING(2);
974 OUT_RING( CP_PACKET0( RADEON_SCRATCH_REG0 + header.scratch.reg * 4, 0 ) );
975 OUT_RING( dev_priv->scratch_ages[header.scratch.reg] );
976 ADVANCE_RING();
977
978 return 0;
979}
980
981
982
983
984
985
986static inline int r300_emit_r500fp(drm_radeon_private_t *dev_priv,
987 drm_radeon_kcmd_buffer_t *cmdbuf,
988 drm_r300_cmd_header_t header)
989{
990 int sz;
991 int addr;
992 int type;
993 int clamp;
994 int stride;
995 RING_LOCALS;
996
997 sz = header.r500fp.count;
998
999 addr = ((header.r500fp.adrhi_flags & 1) << 8) | header.r500fp.adrlo;
1000
1001 type = !!(header.r500fp.adrhi_flags & R500FP_CONSTANT_TYPE);
1002 clamp = !!(header.r500fp.adrhi_flags & R500FP_CONSTANT_CLAMP);
1003
1004 addr |= (type << 16);
1005 addr |= (clamp << 17);
1006
1007 stride = type ? 4 : 6;
1008
1009 DRM_DEBUG("r500fp %d %d type: %d\n", sz, addr, type);
1010 if (!sz)
1011 return 0;
1012 if (sz * stride * 4 > cmdbuf->bufsz)
1013 return -EINVAL;
1014
1015 BEGIN_RING(3 + sz * stride);
1016 OUT_RING_REG(R500_GA_US_VECTOR_INDEX, addr);
1017 OUT_RING(CP_PACKET0_TABLE(R500_GA_US_VECTOR_DATA, sz * stride - 1));
1018 OUT_RING_TABLE((int *)cmdbuf->buf, sz * stride);
1019
1020 ADVANCE_RING();
1021
1022 cmdbuf->buf += sz * stride * 4;
1023 cmdbuf->bufsz -= sz * stride * 4;
1024
1025 return 0;
1026}
1027
1028
1029
1030
1031
1032
1033
1034int r300_do_cp_cmdbuf(struct drm_device *dev,
1035 struct drm_file *file_priv,
1036 drm_radeon_kcmd_buffer_t *cmdbuf)
1037{
1038 drm_radeon_private_t *dev_priv = dev->dev_private;
1039 struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
1040 struct drm_device_dma *dma = dev->dma;
1041 struct drm_buf *buf = NULL;
1042 int emit_dispatch_age = 0;
1043 int ret = 0;
1044
1045 DRM_DEBUG("\n");
1046
1047
1048 r300_pacify(dev_priv);
1049
1050 if (cmdbuf->nbox <= R300_SIMULTANEOUS_CLIPRECTS) {
1051 ret = r300_emit_cliprects(dev_priv, cmdbuf, 0);
1052 if (ret)
1053 goto cleanup;
1054 }
1055
1056 while (cmdbuf->bufsz >= sizeof(drm_r300_cmd_header_t)) {
1057 int idx;
1058 drm_r300_cmd_header_t header;
1059
1060 header.u = *(unsigned int *)cmdbuf->buf;
1061
1062 cmdbuf->buf += sizeof(header);
1063 cmdbuf->bufsz -= sizeof(header);
1064
1065 switch (header.header.cmd_type) {
1066 case R300_CMD_PACKET0:
1067 DRM_DEBUG("R300_CMD_PACKET0\n");
1068 ret = r300_emit_packet0(dev_priv, cmdbuf, header);
1069 if (ret) {
1070 DRM_ERROR("r300_emit_packet0 failed\n");
1071 goto cleanup;
1072 }
1073 break;
1074
1075 case R300_CMD_VPU:
1076 DRM_DEBUG("R300_CMD_VPU\n");
1077 ret = r300_emit_vpu(dev_priv, cmdbuf, header);
1078 if (ret) {
1079 DRM_ERROR("r300_emit_vpu failed\n");
1080 goto cleanup;
1081 }
1082 break;
1083
1084 case R300_CMD_PACKET3:
1085 DRM_DEBUG("R300_CMD_PACKET3\n");
1086 ret = r300_emit_packet3(dev_priv, cmdbuf, header);
1087 if (ret) {
1088 DRM_ERROR("r300_emit_packet3 failed\n");
1089 goto cleanup;
1090 }
1091 break;
1092
1093 case R300_CMD_END3D:
1094 DRM_DEBUG("R300_CMD_END3D\n");
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110 r300_pacify(dev_priv);
1111 break;
1112
1113 case R300_CMD_CP_DELAY:
1114
1115 DRM_DEBUG("R300_CMD_CP_DELAY\n");
1116 {
1117 int i;
1118 RING_LOCALS;
1119
1120 BEGIN_RING(header.delay.count);
1121 for (i = 0; i < header.delay.count; i++)
1122 OUT_RING(RADEON_CP_PACKET2);
1123 ADVANCE_RING();
1124 }
1125 break;
1126
1127 case R300_CMD_DMA_DISCARD:
1128 DRM_DEBUG("RADEON_CMD_DMA_DISCARD\n");
1129 idx = header.dma.buf_idx;
1130 if (idx < 0 || idx >= dma->buf_count) {
1131 DRM_ERROR("buffer index %d (of %d max)\n",
1132 idx, dma->buf_count - 1);
1133 ret = -EINVAL;
1134 goto cleanup;
1135 }
1136
1137 buf = dma->buflist[idx];
1138 if (buf->file_priv != file_priv || buf->pending) {
1139 DRM_ERROR("bad buffer %p %p %d\n",
1140 buf->file_priv, file_priv,
1141 buf->pending);
1142 ret = -EINVAL;
1143 goto cleanup;
1144 }
1145
1146 emit_dispatch_age = 1;
1147 r300_discard_buffer(dev, file_priv->master, buf);
1148 break;
1149
1150 case R300_CMD_WAIT:
1151 DRM_DEBUG("R300_CMD_WAIT\n");
1152 r300_cmd_wait(dev_priv, header);
1153 break;
1154
1155 case R300_CMD_SCRATCH:
1156 DRM_DEBUG("R300_CMD_SCRATCH\n");
1157 ret = r300_scratch(dev_priv, cmdbuf, header);
1158 if (ret) {
1159 DRM_ERROR("r300_scratch failed\n");
1160 goto cleanup;
1161 }
1162 break;
1163
1164 case R300_CMD_R500FP:
1165 if ((dev_priv->flags & RADEON_FAMILY_MASK) < CHIP_RV515) {
1166 DRM_ERROR("Calling r500 command on r300 card\n");
1167 ret = -EINVAL;
1168 goto cleanup;
1169 }
1170 DRM_DEBUG("R300_CMD_R500FP\n");
1171 ret = r300_emit_r500fp(dev_priv, cmdbuf, header);
1172 if (ret) {
1173 DRM_ERROR("r300_emit_r500fp failed\n");
1174 goto cleanup;
1175 }
1176 break;
1177 default:
1178 DRM_ERROR("bad cmd_type %i at %p\n",
1179 header.header.cmd_type,
1180 cmdbuf->buf - sizeof(header));
1181 ret = -EINVAL;
1182 goto cleanup;
1183 }
1184 }
1185
1186 DRM_DEBUG("END\n");
1187
1188 cleanup:
1189 r300_pacify(dev_priv);
1190
1191
1192
1193
1194
1195
1196
1197 if (emit_dispatch_age) {
1198 RING_LOCALS;
1199
1200
1201 BEGIN_RING(2);
1202 RADEON_DISPATCH_AGE(master_priv->sarea_priv->last_dispatch);
1203 ADVANCE_RING();
1204 }
1205
1206 COMMIT_RING();
1207
1208 return ret;
1209}
1210