xref: /titanic_41/usr/src/uts/intel/io/drm/i915_irq.c (revision 2e6e901d9406e1a048063c872149376a6bf7cb63)
1ae115bc7Smrj /* BEGIN CSTYLED */
2ae115bc7Smrj 
3ae115bc7Smrj /* i915_irq.c -- IRQ support for the I915 -*- linux-c -*-
4ae115bc7Smrj  */
5e92e3a86Szw161486 /*
6ae115bc7Smrj  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
70035d21cSmiao chen - Sun Microsystems - Beijing China  * Copyright (c) 2009, Intel Corporation.
8ae115bc7Smrj  * All Rights Reserved.
9ae115bc7Smrj  *
10ae115bc7Smrj  * Permission is hereby granted, free of charge, to any person obtaining a
11ae115bc7Smrj  * copy of this software and associated documentation files (the
12ae115bc7Smrj  * "Software"), to deal in the Software without restriction, including
13ae115bc7Smrj  * without limitation the rights to use, copy, modify, merge, publish,
14ae115bc7Smrj  * distribute, sub license, and/or sell copies of the Software, and to
15ae115bc7Smrj  * permit persons to whom the Software is furnished to do so, subject to
16ae115bc7Smrj  * the following conditions:
17ae115bc7Smrj  *
18ae115bc7Smrj  * The above copyright notice and this permission notice (including the
19ae115bc7Smrj  * next paragraph) shall be included in all copies or substantial portions
20ae115bc7Smrj  * of the Software.
21ae115bc7Smrj  *
22ae115bc7Smrj  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23ae115bc7Smrj  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24ae115bc7Smrj  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
25ae115bc7Smrj  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
26ae115bc7Smrj  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
27ae115bc7Smrj  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
28ae115bc7Smrj  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29ae115bc7Smrj  *
30e92e3a86Szw161486  */
31e92e3a86Szw161486 
32e92e3a86Szw161486 /*
33d0231070Smiao chen - Sun Microsystems - Beijing China  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
34e92e3a86Szw161486  * Use is subject to license terms.
35e92e3a86Szw161486  */
36ae115bc7Smrj 
37ae115bc7Smrj #include "drmP.h"
38ae115bc7Smrj #include "drm.h"
39ae115bc7Smrj #include "i915_drm.h"
40ae115bc7Smrj #include "i915_drv.h"
41ae115bc7Smrj 
42e92e3a86Szw161486 
43ae115bc7Smrj #define MAX_NOPID ((u32)~0)
44e92e3a86Szw161486 
450035d21cSmiao chen - Sun Microsystems - Beijing China /**
460035d21cSmiao chen - Sun Microsystems - Beijing China  * Interrupts that are always left unmasked.
470035d21cSmiao chen - Sun Microsystems - Beijing China  *
480035d21cSmiao chen - Sun Microsystems - Beijing China  * Since pipe events are edge-triggered from the PIPESTAT register to IIR,
490035d21cSmiao chen - Sun Microsystems - Beijing China  * we leave them always unmasked in IMR and then control enabling them through
500035d21cSmiao chen - Sun Microsystems - Beijing China  * PIPESTAT alone.
51d0231070Smiao chen - Sun Microsystems - Beijing China  */
520035d21cSmiao chen - Sun Microsystems - Beijing China 
530035d21cSmiao chen - Sun Microsystems - Beijing China #define I915_INTERRUPT_ENABLE_FIX (I915_ASLE_INTERRUPT |		 \
54d0231070Smiao chen - Sun Microsystems - Beijing China 				   I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | \
550035d21cSmiao chen - Sun Microsystems - Beijing China 				   I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | \
560035d21cSmiao chen - Sun Microsystems - Beijing China 				   I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT)
570035d21cSmiao chen - Sun Microsystems - Beijing China 
580035d21cSmiao chen - Sun Microsystems - Beijing China /** Interrupts that we mask and unmask at runtime. */
590035d21cSmiao chen - Sun Microsystems - Beijing China #define I915_INTERRUPT_ENABLE_VAR (I915_USER_INTERRUPT)
600035d21cSmiao chen - Sun Microsystems - Beijing China 
610035d21cSmiao chen - Sun Microsystems - Beijing China /** These are all of the interrupts used by the driver */
620035d21cSmiao chen - Sun Microsystems - Beijing China #define I915_INTERRUPT_ENABLE_MASK (I915_INTERRUPT_ENABLE_FIX | \
630035d21cSmiao chen - Sun Microsystems - Beijing China 				    I915_INTERRUPT_ENABLE_VAR)
64d0231070Smiao chen - Sun Microsystems - Beijing China 
65*2e6e901dSmiao chen - Sun Microsystems - Beijing China void
igdng_enable_irq(drm_i915_private_t * dev_priv,u32 mask,int gfx_irq)66*2e6e901dSmiao chen - Sun Microsystems - Beijing China igdng_enable_irq(drm_i915_private_t *dev_priv, u32 mask, int gfx_irq)
67*2e6e901dSmiao chen - Sun Microsystems - Beijing China {
68*2e6e901dSmiao chen - Sun Microsystems - Beijing China 	if (gfx_irq && ((dev_priv->gt_irq_mask_reg & mask) != 0)) {
69*2e6e901dSmiao chen - Sun Microsystems - Beijing China 		dev_priv->gt_irq_mask_reg &= ~mask;
70*2e6e901dSmiao chen - Sun Microsystems - Beijing China 		I915_WRITE(GTIMR, dev_priv->gt_irq_mask_reg);
71*2e6e901dSmiao chen - Sun Microsystems - Beijing China 		(void) I915_READ(GTIMR);
72*2e6e901dSmiao chen - Sun Microsystems - Beijing China 	} else if ((dev_priv->irq_mask_reg & mask) != 0) {
73*2e6e901dSmiao chen - Sun Microsystems - Beijing China 		dev_priv->irq_mask_reg &= ~mask;
74*2e6e901dSmiao chen - Sun Microsystems - Beijing China 		I915_WRITE(DEIMR, dev_priv->irq_mask_reg);
75*2e6e901dSmiao chen - Sun Microsystems - Beijing China 		(void) I915_READ(DEIMR);
76*2e6e901dSmiao chen - Sun Microsystems - Beijing China 
77*2e6e901dSmiao chen - Sun Microsystems - Beijing China 	}
78*2e6e901dSmiao chen - Sun Microsystems - Beijing China }
79*2e6e901dSmiao chen - Sun Microsystems - Beijing China 
80*2e6e901dSmiao chen - Sun Microsystems - Beijing China static inline void
igdng_disable_irq(drm_i915_private_t * dev_priv,u32 mask,int gfx_irq)81*2e6e901dSmiao chen - Sun Microsystems - Beijing China igdng_disable_irq(drm_i915_private_t *dev_priv, u32 mask, int gfx_irq)
82*2e6e901dSmiao chen - Sun Microsystems - Beijing China {
83*2e6e901dSmiao chen - Sun Microsystems - Beijing China 	if (gfx_irq && ((dev_priv->gt_irq_mask_reg & mask) != mask)) {
84*2e6e901dSmiao chen - Sun Microsystems - Beijing China 		dev_priv->gt_irq_mask_reg |= mask;
85*2e6e901dSmiao chen - Sun Microsystems - Beijing China 		I915_WRITE(GTIMR, dev_priv->gt_irq_mask_reg);
86*2e6e901dSmiao chen - Sun Microsystems - Beijing China 		(void) I915_READ(GTIMR);
87*2e6e901dSmiao chen - Sun Microsystems - Beijing China 	} else if ((dev_priv->irq_mask_reg & mask) != mask) {
88*2e6e901dSmiao chen - Sun Microsystems - Beijing China 		dev_priv->irq_mask_reg |= mask;
89*2e6e901dSmiao chen - Sun Microsystems - Beijing China 		I915_WRITE(DEIMR, dev_priv->irq_mask_reg);
90*2e6e901dSmiao chen - Sun Microsystems - Beijing China 		(void) I915_READ(DEIMR);
91*2e6e901dSmiao chen - Sun Microsystems - Beijing China 	}
92*2e6e901dSmiao chen - Sun Microsystems - Beijing China }
93*2e6e901dSmiao chen - Sun Microsystems - Beijing China 
94*2e6e901dSmiao chen - Sun Microsystems - Beijing China /* For display hotplug interrupt */
95*2e6e901dSmiao chen - Sun Microsystems - Beijing China void
igdng_enable_display_irq(drm_i915_private_t * dev_priv,u32 mask)96*2e6e901dSmiao chen - Sun Microsystems - Beijing China igdng_enable_display_irq(drm_i915_private_t *dev_priv, u32 mask)
97*2e6e901dSmiao chen - Sun Microsystems - Beijing China {
98*2e6e901dSmiao chen - Sun Microsystems - Beijing China        if ((dev_priv->irq_mask_reg & mask) != 0) {
99*2e6e901dSmiao chen - Sun Microsystems - Beijing China                dev_priv->irq_mask_reg &= ~mask;
100*2e6e901dSmiao chen - Sun Microsystems - Beijing China                I915_WRITE(DEIMR, dev_priv->irq_mask_reg);
101*2e6e901dSmiao chen - Sun Microsystems - Beijing China                (void) I915_READ(DEIMR);
102*2e6e901dSmiao chen - Sun Microsystems - Beijing China        }
103*2e6e901dSmiao chen - Sun Microsystems - Beijing China }
104*2e6e901dSmiao chen - Sun Microsystems - Beijing China 
105*2e6e901dSmiao chen - Sun Microsystems - Beijing China #if 0
106*2e6e901dSmiao chen - Sun Microsystems - Beijing China static inline void
107*2e6e901dSmiao chen - Sun Microsystems - Beijing China igdng_disable_display_irq(drm_i915_private_t *dev_priv, u32 mask)
108*2e6e901dSmiao chen - Sun Microsystems - Beijing China {
109*2e6e901dSmiao chen - Sun Microsystems - Beijing China        if ((dev_priv->irq_mask_reg & mask) != mask) {
110*2e6e901dSmiao chen - Sun Microsystems - Beijing China                dev_priv->irq_mask_reg |= mask;
111*2e6e901dSmiao chen - Sun Microsystems - Beijing China                I915_WRITE(DEIMR, dev_priv->irq_mask_reg);
112*2e6e901dSmiao chen - Sun Microsystems - Beijing China                (void) I915_READ(DEIMR);
113*2e6e901dSmiao chen - Sun Microsystems - Beijing China        }
114*2e6e901dSmiao chen - Sun Microsystems - Beijing China }
115*2e6e901dSmiao chen - Sun Microsystems - Beijing China #endif
116*2e6e901dSmiao chen - Sun Microsystems - Beijing China 
117d0231070Smiao chen - Sun Microsystems - Beijing China static inline void
i915_enable_irq(drm_i915_private_t * dev_priv,uint32_t mask)118d0231070Smiao chen - Sun Microsystems - Beijing China i915_enable_irq(drm_i915_private_t *dev_priv, uint32_t mask)
119d0231070Smiao chen - Sun Microsystems - Beijing China {
120d0231070Smiao chen - Sun Microsystems - Beijing China         if ((dev_priv->irq_mask_reg & mask) != 0) {
121d0231070Smiao chen - Sun Microsystems - Beijing China                 dev_priv->irq_mask_reg &= ~mask;
122d0231070Smiao chen - Sun Microsystems - Beijing China                 I915_WRITE(IMR, dev_priv->irq_mask_reg);
123d0231070Smiao chen - Sun Microsystems - Beijing China                 (void) I915_READ(IMR);
124d0231070Smiao chen - Sun Microsystems - Beijing China         }
125d0231070Smiao chen - Sun Microsystems - Beijing China }
126d0231070Smiao chen - Sun Microsystems - Beijing China 
127d0231070Smiao chen - Sun Microsystems - Beijing China static inline void
i915_disable_irq(drm_i915_private_t * dev_priv,uint32_t mask)128d0231070Smiao chen - Sun Microsystems - Beijing China i915_disable_irq(drm_i915_private_t *dev_priv, uint32_t mask)
129d0231070Smiao chen - Sun Microsystems - Beijing China {
130d0231070Smiao chen - Sun Microsystems - Beijing China 	if ((dev_priv->irq_mask_reg & mask) != mask) {
131d0231070Smiao chen - Sun Microsystems - Beijing China                 dev_priv->irq_mask_reg |= mask;
132d0231070Smiao chen - Sun Microsystems - Beijing China                 I915_WRITE(IMR, dev_priv->irq_mask_reg);
133d0231070Smiao chen - Sun Microsystems - Beijing China                 (void) I915_READ(IMR);
134d0231070Smiao chen - Sun Microsystems - Beijing China         }
135d0231070Smiao chen - Sun Microsystems - Beijing China }
1360035d21cSmiao chen - Sun Microsystems - Beijing China 
1370035d21cSmiao chen - Sun Microsystems - Beijing China static inline uint32_t
i915_pipestat(int pipe)1380035d21cSmiao chen - Sun Microsystems - Beijing China i915_pipestat(int pipe)
139d0231070Smiao chen - Sun Microsystems - Beijing China {
1400035d21cSmiao chen - Sun Microsystems - Beijing China 	if (pipe == 0)
1410035d21cSmiao chen - Sun Microsystems - Beijing China 		return PIPEASTAT;
1420035d21cSmiao chen - Sun Microsystems - Beijing China 	if (pipe == 1)
1430035d21cSmiao chen - Sun Microsystems - Beijing China 		return PIPEBSTAT;
1440035d21cSmiao chen - Sun Microsystems - Beijing China 	return 0;
145d0231070Smiao chen - Sun Microsystems - Beijing China }
146d0231070Smiao chen - Sun Microsystems - Beijing China 
1470035d21cSmiao chen - Sun Microsystems - Beijing China void
i915_enable_pipestat(drm_i915_private_t * dev_priv,int pipe,uint32_t mask)1480035d21cSmiao chen - Sun Microsystems - Beijing China i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, uint32_t mask)
149d0231070Smiao chen - Sun Microsystems - Beijing China {
1500035d21cSmiao chen - Sun Microsystems - Beijing China 	if ((dev_priv->pipestat[pipe] & mask) != mask) {
1510035d21cSmiao chen - Sun Microsystems - Beijing China 		u32 reg = i915_pipestat(pipe);
1520035d21cSmiao chen - Sun Microsystems - Beijing China 
1530035d21cSmiao chen - Sun Microsystems - Beijing China 		dev_priv->pipestat[pipe] |= mask;
1540035d21cSmiao chen - Sun Microsystems - Beijing China 		/* Enable the interrupt, clear any pending status */
1550035d21cSmiao chen - Sun Microsystems - Beijing China 		I915_WRITE(reg, dev_priv->pipestat[pipe] | (mask >> 16));
1560035d21cSmiao chen - Sun Microsystems - Beijing China 		(void) I915_READ(reg);
1570035d21cSmiao chen - Sun Microsystems - Beijing China 	}
1580035d21cSmiao chen - Sun Microsystems - Beijing China }
1590035d21cSmiao chen - Sun Microsystems - Beijing China 
1600035d21cSmiao chen - Sun Microsystems - Beijing China void
i915_disable_pipestat(drm_i915_private_t * dev_priv,int pipe,u32 mask)1610035d21cSmiao chen - Sun Microsystems - Beijing China i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask)
1620035d21cSmiao chen - Sun Microsystems - Beijing China {
1630035d21cSmiao chen - Sun Microsystems - Beijing China 	if ((dev_priv->pipestat[pipe] & mask) != 0) {
1640035d21cSmiao chen - Sun Microsystems - Beijing China 		u32 reg = i915_pipestat(pipe);
1650035d21cSmiao chen - Sun Microsystems - Beijing China 
1660035d21cSmiao chen - Sun Microsystems - Beijing China 		dev_priv->pipestat[pipe] &= ~mask;
1670035d21cSmiao chen - Sun Microsystems - Beijing China 		I915_WRITE(reg, dev_priv->pipestat[pipe]);
1680035d21cSmiao chen - Sun Microsystems - Beijing China 		(void) I915_READ(reg);
1690035d21cSmiao chen - Sun Microsystems - Beijing China 	}
170d0231070Smiao chen - Sun Microsystems - Beijing China }
171d0231070Smiao chen - Sun Microsystems - Beijing China 
172d0231070Smiao chen - Sun Microsystems - Beijing China /**
173d0231070Smiao chen - Sun Microsystems - Beijing China  * i915_pipe_enabled - check if a pipe is enabled
174d0231070Smiao chen - Sun Microsystems - Beijing China  * @dev: DRM device
175d0231070Smiao chen - Sun Microsystems - Beijing China  * @pipe: pipe to check
176d0231070Smiao chen - Sun Microsystems - Beijing China  *
177d0231070Smiao chen - Sun Microsystems - Beijing China  * Reading certain registers when the pipe is disabled can hang the chip.
178d0231070Smiao chen - Sun Microsystems - Beijing China  * Use this routine to make sure the PLL is running and the pipe is active
179d0231070Smiao chen - Sun Microsystems - Beijing China  * before reading such registers if unsure.
180d0231070Smiao chen - Sun Microsystems - Beijing China  */
181d0231070Smiao chen - Sun Microsystems - Beijing China static int
i915_pipe_enabled(struct drm_device * dev,int pipe)182d0231070Smiao chen - Sun Microsystems - Beijing China i915_pipe_enabled(struct drm_device *dev, int pipe)
183d0231070Smiao chen - Sun Microsystems - Beijing China {
184d0231070Smiao chen - Sun Microsystems - Beijing China 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
185d0231070Smiao chen - Sun Microsystems - Beijing China 	unsigned long pipeconf = pipe ? PIPEBCONF : PIPEACONF;
186d0231070Smiao chen - Sun Microsystems - Beijing China 
187d0231070Smiao chen - Sun Microsystems - Beijing China 	if (I915_READ(pipeconf) & PIPEACONF_ENABLE)
188d0231070Smiao chen - Sun Microsystems - Beijing China 		return 1;
189d0231070Smiao chen - Sun Microsystems - Beijing China 
190d0231070Smiao chen - Sun Microsystems - Beijing China 	return 0;
191d0231070Smiao chen - Sun Microsystems - Beijing China }
192d0231070Smiao chen - Sun Microsystems - Beijing China 
i915_get_vblank_counter(struct drm_device * dev,int pipe)1930035d21cSmiao chen - Sun Microsystems - Beijing China u32 i915_get_vblank_counter(struct drm_device *dev, int pipe)
194d0231070Smiao chen - Sun Microsystems - Beijing China {
195d0231070Smiao chen - Sun Microsystems - Beijing China 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
196d0231070Smiao chen - Sun Microsystems - Beijing China 	unsigned long high_frame;
197d0231070Smiao chen - Sun Microsystems - Beijing China 	unsigned long low_frame;
198d0231070Smiao chen - Sun Microsystems - Beijing China 	u32 high1, high2, low, count;
199d0231070Smiao chen - Sun Microsystems - Beijing China 
200d0231070Smiao chen - Sun Microsystems - Beijing China 	high_frame = pipe ? PIPEBFRAMEHIGH : PIPEAFRAMEHIGH;
201d0231070Smiao chen - Sun Microsystems - Beijing China 	low_frame = pipe ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL;
202d0231070Smiao chen - Sun Microsystems - Beijing China 
203d0231070Smiao chen - Sun Microsystems - Beijing China 	if (!i915_pipe_enabled(dev, pipe)) {
2040035d21cSmiao chen - Sun Microsystems - Beijing China 	    DRM_ERROR("trying to get vblank count for disabled pipe %d\n", pipe);
205d0231070Smiao chen - Sun Microsystems - Beijing China 	    return 0;
206d0231070Smiao chen - Sun Microsystems - Beijing China 	}
207d0231070Smiao chen - Sun Microsystems - Beijing China 
208d0231070Smiao chen - Sun Microsystems - Beijing China 	/*
209d0231070Smiao chen - Sun Microsystems - Beijing China 	 * High & low register fields aren't synchronized, so make sure
210d0231070Smiao chen - Sun Microsystems - Beijing China 	 * we get a low value that's stable across two reads of the high
211d0231070Smiao chen - Sun Microsystems - Beijing China 	 * register.
212d0231070Smiao chen - Sun Microsystems - Beijing China 	 */
213d0231070Smiao chen - Sun Microsystems - Beijing China 	do {
214d0231070Smiao chen - Sun Microsystems - Beijing China 		high1 = ((I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >>
215d0231070Smiao chen - Sun Microsystems - Beijing China 			 PIPE_FRAME_HIGH_SHIFT);
216d0231070Smiao chen - Sun Microsystems - Beijing China 		low =  ((I915_READ(low_frame) & PIPE_FRAME_LOW_MASK) >>
217d0231070Smiao chen - Sun Microsystems - Beijing China 			PIPE_FRAME_LOW_SHIFT);
218d0231070Smiao chen - Sun Microsystems - Beijing China 		high2 = ((I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >>
219d0231070Smiao chen - Sun Microsystems - Beijing China 			 PIPE_FRAME_HIGH_SHIFT);
220d0231070Smiao chen - Sun Microsystems - Beijing China 	} while (high1 != high2);
221d0231070Smiao chen - Sun Microsystems - Beijing China 
222d0231070Smiao chen - Sun Microsystems - Beijing China 	count = (high1 << 8) | low;
223d0231070Smiao chen - Sun Microsystems - Beijing China 
224d0231070Smiao chen - Sun Microsystems - Beijing China 	return count;
225d0231070Smiao chen - Sun Microsystems - Beijing China }
226d0231070Smiao chen - Sun Microsystems - Beijing China 
2270035d21cSmiao chen - Sun Microsystems - Beijing China /**
2280035d21cSmiao chen - Sun Microsystems - Beijing China  * i915_capture_error_state - capture an error record for later analysis
2290035d21cSmiao chen - Sun Microsystems - Beijing China  * @dev: drm device
2300035d21cSmiao chen - Sun Microsystems - Beijing China  *
2310035d21cSmiao chen - Sun Microsystems - Beijing China  * Should be called when an error is detected (either a hang or an error
2320035d21cSmiao chen - Sun Microsystems - Beijing China  * interrupt) to capture error state from the time of the error.  Fills
2330035d21cSmiao chen - Sun Microsystems - Beijing China  * out a structure which becomes available in debugfs for user level tools
2340035d21cSmiao chen - Sun Microsystems - Beijing China  * to pick up.
2350035d21cSmiao chen - Sun Microsystems - Beijing China  */
i915_capture_error_state(struct drm_device * dev)2360035d21cSmiao chen - Sun Microsystems - Beijing China static void i915_capture_error_state(struct drm_device *dev)
2370035d21cSmiao chen - Sun Microsystems - Beijing China {
2380035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_private *dev_priv = dev->dev_private;
2390035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_error_state *error;
2400035d21cSmiao chen - Sun Microsystems - Beijing China 
2410035d21cSmiao chen - Sun Microsystems - Beijing China 	spin_lock_irqsave(&dev_priv->error_lock, flags);
2420035d21cSmiao chen - Sun Microsystems - Beijing China #if 0
2430035d21cSmiao chen - Sun Microsystems - Beijing China 	if (dev_priv->first_error)
2440035d21cSmiao chen - Sun Microsystems - Beijing China 		goto out;
2450035d21cSmiao chen - Sun Microsystems - Beijing China #endif
2460035d21cSmiao chen - Sun Microsystems - Beijing China 	error = drm_alloc(sizeof(*error), DRM_MEM_DRIVER);
2470035d21cSmiao chen - Sun Microsystems - Beijing China 	if (!error) {
2480035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_DEBUG("out ot memory, not capturing error state\n");
2490035d21cSmiao chen - Sun Microsystems - Beijing China 		goto out;
2500035d21cSmiao chen - Sun Microsystems - Beijing China 	}
2510035d21cSmiao chen - Sun Microsystems - Beijing China 
2520035d21cSmiao chen - Sun Microsystems - Beijing China 	error->eir = I915_READ(EIR);
2530035d21cSmiao chen - Sun Microsystems - Beijing China 	error->pgtbl_er = I915_READ(PGTBL_ER);
2540035d21cSmiao chen - Sun Microsystems - Beijing China 	error->pipeastat = I915_READ(PIPEASTAT);
2550035d21cSmiao chen - Sun Microsystems - Beijing China 	error->pipebstat = I915_READ(PIPEBSTAT);
2560035d21cSmiao chen - Sun Microsystems - Beijing China 	error->instpm = I915_READ(INSTPM);
2570035d21cSmiao chen - Sun Microsystems - Beijing China 	if (!IS_I965G(dev)) {
2580035d21cSmiao chen - Sun Microsystems - Beijing China 		error->ipeir = I915_READ(IPEIR);
2590035d21cSmiao chen - Sun Microsystems - Beijing China 		error->ipehr = I915_READ(IPEHR);
2600035d21cSmiao chen - Sun Microsystems - Beijing China 		error->instdone = I915_READ(INSTDONE);
2610035d21cSmiao chen - Sun Microsystems - Beijing China 		error->acthd = I915_READ(ACTHD);
2620035d21cSmiao chen - Sun Microsystems - Beijing China 	} else {
2630035d21cSmiao chen - Sun Microsystems - Beijing China 		error->ipeir = I915_READ(IPEIR_I965);
2640035d21cSmiao chen - Sun Microsystems - Beijing China 		error->ipehr = I915_READ(IPEHR_I965);
2650035d21cSmiao chen - Sun Microsystems - Beijing China 		error->instdone = I915_READ(INSTDONE_I965);
2660035d21cSmiao chen - Sun Microsystems - Beijing China 		error->instps = I915_READ(INSTPS);
2670035d21cSmiao chen - Sun Microsystems - Beijing China 		error->instdone1 = I915_READ(INSTDONE1);
2680035d21cSmiao chen - Sun Microsystems - Beijing China 		error->acthd = I915_READ(ACTHD_I965);
2690035d21cSmiao chen - Sun Microsystems - Beijing China 	}
2700035d21cSmiao chen - Sun Microsystems - Beijing China 
2710035d21cSmiao chen - Sun Microsystems - Beijing China 	(void) uniqtime(&error->time);
2720035d21cSmiao chen - Sun Microsystems - Beijing China 
2730035d21cSmiao chen - Sun Microsystems - Beijing China 	dev_priv->first_error = error;
2740035d21cSmiao chen - Sun Microsystems - Beijing China 
2750035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_DEBUG("Time: %ld s %ld us\n", error->time.tv_sec,
2760035d21cSmiao chen - Sun Microsystems - Beijing China 		   error->time.tv_usec);
2770035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_DEBUG("EIR: 0x%08x\n", error->eir);
2780035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_DEBUG("  PGTBL_ER: 0x%08x\n", error->pgtbl_er);
2790035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_DEBUG("  INSTPM: 0x%08x\n", error->instpm);
2800035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_DEBUG("  IPEIR: 0x%08x\n", error->ipeir);
2810035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_DEBUG("  IPEHR: 0x%08x\n", error->ipehr);
2820035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_DEBUG("  INSTDONE: 0x%08x\n", error->instdone);
2830035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_DEBUG("  ACTHD: 0x%08x\n", error->acthd);
2840035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_DEBUG("  DMA_FADD_P: 0x%08x\n", I915_READ(0x2078));
2850035d21cSmiao chen - Sun Microsystems - Beijing China 	if (IS_I965G(dev)) {
2860035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_DEBUG("  INSTPS: 0x%08x\n", error->instps);
2870035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_DEBUG("  INSTDONE1: 0x%08x\n", error->instdone1);
2880035d21cSmiao chen - Sun Microsystems - Beijing China 	}
2890035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_free(error, sizeof(*error), DRM_MEM_DRIVER);
2900035d21cSmiao chen - Sun Microsystems - Beijing China out:
2910035d21cSmiao chen - Sun Microsystems - Beijing China 	spin_unlock_irqrestore(&dev_priv->error_lock, flags);
2920035d21cSmiao chen - Sun Microsystems - Beijing China }
2930035d21cSmiao chen - Sun Microsystems - Beijing China 
2940035d21cSmiao chen - Sun Microsystems - Beijing China /**
2950035d21cSmiao chen - Sun Microsystems - Beijing China  * i915_handle_error - handle an error interrupt
2960035d21cSmiao chen - Sun Microsystems - Beijing China  * @dev: drm device
2970035d21cSmiao chen - Sun Microsystems - Beijing China  *
2980035d21cSmiao chen - Sun Microsystems - Beijing China  * Do some basic checking of regsiter state at error interrupt time and
2990035d21cSmiao chen - Sun Microsystems - Beijing China  * dump it to the syslog.  Also call i915_capture_error_state() to make
3000035d21cSmiao chen - Sun Microsystems - Beijing China  * sure we get a record and make it available in debugfs.  Fire a uevent
3010035d21cSmiao chen - Sun Microsystems - Beijing China  * so userspace knows something bad happened (should trigger collection
3020035d21cSmiao chen - Sun Microsystems - Beijing China  * of a ring dump etc.).
3030035d21cSmiao chen - Sun Microsystems - Beijing China  */
i915_handle_error(struct drm_device * dev)3040035d21cSmiao chen - Sun Microsystems - Beijing China void i915_handle_error(struct drm_device *dev)
3050035d21cSmiao chen - Sun Microsystems - Beijing China {
3060035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_private *dev_priv = dev->dev_private;
3070035d21cSmiao chen - Sun Microsystems - Beijing China 	u32 eir = I915_READ(EIR);
3080035d21cSmiao chen - Sun Microsystems - Beijing China 	u32 pipea_stats = I915_READ(PIPEASTAT);
3090035d21cSmiao chen - Sun Microsystems - Beijing China 	u32 pipeb_stats = I915_READ(PIPEBSTAT);
3100035d21cSmiao chen - Sun Microsystems - Beijing China 
3110035d21cSmiao chen - Sun Microsystems - Beijing China 	i915_capture_error_state(dev);
3120035d21cSmiao chen - Sun Microsystems - Beijing China 
3130035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_DEBUG("render error detected, EIR: 0x%08x\n",
3140035d21cSmiao chen - Sun Microsystems - Beijing China 	       eir);
3150035d21cSmiao chen - Sun Microsystems - Beijing China 
3160035d21cSmiao chen - Sun Microsystems - Beijing China 	if (IS_G4X(dev)) {
3170035d21cSmiao chen - Sun Microsystems - Beijing China 		if (eir & (GM45_ERROR_MEM_PRIV | GM45_ERROR_CP_PRIV)) {
3180035d21cSmiao chen - Sun Microsystems - Beijing China 			u32 ipeir = I915_READ(IPEIR_I965);
3190035d21cSmiao chen - Sun Microsystems - Beijing China 
3200035d21cSmiao chen - Sun Microsystems - Beijing China 			DRM_DEBUG("  IPEIR: 0x%08x\n",
3210035d21cSmiao chen - Sun Microsystems - Beijing China 			       I915_READ(IPEIR_I965));
3220035d21cSmiao chen - Sun Microsystems - Beijing China 			DRM_DEBUG("  IPEHR: 0x%08x\n",
3230035d21cSmiao chen - Sun Microsystems - Beijing China 			       I915_READ(IPEHR_I965));
3240035d21cSmiao chen - Sun Microsystems - Beijing China 			DRM_DEBUG("  INSTDONE: 0x%08x\n",
3250035d21cSmiao chen - Sun Microsystems - Beijing China 			       I915_READ(INSTDONE_I965));
3260035d21cSmiao chen - Sun Microsystems - Beijing China 			DRM_DEBUG("  INSTPS: 0x%08x\n",
3270035d21cSmiao chen - Sun Microsystems - Beijing China 			       I915_READ(INSTPS));
3280035d21cSmiao chen - Sun Microsystems - Beijing China 			DRM_DEBUG("  INSTDONE1: 0x%08x\n",
3290035d21cSmiao chen - Sun Microsystems - Beijing China 			       I915_READ(INSTDONE1));
3300035d21cSmiao chen - Sun Microsystems - Beijing China 			DRM_DEBUG("  ACTHD: 0x%08x\n",
3310035d21cSmiao chen - Sun Microsystems - Beijing China 			       I915_READ(ACTHD_I965));
3320035d21cSmiao chen - Sun Microsystems - Beijing China 			I915_WRITE(IPEIR_I965, ipeir);
3330035d21cSmiao chen - Sun Microsystems - Beijing China 			(void)I915_READ(IPEIR_I965);
3340035d21cSmiao chen - Sun Microsystems - Beijing China 		}
3350035d21cSmiao chen - Sun Microsystems - Beijing China 		if (eir & GM45_ERROR_PAGE_TABLE) {
3360035d21cSmiao chen - Sun Microsystems - Beijing China 			u32 pgtbl_err = I915_READ(PGTBL_ER);
3370035d21cSmiao chen - Sun Microsystems - Beijing China 			DRM_DEBUG("page table error\n");
3380035d21cSmiao chen - Sun Microsystems - Beijing China 			DRM_DEBUG("  PGTBL_ER: 0x%08x\n",
3390035d21cSmiao chen - Sun Microsystems - Beijing China 			       pgtbl_err);
3400035d21cSmiao chen - Sun Microsystems - Beijing China 			I915_WRITE(PGTBL_ER, pgtbl_err);
3410035d21cSmiao chen - Sun Microsystems - Beijing China 			(void)I915_READ(PGTBL_ER);
3420035d21cSmiao chen - Sun Microsystems - Beijing China 		}
3430035d21cSmiao chen - Sun Microsystems - Beijing China 	}
3440035d21cSmiao chen - Sun Microsystems - Beijing China 
3450035d21cSmiao chen - Sun Microsystems - Beijing China 	if (IS_I9XX(dev)) {
3460035d21cSmiao chen - Sun Microsystems - Beijing China 		if (eir & I915_ERROR_PAGE_TABLE) {
3470035d21cSmiao chen - Sun Microsystems - Beijing China 			u32 pgtbl_err = I915_READ(PGTBL_ER);
3480035d21cSmiao chen - Sun Microsystems - Beijing China 			DRM_DEBUG("page table error\n");
3490035d21cSmiao chen - Sun Microsystems - Beijing China 			DRM_DEBUG("PGTBL_ER: 0x%08x\n",
3500035d21cSmiao chen - Sun Microsystems - Beijing China 			       pgtbl_err);
3510035d21cSmiao chen - Sun Microsystems - Beijing China 			I915_WRITE(PGTBL_ER, pgtbl_err);
3520035d21cSmiao chen - Sun Microsystems - Beijing China 			(void)I915_READ(PGTBL_ER);
3530035d21cSmiao chen - Sun Microsystems - Beijing China 		}
3540035d21cSmiao chen - Sun Microsystems - Beijing China 	}
3550035d21cSmiao chen - Sun Microsystems - Beijing China 
3560035d21cSmiao chen - Sun Microsystems - Beijing China 	if (eir & I915_ERROR_MEMORY_REFRESH) {
3570035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_DEBUG("memory refresh error\n");
3580035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_DEBUG("PIPEASTAT: 0x%08x\n",
3590035d21cSmiao chen - Sun Microsystems - Beijing China 		       pipea_stats);
3600035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_DEBUG("PIPEBSTAT: 0x%08x\n",
3610035d21cSmiao chen - Sun Microsystems - Beijing China 		       pipeb_stats);
3620035d21cSmiao chen - Sun Microsystems - Beijing China 		/* pipestat has already been acked */
3630035d21cSmiao chen - Sun Microsystems - Beijing China 	}
3640035d21cSmiao chen - Sun Microsystems - Beijing China 	if (eir & I915_ERROR_INSTRUCTION) {
3650035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_DEBUG("instruction error\n");
3660035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_DEBUG("  INSTPM: 0x%08x\n",
3670035d21cSmiao chen - Sun Microsystems - Beijing China 		       I915_READ(INSTPM));
3680035d21cSmiao chen - Sun Microsystems - Beijing China 		if (!IS_I965G(dev)) {
3690035d21cSmiao chen - Sun Microsystems - Beijing China 			u32 ipeir = I915_READ(IPEIR);
3700035d21cSmiao chen - Sun Microsystems - Beijing China 
3710035d21cSmiao chen - Sun Microsystems - Beijing China 			DRM_DEBUG("  IPEIR: 0x%08x\n",
3720035d21cSmiao chen - Sun Microsystems - Beijing China 			       I915_READ(IPEIR));
3730035d21cSmiao chen - Sun Microsystems - Beijing China 			DRM_DEBUG("  IPEHR: 0x%08x\n",
3740035d21cSmiao chen - Sun Microsystems - Beijing China 			       I915_READ(IPEHR));
3750035d21cSmiao chen - Sun Microsystems - Beijing China 			DRM_DEBUG("  INSTDONE: 0x%08x\n",
3760035d21cSmiao chen - Sun Microsystems - Beijing China 			       I915_READ(INSTDONE));
3770035d21cSmiao chen - Sun Microsystems - Beijing China 			DRM_DEBUG("  ACTHD: 0x%08x\n",
3780035d21cSmiao chen - Sun Microsystems - Beijing China 			       I915_READ(ACTHD));
3790035d21cSmiao chen - Sun Microsystems - Beijing China 			I915_WRITE(IPEIR, ipeir);
3800035d21cSmiao chen - Sun Microsystems - Beijing China 			(void)I915_READ(IPEIR);
3810035d21cSmiao chen - Sun Microsystems - Beijing China 		} else {
3820035d21cSmiao chen - Sun Microsystems - Beijing China 			u32 ipeir = I915_READ(IPEIR_I965);
3830035d21cSmiao chen - Sun Microsystems - Beijing China 
3840035d21cSmiao chen - Sun Microsystems - Beijing China 			DRM_DEBUG("  IPEIR: 0x%08x\n",
3850035d21cSmiao chen - Sun Microsystems - Beijing China 			       I915_READ(IPEIR_I965));
3860035d21cSmiao chen - Sun Microsystems - Beijing China 			DRM_DEBUG("  IPEHR: 0x%08x\n",
3870035d21cSmiao chen - Sun Microsystems - Beijing China 			       I915_READ(IPEHR_I965));
3880035d21cSmiao chen - Sun Microsystems - Beijing China 			DRM_DEBUG("  INSTDONE: 0x%08x\n",
3890035d21cSmiao chen - Sun Microsystems - Beijing China 			       I915_READ(INSTDONE_I965));
3900035d21cSmiao chen - Sun Microsystems - Beijing China 			DRM_DEBUG("  INSTPS: 0x%08x\n",
3910035d21cSmiao chen - Sun Microsystems - Beijing China 			       I915_READ(INSTPS));
3920035d21cSmiao chen - Sun Microsystems - Beijing China 			DRM_DEBUG("  INSTDONE1: 0x%08x\n",
3930035d21cSmiao chen - Sun Microsystems - Beijing China 			       I915_READ(INSTDONE1));
3940035d21cSmiao chen - Sun Microsystems - Beijing China 			DRM_DEBUG("  ACTHD: 0x%08x\n",
3950035d21cSmiao chen - Sun Microsystems - Beijing China 			       I915_READ(ACTHD_I965));
3960035d21cSmiao chen - Sun Microsystems - Beijing China 			I915_WRITE(IPEIR_I965, ipeir);
3970035d21cSmiao chen - Sun Microsystems - Beijing China 			(void)I915_READ(IPEIR_I965);
3980035d21cSmiao chen - Sun Microsystems - Beijing China 		}
3990035d21cSmiao chen - Sun Microsystems - Beijing China 	}
4000035d21cSmiao chen - Sun Microsystems - Beijing China 
4010035d21cSmiao chen - Sun Microsystems - Beijing China 	I915_WRITE(EIR, eir);
4020035d21cSmiao chen - Sun Microsystems - Beijing China 	(void)I915_READ(EIR);
4030035d21cSmiao chen - Sun Microsystems - Beijing China 	eir = I915_READ(EIR);
4040035d21cSmiao chen - Sun Microsystems - Beijing China 	if (eir) {
4050035d21cSmiao chen - Sun Microsystems - Beijing China 		/*
4060035d21cSmiao chen - Sun Microsystems - Beijing China 		 * some errors might have become stuck,
4070035d21cSmiao chen - Sun Microsystems - Beijing China 		 * mask them.
4080035d21cSmiao chen - Sun Microsystems - Beijing China 		 */
4090035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_DEBUG("EIR stuck: 0x%08x, masking\n", eir);
4100035d21cSmiao chen - Sun Microsystems - Beijing China 		I915_WRITE(EMR, I915_READ(EMR) | eir);
4110035d21cSmiao chen - Sun Microsystems - Beijing China 		I915_WRITE(IIR, I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT);
4120035d21cSmiao chen - Sun Microsystems - Beijing China 	}
4130035d21cSmiao chen - Sun Microsystems - Beijing China 
4140035d21cSmiao chen - Sun Microsystems - Beijing China }
4150035d21cSmiao chen - Sun Microsystems - Beijing China 
gm45_get_vblank_counter(struct drm_device * dev,int pipe)4160035d21cSmiao chen - Sun Microsystems - Beijing China u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe)
4170035d21cSmiao chen - Sun Microsystems - Beijing China {
4180035d21cSmiao chen - Sun Microsystems - Beijing China        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
4190035d21cSmiao chen - Sun Microsystems - Beijing China        int reg = pipe ? PIPEB_FRMCOUNT_GM45 : PIPEA_FRMCOUNT_GM45;
4200035d21cSmiao chen - Sun Microsystems - Beijing China 
4210035d21cSmiao chen - Sun Microsystems - Beijing China        if (!i915_pipe_enabled(dev, pipe)) {
4220035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("trying to get vblank count for disabled pipe %d\n", pipe);
4230035d21cSmiao chen - Sun Microsystems - Beijing China                return 0;
4240035d21cSmiao chen - Sun Microsystems - Beijing China        }
4250035d21cSmiao chen - Sun Microsystems - Beijing China 
4260035d21cSmiao chen - Sun Microsystems - Beijing China        return I915_READ(reg);
4270035d21cSmiao chen - Sun Microsystems - Beijing China }
4280035d21cSmiao chen - Sun Microsystems - Beijing China 
igdng_irq_handler(struct drm_device * dev)429*2e6e901dSmiao chen - Sun Microsystems - Beijing China irqreturn_t igdng_irq_handler(struct drm_device *dev)
430*2e6e901dSmiao chen - Sun Microsystems - Beijing China {
431*2e6e901dSmiao chen - Sun Microsystems - Beijing China        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
432*2e6e901dSmiao chen - Sun Microsystems - Beijing China        int ret = IRQ_NONE;
433*2e6e901dSmiao chen - Sun Microsystems - Beijing China        u32 de_iir, gt_iir, de_ier;
434*2e6e901dSmiao chen - Sun Microsystems - Beijing China        u32 new_de_iir, new_gt_iir;
435*2e6e901dSmiao chen - Sun Microsystems - Beijing China        int vblank = 0;
436*2e6e901dSmiao chen - Sun Microsystems - Beijing China 
437*2e6e901dSmiao chen - Sun Microsystems - Beijing China 	/* disable master interrupt before clearing iir  */
438*2e6e901dSmiao chen - Sun Microsystems - Beijing China 	de_ier = I915_READ(DEIER);
439*2e6e901dSmiao chen - Sun Microsystems - Beijing China 	I915_WRITE(DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL);
440*2e6e901dSmiao chen - Sun Microsystems - Beijing China 	(void)I915_READ(DEIER);
441*2e6e901dSmiao chen - Sun Microsystems - Beijing China 
442*2e6e901dSmiao chen - Sun Microsystems - Beijing China        de_iir = I915_READ(DEIIR);
443*2e6e901dSmiao chen - Sun Microsystems - Beijing China        gt_iir = I915_READ(GTIIR);
444*2e6e901dSmiao chen - Sun Microsystems - Beijing China 
445*2e6e901dSmiao chen - Sun Microsystems - Beijing China        for (;;) {
446*2e6e901dSmiao chen - Sun Microsystems - Beijing China                if (de_iir == 0 && gt_iir == 0)
447*2e6e901dSmiao chen - Sun Microsystems - Beijing China                        break;
448*2e6e901dSmiao chen - Sun Microsystems - Beijing China 
449*2e6e901dSmiao chen - Sun Microsystems - Beijing China                ret = IRQ_HANDLED;
450*2e6e901dSmiao chen - Sun Microsystems - Beijing China 
451*2e6e901dSmiao chen - Sun Microsystems - Beijing China                I915_WRITE(DEIIR, de_iir);
452*2e6e901dSmiao chen - Sun Microsystems - Beijing China                new_de_iir = I915_READ(DEIIR);
453*2e6e901dSmiao chen - Sun Microsystems - Beijing China                I915_WRITE(GTIIR, gt_iir);
454*2e6e901dSmiao chen - Sun Microsystems - Beijing China                new_gt_iir = I915_READ(GTIIR);
455*2e6e901dSmiao chen - Sun Microsystems - Beijing China 
456*2e6e901dSmiao chen - Sun Microsystems - Beijing China         if (dev_priv->sarea_priv) {
457*2e6e901dSmiao chen - Sun Microsystems - Beijing China             dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
458*2e6e901dSmiao chen - Sun Microsystems - Beijing China 
459*2e6e901dSmiao chen - Sun Microsystems - Beijing China 	}
460*2e6e901dSmiao chen - Sun Microsystems - Beijing China 
461*2e6e901dSmiao chen - Sun Microsystems - Beijing China                if (gt_iir & GT_USER_INTERRUPT) {
462*2e6e901dSmiao chen - Sun Microsystems - Beijing China                        dev_priv->mm.irq_gem_seqno = i915_get_gem_seqno(dev);
463*2e6e901dSmiao chen - Sun Microsystems - Beijing China                        DRM_WAKEUP(&dev_priv->irq_queue);
464*2e6e901dSmiao chen - Sun Microsystems - Beijing China                }
465*2e6e901dSmiao chen - Sun Microsystems - Beijing China                if (de_iir & DE_PIPEA_VBLANK) {
466*2e6e901dSmiao chen - Sun Microsystems - Beijing China                        vblank++;
467*2e6e901dSmiao chen - Sun Microsystems - Beijing China                        drm_handle_vblank(dev, 0);
468*2e6e901dSmiao chen - Sun Microsystems - Beijing China                }
469*2e6e901dSmiao chen - Sun Microsystems - Beijing China 
470*2e6e901dSmiao chen - Sun Microsystems - Beijing China                if (de_iir & DE_PIPEB_VBLANK) {
471*2e6e901dSmiao chen - Sun Microsystems - Beijing China                        vblank++;
472*2e6e901dSmiao chen - Sun Microsystems - Beijing China                        drm_handle_vblank(dev, 1);
473*2e6e901dSmiao chen - Sun Microsystems - Beijing China                }
474*2e6e901dSmiao chen - Sun Microsystems - Beijing China 
475*2e6e901dSmiao chen - Sun Microsystems - Beijing China                de_iir = new_de_iir;
476*2e6e901dSmiao chen - Sun Microsystems - Beijing China                gt_iir = new_gt_iir;
477*2e6e901dSmiao chen - Sun Microsystems - Beijing China        }
478*2e6e901dSmiao chen - Sun Microsystems - Beijing China 
479*2e6e901dSmiao chen - Sun Microsystems - Beijing China 	I915_WRITE(DEIER, de_ier);
480*2e6e901dSmiao chen - Sun Microsystems - Beijing China 	(void)I915_READ(DEIER);
481*2e6e901dSmiao chen - Sun Microsystems - Beijing China 
482*2e6e901dSmiao chen - Sun Microsystems - Beijing China        return ret;
483*2e6e901dSmiao chen - Sun Microsystems - Beijing China }
484*2e6e901dSmiao chen - Sun Microsystems - Beijing China 
i915_driver_irq_handler(DRM_IRQ_ARGS)485ae115bc7Smrj irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
486ae115bc7Smrj {
4870bdffa0fShh224818         drm_device_t *dev = (drm_device_t *) (void *) arg;
488ae115bc7Smrj         drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
489d0231070Smiao chen - Sun Microsystems - Beijing China         u32 iir;
490d0231070Smiao chen - Sun Microsystems - Beijing China         u32 pipea_stats = 0, pipeb_stats = 0;
491d0231070Smiao chen - Sun Microsystems - Beijing China 	int vblank = 0;
492e92e3a86Szw161486 
493*2e6e901dSmiao chen - Sun Microsystems - Beijing China 	if (IS_IGDNG(dev))
494*2e6e901dSmiao chen - Sun Microsystems - Beijing China 		return igdng_irq_handler(dev);
495*2e6e901dSmiao chen - Sun Microsystems - Beijing China 
4960035d21cSmiao chen - Sun Microsystems - Beijing China 	iir = I915_READ(IIR);
497ae115bc7Smrj 
498d0231070Smiao chen - Sun Microsystems - Beijing China 	if (iir == 0) {
499e92e3a86Szw161486 		return IRQ_NONE;
500d0231070Smiao chen - Sun Microsystems - Beijing China 	}
5010035d21cSmiao chen - Sun Microsystems - Beijing China start:
5020035d21cSmiao chen - Sun Microsystems - Beijing China 
5030035d21cSmiao chen - Sun Microsystems - Beijing China 	if (dev_priv->sarea_priv) {
5040035d21cSmiao chen - Sun Microsystems - Beijing China 		if (dev_priv->hw_status_page)
5050035d21cSmiao chen - Sun Microsystems - Beijing China 	    		dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
5060035d21cSmiao chen - Sun Microsystems - Beijing China 	}
5070035d21cSmiao chen - Sun Microsystems - Beijing China 
5080035d21cSmiao chen - Sun Microsystems - Beijing China 	I915_WRITE(IIR, iir);
5090035d21cSmiao chen - Sun Microsystems - Beijing China 
5100035d21cSmiao chen - Sun Microsystems - Beijing China 	(void) I915_READ(IIR); /* Flush posted writes */
5110035d21cSmiao chen - Sun Microsystems - Beijing China 
5120035d21cSmiao chen - Sun Microsystems - Beijing China 
5130035d21cSmiao chen - Sun Microsystems - Beijing China 	if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT)
5140035d21cSmiao chen - Sun Microsystems - Beijing China 		i915_handle_error(dev);
5150035d21cSmiao chen - Sun Microsystems - Beijing China 
5160035d21cSmiao chen - Sun Microsystems - Beijing China         if (iir & I915_USER_INTERRUPT) {
5170035d21cSmiao chen - Sun Microsystems - Beijing China 		dev_priv->mm.irq_gem_seqno = i915_get_gem_seqno(dev);
5180035d21cSmiao chen - Sun Microsystems - Beijing China                 DRM_WAKEUP(&dev_priv->irq_queue);
5190035d21cSmiao chen - Sun Microsystems - Beijing China         }
520ae115bc7Smrj 
521d0231070Smiao chen - Sun Microsystems - Beijing China         if (iir & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT) {
522d0231070Smiao chen - Sun Microsystems - Beijing China                 pipea_stats = I915_READ(PIPEASTAT);
523e92e3a86Szw161486 
524d0231070Smiao chen - Sun Microsystems - Beijing China                 /* The vblank interrupt gets enabled even if we didn't ask for
525d0231070Smiao chen - Sun Microsystems - Beijing China                    it, so make sure it's shut down again */
526d0231070Smiao chen - Sun Microsystems - Beijing China                 if (!(dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A))
527d0231070Smiao chen - Sun Microsystems - Beijing China                         pipea_stats &= ~(PIPE_START_VBLANK_INTERRUPT_ENABLE |
528d0231070Smiao chen - Sun Microsystems - Beijing China                                          PIPE_VBLANK_INTERRUPT_ENABLE);
529d0231070Smiao chen - Sun Microsystems - Beijing China                 else if (pipea_stats & (PIPE_START_VBLANK_INTERRUPT_STATUS|
530d0231070Smiao chen - Sun Microsystems - Beijing China                                         PIPE_VBLANK_INTERRUPT_STATUS))
531d0231070Smiao chen - Sun Microsystems - Beijing China                 {
532d0231070Smiao chen - Sun Microsystems - Beijing China                         vblank++;
5330035d21cSmiao chen - Sun Microsystems - Beijing China                         drm_handle_vblank(dev, 0);
534d0231070Smiao chen - Sun Microsystems - Beijing China                 }
535d0231070Smiao chen - Sun Microsystems - Beijing China 
536d0231070Smiao chen - Sun Microsystems - Beijing China                 I915_WRITE(PIPEASTAT, pipea_stats);
537d0231070Smiao chen - Sun Microsystems - Beijing China         }
538d0231070Smiao chen - Sun Microsystems - Beijing China         if (iir & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) {
539d0231070Smiao chen - Sun Microsystems - Beijing China                 pipeb_stats = I915_READ(PIPEBSTAT);
540d0231070Smiao chen - Sun Microsystems - Beijing China 
541d0231070Smiao chen - Sun Microsystems - Beijing China                 /* The vblank interrupt gets enabled even if we didn't ask for
542d0231070Smiao chen - Sun Microsystems - Beijing China                    it, so make sure it's shut down again */
543d0231070Smiao chen - Sun Microsystems - Beijing China                 if (!(dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B))
544d0231070Smiao chen - Sun Microsystems - Beijing China                         pipeb_stats &= ~(PIPE_START_VBLANK_INTERRUPT_ENABLE |
545d0231070Smiao chen - Sun Microsystems - Beijing China                                          PIPE_VBLANK_INTERRUPT_ENABLE);
546d0231070Smiao chen - Sun Microsystems - Beijing China                 else if (pipeb_stats & (PIPE_START_VBLANK_INTERRUPT_STATUS|
547d0231070Smiao chen - Sun Microsystems - Beijing China                                         PIPE_VBLANK_INTERRUPT_STATUS))
548d0231070Smiao chen - Sun Microsystems - Beijing China                 {
549d0231070Smiao chen - Sun Microsystems - Beijing China                         vblank++;
5500035d21cSmiao chen - Sun Microsystems - Beijing China                         drm_handle_vblank(dev, 1);
551d0231070Smiao chen - Sun Microsystems - Beijing China                 }
552d0231070Smiao chen - Sun Microsystems - Beijing China 
553d0231070Smiao chen - Sun Microsystems - Beijing China                 I915_WRITE(PIPEBSTAT, pipeb_stats);
554d0231070Smiao chen - Sun Microsystems - Beijing China         }
555ae115bc7Smrj        return IRQ_HANDLED;
556d0231070Smiao chen - Sun Microsystems - Beijing China 
557ae115bc7Smrj }
558ae115bc7Smrj 
i915_emit_irq(drm_device_t * dev)559e92e3a86Szw161486 int i915_emit_irq(drm_device_t * dev)
560ae115bc7Smrj {
561e92e3a86Szw161486 
562ae115bc7Smrj 	drm_i915_private_t *dev_priv = dev->dev_private;
563ae115bc7Smrj 	RING_LOCALS;
564ae115bc7Smrj 
565ae115bc7Smrj 	i915_kernel_lost_context(dev);
566ae115bc7Smrj 
5670035d21cSmiao chen - Sun Microsystems - Beijing China 	dev_priv->counter++;
5680035d21cSmiao chen - Sun Microsystems - Beijing China 	if (dev_priv->counter > 0x7FFFFFFFUL)
5690035d21cSmiao chen - Sun Microsystems - Beijing China 		dev_priv->counter = 1;
5700035d21cSmiao chen - Sun Microsystems - Beijing China 	if (dev_priv->sarea_priv)
5710035d21cSmiao chen - Sun Microsystems - Beijing China 		dev_priv->sarea_priv->last_enqueue = dev_priv->counter;
572ae115bc7Smrj 
5730035d21cSmiao chen - Sun Microsystems - Beijing China #if defined(__i386)
5740035d21cSmiao chen - Sun Microsystems - Beijing China 	if (IS_GM45(dev)) {
5750035d21cSmiao chen - Sun Microsystems - Beijing China 		BEGIN_LP_RING(3);
5760035d21cSmiao chen - Sun Microsystems - Beijing China 		OUT_RING(MI_STORE_DWORD_INDEX);
5770035d21cSmiao chen - Sun Microsystems - Beijing China 		OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
5780035d21cSmiao chen - Sun Microsystems - Beijing China 		OUT_RING(dev_priv->counter);
5790035d21cSmiao chen - Sun Microsystems - Beijing China 		ADVANCE_LP_RING();
5800035d21cSmiao chen - Sun Microsystems - Beijing China 
5810035d21cSmiao chen - Sun Microsystems - Beijing China 		(void) READ_BREADCRUMB(dev_priv);
582d0231070Smiao chen - Sun Microsystems - Beijing China 		BEGIN_LP_RING(2);
583e92e3a86Szw161486 		OUT_RING(0);
584d0231070Smiao chen - Sun Microsystems - Beijing China 		OUT_RING(MI_USER_INTERRUPT);
585ae115bc7Smrj 		ADVANCE_LP_RING();
5860035d21cSmiao chen - Sun Microsystems - Beijing China 	} else {
5870035d21cSmiao chen - Sun Microsystems - Beijing China #endif  /* __i386 */
5880035d21cSmiao chen - Sun Microsystems - Beijing China 	BEGIN_LP_RING(4);
5890035d21cSmiao chen - Sun Microsystems - Beijing China 	OUT_RING(MI_STORE_DWORD_INDEX);
5900035d21cSmiao chen - Sun Microsystems - Beijing China 	OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
5910035d21cSmiao chen - Sun Microsystems - Beijing China 	OUT_RING(dev_priv->counter);
5920035d21cSmiao chen - Sun Microsystems - Beijing China 	OUT_RING(MI_USER_INTERRUPT);
5930035d21cSmiao chen - Sun Microsystems - Beijing China 	ADVANCE_LP_RING();
5940035d21cSmiao chen - Sun Microsystems - Beijing China #if defined(__i386)
5950035d21cSmiao chen - Sun Microsystems - Beijing China 	}
5960035d21cSmiao chen - Sun Microsystems - Beijing China #endif  /* __i386 */
5970035d21cSmiao chen - Sun Microsystems - Beijing China 
5980035d21cSmiao chen - Sun Microsystems - Beijing China #if defined(__i386)
599*2e6e901dSmiao chen - Sun Microsystems - Beijing China 	if (IS_I965GM(dev) || IS_IGDNG(dev) || IS_GM45(dev))
6000035d21cSmiao chen - Sun Microsystems - Beijing China #else
601*2e6e901dSmiao chen - Sun Microsystems - Beijing China 	if (IS_I965GM(dev) || IS_IGDNG(dev))
6020035d21cSmiao chen - Sun Microsystems - Beijing China #endif  /* __i386 */
6030035d21cSmiao chen - Sun Microsystems - Beijing China 	{
6040035d21cSmiao chen - Sun Microsystems - Beijing China 		(void) READ_BREADCRUMB(dev_priv);
6050035d21cSmiao chen - Sun Microsystems - Beijing China 		BEGIN_LP_RING(2);
6060035d21cSmiao chen - Sun Microsystems - Beijing China 		OUT_RING(0);
6070035d21cSmiao chen - Sun Microsystems - Beijing China 		OUT_RING(0);
6080035d21cSmiao chen - Sun Microsystems - Beijing China 		ADVANCE_LP_RING();
6090035d21cSmiao chen - Sun Microsystems - Beijing China 		(void) READ_BREADCRUMB(dev_priv);
6100035d21cSmiao chen - Sun Microsystems - Beijing China 	}
611ae115bc7Smrj 
612e92e3a86Szw161486 	return dev_priv->counter;
613ae115bc7Smrj }
614ae115bc7Smrj 
i915_user_irq_on(struct drm_device * dev)6150035d21cSmiao chen - Sun Microsystems - Beijing China void i915_user_irq_on(struct drm_device *dev)
616e92e3a86Szw161486 {
6170035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
618e92e3a86Szw161486 	spin_lock(&dev_priv->user_irq_lock);
6190035d21cSmiao chen - Sun Microsystems - Beijing China 	if (dev->irq_enabled && (++dev_priv->user_irq_refcount == 1)){
620*2e6e901dSmiao chen - Sun Microsystems - Beijing China                if (IS_IGDNG(dev))
621*2e6e901dSmiao chen - Sun Microsystems - Beijing China                        igdng_enable_irq(dev_priv, GT_USER_INTERRUPT, 1);
622*2e6e901dSmiao chen - Sun Microsystems - Beijing China                else
623d0231070Smiao chen - Sun Microsystems - Beijing China                        i915_enable_irq(dev_priv, I915_USER_INTERRUPT);
624e92e3a86Szw161486 	}
625e92e3a86Szw161486 	spin_unlock(&dev_priv->user_irq_lock);
626e92e3a86Szw161486 
627e92e3a86Szw161486 }
628e92e3a86Szw161486 
i915_user_irq_off(struct drm_device * dev)6290035d21cSmiao chen - Sun Microsystems - Beijing China void i915_user_irq_off(struct drm_device *dev)
630e92e3a86Szw161486 {
6310035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
632e92e3a86Szw161486 	spin_lock(&dev_priv->user_irq_lock);
6330035d21cSmiao chen - Sun Microsystems - Beijing China 	if (dev->irq_enabled && (--dev_priv->user_irq_refcount == 0)) {
634*2e6e901dSmiao chen - Sun Microsystems - Beijing China                if (IS_IGDNG(dev))
635*2e6e901dSmiao chen - Sun Microsystems - Beijing China                        igdng_disable_irq(dev_priv, GT_USER_INTERRUPT, 1);
636*2e6e901dSmiao chen - Sun Microsystems - Beijing China                else
637d0231070Smiao chen - Sun Microsystems - Beijing China                        i915_disable_irq(dev_priv, I915_USER_INTERRUPT);
638e92e3a86Szw161486 	}
639e92e3a86Szw161486 	spin_unlock(&dev_priv->user_irq_lock);
640e92e3a86Szw161486 }
641e92e3a86Szw161486 
642e92e3a86Szw161486 
i915_wait_irq(drm_device_t * dev,int irq_nr)643ae115bc7Smrj static int i915_wait_irq(drm_device_t * dev, int irq_nr)
644ae115bc7Smrj {
645ae115bc7Smrj 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
646ae115bc7Smrj 	int ret = 0;
647*2e6e901dSmiao chen - Sun Microsystems - Beijing China 	int wait_time = 0;
648ae115bc7Smrj 
649d0231070Smiao chen - Sun Microsystems - Beijing China 	if (!dev_priv) {
650d0231070Smiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("called with no initialization\n");
651d0231070Smiao chen - Sun Microsystems - Beijing China 		return -EINVAL;
652d0231070Smiao chen - Sun Microsystems - Beijing China 	}
653d0231070Smiao chen - Sun Microsystems - Beijing China 
654*2e6e901dSmiao chen - Sun Microsystems - Beijing China waitmore:
655*2e6e901dSmiao chen - Sun Microsystems - Beijing China 	wait_time++;
656d0231070Smiao chen - Sun Microsystems - Beijing China 	if (READ_BREADCRUMB(dev_priv) >= irq_nr) {
6570035d21cSmiao chen - Sun Microsystems - Beijing China 		if (dev_priv->sarea_priv) {
658d0231070Smiao chen - Sun Microsystems - Beijing China 			dev_priv->sarea_priv->last_dispatch =
659d0231070Smiao chen - Sun Microsystems - Beijing China 				READ_BREADCRUMB(dev_priv);
6600035d21cSmiao chen - Sun Microsystems - Beijing China 		}
661ae115bc7Smrj 		return 0;
662d0231070Smiao chen - Sun Microsystems - Beijing China 	}
663d0231070Smiao chen - Sun Microsystems - Beijing China 	DRM_DEBUG("i915_wait_irq: irq_nr=%d breadcrumb=%d\n", irq_nr, READ_BREADCRUMB(dev_priv));
6640035d21cSmiao chen - Sun Microsystems - Beijing China 	i915_user_irq_on(dev);
665d0538f66Scg149915 	DRM_WAIT_ON(ret, &dev_priv->irq_queue, 3 * DRM_HZ,
666ae115bc7Smrj 		    READ_BREADCRUMB(dev_priv) >= irq_nr);
6670035d21cSmiao chen - Sun Microsystems - Beijing China 	i915_user_irq_off(dev);
668ae115bc7Smrj 
6690035d21cSmiao chen - Sun Microsystems - Beijing China 	if (ret == EBUSY) {
670*2e6e901dSmiao chen - Sun Microsystems - Beijing China 		if (wait_time > 5) {
671d0231070Smiao chen - Sun Microsystems - Beijing China 		DRM_DEBUG("%d: EBUSY -- rec: %d emitted: %d\n",
672d0231070Smiao chen - Sun Microsystems - Beijing China 			  ret,
673ae115bc7Smrj 			  READ_BREADCRUMB(dev_priv), (int)dev_priv->counter);
674*2e6e901dSmiao chen - Sun Microsystems - Beijing China 			return ret;
675*2e6e901dSmiao chen - Sun Microsystems - Beijing China 		}
676*2e6e901dSmiao chen - Sun Microsystems - Beijing China 		goto waitmore;
677ae115bc7Smrj 	}
678ae115bc7Smrj 
679d0231070Smiao chen - Sun Microsystems - Beijing China 	if (dev_priv->sarea_priv)
680ae115bc7Smrj 		dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
681e92e3a86Szw161486 
682*2e6e901dSmiao chen - Sun Microsystems - Beijing China 	if (ret == EINTR) {
683*2e6e901dSmiao chen - Sun Microsystems - Beijing China 		if (wait_time > 5) {
684*2e6e901dSmiao chen - Sun Microsystems - Beijing China 			DRM_DEBUG("EINTR wait %d now %d", dev_priv->counter, READ_BREADCRUMB(dev_priv));
685*2e6e901dSmiao chen - Sun Microsystems - Beijing China 			return ret;
686*2e6e901dSmiao chen - Sun Microsystems - Beijing China 		}
687*2e6e901dSmiao chen - Sun Microsystems - Beijing China 		goto waitmore;
688*2e6e901dSmiao chen - Sun Microsystems - Beijing China 	}
689*2e6e901dSmiao chen - Sun Microsystems - Beijing China 
690e92e3a86Szw161486 	return ret;
691e92e3a86Szw161486 }
692e92e3a86Szw161486 
693e92e3a86Szw161486 
694ae115bc7Smrj /* Needs the lock as it touches the ring.
695ae115bc7Smrj  */
696ae115bc7Smrj /*ARGSUSED*/
i915_irq_emit(DRM_IOCTL_ARGS)697ae115bc7Smrj int i915_irq_emit(DRM_IOCTL_ARGS)
698ae115bc7Smrj {
699ae115bc7Smrj 	DRM_DEVICE;
700ae115bc7Smrj 	drm_i915_private_t *dev_priv = dev->dev_private;
701ae115bc7Smrj 	drm_i915_irq_emit_t emit;
702ae115bc7Smrj 	int result;
703ae115bc7Smrj 
704d0538f66Scg149915 	LOCK_TEST_WITH_RETURN(dev, fpriv);
705ae115bc7Smrj 
706ae115bc7Smrj 	if (!dev_priv) {
707ae115bc7Smrj 		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
708d0538f66Scg149915 		return (EINVAL);
709ae115bc7Smrj 	}
710ae115bc7Smrj 
7110035d21cSmiao chen - Sun Microsystems - Beijing China 
712ae115bc7Smrj 	if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
713ae115bc7Smrj 		drm_i915_irq_emit32_t irq_emit32;
714ae115bc7Smrj 
715d0538f66Scg149915 		DRM_COPYFROM_WITH_RETURN(&irq_emit32,
716ae115bc7Smrj 			(drm_i915_irq_emit32_t __user *) data,
717ae115bc7Smrj 			sizeof (drm_i915_irq_emit32_t));
718ae115bc7Smrj 		emit.irq_seq = (int __user *)(uintptr_t)irq_emit32.irq_seq;
719ae115bc7Smrj 	} else
720d0538f66Scg149915 		DRM_COPYFROM_WITH_RETURN(&emit,
721d0538f66Scg149915 		    (drm_i915_irq_emit_t __user *) data, sizeof(emit));
722ae115bc7Smrj 
7230035d21cSmiao chen - Sun Microsystems - Beijing China 	spin_lock(&dev->struct_mutex);
724ae115bc7Smrj 	result = i915_emit_irq(dev);
7250035d21cSmiao chen - Sun Microsystems - Beijing China 	spin_unlock(&dev->struct_mutex);
726ae115bc7Smrj 
727ae115bc7Smrj 	if (DRM_COPY_TO_USER(emit.irq_seq, &result, sizeof(int))) {
728ae115bc7Smrj 		DRM_ERROR("copy_to_user\n");
729d0538f66Scg149915 		return (EFAULT);
730ae115bc7Smrj 	}
731ae115bc7Smrj 
732ae115bc7Smrj 	return 0;
733ae115bc7Smrj }
734ae115bc7Smrj 
735ae115bc7Smrj /* Doesn't need the hardware lock.
736ae115bc7Smrj  */
737ae115bc7Smrj /*ARGSUSED*/
i915_irq_wait(DRM_IOCTL_ARGS)738ae115bc7Smrj int i915_irq_wait(DRM_IOCTL_ARGS)
739ae115bc7Smrj {
740ae115bc7Smrj 	DRM_DEVICE;
741ae115bc7Smrj 	drm_i915_private_t *dev_priv = dev->dev_private;
742ae115bc7Smrj 	drm_i915_irq_wait_t irqwait;
743ae115bc7Smrj 
744ae115bc7Smrj 	if (!dev_priv) {
745ae115bc7Smrj 		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
746d0538f66Scg149915 		return (EINVAL);
747ae115bc7Smrj 	}
748ae115bc7Smrj 
749d0538f66Scg149915 	DRM_COPYFROM_WITH_RETURN(&irqwait,
750d0538f66Scg149915 	    (drm_i915_irq_wait_t __user *) data, sizeof(irqwait));
751ae115bc7Smrj 
752ae115bc7Smrj 	return i915_wait_irq(dev, irqwait.irq_seq);
753ae115bc7Smrj }
754ae115bc7Smrj 
igdng_enable_vblank(struct drm_device * dev,int pipe)755*2e6e901dSmiao chen - Sun Microsystems - Beijing China static void igdng_enable_vblank(struct drm_device *dev, int pipe)
756*2e6e901dSmiao chen - Sun Microsystems - Beijing China {
757*2e6e901dSmiao chen - Sun Microsystems - Beijing China 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
758*2e6e901dSmiao chen - Sun Microsystems - Beijing China 	u32 vblank;
759*2e6e901dSmiao chen - Sun Microsystems - Beijing China 
760*2e6e901dSmiao chen - Sun Microsystems - Beijing China 	if (pipe == 0)
761*2e6e901dSmiao chen - Sun Microsystems - Beijing China 		vblank = DE_PIPEA_VBLANK;
762*2e6e901dSmiao chen - Sun Microsystems - Beijing China 	else
763*2e6e901dSmiao chen - Sun Microsystems - Beijing China 		vblank = DE_PIPEB_VBLANK;
764*2e6e901dSmiao chen - Sun Microsystems - Beijing China 
765*2e6e901dSmiao chen - Sun Microsystems - Beijing China 	if ((dev_priv->de_irq_enable_reg & vblank) == 0) {
766*2e6e901dSmiao chen - Sun Microsystems - Beijing China 		igdng_enable_irq(dev_priv, vblank, 0);
767*2e6e901dSmiao chen - Sun Microsystems - Beijing China 		dev_priv->de_irq_enable_reg |= vblank;
768*2e6e901dSmiao chen - Sun Microsystems - Beijing China 		I915_WRITE(DEIER, dev_priv->de_irq_enable_reg);
769*2e6e901dSmiao chen - Sun Microsystems - Beijing China 		(void) I915_READ(DEIER);
770*2e6e901dSmiao chen - Sun Microsystems - Beijing China 	}
771*2e6e901dSmiao chen - Sun Microsystems - Beijing China }
772*2e6e901dSmiao chen - Sun Microsystems - Beijing China 
igdng_disable_vblank(struct drm_device * dev,int pipe)773*2e6e901dSmiao chen - Sun Microsystems - Beijing China static void igdng_disable_vblank(struct drm_device *dev, int pipe)
774*2e6e901dSmiao chen - Sun Microsystems - Beijing China {
775*2e6e901dSmiao chen - Sun Microsystems - Beijing China 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
776*2e6e901dSmiao chen - Sun Microsystems - Beijing China 	u32 vblank;
777*2e6e901dSmiao chen - Sun Microsystems - Beijing China 
778*2e6e901dSmiao chen - Sun Microsystems - Beijing China 	if (pipe == 0)
779*2e6e901dSmiao chen - Sun Microsystems - Beijing China 		vblank = DE_PIPEA_VBLANK;
780*2e6e901dSmiao chen - Sun Microsystems - Beijing China 	else
781*2e6e901dSmiao chen - Sun Microsystems - Beijing China 		vblank = DE_PIPEB_VBLANK;
782*2e6e901dSmiao chen - Sun Microsystems - Beijing China 
783*2e6e901dSmiao chen - Sun Microsystems - Beijing China 	if ((dev_priv->de_irq_enable_reg & vblank) != 0) {
784*2e6e901dSmiao chen - Sun Microsystems - Beijing China 		igdng_disable_irq(dev_priv, vblank, 0);
785*2e6e901dSmiao chen - Sun Microsystems - Beijing China 		dev_priv->de_irq_enable_reg &= ~vblank;
786*2e6e901dSmiao chen - Sun Microsystems - Beijing China 		I915_WRITE(DEIER, dev_priv->de_irq_enable_reg);
787*2e6e901dSmiao chen - Sun Microsystems - Beijing China 		(void) I915_READ(DEIER);
788*2e6e901dSmiao chen - Sun Microsystems - Beijing China 	}
789*2e6e901dSmiao chen - Sun Microsystems - Beijing China }
790*2e6e901dSmiao chen - Sun Microsystems - Beijing China 
i915_enable_vblank(struct drm_device * dev,int pipe)7910035d21cSmiao chen - Sun Microsystems - Beijing China int i915_enable_vblank(struct drm_device *dev, int pipe)
792d0231070Smiao chen - Sun Microsystems - Beijing China {
793d0231070Smiao chen - Sun Microsystems - Beijing China 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
7940035d21cSmiao chen - Sun Microsystems - Beijing China 	int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
7950035d21cSmiao chen - Sun Microsystems - Beijing China 	u32 pipeconf;
796d0231070Smiao chen - Sun Microsystems - Beijing China 
7970035d21cSmiao chen - Sun Microsystems - Beijing China 	pipeconf = I915_READ(pipeconf_reg);
7980035d21cSmiao chen - Sun Microsystems - Beijing China 	if (!(pipeconf & PIPEACONF_ENABLE))
7990035d21cSmiao chen - Sun Microsystems - Beijing China 		return -EINVAL;
800d0231070Smiao chen - Sun Microsystems - Beijing China 
8010035d21cSmiao chen - Sun Microsystems - Beijing China 	spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
802*2e6e901dSmiao chen - Sun Microsystems - Beijing China 	if (IS_IGDNG(dev))
803*2e6e901dSmiao chen - Sun Microsystems - Beijing China 		igdng_enable_vblank(dev, pipe);
804*2e6e901dSmiao chen - Sun Microsystems - Beijing China 	else if (IS_I965G(dev))
8050035d21cSmiao chen - Sun Microsystems - Beijing China 		i915_enable_pipestat(dev_priv, pipe,
8060035d21cSmiao chen - Sun Microsystems - Beijing China 				     PIPE_START_VBLANK_INTERRUPT_ENABLE);
807d0231070Smiao chen - Sun Microsystems - Beijing China 	else
8080035d21cSmiao chen - Sun Microsystems - Beijing China 		i915_enable_pipestat(dev_priv, pipe,
8090035d21cSmiao chen - Sun Microsystems - Beijing China 				     PIPE_VBLANK_INTERRUPT_ENABLE);
8100035d21cSmiao chen - Sun Microsystems - Beijing China 	spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
811d0231070Smiao chen - Sun Microsystems - Beijing China 
812d0231070Smiao chen - Sun Microsystems - Beijing China 	return 0;
813d0231070Smiao chen - Sun Microsystems - Beijing China }
814d0231070Smiao chen - Sun Microsystems - Beijing China 
i915_disable_vblank(struct drm_device * dev,int pipe)8150035d21cSmiao chen - Sun Microsystems - Beijing China void i915_disable_vblank(struct drm_device *dev, int pipe)
816e92e3a86Szw161486 {
817e92e3a86Szw161486 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
818e92e3a86Szw161486 
8190035d21cSmiao chen - Sun Microsystems - Beijing China 	spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
820*2e6e901dSmiao chen - Sun Microsystems - Beijing China 	if (IS_IGDNG(dev))
821*2e6e901dSmiao chen - Sun Microsystems - Beijing China 		igdng_disable_vblank(dev, pipe);
822*2e6e901dSmiao chen - Sun Microsystems - Beijing China 	else
8230035d21cSmiao chen - Sun Microsystems - Beijing China 	i915_disable_pipestat(dev_priv, pipe,
8240035d21cSmiao chen - Sun Microsystems - Beijing China 			      PIPE_VBLANK_INTERRUPT_ENABLE |
8250035d21cSmiao chen - Sun Microsystems - Beijing China 			      PIPE_START_VBLANK_INTERRUPT_ENABLE);
8260035d21cSmiao chen - Sun Microsystems - Beijing China 	spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
827e92e3a86Szw161486 }
828e92e3a86Szw161486 
829d0231070Smiao chen - Sun Microsystems - Beijing China /* Set the vblank monitor pipe
830d0231070Smiao chen - Sun Microsystems - Beijing China  */
831d0231070Smiao chen - Sun Microsystems - Beijing China /*ARGSUSED*/
i915_vblank_pipe_set(DRM_IOCTL_ARGS)832d0231070Smiao chen - Sun Microsystems - Beijing China int i915_vblank_pipe_set(DRM_IOCTL_ARGS)
833d0231070Smiao chen - Sun Microsystems - Beijing China {
834d0231070Smiao chen - Sun Microsystems - Beijing China 	DRM_DEVICE;
835d0231070Smiao chen - Sun Microsystems - Beijing China 	drm_i915_private_t *dev_priv = dev->dev_private;
836d0231070Smiao chen - Sun Microsystems - Beijing China 
837d0231070Smiao chen - Sun Microsystems - Beijing China 	if (!dev_priv) {
838d0231070Smiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("called with no initialization\n");
839d0231070Smiao chen - Sun Microsystems - Beijing China 		return (-EINVAL);
840d0231070Smiao chen - Sun Microsystems - Beijing China 	}
841d0231070Smiao chen - Sun Microsystems - Beijing China 
842d0231070Smiao chen - Sun Microsystems - Beijing China 	return (0);
843d0231070Smiao chen - Sun Microsystems - Beijing China }
844d0231070Smiao chen - Sun Microsystems - Beijing China 
845d0231070Smiao chen - Sun Microsystems - Beijing China /*ARGSUSED*/
i915_vblank_pipe_get(DRM_IOCTL_ARGS)846d0231070Smiao chen - Sun Microsystems - Beijing China int i915_vblank_pipe_get(DRM_IOCTL_ARGS)
847d0231070Smiao chen - Sun Microsystems - Beijing China {
848d0231070Smiao chen - Sun Microsystems - Beijing China 	DRM_DEVICE;
849d0231070Smiao chen - Sun Microsystems - Beijing China 	drm_i915_private_t *dev_priv = dev->dev_private;
850d0231070Smiao chen - Sun Microsystems - Beijing China 	drm_i915_vblank_pipe_t pipe;
851d0231070Smiao chen - Sun Microsystems - Beijing China 
852d0231070Smiao chen - Sun Microsystems - Beijing China 	if (!dev_priv) {
853d0231070Smiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("called with no initialization\n");
854d0231070Smiao chen - Sun Microsystems - Beijing China 		return -EINVAL;
855d0231070Smiao chen - Sun Microsystems - Beijing China 	}
856d0231070Smiao chen - Sun Microsystems - Beijing China 
857d0231070Smiao chen - Sun Microsystems - Beijing China 	DRM_COPYFROM_WITH_RETURN(&pipe, (drm_i915_vblank_pipe_t __user *)data, sizeof (pipe));
858d0231070Smiao chen - Sun Microsystems - Beijing China 
859d0231070Smiao chen - Sun Microsystems - Beijing China 	pipe.pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
860d0231070Smiao chen - Sun Microsystems - Beijing China 
861d0231070Smiao chen - Sun Microsystems - Beijing China 	return 0;
862d0231070Smiao chen - Sun Microsystems - Beijing China }
863d0231070Smiao chen - Sun Microsystems - Beijing China 
864d0231070Smiao chen - Sun Microsystems - Beijing China /**
865d0231070Smiao chen - Sun Microsystems - Beijing China  * Schedule buffer swap at given vertical blank.
866d0231070Smiao chen - Sun Microsystems - Beijing China  */
867d0231070Smiao chen - Sun Microsystems - Beijing China /*ARGSUSED*/
i915_vblank_swap(DRM_IOCTL_ARGS)868d0231070Smiao chen - Sun Microsystems - Beijing China int i915_vblank_swap(DRM_IOCTL_ARGS)
869d0231070Smiao chen - Sun Microsystems - Beijing China {
8700035d21cSmiao chen - Sun Microsystems - Beijing China         /* The delayed swap mechanism was fundamentally racy, and has been
8710035d21cSmiao chen - Sun Microsystems - Beijing China         * removed.  The model was that the client requested a delayed flip/swap
8720035d21cSmiao chen - Sun Microsystems - Beijing China         * from the kernel, then waited for vblank before continuing to perform
8730035d21cSmiao chen - Sun Microsystems - Beijing China         * rendering.  The problem was that the kernel might wake the client
8740035d21cSmiao chen - Sun Microsystems - Beijing China         * up before it dispatched the vblank swap (since the lock has to be
8750035d21cSmiao chen - Sun Microsystems - Beijing China         * held while touching the ringbuffer), in which case the client would
8760035d21cSmiao chen - Sun Microsystems - Beijing China         * clear and start the next frame before the swap occurred, and
8770035d21cSmiao chen - Sun Microsystems - Beijing China         * flicker would occur in addition to likely missing the vblank.
8780035d21cSmiao chen - Sun Microsystems - Beijing China         *
8790035d21cSmiao chen - Sun Microsystems - Beijing China         * In the absence of this ioctl, userland falls back to a correct path
8800035d21cSmiao chen - Sun Microsystems - Beijing China         * of waiting for a vblank, then dispatching the swap on its own.
8810035d21cSmiao chen - Sun Microsystems - Beijing China         * Context switching to userland and back is plenty fast enough for
8820035d21cSmiao chen - Sun Microsystems - Beijing China         * meeting the requirements of vblank swapping.
883d0231070Smiao chen - Sun Microsystems - Beijing China         */
884d0231070Smiao chen - Sun Microsystems - Beijing China 	return -EINVAL;
885d0231070Smiao chen - Sun Microsystems - Beijing China 
886d0231070Smiao chen - Sun Microsystems - Beijing China }
887d0231070Smiao chen - Sun Microsystems - Beijing China 
888ae115bc7Smrj /* drm_dma.h hooks
889ae115bc7Smrj */
890*2e6e901dSmiao chen - Sun Microsystems - Beijing China 
igdng_irq_preinstall(struct drm_device * dev)891*2e6e901dSmiao chen - Sun Microsystems - Beijing China static void igdng_irq_preinstall(struct drm_device *dev)
892*2e6e901dSmiao chen - Sun Microsystems - Beijing China {
893*2e6e901dSmiao chen - Sun Microsystems - Beijing China        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
894*2e6e901dSmiao chen - Sun Microsystems - Beijing China 
895*2e6e901dSmiao chen - Sun Microsystems - Beijing China        I915_WRITE(HWSTAM, 0xeffe);
896*2e6e901dSmiao chen - Sun Microsystems - Beijing China 
897*2e6e901dSmiao chen - Sun Microsystems - Beijing China       /* XXX hotplug from PCH */
898*2e6e901dSmiao chen - Sun Microsystems - Beijing China 
899*2e6e901dSmiao chen - Sun Microsystems - Beijing China        I915_WRITE(DEIMR, 0xffffffff);
900*2e6e901dSmiao chen - Sun Microsystems - Beijing China        I915_WRITE(DEIER, 0x0);
901*2e6e901dSmiao chen - Sun Microsystems - Beijing China        (void) I915_READ(DEIER);
902*2e6e901dSmiao chen - Sun Microsystems - Beijing China 
903*2e6e901dSmiao chen - Sun Microsystems - Beijing China        /* and GT */
904*2e6e901dSmiao chen - Sun Microsystems - Beijing China        I915_WRITE(GTIMR, 0xffffffff);
905*2e6e901dSmiao chen - Sun Microsystems - Beijing China        I915_WRITE(GTIER, 0x0);
906*2e6e901dSmiao chen - Sun Microsystems - Beijing China        (void) I915_READ(GTIER);
907*2e6e901dSmiao chen - Sun Microsystems - Beijing China }
908*2e6e901dSmiao chen - Sun Microsystems - Beijing China 
igdng_irq_postinstall(struct drm_device * dev)909*2e6e901dSmiao chen - Sun Microsystems - Beijing China static int igdng_irq_postinstall(struct drm_device *dev)
910*2e6e901dSmiao chen - Sun Microsystems - Beijing China {
911*2e6e901dSmiao chen - Sun Microsystems - Beijing China        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
912*2e6e901dSmiao chen - Sun Microsystems - Beijing China        /* enable kind of interrupts always enabled */
913*2e6e901dSmiao chen - Sun Microsystems - Beijing China        u32 display_mask = DE_MASTER_IRQ_CONTROL /*| DE_PCH_EVENT */;
914*2e6e901dSmiao chen - Sun Microsystems - Beijing China        u32 render_mask = GT_USER_INTERRUPT;
915*2e6e901dSmiao chen - Sun Microsystems - Beijing China 
916*2e6e901dSmiao chen - Sun Microsystems - Beijing China        dev_priv->irq_mask_reg = ~display_mask;
917*2e6e901dSmiao chen - Sun Microsystems - Beijing China        dev_priv->de_irq_enable_reg = display_mask;
918*2e6e901dSmiao chen - Sun Microsystems - Beijing China 
919*2e6e901dSmiao chen - Sun Microsystems - Beijing China        /* should always can generate irq */
920*2e6e901dSmiao chen - Sun Microsystems - Beijing China        I915_WRITE(DEIIR, I915_READ(DEIIR));
921*2e6e901dSmiao chen - Sun Microsystems - Beijing China        (void) I915_READ(DEIIR);
922*2e6e901dSmiao chen - Sun Microsystems - Beijing China        I915_WRITE(DEIMR, dev_priv->irq_mask_reg);
923*2e6e901dSmiao chen - Sun Microsystems - Beijing China        I915_WRITE(DEIER, dev_priv->de_irq_enable_reg);
924*2e6e901dSmiao chen - Sun Microsystems - Beijing China        (void) I915_READ(DEIER);
925*2e6e901dSmiao chen - Sun Microsystems - Beijing China 
926*2e6e901dSmiao chen - Sun Microsystems - Beijing China        /* user interrupt should be enabled, but masked initial */
927*2e6e901dSmiao chen - Sun Microsystems - Beijing China        dev_priv->gt_irq_mask_reg = 0xffffffff;
928*2e6e901dSmiao chen - Sun Microsystems - Beijing China        dev_priv->gt_irq_enable_reg = render_mask;
929*2e6e901dSmiao chen - Sun Microsystems - Beijing China 
930*2e6e901dSmiao chen - Sun Microsystems - Beijing China        I915_WRITE(GTIIR, I915_READ(GTIIR));
931*2e6e901dSmiao chen - Sun Microsystems - Beijing China        (void) I915_READ(GTIIR);
932*2e6e901dSmiao chen - Sun Microsystems - Beijing China        I915_WRITE(GTIMR, dev_priv->gt_irq_mask_reg);
933*2e6e901dSmiao chen - Sun Microsystems - Beijing China        I915_WRITE(GTIER, dev_priv->gt_irq_enable_reg);
934*2e6e901dSmiao chen - Sun Microsystems - Beijing China        (void) I915_READ(GTIER);
935*2e6e901dSmiao chen - Sun Microsystems - Beijing China 
936*2e6e901dSmiao chen - Sun Microsystems - Beijing China        return 0;
937*2e6e901dSmiao chen - Sun Microsystems - Beijing China }
938*2e6e901dSmiao chen - Sun Microsystems - Beijing China 
igdng_irq_uninstall(struct drm_device * dev)939*2e6e901dSmiao chen - Sun Microsystems - Beijing China static void igdng_irq_uninstall(struct drm_device *dev)
940*2e6e901dSmiao chen - Sun Microsystems - Beijing China {
941*2e6e901dSmiao chen - Sun Microsystems - Beijing China        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
942*2e6e901dSmiao chen - Sun Microsystems - Beijing China        I915_WRITE(HWSTAM, 0xffffffff);
943*2e6e901dSmiao chen - Sun Microsystems - Beijing China 
944*2e6e901dSmiao chen - Sun Microsystems - Beijing China        I915_WRITE(DEIMR, 0xffffffff);
945*2e6e901dSmiao chen - Sun Microsystems - Beijing China        I915_WRITE(DEIER, 0x0);
946*2e6e901dSmiao chen - Sun Microsystems - Beijing China        I915_WRITE(DEIIR, I915_READ(DEIIR));
947*2e6e901dSmiao chen - Sun Microsystems - Beijing China 
948*2e6e901dSmiao chen - Sun Microsystems - Beijing China        I915_WRITE(GTIMR, 0xffffffff);
949*2e6e901dSmiao chen - Sun Microsystems - Beijing China        I915_WRITE(GTIER, 0x0);
950*2e6e901dSmiao chen - Sun Microsystems - Beijing China        I915_WRITE(GTIIR, I915_READ(GTIIR));
951*2e6e901dSmiao chen - Sun Microsystems - Beijing China }
952*2e6e901dSmiao chen - Sun Microsystems - Beijing China 
i915_driver_irq_preinstall(drm_device_t * dev)9530f7bfed6Smiao chen - Sun Microsystems - Beijing China int i915_driver_irq_preinstall(drm_device_t * dev)
954ae115bc7Smrj {
955ae115bc7Smrj 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
956ae115bc7Smrj 
9570f7bfed6Smiao chen - Sun Microsystems - Beijing China 	if (!dev_priv->mmio_map)
9580f7bfed6Smiao chen - Sun Microsystems - Beijing China 		return -EINVAL;
9590f7bfed6Smiao chen - Sun Microsystems - Beijing China 
960*2e6e901dSmiao chen - Sun Microsystems - Beijing China 	if (IS_IGDNG(dev)) {
961*2e6e901dSmiao chen - Sun Microsystems - Beijing China                igdng_irq_preinstall(dev);
962*2e6e901dSmiao chen - Sun Microsystems - Beijing China                return 0;
963*2e6e901dSmiao chen - Sun Microsystems - Beijing China 	}
964*2e6e901dSmiao chen - Sun Microsystems - Beijing China 
9650035d21cSmiao chen - Sun Microsystems - Beijing China 	I915_WRITE16(HWSTAM, 0xeffe);
9660035d21cSmiao chen - Sun Microsystems - Beijing China 	I915_WRITE(PIPEASTAT, 0);
9670035d21cSmiao chen - Sun Microsystems - Beijing China 	I915_WRITE(PIPEBSTAT, 0);
968d0231070Smiao chen - Sun Microsystems - Beijing China 	I915_WRITE(IMR, 0xffffffff);
9690035d21cSmiao chen - Sun Microsystems - Beijing China 	I915_WRITE16(IER, 0x0);
9700035d21cSmiao chen - Sun Microsystems - Beijing China 	(void) I915_READ(IER);
9710f7bfed6Smiao chen - Sun Microsystems - Beijing China 
9720f7bfed6Smiao chen - Sun Microsystems - Beijing China 	return 0;
973ae115bc7Smrj }
974ae115bc7Smrj 
i915_driver_irq_postinstall(drm_device_t * dev)975ae115bc7Smrj void i915_driver_irq_postinstall(drm_device_t * dev)
976ae115bc7Smrj {
9770035d21cSmiao chen - Sun Microsystems - Beijing China 	int error_mask;
978ae115bc7Smrj 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
979ae115bc7Smrj 
980d0231070Smiao chen - Sun Microsystems - Beijing China 	dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
981d0538f66Scg149915 
982*2e6e901dSmiao chen - Sun Microsystems - Beijing China 	if (IS_IGDNG(dev)) {
983*2e6e901dSmiao chen - Sun Microsystems - Beijing China 		(void) igdng_irq_postinstall(dev);
984*2e6e901dSmiao chen - Sun Microsystems - Beijing China 		DRM_INIT_WAITQUEUE(&dev_priv->irq_queue, DRM_INTR_PRI(dev));
985*2e6e901dSmiao chen - Sun Microsystems - Beijing China 		return;
986*2e6e901dSmiao chen - Sun Microsystems - Beijing China 	}
987*2e6e901dSmiao chen - Sun Microsystems - Beijing China 
9880035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Unmask the interrupts that we always want on. */
9890035d21cSmiao chen - Sun Microsystems - Beijing China 	dev_priv->irq_mask_reg = ~I915_INTERRUPT_ENABLE_FIX;
9900035d21cSmiao chen - Sun Microsystems - Beijing China 
9910035d21cSmiao chen - Sun Microsystems - Beijing China 	dev_priv->pipestat[0] = 0;
9920035d21cSmiao chen - Sun Microsystems - Beijing China 	dev_priv->pipestat[1] = 0;
9930035d21cSmiao chen - Sun Microsystems - Beijing China 
9940035d21cSmiao chen - Sun Microsystems - Beijing China 	/*
9950035d21cSmiao chen - Sun Microsystems - Beijing China 	 * Enable some error detection, note the instruction error mask
9960035d21cSmiao chen - Sun Microsystems - Beijing China 	 * bit is reserved, so we leave it masked.
9970035d21cSmiao chen - Sun Microsystems - Beijing China 	 */
9980035d21cSmiao chen - Sun Microsystems - Beijing China 	if (IS_G4X(dev)) {
9990035d21cSmiao chen - Sun Microsystems - Beijing China 		error_mask = ~(GM45_ERROR_PAGE_TABLE |
10000035d21cSmiao chen - Sun Microsystems - Beijing China 			       GM45_ERROR_MEM_PRIV |
10010035d21cSmiao chen - Sun Microsystems - Beijing China 			       GM45_ERROR_CP_PRIV |
10020035d21cSmiao chen - Sun Microsystems - Beijing China 			       I915_ERROR_MEMORY_REFRESH);
10030035d21cSmiao chen - Sun Microsystems - Beijing China 	} else {
10040035d21cSmiao chen - Sun Microsystems - Beijing China 		error_mask = ~(I915_ERROR_PAGE_TABLE |
10050035d21cSmiao chen - Sun Microsystems - Beijing China 			       I915_ERROR_MEMORY_REFRESH);
10060035d21cSmiao chen - Sun Microsystems - Beijing China 	}
10070035d21cSmiao chen - Sun Microsystems - Beijing China 	I915_WRITE(EMR, error_mask);
10080035d21cSmiao chen - Sun Microsystems - Beijing China 
10090035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Disable pipe interrupt enables, clear pending pipe status */
10100035d21cSmiao chen - Sun Microsystems - Beijing China 	I915_WRITE(PIPEASTAT, I915_READ(PIPEASTAT) & 0x8000ffff);
10110035d21cSmiao chen - Sun Microsystems - Beijing China 	I915_WRITE(PIPEBSTAT, I915_READ(PIPEBSTAT) & 0x8000ffff);
1012*2e6e901dSmiao chen - Sun Microsystems - Beijing China 	(void) I915_READ(PIPEASTAT);
1013*2e6e901dSmiao chen - Sun Microsystems - Beijing China         (void) I915_READ(PIPEBSTAT);
10140035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Clear pending interrupt status */
10150035d21cSmiao chen - Sun Microsystems - Beijing China 	I915_WRITE(IIR, I915_READ(IIR));
10160035d21cSmiao chen - Sun Microsystems - Beijing China 
1017*2e6e901dSmiao chen - Sun Microsystems - Beijing China 	(void) I915_READ(IIR);
10180035d21cSmiao chen - Sun Microsystems - Beijing China 	I915_WRITE(IMR, dev_priv->irq_mask_reg);
10190035d21cSmiao chen - Sun Microsystems - Beijing China 	I915_WRITE(IER, I915_INTERRUPT_ENABLE_MASK);
10200035d21cSmiao chen - Sun Microsystems - Beijing China 	(void) I915_READ(IER);
1021d0538f66Scg149915 
1022d0231070Smiao chen - Sun Microsystems - Beijing China 	DRM_INIT_WAITQUEUE(&dev_priv->irq_queue, DRM_INTR_PRI(dev));
1023e92e3a86Szw161486 
1024d0231070Smiao chen - Sun Microsystems - Beijing China 	return;
1025ae115bc7Smrj }
1026ae115bc7Smrj 
i915_driver_irq_uninstall(drm_device_t * dev)1027ae115bc7Smrj void i915_driver_irq_uninstall(drm_device_t * dev)
1028ae115bc7Smrj {
1029ae115bc7Smrj 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
10300035d21cSmiao chen - Sun Microsystems - Beijing China 	if ((!dev_priv) || (dev->irq_enabled == 0))
1031ae115bc7Smrj 		return;
1032ae115bc7Smrj 
1033d0231070Smiao chen - Sun Microsystems - Beijing China 	dev_priv->vblank_pipe = 0;
1034e92e3a86Szw161486 
1035*2e6e901dSmiao chen - Sun Microsystems - Beijing China 	if (IS_IGDNG(dev)) {
1036*2e6e901dSmiao chen - Sun Microsystems - Beijing China 		igdng_irq_uninstall(dev);
1037*2e6e901dSmiao chen - Sun Microsystems - Beijing China 		DRM_FINI_WAITQUEUE(&dev_priv->irq_queue);
1038*2e6e901dSmiao chen - Sun Microsystems - Beijing China 		return;
1039*2e6e901dSmiao chen - Sun Microsystems - Beijing China 	}
1040*2e6e901dSmiao chen - Sun Microsystems - Beijing China 
1041d0231070Smiao chen - Sun Microsystems - Beijing China 	I915_WRITE(HWSTAM, 0xffffffff);
10420035d21cSmiao chen - Sun Microsystems - Beijing China 	I915_WRITE(PIPEASTAT, 0);
10430035d21cSmiao chen - Sun Microsystems - Beijing China 	I915_WRITE(PIPEBSTAT, 0);
1044d0231070Smiao chen - Sun Microsystems - Beijing China 	I915_WRITE(IMR, 0xffffffff);
1045d0231070Smiao chen - Sun Microsystems - Beijing China 	I915_WRITE(IER, 0x0);
1046d0538f66Scg149915 
10470035d21cSmiao chen - Sun Microsystems - Beijing China 	I915_WRITE(PIPEASTAT, I915_READ(PIPEASTAT) & 0x8000ffff);
10480035d21cSmiao chen - Sun Microsystems - Beijing China 	I915_WRITE(PIPEBSTAT, I915_READ(PIPEBSTAT) & 0x8000ffff);
10490035d21cSmiao chen - Sun Microsystems - Beijing China 	I915_WRITE(IIR, I915_READ(IIR));
1050d0538f66Scg149915 
10510035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_FINI_WAITQUEUE(&dev_priv->irq_queue);
1052ae115bc7Smrj }
1053