OSDN Git Service

Merge branch 'radeon-gem-cs' into modesetting-gem
authorDave Airlie <airlied@redhat.com>
Wed, 13 Aug 2008 23:36:34 +0000 (09:36 +1000)
committerDave Airlie <airlied@redhat.com>
Wed, 13 Aug 2008 23:36:34 +0000 (09:36 +1000)
Conflicts:

libdrm/xf86drm.c
linux-core/Makefile.kernel
linux-core/drmP.h
linux-core/drm_compat.h
linux-core/drm_drv.c
linux-core/drm_stub.c
linux-core/drm_vm.c
shared-core/i915_dma.c
shared-core/r300_cmdbuf.c
shared-core/radeon_drv.h

20 files changed:
1  2 
libdrm/intel/intel_bufmgr_fake.c
linux-core/Makefile.kernel
linux-core/drmP.h
linux-core/drm_bo.c
linux-core/drm_drv.c
linux-core/drm_memory.c
linux-core/drm_objects.h
linux-core/drm_stub.c
linux-core/drm_vm.c
linux-core/radeon_buffer.c
linux-core/radeon_reg.h
shared-core/drm.h
shared-core/i915_dma.c
shared-core/i915_drm.h
shared-core/i915_init.c
shared-core/r300_cmdbuf.c
shared-core/r300_reg.h
shared-core/radeon_cp.c
shared-core/radeon_cs.c
shared-core/radeon_drv.h

Simple merge
@@@ -12,21 -12,18 +12,20 @@@ drm-objs    := drm_auth.o drm_bufs.o dr
                drm_lock.o drm_memory.o drm_proc.o drm_stub.o drm_vm.o \
                drm_sysfs.o drm_pci.o drm_agpsupport.o drm_scatter.o \
                drm_memory_debug.o ati_pcigart.o drm_sman.o \
-               drm_hashtab.o drm_mm.o drm_object.o drm_compat.o \
-               drm_fence.o drm_ttm.o drm_bo.o drm_bo_move.o drm_bo_lock.o \
 -              drm_hashtab.o drm_memrange.o drm_compat.o \
++              drm_hashtab.o drm_mm.o drm_compat.o \
+               drm_fence.o drm_ttm.o drm_bo.o drm_bo_move.o \
                drm_crtc.o drm_edid.o drm_modes.o drm_crtc_helper.o \
                drm_regman.o drm_vm_nopage_compat.o drm_gem.o
  tdfx-objs   := tdfx_drv.o
  r128-objs   := r128_drv.o r128_cce.o r128_state.o r128_irq.o
  mga-objs    := mga_drv.o mga_dma.o mga_state.o mga_warp.o mga_irq.o
  i810-objs   := i810_drv.o i810_dma.o
- i915-objs   := i915_drv.o i915_dma.o i915_irq.o i915_mem.o i915_fence.o \
-               i915_buffer.o i915_compat.o i915_execbuf.o i915_suspend.o \
-               i915_opregion.o \
 -i915-objs   := i915_drv.o i915_dma.o i915_irq.o i915_mem.o i915_gem.o \
++i915-objs   := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \
++              i915_compat.o i915_suspend.o i915_opregion.o \
 +              i915_gem.o i915_gem_debug.o i915_gem_proc.o i915_gem_tiling.o \
                intel_display.o intel_crt.o intel_lvds.o intel_bios.o \
                intel_sdvo.o intel_modes.o intel_i2c.o i915_init.o intel_fb.o \
 -              intel_tv.o i915_compat.o intel_dvo.o dvo_ch7xxx.o \
 +              intel_tv.o intel_dvo.o dvo_ch7xxx.o \
                dvo_ch7017.o dvo_ivch.o dvo_tfp410.o dvo_sil164.o
  nouveau-objs := nouveau_drv.o nouveau_state.o nouveau_fifo.o nouveau_mem.o \
                nouveau_object.o nouveau_irq.o nouveau_notifier.o nouveau_swmthd.o \
