summaryrefslogtreecommitdiff
path: root/linux-core/i810_dma.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@linux.ie>2003-08-13 23:35:40 +0000
committerDave Airlie <airlied@linux.ie>2003-08-13 23:35:40 +0000
commit428cbe0b91b1b446b0878544f30121df9b5bb2ac (patch)
tree7c3cb32bde568b451f312d5037278d1fb37a9f5d /linux-core/i810_dma.c
parent03e6674c13f8e7033c891ae8979e7f996fe9a6c1 (diff)
DA: patch from Matthew upgraded to latest DRI head to solve issue with i810
compatibility
Diffstat (limited to 'linux-core/i810_dma.c')
-rw-r--r--linux-core/i810_dma.c72
1 files changed, 68 insertions, 4 deletions
diff --git a/linux-core/i810_dma.c b/linux-core/i810_dma.c
index 88e5b9db..6af9181a 100644
--- a/linux-core/i810_dma.c
+++ b/linux-core/i810_dma.c
@@ -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;