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 "dev/drm/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 DRM_SPINLOCK(&dev_priv
->cs
.cs_mutex
);
146 /* set command stream id to 0 which is fake id */
150 if (dev_priv
== NULL
) {
151 DRM_ERROR("called with no initialization\n");
152 DRM_SPINUNLOCK(&dev_priv
->cs
.cs_mutex
);
155 if (!cs
->num_chunks
) {
156 DRM_SPINUNLOCK(&dev_priv
->cs
.cs_mutex
);
161 chunk_array
= drm_calloc(cs
->num_chunks
, sizeof(uint64_t), DRM_MEM_DRIVER
);
163 DRM_SPINUNLOCK(&dev_priv
->cs
.cs_mutex
);
167 chunk_array_ptr
= (uint64_t *)(unsigned long)(cs
->chunks
);
169 if (DRM_COPY_FROM_USER(chunk_array
, chunk_array_ptr
, sizeof(uint64_t)*cs
->num_chunks
)) {
175 parser
.file_priv
= fpriv
;
176 parser
.reloc_index
= -1;
177 parser
.ib_index
= -1;
178 parser
.num_chunks
= cs
->num_chunks
;
179 /* copy out the chunk headers */
180 parser
.chunks
= drm_calloc(parser
.num_chunks
, sizeof(struct drm_radeon_kernel_chunk
), DRM_MEM_DRIVER
);
181 if (!parser
.chunks
) {
186 for (i
= 0; i
< parser
.num_chunks
; i
++) {
187 struct drm_radeon_cs_chunk user_chunk
;
189 chunk_ptr
= (void __user
*)(unsigned long)chunk_array
[i
];
191 if (DRM_COPY_FROM_USER(&user_chunk
, chunk_ptr
, sizeof(struct drm_radeon_cs_chunk
))){
195 parser
.chunks
[i
].chunk_id
= user_chunk
.chunk_id
;
197 if (parser
.chunks
[i
].chunk_id
== RADEON_CHUNK_ID_RELOCS
)
198 parser
.reloc_index
= i
;
200 if (parser
.chunks
[i
].chunk_id
== RADEON_CHUNK_ID_IB
)
203 if (parser
.chunks
[i
].chunk_id
== RADEON_CHUNK_ID_OLD
) {
205 parser
.reloc_index
= -1;
208 parser
.chunks
[i
].length_dw
= user_chunk
.length_dw
;
209 parser
.chunks
[i
].chunk_data
= (uint32_t *)(unsigned long)user_chunk
.chunk_data
;
211 parser
.chunks
[i
].kdata
= NULL
;
212 size
= parser
.chunks
[i
].length_dw
* sizeof(uint32_t);
214 switch(parser
.chunks
[i
].chunk_id
) {
215 case RADEON_CHUNK_ID_IB
:
216 case RADEON_CHUNK_ID_OLD
:
221 case RADEON_CHUNK_ID_RELOCS
:
223 parser
.chunks
[i
].kdata
= drm_alloc(size
, DRM_MEM_DRIVER
);
224 if (!parser
.chunks
[i
].kdata
) {
229 if (DRM_COPY_FROM_USER(parser
.chunks
[i
].kdata
, parser
.chunks
[i
].chunk_data
, size
)) {
234 parser
.chunks
[i
].kdata
= NULL
;
239 DRM_DEBUG("chunk %d %d %d %p\n", i
, parser
.chunks
[i
].chunk_id
, parser
.chunks
[i
].length_dw
,
240 parser
.chunks
[i
].chunk_data
);
243 if (parser
.chunks
[parser
.ib_index
].length_dw
> (16 * 1024)) {
244 DRM_ERROR("cs->dwords too big: %d\n", parser
.chunks
[parser
.ib_index
].length_dw
);
250 r
= dev_priv
->cs
.ib_get(&parser
);
252 DRM_ERROR("ib_get failed\n");
256 /* now parse command stream */
257 r
= dev_priv
->cs
.parse(&parser
);
263 dev_priv
->cs
.ib_free(&parser
, r
);
265 /* emit cs id sequence */
266 dev_priv
->cs
.id_emit(&parser
, &cs_id
);
270 DRM_SPINUNLOCK(&dev_priv
->cs
.cs_mutex
);
272 for (i
= 0; i
< parser
.num_chunks
; i
++) {
273 if (parser
.chunks
[i
].kdata
)
274 drm_free(parser
.chunks
[i
].kdata
, parser
.chunks
[i
].length_dw
* sizeof(uint32_t), DRM_MEM_DRIVER
);
277 drm_free(parser
.chunks
, sizeof(struct drm_radeon_kernel_chunk
)*parser
.num_chunks
, DRM_MEM_DRIVER
);
278 drm_free(chunk_array
, sizeof(uint64_t)*parser
.num_chunks
, DRM_MEM_DRIVER
);
284 static int r600_nomm_relocate(struct drm_radeon_cs_parser
*parser
, uint32_t *reloc
, uint64_t *offset
)
286 struct drm_device
*dev
= parser
->dev
;
287 drm_radeon_private_t
*dev_priv
= dev
->dev_private
;
288 struct drm_radeon_kernel_chunk
*reloc_chunk
= &parser
->chunks
[parser
->reloc_index
];
289 uint32_t offset_dw
= reloc
[1];
291 //DRM_INFO("reloc: 0x%08x 0x%08x\n", reloc[0], reloc[1]);
292 //DRM_INFO("length: %d\n", reloc_chunk->length_dw);
294 if (!reloc_chunk
->kdata
)
297 if (offset_dw
> reloc_chunk
->length_dw
) {
298 DRM_ERROR("Offset larger than chunk 0x%x %d\n", offset_dw
, reloc_chunk
->length_dw
);
303 *offset
= reloc_chunk
->kdata
[offset_dw
+ 3];
305 *offset
|= reloc_chunk
->kdata
[offset_dw
+ 0];
307 //DRM_INFO("offset 0x%lx\n", *offset);
309 if (!radeon_check_offset(dev_priv
, *offset
)) {
310 DRM_ERROR("bad offset! 0x%lx\n", (unsigned long)*offset
);
317 static inline int r600_cs_packet0(struct drm_radeon_cs_parser
*parser
, uint32_t *offset_dw_p
)
319 uint32_t hdr
, num_dw
, reg
;
322 uint32_t offset_dw
= *offset_dw_p
;
325 hdr
= parser
->chunks
[parser
->ib_index
].kdata
[offset_dw
];
326 num_dw
= ((hdr
& RADEON_CP_PACKET_COUNT_MASK
) >> 16) + 2;
327 reg
= (hdr
& 0xffff) << 2;
329 while (count_dw
< num_dw
) {
331 case AVIVO_D1MODE_VLINE_START_END
:
332 case AVIVO_D2MODE_VLINE_START_END
:
336 DRM_ERROR("bad packet 0 reg: 0x%08x\n", reg
);
344 *offset_dw_p
+= incr
;
348 static inline int r600_cs_packet3(struct drm_radeon_cs_parser
*parser
, uint32_t *offset_dw_p
)
350 struct drm_device
*dev
= parser
->dev
;
351 drm_radeon_private_t
*dev_priv
= dev
->dev_private
;
352 uint32_t hdr
, num_dw
, start_reg
, end_reg
, reg
;
356 uint32_t offset_dw
= *offset_dw_p
;
359 struct drm_radeon_kernel_chunk
*ib_chunk
;
361 ib_chunk
= &parser
->chunks
[parser
->ib_index
];
363 hdr
= ib_chunk
->kdata
[offset_dw
];
364 num_dw
= ((hdr
& RADEON_CP_PACKET_COUNT_MASK
) >> 16) + 2;
366 /* just the ones we use for now, add more later */
367 switch (hdr
& 0xff00) {
368 case R600_IT_START_3D_CMDBUF
:
369 //DRM_INFO("R600_IT_START_3D_CMDBUF\n");
370 if ((dev_priv
->flags
& RADEON_FAMILY_MASK
) >= CHIP_RV770
)
375 DRM_ERROR("bad START_3D\n");
377 case R600_IT_CONTEXT_CONTROL
:
378 //DRM_INFO("R600_IT_CONTEXT_CONTROL\n");
382 DRM_ERROR("bad CONTEXT_CONTROL\n");
384 case R600_IT_INDEX_TYPE
:
385 case R600_IT_NUM_INSTANCES
:
386 //DRM_INFO("R600_IT_INDEX_TYPE/R600_IT_NUM_INSTANCES\n");
390 DRM_ERROR("bad INDEX_TYPE/NUM_INSTANCES\n");
392 case R600_IT_DRAW_INDEX
:
393 //DRM_INFO("R600_IT_DRAW_INDEX\n");
396 DRM_ERROR("bad DRAW_INDEX\n");
399 reloc
= ib_chunk
->kdata
+ offset_dw
+ num_dw
;
400 ret
= dev_priv
->cs
.relocate(parser
, reloc
, &offset
);
402 DRM_ERROR("bad DRAW_INDEX\n");
405 ib_chunk
->kdata
[offset_dw
+ 1] += (offset
& 0xffffffff);
406 ib_chunk
->kdata
[offset_dw
+ 2] += (upper_32_bits(offset
) & 0xff);
408 case R600_IT_DRAW_INDEX_AUTO
:
409 //DRM_INFO("R600_IT_DRAW_INDEX_AUTO\n");
413 DRM_ERROR("bad DRAW_INDEX_AUTO\n");
415 case R600_IT_DRAW_INDEX_IMMD_BE
:
416 case R600_IT_DRAW_INDEX_IMMD
:
417 //DRM_INFO("R600_IT_DRAW_INDEX_IMMD\n");
421 DRM_ERROR("bad DRAW_INDEX_IMMD\n");
423 case R600_IT_WAIT_REG_MEM
:
424 //DRM_INFO("R600_IT_WAIT_REG_MEM\n");
427 /* bit 4 is reg (0) or mem (1) */
428 if (ib_chunk
->kdata
[offset_dw
+ 1] & 0x10) {
429 reloc
= ib_chunk
->kdata
+ offset_dw
+ num_dw
;
430 ret
= dev_priv
->cs
.relocate(parser
, reloc
, &offset
);
432 DRM_ERROR("bad WAIT_REG_MEM\n");
435 ib_chunk
->kdata
[offset_dw
+ 2] += (offset
& 0xffffffff);
436 ib_chunk
->kdata
[offset_dw
+ 3] += (upper_32_bits(offset
) & 0xff);
439 DRM_ERROR("bad WAIT_REG_MEM\n");
441 case R600_IT_SURFACE_SYNC
:
442 //DRM_INFO("R600_IT_SURFACE_SYNC\n");
445 /* 0xffffffff/0x0 is flush all cache flag */
446 else if ((ib_chunk
->kdata
[offset_dw
+ 2] == 0xffffffff) &&
447 (ib_chunk
->kdata
[offset_dw
+ 3] == 0))
450 reloc
= ib_chunk
->kdata
+ offset_dw
+ num_dw
;
451 ret
= dev_priv
->cs
.relocate(parser
, reloc
, &offset
);
453 DRM_ERROR("bad SURFACE_SYNC\n");
456 ib_chunk
->kdata
[offset_dw
+ 3] += ((offset
>> 8) & 0xffffffff);
459 case R600_IT_EVENT_WRITE
:
460 //DRM_INFO("R600_IT_EVENT_WRITE\n");
461 if ((num_dw
!= 4) && (num_dw
!= 2))
464 reloc
= ib_chunk
->kdata
+ offset_dw
+ num_dw
;
465 ret
= dev_priv
->cs
.relocate(parser
, reloc
, &offset
);
467 DRM_ERROR("bad EVENT_WRITE\n");
470 ib_chunk
->kdata
[offset_dw
+ 2] += (offset
& 0xffffffff);
471 ib_chunk
->kdata
[offset_dw
+ 3] += (upper_32_bits(offset
) & 0xff);
474 DRM_ERROR("bad EVENT_WRITE\n");
476 case R600_IT_EVENT_WRITE_EOP
:
477 //DRM_INFO("R600_IT_EVENT_WRITE_EOP\n");
480 DRM_ERROR("bad EVENT_WRITE_EOP\n");
483 reloc
= ib_chunk
->kdata
+ offset_dw
+ num_dw
;
484 ret
= dev_priv
->cs
.relocate(parser
, reloc
, &offset
);
486 DRM_ERROR("bad EVENT_WRITE_EOP\n");
489 ib_chunk
->kdata
[offset_dw
+ 2] += (offset
& 0xffffffff);
490 ib_chunk
->kdata
[offset_dw
+ 3] += (upper_32_bits(offset
) & 0xff);
492 case R600_IT_SET_CONFIG_REG
:
493 //DRM_INFO("R600_IT_SET_CONFIG_REG\n");
494 start_reg
= (ib_chunk
->kdata
[offset_dw
+ 1] << 2) + R600_SET_CONFIG_REG_OFFSET
;
495 end_reg
= 4 * (num_dw
- 2) + start_reg
- 4;
496 if ((start_reg
< R600_SET_CONFIG_REG_OFFSET
) ||
497 (start_reg
>= R600_SET_CONFIG_REG_END
) ||
498 (end_reg
>= R600_SET_CONFIG_REG_END
))
501 for (i
= 0; i
< (num_dw
- 2); i
++) {
502 reg
= start_reg
+ (4 * i
);
504 case R600_CP_COHER_BASE
:
505 /* use R600_IT_SURFACE_SYNC */
516 DRM_ERROR("bad SET_CONFIG_REG\n");
518 case R600_IT_SET_CONTEXT_REG
:
519 //DRM_INFO("R600_IT_SET_CONTEXT_REG\n");
520 start_reg
= ib_chunk
->kdata
[offset_dw
+ 1] << 2;
521 start_reg
+= R600_SET_CONTEXT_REG_OFFSET
;
522 end_reg
= 4 * (num_dw
- 2) + start_reg
- 4;
523 if ((start_reg
< R600_SET_CONTEXT_REG_OFFSET
) ||
524 (start_reg
>= R600_SET_CONTEXT_REG_END
) ||
525 (end_reg
>= R600_SET_CONTEXT_REG_END
))
528 for (i
= 0; i
< (num_dw
- 2); i
++) {
529 reg
= start_reg
+ (4 * i
);
531 case R600_DB_DEPTH_BASE
:
532 case R600_CB_COLOR0_BASE
:
533 case R600_CB_COLOR1_BASE
:
534 case R600_CB_COLOR2_BASE
:
535 case R600_CB_COLOR3_BASE
:
536 case R600_CB_COLOR4_BASE
:
537 case R600_CB_COLOR5_BASE
:
538 case R600_CB_COLOR6_BASE
:
539 case R600_CB_COLOR7_BASE
:
540 case R600_SQ_PGM_START_FS
:
541 case R600_SQ_PGM_START_ES
:
542 case R600_SQ_PGM_START_VS
:
543 case R600_SQ_PGM_START_GS
:
544 case R600_SQ_PGM_START_PS
:
545 //DRM_INFO("reg: 0x%08x\n", reg);
546 reloc
= ib_chunk
->kdata
+ offset_dw
+ num_dw
+ (i
* 2);
547 ret
= dev_priv
->cs
.relocate(parser
, reloc
, &offset
);
549 DRM_ERROR("bad SET_CONTEXT_REG\n");
552 ib_chunk
->kdata
[offset_dw
+ 2 + i
] +=
553 ((offset
>> 8) & 0xffffffff);
555 case R600_VGT_DMA_BASE
:
556 case R600_VGT_DMA_BASE_HI
:
557 /* These should be handled by DRAW_INDEX packet 3 */
558 case R600_VGT_STRMOUT_BASE_OFFSET_0
:
559 case R600_VGT_STRMOUT_BASE_OFFSET_1
:
560 case R600_VGT_STRMOUT_BASE_OFFSET_2
:
561 case R600_VGT_STRMOUT_BASE_OFFSET_3
:
562 case R600_VGT_STRMOUT_BASE_OFFSET_HI_0
:
563 case R600_VGT_STRMOUT_BASE_OFFSET_HI_1
:
564 case R600_VGT_STRMOUT_BASE_OFFSET_HI_2
:
565 case R600_VGT_STRMOUT_BASE_OFFSET_HI_3
:
566 case R600_VGT_STRMOUT_BUFFER_BASE_0
:
567 case R600_VGT_STRMOUT_BUFFER_BASE_1
:
568 case R600_VGT_STRMOUT_BUFFER_BASE_2
:
569 case R600_VGT_STRMOUT_BUFFER_BASE_3
:
570 case R600_VGT_STRMOUT_BUFFER_OFFSET_0
:
571 case R600_VGT_STRMOUT_BUFFER_OFFSET_1
:
572 case R600_VGT_STRMOUT_BUFFER_OFFSET_2
:
573 case R600_VGT_STRMOUT_BUFFER_OFFSET_3
:
574 /* These should be handled by STRMOUT_BUFFER packet 3 */
575 DRM_ERROR("bad context reg: 0x%08x\n", reg
);
586 DRM_ERROR("bad SET_CONTEXT_REG\n");
588 case R600_IT_SET_RESOURCE
:
589 //DRM_INFO("R600_IT_SET_RESOURCE\n");
590 if ((num_dw
- 2) % 7)
592 start_reg
= ib_chunk
->kdata
[offset_dw
+ 1] << 2;
593 start_reg
+= R600_SET_RESOURCE_OFFSET
;
594 end_reg
= 4 * (num_dw
- 2) + start_reg
- 4;
595 if ((start_reg
< R600_SET_RESOURCE_OFFSET
) ||
596 (start_reg
>= R600_SET_RESOURCE_END
) ||
597 (end_reg
>= R600_SET_RESOURCE_END
))
600 for (i
= 0; i
< ((num_dw
- 2) / 7); i
++) {
601 switch ((ib_chunk
->kdata
[offset_dw
+ (i
* 7) + 6 + 2] & 0xc0000000) >> 30) {
602 case R600_SQ_TEX_VTX_INVALID_TEXTURE
:
603 case R600_SQ_TEX_VTX_INVALID_BUFFER
:
607 case R600_SQ_TEX_VTX_VALID_TEXTURE
:
609 reloc
= ib_chunk
->kdata
+ offset_dw
+ num_dw
+ (i
* 4);
610 ret
= dev_priv
->cs
.relocate(parser
, reloc
, &offset
);
613 ib_chunk
->kdata
[offset_dw
+ (i
* 7) + 2 + 2] +=
614 ((offset
>> 8) & 0xffffffff);
616 reloc
= ib_chunk
->kdata
+ offset_dw
+ num_dw
+ (i
* 4) + 2;
617 ret
= dev_priv
->cs
.relocate(parser
, reloc
, &offset
);
620 ib_chunk
->kdata
[offset_dw
+ (i
* 7) + 3 + 2] +=
621 ((offset
>> 8) & 0xffffffff);
623 case R600_SQ_TEX_VTX_VALID_BUFFER
:
625 reloc
= ib_chunk
->kdata
+ offset_dw
+ num_dw
+ (i
* 2);
626 ret
= dev_priv
->cs
.relocate(parser
, reloc
, &offset
);
629 ib_chunk
->kdata
[offset_dw
+ (i
* 7) + 0 + 2] += (offset
& 0xffffffff);
630 ib_chunk
->kdata
[offset_dw
+ (i
* 7) + 2 + 2] += (upper_32_bits(offset
) & 0xff);
638 DRM_ERROR("bad SET_RESOURCE\n");
640 case R600_IT_SET_ALU_CONST
:
641 //DRM_INFO("R600_IT_SET_ALU_CONST\n");
642 start_reg
= ib_chunk
->kdata
[offset_dw
+ 1] << 2;
643 start_reg
+= R600_SET_ALU_CONST_OFFSET
;
644 end_reg
= 4 * (num_dw
- 2) + start_reg
- 4;
645 if ((start_reg
< R600_SET_ALU_CONST_OFFSET
) ||
646 (start_reg
>= R600_SET_ALU_CONST_END
) ||
647 (end_reg
>= R600_SET_ALU_CONST_END
))
650 DRM_ERROR("bad SET_ALU_CONST\n");
652 case R600_IT_SET_BOOL_CONST
:
653 //DRM_INFO("R600_IT_SET_BOOL_CONST\n");
654 start_reg
= ib_chunk
->kdata
[offset_dw
+ 1] << 2;
655 start_reg
+= R600_SET_BOOL_CONST_OFFSET
;
656 end_reg
= 4 * (num_dw
- 2) + start_reg
- 4;
657 if ((start_reg
< R600_SET_BOOL_CONST_OFFSET
) ||
658 (start_reg
>= R600_SET_BOOL_CONST_END
) ||
659 (end_reg
>= R600_SET_BOOL_CONST_END
))
662 DRM_ERROR("bad SET_BOOL_CONST\n");
664 case R600_IT_SET_LOOP_CONST
:
665 //DRM_INFO("R600_IT_SET_LOOP_CONST\n");
666 start_reg
= ib_chunk
->kdata
[offset_dw
+ 1] << 2;
667 start_reg
+= R600_SET_LOOP_CONST_OFFSET
;
668 end_reg
= 4 * (num_dw
- 2) + start_reg
- 4;
669 if ((start_reg
< R600_SET_LOOP_CONST_OFFSET
) ||
670 (start_reg
>= R600_SET_LOOP_CONST_END
) ||
671 (end_reg
>= R600_SET_LOOP_CONST_END
))
674 DRM_ERROR("bad SET_LOOP_CONST\n");
676 case R600_IT_SET_CTL_CONST
:
677 //DRM_INFO("R600_IT_SET_CTL_CONST\n");
678 start_reg
= ib_chunk
->kdata
[offset_dw
+ 1] << 2;
679 start_reg
+= R600_SET_CTL_CONST_OFFSET
;
680 end_reg
= 4 * (num_dw
- 2) + start_reg
- 4;
681 if ((start_reg
< R600_SET_CTL_CONST_OFFSET
) ||
682 (start_reg
>= R600_SET_CTL_CONST_END
) ||
683 (end_reg
>= R600_SET_CTL_CONST_END
))
686 DRM_ERROR("bad SET_CTL_CONST\n");
688 case R600_IT_SET_SAMPLER
:
689 //DRM_INFO("R600_IT_SET_SAMPLER\n");
690 if ((num_dw
- 2) % 3)
692 start_reg
= ib_chunk
->kdata
[offset_dw
+ 1] << 2;
693 start_reg
+= R600_SET_SAMPLER_OFFSET
;
694 end_reg
= 4 * (num_dw
- 2) + start_reg
- 4;
695 if ((start_reg
< R600_SET_SAMPLER_OFFSET
) ||
696 (start_reg
>= R600_SET_SAMPLER_END
) ||
697 (end_reg
>= R600_SET_SAMPLER_END
))
700 DRM_ERROR("bad SET_SAMPLER\n");
702 case R600_IT_SURFACE_BASE_UPDATE
:
703 //DRM_INFO("R600_IT_SURFACE_BASE_UPDATE\n");
704 if (((dev_priv
->flags
& RADEON_FAMILY_MASK
) >= CHIP_RV770
) ||
705 ((dev_priv
->flags
& RADEON_FAMILY_MASK
) == CHIP_R600
))
710 DRM_ERROR("bad SURFACE_BASE_UPDATE\n");
713 //DRM_INFO("NOP: %d\n", ib_chunk->kdata[offset_dw + 1]);
716 DRM_ERROR("invalid packet 3 0x%08x\n", 0xff00);
721 *offset_dw_p
+= incr
;
725 static int r600_cs_parse(struct drm_radeon_cs_parser
*parser
)
728 struct drm_radeon_kernel_chunk
*ib_chunk
;
729 /* scan the packet for various things */
730 int count_dw
= 0, size_dw
;
733 ib_chunk
= &parser
->chunks
[parser
->ib_index
];
734 size_dw
= ib_chunk
->length_dw
;
736 while (count_dw
< size_dw
&& ret
== 0) {
737 int hdr
= ib_chunk
->kdata
[count_dw
];
738 int num_dw
= (hdr
& RADEON_CP_PACKET_COUNT_MASK
) >> 16;
740 switch (hdr
& RADEON_CP_PACKET_MASK
) {
741 case RADEON_CP_PACKET0
:
742 ret
= r600_cs_packet0(parser
, &count_dw
);
744 case RADEON_CP_PACKET1
:
747 case RADEON_CP_PACKET2
:
748 DRM_DEBUG("Packet 2\n");
751 case RADEON_CP_PACKET3
:
752 ret
= r600_cs_packet3(parser
, &count_dw
);
763 /* copy the packet into the IB */
764 memcpy(parser
->ib
, ib_chunk
->kdata
, ib_chunk
->length_dw
* sizeof(uint32_t));
766 /* read back last byte to flush WC buffers */
767 rb
= readl(((vm_offset_t
)parser
->ib
+ (ib_chunk
->length_dw
-1) * sizeof(uint32_t)));
772 static uint32_t radeon_cs_id_get(struct drm_radeon_private
*radeon
)
774 /* FIXME: protect with a spinlock */
775 /* FIXME: check if wrap affect last reported wrap & sequence */
776 radeon
->cs
.id_scnt
= (radeon
->cs
.id_scnt
+ 1) & 0x00FFFFFF;
777 if (!radeon
->cs
.id_scnt
) {
778 /* increment wrap counter */
779 radeon
->cs
.id_wcnt
+= 0x01000000;
780 /* valid sequence counter start at 1 */
781 radeon
->cs
.id_scnt
= 1;
783 return (radeon
->cs
.id_scnt
| radeon
->cs
.id_wcnt
);
786 static void r600_cs_id_emit(struct drm_radeon_cs_parser
*parser
, uint32_t *id
)
788 drm_radeon_private_t
*dev_priv
= parser
->dev
->dev_private
;
791 //dev_priv->irq_emitted = radeon_update_breadcrumb(parser->dev);
793 *id
= radeon_cs_id_get(dev_priv
);
802 static uint32_t r600_cs_id_last_get(struct drm_device
*dev
)
804 //drm_radeon_private_t *dev_priv = dev->dev_private;
806 //return GET_R600_SCRATCH(dev_priv, 2);
810 static int r600_ib_get(struct drm_radeon_cs_parser
*parser
)
812 struct drm_device
*dev
= parser
->dev
;
813 drm_radeon_private_t
*dev_priv
= dev
->dev_private
;
816 buf
= radeon_freelist_get(dev
);
818 dev_priv
->cs_buf
= NULL
;
821 buf
->file_priv
= parser
->file_priv
;
822 dev_priv
->cs_buf
= buf
;
823 parser
->ib
= (void *)((vm_offset_t
)dev
->agp_buffer_map
->handle
+
829 static void r600_ib_free(struct drm_radeon_cs_parser
*parser
, int error
)
831 struct drm_device
*dev
= parser
->dev
;
832 drm_radeon_private_t
*dev_priv
= dev
->dev_private
;
833 struct drm_buf
*buf
= dev_priv
->cs_buf
;
837 r600_cp_dispatch_indirect(dev
, buf
, 0,
838 parser
->chunks
[parser
->ib_index
].length_dw
* sizeof(uint32_t));
839 radeon_cp_discard_buffer(dev
, buf
);
844 int r600_cs_init(struct drm_device
*dev
)
846 drm_radeon_private_t
*dev_priv
= dev
->dev_private
;
848 dev_priv
->cs
.ib_get
= r600_ib_get
;
849 dev_priv
->cs
.ib_free
= r600_ib_free
;
850 dev_priv
->cs
.id_emit
= r600_cs_id_emit
;
851 dev_priv
->cs
.id_last_get
= r600_cs_id_last_get
;
852 dev_priv
->cs
.parse
= r600_cs_parse
;
853 dev_priv
->cs
.relocate
= r600_nomm_relocate
;