@@@ -900,8 -888,7 +883,7 @@@ struct drm_device 
        struct list_head maplist;       /**< Linked list of regions */
        int map_count;                  /**< Number of mappable regions */
        struct drm_open_hash map_hash;       /**< User token hash table for maps */
 -      struct drm_memrange offset_manager;  /**< User token manager */
 +      struct drm_mm offset_manager;        /**< User token manager */
-       struct drm_open_hash object_hash;    /**< User token hash table for objects */
        struct address_space *dev_mapping;  /**< For unmap_mapping_range() */
        struct page *ttm_dummy_page;
  
Simple merge
@@@ -146,37 -146,6 +146,7 @@@ static struct drm_ioctl_desc drm_ioctls
        DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_MASTER),
        DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER),
  
-       DRM_IOCTL_DEF(DRM_IOCTL_MM_INIT, drm_mm_init_ioctl,
-                     DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_IOCTL_MM_TAKEDOWN, drm_mm_takedown_ioctl,
-                     DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_IOCTL_MM_LOCK, drm_mm_lock_ioctl,
-                     DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_IOCTL_MM_UNLOCK, drm_mm_unlock_ioctl,
-                     DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_IOCTL_FENCE_CREATE, drm_fence_create_ioctl, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_IOCTL_FENCE_REFERENCE, drm_fence_reference_ioctl, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_IOCTL_FENCE_UNREFERENCE, drm_fence_unreference_ioctl, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_IOCTL_FENCE_SIGNALED, drm_fence_signaled_ioctl, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_IOCTL_FENCE_FLUSH, drm_fence_flush_ioctl, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_IOCTL_FENCE_WAIT, drm_fence_wait_ioctl, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_IOCTL_FENCE_EMIT, drm_fence_emit_ioctl, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_IOCTL_FENCE_BUFFERS, drm_fence_buffers_ioctl, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_IOCTL_BO_CREATE, drm_bo_create_ioctl, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_IOCTL_BO_MAP, drm_bo_map_ioctl, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_IOCTL_BO_UNMAP, drm_bo_unmap_ioctl, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_IOCTL_BO_REFERENCE, drm_bo_reference_ioctl, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_IOCTL_BO_UNREFERENCE, drm_bo_unreference_ioctl, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_IOCTL_BO_SETSTATUS, drm_bo_setstatus_ioctl, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_IOCTL_BO_INFO, drm_bo_info_ioctl, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_IOCTL_BO_WAIT_IDLE, drm_bo_wait_idle_ioctl, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_IOCTL_BO_VERSION, drm_bo_version_ioctl, 0),
-       DRM_IOCTL_DEF(DRM_IOCTL_MM_INFO, drm_mm_info_ioctl, 0),
 +#if OS_HAS_GEM
        DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, 0),
        DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH),
        DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH),
