connector->funcs->reset(connector);
 }
 EXPORT_SYMBOL(drm_mode_config_reset);
+
+int drm_mode_create_dumb_ioctl(struct drm_device *dev,
+                              void *data, struct drm_file *file_priv)
+{
+       struct drm_mode_create_dumb *args = data;
+
+       if (!dev->driver->dumb_create)
+               return -ENOSYS;
+       return dev->driver->dumb_create(file_priv, dev, args);
+}
+
+int drm_mode_mmap_dumb_ioctl(struct drm_device *dev,
+                            void *data, struct drm_file *file_priv)
+{
+       struct drm_mode_map_dumb *args = data;
+
+       /* call driver ioctl to get mmap offset */
+       if (!dev->driver->dumb_map_offset)
+               return -ENOSYS;
+
+       return dev->driver->dumb_map_offset(file_priv, dev, args->handle, &args->offset);
+}
+
+int drm_mode_destroy_dumb_ioctl(struct drm_device *dev,
+                               void *data, struct drm_file *file_priv)
+{
+       struct drm_mode_destroy_dumb *args = data;
+
+       if (!dev->driver->dumb_destroy)
+               return -ENOSYS;
+
+       return dev->driver->dumb_destroy(file_priv, dev, args->handle);
+}
 
        DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
        DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
        DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED)
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_DUMB, drm_mode_create_dumb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_MAP_DUMB, drm_mode_mmap_dumb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED)
 };
 
 #define DRM_CORE_IOCTL_COUNT   ARRAY_SIZE( drm_ioctls )
 
 /**
  * Removes the mapping from handle to filp for this object.
  */
-static int
+int
 drm_gem_handle_delete(struct drm_file *filp, u32 handle)
 {
        struct drm_device *dev;
 
        return 0;
 }
+EXPORT_SYMBOL(drm_gem_handle_delete);
 
 /**
  * Create a handle for this object. This adds a handle reference
 
        .gem_init_object = i915_gem_init_object,
        .gem_free_object = i915_gem_free_object,
        .gem_vm_ops = &i915_gem_vm_ops,
+       .dumb_create = i915_gem_dumb_create,
+       .dumb_map_offset = i915_gem_mmap_gtt,
+       .dumb_destroy = i915_gem_dumb_destroy,
        .ioctls = i915_ioctls,
        .fops = {
                 .owner = THIS_MODULE,
 
                                    struct intel_ring_buffer *ring,
                                    u32 seqno);
 
+int i915_gem_dumb_create(struct drm_file *file_priv,
+                        struct drm_device *dev,
+                        struct drm_mode_create_dumb *args);
+int i915_gem_mmap_gtt(struct drm_file *file_priv, struct drm_device *dev,
+                     uint32_t handle, uint64_t *offset);
+int i915_gem_dumb_destroy(struct drm_file *file_priv, struct drm_device *dev,
+                         uint32_t handle);                       
 /**
  * Returns true if seq1 is later than seq2.
  */
 
        return 0;
 }
 
-/**
- * Creates a new mm object and returns a handle to it.
- */
-int
-i915_gem_create_ioctl(struct drm_device *dev, void *data,
-                     struct drm_file *file)
+static int
+i915_gem_create(struct drm_file *file,
+               struct drm_device *dev,
+               uint64_t size,
+               uint32_t *handle_p)
 {
-       struct drm_i915_gem_create *args = data;
        struct drm_i915_gem_object *obj;
        int ret;
        u32 handle;
 
-       args->size = roundup(args->size, PAGE_SIZE);
+       size = roundup(size, PAGE_SIZE);
 
        /* Allocate the new object */
-       obj = i915_gem_alloc_object(dev, args->size);
+       obj = i915_gem_alloc_object(dev, size);
        if (obj == NULL)
                return -ENOMEM;
 
        drm_gem_object_unreference(&obj->base);
        trace_i915_gem_object_create(obj);
 
-       args->handle = handle;
+       *handle_p = handle;
        return 0;
 }
 
