summaryrefslogtreecommitdiff
path: root/linux-core
diff options
context:
space:
mode:
Diffstat (limited to 'linux-core')
-rw-r--r--linux-core/drm_dma.c7
-rw-r--r--linux-core/i810_dma.c12
-rw-r--r--linux-core/i810_drv.h3
-rw-r--r--linux-core/i830_dma.c22
-rw-r--r--linux-core/i830_drv.h3
-rw-r--r--linux-core/i830_irq.c41
6 files changed, 66 insertions, 22 deletions
diff --git a/linux-core/drm_dma.c b/linux-core/drm_dma.c
index 7c1785b4..34ab5322 100644
--- a/linux-core/drm_dma.c
+++ b/linux-core/drm_dma.c
@@ -194,6 +194,13 @@ int DRM(irq_install)( drm_device_t *dev, int irq )
return -EINVAL;
down( &dev->struct_sem );
+
+ /* Driver must have been initialized */
+ if ( !dev->dev_private ) {
+ up( &dev->struct_sem );
+ return -EINVAL;
+ }
+
if ( dev->irq ) {
up( &dev->struct_sem );
return -EBUSY;
diff --git a/linux-core/i810_dma.c b/linux-core/i810_dma.c
index 30b7dfcf..8e0e8f45 100644
--- a/linux-core/i810_dma.c
+++ b/linux-core/i810_dma.c
@@ -234,11 +234,19 @@ static int i810_dma_get_buffer(drm_device_t *dev, drm_i810_dma_t *d,
return retcode;
}
-static int i810_dma_cleanup(drm_device_t *dev)
+int i810_dma_cleanup(drm_device_t *dev)
{
drm_device_dma_t *dma = dev->dma;
- if(dev->dev_private) {
+#if _HAVE_DMA_IRQ
+ /* 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);
+#endif
+
+ if (dev->dev_private) {
int i;
drm_i810_private_t *dev_priv =
(drm_i810_private_t *) dev->dev_private;
diff --git a/linux-core/i810_drv.h b/linux-core/i810_drv.h
index 27166449..aa82c647 100644
--- a/linux-core/i810_drv.h
+++ b/linux-core/i810_drv.h
@@ -38,8 +38,6 @@ typedef struct drm_i810_buf_priv {
int currently_mapped;
void *virtual;
void *kernel_virtual;
- int map_count;
- struct vm_area_struct *vma;
} drm_i810_buf_priv_t;
typedef struct _drm_i810_ring_buffer{
@@ -86,6 +84,7 @@ extern int i810_getbuf(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int i810_dma_init(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
+extern int i810_dma_cleanup(drm_device_t *dev);
extern int i810_flush_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern void i810_reclaim_buffers(struct file *filp);
diff --git a/linux-core/i830_dma.c b/linux-core/i830_dma.c
index d206d5b5..af9c1cb7 100644
--- a/linux-core/i830_dma.c
+++ b/linux-core/i830_dma.c
@@ -234,16 +234,24 @@ static int i830_dma_get_buffer(drm_device_t *dev, drm_i830_dma_t *d,
return retcode;
}
-static int i830_dma_cleanup(drm_device_t *dev)
+int i830_dma_cleanup(drm_device_t *dev)
{
drm_device_dma_t *dma = dev->dma;
- if(dev->dev_private) {
+#if _HAVE_DMA_IRQ
+ /* 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);
+#endif
+
+ if (dev->dev_private) {
int i;
drm_i830_private_t *dev_priv =
(drm_i830_private_t *) dev->dev_private;
- if(dev_priv->ring.virtual_start) {
+ if (dev_priv->ring.virtual_start) {
DRM(ioremapfree)((void *) dev_priv->ring.virtual_start,
dev_priv->ring.Size);
}
@@ -255,14 +263,6 @@ static int i830_dma_cleanup(drm_device_t *dev)
I830_WRITE(0x02080, 0x1ffff000);
}
- /* Disable interrupts here because after dev_private
- * is freed, it's too late.
- */
- if (dev->irq) {
- I830_WRITE16( I830REG_INT_MASK_R, 0xffff );
- I830_WRITE16( I830REG_INT_ENABLE_R, 0x0 );
- }
-
DRM(free)(dev->dev_private, sizeof(drm_i830_private_t),
DRM_MEM_DRIVER);
dev->dev_private = NULL;
diff --git a/linux-core/i830_drv.h b/linux-core/i830_drv.h
index 6b172ece..b611c133 100644
--- a/linux-core/i830_drv.h
+++ b/linux-core/i830_drv.h
@@ -38,8 +38,6 @@ typedef struct drm_i830_buf_priv {
int currently_mapped;
void *virtual;
void *kernel_virtual;
- int map_count;
- struct vm_area_struct *vma;
} drm_i830_buf_priv_t;
typedef struct _drm_i830_ring_buffer{
@@ -99,6 +97,7 @@ extern int i830_getbuf(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int i830_dma_init(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
+extern int i830_dma_cleanup(drm_device_t *dev);
extern int i830_flush_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern void i830_reclaim_buffers(struct file *filp);
diff --git a/linux-core/i830_irq.c b/linux-core/i830_irq.c
index cedafc0d..1fcd9f0a 100644
--- a/linux-core/i830_irq.c
+++ b/linux-core/i830_irq.c
@@ -41,12 +41,12 @@ void DRM(dma_service)(int irq, void *device, struct pt_regs *regs)
drm_device_t *dev = (drm_device_t *)device;
drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
u16 temp;
-
+
temp = I830_READ16(I830REG_INT_IDENTITY_R);
- printk("%s: %x\n", __FUNCTION__, temp);
-
- if(temp == 0)
- return;
+ DRM_DEBUG("%x\n", temp);
+
+ if (temp == 0)
+ return;
I830_WRITE16(I830REG_INT_IDENTITY_R, temp);
@@ -176,3 +176,34 @@ int i830_irq_wait( struct inode *inode, struct file *filp, unsigned int cmd,
return i830_wait_irq( dev, irqwait.irq_seq );
}
+
+/* drm_dma.h hooks
+*/
+void DRM(driver_irq_preinstall)( drm_device_t *dev ) {
+ drm_i830_private_t *dev_priv =
+ (drm_i830_private_t *)dev->dev_private;
+
+ I830_WRITE16( I830REG_HWSTAM, 0xffff );
+ I830_WRITE16( I830REG_INT_MASK_R, 0x0 );
+ I830_WRITE16( I830REG_INT_ENABLE_R, 0x0 );
+}
+
+void DRM(driver_irq_postinstall)( drm_device_t *dev ) {
+ drm_i830_private_t *dev_priv =
+ (drm_i830_private_t *)dev->dev_private;
+
+ I830_WRITE16( I830REG_INT_ENABLE_R, 0x2 );
+ atomic_set(&dev_priv->irq_received, 0);
+ atomic_set(&dev_priv->irq_emitted, 0);
+ init_waitqueue_head(&dev_priv->irq_queue);
+}
+
+void DRM(driver_irq_uninstall)( drm_device_t *dev ) {
+ drm_i830_private_t *dev_priv =
+ (drm_i830_private_t *)dev->dev_private;
+ if (!dev_priv)
+ return;
+
+ I830_WRITE16( I830REG_INT_MASK_R, 0xffff );
+ I830_WRITE16( I830REG_INT_ENABLE_R, 0x0 );
+}