OSDN Git Service

4a2319620ba4d9dc57c19ae4178215d16129df7a
[android-x86/external-libdrm.git] / shared-core / radeon_cs.c
1 /*
2  * Copyright 2008 Jerome Glisse.
3  * All Rights Reserved.
4  *
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:
11  *
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
14  * Software.
15  *
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.
23  *
24  * Authors:
25  *    Jerome Glisse <glisse@freedesktop.org>
26  */
27 #include "drmP.h"
28 #include "radeon_drm.h"
29 #include "radeon_drv.h"
30 #include "r300_reg.h"
31
32 int radeon_cs2_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv)
33 {
34         struct drm_radeon_cs_parser parser;
35         struct drm_radeon_private *dev_priv = dev->dev_private;
36         struct drm_radeon_cs2 *cs = data;
37         uint32_t cs_id;
38         struct drm_radeon_cs_chunk __user **chunk_ptr = NULL;
39         uint64_t *chunk_array;
40         uint64_t *chunk_array_ptr;
41         long size;
42         int r, i;
43
44         /* set command stream id to 0 which is fake id */
45         cs_id = 0;
46         cs->cs_id = cs_id;
47
48         if (dev_priv == NULL) {
49                 DRM_ERROR("called with no initialization\n");
50                 return -EINVAL;
51         }
52         if (!cs->num_chunks) {
53                 return 0;
54         }
55
56
57         chunk_array = drm_calloc(cs->num_chunks, sizeof(uint64_t), DRM_MEM_DRIVER);
58         if (!chunk_array) {
59                 return -ENOMEM;
60         }
61
62         chunk_array_ptr = (uint64_t *)(unsigned long)(cs->chunks);
63
64         if (DRM_COPY_FROM_USER(chunk_array, chunk_array_ptr, sizeof(uint64_t)*cs->num_chunks)) {
65                 r = -EFAULT;
66                 goto out;
67         }
68
69         parser.dev = dev;
70         parser.file_priv = fpriv;
71         parser.reloc_index = -1;
72         parser.ib_index = -1;
73         parser.num_chunks = cs->num_chunks;
74         /* copy out the chunk headers */
75         parser.chunks = drm_calloc(parser.num_chunks, sizeof(struct drm_radeon_kernel_chunk), DRM_MEM_DRIVER);
76         if (!parser.chunks) {
77                 return -ENOMEM;
78         }
79
80         for (i = 0; i < parser.num_chunks; i++) {
81                 struct drm_radeon_cs_chunk user_chunk;
82
83                 chunk_ptr = (void __user *)(unsigned long)chunk_array[i];
84
85                 if (DRM_COPY_FROM_USER(&user_chunk, chunk_ptr, sizeof(struct drm_radeon_cs_chunk))){
86                         r = -EFAULT;
87                         goto out;
88                 }
89                 parser.chunks[i].chunk_id = user_chunk.chunk_id;
90
91                 if (parser.chunks[i].chunk_id == RADEON_CHUNK_ID_RELOCS)
92                         parser.reloc_index = i;
93
94                 if (parser.chunks[i].chunk_id == RADEON_CHUNK_ID_IB)
95                         parser.ib_index = i;
96
97                 if (parser.chunks[i].chunk_id == RADEON_CHUNK_ID_OLD) {
98                         parser.ib_index = i;
99                         parser.reloc_index = -1;
100                 }
101
102                 parser.chunks[i].length_dw = user_chunk.length_dw;
103                 parser.chunks[i].chunk_data = (uint32_t *)(unsigned long)user_chunk.chunk_data;
104
105                 parser.chunks[i].kdata = NULL;
106                 size = parser.chunks[i].length_dw * sizeof(uint32_t);
107
108                 switch(parser.chunks[i].chunk_id) {
109                 case RADEON_CHUNK_ID_IB:
110                 case RADEON_CHUNK_ID_OLD:
111                         if (size == 0) {
112                                 r = -EINVAL;
113                                 goto out;
114                         }
115                 case RADEON_CHUNK_ID_RELOCS:
116                         if (size) {
117                                 parser.chunks[i].kdata = drm_alloc(size, DRM_MEM_DRIVER);
118                                 if (!parser.chunks[i].kdata) { 
119                                         r = -ENOMEM;
120                                         goto out;
121                                 }
122                                 
123                                 if (DRM_COPY_FROM_USER(parser.chunks[i].kdata, parser.chunks[i].chunk_data, size)) {
124                                         r = -EFAULT;
125                                         goto out;
126                                 }
127                         } else
128                                 parser.chunks[i].kdata = NULL;
129                         break;
130                 default:
131                         break;
132                 }
133                 DRM_DEBUG("chunk %d %d %d %p\n", i, parser.chunks[i].chunk_id, parser.chunks[i].length_dw,
134                           parser.chunks[i].chunk_data);
135         }
136
137
138         if (parser.chunks[parser.ib_index].length_dw > (16 * 1024)) {
139                 DRM_ERROR("cs->dwords too big: %d\n", parser.chunks[parser.ib_index].length_dw);
140                 r = -EINVAL;
141                 goto out;
142         }
143
144         /* get ib */
145         r = dev_priv->cs.ib_get(&parser);
146         if (r) {
147                 DRM_ERROR("ib_get failed\n");
148                 goto out;
149         }
150
151         /* now parse command stream */
152         r = dev_priv->cs.parse(&parser);
153         if (r) {
154                 goto out;
155         }
156
157         /* emit cs id sequence */
158         dev_priv->cs.id_emit(&parser, &cs_id);
159
160         cs->cs_id = cs_id;
161                 
162 out:
163         dev_priv->cs.ib_free(&parser);
164
165         for (i = 0; i < parser.num_chunks; i++) {
166                 if (parser.chunks[i].kdata)
167                         drm_free(parser.chunks[i].kdata, parser.chunks[i].length_dw * sizeof(uint32_t), DRM_MEM_DRIVER);
168         }
169
170         drm_free(parser.chunks, sizeof(struct drm_radeon_kernel_chunk)*parser.num_chunks, DRM_MEM_DRIVER);
171         drm_free(chunk_array, sizeof(uint64_t)*parser.num_chunks, DRM_MEM_DRIVER);
172
173         return r;
174 }
175
176 int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv)
177 {
178         struct drm_radeon_cs_parser parser;
179         struct drm_radeon_private *dev_priv = dev->dev_private;
180         struct drm_radeon_cs *cs = data;
181         uint32_t *packets = NULL;
182         uint32_t cs_id;
183         uint32_t card_offset;
184         long size;
185         int r;
186         struct drm_radeon_kernel_chunk chunk_fake[1];
187
188         /* set command stream id to 0 which is fake id */
189         cs_id = 0;
190         cs->cs_id = cs_id;
191
192         if (dev_priv == NULL) {
193                 DRM_ERROR("called with no initialization\n");
194                 return -EINVAL;
195         }
196         if (!cs->dwords) {
197                 return 0;
198         }
199         /* limit cs to 64K ib */
200         if (cs->dwords > (16 * 1024)) {
201                 return -EINVAL;
202         }
203         /* copy cs from userspace maybe we should copy into ib to save
204          * one copy but ib will be mapped wc so not good for cmd checking
205          * somethings worth testing i guess (Jerome)
206          */
207         size = cs->dwords * sizeof(uint32_t);
208         packets = drm_alloc(size, DRM_MEM_DRIVER);
209         if (packets == NULL) {
210                 return -ENOMEM;
211         }
212         if (DRM_COPY_FROM_USER(packets, (void __user *)(unsigned long)cs->packets, size)) {
213                 r = -EFAULT;
214                 goto out;
215         }
216
217         chunk_fake[0].chunk_id = RADEON_CHUNK_ID_OLD;
218         chunk_fake[0].length_dw = cs->dwords;
219         chunk_fake[0].kdata = packets;
220
221         parser.dev = dev;
222         parser.file_priv = fpriv;
223         parser.num_chunks = 1;
224         parser.chunks = chunk_fake;
225         parser.ib_index = 0;
226         parser.reloc_index = -1;
227
228         /* get ib */
229         r = dev_priv->cs.ib_get(&parser);
230         if (r) {
231                 goto out;
232         }
233
234         /* now parse command stream */
235         r = dev_priv->cs.parse(&parser);
236         if (r) {
237                 goto out;
238         }
239
240         /* emit cs id sequence */
241         dev_priv->cs.id_emit(&parser, &cs_id);
242         COMMIT_RING();
243
244         cs->cs_id = cs_id;
245 out:
246         dev_priv->cs.ib_free(&parser);
247         drm_free(packets, size, DRM_MEM_DRIVER);
248         return r;
249 }
250
251 /* for non-mm */
252 static int radeon_nomm_relocate(struct drm_radeon_cs_parser *parser, uint32_t *reloc, uint32_t *offset)
253 {
254         *offset = reloc[1];
255         return 0;
256 }
257 #define RELOC_SIZE 2
258 #define RELOC_SIZE_NEW 0
259 #define RADEON_2D_OFFSET_MASK 0x3fffff
260
261 static __inline__ int radeon_cs_relocate_packet0(struct drm_radeon_cs_parser *parser, uint32_t offset_dw)
262 {
263         struct drm_device *dev = parser->dev;
264         drm_radeon_private_t *dev_priv = dev->dev_private;
265         uint32_t hdr, reg, val, packet3_hdr;
266         uint32_t tmp, offset;
267         struct drm_radeon_kernel_chunk *ib_chunk;
268         int ret;
269
270         ib_chunk = &parser->chunks[parser->ib_index];
271 //      if (parser->reloc_index == -1)
272 //              is_old = 1;
273
274         hdr = ib_chunk->kdata[offset_dw];
275         reg = (hdr & R300_CP_PACKET0_REG_MASK) << 2;
276         val = ib_chunk->kdata[offset_dw + 1];
277         packet3_hdr = ib_chunk->kdata[offset_dw + 2];
278
279         /* this is too strict we may want to expand the length in the future and have
280          old kernels ignore it. */ 
281         if (parser->reloc_index == -1) {
282                 if (packet3_hdr != (RADEON_CP_PACKET3 | RADEON_CP_NOP | (RELOC_SIZE << 16))) {
283                         DRM_ERROR("Packet 3 was %x should have been %x: reg is %x\n", packet3_hdr, RADEON_CP_PACKET3 | RADEON_CP_NOP | (RELOC_SIZE << 16), reg);
284                         return -EINVAL;
285                 }
286         } else {
287                 if (packet3_hdr != (RADEON_CP_PACKET3 | RADEON_CP_NOP | (RELOC_SIZE_NEW << 16))) {
288                         DRM_ERROR("Packet 3 was %x should have been %x: reg is %x\n", packet3_hdr, RADEON_CP_PACKET3 | RADEON_CP_NOP | (RELOC_SIZE_NEW << 16), reg);
289                         return -EINVAL;
290
291                 }
292         }
293         
294         switch(reg) {
295         case RADEON_DST_PITCH_OFFSET:
296         case RADEON_SRC_PITCH_OFFSET:
297                 /* pass in the start of the reloc */
298                 ret = dev_priv->cs.relocate(parser, ib_chunk->kdata + offset_dw + 2, &offset);
299                 if (ret)
300                         return ret;
301                 tmp = (val & RADEON_2D_OFFSET_MASK) << 10;
302                 val &= ~RADEON_2D_OFFSET_MASK;
303                 offset += tmp;
304                 offset >>= 10;
305                 val |= offset;
306                 break;
307         case RADEON_RB3D_COLOROFFSET:
308         case R300_RB3D_COLOROFFSET0:
309         case R300_ZB_DEPTHOFFSET:
310         case R300_TX_OFFSET_0:
311         case R300_TX_OFFSET_0+4:
312         case R200_PP_TXOFFSET_0:
313         case R200_PP_TXOFFSET_1:
314         case RADEON_PP_TXOFFSET_0:
315         case RADEON_PP_TXOFFSET_1:
316                 ret = dev_priv->cs.relocate(parser. ib_chunk->kdata + offset_dw + 2, &offset);
317                 if (ret)
318                         return ret;
319
320                 offset &= 0xffffffe0;
321                 val += offset;
322                 break;
323         default:
324                 break;
325         }
326
327         ib_chunk->kdata[offset_dw + 1] = val;
328         return 0;
329 }
330
331 static int radeon_cs_relocate_packet3(struct drm_radeon_cs_parser *parser,
332                                       uint32_t offset_dw)
333 {
334         drm_radeon_private_t *dev_priv = parser->dev->dev_private;
335         uint32_t hdr, num_dw, reg;
336         uint32_t offset, val, tmp;
337         int ret;
338         struct drm_radeon_kernel_chunk *ib_chunk;
339
340         ib_chunk = &parser->chunks[parser->ib_index];
341 //      if (parser->reloc_index == -1)
342 //              is_old = 1;
343
344         hdr = ib_chunk->kdata[offset_dw];
345         num_dw = (hdr & RADEON_CP_PACKET_COUNT_MASK) >> 16;
346         reg = hdr & 0xff00;
347
348         switch(reg) {
349         case RADEON_CNTL_HOSTDATA_BLT:
350         {
351                 val = ib_chunk->kdata[offset_dw + 2];
352                 ret = dev_priv->cs.relocate(parser, ib_chunk->kdata + offset_dw + num_dw + 2, &offset);
353                 if (ret)
354                         return ret;
355
356                 tmp = (val & RADEON_2D_OFFSET_MASK) << 10;
357                 val &= ~RADEON_2D_OFFSET_MASK;
358                 offset += tmp;
359                 offset >>= 10;
360                 val |= offset;
361
362                 ib_chunk->kdata[offset_dw + 2] = val;
363         }
364         default:
365                 return -EINVAL;
366         }
367         return 0;
368 }
369
370 int radeon_cs_packet0(struct drm_radeon_cs_parser *parser, uint32_t offset_dw)
371 {
372         uint32_t hdr, num_dw, reg;
373         int count_dw = 1;
374         int ret;
375
376         hdr = parser->chunks[parser->ib_index].kdata[offset_dw];
377         num_dw = ((hdr & RADEON_CP_PACKET_COUNT_MASK) >> 16) + 2;
378         reg = (hdr & R300_CP_PACKET0_REG_MASK) << 2;
379
380         while (count_dw < num_dw) {
381                 /* need to have something like the r300 validation here - 
382                    list of allowed registers */
383                 int flags;
384
385                 ret = r300_check_range(reg, 1);
386                 switch(ret) {
387                 case -1:
388                         DRM_ERROR("Illegal register %x\n", reg);
389                         break;
390                 case 0:
391                         break;
392                 case 1:
393                         flags = r300_get_reg_flags(reg);
394                         if (flags == MARK_CHECK_OFFSET) {
395                                 if (num_dw > 2) {
396                                         DRM_ERROR("Cannot relocate inside type stream of reg0 packets\n");
397                                         return -EINVAL;
398                                 }
399
400                                 ret = radeon_cs_relocate_packet0(parser, offset_dw);
401                                 if (ret)
402                                         return ret;
403                                 DRM_DEBUG("need to relocate %x %d\n", reg, flags);
404                                 /* okay it should be followed by a NOP */
405                         } else if (flags == MARK_CHECK_SCISSOR) {
406                                 DRM_DEBUG("need to validate scissor %x %d\n", reg, flags);
407                         } else {
408                                 DRM_DEBUG("illegal register %x %d\n", reg, flags);
409                                 return -EINVAL;
410                         }
411                         break;
412                 }
413                 count_dw++;
414                 reg += 4;
415         }
416         return 0;
417 }
418
419 int radeon_cs_parse(struct drm_radeon_cs_parser *parser)
420 {
421         volatile int rb;
422         struct drm_radeon_kernel_chunk *ib_chunk;
423         /* scan the packet for various things */
424         int count_dw = 0, size_dw;
425         int ret = 0;
426
427         ib_chunk = &parser->chunks[parser->ib_index];
428         size_dw = ib_chunk->length_dw;
429
430         while (count_dw < size_dw && ret == 0) {
431                 int hdr = ib_chunk->kdata[count_dw];
432                 int num_dw = (hdr & RADEON_CP_PACKET_COUNT_MASK) >> 16;
433                 int reg;
434
435                 switch (hdr & RADEON_CP_PACKET_MASK) {
436                 case RADEON_CP_PACKET0:
437                         ret = radeon_cs_packet0(parser, count_dw);
438                         break;
439                 case RADEON_CP_PACKET1:
440                 case RADEON_CP_PACKET2:
441                         reg = hdr & RADEON_CP_PACKET0_REG_MASK;
442                         DRM_DEBUG("Packet 1/2: %d  %x\n", num_dw, reg);
443                         break;
444
445                 case RADEON_CP_PACKET3:
446                         reg = hdr & 0xff00;
447                         
448                         switch(reg) {
449                         case RADEON_CNTL_HOSTDATA_BLT:
450                                 radeon_cs_relocate_packet3(parser, count_dw);
451                                 break;
452
453                         case RADEON_CNTL_BITBLT_MULTI:
454                         case RADEON_3D_LOAD_VBPNTR:     /* load vertex array pointers */
455                         case RADEON_CP_INDX_BUFFER:
456                                 DRM_ERROR("need relocate packet 3 for %x\n", reg);
457                                 break;
458
459                         case RADEON_3D_DRAW_IMMD:       /* triggers drawing using in-packet vertex data */
460                         case RADEON_CP_3D_DRAW_IMMD_2:  /* triggers drawing using in-packet vertex data */
461                         case RADEON_CP_3D_DRAW_VBUF_2:  /* triggers drawing of vertex buffers setup elsewhere */
462                         case RADEON_CP_3D_DRAW_INDX_2:  /* triggers drawing using indices to vertex buffer */
463                         case RADEON_WAIT_FOR_IDLE:
464                         case RADEON_CP_NOP:
465                                 break;
466                         default:
467                                 DRM_ERROR("unknown packet 3 %x\n", reg);
468                                 ret = -EINVAL;
469                         }
470                         break;
471                 }
472
473                 count_dw += num_dw+2;
474         }
475
476         if (ret)
477                 return ret;
478              
479
480         /* copy the packet into the IB */
481         memcpy(parser->ib, ib_chunk->kdata, ib_chunk->length_dw * sizeof(uint32_t));
482
483         /* read back last byte to flush WC buffers */
484         rb = readl((parser->ib + (ib_chunk->length_dw-1) * sizeof(uint32_t)));
485
486         return 0;
487 }
488
489 uint32_t radeon_cs_id_get(struct drm_radeon_private *radeon)
490 {
491         /* FIXME: protect with a spinlock */
492         /* FIXME: check if wrap affect last reported wrap & sequence */
493         radeon->cs.id_scnt = (radeon->cs.id_scnt + 1) & 0x00FFFFFF;
494         if (!radeon->cs.id_scnt) {
495                 /* increment wrap counter */
496                 radeon->cs.id_wcnt += 0x01000000;
497                 /* valid sequence counter start at 1 */
498                 radeon->cs.id_scnt = 1;
499         }
500         return (radeon->cs.id_scnt | radeon->cs.id_wcnt);
501 }
502
503 void r100_cs_id_emit(struct drm_radeon_cs_parser *parser, uint32_t *id)
504 {
505         drm_radeon_private_t *dev_priv = parser->dev->dev_private;
506         RING_LOCALS;
507
508         dev_priv->irq_emitted = radeon_update_breadcrumb(parser->dev);
509         /* ISYNC_CNTL should have CPSCRACTH bit set */
510         *id = radeon_cs_id_get(dev_priv);
511         /* emit id in SCRATCH4 (not used yet in old drm) */
512         BEGIN_RING(10);
513         OUT_RING(CP_PACKET0(RADEON_CP_IB_BASE, 1));
514         OUT_RING(parser->card_offset);
515         OUT_RING(parser->chunks[parser->ib_index].length_dw);
516         OUT_RING(CP_PACKET2());
517         OUT_RING(CP_PACKET0(RADEON_SCRATCH_REG4, 0));
518         OUT_RING(*id);
519         OUT_RING_REG(RADEON_LAST_SWI_REG, dev_priv->irq_emitted);
520         OUT_RING_REG(RADEON_GEN_INT_STATUS, RADEON_SW_INT_FIRE);
521         ADVANCE_RING(); 
522         COMMIT_RING();
523
524 }
525
526 void r300_cs_id_emit(struct drm_radeon_cs_parser *parser, uint32_t *id)
527 {
528         drm_radeon_private_t *dev_priv = parser->dev->dev_private;
529         int i;
530         RING_LOCALS;
531
532         dev_priv->irq_emitted = radeon_update_breadcrumb(parser->dev);
533
534         /* ISYNC_CNTL should not have CPSCRACTH bit set */
535         *id = radeon_cs_id_get(dev_priv);
536
537         /* emit id in SCRATCH6 */
538         BEGIN_RING(16);
539         OUT_RING(CP_PACKET0(RADEON_CP_IB_BASE, 1));
540         OUT_RING(parser->card_offset);
541         OUT_RING(parser->chunks[parser->ib_index].length_dw);
542         OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
543         OUT_RING(0);
544         for (i = 0; i < 11; i++) /* emit fillers like fglrx */
545                 OUT_RING(CP_PACKET2());
546         ADVANCE_RING();
547         COMMIT_RING();
548
549         BEGIN_RING(16);
550         OUT_RING_REG(R300_RB3D_DSTCACHE_CTLSTAT, R300_RB3D_DC_FLUSH);
551         OUT_RING(CP_PACKET0(R300_CP_RESYNC_ADDR, 1));
552         OUT_RING(6);
553         OUT_RING(*id);
554         OUT_RING_REG(R300_RB3D_DSTCACHE_CTLSTAT, R300_RB3D_DC_FINISH|R300_RB3D_DC_FLUSH);
555         /* emit inline breadcrumb for TTM fencing */
556 #if 1
557         RADEON_WAIT_UNTIL_3D_IDLE();
558         OUT_RING_REG(RADEON_LAST_SWI_REG, dev_priv->irq_emitted);
559 #else
560         OUT_RING(CP_PACKET0(R300_CP_RESYNC_ADDR, 1));
561         OUT_RING(3); /* breadcrumb register */
562         OUT_RING(dev_priv->irq_emitted);
563         OUT_RING(CP_PACKET2());
564 #endif
565         OUT_RING_REG(RADEON_GEN_INT_STATUS, RADEON_SW_INT_FIRE);
566         OUT_RING(CP_PACKET2());
567         OUT_RING(CP_PACKET2());
568         OUT_RING(CP_PACKET2());
569         ADVANCE_RING(); 
570         COMMIT_RING();
571
572 }
573
574 uint32_t r100_cs_id_last_get(struct drm_device *dev)
575 {
576         drm_radeon_private_t *dev_priv = dev->dev_private;
577
578         return GET_SCRATCH(4);
579 }
580
581 uint32_t r300_cs_id_last_get(struct drm_device *dev)
582 {
583         drm_radeon_private_t *dev_priv = dev->dev_private;
584
585         return GET_SCRATCH(6);
586 }
587
588 int radeon_cs_init(struct drm_device *dev)
589 {
590         drm_radeon_private_t *dev_priv = dev->dev_private;
591
592         if (dev_priv->chip_family < CHIP_RV280) {
593                 dev_priv->cs.id_emit = r100_cs_id_emit;
594                 dev_priv->cs.id_last_get = r100_cs_id_last_get;
595         } else if (dev_priv->chip_family < CHIP_R600) {
596                 dev_priv->cs.id_emit = r300_cs_id_emit;
597                 dev_priv->cs.id_last_get = r300_cs_id_last_get;
598         }
599
600         dev_priv->cs.parse = radeon_cs_parse;
601         /* ib get depends on memory manager or not so memory manager */
602         dev_priv->cs.relocate = radeon_nomm_relocate;
603         return 0;
604 }