@@@ -430,12 -393,12 +395,12 @@@ static void drm_cleanup(struct drm_devi
  
        drm_ctxbitmap_cleanup(dev);
        drm_ht_remove(&dev->map_hash);
 -      drm_memrange_takedown(&dev->offset_manager);
 +      drm_mm_takedown(&dev->offset_manager);
-       drm_ht_remove(&dev->object_hash);
  
-       drm_put_minor(dev, &dev->primary);
        if (drm_core_check_feature(dev, DRIVER_MODESET))
-               drm_put_minor(dev, &dev->control);
+               drm_put_minor(&dev->control);
+       drm_put_minor(&dev->primary);
  
        if (drm_put_dev(dev))
                DRM_ERROR("Cannot unload module\n");
Simple merge
Simple merge
Simple merge
@@@ -715,13 -715,8 +715,9 @@@ static int drm_bo_vm_fault(struct vm_ar
        unsigned long ret = VM_FAULT_NOPAGE;
  
        dev = bo->dev;
-       err = drm_bo_read_lock(&dev->bm.bm_lock, 1);
-       if (err)
-               return VM_FAULT_NOPAGE;
 +
        err = mutex_lock_interruptible(&bo->mutex);
        if (err) {
-               drm_bo_read_unlock(&dev->bm.bm_lock);
                return VM_FAULT_NOPAGE;
        }
  
Simple merge
  #       define R300_ENDIAN_SWAP_HALF_DWORD              (3 << 0)
  #       define R300_MACRO_TILE                          (1 << 2)
  
 -#define R300_TX_BORDER_COLOR_0                                0x45c0
++#define R300_TX_BORDER_COLOR_0                          0x45c0
  #define R300_TX_ENABLE                                        0x4104
  #       define R300_TEX_0_ENABLE                        (1 << 0)
  #       define R300_TEX_1_ENABLE                        (1 << 1)
  #       define R300_READ_ENABLE                         (1 << 2)
  #define R300_RB3D_ABLENDCNTL                          0x4e08
  #define R300_RB3D_DSTCACHE_CTLSTAT                    0x4e4c
 -#define R300_RB3D_COLOROFFSET0                                0x4e28
 -#define R300_RB3D_COLORPITCH0                         0x4e38
++#define R300_RB3D_COLOROFFSET0                          0x4e28
++#define R300_RB3D_COLORPITCH0                           0x4e38
+ #       define R300_COLORTILE                           (1 << 16)
+ #       define R300_COLORENDIAN_WORD                    (1 << 19)
+ #       define R300_COLORENDIAN_DWORD                   (2 << 19)
+ #       define R300_COLORENDIAN_HALF_DWORD              (3 << 19)
+ #       define R300_COLORFORMAT_ARGB1555                (3 << 21)
+ #       define R300_COLORFORMAT_RGB565                  (4 << 21)
+ #       define R300_COLORFORMAT_ARGB8888                (6 << 21)
+ #       define R300_COLORFORMAT_ARGB32323232            (7 << 21)
+ #       define R300_COLORFORMAT_I8                      (9 << 21)
+ #       define R300_COLORFORMAT_ARGB16161616            (10 << 21)
+ #       define R300_COLORFORMAT_VYUY                    (11 << 21)
+ #       define R300_COLORFORMAT_YVYU                    (12 << 21)
+ #       define R300_COLORFORMAT_UV88                    (13 << 21)
+ #       define R300_COLORFORMAT_ARGB4444                (15 << 21)
 -#define R300_RB3D_AARESOLVE_CTL                               0x4e88
++#define R300_RB3D_AARESOLVE_CTL                         0x4e88
  #define R300_RB3D_COLOR_CHANNEL_MASK                  0x4e0c
  #       define R300_BLUE_MASK_EN                        (1 << 0)
  #       define R300_GREEN_MASK_EN                       (1 << 1)
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -256,7 -246,8 +259,8 @@@ void r300_init_reg_flags(struct drm_dev
                ADD_RANGE(R500_RS_INST_0, 16);
                ADD_RANGE(R500_RB3D_COLOR_CLEAR_VALUE_AR, 2);
                ADD_RANGE(R500_RB3D_CONSTANT_COLOR_AR, 2);
 -
 +              ADD_RANGE(R500_ZB_FIFO_SIZE, 2);
+               ADD_RANGE(R500_GA_US_VECTOR_INDEX, 2);
        } else {
                ADD_RANGE(R300_PFS_CNTL_0, 3);
                ADD_RANGE(R300_PFS_NODE_0, 4);
Simple merge
Simple merge
index 0000000,d961189..b0c4abe
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,411 +1,411 @@@
 -      case R300_RB3D_DEPTHOFFSET:
+ /*
+  * Copyright 2008 Jerome Glisse.
+  * All Rights Reserved.
+  *
+  * Permission is hereby granted, free of charge, to any person obtaining a
+  * copy of this software and associated documentation files (the "Software"),
+  * to deal in the Software without restriction, including without limitation
+  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+  * and/or sell copies of the Software, and to permit persons to whom the
+  * Software is furnished to do so, subject to the following conditions:
+  *
+  * The above copyright notice and this permission notice (including the next
+  * paragraph) shall be included in all copies or substantial portions of the
+  * Software.
+  *
+  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+  * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+  * DEALINGS IN THE SOFTWARE.
+  *
+  * Authors:
+  *    Jerome Glisse <glisse@freedesktop.org>
+  */
+ #include "drmP.h"
+ #include "radeon_drm.h"
+ #include "radeon_drv.h"
+ #include "r300_reg.h"
+ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv)
+ {
+       struct drm_radeon_private *dev_priv = dev->dev_private;
+       struct drm_radeon_cs *cs = data;
+       uint32_t *packets = NULL;
+       uint32_t cs_id;
+       uint32_t card_offset;
+       void *ib = NULL;
+       long size;
+       int r;
+       RING_LOCALS;
+       /* set command stream id to 0 which is fake id */
+       cs_id = 0;
+       DRM_COPY_TO_USER(&cs->cs_id, &cs_id, sizeof(uint32_t));
+       if (dev_priv == NULL) {
+               DRM_ERROR("called with no initialization\n");
+               return -EINVAL;
+       }
+       if (!cs->dwords) {
+               return 0;
+       }
+       /* limit cs to 64K ib */
+       if (cs->dwords > (16 * 1024)) {
+               return -EINVAL;
+       }
+       /* copy cs from userspace maybe we should copy into ib to save
+        * one copy but ib will be mapped wc so not good for cmd checking
+        * somethings worth testing i guess (Jerome)
+        */
+       size = cs->dwords * sizeof(uint32_t);
+       packets = drm_alloc(size, DRM_MEM_DRIVER);
+       if (packets == NULL) {
+               return -ENOMEM;
+       }
+       if (DRM_COPY_FROM_USER(packets, (void __user *)(unsigned long)cs->packets, size)) {
+               r = -EFAULT;
+               goto out;
+       }
+       /* get ib */
+       r = dev_priv->cs.ib_get(dev, &ib, cs->dwords, &card_offset);
+       if (r) {
+               goto out;
+       }
+       /* now parse command stream */
+       r = dev_priv->cs.parse(dev, fpriv, ib, packets, cs->dwords);
+       if (r) {
+               goto out;
+       }
+       BEGIN_RING(4);
+       OUT_RING(CP_PACKET0(RADEON_CP_IB_BASE, 1));
+       OUT_RING(card_offset);
+       OUT_RING(cs->dwords);
+       OUT_RING(CP_PACKET2());
+       ADVANCE_RING();
+       /* emit cs id sequence */
+       dev_priv->cs.id_emit(dev, &cs_id);
+       COMMIT_RING();
+       DRM_COPY_TO_USER(&cs->cs_id, &cs_id, sizeof(uint32_t));
+ out:
+       dev_priv->cs.ib_free(dev, ib, cs->dwords);
+       drm_free(packets, size, DRM_MEM_DRIVER);
+       return r;
+ }
+ /* for non-mm */
+ static int radeon_nomm_relocate(struct drm_device *dev, struct drm_file *file_priv, uint32_t *reloc, uint32_t *offset)
+ {
+       *offset = reloc[1];
+       return 0;
+ }
+ #define RELOC_SIZE 2
+ #define RADEON_2D_OFFSET_MASK 0x3fffff
+ static __inline__ int radeon_cs_relocate_packet0(struct drm_device *dev, struct drm_file *file_priv,
+                                                uint32_t *packets, uint32_t offset_dw)
+ {
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       uint32_t hdr = packets[offset_dw];
+       uint32_t reg = (hdr & R300_CP_PACKET0_REG_MASK) << 2;
+       uint32_t val = packets[offset_dw + 1];
+       uint32_t packet3_hdr = packets[offset_dw+2];
+       uint32_t tmp, offset;
+       int ret;
+       /* this is too strict we may want to expand the length in the future and have
+        old kernels ignore it. */ 
+       if (packet3_hdr != (RADEON_CP_PACKET3 | RADEON_CP_NOP | (RELOC_SIZE << 16))) {
+               DRM_ERROR("Packet 3 was %x should have been %x\n", packet3_hdr, RADEON_CP_PACKET3 | RADEON_CP_NOP | (RELOC_SIZE << 16));
+               return -EINVAL;
+       }
+       
+       switch(reg) {
+       case RADEON_DST_PITCH_OFFSET:
+       case RADEON_SRC_PITCH_OFFSET:
+               /* pass in the start of the reloc */
+               ret = dev_priv->cs.relocate(dev, file_priv, packets + offset_dw + 2, &offset);
+               if (ret)
+                       return ret;
+               tmp = (val & RADEON_2D_OFFSET_MASK) << 10;
+               val &= ~RADEON_2D_OFFSET_MASK;
+               offset += tmp;
+               offset >>= 10;
+               val |= offset;
+               break;
+       case R300_RB3D_COLOROFFSET0:
 -      case R300_RB3D_DEPTHOFFSET:
++      case R300_ZB_DEPTHOFFSET:
+       case R300_TX_OFFSET_0:
+       case R300_TX_OFFSET_0+4:
+               ret = dev_priv->cs.relocate(dev, file_priv, packets + offset_dw + 2, &offset);
+               if (ret)
+                       return ret;
+               offset &= 0xffffffe0;
+               val += offset;
+               break;
+       default:
+               break;
+       }
+       packets[offset_dw + 1] = val;
+       return 0;
+ }
+ static int radeon_cs_relocate_packet3(struct drm_device *dev, struct drm_file *file_priv,
+                                     uint32_t *packets, uint32_t offset_dw)
+ {
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       uint32_t hdr = packets[offset_dw];
+       int num_dw = (hdr & RADEON_CP_PACKET_COUNT_MASK) >> 16;
+       uint32_t reg = hdr & 0xff00;
+       uint32_t offset, val, tmp;
+       int ret;
+       switch(reg) {
+       case RADEON_CNTL_HOSTDATA_BLT:
+       {
+               val = packets[offset_dw + 2];
+               ret = dev_priv->cs.relocate(dev, file_priv, packets + offset_dw + num_dw + 2, &offset);
+               if (ret)
+                       return ret;
+               tmp = (val & RADEON_2D_OFFSET_MASK) << 10;
+               val &= ~RADEON_2D_OFFSET_MASK;
+               offset += tmp;
+               offset >>= 10;
+               val |= offset;
+               packets[offset_dw + 2] = val;
+       }
+       default:
+               return -EINVAL;
+       }
+       return 0;
+ }
+ static __inline__ int radeon_cs_check_offset(struct drm_device *dev,
+                                            uint32_t reg, uint32_t val)
+ {
+       uint32_t offset;
+       switch(reg) {
+       case RADEON_DST_PITCH_OFFSET:
+       case RADEON_SRC_PITCH_OFFSET:
+               offset = val & ((1 << 22) - 1);
+               offset <<= 10;
+               break;
+       case R300_RB3D_COLOROFFSET0:
++      case R300_ZB_DEPTHOFFSET:
+               offset = val;
+               break;
+       case R300_TX_OFFSET_0:
+       case R300_TX_OFFSET_0+4:
+               offset = val & 0xffffffe0;
+               break;
+       }
+       
+       return 0;
+ }
+ int radeon_cs_packet0(struct drm_device *dev, struct drm_file *file_priv,
+                     uint32_t *packets, uint32_t offset_dw)
+ {
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       uint32_t hdr = packets[offset_dw];
+       int num_dw = ((hdr & RADEON_CP_PACKET_COUNT_MASK) >> 16) + 2;
+       int need_reloc = 0;
+       int reg = (hdr & R300_CP_PACKET0_REG_MASK) << 2;
+       int count_dw = 1;
+       int ret;
+       while (count_dw < num_dw) {
+               /* need to have something like the r300 validation here - 
+                  list of allowed registers */
+               int flags;
+               ret = r300_check_range(reg, 1);
+               switch(ret) {
+               case -1:
+                       DRM_ERROR("Illegal register %x\n", reg);
+                       break;
+               case 0:
+                       break;
+               case 1:
+                       flags = r300_get_reg_flags(reg);
+                       if (flags == MARK_CHECK_OFFSET) {
+                               if (num_dw > 2) {
+                                       DRM_ERROR("Cannot relocate inside type stream of reg0 packets\n");
+                                       return -EINVAL;
+                               }
+                               ret = radeon_cs_relocate_packet0(dev, file_priv, packets, offset_dw);
+                               if (ret)
+                                       return ret;
+                               DRM_DEBUG("need to relocate %x %d\n", reg, flags);
+                               /* okay it should be followed by a NOP */
+                       } else if (flags == MARK_CHECK_SCISSOR) {
+                               DRM_DEBUG("need to validate scissor %x %d\n", reg, flags);
+                       } else {
+                               DRM_DEBUG("illegal register %x %d\n", reg, flags);
+                               return -EINVAL;
+                       }
+                       break;
+               }
+               count_dw++;
+               reg += 4;
+       }
+       return 0;
+ }
+ int radeon_cs_parse(struct drm_device *dev, struct drm_file *file_priv,
+                   void *ib, uint32_t *packets, uint32_t dwords)
+ {
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       volatile int rb;
+       int size_dw = dwords;
+       /* scan the packet for various things */
+       int count_dw = 0;
+       int ret = 0;
+       while (count_dw < size_dw && ret == 0) {
+               int hdr = packets[count_dw];
+               int num_dw = (hdr & RADEON_CP_PACKET_COUNT_MASK) >> 16;
+               int reg;
+               switch (hdr & RADEON_CP_PACKET_MASK) {
+               case RADEON_CP_PACKET0:
+                       ret = radeon_cs_packet0(dev, file_priv, packets, count_dw);
+                       break;
+               case RADEON_CP_PACKET1:
+               case RADEON_CP_PACKET2:
+                       reg = hdr & RADEON_CP_PACKET0_REG_MASK;
+                       DRM_DEBUG("Packet 1/2: %d  %x\n", num_dw, reg);
+                       break;
+               case RADEON_CP_PACKET3:
+                       reg = hdr & 0xff00;
+                       
+                       switch(reg) {
+                       case RADEON_CNTL_HOSTDATA_BLT:
+                               radeon_cs_relocate_packet3(dev, file_priv, packets, count_dw);
+                               break;
+                       case RADEON_CNTL_BITBLT_MULTI:
+                       case RADEON_3D_LOAD_VBPNTR:     /* load vertex array pointers */
+                       case RADEON_CP_INDX_BUFFER:
+                               DRM_ERROR("need relocate packet 3 for %x\n", reg);
+                               break;
+                       case RADEON_CP_3D_DRAW_IMMD_2:  /* triggers drawing using in-packet vertex data */
+                       case RADEON_CP_3D_DRAW_VBUF_2:  /* triggers drawing of vertex buffers setup elsewhere */
+                       case RADEON_CP_3D_DRAW_INDX_2:  /* triggers drawing using indices to vertex buffer */
+                       case RADEON_WAIT_FOR_IDLE:
+                       case RADEON_CP_NOP:
+                               break;
+                       default:
+                               DRM_ERROR("unknown packet 3 %x\n", reg);
+                               ret = -EINVAL;
+                       }
+                       break;
+               }
+               count_dw += num_dw+2;
+       }
+       if (ret)
+               return ret;
+            
+       /* copy the packet into the IB */
+       memcpy(ib, packets, dwords * sizeof(uint32_t));
+       /* read back last byte to flush WC buffers */
+       rb = readl((ib + (dwords-1) * sizeof(uint32_t)));
+       return 0;
+ }
+ uint32_t radeon_cs_id_get(struct drm_radeon_private *radeon)
+ {
+       /* FIXME: protect with a spinlock */
+       /* FIXME: check if wrap affect last reported wrap & sequence */
+       radeon->cs.id_scnt = (radeon->cs.id_scnt + 1) & 0x00FFFFFF;
+       if (!radeon->cs.id_scnt) {
+               /* increment wrap counter */
+               radeon->cs.id_wcnt += 0x01000000;
+               /* valid sequence counter start at 1 */
+               radeon->cs.id_scnt = 1;
+       }
+       return (radeon->cs.id_scnt | radeon->cs.id_wcnt);
+ }
+ void r100_cs_id_emit(struct drm_device *dev, uint32_t *id)
+ {
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       RING_LOCALS;
+       /* ISYNC_CNTL should have CPSCRACTH bit set */
+       *id = radeon_cs_id_get(dev_priv);
+       /* emit id in SCRATCH4 (not used yet in old drm) */
+       BEGIN_RING(2);
+       OUT_RING(CP_PACKET0(RADEON_SCRATCH_REG4, 0));
+       OUT_RING(*id);
+       ADVANCE_RING(); 
+ }
+ void r300_cs_id_emit(struct drm_device *dev, uint32_t *id)
+ {
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       RING_LOCALS;
+       /* ISYNC_CNTL should not have CPSCRACTH bit set */
+       *id = radeon_cs_id_get(dev_priv);
+       /* emit id in SCRATCH6 */
+       BEGIN_RING(6);
+       OUT_RING(CP_PACKET0(R300_CP_RESYNC_ADDR, 0));
+       OUT_RING(6);
+       OUT_RING(CP_PACKET0(R300_CP_RESYNC_DATA, 0));
+       OUT_RING(*id);
+       OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
+       OUT_RING(R300_RB3D_DC_FINISH);
+       ADVANCE_RING(); 
+ }
+ uint32_t r100_cs_id_last_get(struct drm_device *dev)
+ {
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       return RADEON_READ(RADEON_SCRATCH_REG4);
+ }
+ uint32_t r300_cs_id_last_get(struct drm_device *dev)
+ {
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       return RADEON_READ(RADEON_SCRATCH_REG6);
+ }
+ int radeon_cs_init(struct drm_device *dev)
+ {
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       if (dev_priv->chip_family < CHIP_RV280) {
+               dev_priv->cs.id_emit = r100_cs_id_emit;
+               dev_priv->cs.id_last_get = r100_cs_id_last_get;
+       } else if (dev_priv->chip_family < CHIP_R600) {
+               dev_priv->cs.id_emit = r300_cs_id_emit;
+               dev_priv->cs.id_last_get = r300_cs_id_last_get;
+       }
+       dev_priv->cs.parse = radeon_cs_parse;
+       /* ib get depends on memory manager or not so memory manager */
+       dev_priv->cs.relocate = radeon_nomm_relocate;
+       return 0;
+ }
@@@ -286,9 -289,28 +289,31 @@@ struct drm_radeon_master_private 
        drm_radeon_sarea_t *sarea_priv;
  };
  
 +#define RADEON_FLUSH_EMITED   (1 < 0)
 +#define RADEON_PURGE_EMITED   (1 < 1)
 +
+ /* command submission struct */
+ struct drm_radeon_cs_priv {
+       uint32_t id_wcnt;
+       uint32_t id_scnt;
+       uint32_t id_last_wcnt;
+       uint32_t id_last_scnt;
+       int (*parse)(struct drm_device *dev, struct drm_file *file_priv,
+                    void *ib, uint32_t *packets, uint32_t dwords);
+       void (*id_emit)(struct drm_device *dev, uint32_t *id);
+       uint32_t (*id_last_get)(struct drm_device *dev);
+       /* this ib handling callback are for hidding memory manager drm
+        * from memory manager less drm, free have to emit ib discard
+        * sequence into the ring */
+       int (*ib_get)(struct drm_device *dev, void **ib, uint32_t dwords, uint32_t *card_offset);
+       uint32_t (*ib_get_ptr)(struct drm_device *dev, void *ib);
+       void (*ib_free)(struct drm_device *dev, void *ib, uint32_t dwords);
+       /* do a relocation either MM or non-MM */
+       int (*relocate)(struct drm_device *dev, struct drm_file *file_priv,
+                        uint32_t *reloc, uint32_t *offset);
+ };
  typedef struct drm_radeon_private {
  
        drm_radeon_ring_buffer_t ring;
        uint32_t flags;         /* see radeon_chip_flags */
        unsigned long fb_aper_offset;
  
 -      int num_gb_pipes;
 -
+       bool mm_enabled;
        struct radeon_mm_info mm;
        drm_local_map_t *mmio;
  
        u32 ram_width;
  
        enum radeon_pll_errata pll_errata;
 +      
 +      int num_gb_pipes;
 +      int track_flush;
 +      uint32_t chip_family; /* extract from flags */
+       struct radeon_mm_obj **ib_objs;
+       /* ib bitmap */
+       uint64_t ib_alloc_bitmap; // TO DO replace with a real bitmap
+       struct drm_radeon_cs_priv cs;
  } drm_radeon_private_t;
  
  typedef struct drm_radeon_buf_priv {
@@@ -1334,12 -1386,12 +1386,12 @@@ do {                                                                 
  
  #define RADEON_PURGE_CACHE() do {                                     \
        if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) {     \
-               OUT_RING(CP_PACKET0( RADEON_RB3D_DSTCACHE_CTLSTAT, 0)); \
-               OUT_RING(RADEON_RB3D_DC_FLUSH | RADEON_RB3D_DC_FREE);   \
+               OUT_RING(CP_PACKET0(RADEON_RB3D_DSTCACHE_CTLSTAT, 0));  \
 -              OUT_RING(RADEON_RB3D_DC_FLUSH_ALL);                     \
++              OUT_RING(RADEON_RB3D_DC_FLUSH | RADEON_RB3D_DC_FREE);   \
        } else {                                                        \
-               OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));    \
-               OUT_RING(R300_RB3D_DC_FLUSH | R300_RB3D_DC_FREE );      \
-         }                                                               \
+               OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));    \
 -              OUT_RING(RADEON_RB3D_DC_FLUSH_ALL);                     \
