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;
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;
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{
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);
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);
}
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;
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{
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);
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);
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 );
+}
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;
#define __HAVE_COUNTER9 _DRM_STAT_SPECIAL
#define __HAVE_COUNTER10 _DRM_STAT_MISSED
+/* Driver customization:
+ */
+#define DRIVER_PRETAKEDOWN() do { \
+ gamma_do_cleanup_dma( dev ); \
+} while (0)
+
/* DMA customization:
*/
#define __HAVE_DMA 1
{
DRM_DEBUG( "%s\n", __FUNCTION__ );
+#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 ) {
drm_gamma_private_t *dev_priv = dev->dev_private;
drm_device_t *dev = priv->dev;
drm_gamma_init_t init;
+ LOCK_TEST_WITH_RETURN( dev, filp );
+
if ( copy_from_user( &init, (drm_gamma_init_t *)arg, sizeof(init) ) )
return -EFAULT;
void DRM(driver_irq_uninstall)( drm_device_t *dev ) {
drm_gamma_private_t *dev_priv =
(drm_gamma_private_t *)dev->dev_private;
+ if (!dev_priv)
+ return;
while(GAMMA_READ(GAMMA_INFIFOSPACE) < 3);
extern int gamma_dma_copy( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg );
+extern int gamma_do_cleanup_dma( drm_device_t *dev );
extern void gamma_dma_ready(drm_device_t *dev);
extern void gamma_dma_quiescent_single(drm_device_t *dev);
extern void gamma_dma_quiescent_dual(drm_device_t *dev);
*/
#define __HAVE_RELEASE 1
#define DRIVER_RELEASE() do { \
- i810_reclaim_buffers( filp ); \
+ i810_reclaim_buffers( filp ); \
+} while (0)
+
+#define DRIVER_PRETAKEDOWN() do { \
+ i810_dma_cleanup( dev ); \
} while (0)
/* DMA customization:
/* Don't need an irq any more. The template code will make sure that
* a noop stub is generated for compatibility.
*/
+/* XXX: Add vblank support? */
#define __HAVE_DMA_IRQ 0
/* Buffer customization:
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;
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{
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);
*/
#define __HAVE_RELEASE 1
#define DRIVER_RELEASE() do { \
- i830_reclaim_buffers( filp ); \
+ i830_reclaim_buffers( filp ); \
+} while (0)
+
+#define DRIVER_PRETAKEDOWN() do { \
+ i830_dma_cleanup( dev ); \
} while (0)
/* DMA customization:
* the card, but are subject to subtle interactions between bios,
* hardware and the driver.
*/
+/* XXX: Add vblank support? */
#define USE_IRQS 0
-
#if USE_IRQS
#define __HAVE_DMA_IRQ 1
#define __HAVE_SHARED_IRQ 1
-
-#define DRIVER_PREINSTALL() do { \
- 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 ); \
-} while (0)
-
-
-#define DRIVER_POSTINSTALL() do { \
- 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); \
-} while (0)
-
-
-/* This gets called too late to be useful: dev_priv has already been
- * freed.
- */
-#define DRIVER_UNINSTALL() do { \
-} while (0)
-
#else
#define __HAVE_DMA_IRQ 0
#endif
-
/* Buffer customization:
*/
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);
}
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;
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{
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);
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);
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 );
+}
{
DRM_DEBUG( "\n" );
+#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 ) {
drm_mga_private_t *dev_priv = dev->dev_private;
DRM_DEVICE;
drm_mga_init_t init;
+ LOCK_TEST_WITH_RETURN( dev, filp );
+
DRM_COPY_FROM_USER_IOCTL( init, (drm_mga_init_t *)data, sizeof(init) );
switch ( init.func ) {
void mga_driver_irq_uninstall( drm_device_t *dev ) {
drm_mga_private_t *dev_priv =
(drm_mga_private_t *)dev->dev_private;
- if ( dev_priv ) {
- /* Disable *all* interrupts */
- MGA_WRITE( MGA_IEN, 0 );
- }
+ if (!dev_priv)
+ return;
+
+ /* Disable *all* interrupts */
+ MGA_WRITE( MGA_IEN, 0 );
}
int r128_do_cleanup_cce( drm_device_t *dev )
{
+
+#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 ) {
drm_r128_private_t *dev_priv = dev->dev_private;
DRM_DEBUG( "\n" );
+ LOCK_TEST_WITH_RETURN( dev, filp );
+
DRM_COPY_FROM_USER_IOCTL( init, (drm_r128_init_t *)data, sizeof(init) );
switch ( init.func ) {
void r128_driver_irq_uninstall( drm_device_t *dev ) {
drm_r128_private_t *dev_priv =
(drm_r128_private_t *)dev->dev_private;
- if ( dev_priv ) {
- /* Disable *all* interrupts */
- R128_WRITE( R128_GEN_INT_CNTL, 0 );
- }
+ if (!dev_priv)
+ return;
+
+ /* Disable *all* interrupts */
+ R128_WRITE( R128_GEN_INT_CNTL, 0 );
}
{
DRM_DEBUG( "\n" );
+#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 ) {
drm_radeon_private_t *dev_priv = dev->dev_private;
DRM_DEVICE;
drm_radeon_init_t init;
+ LOCK_TEST_WITH_RETURN( dev, filp );
+
DRM_COPY_FROM_USER_IOCTL( init, (drm_radeon_init_t *)data, sizeof(init) );
switch ( init.func ) {
void DRM(driver_irq_uninstall)( drm_device_t *dev ) {
drm_radeon_private_t *dev_priv =
(drm_radeon_private_t *)dev->dev_private;
- if ( dev_priv ) {
- /* Disable *all* interrupts */
- RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 );
- }
+ if (!dev_priv)
+ return;
+
+ /* Disable *all* interrupts */
+ RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 );
}
/* Driver customization:
*/
#define DRIVER_PRETAKEDOWN() do { \
- if ( dev->dev_private ) mga_do_cleanup_dma( dev ); \
+ mga_do_cleanup_dma( dev ); \
} while (0)
/* DMA customization:
{
DRM_DEBUG( "\n" );
+#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 ) {
drm_mga_private_t *dev_priv = dev->dev_private;
DRM_DEVICE;
drm_mga_init_t init;
+ LOCK_TEST_WITH_RETURN( dev, filp );
+
DRM_COPY_FROM_USER_IOCTL( init, (drm_mga_init_t *)data, sizeof(init) );
switch ( init.func ) {
void mga_driver_irq_uninstall( drm_device_t *dev ) {
drm_mga_private_t *dev_priv =
(drm_mga_private_t *)dev->dev_private;
- if ( dev_priv ) {
- /* Disable *all* interrupts */
- MGA_WRITE( MGA_IEN, 0 );
- }
+ if (!dev_priv)
+ return;
+
+ /* Disable *all* interrupts */
+ MGA_WRITE( MGA_IEN, 0 );
}
} while (0)
#define DRIVER_PRETAKEDOWN() do { \
- if ( dev->dev_private ) r128_do_cleanup_cce( dev ); \
+ r128_do_cleanup_cce( dev ); \
} while (0)
/* DMA customization:
int r128_do_cleanup_cce( drm_device_t *dev )
{
+
+#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 ) {
drm_r128_private_t *dev_priv = dev->dev_private;
DRM_DEBUG( "\n" );
+ LOCK_TEST_WITH_RETURN( dev, filp );
+
DRM_COPY_FROM_USER_IOCTL( init, (drm_r128_init_t *)data, sizeof(init) );
switch ( init.func ) {
void r128_driver_irq_uninstall( drm_device_t *dev ) {
drm_r128_private_t *dev_priv =
(drm_r128_private_t *)dev->dev_private;
- if ( dev_priv ) {
- /* Disable *all* interrupts */
- R128_WRITE( R128_GEN_INT_CNTL, 0 );
- }
+ if (!dev_priv)
+ return;
+
+ /* Disable *all* interrupts */
+ R128_WRITE( R128_GEN_INT_CNTL, 0 );
}
{
DRM_DEBUG( "\n" );
+#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 ) {
drm_radeon_private_t *dev_priv = dev->dev_private;
DRM_DEVICE;
drm_radeon_init_t init;
+ LOCK_TEST_WITH_RETURN( dev, filp );
+
DRM_COPY_FROM_USER_IOCTL( init, (drm_radeon_init_t *)data, sizeof(init) );
switch ( init.func ) {
void DRM(driver_irq_uninstall)( drm_device_t *dev ) {
drm_radeon_private_t *dev_priv =
(drm_radeon_private_t *)dev->dev_private;
- if ( dev_priv ) {
- /* Disable *all* interrupts */
- RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 );
- }
+ if (!dev_priv)
+ return;
+
+ /* Disable *all* interrupts */
+ RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 );
}