aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/drm/i915_irq.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/char/drm/i915_irq.c
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'drivers/char/drm/i915_irq.c')
-rw-r--r--drivers/char/drm/i915_irq.c161
1 files changed, 161 insertions, 0 deletions
diff --git a/drivers/char/drm/i915_irq.c b/drivers/char/drm/i915_irq.c
new file mode 100644
index 000000000000..b0239262a84a
--- /dev/null
+++ b/drivers/char/drm/i915_irq.c
@@ -0,0 +1,161 @@
1/* i915_dma.c -- DMA support for the I915 -*- linux-c -*-
2 */
3/**************************************************************************
4 *
5 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
6 * All Rights Reserved.
7 *
8 **************************************************************************/
9
10#include "drmP.h"
11#include "drm.h"
12#include "i915_drm.h"
13#include "i915_drv.h"
14
15#define USER_INT_FLAG 0x2
16#define MAX_NOPID ((u32)~0)
17#define READ_BREADCRUMB(dev_priv) (((u32*)(dev_priv->hw_status_page))[5])
18
19irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
20{
21 drm_device_t *dev = (drm_device_t *) arg;
22 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
23 u16 temp;
24
25 temp = I915_READ16(I915REG_INT_IDENTITY_R);
26 temp &= USER_INT_FLAG;
27
28 DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp);
29
30 if (temp == 0)
31 return IRQ_NONE;
32
33 I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
34 DRM_WAKEUP(&dev_priv->irq_queue);
35
36 return IRQ_HANDLED;
37}
38
39int i915_emit_irq(drm_device_t * dev)
40{
41 drm_i915_private_t *dev_priv = dev->dev_private;
42 u32 ret;
43 RING_LOCALS;
44
45 i915_kernel_lost_context(dev);
46
47 DRM_DEBUG("%s\n", __FUNCTION__);
48
49 ret = dev_priv->counter;
50
51 BEGIN_LP_RING(2);
52 OUT_RING(0);
53 OUT_RING(GFX_OP_USER_INTERRUPT);
54 ADVANCE_LP_RING();
55
56 return ret;
57}
58
59int i915_wait_irq(drm_device_t * dev, int irq_nr)
60{
61 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
62 int ret = 0;
63
64 DRM_DEBUG("%s irq_nr=%d breadcrumb=%d\n", __FUNCTION__, irq_nr,
65 READ_BREADCRUMB(dev_priv));
66
67 if (READ_BREADCRUMB(dev_priv) >= irq_nr)
68 return 0;
69
70 dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
71
72 DRM_WAIT_ON(ret, dev_priv->irq_queue, 3 * DRM_HZ,
73 READ_BREADCRUMB(dev_priv) >= irq_nr);
74
75 if (ret == DRM_ERR(EBUSY)) {
76 DRM_ERROR("%s: EBUSY -- rec: %d emitted: %d\n",
77 __FUNCTION__,
78 READ_BREADCRUMB(dev_priv), (int)dev_priv->counter);
79 }
80
81 dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
82 return ret;
83}
84
85/* Needs the lock as it touches the ring.
86 */
87int i915_irq_emit(DRM_IOCTL_ARGS)
88{
89 DRM_DEVICE;
90 drm_i915_private_t *dev_priv = dev->dev_private;
91 drm_i915_irq_emit_t emit;
92 int result;
93
94 LOCK_TEST_WITH_RETURN(dev, filp);
95
96 if (!dev_priv) {
97 DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
98 return DRM_ERR(EINVAL);
99 }
100
101 DRM_COPY_FROM_USER_IOCTL(emit, (drm_i915_irq_emit_t __user *) data,
102 sizeof(emit));
103
104 result = i915_emit_irq(dev);
105
106 if (DRM_COPY_TO_USER(emit.irq_seq, &result, sizeof(int))) {
107 DRM_ERROR("copy_to_user\n");
108 return DRM_ERR(EFAULT);
109 }
110
111 return 0;
112}
113
114/* Doesn't need the hardware lock.
115 */
116int i915_irq_wait(DRM_IOCTL_ARGS)
117{
118 DRM_DEVICE;
119 drm_i915_private_t *dev_priv = dev->dev_private;
120 drm_i915_irq_wait_t irqwait;
121
122 if (!dev_priv) {
123 DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
124 return DRM_ERR(EINVAL);
125 }
126
127 DRM_COPY_FROM_USER_IOCTL(irqwait, (drm_i915_irq_wait_t __user *) data,
128 sizeof(irqwait));
129
130 return i915_wait_irq(dev, irqwait.irq_seq);
131}
132
133/* drm_dma.h hooks
134*/
135void i915_driver_irq_preinstall(drm_device_t * dev)
136{
137 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
138
139 I915_WRITE16(I915REG_HWSTAM, 0xfffe);
140 I915_WRITE16(I915REG_INT_MASK_R, 0x0);
141 I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
142}
143
144void i915_driver_irq_postinstall(drm_device_t * dev)
145{
146 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
147
148 I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG);
149 DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
150}
151
152void i915_driver_irq_uninstall(drm_device_t * dev)
153{
154 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
155 if (!dev_priv)
156 return;
157
158 I915_WRITE16(I915REG_HWSTAM, 0xffff);
159 I915_WRITE16(I915REG_INT_MASK_R, 0xffff);
160 I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
161}