++              OUT_RING(R300_RB3D_DC_FLUSH | R300_RB3D_DC_FREE );      \
+       }                                                               \
  } while (0)
  
  #define RADEON_FLUSH_ZCACHE() do {                                    \
  
  #define RADEON_PURGE_ZCACHE() do {                                    \
        if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) {     \
-               OUT_RING(CP_PACKET0(RADEON_RB3D_ZCACHE_CTLSTAT, 0));    \
-               OUT_RING(RADEON_RB3D_ZC_FLUSH | RADEON_RB3D_ZC_FREE);   \
+               OUT_RING(CP_PACKET0(RADEON_RB3D_ZCACHE_CTLSTAT, 0));    \
 -              OUT_RING(RADEON_RB3D_ZC_FLUSH_ALL);                     \
++              OUT_RING(RADEON_RB3D_ZC_FLUSH | RADEON_RB3D_ZC_FREE);   \
        } else {                                                        \
-               OUT_RING(CP_PACKET0(R300_ZB_ZCACHE_CTLSTAT, 0));        \
-               OUT_RING(R300_ZC_FLUSH | R300_ZC_FREE);                 \
-         }                                                               \
 -              OUT_RING(CP_PACKET0(R300_RB3D_ZCACHE_CTLSTAT, 0));      \
 -              OUT_RING(R300_ZC_FLUSH_ALL);                            \
++              OUT_RING(CP_PACKET0(R300_ZB_ZCACHE_CTLSTAT, 0));        \
++              OUT_RING(R300_ZC_FLUSH | R300_ZC_FREE);                 \
+       }                                                               \
  } while (0)
  
  /* ================================================================