#if __FreeBSD_version >= 400005
struct task task;
#endif
+#if __HAVE_VBL_IRQ
+ wait_queue_head_t vbl_queue; /* vbl wait channel */
+ atomic_t vbl_received;
+#endif
cycles_t ctx_start;
cycles_t lck_start;
#if __HAVE_DMA_HISTOGRAM
extern int DRM(irq_install)( drm_device_t *dev, int irq );
extern int DRM(irq_uninstall)( drm_device_t *dev );
extern void DRM(dma_service)( DRM_IRQ_ARGS );
+extern void DRM(driver_irq_preinstall)( drm_device_t *dev );
+extern void DRM(driver_irq_postinstall)( drm_device_t *dev );
+extern void DRM(driver_irq_uninstall)( drm_device_t *dev );
#if __HAVE_DMA_IRQ_BH
extern void DRM(dma_immediate_bh)( DRM_TASKQUEUE_ARGS );
#endif
extern drm_buf_t *DRM(freelist_get)(drm_freelist_t *bl, int block);
#endif
#endif /* __HAVE_DMA */
+#if __HAVE_VBL_IRQ
+extern int DRM(vblank_wait)(drm_device_t *dev, unsigned int *vbl_seq);
+#endif
#if __REALLY_HAVE_AGP
/* AGP/GART support (drm_agpsupport.h) */
#endif
/* Before installing handler */
- DRIVER_PREINSTALL();
+ DRM(driver_irq_preinstall)( dev );
/* Install handler */
rid = 0;
}
/* After installing handler */
- DRIVER_POSTINSTALL();
+ DRM(driver_irq_postinstall)( dev );
return 0;
}
DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, irq );
- DRIVER_UNINSTALL();
+ DRM(driver_irq_uninstall)( dev );
bus_teardown_intr(dev->device, dev->irqr, dev->irqh);
bus_release_resource(dev->device, SYS_RES_IRQ, 0, dev->irqr);
}
}
+#if __HAVE_VBL_IRQ
+
+int DRM(vblank_wait)(drm_device_t *dev, unsigned int *sequence)
+{
+ unsigned int cur_vblank;
+ int ret = 0;
+
+ /* Assume that the user has missed the current sequence number by about
+ * a day rather than she wants to wait for years using vertical blanks :)
+ */
+ while ( ( ( cur_vblank = atomic_read(&dev->vbl_received ) )
+ + ~*sequence + 1 ) > (1<<23) ) {
+ ret = tsleep( &dev->vbl_queue, 3*hz, "rdnvbl", PZERO | PCATCH);
+ if (ret)
+ break;
+ }
+
+ *sequence = cur_vblank;
+
+ return ret;
+}
+
+int DRM(wait_vblank)( DRM_IOCTL_ARGS )
+{
+ DRM_DEVICE;
+ drm_wait_vblank_t vblwait;
+ struct timeval now;
+ int ret;
+
+ if (!dev->irq)
+ return DRM_ERR(EINVAL);
+
+ DRM_COPY_FROM_USER_IOCTL( vblwait, (drm_wait_vblank_t *)data,
+ sizeof(vblwait) );
+
+ if ( vblwait.type == _DRM_VBLANK_RELATIVE ) {
+ vblwait.sequence += atomic_read( &dev->vbl_received );
+ }
+
+ ret = DRM(vblank_wait)( dev, &vblwait.sequence );
+
+ microtime( &now );
+ vblwait.tval_sec = now.tv_sec;
+ vblwait.tval_usec = now.tv_usec;
+
+ DRM_COPY_TO_USER_IOCTL( (drm_wait_vblank_t *)data, vblwait,
+ sizeof(vblwait) );
+
+ return ret;
+}
+#endif /* __HAVE_VBL_IRQ */
+
#else
int DRM(control)( DRM_IOCTL_ARGS )
#endif /* __HAVE_DMA_IRQ */
#endif /* __HAVE_DMA */
+
[DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] = { DRM(sg_free), 1, 1 },
#endif
+#if __HAVE_VBL_IRQ
+ [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)] = { DRM(wait_vblank), 0, 0 },
+#endif
+
DRIVER_IOCTLS
};
#if __HAVE_DMA
extern d_ioctl_t DRM(control);
#endif
+#if __HAVE_VBL_IRQ
+extern d_ioctl_t DRM(wait_vblank);
+#endif
/* AGP/GART support (drm_agpsupport.h) */
#if __REALLY_HAVE_AGP
int funcnum;
} drm_irq_busid_t;
+typedef enum {
+ _DRM_VBLANK_ABSOLUTE = 0x0, /* Wait for specific vblank sequence number */
+ _DRM_VBLANK_RELATIVE = 0x1 /* Wait for given number of vblanks */
+} drm_vblank_seq_type_t;
+
+typedef struct drm_radeon_vbl_wait {
+ drm_vblank_seq_type_t type;
+ unsigned int sequence;
+ long tval_sec;
+ long tval_usec;
+} drm_wait_vblank_t;
+
typedef struct drm_agp_mode {
unsigned long mode;
} drm_agp_mode_t;
#define DRM_IOCTL_SG_ALLOC DRM_IOW( 0x38, drm_scatter_gather_t)
#define DRM_IOCTL_SG_FREE DRM_IOW( 0x39, drm_scatter_gather_t)
+#define DRM_IOCTL_WAIT_VBLANK DRM_IOWR(0x3a, drm_wait_vblank_t)
+
/* Device specfic ioctls should only be in their respective headers
* The device specific ioctl range is 0x40 to 0x79. */
#define DRM_COMMAND_BASE 0x40
#if __FreeBSD_version >= 400005
struct task task;
#endif
+#if __HAVE_VBL_IRQ
+ wait_queue_head_t vbl_queue; /* vbl wait channel */
+ atomic_t vbl_received;
+#endif
cycles_t ctx_start;
cycles_t lck_start;
#if __HAVE_DMA_HISTOGRAM
extern int DRM(irq_install)( drm_device_t *dev, int irq );
extern int DRM(irq_uninstall)( drm_device_t *dev );
extern void DRM(dma_service)( DRM_IRQ_ARGS );
+extern void DRM(driver_irq_preinstall)( drm_device_t *dev );
+extern void DRM(driver_irq_postinstall)( drm_device_t *dev );
+extern void DRM(driver_irq_uninstall)( drm_device_t *dev );
#if __HAVE_DMA_IRQ_BH
extern void DRM(dma_immediate_bh)( DRM_TASKQUEUE_ARGS );
#endif
extern drm_buf_t *DRM(freelist_get)(drm_freelist_t *bl, int block);
#endif
#endif /* __HAVE_DMA */
+#if __HAVE_VBL_IRQ
+extern int DRM(vblank_wait)(drm_device_t *dev, unsigned int *vbl_seq);
+#endif
#if __REALLY_HAVE_AGP
/* AGP/GART support (drm_agpsupport.h) */
#endif
/* Before installing handler */
- DRIVER_PREINSTALL();
+ DRM(driver_irq_preinstall)( dev );
/* Install handler */
rid = 0;
}
/* After installing handler */
- DRIVER_POSTINSTALL();
+ DRM(driver_irq_postinstall)( dev );
return 0;
}
DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, irq );
- DRIVER_UNINSTALL();
+ DRM(driver_irq_uninstall)( dev );
bus_teardown_intr(dev->device, dev->irqr, dev->irqh);
bus_release_resource(dev->device, SYS_RES_IRQ, 0, dev->irqr);
}
}
+#if __HAVE_VBL_IRQ
+
+int DRM(vblank_wait)(drm_device_t *dev, unsigned int *sequence)
+{
+ unsigned int cur_vblank;
+ int ret = 0;
+
+ /* Assume that the user has missed the current sequence number by about
+ * a day rather than she wants to wait for years using vertical blanks :)
+ */
+ while ( ( ( cur_vblank = atomic_read(&dev->vbl_received ) )
+ + ~*sequence + 1 ) > (1<<23) ) {
+ ret = tsleep( &dev->vbl_queue, 3*hz, "rdnvbl", PZERO | PCATCH);
+ if (ret)
+ break;
+ }
+
+ *sequence = cur_vblank;
+
+ return ret;
+}
+
+int DRM(wait_vblank)( DRM_IOCTL_ARGS )
+{
+ DRM_DEVICE;
+ drm_wait_vblank_t vblwait;
+ struct timeval now;
+ int ret;
+
+ if (!dev->irq)
+ return DRM_ERR(EINVAL);
+
+ DRM_COPY_FROM_USER_IOCTL( vblwait, (drm_wait_vblank_t *)data,
+ sizeof(vblwait) );
+
+ if ( vblwait.type == _DRM_VBLANK_RELATIVE ) {
+ vblwait.sequence += atomic_read( &dev->vbl_received );
+ }
+
+ ret = DRM(vblank_wait)( dev, &vblwait.sequence );
+
+ microtime( &now );
+ vblwait.tval_sec = now.tv_sec;
+ vblwait.tval_usec = now.tv_usec;
+
+ DRM_COPY_TO_USER_IOCTL( (drm_wait_vblank_t *)data, vblwait,
+ sizeof(vblwait) );
+
+ return ret;
+}
+#endif /* __HAVE_VBL_IRQ */
+
#else
int DRM(control)( DRM_IOCTL_ARGS )
#endif /* __HAVE_DMA_IRQ */
#endif /* __HAVE_DMA */
+
[DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] = { DRM(sg_free), 1, 1 },
#endif
+#if __HAVE_VBL_IRQ
+ [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)] = { DRM(wait_vblank), 0, 0 },
+#endif
+
DRIVER_IOCTLS
};
#if __HAVE_DMA
extern d_ioctl_t DRM(control);
#endif
+#if __HAVE_VBL_IRQ
+extern d_ioctl_t DRM(wait_vblank);
+#endif
/* AGP/GART support (drm_agpsupport.h) */
#if __REALLY_HAVE_AGP
#define __HAVE_DMA_IRQ 1
#define __HAVE_DMA_IRQ_BH 1
-#define DRIVER_PREINSTALL() do { \
- drm_gamma_private_t *dev_priv = \
- (drm_gamma_private_t *)dev->dev_private;\
- GAMMA_WRITE( GAMMA_GCOMMANDMODE, 0x00000000 ); \
- GAMMA_WRITE( GAMMA_GDMACONTROL, 0x00000000 ); \
-} while (0)
-
-#define DRIVER_POSTINSTALL() do { \
- drm_gamma_private_t *dev_priv = \
- (drm_gamma_private_t *)dev->dev_private;\
- GAMMA_WRITE( GAMMA_GINTENABLE, 0x00002001 ); \
- GAMMA_WRITE( GAMMA_COMMANDINTENABLE, 0x00000008 ); \
- GAMMA_WRITE( GAMMA_GDELAYTIMER, 0x00039090 ); \
-} while (0)
-
-#define DRIVER_UNINSTALL() do { \
- drm_gamma_private_t *dev_priv = \
- (drm_gamma_private_t *)dev->dev_private;\
- GAMMA_WRITE( GAMMA_GDELAYTIMER, 0x00000000 ); \
- GAMMA_WRITE( GAMMA_COMMANDINTENABLE, 0x00000000 ); \
- GAMMA_WRITE( GAMMA_GINTENABLE, 0x00000000 ); \
-} while (0)
#endif /* __GAMMA_H__ */
return retcode;
}
+
+void DRM(driver_irq_preinstall)(drm_device_t *dev) {
+ drm_gamma_private_t *dev_priv =
+ (drm_gamma_private_t *)dev->dev_private;
+#if 1
+ while(GAMMA_READ(GAMMA_INFIFOSPACE) < 2);
+ GAMMA_WRITE( GAMMA_GCOMMANDMODE, 0x00000004 );
+ GAMMA_WRITE( GAMMA_GDMACONTROL, 0x00000000 );
+#else
+ while(GAMMA_READ(GAMMA_INFIFOSPACE) < 2);
+ while(GAMMA_READ(GAMMA_INFIFOSPACE) < 2);
+ GAMMA_WRITE( GAMMA_GCOMMANDMODE, GAMMA_QUEUED_DMA_MODE );
+ GAMMA_WRITE( GAMMA_GDMACONTROL, 0x00000000 );
+#endif
+}
+
+void DRM(driver_irq_postinstall)(drm_device_t *dev) {
+ drm_gamma_private_t *dev_priv =
+ (drm_gamma_private_t *)dev->dev_private;
+#if 1
+ while(GAMMA_READ(GAMMA_INFIFOSPACE) < 2);
+ while(GAMMA_READ(GAMMA_INFIFOSPACE) < 3);
+ GAMMA_WRITE( GAMMA_GINTENABLE, 0x00002001 );
+ GAMMA_WRITE( GAMMA_COMMANDINTENABLE, 0x00000008 );
+ GAMMA_WRITE( GAMMA_GDELAYTIMER, 0x00039090 );
+#else
+ while(GAMMA_READ(GAMMA_INFIFOSPACE) < 2);
+ while(GAMMA_READ(GAMMA_INFIFOSPACE) < 2);
+ GAMMA_WRITE( GAMMA_GINTENABLE, 0x00002000 );
+ GAMMA_WRITE( GAMMA_COMMANDINTENABLE, 0x00000004 );
+#endif
+}
+
+void DRM(driver_irq_uninstall)( drm_device_t *dev ) {
+ drm_gamma_private_t *dev_priv =
+ (drm_gamma_private_t *)dev->dev_private;
+ while(GAMMA_READ(GAMMA_INFIFOSPACE) < 2);
+ while(GAMMA_READ(GAMMA_INFIFOSPACE) < 3);
+ GAMMA_WRITE( GAMMA_GDELAYTIMER, 0x00000000 );
+ GAMMA_WRITE( GAMMA_COMMANDINTENABLE, 0x00000000 );
+ GAMMA_WRITE( GAMMA_GINTENABLE, 0x00000000 );
+}
extern int radeon_emit_and_wait_irq(drm_device_t *dev);
extern int radeon_wait_irq(drm_device_t *dev, int swi_nr);
extern int radeon_emit_irq(drm_device_t *dev);
-extern int radeon_vblank_wait(drm_device_t *dev, unsigned int *vbl_seq);
/* Flags for stats.boxes
extern int radeon_emit_and_wait_irq(drm_device_t *dev);
extern int radeon_wait_irq(drm_device_t *dev, int swi_nr);
extern int radeon_emit_irq(drm_device_t *dev);
-extern int radeon_vblank_wait(drm_device_t *dev, unsigned int *vbl_seq);
/* Flags for stats.boxes