Merge remote branch 'origin/master' into modesetting-101
authorDave Airlie <airlied@panoply-rh.(none)>
Wed, 5 Mar 2008 00:37:02 +0000 (10:37 +1000)
committerDave Airlie <airlied@panoply-rh.(none)>
Wed, 5 Mar 2008 00:37:02 +0000 (10:37 +1000)
Conflicts:

linux-core/drm_compat.c

1  2 
libdrm/xf86drm.c
linux-core/drm_agpsupport.c
linux-core/drm_bo_move.c
linux-core/drm_compat.c
linux-core/drm_compat.h
linux-core/drm_objects.h
shared-core/drm.h
shared-core/i915_dma.c
shared-core/i915_irq.c

diff --combined libdrm/xf86drm.c
@@@ -87,9 -87,6 +87,9 @@@
  
  #define DRM_MSG_VERBOSITY 3
  
 +#define DRM_NODE_CONTROL 0
 +#define DRM_NODE_RENDER 1
 +
  static drmServerInfoPtr drm_server_info;
  
  void drmSetServerInfo(drmServerInfoPtr info)
@@@ -267,7 -264,7 +267,7 @@@ static int drmMatchBusID(const char *id
   * special file node with the major and minor numbers specified by \p dev and
   * parent directory if necessary and was called by root.
   */
 -static int drmOpenDevice(long dev, int minor)
 +static int drmOpenDevice(long dev, int minor, int type)
  {
      stat_t          st;
      char            buf[64];
      uid_t           user    = DRM_DEV_UID;
      gid_t           group   = DRM_DEV_GID, serv_group;
      
 -    sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, minor);
 +    sprintf(buf, type ? DRM_DEV_NAME : DRM_CONTROL_DEV_NAME, DRM_DIR_NAME, minor);
      drmMsg("drmOpenDevice: node name is %s\n", buf);
  
      if (drm_server_info) {
   * Calls drmOpenDevice() if \p create is set, otherwise assembles the device
   * name from \p minor and opens it.
   */
 -static int drmOpenMinor(int minor, int create)
 +static int drmOpenMinor(int minor, int create, int type)
  {
      int  fd;
      char buf[64];
      
      if (create)
 -      return drmOpenDevice(makedev(DRM_MAJOR, minor), minor);
 +      return drmOpenDevice(makedev(DRM_MAJOR, minor), minor, type);
      
 -    sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, minor);
 +    sprintf(buf, type ? DRM_DEV_NAME : DRM_CONTROL_DEV_NAME, DRM_DIR_NAME, minor);
      if ((fd = open(buf, O_RDWR, 0)) >= 0)
        return fd;
      return -errno;
@@@ -382,7 -379,7 +382,7 @@@ int drmAvailable(void
      int           retval = 0;
      int           fd;
  
 -    if ((fd = drmOpenMinor(0, 1)) < 0) {
 +    if ((fd = drmOpenMinor(0, 1, DRM_NODE_RENDER)) < 0) {
  #ifdef __linux__
        /* Try proc for backward Linux compatibility */
        if (!access("/proc/dri/0", R_OK))
@@@ -423,7 -420,7 +423,7 @@@ static int drmOpenByBusid(const char *b
  
      drmMsg("drmOpenByBusid: Searching for BusID %s\n", busid);
      for (i = 0; i < DRM_MAX_MINOR; i++) {
 -      fd = drmOpenMinor(i, 1);
 +      fd = drmOpenMinor(i, 1, DRM_NODE_RENDER);
        drmMsg("drmOpenByBusid: drmOpenMinor returns %d\n", fd);
        if (fd >= 0) {
            sv.drm_di_major = 1;
@@@ -485,7 -482,7 +485,7 @@@ static int drmOpenByName(const char *na
       * already in use.  If it's in use it will have a busid assigned already.
       */
      for (i = 0; i < DRM_MAX_MINOR; i++) {
 -      if ((fd = drmOpenMinor(i, 1)) >= 0) {
 +      if ((fd = drmOpenMinor(i, 1, DRM_NODE_RENDER)) >= 0) {
            if ((version = drmGetVersion(fd))) {
                if (!strcmp(version->name, name)) {
                    drmFreeVersion(version);
                        if (*pt) { /* Found busid */
                            return drmOpenByBusid(++pt);
                        } else { /* No busid */
 -                          return drmOpenDevice(strtol(devstring, NULL, 0),i);
 +                          return drmOpenDevice(strtol(devstring, NULL, 0),i, DRM_NODE_RENDER);
                        }
                    }
                }
@@@ -579,10 -576,6 +579,10 @@@ int drmOpen(const char *name, const cha
      return -1;
  }
  
 +int drmOpenControl(int minor)
 +{
 +    return drmOpenMinor(minor, 0, DRM_NODE_CONTROL);
 +}
  
  /**
   * Free the version information returned by drmGetVersion().
@@@ -2806,23 -2799,18 +2806,18 @@@ int drmBOWaitIdle(int fd, drmBO *buf, u
      }
      return 0;
  }
-       
  int drmBOBusy(int fd, drmBO *buf, int *busy)
  {
-     if (!(buf->flags & DRM_BO_FLAG_SHAREABLE) &&
-       !(buf->replyFlags & DRM_BO_REP_BUSY)) {
-       *busy = 0;
-       return 0;
-     }
-     else {
-       int ret = drmBOInfo(fd, buf);
-       if (ret)
-           return ret;
-       *busy = (buf->replyFlags & DRM_BO_REP_BUSY);
-       return 0;
-     }
+     int ret = drmBOInfo(fd, buf);
+     if (ret)
+       return ret;
+     *busy = (buf->replyFlags & DRM_BO_REP_BUSY);
+     return 0;
  }
-     
  int drmMMInit(int fd, unsigned long pOffset, unsigned long pSize,
              unsigned memType)
  {
@@@ -2883,21 -2871,6 +2878,21 @@@ int drmMMUnlock(int fd, unsigned memTyp
      return drmIoctlTimeout(fd, DRM_IOCTL_MM_UNLOCK, &arg);
  }
  
 +int drmMMInfo(int fd, unsigned memType, uint64_t *size)
 +{
 +    struct drm_mm_info_arg arg;
 +
 +    memset(&arg, 0, sizeof(arg));
 +    
 +    arg.mem_type = memType;
 +
 +    if (ioctl(fd, DRM_IOCTL_MM_INFO, &arg))
 +      return -errno;
 +
 +    *size = arg.p_size;
 +    return 0;
 +}
 +
  int drmBOVersion(int fd, unsigned int *major,
                 unsigned int *minor,
                 unsigned int *patchlevel)
@@@ -130,7 -130,7 +130,7 @@@ EXPORT_SYMBOL(drm_agp_acquire)
  int drm_agp_acquire_ioctl(struct drm_device *dev, void *data,
                          struct drm_file *file_priv)
  {
 -      return drm_agp_acquire((struct drm_device *) file_priv->head->dev);
 +      return drm_agp_acquire((struct drm_device *) file_priv->minor->dev);
  }
  
  /**
@@@ -666,7 -666,7 +666,7 @@@ void drm_agp_chipset_flush(struct drm_d
  {
        agp_flush_chipset(dev->agp->bridge);
  }
- EXPORT_SYMBOL(drm_agp_flush_chipset);
+ EXPORT_SYMBOL(drm_agp_chipset_flush);
  #endif
  
  #endif                                /* __OS_HAS_AGP */
diff --combined linux-core/drm_bo_move.c
@@@ -147,7 -147,6 +147,7 @@@ void drm_mem_reg_iounmap(struct drm_dev
        if (virtual && (man->flags & _DRM_FLAG_NEEDS_IOREMAP))
                iounmap(virtual);
  }
 +EXPORT_SYMBOL(drm_mem_reg_iounmap);
  
  static int drm_copy_io_page(void *dst, void *src, unsigned long page)
  {
@@@ -596,3 -595,36 +596,36 @@@ void drm_bo_kunmap(struct drm_bo_kmap_o
        map->page = NULL;
  }
  EXPORT_SYMBOL(drm_bo_kunmap);
+ int drm_bo_pfn_prot(struct drm_buffer_object *bo,
+                   unsigned long dst_offset,
+                   unsigned long *pfn,
+                   pgprot_t *prot)
+ {
+       struct drm_bo_mem_reg *mem = &bo->mem;
+       struct drm_device *dev = bo->dev;
+       unsigned long bus_offset;
+       unsigned long bus_size;
+       unsigned long bus_base;
+       struct drm_mem_type_manager *man = &dev->bm.man[mem->mem_type];
+       int ret;
+       ret = drm_bo_pci_offset(dev, mem, &bus_base, &bus_offset,
+                               &bus_size);
+       if (ret)
+               return -EINVAL;
+       if (bus_size != 0)
+               *pfn = (bus_base + bus_offset + dst_offset) >> PAGE_SHIFT;
+       else if (!bo->ttm)
+               return -EINVAL;
+       else
+               *pfn = page_to_pfn(drm_ttm_get_page(bo->ttm, dst_offset >> PAGE_SHIFT));
+       *prot = (mem->flags & DRM_BO_FLAG_CACHED) ?
+               PAGE_KERNEL : drm_kernel_io_prot(man->drm_bus_maptype);
+       return 0;
+ }
+ EXPORT_SYMBOL(drm_bo_pfn_prot);
diff --combined linux-core/drm_compat.c
@@@ -730,52 -730,33 +730,81 @@@ void *idr_replace(struct idr *idp, voi
  EXPORT_SYMBOL(idr_replace);
  #endif
  
 -#endif
 -
 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
 +static __inline__ unsigned long __round_jiffies(unsigned long j, int cpu)
 +{
 +      int rem;
 +      unsigned long original = j;
 +
 +      j += cpu * 3;
 +
 +      rem = j % HZ;
 +
 +      if (rem < HZ/4) /* round down */
 +              j = j - rem;
 +      else /* round up */
 +              j = j - rem + HZ;
 +
 +      /* now that we have rounded, subtract the extra skew again */
 +      j -= cpu * 3;
 +
 +      if (j <= jiffies) /* rounding ate our timeout entirely; */
 +              return original;
 +      return j;
 +}
 +
 +static __inline__ unsigned long __round_jiffies_relative(unsigned long j, int cpu)
 +{
 +      return  __round_jiffies(j + jiffies, cpu) - jiffies;
 +}
 +
 +unsigned long round_jiffies_relative(unsigned long j)
 +{
 +      return __round_jiffies_relative(j, raw_smp_processor_id());
 +}
 +EXPORT_SYMBOL(round_jiffies_relative);
 +#endif
 +
 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
 +struct pci_dev * pci_get_bus_and_slot(unsigned int bus, unsigned int devfn)
 +{
 +    struct pci_dev *dev = NULL;
 +
 +    while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
 +        if (pci_domain_nr(dev->bus) == 0 &&
 +           (dev->bus->number == bus && dev->devfn == devfn))
 +            return dev;
 +   }
 +   return NULL;
 +}
 +EXPORT_SYMBOL(pci_get_bus_and_slot);
 +#endif
++
+ #if defined(DRM_KMAP_ATOMIC_PROT_PFN) && defined(CONFIG_HIMEM)
+ #define drm_kmap_get_fixmap_pte(vaddr)                                        \
+       pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), vaddr), (vaddr)), (vaddr))
+ void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type,
+                          pgprot_t protection)
+ {
+       enum fixed_addresses idx;
+       unsigned long vaddr;
+       static pte_t *km_pte;
+       static int initialized = 0;
+       if (unlikely(!initialized)) {
+               km_pte = drm_kmap_get_fixmap_pte(__fix_to_virt(FIX_KMAP_BEGIN));
+               initialized = 1;
+       }
+       pagefault_disable();
+       idx = type + KM_TYPE_NR*smp_processor_id();
+       vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
+       set_pte(km_pte-idx, pfn_pte(pfn, protection));
+       return (void*) vaddr;
+ }
+ EXPORT_SYMBOL(kmap_atomic_prot_pfn);
diff --combined linux-core/drm_compat.h
  #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
  #undef DRM_IRQ_ARGS
  #define DRM_IRQ_ARGS          int irq, void *arg, struct pt_regs *regs
 +
 +typedef _Bool bool;
 +enum {
 +        false   = 0,
 +        true    = 1
 +};
 +
  #endif
  
  #ifndef list_for_each_safe
@@@ -159,7 -152,7 +159,7 @@@ static __inline__ void *kcalloc(size_t 
  
  #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
  #define vmalloc_user(_size) ({void * tmp = vmalloc(_size);   \
 -      if (tmp) memset(tmp, 0, size);                       \
 +      if (tmp) memset(tmp, 0, _size);                      \
        (tmp);})
  #endif
  
@@@ -332,15 -325,12 +332,20 @@@ void *idr_replace(struct idr *idp, voi
  #endif
  
  #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
 -typedef _Bool                   bool;
 +extern unsigned long round_jiffies_relative(unsigned long j);
 +#endif
 +
 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
 +extern struct pci_dev * pci_get_bus_and_slot(unsigned int bus, unsigned int devfn);
 +#endif
 +
 +#ifndef PM_EVENT_PRETHAW 
 +#define PM_EVENT_PRETHAW 3
  #endif
  
+ #if (defined(CONFIG_X86) && defined(CONFIG_X86_32) && defined(CONFIG_HIMEM))
+ #define DRM_KMAP_ATOMIC_PROT_PFN
+ extern void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type,
+                                 pgprot_t protection);
+ #endif
  #endif
diff --combined linux-core/drm_objects.h
@@@ -156,6 -156,7 +156,6 @@@ struct drm_fence_object 
  };
  
  #define _DRM_FENCE_CLASSES 8
 -#define _DRM_FENCE_TYPE_EXE 0x00
  
  struct drm_fence_class_manager {
        struct list_head ring;
@@@ -383,7 -384,7 +383,7 @@@ extern int drm_ttm_destroy(struct drm_t
   * The array of page pointers was allocated with vmalloc
   * instead of drm_calloc.
   */
- #define DRM_TTM_PAGE_VMALLOC    (1 << 4)
+ #define DRM_TTM_PAGEDIR_VMALLOC (1 << 4)
  /*
   * This ttm is mapped from user space
   */
@@@ -515,7 -516,6 +515,7 @@@ struct drm_buffer_object 
  struct drm_mem_type_manager {
        int has_type;
        int use_type;
 +      int kern_init_type;
        struct drm_mm manager;
        struct list_head lru;
        struct list_head pinned;
        unsigned long io_offset;
        unsigned long io_size;
        void *io_addr;
 +      uint64_t size; /* size of managed area for reporting to userspace */
  };
  
  struct drm_bo_lock {
@@@ -638,12 -637,12 +638,12 @@@ struct drm_bo_driver 
  /*
   * buffer objects (drm_bo.c)
   */
 -
  extern int drm_bo_create_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv);
  extern int drm_bo_destroy_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv);
  extern int drm_bo_map_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv);
  extern int drm_bo_unmap_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv);
  extern int drm_bo_reference_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv);
 +extern int drm_bo_set_pin(struct drm_device *dev, struct drm_buffer_object *bo, int pin);
  extern int drm_bo_unreference_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv);
  extern int drm_bo_wait_idle_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv);
  extern int drm_bo_info_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv);
@@@ -652,7 -651,6 +652,7 @@@ extern int drm_mm_init_ioctl(struct drm
  extern int drm_mm_takedown_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv);
  extern int drm_mm_lock_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv);
  extern int drm_mm_unlock_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv);
 +extern int drm_mm_info_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv);
  extern int drm_bo_version_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv);
  extern int drm_bo_driver_finish(struct drm_device *dev);
  extern int drm_bo_driver_init(struct drm_device *dev);