+int
+i915_gem_dumb_create(struct drm_file *file,
+                    struct drm_device *dev,
+                    struct drm_mode_create_dumb *args)
+{
+       /* have to work out size/pitch and return them */
+       args->pitch = ALIGN(args->width & ((args->bpp + 1) / 8), 64);
+       args->size = args->pitch * args->height;
+       return i915_gem_create(file, dev,
+                              args->size, &args->handle);
+}
+
+int i915_gem_dumb_destroy(struct drm_file *file,
+                         struct drm_device *dev,
+                         uint32_t handle)
+{
+       return drm_gem_handle_delete(file, handle);
+}
+
+/**
+ * Creates a new mm object and returns a handle to it.
+ */
+int
+i915_gem_create_ioctl(struct drm_device *dev, void *data,
+                     struct drm_file *file)
+{
+       struct drm_i915_gem_create *args = data;
+       return i915_gem_create(file, dev,
+                              args->size, &args->handle);
+}
+
 static int i915_gem_object_needs_bit17_swizzle(struct drm_i915_gem_object *obj)
 {
        drm_i915_private_t *dev_priv = obj->base.dev->dev_private;
        return tile_height * obj->stride * 2;
 }
 
-/**
- * i915_gem_mmap_gtt_ioctl - prepare an object for GTT mmap'ing
- * @dev: DRM device
- * @data: GTT mapping ioctl data
- * @file: GEM object info
- *
- * Simply returns the fake offset to userspace so it can mmap it.
- * The mmap call will end up in drm_gem_mmap(), which will set things
- * up so we can get faults in the handler above.
- *
- * The fault handler will take care of binding the object into the GTT
- * (since it may have been evicted to make room for something), allocating
- * a fence register, and mapping the appropriate aperture address into
- * userspace.
- */
 int
-i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data,
-                       struct drm_file *file)
+i915_gem_mmap_gtt(struct drm_file *file,
+                 struct drm_device *dev,
+                 uint32_t handle,
+                 uint64_t *offset)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct drm_i915_gem_mmap_gtt *args = data;
        struct drm_i915_gem_object *obj;
        int ret;
 
        if (ret)
                return ret;
 
-       obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
+       obj = to_intel_bo(drm_gem_object_lookup(dev, file, handle));
        if (obj == NULL) {
                ret = -ENOENT;
                goto unlock;
                        goto out;
        }
 
-       args->offset = (u64)obj->base.map_list.hash.key << PAGE_SHIFT;
+       *offset = (u64)obj->base.map_list.hash.key << PAGE_SHIFT;
 
 out:
        drm_gem_object_unreference(&obj->base);
        return ret;
 }
 
+/**
+ * i915_gem_mmap_gtt_ioctl - prepare an object for GTT mmap'ing
+ * @dev: DRM device
+ * @data: GTT mapping ioctl data
+ * @file: GEM object info
+ *
+ * Simply returns the fake offset to userspace so it can mmap it.
+ * The mmap call will end up in drm_gem_mmap(), which will set things
+ * up so we can get faults in the handler above.
+ *
+ * The fault handler will take care of binding the object into the GTT
+ * (since it may have been evicted to make room for something), allocating
+ * a fence register, and mapping the appropriate aperture address into
+ * userspace.
+ */
+int
+i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data,
+                       struct drm_file *file)
+{
+       struct drm_i915_gem_mmap_gtt *args = data;
+
+       if (!(dev->driver->driver_features & DRIVER_GEM))
+               return -ENODEV;
+
+       return i915_gem_mmap_gtt(file, dev, args->handle, &args->offset);
+}
+
+
 static int
 i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj,
                              gfp_t gfpmask)
 
                          uint64_t *gpu_addr);
 void radeon_gem_object_unpin(struct drm_gem_object *obj);
 
