From 291ffeae9a2b95cf35835ddd0f25e434e4c26f44 Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Thu, 10 Jun 2004 12:45:38 +0000 Subject: i915.o drm driver --- shared-core/i915_irq.c | 173 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 shared-core/i915_irq.c (limited to 'shared-core/i915_irq.c') diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c new file mode 100644 index 00000000..f9d5d4b7 --- /dev/null +++ b/shared-core/i915_irq.c @@ -0,0 +1,173 @@ +/* i915_dma.c -- DMA support for the I915 -*- linux-c -*- + */ +/************************************************************************** + * + * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + **************************************************************************/ + +#define __NO_VERSION__ +#include "i915.h" +#include "drmP.h" +#include "drm.h" +#include "i915_drm.h" +#include "i915_drv.h" + +#define USER_INT_FLAG 0x2 +#define MAX_NOPID ((u32)~0) +#define READ_BREADCRUMB(dev_priv) (((u32*)(dev_priv->hw_status_page))[5]) + + +irqreturn_t DRM(irq_handler)( DRM_IRQ_ARGS ) +{ + drm_device_t *dev = (drm_device_t *)arg; + drm_i915_private_t *dev_priv = (drm_i915_private_t *)dev->dev_private; + u16 temp; + + temp = I915_READ16(I915REG_INT_IDENTITY_R); + temp &= USER_INT_FLAG; + + DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp); + + if (temp == 0) + return IRQ_NONE; + + I915_WRITE16(I915REG_INT_IDENTITY_R, temp); + DRM_WAKEUP( &dev_priv->irq_queue ); + + return IRQ_HANDLED; +} + + +int i915_emit_irq(drm_device_t *dev) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + u32 ret; + RING_LOCALS; + + i915_kernel_lost_context(dev); + + DRM_DEBUG("%s\n", __FUNCTION__); + + ret = dev_priv->counter; + + BEGIN_LP_RING(2); + OUT_RING( 0 ); + OUT_RING( GFX_OP_USER_INTERRUPT ); + ADVANCE_LP_RING(); + + return ret; +} + + +int i915_wait_irq(drm_device_t *dev, int irq_nr) +{ + drm_i915_private_t *dev_priv = + (drm_i915_private_t *)dev->dev_private; + int ret = 0; + + DRM_DEBUG("%s irq_nr=%d breadcrumb=%d\n", __FUNCTION__, irq_nr, READ_BREADCRUMB(dev_priv)); + + if (READ_BREADCRUMB(dev_priv) >= irq_nr) + return 0; + + dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT; + + DRM_WAIT_ON( ret, dev_priv->irq_queue, 3 * DRM_HZ, + READ_BREADCRUMB(dev_priv) >= irq_nr ); + + if (ret == DRM_ERR(EBUSY)) { + DRM_ERROR("%s: EBUSY -- rec: %d emitted: %d\n", + __FUNCTION__, + READ_BREADCRUMB(dev_priv), + (int)dev_priv->counter); + } + + dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); + return ret; +} + + +/* Needs the lock as it touches the ring. + */ +int i915_irq_emit( DRM_IOCTL_ARGS ) +{ + DRM_DEVICE; + drm_i915_private_t *dev_priv = dev->dev_private; + drm_i915_irq_emit_t emit; + int result; + + if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { + DRM_ERROR("i915_irq_emit called without lock held\n"); + return DRM_ERR(EINVAL); + } + + if ( !dev_priv ) { + DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); + return DRM_ERR(EINVAL); + } + + DRM_COPY_FROM_USER_IOCTL( emit, (drm_i915_irq_emit_t *)data, + sizeof(emit) ); + + result = i915_emit_irq( dev ); + + if ( DRM_COPY_TO_USER( emit.irq_seq, &result, sizeof(int) ) ) { + DRM_ERROR( "copy_to_user\n" ); + return DRM_ERR(EFAULT); + } + + return 0; +} + + +/* Doesn't need the hardware lock. + */ +int i915_irq_wait( DRM_IOCTL_ARGS ) +{ + DRM_DEVICE; + drm_i915_private_t *dev_priv = dev->dev_private; + drm_i915_irq_wait_t irqwait; + + if ( !dev_priv ) { + DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); + return DRM_ERR(EINVAL); + } + + DRM_COPY_FROM_USER_IOCTL( irqwait, (drm_i915_irq_wait_t *)data, + sizeof(irqwait) ); + + return i915_wait_irq( dev, irqwait.irq_seq ); +} + + +/* drm_dma.h hooks +*/ +void DRM(driver_irq_preinstall)( drm_device_t *dev ) { + drm_i915_private_t *dev_priv = + (drm_i915_private_t *)dev->dev_private; + + I915_WRITE16( I915REG_HWSTAM, 0xfffe ); + I915_WRITE16( I915REG_INT_MASK_R, 0x0 ); + I915_WRITE16( I915REG_INT_ENABLE_R, 0x0 ); +} + +void DRM(driver_irq_postinstall)( drm_device_t *dev ) { + drm_i915_private_t *dev_priv = + (drm_i915_private_t *)dev->dev_private; + + I915_WRITE16( I915REG_INT_ENABLE_R, USER_INT_FLAG ); + DRM_INIT_WAITQUEUE(&dev_priv->irq_queue); +} + +void DRM(driver_irq_uninstall)( drm_device_t *dev ) { + drm_i915_private_t *dev_priv = + (drm_i915_private_t *)dev->dev_private; + if (!dev_priv) + return; + + I915_WRITE16( I915REG_HWSTAM, 0xffff ); + I915_WRITE16( I915REG_INT_MASK_R, 0xffff ); + I915_WRITE16( I915REG_INT_ENABLE_R, 0x0 ); +} -- cgit v1.2.3