diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/char/drm/i830_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/i830_irq.c')
-rw-r--r-- | drivers/char/drm/i830_irq.c | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/drivers/char/drm/i830_irq.c b/drivers/char/drm/i830_irq.c new file mode 100644 index 000000000000..6d7729ffe2dc --- /dev/null +++ b/drivers/char/drm/i830_irq.c | |||
@@ -0,0 +1,204 @@ | |||
1 | /* i830_dma.c -- DMA support for the I830 -*- linux-c -*- | ||
2 | * | ||
3 | * Copyright 2002 Tungsten Graphics, Inc. | ||
4 | * All Rights Reserved. | ||
5 | * | ||
6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
7 | * copy of this software and associated documentation files (the "Software"), | ||
8 | * to deal in the Software without restriction, including without limitation | ||
9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
10 | * and/or sell copies of the Software, and to permit persons to whom the | ||
11 | * Software is furnished to do so, subject to the following conditions: | ||
12 | * | ||
13 | * The above copyright notice and this permission notice (including the next | ||
14 | * paragraph) shall be included in all copies or substantial portions of the | ||
15 | * Software. | ||
16 | * | ||
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
20 | * TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
23 | * DEALINGS IN THE SOFTWARE. | ||
24 | * | ||
25 | * Authors: Keith Whitwell <keith@tungstengraphics.com> | ||
26 | * | ||
27 | */ | ||
28 | |||
29 | #include "drmP.h" | ||
30 | #include "drm.h" | ||
31 | #include "i830_drm.h" | ||
32 | #include "i830_drv.h" | ||
33 | #include <linux/interrupt.h> /* For task queue support */ | ||
34 | #include <linux/delay.h> | ||
35 | |||
36 | |||
37 | irqreturn_t i830_driver_irq_handler( DRM_IRQ_ARGS ) | ||
38 | { | ||
39 | drm_device_t *dev = (drm_device_t *)arg; | ||
40 | drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private; | ||
41 | u16 temp; | ||
42 | |||
43 | temp = I830_READ16(I830REG_INT_IDENTITY_R); | ||
44 | DRM_DEBUG("%x\n", temp); | ||
45 | |||
46 | if ( !( temp & 2 ) ) | ||
47 | return IRQ_NONE; | ||
48 | |||
49 | I830_WRITE16(I830REG_INT_IDENTITY_R, temp); | ||
50 | |||
51 | atomic_inc(&dev_priv->irq_received); | ||
52 | wake_up_interruptible(&dev_priv->irq_queue); | ||
53 | |||
54 | return IRQ_HANDLED; | ||
55 | } | ||
56 | |||
57 | |||
58 | int i830_emit_irq(drm_device_t *dev) | ||
59 | { | ||
60 | drm_i830_private_t *dev_priv = dev->dev_private; | ||
61 | RING_LOCALS; | ||
62 | |||
63 | DRM_DEBUG("%s\n", __FUNCTION__); | ||
64 | |||
65 | atomic_inc(&dev_priv->irq_emitted); | ||
66 | |||
67 | BEGIN_LP_RING(2); | ||
68 | OUT_RING( 0 ); | ||
69 | OUT_RING( GFX_OP_USER_INTERRUPT ); | ||
70 | ADVANCE_LP_RING(); | ||
71 | |||
72 | return atomic_read(&dev_priv->irq_emitted); | ||
73 | } | ||
74 | |||
75 | |||
76 | int i830_wait_irq(drm_device_t *dev, int irq_nr) | ||
77 | { | ||
78 | drm_i830_private_t *dev_priv = | ||
79 | (drm_i830_private_t *)dev->dev_private; | ||
80 | DECLARE_WAITQUEUE(entry, current); | ||
81 | unsigned long end = jiffies + HZ*3; | ||
82 | int ret = 0; | ||
83 | |||
84 | DRM_DEBUG("%s\n", __FUNCTION__); | ||
85 | |||
86 | if (atomic_read(&dev_priv->irq_received) >= irq_nr) | ||
87 | return 0; | ||
88 | |||
89 | dev_priv->sarea_priv->perf_boxes |= I830_BOX_WAIT; | ||
90 | |||
91 | add_wait_queue(&dev_priv->irq_queue, &entry); | ||
92 | |||
93 | for (;;) { | ||
94 | __set_current_state(TASK_INTERRUPTIBLE); | ||
95 | if (atomic_read(&dev_priv->irq_received) >= irq_nr) | ||
96 | break; | ||
97 | if((signed)(end - jiffies) <= 0) { | ||
98 | DRM_ERROR("timeout iir %x imr %x ier %x hwstam %x\n", | ||
99 | I830_READ16( I830REG_INT_IDENTITY_R ), | ||
100 | I830_READ16( I830REG_INT_MASK_R ), | ||
101 | I830_READ16( I830REG_INT_ENABLE_R ), | ||
102 | I830_READ16( I830REG_HWSTAM )); | ||
103 | |||
104 | ret = -EBUSY; /* Lockup? Missed irq? */ | ||
105 | break; | ||
106 | } | ||
107 | schedule_timeout(HZ*3); | ||
108 | if (signal_pending(current)) { | ||
109 | ret = -EINTR; | ||
110 | break; | ||
111 | } | ||
112 | } | ||
113 | |||
114 | __set_current_state(TASK_RUNNING); | ||
115 | remove_wait_queue(&dev_priv->irq_queue, &entry); | ||
116 | return ret; | ||
117 | } | ||
118 | |||
119 | |||
120 | /* Needs the lock as it touches the ring. | ||
121 | */ | ||
122 | int i830_irq_emit( struct inode *inode, struct file *filp, unsigned int cmd, | ||
123 | unsigned long arg ) | ||
124 | { | ||
125 | drm_file_t *priv = filp->private_data; | ||
126 | drm_device_t *dev = priv->head->dev; | ||
127 | drm_i830_private_t *dev_priv = dev->dev_private; | ||
128 | drm_i830_irq_emit_t emit; | ||
129 | int result; | ||
130 | |||
131 | LOCK_TEST_WITH_RETURN(dev, filp); | ||
132 | |||
133 | if ( !dev_priv ) { | ||
134 | DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); | ||
135 | return -EINVAL; | ||
136 | } | ||
137 | |||
138 | if (copy_from_user( &emit, (drm_i830_irq_emit_t __user *)arg, sizeof(emit) )) | ||
139 | return -EFAULT; | ||
140 | |||
141 | result = i830_emit_irq( dev ); | ||
142 | |||
143 | if ( copy_to_user( emit.irq_seq, &result, sizeof(int) ) ) { | ||
144 | DRM_ERROR( "copy_to_user\n" ); | ||
145 | return -EFAULT; | ||
146 | } | ||
147 | |||
148 | return 0; | ||
149 | } | ||
150 | |||
151 | |||
152 | /* Doesn't need the hardware lock. | ||
153 | */ | ||
154 | int i830_irq_wait( struct inode *inode, struct file *filp, unsigned int cmd, | ||
155 | unsigned long arg ) | ||
156 | { | ||
157 | drm_file_t *priv = filp->private_data; | ||
158 | drm_device_t *dev = priv->head->dev; | ||
159 | drm_i830_private_t *dev_priv = dev->dev_private; | ||
160 | drm_i830_irq_wait_t irqwait; | ||
161 | |||
162 | if ( !dev_priv ) { | ||
163 | DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); | ||
164 | return -EINVAL; | ||
165 | } | ||
166 | |||
167 | if (copy_from_user( &irqwait, (drm_i830_irq_wait_t __user *)arg, | ||
168 | sizeof(irqwait) )) | ||
169 | return -EFAULT; | ||
170 | |||
171 | return i830_wait_irq( dev, irqwait.irq_seq ); | ||
172 | } | ||
173 | |||
174 | |||
175 | /* drm_dma.h hooks | ||
176 | */ | ||
177 | void i830_driver_irq_preinstall( drm_device_t *dev ) { | ||
178 | drm_i830_private_t *dev_priv = | ||
179 | (drm_i830_private_t *)dev->dev_private; | ||
180 | |||
181 | I830_WRITE16( I830REG_HWSTAM, 0xffff ); | ||
182 | I830_WRITE16( I830REG_INT_MASK_R, 0x0 ); | ||
183 | I830_WRITE16( I830REG_INT_ENABLE_R, 0x0 ); | ||
184 | atomic_set(&dev_priv->irq_received, 0); | ||
185 | atomic_set(&dev_priv->irq_emitted, 0); | ||
186 | init_waitqueue_head(&dev_priv->irq_queue); | ||
187 | } | ||
188 | |||
189 | void i830_driver_irq_postinstall( drm_device_t *dev ) { | ||
190 | drm_i830_private_t *dev_priv = | ||
191 | (drm_i830_private_t *)dev->dev_private; | ||
192 | |||
193 | I830_WRITE16( I830REG_INT_ENABLE_R, 0x2 ); | ||
194 | } | ||
195 | |||
196 | void i830_driver_irq_uninstall( drm_device_t *dev ) { | ||
197 | drm_i830_private_t *dev_priv = | ||
198 | (drm_i830_private_t *)dev->dev_private; | ||
199 | if (!dev_priv) | ||
200 | return; | ||
201 | |||
202 | I830_WRITE16( I830REG_INT_MASK_R, 0xffff ); | ||
203 | I830_WRITE16( I830REG_INT_ENABLE_R, 0x0 ); | ||
204 | } | ||