2 * Copyright 2008 Jerome Glisse.
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
25 * Jerome Glisse <glisse@freedesktop.org>
26 * __FBSDID("$FreeBSD: src/sys/dev/drm/radeon_cs.c,v 1.2 2009/09/28 22:41:28 rnoland Exp $");
29 #include "dev/drm/drmP.h"
30 #include "dev/drm/radeon_drm.h"
31 #include "radeon_drv.h"
34 #define AVIVO_D1MODE_VLINE_START_END 0x6538
35 #define AVIVO_D2MODE_VLINE_START_END 0x6d38
36 #define R600_CP_COHER_BASE 0x85f8
37 #define R600_DB_DEPTH_BASE 0x2800c
38 #define R600_CB_COLOR0_BASE 0x28040
39 #define R600_CB_COLOR1_BASE 0x28044
40 #define R600_CB_COLOR2_BASE 0x28048
41 #define R600_CB_COLOR3_BASE 0x2804c
42 #define R600_CB_COLOR4_BASE 0x28050
43 #define R600_CB_COLOR5_BASE 0x28054
44 #define R600_CB_COLOR6_BASE 0x28058
45 #define R600_CB_COLOR7_BASE 0x2805c
46 #define R600_SQ_PGM_START_FS 0x28894
47 #define R600_SQ_PGM_START_ES 0x28880
48 #define R600_SQ_PGM_START_VS 0x28858
49 #define R600_SQ_PGM_START_GS 0x2886c
50 #define R600_SQ_PGM_START_PS 0x28840
51 #define R600_VGT_DMA_BASE 0x287e8
52 #define R600_VGT_DMA_BASE_HI 0x287e4
53 #define R600_VGT_STRMOUT_BASE_OFFSET_0 0x28b10
54 #define R600_VGT_STRMOUT_BASE_OFFSET_1 0x28b14
55 #define R600_VGT_STRMOUT_BASE_OFFSET_2 0x28b18
56 #define R600_VGT_STRMOUT_BASE_OFFSET_3 0x28b1c
57 #define R600_VGT_STRMOUT_BASE_OFFSET_HI_0 0x28b44
58 #define R600_VGT_STRMOUT_BASE_OFFSET_HI_1 0x28b48
59 #define R600_VGT_STRMOUT_BASE_OFFSET_HI_2 0x28b4c
60 #define R600_VGT_STRMOUT_BASE_OFFSET_HI_3 0x28b50
61 #define R600_VGT_STRMOUT_BUFFER_BASE_0 0x28ad8
62 #define R600_VGT_STRMOUT_BUFFER_BASE_1 0x28ae8
63 #define R600_VGT_STRMOUT_BUFFER_BASE_2 0x28af8
64 #define R600_VGT_STRMOUT_BUFFER_BASE_3 0x28b08
65 #define R600_VGT_STRMOUT_BUFFER_OFFSET_0 0x28adc
66 #define R600_VGT_STRMOUT_BUFFER_OFFSET_1 0x28aec
67 #define R600_VGT_STRMOUT_BUFFER_OFFSET_2 0x28afc
68 #define R600_VGT_STRMOUT_BUFFER_OFFSET_3 0x28b0c
71 #define R600_SQ_TEX_VTX_INVALID_TEXTURE 0x0
72 #define R600_SQ_TEX_VTX_INVALID_BUFFER 0x1
73 #define R600_SQ_TEX_VTX_VALID_TEXTURE 0x2
74 #define R600_SQ_TEX_VTX_VALID_BUFFER 0x3
76 /* packet 3 type offsets */
77 #define R600_SET_CONFIG_REG_OFFSET 0x00008000
78 #define R600_SET_CONFIG_REG_END 0x0000ac00
79 #define R600_SET_CONTEXT_REG_OFFSET 0x00028000
80 #define R600_SET_CONTEXT_REG_END 0x00029000
81 #define R600_SET_ALU_CONST_OFFSET 0x00030000
82 #define R600_SET_ALU_CONST_END 0x00032000
83 #define R600_SET_RESOURCE_OFFSET 0x00038000
84 #define R600_SET_RESOURCE_END 0x0003c000
85 #define R600_SET_SAMPLER_OFFSET 0x0003c000
86 #define R600_SET_SAMPLER_END 0x0003cff0
87 #define R600_SET_CTL_CONST_OFFSET 0x0003cff0
88 #define R600_SET_CTL_CONST_END 0x0003e200
89 #define R600_SET_LOOP_CONST_OFFSET 0x0003e200
90 #define R600_SET_LOOP_CONST_END 0x0003e380
91 #define R600_SET_BOOL_CONST_OFFSET 0x0003e380
92 #define R600_SET_BOOL_CONST_END 0x00040000
95 #define R600_IT_INDIRECT_BUFFER_END 0x00001700
96 #define R600_IT_SET_PREDICATION 0x00002000
97 #define R600_IT_REG_RMW 0x00002100
98 #define R600_IT_COND_EXEC 0x00002200
99 #define R600_IT_PRED_EXEC 0x00002300
100 #define R600_IT_START_3D_CMDBUF 0x00002400
101 #define R600_IT_DRAW_INDEX_2 0x00002700
102 #define R600_IT_CONTEXT_CONTROL 0x00002800
103 #define R600_IT_DRAW_INDEX_IMMD_BE 0x00002900
104 #define R600_IT_INDEX_TYPE 0x00002A00
105 #define R600_IT_DRAW_INDEX 0x00002B00
106 #define R600_IT_DRAW_INDEX_AUTO 0x00002D00
107 #define R600_IT_DRAW_INDEX_IMMD 0x00002E00
108 #define R600_IT_NUM_INSTANCES 0x00002F00
109 #define R600_IT_STRMOUT_BUFFER_UPDATE 0x00003400
110 #define R600_IT_INDIRECT_BUFFER_MP 0x00003800
111 #define R600_IT_MEM_SEMAPHORE 0x00003900
112 #define R600_IT_MPEG_INDEX 0x00003A00
113 #define R600_IT_WAIT_REG_MEM 0x00003C00
114 #define R600_IT_MEM_WRITE 0x00003D00
115 #define R600_IT_INDIRECT_BUFFER 0x00003200
116 #define R600_IT_CP_INTERRUPT 0x00004000
117 #define R600_IT_SURFACE_SYNC 0x00004300
118 #define R600_IT_ME_INITIALIZE 0x00004400
119 #define R600_IT_COND_WRITE 0x00004500
120 #define R600_IT_EVENT_WRITE 0x00004600
121 #define R600_IT_EVENT_WRITE_EOP 0x00004700
122 #define R600_IT_ONE_REG_WRITE 0x00005700
123 #define R600_IT_SET_CONFIG_REG 0x00006800
124 #define R600_IT_SET_CONTEXT_REG 0x00006900
125 #define R600_IT_SET_ALU_CONST 0x00006A00
126 #define R600_IT_SET_BOOL_CONST 0x00006B00
127 #define R600_IT_SET_LOOP_CONST 0x00006C00
128 #define R600_IT_SET_RESOURCE 0x00006D00
129 #define R600_IT_SET_SAMPLER 0x00006E00
130 #define R600_IT_SET_CTL_CONST 0x00006F00
131 #define R600_IT_SURFACE_BASE_UPDATE 0x00007300
133 int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv)
135 struct drm_radeon_cs_parser parser;
136 struct drm_radeon_private *dev_priv = dev->dev_private;
137 struct drm_radeon_cs *cs = data;
139 struct drm_radeon_cs_chunk __user **chunk_ptr = NULL;
140 uint64_t *chunk_array;
141 uint64_t *chunk_array_ptr;
145 if (dev_priv == NULL) {
146 DRM_ERROR("called with no initialization\n");
149 DRM_SPINLOCK(&dev_priv->cs.cs_mutex);
150 /* set command stream id to 0 which is fake id */
154 if (!cs->num_chunks) {
155 DRM_SPINUNLOCK(&dev_priv->cs.cs_mutex);
160 chunk_array = drm_calloc(cs->num_chunks, sizeof(uint64_t), DRM_MEM_DRIVER);
162 DRM_SPINUNLOCK(&dev_priv->cs.cs_mutex);
166 chunk_array_ptr = (uint64_t *)(unsigned long)(cs->chunks);
168 if (DRM_COPY_FROM_USER(chunk_array, chunk_array_ptr, sizeof(uint64_t)*cs->num_chunks)) {
174 parser.file_priv = fpriv;
175 parser.reloc_index = -1;
176 parser.ib_index = -1;
177 parser.num_chunks = cs->num_chunks;
178 /* copy out the chunk headers */
179 parser.chunks = drm_calloc(parser.num_chunks, sizeof(struct drm_radeon_kernel_chunk), DRM_MEM_DRIVER);
180 if (!parser.chunks) {
185 for (i = 0; i < parser.num_chunks; i++) {
186 struct drm_radeon_cs_chunk user_chunk;
188 chunk_ptr = (void __user *)(unsigned long)chunk_array[i];
190 if (DRM_COPY_FROM_USER(&user_chunk, chunk_ptr, sizeof(struct drm_radeon_cs_chunk))){
194 parser.chunks[i].chunk_id = user_chunk.chunk_id;
196 if (parser.chunks[i].chunk_id == RADEON_CHUNK_ID_RELOCS)
197 parser.reloc_index = i;
199 if (parser.chunks[i].chunk_id == RADEON_CHUNK_ID_IB)
202 if (parser.chunks[i].chunk_id == RADEON_CHUNK_ID_OLD) {
204 parser.reloc_index = -1;
207 parser.chunks[i].length_dw = user_chunk.length_dw;
208 parser.chunks[i].chunk_data = (uint32_t *)(unsigned long)user_chunk.chunk_data;
210 parser.chunks[i].kdata = NULL;
211 size = parser.chunks[i].length_dw * sizeof(uint32_t);
213 switch(parser.chunks[i].chunk_id) {
214 case RADEON_CHUNK_ID_IB:
215 case RADEON_CHUNK_ID_OLD:
220 case RADEON_CHUNK_ID_RELOCS:
222 parser.chunks[i].kdata = drm_alloc(size, DRM_MEM_DRIVER);
223 if (!parser.chunks[i].kdata) {
228 if (DRM_COPY_FROM_USER(parser.chunks[i].kdata, parser.chunks[i].chunk_data, size)) {
233 parser.chunks[i].kdata = NULL;
238 DRM_DEBUG("chunk %d %d %d %p\n", i, parser.chunks[i].chunk_id, parser.chunks[i].length_dw,
239 parser.chunks[i].chunk_data);
242 if (parser.chunks[parser.ib_index].length_dw > (16 * 1024)) {
243 DRM_ERROR("cs->dwords too big: %d\n", parser.chunks[parser.ib_index].length_dw);
249 r = dev_priv->cs.ib_get(&parser);
251 DRM_ERROR("ib_get failed\n");
255 /* now parse command stream */
256 r = dev_priv->cs.parse(&parser);
262 dev_priv->cs.ib_free(&parser, r);
264 /* emit cs id sequence */
265 dev_priv->cs.id_emit(&parser, &cs_id);
269 DRM_SPINUNLOCK(&dev_priv->cs.cs_mutex);
271 for (i = 0; i < parser.num_chunks; i++) {
272 if (parser.chunks[i].kdata)
273 drm_free(parser.chunks[i].kdata, parser.chunks[i].length_dw * sizeof(uint32_t), DRM_MEM_DRIVER);
276 drm_free(parser.chunks, sizeof(struct drm_radeon_kernel_chunk)*parser.num_chunks, DRM_MEM_DRIVER);
277 drm_free(chunk_array, sizeof(uint64_t)*parser.num_chunks, DRM_MEM_DRIVER);
283 static int r600_nomm_relocate(struct drm_radeon_cs_parser *parser, uint32_t *reloc, uint64_t *offset)
285 struct drm_device *dev = parser->dev;
286 drm_radeon_private_t *dev_priv = dev->dev_private;
287 struct drm_radeon_kernel_chunk *reloc_chunk = &parser->chunks[parser->reloc_index];
288 uint32_t offset_dw = reloc[1];
290 //DRM_INFO("reloc: 0x%08x 0x%08x\n", reloc[0], reloc[1]);
291 //DRM_INFO("length: %d\n", reloc_chunk->length_dw);
293 if (!reloc_chunk->kdata)
296 if (offset_dw > reloc_chunk->length_dw) {
297 DRM_ERROR("Offset larger than chunk 0x%x %d\n", offset_dw, reloc_chunk->length_dw);
302 *offset = reloc_chunk->kdata[offset_dw + 3];
304 *offset |= reloc_chunk->kdata[offset_dw + 0];
306 //DRM_INFO("offset 0x%lx\n", *offset);
308 if (!radeon_check_offset(dev_priv, *offset)) {
309 DRM_ERROR("bad offset! 0x%lx\n", (unsigned long)*offset);
316 static inline int r600_cs_packet0(struct drm_radeon_cs_parser *parser, uint32_t *offset_dw_p)
318 uint32_t hdr, num_dw, reg;
321 uint32_t offset_dw = *offset_dw_p;
324 hdr = parser->chunks[parser->ib_index].kdata[offset_dw];
325 num_dw = ((hdr & RADEON_CP_PACKET_COUNT_MASK) >> 16) + 2;
326 reg = (hdr & 0xffff) << 2;
328 while (count_dw < num_dw) {
330 case AVIVO_D1MODE_VLINE_START_END:
331 case AVIVO_D2MODE_VLINE_START_END:
335 DRM_ERROR("bad packet 0 reg: 0x%08x\n", reg);
343 *offset_dw_p += incr;
347 static inline int r600_cs_packet3(struct drm_radeon_cs_parser *parser, uint32_t *offset_dw_p)
349 struct drm_device *dev = parser->dev;
350 drm_radeon_private_t *dev_priv = dev->dev_private;
351 uint32_t hdr, num_dw, start_reg, end_reg, reg;
355 uint32_t offset_dw = *offset_dw_p;
358 struct drm_radeon_kernel_chunk *ib_chunk;
360 ib_chunk = &parser->chunks[parser->ib_index];
362 hdr = ib_chunk->kdata[offset_dw];
363 num_dw = ((hdr & RADEON_CP_PACKET_COUNT_MASK) >> 16) + 2;
365 /* just the ones we use for now, add more later */
366 switch (hdr & 0xff00) {
367 case R600_IT_START_3D_CMDBUF:
368 //DRM_INFO("R600_IT_START_3D_CMDBUF\n");
369 if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770)
374 DRM_ERROR("bad START_3D\n");
376 case R600_IT_CONTEXT_CONTROL:
377 //DRM_INFO("R600_IT_CONTEXT_CONTROL\n");
381 DRM_ERROR("bad CONTEXT_CONTROL\n");
383 case R600_IT_INDEX_TYPE:
384 case R600_IT_NUM_INSTANCES:
385 //DRM_INFO("R600_IT_INDEX_TYPE/R600_IT_NUM_INSTANCES\n");
389 DRM_ERROR("bad INDEX_TYPE/NUM_INSTANCES\n");
391 case R600_IT_DRAW_INDEX:
392 //DRM_INFO("R600_IT_DRAW_INDEX\n");
395 DRM_ERROR("bad DRAW_INDEX\n");
398 reloc = ib_chunk->kdata + offset_dw + num_dw;
399 ret = dev_priv->cs.relocate(parser, reloc, &offset);
401 DRM_ERROR("bad DRAW_INDEX\n");
404 ib_chunk->kdata[offset_dw + 1] += (offset & 0xffffffff);
405 ib_chunk->kdata[offset_dw + 2] += (upper_32_bits(offset) & 0xff);
407 case R600_IT_DRAW_INDEX_AUTO:
408 //DRM_INFO("R600_IT_DRAW_INDEX_AUTO\n");
412 DRM_ERROR("bad DRAW_INDEX_AUTO\n");
414 case R600_IT_DRAW_INDEX_IMMD_BE:
415 case R600_IT_DRAW_INDEX_IMMD:
416 //DRM_INFO("R600_IT_DRAW_INDEX_IMMD\n");
420 DRM_ERROR("bad DRAW_INDEX_IMMD\n");
422 case R600_IT_WAIT_REG_MEM:
423 //DRM_INFO("R600_IT_WAIT_REG_MEM\n");
426 /* bit 4 is reg (0) or mem (1) */
427 if (ib_chunk->kdata[offset_dw + 1] & 0x10) {
428 reloc = ib_chunk->kdata + offset_dw + num_dw;
429 ret = dev_priv->cs.relocate(parser, reloc, &offset);
431 DRM_ERROR("bad WAIT_REG_MEM\n");
434 ib_chunk->kdata[offset_dw + 2] += (offset & 0xffffffff);
435 ib_chunk->kdata[offset_dw + 3] += (upper_32_bits(offset) & 0xff);
438 DRM_ERROR("bad WAIT_REG_MEM\n");
440 case R600_IT_SURFACE_SYNC:
441 //DRM_INFO("R600_IT_SURFACE_SYNC\n");
444 /* 0xffffffff/0x0 is flush all cache flag */
445 else if ((ib_chunk->kdata[offset_dw + 2] == 0xffffffff) &&
446 (ib_chunk->kdata[offset_dw + 3] == 0))
449 reloc = ib_chunk->kdata + offset_dw + num_dw;
450 ret = dev_priv->cs.relocate(parser, reloc, &offset);
452 DRM_ERROR("bad SURFACE_SYNC\n");
455 ib_chunk->kdata[offset_dw + 3] += ((offset >> 8) & 0xffffffff);
458 case R600_IT_EVENT_WRITE:
459 //DRM_INFO("R600_IT_EVENT_WRITE\n");
460 if ((num_dw != 4) && (num_dw != 2))
463 reloc = ib_chunk->kdata + offset_dw + num_dw;
464 ret = dev_priv->cs.relocate(parser, reloc, &offset);
466 DRM_ERROR("bad EVENT_WRITE\n");
469 ib_chunk->kdata[offset_dw + 2] += (offset & 0xffffffff);
470 ib_chunk->kdata[offset_dw + 3] += (upper_32_bits(offset) & 0xff);
473 DRM_ERROR("bad EVENT_WRITE\n");
475 case R600_IT_EVENT_WRITE_EOP:
476 //DRM_INFO("R600_IT_EVENT_WRITE_EOP\n");
479 DRM_ERROR("bad EVENT_WRITE_EOP\n");
482 reloc = ib_chunk->kdata + offset_dw + num_dw;
483 ret = dev_priv->cs.relocate(parser, reloc, &offset);
485 DRM_ERROR("bad EVENT_WRITE_EOP\n");
488 ib_chunk->kdata[offset_dw + 2] += (offset & 0xffffffff);
489 ib_chunk->kdata[offset_dw + 3] += (upper_32_bits(offset) & 0xff);
491 case R600_IT_SET_CONFIG_REG:
492 //DRM_INFO("R600_IT_SET_CONFIG_REG\n");
493 start_reg = (ib_chunk->kdata[offset_dw + 1] << 2) + R600_SET_CONFIG_REG_OFFSET;
494 end_reg = 4 * (num_dw - 2) + start_reg - 4;
495 if ((start_reg < R600_SET_CONFIG_REG_OFFSET) ||
496 (start_reg >= R600_SET_CONFIG_REG_END) ||
497 (end_reg >= R600_SET_CONFIG_REG_END))
500 for (i = 0; i < (num_dw - 2); i++) {
501 reg = start_reg + (4 * i);
503 case R600_CP_COHER_BASE:
504 /* use R600_IT_SURFACE_SYNC */
515 DRM_ERROR("bad SET_CONFIG_REG\n");
517 case R600_IT_SET_CONTEXT_REG:
518 //DRM_INFO("R600_IT_SET_CONTEXT_REG\n");
519 start_reg = ib_chunk->kdata[offset_dw + 1] << 2;
520 start_reg += R600_SET_CONTEXT_REG_OFFSET;
521 end_reg = 4 * (num_dw - 2) + start_reg - 4;
522 if ((start_reg < R600_SET_CONTEXT_REG_OFFSET) ||
523 (start_reg >= R600_SET_CONTEXT_REG_END) ||
524 (end_reg >= R600_SET_CONTEXT_REG_END))
527 for (i = 0; i < (num_dw - 2); i++) {
528 reg = start_reg + (4 * i);
530 case R600_DB_DEPTH_BASE:
531 case R600_CB_COLOR0_BASE:
532 case R600_CB_COLOR1_BASE:
533 case R600_CB_COLOR2_BASE:
534 case R600_CB_COLOR3_BASE:
535 case R600_CB_COLOR4_BASE:
536 case R600_CB_COLOR5_BASE:
537 case R600_CB_COLOR6_BASE:
538 case R600_CB_COLOR7_BASE:
539 case R600_SQ_PGM_START_FS:
540 case R600_SQ_PGM_START_ES:
541 case R600_SQ_PGM_START_VS:
542 case R600_SQ_PGM_START_GS:
543 case R600_SQ_PGM_START_PS:
544 //DRM_INFO("reg: 0x%08x\n", reg);
545 reloc = ib_chunk->kdata + offset_dw + num_dw + (i * 2);
546 ret = dev_priv->cs.relocate(parser, reloc, &offset);
548 DRM_ERROR("bad SET_CONTEXT_REG\n");
551 ib_chunk->kdata[offset_dw + 2 + i] +=
552 ((offset >> 8) & 0xffffffff);
554 case R600_VGT_DMA_BASE:
555 case R600_VGT_DMA_BASE_HI:
556 /* These should be handled by DRAW_INDEX packet 3 */
557 case R600_VGT_STRMOUT_BASE_OFFSET_0:
558 case R600_VGT_STRMOUT_BASE_OFFSET_1:
559 case R600_VGT_STRMOUT_BASE_OFFSET_2:
560 case R600_VGT_STRMOUT_BASE_OFFSET_3:
561 case R600_VGT_STRMOUT_BASE_OFFSET_HI_0:
562 case R600_VGT_STRMOUT_BASE_OFFSET_HI_1:
563 case R600_VGT_STRMOUT_BASE_OFFSET_HI_2:
564 case R600_VGT_STRMOUT_BASE_OFFSET_HI_3:
565 case R600_VGT_STRMOUT_BUFFER_BASE_0:
566 case R600_VGT_STRMOUT_BUFFER_BASE_1:
567 case R600_VGT_STRMOUT_BUFFER_BASE_2:
568 case R600_VGT_STRMOUT_BUFFER_BASE_3:
569 case R600_VGT_STRMOUT_BUFFER_OFFSET_0:
570 case R600_VGT_STRMOUT_BUFFER_OFFSET_1:
571 case R600_VGT_STRMOUT_BUFFER_OFFSET_2:
572 case R600_VGT_STRMOUT_BUFFER_OFFSET_3:
573 /* These should be handled by STRMOUT_BUFFER packet 3 */
574 DRM_ERROR("bad context reg: 0x%08x\n", reg);
585 DRM_ERROR("bad SET_CONTEXT_REG\n");
587 case R600_IT_SET_RESOURCE:
588 //DRM_INFO("R600_IT_SET_RESOURCE\n");
589 if ((num_dw - 2) % 7)
591 start_reg = ib_chunk->kdata[offset_dw + 1] << 2;
592 start_reg += R600_SET_RESOURCE_OFFSET;
593 end_reg = 4 * (num_dw - 2) + start_reg - 4;
594 if ((start_reg < R600_SET_RESOURCE_OFFSET) ||
595 (start_reg >= R600_SET_RESOURCE_END) ||
596 (end_reg >= R600_SET_RESOURCE_END))
599 for (i = 0; i < ((num_dw - 2) / 7); i++) {
600 switch ((ib_chunk->kdata[offset_dw + (i * 7) + 6 + 2] & 0xc0000000) >> 30) {
601 case R600_SQ_TEX_VTX_INVALID_TEXTURE:
602 case R600_SQ_TEX_VTX_INVALID_BUFFER:
606 case R600_SQ_TEX_VTX_VALID_TEXTURE:
608 reloc = ib_chunk->kdata + offset_dw + num_dw + (i * 4);
609 ret = dev_priv->cs.relocate(parser, reloc, &offset);
612 ib_chunk->kdata[offset_dw + (i * 7) + 2 + 2] +=
613 ((offset >> 8) & 0xffffffff);
615 reloc = ib_chunk->kdata + offset_dw + num_dw + (i * 4) + 2;
616 ret = dev_priv->cs.relocate(parser, reloc, &offset);
619 ib_chunk->kdata[offset_dw + (i * 7) + 3 + 2] +=
620 ((offset >> 8) & 0xffffffff);
622 case R600_SQ_TEX_VTX_VALID_BUFFER:
624 reloc = ib_chunk->kdata + offset_dw + num_dw + (i * 2);
625 ret = dev_priv->cs.relocate(parser, reloc, &offset);
628 ib_chunk->kdata[offset_dw + (i * 7) + 0 + 2] += (offset & 0xffffffff);
629 ib_chunk->kdata[offset_dw + (i * 7) + 2 + 2] += (upper_32_bits(offset) & 0xff);
637 DRM_ERROR("bad SET_RESOURCE\n");
639 case R600_IT_SET_ALU_CONST:
640 //DRM_INFO("R600_IT_SET_ALU_CONST\n");
641 start_reg = ib_chunk->kdata[offset_dw + 1] << 2;
642 start_reg += R600_SET_ALU_CONST_OFFSET;
643 end_reg = 4 * (num_dw - 2) + start_reg - 4;
644 if ((start_reg < R600_SET_ALU_CONST_OFFSET) ||
645 (start_reg >= R600_SET_ALU_CONST_END) ||
646 (end_reg >= R600_SET_ALU_CONST_END))
649 DRM_ERROR("bad SET_ALU_CONST\n");
651 case R600_IT_SET_BOOL_CONST:
652 //DRM_INFO("R600_IT_SET_BOOL_CONST\n");
653 start_reg = ib_chunk->kdata[offset_dw + 1] << 2;
654 start_reg += R600_SET_BOOL_CONST_OFFSET;
655 end_reg = 4 * (num_dw - 2) + start_reg - 4;
656 if ((start_reg < R600_SET_BOOL_CONST_OFFSET) ||
657 (start_reg >= R600_SET_BOOL_CONST_END) ||
658 (end_reg >= R600_SET_BOOL_CONST_END))
661 DRM_ERROR("bad SET_BOOL_CONST\n");
663 case R600_IT_SET_LOOP_CONST:
664 //DRM_INFO("R600_IT_SET_LOOP_CONST\n");
665 start_reg = ib_chunk->kdata[offset_dw + 1] << 2;
666 start_reg += R600_SET_LOOP_CONST_OFFSET;
667 end_reg = 4 * (num_dw - 2) + start_reg - 4;
668 if ((start_reg < R600_SET_LOOP_CONST_OFFSET) ||
669 (start_reg >= R600_SET_LOOP_CONST_END) ||
670 (end_reg >= R600_SET_LOOP_CONST_END))
673 DRM_ERROR("bad SET_LOOP_CONST\n");
675 case R600_IT_SET_CTL_CONST:
676 //DRM_INFO("R600_IT_SET_CTL_CONST\n");
677 start_reg = ib_chunk->kdata[offset_dw + 1] << 2;
678 start_reg += R600_SET_CTL_CONST_OFFSET;
679 end_reg = 4 * (num_dw - 2) + start_reg - 4;
680 if ((start_reg < R600_SET_CTL_CONST_OFFSET) ||
681 (start_reg >= R600_SET_CTL_CONST_END) ||
682 (end_reg >= R600_SET_CTL_CONST_END))
685 DRM_ERROR("bad SET_CTL_CONST\n");
687 case R600_IT_SET_SAMPLER:
688 //DRM_INFO("R600_IT_SET_SAMPLER\n");
689 if ((num_dw - 2) % 3)
691 start_reg = ib_chunk->kdata[offset_dw + 1] << 2;
692 start_reg += R600_SET_SAMPLER_OFFSET;
693 end_reg = 4 * (num_dw - 2) + start_reg - 4;
694 if ((start_reg < R600_SET_SAMPLER_OFFSET) ||
695 (start_reg >= R600_SET_SAMPLER_END) ||
696 (end_reg >= R600_SET_SAMPLER_END))
699 DRM_ERROR("bad SET_SAMPLER\n");
701 case R600_IT_SURFACE_BASE_UPDATE:
702 //DRM_INFO("R600_IT_SURFACE_BASE_UPDATE\n");
703 if (((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770) ||
704 ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R600))
709 DRM_ERROR("bad SURFACE_BASE_UPDATE\n");
712 //DRM_INFO("NOP: %d\n", ib_chunk->kdata[offset_dw + 1]);
715 DRM_ERROR("invalid packet 3 0x%08x\n", 0xff00);
720 *offset_dw_p += incr;
724 static int r600_cs_parse(struct drm_radeon_cs_parser *parser)
727 struct drm_radeon_kernel_chunk *ib_chunk;
728 /* scan the packet for various things */
729 int count_dw = 0, size_dw;
732 ib_chunk = &parser->chunks[parser->ib_index];
733 size_dw = ib_chunk->length_dw;
735 while (count_dw < size_dw && ret == 0) {
736 int hdr = ib_chunk->kdata[count_dw];
737 int num_dw = (hdr & RADEON_CP_PACKET_COUNT_MASK) >> 16;
739 switch (hdr & RADEON_CP_PACKET_MASK) {
740 case RADEON_CP_PACKET0:
741 ret = r600_cs_packet0(parser, &count_dw);
743 case RADEON_CP_PACKET1:
746 case RADEON_CP_PACKET2:
747 DRM_DEBUG("Packet 2\n");
750 case RADEON_CP_PACKET3:
751 ret = r600_cs_packet3(parser, &count_dw);
762 /* copy the packet into the IB */
763 memcpy(parser->ib, ib_chunk->kdata, ib_chunk->length_dw * sizeof(uint32_t));
765 /* read back last byte to flush WC buffers */
766 rb = readl(((vm_offset_t)parser->ib + (ib_chunk->length_dw-1) * sizeof(uint32_t)));
771 static uint32_t radeon_cs_id_get(struct drm_radeon_private *radeon)
773 /* FIXME: protect with a spinlock */
774 /* FIXME: check if wrap affect last reported wrap & sequence */
775 radeon->cs.id_scnt = (radeon->cs.id_scnt + 1) & 0x00FFFFFF;
776 if (!radeon->cs.id_scnt) {
777 /* increment wrap counter */
778 radeon->cs.id_wcnt += 0x01000000;
779 /* valid sequence counter start at 1 */
780 radeon->cs.id_scnt = 1;
782 return (radeon->cs.id_scnt | radeon->cs.id_wcnt);
785 static void r600_cs_id_emit(struct drm_radeon_cs_parser *parser, uint32_t *id)
787 drm_radeon_private_t *dev_priv = parser->dev->dev_private;
790 //dev_priv->irq_emitted = radeon_update_breadcrumb(parser->dev);
792 *id = radeon_cs_id_get(dev_priv);
801 static uint32_t r600_cs_id_last_get(struct drm_device *dev)
803 //drm_radeon_private_t *dev_priv = dev->dev_private;
805 //return GET_R600_SCRATCH(dev_priv, 2);
809 static int r600_ib_get(struct drm_radeon_cs_parser *parser)
811 struct drm_device *dev = parser->dev;
812 drm_radeon_private_t *dev_priv = dev->dev_private;
815 buf = radeon_freelist_get(dev);
817 dev_priv->cs_buf = NULL;
820 buf->file_priv = parser->file_priv;
821 dev_priv->cs_buf = buf;
822 parser->ib = (void *)((vm_offset_t)dev->agp_buffer_map->handle +
828 static void r600_ib_free(struct drm_radeon_cs_parser *parser, int error)
830 struct drm_device *dev = parser->dev;
831 drm_radeon_private_t *dev_priv = dev->dev_private;
832 struct drm_buf *buf = dev_priv->cs_buf;
836 r600_cp_dispatch_indirect(dev, buf, 0,
837 parser->chunks[parser->ib_index].length_dw * sizeof(uint32_t));
838 radeon_cp_discard_buffer(dev, buf);
843 int r600_cs_init(struct drm_device *dev)
845 drm_radeon_private_t *dev_priv = dev->dev_private;
847 dev_priv->cs.ib_get = r600_ib_get;
848 dev_priv->cs.ib_free = r600_ib_free;
849 dev_priv->cs.id_emit = r600_cs_id_emit;
850 dev_priv->cs.id_last_get = r600_cs_id_last_get;
851 dev_priv->cs.parse = r600_cs_parse;
852 dev_priv->cs.relocate = r600_nomm_relocate;