+int radeon_mode_dumb_create(struct drm_file *file_priv,
+                           struct drm_device *dev,
+                           struct drm_mode_create_dumb *args);
+int radeon_mode_dumb_mmap(struct drm_file *filp,
+                         struct drm_device *dev,
+                         uint32_t handle, uint64_t *offset_p);
+int radeon_mode_dumb_destroy(struct drm_file *file_priv,
+                            struct drm_device *dev,
+                            uint32_t handle);
 
 /*
  * GART structures, functions & helpers
 
 extern struct drm_ioctl_desc radeon_ioctls_kms[];
 extern int radeon_max_kms_ioctl;
 int radeon_mmap(struct file *filp, struct vm_area_struct *vma);
+int radeon_mode_dumb_mmap(struct drm_file *filp,
+                         struct drm_device *dev,
+                         uint32_t handle, uint64_t *offset_p);
+int radeon_mode_dumb_create(struct drm_file *file_priv,
+                           struct drm_device *dev,
+                           struct drm_mode_create_dumb *args);
+int radeon_mode_dumb_destroy(struct drm_file *file_priv,
+                            struct drm_device *dev,
+                            uint32_t handle);
+
 #if defined(CONFIG_DEBUG_FS)
 int radeon_debugfs_init(struct drm_minor *minor);
 void radeon_debugfs_cleanup(struct drm_minor *minor);
        .gem_init_object = radeon_gem_object_init,
        .gem_free_object = radeon_gem_object_free,
        .dma_ioctl = radeon_dma_ioctl_kms,
+       .dumb_create = radeon_mode_dumb_create,
+       .dumb_map_offset = radeon_mode_dumb_mmap,
+       .dumb_destroy = radeon_mode_dumb_destroy,
        .fops = {
                 .owner = THIS_MODULE,
                 .open = drm_open,
 
 };
 
 
-static int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tiled)
+int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tiled)
 {
        int aligned = width;
        int align_large = (ASIC_IS_AVIVO(rdev)) || tiled;
 
        return r;
 }
 
-int radeon_gem_mmap_ioctl(struct drm_device *dev, void *data,
-                         struct drm_file *filp)
+int radeon_mode_dumb_mmap(struct drm_file *filp,
+                         struct drm_device *dev,
+                         uint32_t handle, uint64_t *offset_p)
 {
-       struct drm_radeon_gem_mmap *args = data;
        struct drm_gem_object *gobj;
        struct radeon_bo *robj;
 
-       gobj = drm_gem_object_lookup(dev, filp, args->handle);
+       gobj = drm_gem_object_lookup(dev, filp, handle);
        if (gobj == NULL) {
                return -ENOENT;
        }
        robj = gobj->driver_private;
-       args->addr_ptr = radeon_bo_mmap_offset(robj);
+       *offset_p = radeon_bo_mmap_offset(robj);
        drm_gem_object_unreference_unlocked(gobj);
        return 0;
 }
 
+int radeon_gem_mmap_ioctl(struct drm_device *dev, void *data,
+                         struct drm_file *filp)
+{
+       struct drm_radeon_gem_mmap *args = data;
+
+       return radeon_mode_dumb_mmap(filp, dev, args->handle, &args->addr_ptr);
+}
+
 int radeon_gem_busy_ioctl(struct drm_device *dev, void *data,
                          struct drm_file *filp)
 {
        drm_gem_object_unreference_unlocked(gobj);
        return r;
 }
+
+int radeon_mode_dumb_create(struct drm_file *file_priv,
+                           struct drm_device *dev,
+                           struct drm_mode_create_dumb *args)
+{
+       struct radeon_device *rdev = dev->dev_private;
+       struct drm_gem_object *gobj;
+       int r;
+
+       args->pitch = radeon_align_pitch(rdev, args->width, args->bpp, 0) * ((args->bpp + 1) / 8);
+       args->size = args->pitch * args->height;
+       args->size = ALIGN(args->size, PAGE_SIZE);
+
+       r = radeon_gem_object_create(rdev, args->size, 0,
+                                    RADEON_GEM_DOMAIN_VRAM,
+                                    false, ttm_bo_type_device,
+                                    &gobj);
+       if (r)
+               return -ENOMEM;
+
+       r = drm_gem_handle_create(file_priv, gobj, &args->handle);
+       if (r) {
+               drm_gem_object_unreference_unlocked(gobj);
+               return r;
+       }
+       drm_gem_object_handle_unreference_unlocked(gobj);
+       return 0;
+}
+
+int radeon_mode_dumb_destroy(struct drm_file *file_priv,
+                            struct drm_device *dev,
+                            uint32_t handle)
+{
+       return drm_gem_handle_delete(file_priv, handle);
+}
 
 
 void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id);
 
+int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tiled);
 #endif
 
 #define DRM_IOCTL_MODE_PAGE_FLIP       DRM_IOWR(0xB0, struct drm_mode_crtc_page_flip)
 #define DRM_IOCTL_MODE_DIRTYFB         DRM_IOWR(0xB1, struct drm_mode_fb_dirty_cmd)
 
+#define DRM_IOCTL_MODE_CREATE_DUMB DRM_IOWR(0xB2, struct drm_mode_create_dumb)
+#define DRM_IOCTL_MODE_MAP_DUMB    DRM_IOWR(0xB3, struct drm_mode_map_dumb)
+#define DRM_IOCTL_MODE_DESTROY_DUMB    DRM_IOWR(0xB4, struct drm_mode_destroy_dumb)
+
 /**
  * Device specific ioctls should only be in their respective headers
  * The device specific ioctl range is from 0x40 to 0x99.
 
        /* vga arb irq handler */
        void (*vgaarb_irq)(struct drm_device *dev, bool state);
 
