]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/drm/i915_irq.c
This commit was generated by cvs2svn to compensate for changes in r146611,
[FreeBSD/FreeBSD.git] / sys / dev / drm / i915_irq.c
1 /* i915_dma.c -- DMA support for the I915 -*- linux-c -*-
2  *
3  * $FreeBSD$
4  */
5 /**************************************************************************
6  *
7  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
8  * All Rights Reserved.
9  *
10  **************************************************************************/
11
12 #include "drmP.h"
13 #include "drm.h"
14 #include "i915_drm.h"
15 #include "i915_drv.h"
16
17 #define USER_INT_FLAG 0x2
18 #define MAX_NOPID ((u32)~0)
19 #define READ_BREADCRUMB(dev_priv)  (((u32*)(dev_priv->hw_status_page))[5])
20
21 irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
22 {
23         drm_device_t *dev = (drm_device_t *) arg;
24         drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
25         u16 temp;
26
27         temp = I915_READ16(I915REG_INT_IDENTITY_R);
28         temp &= USER_INT_FLAG;
29
30         DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp);
31
32         if (temp == 0)
33                 return IRQ_NONE;
34
35         I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
36         DRM_WAKEUP(&dev_priv->irq_queue);
37
38         return IRQ_HANDLED;
39 }
40
41 static int i915_emit_irq(drm_device_t * dev)
42 {
43         drm_i915_private_t *dev_priv = dev->dev_private;
44         u32 ret;
45         RING_LOCALS;
46
47         i915_kernel_lost_context(dev);
48
49         DRM_DEBUG("%s\n", __FUNCTION__);
50
51         ret = dev_priv->counter;
52
53         BEGIN_LP_RING(2);
54         OUT_RING(0);
55         OUT_RING(GFX_OP_USER_INTERRUPT);
56         ADVANCE_LP_RING();
57
58         return ret;
59 }
60
61 static int i915_wait_irq(drm_device_t * dev, int irq_nr)
62 {
63         drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
64         int ret = 0;
65
66         DRM_DEBUG("%s irq_nr=%d breadcrumb=%d\n", __FUNCTION__, irq_nr,
67                   READ_BREADCRUMB(dev_priv));
68
69         if (READ_BREADCRUMB(dev_priv) >= irq_nr)
70                 return 0;
71
72         dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
73
74         DRM_WAIT_ON(ret, dev_priv->irq_queue, 3 * DRM_HZ,
75                     READ_BREADCRUMB(dev_priv) >= irq_nr);
76
77         if (ret == DRM_ERR(EBUSY)) {
78                 DRM_ERROR("%s: EBUSY -- rec: %d emitted: %d\n",
79                           __FUNCTION__,
80                           READ_BREADCRUMB(dev_priv), (int)dev_priv->counter);
81         }
82
83         dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
84         return ret;
85 }
86
87 /* Needs the lock as it touches the ring.
88  */
89 int i915_irq_emit(DRM_IOCTL_ARGS)
90 {
91         DRM_DEVICE;
92         drm_i915_private_t *dev_priv = dev->dev_private;
93         drm_i915_irq_emit_t emit;
94         int result;
95
96         LOCK_TEST_WITH_RETURN(dev, filp);
97
98         if (!dev_priv) {
99                 DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
100                 return DRM_ERR(EINVAL);
101         }
102
103         DRM_COPY_FROM_USER_IOCTL(emit, (drm_i915_irq_emit_t __user *) data,
104                                  sizeof(emit));
105
106         result = i915_emit_irq(dev);
107
108         if (DRM_COPY_TO_USER(emit.irq_seq, &result, sizeof(int))) {
109                 DRM_ERROR("copy_to_user\n");
110                 return DRM_ERR(EFAULT);
111         }
112
113         return 0;
114 }
115
116 /* Doesn't need the hardware lock.
117  */
118 int i915_irq_wait(DRM_IOCTL_ARGS)
119 {
120         DRM_DEVICE;
121         drm_i915_private_t *dev_priv = dev->dev_private;
122         drm_i915_irq_wait_t irqwait;
123
124         if (!dev_priv) {
125                 DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
126                 return DRM_ERR(EINVAL);
127         }
128
129         DRM_COPY_FROM_USER_IOCTL(irqwait, (drm_i915_irq_wait_t __user *) data,
130                                  sizeof(irqwait));
131
132         return i915_wait_irq(dev, irqwait.irq_seq);
133 }
134
135 /* drm_dma.h hooks
136 */
137 void i915_driver_irq_preinstall(drm_device_t * dev)
138 {
139         drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
140
141         I915_WRITE16(I915REG_HWSTAM, 0xfffe);
142         I915_WRITE16(I915REG_INT_MASK_R, 0x0);
143         I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
144 }
145
146 void i915_driver_irq_postinstall(drm_device_t * dev)
147 {
148         drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
149
150         I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG);
151         DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
152 }
153
154 void i915_driver_irq_uninstall(drm_device_t * dev)
155 {
156         drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
157         if (!dev_priv)
158                 return;
159
160         I915_WRITE16(I915REG_HWSTAM, 0xffff);
161         I915_WRITE16(I915REG_INT_MASK_R, 0xffff);
162         I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
163 }