1 /* i915_irq.c -- IRQ support for the I915 -*- linux-c -*-
4 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the
9 * "Software"), to deal in the Software without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sub license, and/or sell copies of the Software, and to
12 * permit persons to whom the Software is furnished to do so, subject to
13 * the following conditions:
15 * The above copyright notice and this permission notice (including the
16 * next paragraph) shall be included in all copies or substantial portions
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
23 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
32 #include "dev/drm/drmP.h"
33 #include "dev/drm/drm.h"
34 #include "dev/drm/i915_drm.h"
35 #include "dev/drm/i915_drv.h"
37 #define USER_INT_FLAG 0x2
38 #define MAX_NOPID ((u32)~0)
39 #define READ_BREADCRUMB(dev_priv) (((u32*)(dev_priv->hw_status_page))[5])
41 irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
43 drm_device_t *dev = (drm_device_t *) arg;
44 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
47 temp = I915_READ16(I915REG_INT_IDENTITY_R);
48 temp &= USER_INT_FLAG;
50 DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp);
55 I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
56 DRM_WAKEUP(&dev_priv->irq_queue);
61 static int i915_emit_irq(drm_device_t * dev)
63 drm_i915_private_t *dev_priv = dev->dev_private;
67 i915_kernel_lost_context(dev);
69 DRM_DEBUG("%s\n", __FUNCTION__);
71 ret = dev_priv->counter;
75 OUT_RING(GFX_OP_USER_INTERRUPT);
81 static int i915_wait_irq(drm_device_t * dev, int irq_nr)
83 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
86 DRM_DEBUG("%s irq_nr=%d breadcrumb=%d\n", __FUNCTION__, irq_nr,
87 READ_BREADCRUMB(dev_priv));
89 if (READ_BREADCRUMB(dev_priv) >= irq_nr)
92 dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
94 DRM_WAIT_ON(ret, dev_priv->irq_queue, 3 * DRM_HZ,
95 READ_BREADCRUMB(dev_priv) >= irq_nr);
97 if (ret == DRM_ERR(EBUSY)) {
98 DRM_ERROR("%s: EBUSY -- rec: %d emitted: %d\n",
100 READ_BREADCRUMB(dev_priv), (int)dev_priv->counter);
103 dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
107 /* Needs the lock as it touches the ring.
109 int i915_irq_emit(DRM_IOCTL_ARGS)
112 drm_i915_private_t *dev_priv = dev->dev_private;
113 drm_i915_irq_emit_t emit;
116 LOCK_TEST_WITH_RETURN(dev, filp);
119 DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
120 return DRM_ERR(EINVAL);
123 DRM_COPY_FROM_USER_IOCTL(emit, (drm_i915_irq_emit_t __user *) data,
126 result = i915_emit_irq(dev);
128 if (DRM_COPY_TO_USER(emit.irq_seq, &result, sizeof(int))) {
129 DRM_ERROR("copy_to_user\n");
130 return DRM_ERR(EFAULT);
136 /* Doesn't need the hardware lock.
138 int i915_irq_wait(DRM_IOCTL_ARGS)
141 drm_i915_private_t *dev_priv = dev->dev_private;
142 drm_i915_irq_wait_t irqwait;
145 DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
146 return DRM_ERR(EINVAL);
149 DRM_COPY_FROM_USER_IOCTL(irqwait, (drm_i915_irq_wait_t __user *) data,
152 return i915_wait_irq(dev, irqwait.irq_seq);
157 void i915_driver_irq_preinstall(drm_device_t * dev)
159 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
161 I915_WRITE16(I915REG_HWSTAM, 0xfffe);
162 I915_WRITE16(I915REG_INT_MASK_R, 0x0);
163 I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
166 void i915_driver_irq_postinstall(drm_device_t * dev)
168 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
170 I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG);
171 DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
174 void i915_driver_irq_uninstall(drm_device_t * dev)
176 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
180 I915_WRITE16(I915REG_HWSTAM, 0xffff);
181 I915_WRITE16(I915REG_INT_MASK_R, 0xffff);
182 I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);