@@@ -684,10 -682,9 +684,10 @@@ extern int drm_bo_mem_space(struct drm_
  extern int drm_bo_move_buffer(struct drm_buffer_object *bo,
                              uint64_t new_mem_flags,
                              int no_wait, int move_unfenced);
 -extern int drm_bo_clean_mm(struct drm_device *dev, unsigned mem_type);
 +extern int drm_bo_clean_mm(struct drm_device *dev, unsigned mem_type, int kern_clean);
  extern int drm_bo_init_mm(struct drm_device *dev, unsigned type,
 -                        unsigned long p_offset, unsigned long p_size);
 +                        unsigned long p_offset, unsigned long p_size,
 +                        int kern_init);
  extern int drm_bo_handle_validate(struct drm_file *file_priv, uint32_t handle,
                                  uint64_t flags, uint64_t mask, uint32_t hint,
                                  uint32_t fence_class, int use_old_fence_class,
@@@ -741,6 -738,10 +741,10 @@@ static inline void *drm_bmo_virtual(str
  extern void drm_bo_kunmap(struct drm_bo_kmap_obj *map);
  extern int drm_bo_kmap(struct drm_buffer_object *bo, unsigned long start_page,
                       unsigned long num_pages, struct drm_bo_kmap_obj *map);
+ extern int drm_bo_pfn_prot(struct drm_buffer_object *bo,
+                          unsigned long dst_offset,
+                          unsigned long *pfn,
+                          pgprot_t *prot);
  
  
  /*
@@@ -781,10 -782,6 +785,10 @@@ extern void drm_regs_init(struct drm_re
                                              const void *),
                          void (*reg_destroy)(struct drm_reg *));
  
 +extern int drm_mem_reg_ioremap(struct drm_device *dev, struct drm_bo_mem_reg * mem,
 +                             void **virtual);
 +extern void drm_mem_reg_iounmap(struct drm_device *dev, struct drm_bo_mem_reg * mem,
 +                              void *virtual);
  /*
   * drm_bo_lock.c
   * Simple replacement for the hardware lock on buffer manager init and clean.
diff --combined shared-core/drm.h
@@@ -645,8 -645,14 +645,14 @@@ struct drm_set_version 
  
  #define DRM_FENCE_FLAG_EMIT                0x00000001
  #define DRM_FENCE_FLAG_SHAREABLE           0x00000002
+ /**
+  * On hardware with no interrupt events for operation completion,
+  * indicates that the kernel should sleep while waiting for any blocking
+  * operation to complete rather than spinning.
+  *
+  * Has no effect otherwise.
+  */
  #define DRM_FENCE_FLAG_WAIT_LAZY           0x00000004
- #define DRM_FENCE_FLAG_WAIT_IGNORE_SIGNALS 0x00000008
  #define DRM_FENCE_FLAG_NO_USER             0x00000010
  
  /* Reserved for driver use */
@@@ -795,13 -801,12 +801,12 @@@ struct drm_fence_arg 
   * with it as a result of this operation
   */
  #define DRM_BO_HINT_DONT_FENCE  0x00000004
- /*
-  * Sleep while waiting for the operation to complete.
-  * Without this flag, the kernel will, instead, spin
-  * until this operation has completed. I'm not sure
-  * why you would ever want this, so please always
-  * provide DRM_BO_HINT_WAIT_LAZY to any operation
-  * which may block
+ /**
+  * On hardware with no interrupt events for operation completion,
+  * indicates that the kernel should sleep while waiting for any blocking
+  * operation to complete rather than spinning.
+  *
+  * Has no effect otherwise.
   */
  #define DRM_BO_HINT_WAIT_LAZY   0x00000008
  /*
@@@ -950,180 -955,6 +955,180 @@@ struct drm_mm_init_arg 
        uint64_t p_size;
  };
  
 +struct drm_mm_info_arg {
 +      unsigned int mem_type;
 +      uint64_t p_size;
 +};
 +
 +
 +/*
 + * Drm mode setting
 + */
 +#define DRM_DISPLAY_INFO_LEN 32
 +#define DRM_OUTPUT_NAME_LEN 32
 +#define DRM_DISPLAY_MODE_LEN 32
 +#define DRM_PROP_NAME_LEN 32
 +
 +#define DRM_MODE_TYPE_BUILTIN (1<<0)
 +#define DRM_MODE_TYPE_CLOCK_C ((1<<1) | DRM_MODE_TYPE_BUILTIN)
 +#define DRM_MODE_TYPE_CRTC_C  ((1<<2) | DRM_MODE_TYPE_BUILTIN)
 +#define DRM_MODE_TYPE_PREFERRED       (1<<3)
 +#define DRM_MODE_TYPE_DEFAULT (1<<4)
 +#define DRM_MODE_TYPE_USERDEF (1<<5)
 +#define DRM_MODE_TYPE_DRIVER  (1<<6)
 +
 +struct drm_mode_modeinfo {
 +      unsigned int clock;
 +      unsigned short hdisplay, hsync_start, hsync_end, htotal, hskew;
 +      unsigned short vdisplay, vsync_start, vsync_end, vtotal, vscan;
 +
 +      unsigned int vrefresh; /* vertical refresh * 1000 */
 +
 +      unsigned int flags;
 +      unsigned int type;
 +      char name[DRM_DISPLAY_MODE_LEN];
 +};
 +
 +struct drm_mode_card_res {
 +      uint64_t fb_id_ptr;
 +      uint64_t crtc_id_ptr;
 +      uint64_t output_id_ptr;
 +      int count_fbs;
 +      int count_crtcs;
 +      int count_outputs;
 +      int min_width, max_width;
 +      int min_height, max_height;
 +};
 +
 +struct drm_mode_crtc {
 +      uint64_t set_outputs_ptr;
 +
 +      unsigned int crtc_id; /**< Id */
 +      unsigned int fb_id; /**< Id of framebuffer */
 +
 +      int x, y; /**< Position on the frameuffer */
 +
 +      int count_outputs;
 +      unsigned int outputs; /**< Outputs that are connected */
 +
 +      int count_possibles;
 +      unsigned int possibles; /**< Outputs that can be connected */
 +      int gamma_size;
 +      int mode_valid;
 +      struct drm_mode_modeinfo mode;
 +};
 +
 +#define DRM_MODE_OUTPUT_NONE 0
 +#define DRM_MODE_OUTPUT_DAC  1
 +#define DRM_MODE_OUTPUT_TMDS 2
 +#define DRM_MODE_OUTPUT_LVDS 3
 +#define DRM_MODE_OUTPUT_TVDAC 4
 +
 +struct drm_mode_get_output {
 +
 +      uint64_t modes_ptr;
 +      uint64_t props_ptr;
 +      uint64_t prop_values_ptr;
 +
 +      int count_modes;
 +      int count_props;
 +      unsigned int output; /**< Id */
 +      unsigned int crtc; /**< Id of crtc */
 +      unsigned int output_type;
 +      unsigned int output_type_id;
 +
 +      unsigned int connection;
 +      unsigned int mm_width, mm_height; /**< HxW in millimeters */
 +      unsigned int subpixel;
 +      int count_crtcs;
 +      int count_clones;
 +      unsigned int crtcs; /**< possible crtc to connect to */
 +      unsigned int clones; /**< list of clones */
 +};
 +
 +#define DRM_MODE_PROP_PENDING (1<<0)
 +#define DRM_MODE_PROP_RANGE (1<<1)
 +#define DRM_MODE_PROP_IMMUTABLE (1<<2)
 +#define DRM_MODE_PROP_ENUM (1<<3) // enumerated type with text strings
 +#define DRM_MODE_PROP_BLOB (1<<4)
 +
 +struct drm_mode_property_enum {
 +      uint64_t value;
 +      unsigned char name[DRM_PROP_NAME_LEN];
 +};
 +
 +struct drm_mode_get_property {
 +      uint64_t values_ptr; /* values and blob lengths */
 +      uint64_t enum_blob_ptr; /* enum and blob id ptrs */
 +
 +      unsigned int prop_id;
 +      unsigned int flags;
 +      unsigned char name[DRM_PROP_NAME_LEN];
 +
 +      int count_values;
 +      int count_enum_blobs;
 +};
 +
 +struct drm_mode_output_set_property {
 +      uint64_t value;
 +      unsigned int prop_id;
 +      unsigned int output_id;
 +};
 +
 +struct drm_mode_get_blob {
 +      uint32_t blob_id;
 +      uint32_t length;
 +      uint64_t data;
 +};
 +
 +struct drm_mode_fb_cmd {
 +        unsigned int buffer_id;
 +        unsigned int width, height;
 +        unsigned int pitch;
 +        unsigned int bpp;
 +        unsigned int handle;
 +      unsigned int depth;
 +};
 +
 +struct drm_mode_mode_cmd {
 +      unsigned int output_id;
 +      struct drm_mode_modeinfo mode;
 +};
 +
 +#define DRM_MODE_CURSOR_BO   0x01
 +#define DRM_MODE_CURSOR_MOVE 0x02
 +
 +/*
 + * depending on the value in flags diffrent members are used.
 + *
 + * CURSOR_BO uses
 + *    crtc
 + *    width
 + *    height
 + *    handle - if 0 turns the cursor of
 + *
 + * CURSOR_MOVE uses
 + *    crtc
 + *    x
 + *    y
 + */
 +struct drm_mode_cursor {
 +      unsigned int flags;
 +      unsigned int crtc;
 +      int x;
 +      int y;
 +      uint32_t width;
 +      uint32_t height;
 +      unsigned int handle;
 +};
 +
 +/*
 + * oh so ugly hotplug
 + */
 +struct drm_mode_hotplug {
 +      uint32_t counter;
 +};
 +
  /**
   * \name Ioctls Definitions
   */
  #define DRM_IOCTL_BO_INFO               DRM_IOWR(0xd4, struct drm_bo_reference_info_arg)
  #define DRM_IOCTL_BO_WAIT_IDLE          DRM_IOWR(0xd5, struct drm_bo_map_wait_idle_arg)
  #define DRM_IOCTL_BO_VERSION          DRM_IOR(0xd6, struct drm_bo_version_arg)
 +#define DRM_IOCTL_MM_INFO               DRM_IOWR(0xd7, struct drm_mm_info_arg)
 +
 +#define DRM_IOCTL_MODE_GETRESOURCES     DRM_IOWR(0xA0, struct drm_mode_card_res)
 +#define DRM_IOCTL_MODE_GETCRTC          DRM_IOWR(0xA1, struct drm_mode_crtc)
 +#define DRM_IOCTL_MODE_GETOUTPUT        DRM_IOWR(0xA2, struct drm_mode_get_output)
 +#define DRM_IOCTL_MODE_SETCRTC          DRM_IOWR(0xA3, struct drm_mode_crtc)
 +#define DRM_IOCTL_MODE_ADDFB            DRM_IOWR(0xA4, struct drm_mode_fb_cmd)
 +#define DRM_IOCTL_MODE_RMFB             DRM_IOWR(0xA5, unsigned int)
 +#define DRM_IOCTL_MODE_GETFB            DRM_IOWR(0xA6, struct drm_mode_fb_cmd)
 +
 +#define DRM_IOCTL_MODE_SETPROPERTY     DRM_IOWR(0xA7, struct drm_mode_output_set_property)
 +#define DRM_IOCTL_MODE_GETPROPBLOB     DRM_IOWR(0xA8, struct drm_mode_get_blob)
 +#define DRM_IOCTL_MODE_ATTACHMODE      DRM_IOWR(0xA9, struct drm_mode_mode_cmd)
 +#define DRM_IOCTL_MODE_DETACHMODE      DRM_IOWR(0xAA, struct drm_mode_mode_cmd)
 +
 +#define DRM_IOCTL_MODE_GETPROPERTY     DRM_IOWR(0xAB, struct drm_mode_get_property)
 +#define DRM_IOCTL_MODE_CURSOR          DRM_IOWR(0xAC, struct drm_mode_cursor)
 +#define DRM_IOCTL_MODE_HOTPLUG         DRM_IOWR(0xAD, struct drm_mode_hotplug)
  
  /*@}*/
  
diff --combined shared-core/i915_dma.c
@@@ -38,8 -38,8 +38,8 @@@
   */
  int i915_wait_ring(struct drm_device * dev, int n, const char *caller)
  {
 -      drm_i915_private_t *dev_priv = dev->dev_private;
 -      drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      struct drm_i915_ring_buffer *ring = &(dev_priv->ring);
        u32 last_head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
        int i;
  
  
  void i915_kernel_lost_context(struct drm_device * dev)
  {
 -      drm_i915_private_t *dev_priv = dev->dev_private;
 -      drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      struct drm_i915_ring_buffer *ring = &(dev_priv->ring);
 +
 +      /* we should never lose context on the ring with modesetting 
 +       * as we don't expose it to userspace */
 +      if (drm_core_check_feature(dev, DRIVER_MODESET))
 +              return;
  
        ring->head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
        ring->tail = I915_READ(LP_RING + RING_TAIL) & TAIL_ADDR;
                ring->space += ring->Size;
  }
  
 -static int i915_dma_cleanup(struct drm_device * dev)
 +int i915_dma_cleanup(struct drm_device * dev)
  {
 -      drm_i915_private_t *dev_priv = dev->dev_private;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +
 +      if (drm_core_check_feature(dev, DRIVER_MODESET))
 +              return 0;
 +
        /* Make sure interrupts are disabled here because the uninstall ioctl
         * may not have been called from userspace and after dev_private
         * is freed, it's too late.
        if (dev->irq)
                drm_irq_uninstall(dev);
  
 -      if (dev_priv->ring.virtual_start) {
 -              drm_core_ioremapfree(&dev_priv->ring.map, dev);
 -              dev_priv->ring.virtual_start = 0;
 -              dev_priv->ring.map.handle = 0;
 -              dev_priv->ring.map.size = 0;
 -      }
 +        if (dev_priv->ring.virtual_start) {
 +                drm_core_ioremapfree(&dev_priv->ring.map, dev);
 +                dev_priv->ring.virtual_start = 0;
 +                dev_priv->ring.map.handle = 0;
 +                dev_priv->ring.map.size = 0;
 +              dev_priv->ring.Size = 0;
 +        }
  
 -      if (dev_priv->status_page_dmah) {
 -              drm_pci_free(dev, dev_priv->status_page_dmah);
 -              dev_priv->status_page_dmah = NULL;
 -              /* Need to rewrite hardware status page */
 -              I915_WRITE(0x02080, 0x1ffff000);
 -      }
 +        if (dev_priv->status_page_dmah) {
 +                drm_pci_free(dev, dev_priv->status_page_dmah);
 +                dev_priv->status_page_dmah = NULL;
 +                /* Need to rewrite hardware status page */
 +                I915_WRITE(0x02080, 0x1ffff000);
 +        }
 +
 +        if (dev_priv->status_gfx_addr) {
 +                dev_priv->status_gfx_addr = 0;
 +                drm_core_ioremapfree(&dev_priv->hws_map, dev);
 +                I915_WRITE(0x02080, 0x1ffff000);
 +        }
  
 -      if (dev_priv->status_gfx_addr) {
 -              dev_priv->status_gfx_addr = 0;
 -              drm_core_ioremapfree(&dev_priv->hws_map, dev);
 -              I915_WRITE(0x02080, 0x1ffff000);
 -      }
  
        return 0;
  }
@@@ -133,7 -122,7 +133,7 @@@ setup_dri2_sarea(struct drm_device * de
                 struct drm_file *file_priv,
                 drm_i915_init_t * init)
  {
 -      drm_i915_private_t *dev_priv = dev->dev_private;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
        int ret;
        unsigned int *p, *end, *next;
  
        while (p < end && DRI2_SAREA_BLOCK_TYPE(*p) != DRI2_SAREA_BLOCK_END) {
                switch (DRI2_SAREA_BLOCK_TYPE(*p)) {
                case DRI2_SAREA_BLOCK_LOCK:
 -                      dev->lock.hw_lock = (void *) (p + 1);
 -                      dev->sigdata.lock = dev->lock.hw_lock;
 +                      dev->primary->master->lock.hw_lock = (void *) (p + 1);
 +                      dev->sigdata.lock = dev->primary->master->lock.hw_lock;
                        break;
                }
                next = DRI2_SAREA_BLOCK_NEXT(p);
@@@ -182,50 -171,63 +182,50 @@@ static int i915_initialize(struct drm_d
                           struct drm_file *file_priv,
                           drm_i915_init_t * init)
  {
 -      drm_i915_private_t *dev_priv = dev->dev_private;
 -      int ret;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
  
 -      dev_priv->sarea = drm_getsarea(dev);
 -      if (!dev_priv->sarea) {
 -              DRM_ERROR("can not find sarea!\n");
 -              i915_dma_cleanup(dev);
 -              return -EINVAL;
 +      if (!drm_core_check_feature(dev, DRIVER_MODESET)) {
 +              if (init->mmio_offset != 0)
 +                      dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset);
 +              if (!dev_priv->mmio_map) {
 +                      i915_dma_cleanup(dev);
 +                      DRM_ERROR("can not find mmio map!\n");
 +                      return -EINVAL;
 +              }
        }
  
 -      if (init->mmio_offset != 0)
 -              dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset);
 -      if (!dev_priv->mmio_map) {
 -              i915_dma_cleanup(dev);
 -              DRM_ERROR("can not find mmio map!\n");
 -              return -EINVAL;
 -      }
  
  #ifdef I915_HAVE_BUFFER
        dev_priv->max_validate_buffers = I915_MAX_VALIDATE_BUFFERS;
  #endif
  
 -      if (init->sarea_priv_offset)
 -              dev_priv->sarea_priv = (drm_i915_sarea_t *)
 -                      ((u8 *) dev_priv->sarea->handle +
 -                       init->sarea_priv_offset);
 -      else {
 -              /* No sarea_priv for you! */
 -              dev_priv->sarea_priv = NULL;
 -      }
 -
 -      dev_priv->ring.Start = init->ring_start;
 -      dev_priv->ring.End = init->ring_end;
 -      dev_priv->ring.Size = init->ring_size;
 -      dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
 -
 -      dev_priv->ring.map.offset = init->ring_start;
 -      dev_priv->ring.map.size = init->ring_size;
 -      dev_priv->ring.map.type = 0;
 -      dev_priv->ring.map.flags = 0;
 -      dev_priv->ring.map.mtrr = 0;
 -
 -      drm_core_ioremap(&dev_priv->ring.map, dev);
 -
 -      if (dev_priv->ring.map.handle == NULL) {
 -              i915_dma_cleanup(dev);
 -              DRM_ERROR("can not ioremap virtual address for"
 -                        " ring buffer\n");
 -              return -ENOMEM;
 +      if (!dev_priv->ring.Size) {
 +              dev_priv->ring.Start = init->ring_start;
 +              dev_priv->ring.End = init->ring_end;
 +              dev_priv->ring.Size = init->ring_size;
 +              dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
 +              
 +              dev_priv->ring.map.offset = init->ring_start;
 +              dev_priv->ring.map.size = init->ring_size;
 +              dev_priv->ring.map.type = 0;
 +              dev_priv->ring.map.flags = 0;
 +              dev_priv->ring.map.mtrr = 0;
 +              
 +              drm_core_ioremap(&dev_priv->ring.map, dev);
 +              
 +              if (dev_priv->ring.map.handle == NULL) {
 +                      i915_dma_cleanup(dev);
 +                      DRM_ERROR("can not ioremap virtual address for"
 +                                " ring buffer\n");
 +                      return -ENOMEM;
 +              }
 +              dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
        }
  
 -      dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
  
        dev_priv->cpp = init->cpp;
 -
 -      if (dev_priv->sarea_priv)
 -              dev_priv->sarea_priv->pf_current_page = 0;
 +      master_priv->sarea_priv->pf_current_page = 0;
  
        /* We are using separate values as placeholders for mechanisms for
         * private backbuffer/depthbuffer usage.
  #endif
  
        if (init->func == I915_INIT_DMA2) {
 -              ret = setup_dri2_sarea(dev, file_priv, init);
 +              int ret = setup_dri2_sarea(dev, file_priv, init);
                if (ret) {
                        i915_dma_cleanup(dev);
                        DRM_ERROR("could not set up dri2 sarea\n");
                        return ret;
                }
        }
 -              
  
        return 0;
  }
  
  static int i915_dma_resume(struct drm_device * dev)
  {
 -      drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 +      struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
  
        DRM_DEBUG("\n");
  
 -      if (!dev_priv->sarea) {
 -              DRM_ERROR("can not find sarea!\n");
 -              return -EINVAL;
 -      }
 +      if (drm_core_check_feature(dev, DRIVER_MODESET))
 +              return 0;
  
        if (!dev_priv->mmio_map) {
                DRM_ERROR("can not find mmio map!\n");
  static int i915_dma_init(struct drm_device *dev, void *data,
                         struct drm_file *file_priv)
  {
 -      drm_i915_init_t *init = data;
 +      struct drm_i915_init *init = data;
        int retcode = 0;
  
        switch (init->func) {
@@@ -416,7 -421,7 +416,7 @@@ static int validate_cmd(int cmd
  static int i915_emit_cmds(struct drm_device *dev, int __user *buffer,
                          int dwords)
  {
 -      drm_i915_private_t *dev_priv = dev->dev_private;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
        int i;
        RING_LOCALS;
  
@@@ -457,7 -462,7 +457,7 @@@ static int i915_emit_box(struct drm_dev
                         struct drm_clip_rect __user * boxes,
                         int i, int DR1, int DR4)
  {
 -      drm_i915_private_t *dev_priv = dev->dev_private;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_clip_rect box;
        RING_LOCALS;
  
  
  void i915_emit_breadcrumb(struct drm_device *dev)
  {
 -      drm_i915_private_t *dev_priv = dev->dev_private;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
        RING_LOCALS;
  
        if (++dev_priv->counter > BREADCRUMB_MASK) {
                 DRM_DEBUG("Breadcrumb counter wrapped around\n");
        }
  
 -      if (dev_priv->sarea_priv)
 -              dev_priv->sarea_priv->last_enqueue = dev_priv->counter;
 +      master_priv->sarea_priv->last_enqueue = dev_priv->counter;
  
        BEGIN_LP_RING(4);
        OUT_RING(CMD_STORE_DWORD_IDX);
  
  int i915_emit_mi_flush(struct drm_device *dev, uint32_t flush)
  {
 -      drm_i915_private_t *dev_priv = dev->dev_private;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
        uint32_t flush_cmd = CMD_MI_FLUSH;
        RING_LOCALS;
  
  
  
  static int i915_dispatch_cmdbuffer(struct drm_device * dev,
 -                                 drm_i915_cmdbuffer_t * cmd)
 +                                 struct drm_i915_cmdbuffer * cmd)
  {
  #ifdef I915_HAVE_FENCE
 -      drm_i915_private_t *dev_priv = dev->dev_private;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
  #endif
        int nbox = cmd->num_cliprects;
        int i = 0, count, ret;
  static int i915_dispatch_batchbuffer(struct drm_device * dev,
                                     drm_i915_batchbuffer_t * batch)
  {
 -      drm_i915_private_t *dev_priv = dev->dev_private;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_clip_rect __user *boxes = batch->cliprects;
        int nbox = batch->num_cliprects;
        int i = 0, count;
  
  static void i915_do_dispatch_flip(struct drm_device * dev, int plane, int sync)
  {
 -      drm_i915_private_t *dev_priv = dev->dev_private;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
        u32 num_pages, current_page, next_page, dspbase;
        int shift = 2 * plane, x, y;
        RING_LOCALS;
  
        /* Calculate display base offset */
 -      num_pages = dev_priv->sarea_priv->third_handle ? 3 : 2;
 -      current_page = (dev_priv->sarea_priv->pf_current_page >> shift) & 0x3;
 +      num_pages = master_priv->sarea_priv->third_handle ? 3 : 2;
 +      current_page = (master_priv->sarea_priv->pf_current_page >> shift) & 0x3;
        next_page = (current_page + 1) % num_pages;
  
        switch (next_page) {
        default:
        case 0:
 -              dspbase = dev_priv->sarea_priv->front_offset;
 +              dspbase = master_priv->sarea_priv->front_offset;
                break;
        case 1:
 -              dspbase = dev_priv->sarea_priv->back_offset;
 +              dspbase = master_priv->sarea_priv->back_offset;
                break;
        case 2:
 -              dspbase = dev_priv->sarea_priv->third_offset;
 +              dspbase = master_priv->sarea_priv->third_offset;
                break;
        }
  
        if (plane == 0) {
 -              x = dev_priv->sarea_priv->planeA_x;
 -              y = dev_priv->sarea_priv->planeA_y;
 +              x = master_priv->sarea_priv->planeA_x;
 +              y = master_priv->sarea_priv->planeA_y;
        } else {
 -              x = dev_priv->sarea_priv->planeB_x;
 -              y = dev_priv->sarea_priv->planeB_y;
 +              x = master_priv->sarea_priv->planeB_x;
 +              y = master_priv->sarea_priv->planeB_y;
        }
  
 -      dspbase += (y * dev_priv->sarea_priv->pitch + x) * dev_priv->cpp;
 +      dspbase += (y * master_priv->sarea_priv->pitch + x) * dev_priv->cpp;
  
        DRM_DEBUG("plane=%d current_page=%d dspbase=0x%x\n", plane, current_page,
                  dspbase);
                                       MI_WAIT_FOR_PLANE_A_FLIP)));
        OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | (sync ? 0 : ASYNC_FLIP) |
                 (plane ? DISPLAY_PLANE_B : DISPLAY_PLANE_A));
 -      OUT_RING(dev_priv->sarea_priv->pitch * dev_priv->cpp);
 +      OUT_RING(master_priv->sarea_priv->pitch * dev_priv->cpp);
        OUT_RING(dspbase);
        ADVANCE_LP_RING();
  
 -      dev_priv->sarea_priv->pf_current_page &= ~(0x3 << shift);
 -      dev_priv->sarea_priv->pf_current_page |= next_page << shift;
 +      master_priv->sarea_priv->pf_current_page &= ~(0x3 << shift);
 +      master_priv->sarea_priv->pf_current_page |= next_page << shift;
  }
  
  void i915_dispatch_flip(struct drm_device * dev, int planes, int sync)
  {
 -      drm_i915_private_t *dev_priv = dev->dev_private;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
        int i;
  
        DRM_DEBUG("planes=0x%x pfCurrentPage=%d\n",
 -                planes, dev_priv->sarea_priv->pf_current_page);
 +                planes, master_priv->sarea_priv->pf_current_page);
  
        i915_emit_mi_flush(dev, MI_READ_FLUSH | MI_EXE_FLUSH);
  
  
  static int i915_quiescent(struct drm_device *dev)
  {
 -      drm_i915_private_t *dev_priv = dev->dev_private;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
  
        i915_kernel_lost_context(dev);
        return i915_wait_ring(dev, dev_priv->ring.Size - 8, __FUNCTION__);
@@@ -728,10 -731,9 +728,10 @@@ static int i915_flush_ioctl(struct drm_
  static int i915_batchbuffer(struct drm_device *dev, void *data,
                            struct drm_file *file_priv)
  {
 -      drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 +      struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
 +      struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
        drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
 -          dev_priv->sarea_priv;
 +          master_priv->sarea_priv;
        drm_i915_batchbuffer_t *batch = data;
        int ret;
  
  static int i915_cmdbuffer(struct drm_device *dev, void *data,
                          struct drm_file *file_priv)
  {
 -      drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 -      drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
 -          dev_priv->sarea_priv;
 -      drm_i915_cmdbuffer_t *cmdbuf = data;
 +      struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
 +      struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
 +      struct drm_i915_sarea *sarea_priv = (struct drm_i915_sarea *)
 +              master_priv->sarea_priv;
 +      struct drm_i915_cmdbuffer *cmdbuf = data;
        int ret;
  
        DRM_DEBUG("i915 cmdbuffer, buf %p sz %d cliprects %d\n",
@@@ -804,6 -805,7 +804,7 @@@ struct i915_relocatee_info 
        unsigned page_offset;
        struct drm_bo_kmap_obj kmap;
        int is_iomem;
+       int idle;
  };
  
  struct drm_i915_validate_buffer {
@@@ -859,6 -861,14 +860,14 @@@ int i915_apply_reloc(struct drm_file *f
                drm_bo_kunmap(&relocatee->kmap);
                relocatee->data_page = NULL;
                relocatee->offset = new_cmd_offset;
+               
+               if (unlikely(!relocatee->idle)) {
+                       ret = drm_bo_wait(relocatee->buf, 0, 0, 0);
+                       if (ret)
+                               return ret;
+                       relocatee->idle = 1;
+               }
                ret = drm_bo_kmap(relocatee->buf, new_cmd_offset >> PAGE_SHIFT,
                                  1, &relocatee->kmap);
                if (ret) {
@@@ -971,7 -981,7 +980,7 @@@ static int i915_exec_reloc(struct drm_f
                           struct drm_i915_validate_buffer *buffers,
                           uint32_t buf_count)
  {
 -      struct drm_device *dev = file_priv->head->dev;
 +      struct drm_device *dev = file_priv->minor->dev;
        struct i915_relocatee_info relocatee;
        int ret = 0;
        int b;
        }
  
        mutex_lock (&relocatee.buf->mutex);
-       ret = drm_bo_wait (relocatee.buf, 0, 0, FALSE);
-       if (ret)
-               goto out_err1;
        while (reloc_user_ptr) {
                ret = i915_process_relocs(file_priv, buf_handle, &reloc_user_ptr, &relocatee, buffers, buf_count);
                if (ret) {
@@@ -1182,7 -1188,7 +1187,7 @@@ void i915_fence_or_sync(struct drm_fil
                        struct drm_fence_arg *fence_arg,
                        struct drm_fence_object **fence_p)
  {
 -      struct drm_device *dev = file_priv->head->dev;
 +      struct drm_device *dev = file_priv->minor->dev;
        int ret;
        struct drm_fence_object *fence;
  
  static int i915_execbuffer(struct drm_device *dev, void *data,
                           struct drm_file *file_priv)
  {
 -      drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 +      struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
 +      struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
        drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
 -              dev_priv->sarea_priv;
 +              master_priv->sarea_priv;
        struct drm_i915_execbuffer *exec_buf = data;
        struct drm_i915_batchbuffer *batch = &exec_buf->batch;
        struct drm_fence_arg *fence_arg = &exec_buf->fence_arg;
@@@ -1342,22 -1347,21 +1347,22 @@@ out_err0
  }
  #endif
  
 -static int i915_do_cleanup_pageflip(struct drm_device * dev)
 +int i915_do_cleanup_pageflip(struct drm_device * dev)
  {
 -      drm_i915_private_t *dev_priv = dev->dev_private;
 -      int i, planes, num_pages = dev_priv->sarea_priv->third_handle ? 3 : 2;
 +      struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
 +      int i, planes, num_pages;
  
        DRM_DEBUG("\n");
 -
 -      for (i = 0, planes = 0; i < 2; i++)
 -              if (dev_priv->sarea_priv->pf_current_page & (0x3 << (2 * i))) {
 -                      dev_priv->sarea_priv->pf_current_page =
 -                              (dev_priv->sarea_priv->pf_current_page &
 +      num_pages = master_priv->sarea_priv->third_handle ? 3 : 2;
 +      for (i = 0, planes = 0; i < 2; i++) {
 +              if (master_priv->sarea_priv->pf_current_page & (0x3 << (2 * i))) {
 +                      master_priv->sarea_priv->pf_current_page =
 +                              (master_priv->sarea_priv->pf_current_page &
                                 ~(0x3 << (2 * i))) | ((num_pages - 1) << (2 * i));
  
                        planes |= 1 << i;
                }
 +      }
  
        if (planes)
                i915_dispatch_flip(dev, planes, 0);
  
  static int i915_flip_bufs(struct drm_device *dev, void *data, struct drm_file *file_priv)
  {
 -      drm_i915_flip_t *param = data;
 +      struct drm_i915_flip *param = data;
  
        DRM_DEBUG("\n");
  
  static int i915_getparam(struct drm_device *dev, void *data,
                         struct drm_file *file_priv)
  {
 -      drm_i915_private_t *dev_priv = dev->dev_private;
 -      drm_i915_getparam_t *param = data;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      struct drm_i915_getparam *param = data;
        int value;
  
        if (!dev_priv) {
  static int i915_setparam(struct drm_device *dev, void *data,
                         struct drm_file *file_priv)
  {
 -      drm_i915_private_t *dev_priv = dev->dev_private;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
        drm_i915_setparam_t *param = data;
  
        if (!dev_priv) {
@@@ -1459,26 -1463,6 +1464,26 @@@ drm_i915_mmio_entry_t mmio_table[] = 
                I915_MMIO_MAY_READ|I915_MMIO_MAY_WRITE,
                0x2350,
                8
 +      },
 +      [MMIO_REGS_DOVSTA] = {
 +              I915_MMIO_MAY_READ,
 +              0x30008,
 +              1
 +      },
 +      [MMIO_REGS_GAMMA] = {
 +              I915_MMIO_MAY_READ|I915_MMIO_MAY_WRITE,
 +              0x30010,
 +              6
 +      },
 +      [MMIO_REGS_FENCE] = {
 +              I915_MMIO_MAY_READ|I915_MMIO_MAY_WRITE,
 +              0x2000,
 +              8
 +      },
 +      [MMIO_REGS_FENCE_NEW] = {
 +              I915_MMIO_MAY_READ|I915_MMIO_MAY_WRITE,
 +              0x3000,
 +              16
        }
  };
  
@@@ -1488,8 -1472,8 +1493,8 @@@ static int i915_mmio(struct drm_device 
                     struct drm_file *file_priv)
  {
        uint32_t buf[8];
 -      drm_i915_private_t *dev_priv = dev->dev_private;
 -      drm_i915_mmio_entry_t *e;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      drm_i915_mmio_entry_t *e;        
        drm_i915_mmio_t *mmio = data;
        void __iomem *base;
        int i;
  static int i915_set_status_page(struct drm_device *dev, void *data,
                                struct drm_file *file_priv)
  {
 -      drm_i915_private_t *dev_priv = dev->dev_private;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
        drm_i915_hws_addr_t *hws = data;
  
        if (!dev_priv) {
        dev_priv->hw_status_page = dev_priv->hws_map.handle;
  
        memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
 -      I915_WRITE(0x02080, dev_priv->status_gfx_addr);
 +      I915_WRITE(I915REG_HWS_PGA, dev_priv->status_gfx_addr);
        DRM_DEBUG("load hws 0x2080 with gfx mem 0x%x\n",
                        dev_priv->status_gfx_addr);
        DRM_DEBUG("load hws at %p\n", dev_priv->hw_status_page);
        return 0;
  }
  
 -int i915_driver_load(struct drm_device *dev, unsigned long flags)
 -{
 -      struct drm_i915_private *dev_priv = dev->dev_private;
 -      unsigned long base, size;
 -      int ret = 0, mmio_bar = IS_I9XX(dev) ? 0 : 1;
 -
 -      /* i915 has 4 more counters */
 -      dev->counters += 4;
 -      dev->types[6] = _DRM_STAT_IRQ;
 -      dev->types[7] = _DRM_STAT_PRIMARY;
 -      dev->types[8] = _DRM_STAT_SECONDARY;
 -      dev->types[9] = _DRM_STAT_DMA;
 -
 -      dev_priv = drm_alloc(sizeof(drm_i915_private_t), DRM_MEM_DRIVER);
 -      if (dev_priv == NULL)
 -              return -ENOMEM;
 -
 -      memset(dev_priv, 0, sizeof(drm_i915_private_t));
 -
 -      dev->dev_private = (void *)dev_priv;
 -
 -      /* Add register map (needed for suspend/resume) */
 -      base = drm_get_resource_start(dev, mmio_bar);
 -      size = drm_get_resource_len(dev, mmio_bar);
 -
 -      ret = drm_addmap(dev, base, size, _DRM_REGISTERS,
 -              _DRM_KERNEL | _DRM_DRIVER, &dev_priv->mmio_map);
 -
 -#ifdef __linux__
 -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
 -      intel_init_chipset_flush_compat(dev);
 -#endif
 -#endif
 -
 -      return ret;
 -}
 -
 -int i915_driver_unload(struct drm_device *dev)
 -{
 -      struct drm_i915_private *dev_priv = dev->dev_private;
 -
 -      if (dev_priv->mmio_map)
 -              drm_rmmap(dev, dev_priv->mmio_map);
 -
 -      drm_free(dev->dev_private, sizeof(drm_i915_private_t),
 -               DRM_MEM_DRIVER);
 -#ifdef __linux__
 -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
 -      intel_fini_chipset_flush_compat(dev);
 -#endif
 -#endif
 -      return 0;
 -}
 -
 -void i915_driver_lastclose(struct drm_device * dev)
 -{
 -      drm_i915_private_t *dev_priv = dev->dev_private;
 -
 -      if (drm_getsarea(dev) && dev_priv->sarea_priv)
 -              i915_do_cleanup_pageflip(dev);
 -      if (dev_priv->agp_heap)
 -              i915_mem_takedown(&(dev_priv->agp_heap));
 -
 -      if (dev_priv->sarea_kmap.virtual) {
 -              drm_bo_kunmap(&dev_priv->sarea_kmap);
 -              dev_priv->sarea_kmap.virtual = NULL;
 -              dev->lock.hw_lock = NULL;
 -              dev->sigdata.lock = NULL;
 -      }
 -
 -      if (dev_priv->sarea_bo) {
 -              mutex_lock(&dev->struct_mutex);
 -              drm_bo_usage_deref_locked(&dev_priv->sarea_bo);
 -              mutex_unlock(&dev->struct_mutex);
 -              dev_priv->sarea_bo = NULL;
 -      }
 -
 -      i915_dma_cleanup(dev);
 -}
 -
 -void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv)
 -{
 -      drm_i915_private_t *dev_priv = dev->dev_private;
 -      i915_mem_release(dev, file_priv, dev_priv->agp_heap);
 -}
 -
  struct drm_ioctl_desc i915_ioctls[] = {
        DRM_IOCTL_DEF(DRM_I915_INIT, i915_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
        DRM_IOCTL_DEF(DRM_I915_FLUSH, i915_flush_ioctl, DRM_AUTH),
@@@ -1611,3 -1681,10 +1616,3 @@@ int i915_driver_device_is_agp(struct dr
        return 1;
  }
  
 -int i915_driver_firstopen(struct drm_device *dev)
 -{
 -#ifdef I915_HAVE_BUFFER
 -      drm_bo_driver_init(dev);
 -#endif
 -      return 0;
 -}
diff --combined shared-core/i915_irq.c
  #include "i915_drm.h"
  #include "i915_drv.h"
  
 +#include "intel_drv.h"
 +
  #define USER_INT_FLAG (1<<1)
  #define VSYNC_PIPEB_FLAG (1<<5)
  #define VSYNC_PIPEA_FLAG (1<<7)
 +#define HOTPLUG_FLAG (1 << 17)
  
  #define MAX_NOPID ((u32)~0)
  
@@@ -52,7 -49,7 +52,7 @@@
  static int
  i915_get_pipe(struct drm_device *dev, int plane)
  {
 -      drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 +      struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
        u32 dspcntr;
  
        dspcntr = plane ? I915_READ(DSPBCNTR) : I915_READ(DSPACNTR);
@@@ -89,7 -86,7 +89,7 @@@ i915_get_plane(struct drm_device *dev, 
  static int
  i915_pipe_enabled(struct drm_device *dev, int pipe)
  {
 -      drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 +      struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
        unsigned long pipeconf = pipe ? PIPEBCONF : PIPEACONF;
  
        if (I915_READ(pipeconf) & PIPEACONF_ENABLE)
@@@ -107,8 -104,8 +107,8 @@@ static voi
  i915_dispatch_vsync_flip(struct drm_device *dev, struct drm_drawable_info *drw,
                         int plane)
  {
 -      drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 -      drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv;
 +      struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
 +      struct drm_i915_sarea *sarea_priv = master_priv->sarea_priv;
        u16 x1, y1, x2, y2;
        int pf_planes = 1 << plane;
  
   */
  static void i915_vblank_tasklet(struct drm_device *dev)
  {
 -      drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 +      struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
 +      struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
        struct list_head *list, *tmp, hits, *hit;
        int nhits, nrects, slice[2], upper[2], lower[2], i, num_pages;
        unsigned counter[2];
        struct drm_drawable_info *drw;
 -      drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv;
 +      struct drm_i915_sarea *sarea_priv;
        u32 cpp = dev_priv->cpp,  offsets[3];
        u32 cmd = (cpp == 4) ? (XY_SRC_COPY_BLT_CMD |
                                XY_SRC_COPY_BLT_WRITE_ALPHA |
                                XY_SRC_COPY_BLT_WRITE_RGB)
                             : XY_SRC_COPY_BLT_CMD;
 -      u32 pitchropcpp = (sarea_priv->pitch * cpp) | (0xcc << 16) |
 -                        (cpp << 23) | (1 << 24);
 +      u32 pitchropcpp;
        RING_LOCALS;
  
        counter[0] = drm_vblank_count(dev, 0);
  
        /* Find buffer swaps scheduled for this vertical blank */
        list_for_each_safe(list, tmp, &dev_priv->vbl_swaps.head) {
 -              drm_i915_vbl_swap_t *vbl_swap =
 -                      list_entry(list, drm_i915_vbl_swap_t, head);
 +              struct drm_i915_vbl_swap *vbl_swap =
 +                      list_entry(list, struct drm_i915_vbl_swap, head);
                int pipe = i915_get_pipe(dev, vbl_swap->plane);
  
                if ((counter[pipe] - vbl_swap->sequence) > (1<<23))
                        continue;
  
 +              master_priv = vbl_swap->minor->master->driver_priv;
 +              sarea_priv = master_priv->sarea_priv;
 +              
 +              pitchropcpp = (sarea_priv->pitch * cpp) | (0xcc << 16) |
 +                      (cpp << 23) | (1 << 24);
 +
                list_del(list);
                dev_priv->swaps_pending--;
                drm_vblank_put(dev, pipe);
                }
  
                list_for_each(hit, &hits) {
 -                      drm_i915_vbl_swap_t *swap_cmp =
 -                              list_entry(hit, drm_i915_vbl_swap_t, head);
 +                      struct drm_i915_vbl_swap *swap_cmp =
 +                              list_entry(hit, struct drm_i915_vbl_swap, head);
                        struct drm_drawable_info *drw_cmp =
                                drm_get_drawable_info(dev, swap_cmp->drw_id);
  
                        lower[0] = lower[1] = sarea_priv->height;
  
                list_for_each(hit, &hits) {
 -                      drm_i915_vbl_swap_t *swap_hit =
 -                              list_entry(hit, drm_i915_vbl_swap_t, head);
 +                      struct drm_i915_vbl_swap *swap_hit =
 +                              list_entry(hit, struct drm_i915_vbl_swap, head);
                        struct drm_clip_rect *rect;
                        int num_rects, plane, front, back;
                        unsigned short top, bottom;
                        top = upper[plane];
                        bottom = lower[plane];
  
 -                      front = (dev_priv->sarea_priv->pf_current_page >>
 +                      front = (master_priv->sarea_priv->pf_current_page >>
                                 (2 * plane)) & 0x3;
                        back = (front + 1) % num_pages;
  
        DRM_SPINUNLOCK(&dev->drw_lock);
  
        list_for_each_safe(hit, tmp, &hits) {
 -              drm_i915_vbl_swap_t *swap_hit =
 -                      list_entry(hit, drm_i915_vbl_swap_t, head);
 +              struct drm_i915_vbl_swap *swap_hit =
 +                      list_entry(hit, struct drm_i915_vbl_swap, head);
  
                list_del(hit);
  
  #if 0
  static int i915_in_vblank(struct drm_device *dev, int pipe)
  {
 -      drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 +      struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
        unsigned long pipedsl, vblank, vtotal;
        unsigned long vbl_start, vbl_end, cur_line;
  
  #endif
  u32 i915_get_vblank_counter(struct drm_device *dev, int plane)
  {
 -      drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 +      struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
        unsigned long high_frame;
        unsigned long low_frame;
        u32 high1, high2, low, count;
        if (i915_in_vblank(dev, pipe))
                count++;
  #endif
+       /* count may be reset by other driver(e.g. 2D driver), 
+          we have no way to know if it is wrapped or resetted 
+          when count is zero. do a rough guess.
+       */
+       if (count == 0 && dev->last_vblank[pipe] < dev->max_vblank_count/2)
+               dev->last_vblank[pipe] = 0; 
+       
        return count;
  }
  
 +#define HOTPLUG_CMD_CRT 1
 +#define HOTPLUG_CMD_CRT_DIS 2
 +#define HOTPLUG_CMD_SDVOB 4
 +#define HOTPLUG_CMD_SDVOC 8
 +
 +static struct drm_device *hotplug_dev;
 +static int hotplug_cmd = 0;
 +static spinlock_t hotplug_lock = SPIN_LOCK_UNLOCKED;
 +
 +static void i915_hotplug_crt(struct drm_device *dev, bool connected)
 +{
 +      struct drm_output *output;
 +      struct intel_output *iout;
 +
 +      mutex_lock(&dev->mode_config.mutex);
 +
 +      /* find the crt output */
 +      list_for_each_entry(output, &dev->mode_config.output_list, head) {
 +              iout = output->driver_private;
 +              if (iout->type == INTEL_OUTPUT_ANALOG)
 +                      break;
 +              else
 +                      iout = 0;
 +      }
 +
 +      if (iout == 0)
 +              goto unlock;
 +
 +      drm_hotplug_stage_two(dev, output, connected);
 +
 +unlock:
 +      mutex_unlock(&dev->mode_config.mutex);
 +}
 +
 +static void i915_hotplug_sdvo(struct drm_device *dev, int sdvoB)
 +{
 +      struct drm_output *output = 0;
 +      enum drm_output_status status;
 +
 +      mutex_lock(&dev->mode_config.mutex);
 +
 +      output = intel_sdvo_find(dev, sdvoB);
 +
 +      if (!output) {
 +              DRM_ERROR("could not find sdvo%s output\n", sdvoB ? "B" : "C");
 +              goto unlock;
 +      }
 +
 +      status = output->funcs->detect(output);
 +
 +      if (status != output_status_connected)
 +              drm_hotplug_stage_two(dev, output, false);
 +      else
 +              drm_hotplug_stage_two(dev, output, true);
 +
 +      /* wierd hw bug, sdvo stop sending interupts */
 +      intel_sdvo_set_hotplug(output, 1);
 +
 +unlock:
 +      mutex_unlock(&dev->mode_config.mutex);
 +}
 +/*
 + * This code is called in a more safe envirmoent to handle the hotplugs.
 + * Add code here for hotplug love to userspace.
 + */
 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
 +static void i915_hotplug_work_func(void *work)
 +#else
 +static void i915_hotplug_work_func(struct work_struct *work)
 +#endif
 +{
 +      struct drm_device *dev = hotplug_dev;
 +      int crt;
 +      int crtDis;
 +      int sdvoB;
 +      int sdvoC;
 +
 +      spin_lock(&hotplug_lock);
 +      crt = hotplug_cmd & HOTPLUG_CMD_CRT;
 +      crtDis = hotplug_cmd & HOTPLUG_CMD_CRT_DIS;
 +      sdvoB = hotplug_cmd & HOTPLUG_CMD_SDVOB;
 +      sdvoC = hotplug_cmd & HOTPLUG_CMD_SDVOC;
 +      hotplug_cmd = 0;
 +      spin_unlock(&hotplug_lock);
 +
 +      if (crt)
 +              i915_hotplug_crt(dev, true);
 +      if (crtDis)
 +              i915_hotplug_crt(dev, false);
 +
 +      if (sdvoB)
 +              i915_hotplug_sdvo(dev, 1);
 +
 +      if (sdvoC)
 +              i915_hotplug_sdvo(dev, 0);
 +
 +}
 +
 +static int i915_run_hotplug_tasklet(struct drm_device *dev, uint32_t stat)
 +{
 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
 +      static DECLARE_WORK(hotplug, i915_hotplug_work_func, NULL);
 +#else
 +      static DECLARE_WORK(hotplug, i915_hotplug_work_func);
 +#endif
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +
 +      hotplug_dev = dev;
 +
 +      if (stat & CRT_HOTPLUG_INT_STATUS) {
 +              DRM_DEBUG("CRT event\n");
 +
 +              if (stat & CRT_HOTPLUG_MONITOR_MASK) {
 +                      spin_lock(&hotplug_lock);
 +                      hotplug_cmd |= HOTPLUG_CMD_CRT;
 +                      spin_unlock(&hotplug_lock);
 +              } else {
 +                      spin_lock(&hotplug_lock);
 +                      hotplug_cmd |= HOTPLUG_CMD_CRT_DIS;
 +                      spin_unlock(&hotplug_lock);
 +              }
 +      }
 +
 +      if (stat & SDVOB_HOTPLUG_INT_STATUS) {
 +              DRM_DEBUG("sDVOB event\n");
 +
 +              spin_lock(&hotplug_lock);
 +              hotplug_cmd |= HOTPLUG_CMD_SDVOB;
 +              spin_unlock(&hotplug_lock);
 +      }
 +
 +      if (stat & SDVOC_HOTPLUG_INT_STATUS) {
 +              DRM_DEBUG("sDVOC event\n");
 +
 +              spin_lock(&hotplug_lock);
 +              hotplug_cmd |= HOTPLUG_CMD_SDVOC;
 +              spin_unlock(&hotplug_lock);
 +      }
 +
 +      queue_work(dev_priv->wq, &hotplug);
 +
 +      return 0;
 +}
 +
  irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
  {
        struct drm_device *dev = (struct drm_device *) arg;
 -      drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 -      u16 temp;
 +      struct drm_i915_master_private *master_priv;
 +      struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
 +      u32 temp = 0;
 +      u32 temp2;
        u32 pipea_stats, pipeb_stats;
  
        pipea_stats = I915_READ(I915REG_PIPEASTAT);
        pipeb_stats = I915_READ(I915REG_PIPEBSTAT);
  
 -      temp = I915_READ16(I915REG_INT_IDENTITY_R);
 +      /* On i8xx hw the IIR and IER are 16bit on i9xx its 32bit */
 +      if (IS_I9XX(dev))
 +              temp = I915_READ(I915REG_INT_IDENTITY_R);
 +      else
 +              temp = I915_READ16(I915REG_INT_IDENTITY_R);
 +
 +      temp2 = temp;
 +      temp &= (dev_priv->irq_enable_reg | USER_INT_FLAG);
  
  #if 0
 +      /* ugly despamification of pipeb event irq */
 +      if (temp & (0xFFFFFFF ^ ((1 << 5) | (1 << 7)))) {
 +              DRM_DEBUG("IIR %08x\n", temp2);
 +              DRM_DEBUG("MSK %08x\n", dev_priv->irq_enable_reg | USER_INT_FLAG);
 +              DRM_DEBUG("M&I %08x\n", temp);
 +              DRM_DEBUG("HOT %08x\n", I915_READ(PORT_HOTPLUG_STAT));
 +      }
 +#else
 +#if 0
        DRM_DEBUG("flag=%08x\n", temp);
  #endif
 +#endif
 +
        if (temp == 0)
                return IRQ_NONE;
  
 +      if (IS_I9XX(dev)) {
 +              I915_WRITE(I915REG_INT_IDENTITY_R, temp);
 +              (void) I915_READ(I915REG_INT_IDENTITY_R);
 +      } else {
 +              I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
 +              (void) I915_READ16(I915REG_INT_IDENTITY_R);
 +      }
 +
        /*
         * Clear the PIPE(A|B)STAT regs before the IIR otherwise
         * we may get extra interrupts.
                           pipea_stats | I915_VBLANK_INTERRUPT_ENABLE |
                           I915_VBLANK_CLEAR);
        }
 +
        if (temp & VSYNC_PIPEB_FLAG) {
                drm_handle_vblank(dev, i915_get_plane(dev, 1));
                I915_WRITE(I915REG_PIPEBSTAT,
        I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
        (void) I915_READ16(I915REG_INT_IDENTITY_R); /* Flush posted write */
  
 +      DRM_READMEMORYBARRIER();
 +
        temp &= (dev_priv->irq_enable_reg | USER_INT_FLAG | VSYNC_PIPEA_FLAG |
                 VSYNC_PIPEB_FLAG);
  
 -      if (dev_priv->sarea_priv)
 -              dev_priv->sarea_priv->last_dispatch =
 -                      READ_BREADCRUMB(dev_priv);
 +      if (dev->primary->master) {
 +              master_priv = dev->primary->master->driver_priv;
 +              master_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
 +      }
  
        if (temp & USER_INT_FLAG) {
                DRM_WAKEUP(&dev_priv->irq_queue);
                        drm_locked_tasklet(dev, i915_vblank_tasklet);
        }
  
 +      /* for now lest just ack it */
 +      if (temp & (1 << 17)) {
 +              DRM_DEBUG("Hotplug event received\n");
 +
 +              temp2 = I915_READ(PORT_HOTPLUG_STAT);
 +
 +              i915_run_hotplug_tasklet(dev, temp2);
 +
 +              I915_WRITE(PORT_HOTPLUG_STAT,temp2);
 +      }
 +
        return IRQ_HANDLED;
  }
  
  int i915_emit_irq(struct drm_device *dev)
  {
 -      drm_i915_private_t *dev_priv = dev->dev_private;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
        RING_LOCALS;
  
        i915_kernel_lost_context(dev);
        return dev_priv->counter;
  }
  
 -void i915_user_irq_on(drm_i915_private_t *dev_priv)
 +void i915_user_irq_on(struct drm_i915_private *dev_priv)
  {
        DRM_SPINLOCK(&dev_priv->user_irq_lock);
        if (dev_priv->irq_enabled && (++dev_priv->user_irq_refcount == 1)){
        DRM_SPINUNLOCK(&dev_priv->user_irq_lock);
  
  }
 -
 -void i915_user_irq_off(drm_i915_private_t *dev_priv)
 +              
 +void i915_user_irq_off(struct drm_i915_private *dev_priv)
  {
        DRM_SPINLOCK(&dev_priv->user_irq_lock);
        if (dev_priv->irq_enabled && (--dev_priv->user_irq_refcount == 0)) {
  
  static int i915_wait_irq(struct drm_device * dev, int irq_nr)
  {
 -      drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 +      struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
 +      struct drm_i915_master_private *master_priv;
        int ret = 0;
  
        DRM_DEBUG("irq_nr=%d breadcrumb=%d\n", irq_nr,
                DRM_ERROR("EBUSY -- rec: %d emitted: %d\n",
                          READ_BREADCRUMB(dev_priv), (int)dev_priv->counter);
        }
 +      
 +      if (dev->primary->master) {
 +              master_priv = dev->primary->master->driver_priv;
 +              master_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
 +      }
  
 -      if (dev_priv->sarea_priv)
 -              dev_priv->sarea_priv->last_dispatch =
 -                      READ_BREADCRUMB(dev_priv);
        return ret;
  }
  
  int i915_irq_emit(struct drm_device *dev, void *data,
                         struct drm_file *file_priv)
  {
 -      drm_i915_private_t *dev_priv = dev->dev_private;
 -      drm_i915_irq_emit_t *emit = data;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      struct drm_i915_irq_emit *emit = data;
        int result;
  
        LOCK_TEST_WITH_RETURN(dev, file_priv);
  int i915_irq_wait(struct drm_device *dev, void *data,
                  struct drm_file *file_priv)
  {
 -      drm_i915_private_t *dev_priv = dev->dev_private;
 -      drm_i915_irq_wait_t *irqwait = data;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      struct drm_i915_irq_wait *irqwait = data;
  
        if (!dev_priv) {
                DRM_ERROR("called with no initialization\n");
  
  int i915_enable_vblank(struct drm_device *dev, int plane)
  {
 -      drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 +      struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
        int pipe = i915_get_pipe(dev, plane);
 -
 +      
        switch (pipe) {
        case 0:
                dev_priv->irq_enable_reg |= VSYNC_PIPEA_FLAG;
  
  void i915_disable_vblank(struct drm_device *dev, int plane)
  {
 -      drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 +      struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
        int pipe = i915_get_pipe(dev, plane);
  
        switch (pipe) {
        I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
  }
  
 -static void i915_enable_interrupt (struct drm_device *dev)
 +void i915_enable_interrupt (struct drm_device *dev)
  {
 -      drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 -      
 +      struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
 +      struct drm_output *o;
 +
        dev_priv->irq_enable_reg |= USER_INT_FLAG;
  
 -      I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
 +      if (IS_I9XX(dev) && dev->mode_config.num_output) {
 +              dev_priv->irq_enable_reg |= HOTPLUG_FLAG;
 +
 +              /* Activate the CRT */
 +              I915_WRITE(PORT_HOTPLUG_EN, CRT_HOTPLUG_INT_EN);
 +
 +              /* SDVOB */
 +              o = intel_sdvo_find(dev, 1);
 +              if (o && intel_sdvo_supports_hotplug(o)) {
 +                      intel_sdvo_set_hotplug(o, 1);
 +                      I915_WRITE(PORT_HOTPLUG_EN, SDVOB_HOTPLUG_INT_EN);
 +              }
 +
 +              /* SDVOC */
 +              o = intel_sdvo_find(dev, 0);
 +              if (o && intel_sdvo_supports_hotplug(o)) {
 +                      intel_sdvo_set_hotplug(o, 1);
 +                      I915_WRITE(PORT_HOTPLUG_EN, SDVOC_HOTPLUG_INT_EN);
 +              }
 +
 +      }
 +
 +      if (IS_I9XX(dev)) {
 +              I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
 +      } else {
 +              I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
 +      }
 +
 +      DRM_DEBUG("HEN %08x\n",I915_READ(PORT_HOTPLUG_EN));
 +      DRM_DEBUG("HST %08x\n",I915_READ(PORT_HOTPLUG_STAT));
 +      DRM_DEBUG("IER %08x\n",I915_READ(I915REG_INT_ENABLE_R));
 +      DRM_DEBUG("SDB %08x\n",I915_READ(SDVOB));
 +
 +      I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
 +
        dev_priv->irq_enabled = 1;
  }
  
  int i915_vblank_pipe_set(struct drm_device *dev, void *data,
                         struct drm_file *file_priv)
  {
 -      drm_i915_private_t *dev_priv = dev->dev_private;
 -      drm_i915_vblank_pipe_t *pipe = data;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      struct drm_i915_vblank_pipe *pipe = data;
  
        if (!dev_priv) {
                DRM_ERROR("called with no initialization\n");
  int i915_vblank_pipe_get(struct drm_device *dev, void *data,
                         struct drm_file *file_priv)
  {
 -      drm_i915_private_t *dev_priv = dev->dev_private;
 -      drm_i915_vblank_pipe_t *pipe = data;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      struct drm_i915_vblank_pipe *pipe = data;
        u16 flag;
  
        if (!dev_priv) {
  int i915_vblank_swap(struct drm_device *dev, void *data,
                     struct drm_file *file_priv)
  {
 -      drm_i915_private_t *dev_priv = dev->dev_private;
 -      drm_i915_vblank_swap_t *swap = data;
 -      drm_i915_vbl_swap_t *vbl_swap;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      struct drm_i915_master_private *master_priv;
 +      struct drm_i915_vblank_swap *swap = data;
 +      struct drm_i915_vbl_swap *vbl_swap;
        unsigned int pipe, seqtype, curseq, plane;
        unsigned long irqflags;
        struct list_head *list;
                return -EINVAL;
        }
  
 -      if (!dev_priv->sarea_priv || dev_priv->sarea_priv->rotation) {
 +      if (!dev->primary->master)
 +              return -EINVAL;
 +
 +      master_priv = dev->primary->master->driver_priv;
 +
 +      if (master_priv->sarea_priv->rotation) {
                DRM_DEBUG("Rotation not supported\n");
                return -EINVAL;
        }
        DRM_SPINLOCK_IRQSAVE(&dev_priv->swaps_lock, irqflags);
  
        list_for_each(list, &dev_priv->vbl_swaps.head) {
 -              vbl_swap = list_entry(list, drm_i915_vbl_swap_t, head);
 +              vbl_swap = list_entry(list, struct drm_i915_vbl_swap, head);
  
                if (vbl_swap->drw_id == swap->drawable &&
                    vbl_swap->plane == plane &&
        vbl_swap->plane = plane;
        vbl_swap->sequence = swap->sequence;
        vbl_swap->flip = (swap->seqtype & _DRM_VBLANK_FLIP);
 +      vbl_swap->minor = file_priv->minor;
  
        if (vbl_swap->flip)
                swap->sequence++;
  */
  void i915_driver_irq_preinstall(struct drm_device * dev)
  {
 -      drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 +      struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
  
        I915_WRITE16(I915REG_HWSTAM, 0xeffe);
 -      I915_WRITE16(I915REG_INT_MASK_R, 0x0);
 -      I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
 +      if (IS_I9XX(dev)) {
 +              I915_WRITE(I915REG_INT_MASK_R, 0x0);
 +              I915_WRITE(I915REG_INT_ENABLE_R, 0x0);
 +      } else {
 +              I915_WRITE16(I915REG_INT_MASK_R, 0x0);
 +              I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
 +      }
 +
  }
  
  int i915_driver_irq_postinstall(struct drm_device * dev)
  {
 -      drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 +      struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
        int ret, num_pipes = 2;
  
        DRM_SPININIT(&dev_priv->swaps_lock, "swap");
  
  void i915_driver_irq_uninstall(struct drm_device * dev)
  {
 -      drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 -      u16 temp;
 +      struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
 +      u32 temp;
  
        if (!dev_priv)
                return;
  
        dev_priv->irq_enabled = 0;
 -      I915_WRITE16(I915REG_HWSTAM, 0xffff);
 -      I915_WRITE16(I915REG_INT_MASK_R, 0xffff);
 -      I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
  
 -      temp = I915_READ16(I915REG_INT_IDENTITY_R);
 -      I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
 +
 +      if(IS_I9XX(dev)) {
 +              I915_WRITE(I915REG_HWSTAM, 0xffffffff);
 +              I915_WRITE(I915REG_INT_MASK_R, 0xffffffff);
 +              I915_WRITE(I915REG_INT_ENABLE_R, 0x0);
 +
 +              temp = I915_READ(I915REG_INT_IDENTITY_R);
 +              I915_WRITE(I915REG_INT_IDENTITY_R, temp);
 +      } else {
 +              I915_WRITE16(I915REG_HWSTAM, 0xffff);
 +              I915_WRITE16(I915REG_INT_MASK_R, 0xffff);
 +              I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
 +
 +              temp = I915_READ16(I915REG_INT_IDENTITY_R);
 +              I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
 +      }
  }