+       /* dumb alloc support */
+       int (*dumb_create)(struct drm_file *file_priv,
+                          struct drm_device *dev,
+                          struct drm_mode_create_dumb *args);
+       int (*dumb_map_offset)(struct drm_file *file_priv,
+                              struct drm_device *dev, uint32_t handle,
+                              uint64_t *offset);
+       int (*dumb_destroy)(struct drm_file *file_priv,
+                           struct drm_device *dev,
+                           uint32_t handle);
+
        /* Driver private ops for this object */
        struct vm_operations_struct *gem_vm_ops;
 
 int drm_gem_handle_create(struct drm_file *file_priv,
                          struct drm_gem_object *obj,
                          u32 *handlep);
+int drm_gem_handle_delete(struct drm_file *filp, u32 handle);
 
 static inline void
 drm_gem_object_handle_reference(struct drm_gem_object *obj)
 
 extern bool drm_edid_is_valid(struct edid *edid);
 struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev,
                                           int hsize, int vsize, int fresh);
+
+extern int drm_mode_create_dumb_ioctl(struct drm_device *dev,
+                                     void *data, struct drm_file *file_priv);
+extern int drm_mode_mmap_dumb_ioctl(struct drm_device *dev,
+                                   void *data, struct drm_file *file_priv);
+extern int drm_mode_destroy_dumb_ioctl(struct drm_device *dev,
+                                     void *data, struct drm_file *file_priv);
 #endif /* __DRM_CRTC_H__ */
 
        __u64 user_data;
 };
 
+/* create a dumb scanout buffer */
+struct drm_mode_create_dumb {
+       uint32_t height;
+       uint32_t width;
+       uint32_t bpp;
+       uint32_t flags;
+       /* handle, pitch, size will be returned */
+       uint32_t handle;
+       uint32_t pitch;
+       uint64_t size;
+};
+
+/* set up for mmap of a dumb scanout buffer */
+struct drm_mode_map_dumb {
+       /** Handle for the object being mapped. */
+       __u32 handle;
+       __u32 pad;
+       /**
+        * Fake offset to use for subsequent mmap call
+        *
+        * This is a fixed-size type for 32/64 compatibility.
+        */
+       __u64 offset;
+};
+
+struct drm_mode_destroy_dumb {
+       uint32_t handle;
+};
+
 #endif