DA: patch from Matthew upgraded to latest DRI head to solve issue with i810
authorDave Airlie <airlied@linux.ie>
Wed, 13 Aug 2003 23:35:40 +0000 (23:35 +0000)
committerDave Airlie <airlied@linux.ie>
Wed, 13 Aug 2003 23:35:40 +0000 (23:35 +0000)
    compatibility

linux-core/i810_dma.c
linux-core/i810_drm.h
linux/i810.h
linux/i810_dma.c
linux/i810_drm.h

index 88e5b9d..6af9181 100644 (file)
@@ -450,6 +450,49 @@ static int i810_dma_initialize(drm_device_t *dev,
        return 0;
 }
 
+/* i810 DRM version 1.1 used a smaller init structure with different
+ * ordering of values than is currently used (drm >= 1.2). There is
+ * no defined way to detect the XFree version to correct this problem,
+ * however by checking using this procedure we can detect the correct
+ * thing to do.
+ *
+ * #1 Read the Smaller init structure from user-space
+ * #2 Verify the overlay_physical is a valid physical address, or NULL
+ *    If it isn't then we have a v1.1 client. Fix up params.
+ *    If it is, then we have a 1.2 client... get the rest of the data.
+ */
+int i810_dma_init_compat(drm_i810_init_t *init, unsigned long arg)
+{
+
+       /* Get v1.1 init data */
+       if(copy_from_user(init, (drm_i810_pre12_init_t *)arg,
+                         sizeof(drm_i810_pre12_init_t))) {
+               return -EFAULT;
+       }
+
+       if ((!init->overlay_physical) || (init->overlay_physical > 4096)) {
+
+               /* This is a v1.2 client, just get the v1.2 init data */
+               DRM_INFO("Using POST v1.2 init.\n");
+               if(copy_from_user(init, (drm_i810_init_t *)arg,
+                                 sizeof(drm_i810_init_t))) {
+                       return -EFAULT;
+               }
+       } else {
+
+               /* This is a v1.1 client, fix the params */
+               DRM_INFO("Using PRE v1.2 init.\n");
+               init->pitch_bits = init->h;
+               init->pitch = init->w;
+               init->h = init->overlay_physical;
+               init->w = init->overlay_offset;
+               init->overlay_physical = 0;
+               init->overlay_offset = 0;
+       }
+
+       return 0;
+}
+
 int i810_dma_init(struct inode *inode, struct file *filp,
                  unsigned int cmd, unsigned long arg)
 {
@@ -459,22 +502,43 @@ int i810_dma_init(struct inode *inode, struct file *filp,
        drm_i810_init_t init;
        int retcode = 0;
 
-       if (copy_from_user(&init, (drm_i810_init_t *)arg, sizeof(init)))
+       /* Get only the init func */
+       if (copy_from_user(&init, (void *)arg, sizeof(drm_i810_init_func_t))) {
                return -EFAULT;
+       }
 
        switch(init.func) {
                case I810_INIT_DMA:
+                       /* This case is for backward compatibility. It
+                        * handles XFree 4.1.0 and 4.2.0, and has to
+                        * do some parameter checking as described below.
+                        * It will someday go away.
+                        */
+                       retcode = i810_dma_init_compat(&init, arg);
+                       if(retcode) {
+                               return retcode;
+                       }
+                       dev_priv = DRM(alloc)(sizeof(drm_i810_private_t),
+                                            DRM_MEM_DRIVER);
+                       if(dev_priv == NULL) return -ENOMEM;
+                       retcode = i810_dma_initialize(dev, dev_priv, &init);
+               break;
+               default:
+               case I810_INIT_DMA_1_4:
+                       DRM_INFO("Using v1.4 init.\n");
+                       if(copy_from_user(&init, (drm_i810_init_t *)arg,
+                                         sizeof(drm_i810_init_t))) {
+                               return -EFAULT;
+                       }
                        dev_priv = DRM(alloc)(sizeof(drm_i810_private_t),
                                             DRM_MEM_DRIVER);
                        if(dev_priv == NULL) return -ENOMEM;
                        retcode = i810_dma_initialize(dev, dev_priv, &init);
                break;
                case I810_CLEANUP_DMA:
+                       DRM_INFO("DMA Cleanup\n");
                        retcode = i810_dma_cleanup(dev);
                break;
-               default:
-                       retcode = -EINVAL;
-               break;
        }
 
        return retcode;
index b35593b..93775f6 100644 (file)
 #define I810_BACK    0x2
 #define I810_DEPTH   0x4
 
+typedef enum _drm_i810_init_func {
+       I810_INIT_DMA = 0x01,
+       I810_CLEANUP_DMA = 0x02,
+       I810_INIT_DMA_1_4 = 0x03
+ } drm_i810_init_func_t;
 
+/* This is the init structure after v1.2 */
 typedef struct _drm_i810_init {
-       enum {
-               I810_INIT_DMA = 0x01,
-               I810_CLEANUP_DMA = 0x02
-       } func;
+       drm_i810_init_func_t func;
 #if CONFIG_XFREE86_VERSION < XFREE86_VERSION(4,1,0,0)
        int ring_map_idx;
        int buffer_map_idx;
@@ -122,6 +125,29 @@ typedef struct _drm_i810_init {
        unsigned int pitch_bits; 
 } drm_i810_init_t;
 
+/* This is the init structure prior to v1.2 */
+typedef struct _drm_i810_pre12_init {
+        drm_i810_init_func_t func;
+#if CONFIG_XFREE86_VERSION < XFREE86_VERSION(4,1,0,0)
+       int ring_map_idx;
+       int buffer_map_idx;
+#else
+        unsigned int mmio_offset;
+       unsigned int buffers_offset;
+#endif
+       int sarea_priv_offset;
+       unsigned int ring_start;
+       unsigned int ring_end;
+       unsigned int ring_size;
+       unsigned int front_offset;
+       unsigned int back_offset;
+       unsigned int depth_offset;
+       unsigned int w;
+       unsigned int h;
+       unsigned int pitch;
+       unsigned int pitch_bits; 
+} drm_i810_pre12_init_t;
+
 /* Warning: If you change the SAREA structure you must change the Xserver
  * structure as well */
 
index ba40892..a5d300a 100644 (file)
  * 1.2.1 - Disable copying code (leave stub ioctls for backwards compatibility)
  *       - Remove requirement for interrupt (leave stubs again)
  * 1.3   - Add page flipping.
+ * 1.4   - fix DRM interface
  */
 #define DRIVER_MAJOR           1
-#define DRIVER_MINOR           3
+#define DRIVER_MINOR           4
 #define DRIVER_PATCHLEVEL      0
 
 #define DRIVER_IOCTLS                                                      \
index 88e5b9d..6af9181 100644 (file)
@@ -450,6 +450,49 @@ static int i810_dma_initialize(drm_device_t *dev,
        return 0;
 }
 
+/* i810 DRM version 1.1 used a smaller init structure with different
+ * ordering of values than is currently used (drm >= 1.2). There is
+ * no defined way to detect the XFree version to correct this problem,
+ * however by checking using this procedure we can detect the correct
+ * thing to do.
+ *
+ * #1 Read the Smaller init structure from user-space
+ * #2 Verify the overlay_physical is a valid physical address, or NULL
+ *    If it isn't then we have a v1.1 client. Fix up params.
+ *    If it is, then we have a 1.2 client... get the rest of the data.
+ */
+int i810_dma_init_compat(drm_i810_init_t *init, unsigned long arg)
+{
+
+       /* Get v1.1 init data */
+       if(copy_from_user(init, (drm_i810_pre12_init_t *)arg,
+                         sizeof(drm_i810_pre12_init_t))) {
+               return -EFAULT;
+       }
+
+       if ((!init->overlay_physical) || (init->overlay_physical > 4096)) {
+
+               /* This is a v1.2 client, just get the v1.2 init data */
+               DRM_INFO("Using POST v1.2 init.\n");
+               if(copy_from_user(init, (drm_i810_init_t *)arg,
+                                 sizeof(drm_i810_init_t))) {
+                       return -EFAULT;
+               }
+       } else {
+
+               /* This is a v1.1 client, fix the params */
+               DRM_INFO("Using PRE v1.2 init.\n");
+               init->pitch_bits = init->h;
+               init->pitch = init->w;
+               init->h = init->overlay_physical;
+               init->w = init->overlay_offset;
+               init->overlay_physical = 0;
+               init->overlay_offset = 0;
+       }
+
+       return 0;
+}
+
 int i810_dma_init(struct inode *inode, struct file *filp,
                  unsigned int cmd, unsigned long arg)
 {
@@ -459,22 +502,43 @@ int i810_dma_init(struct inode *inode, struct file *filp,
        drm_i810_init_t init;
        int retcode = 0;
 
-       if (copy_from_user(&init, (drm_i810_init_t *)arg, sizeof(init)))
+       /* Get only the init func */
+       if (copy_from_user(&init, (void *)arg, sizeof(drm_i810_init_func_t))) {
                return -EFAULT;
+       }
 
        switch(init.func) {
                case I810_INIT_DMA:
+                       /* This case is for backward compatibility. It
+                        * handles XFree 4.1.0 and 4.2.0, and has to
+                        * do some parameter checking as described below.
+                        * It will someday go away.
+                        */
+                       retcode = i810_dma_init_compat(&init, arg);
+                       if(retcode) {
+                               return retcode;
+                       }
+                       dev_priv = DRM(alloc)(sizeof(drm_i810_private_t),
+                                            DRM_MEM_DRIVER);
+                       if(dev_priv == NULL) return -ENOMEM;
+                       retcode = i810_dma_initialize(dev, dev_priv, &init);
+               break;
+               default:
+               case I810_INIT_DMA_1_4:
+                       DRM_INFO("Using v1.4 init.\n");
+                       if(copy_from_user(&init, (drm_i810_init_t *)arg,
+                                         sizeof(drm_i810_init_t))) {
+                               return -EFAULT;
+                       }
                        dev_priv = DRM(alloc)(sizeof(drm_i810_private_t),
                                             DRM_MEM_DRIVER);
                        if(dev_priv == NULL) return -ENOMEM;
                        retcode = i810_dma_initialize(dev, dev_priv, &init);
                break;
                case I810_CLEANUP_DMA:
+                       DRM_INFO("DMA Cleanup\n");
                        retcode = i810_dma_cleanup(dev);
                break;
-               default:
-                       retcode = -EINVAL;
-               break;
        }
 
        return retcode;
index b35593b..93775f6 100644 (file)
 #define I810_BACK    0x2
 #define I810_DEPTH   0x4
 
+typedef enum _drm_i810_init_func {
+       I810_INIT_DMA = 0x01,
+       I810_CLEANUP_DMA = 0x02,
+       I810_INIT_DMA_1_4 = 0x03
+ } drm_i810_init_func_t;
 
+/* This is the init structure after v1.2 */
 typedef struct _drm_i810_init {
-       enum {
-               I810_INIT_DMA = 0x01,
-               I810_CLEANUP_DMA = 0x02
-       } func;
+       drm_i810_init_func_t func;
 #if CONFIG_XFREE86_VERSION < XFREE86_VERSION(4,1,0,0)
        int ring_map_idx;
        int buffer_map_idx;
@@ -122,6 +125,29 @@ typedef struct _drm_i810_init {
        unsigned int pitch_bits; 
 } drm_i810_init_t;
 
+/* This is the init structure prior to v1.2 */
+typedef struct _drm_i810_pre12_init {
+        drm_i810_init_func_t func;
+#if CONFIG_XFREE86_VERSION < XFREE86_VERSION(4,1,0,0)
+       int ring_map_idx;
+       int buffer_map_idx;
+#else
+        unsigned int mmio_offset;
+       unsigned int buffers_offset;
+#endif
+       int sarea_priv_offset;
+       unsigned int ring_start;
+       unsigned int ring_end;
+       unsigned int ring_size;
+       unsigned int front_offset;
+       unsigned int back_offset;
+       unsigned int depth_offset;
+       unsigned int w;
+       unsigned int h;
+       unsigned int pitch;
+       unsigned int pitch_bits; 
+} drm_i810_pre12_init_t;
+
 /* Warning: If you change the SAREA structure you must change the Xserver
  * structure as well */