xref: /titanic_50/usr/src/uts/intel/io/drm/i915_dma.c (revision c1374a13e412c4ec42cba867e57347a0e049a822)
1ae115bc7Smrj /* BEGIN CSTYLED */
2ae115bc7Smrj 
3ae115bc7Smrj /* i915_dma.c -- DMA 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 
42dc8c6b69Sms148562 
43e92e3a86Szw161486 
44ae115bc7Smrj /* Really want an OS-independent resettable timer.  Would like to have
45ae115bc7Smrj  * this loop run for (eg) 3 sec, but have the timer reset every time
46ae115bc7Smrj  * the head pointer changes, so that EBUSY only happens if the ring
47ae115bc7Smrj  * actually stalls for (eg) 3 seconds.
48ae115bc7Smrj  */
49ae115bc7Smrj /*ARGSUSED*/
i915_wait_ring(drm_device_t * dev,int n,const char * caller)50ae115bc7Smrj int i915_wait_ring(drm_device_t * dev, int n, const char *caller)
51ae115bc7Smrj {
52ae115bc7Smrj 	drm_i915_private_t *dev_priv = dev->dev_private;
53ae115bc7Smrj 	drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
54d0231070Smiao chen - Sun Microsystems - Beijing China 	u32 last_head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
55d0231070Smiao chen - Sun Microsystems - Beijing China 	u32 acthd_reg = IS_I965G(dev) ? ACTHD_I965 : ACTHD;
56d0231070Smiao chen - Sun Microsystems - Beijing China 	u32 last_acthd = I915_READ(acthd_reg);
57d0231070Smiao chen - Sun Microsystems - Beijing China 	u32 acthd;
58ae115bc7Smrj 	int i;
59ae115bc7Smrj 
60d0231070Smiao chen - Sun Microsystems - Beijing China 	for (i = 0; i < 100000; i++) {
61d0231070Smiao chen - Sun Microsystems - Beijing China 		ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
62d0231070Smiao chen - Sun Microsystems - Beijing China 		acthd = I915_READ(acthd_reg);
63ae115bc7Smrj 		ring->space = ring->head - (ring->tail + 8);
64ae115bc7Smrj 		if (ring->space < 0)
65ae115bc7Smrj 			ring->space += ring->Size;
66ae115bc7Smrj 		if (ring->space >= n)
67ae115bc7Smrj 			return 0;
68ae115bc7Smrj 
69ae115bc7Smrj 		if (ring->head != last_head)
70ae115bc7Smrj 			i = 0;
71ae115bc7Smrj 
72d0231070Smiao chen - Sun Microsystems - Beijing China 		if (acthd != last_acthd)
73d0231070Smiao chen - Sun Microsystems - Beijing China 			i = 0;
74d0231070Smiao chen - Sun Microsystems - Beijing China 
75ae115bc7Smrj 		last_head = ring->head;
76d0231070Smiao chen - Sun Microsystems - Beijing China 		last_acthd = acthd;
77d0231070Smiao chen - Sun Microsystems - Beijing China 		DRM_UDELAY(10);
78ae115bc7Smrj 	}
79ae115bc7Smrj 
80d0538f66Scg149915 	return (EBUSY);
81ae115bc7Smrj }
82ae115bc7Smrj 
i915_init_hardware_status(drm_device_t * dev)83d0231070Smiao chen - Sun Microsystems - Beijing China int i915_init_hardware_status(drm_device_t *dev)
84d0231070Smiao chen - Sun Microsystems - Beijing China {
85d0231070Smiao chen - Sun Microsystems - Beijing China        drm_i915_private_t *dev_priv = dev->dev_private;
86d0231070Smiao chen - Sun Microsystems - Beijing China        drm_dma_handle_t *dmah;
87d0231070Smiao chen - Sun Microsystems - Beijing China 
88d0231070Smiao chen - Sun Microsystems - Beijing China        /* Program Hardware Status Page */
89d0231070Smiao chen - Sun Microsystems - Beijing China        dmah = drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff,1);
90d0231070Smiao chen - Sun Microsystems - Beijing China 
91d0231070Smiao chen - Sun Microsystems - Beijing China        if (!dmah) {
92d0231070Smiao chen - Sun Microsystems - Beijing China                DRM_ERROR("Can not allocate hardware status page\n");
93d0231070Smiao chen - Sun Microsystems - Beijing China                return -ENOMEM;
94d0231070Smiao chen - Sun Microsystems - Beijing China        }
95d0231070Smiao chen - Sun Microsystems - Beijing China 
96d0231070Smiao chen - Sun Microsystems - Beijing China        dev_priv->status_page_dmah = dmah;
97d0231070Smiao chen - Sun Microsystems - Beijing China        dev_priv->hw_status_page = (void *)dmah->vaddr;
98d0231070Smiao chen - Sun Microsystems - Beijing China        dev_priv->dma_status_page = dmah->paddr;
99d0231070Smiao chen - Sun Microsystems - Beijing China 
100d0231070Smiao chen - Sun Microsystems - Beijing China        (void) memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
101d0231070Smiao chen - Sun Microsystems - Beijing China 
102d0231070Smiao chen - Sun Microsystems - Beijing China        I915_WRITE(HWS_PGA, dev_priv->dma_status_page);
1030035d21cSmiao chen - Sun Microsystems - Beijing China        (void) I915_READ(HWS_PGA);
1040035d21cSmiao chen - Sun Microsystems - Beijing China 
1050035d21cSmiao chen - Sun Microsystems - Beijing China        DRM_DEBUG("Enabled hardware status page add 0x%lx read GEM HWS 0x%x\n",dev_priv->hw_status_page, READ_HWSP(dev_priv, 0x20));
106d0231070Smiao chen - Sun Microsystems - Beijing China        return 0;
107d0231070Smiao chen - Sun Microsystems - Beijing China }
108d0231070Smiao chen - Sun Microsystems - Beijing China 
i915_free_hardware_status(drm_device_t * dev)109d0231070Smiao chen - Sun Microsystems - Beijing China void i915_free_hardware_status(drm_device_t *dev)
110d0231070Smiao chen - Sun Microsystems - Beijing China {
111d0231070Smiao chen - Sun Microsystems - Beijing China        drm_i915_private_t *dev_priv = dev->dev_private;
112d0231070Smiao chen - Sun Microsystems - Beijing China 	if (!I915_NEED_GFX_HWS(dev)) {
113d0231070Smiao chen - Sun Microsystems - Beijing China 		if (dev_priv->status_page_dmah) {
1140035d21cSmiao chen - Sun Microsystems - Beijing China 			DRM_DEBUG("free status_page_dmal %x", dev_priv->status_page_dmah);
115d0231070Smiao chen - Sun Microsystems - Beijing China 			drm_pci_free(dev, dev_priv->status_page_dmah);
116d0231070Smiao chen - Sun Microsystems - Beijing China 			dev_priv->status_page_dmah = NULL;
117d0231070Smiao chen - Sun Microsystems - Beijing China 			/* Need to rewrite hardware status page */
118d0231070Smiao chen - Sun Microsystems - Beijing China 			I915_WRITE(HWS_PGA, 0x1ffff000);
119d0231070Smiao chen - Sun Microsystems - Beijing China 		}
120d0231070Smiao chen - Sun Microsystems - Beijing China        	} else {
121d0231070Smiao chen - Sun Microsystems - Beijing China 		if (dev_priv->status_gfx_addr) {
1220035d21cSmiao chen - Sun Microsystems - Beijing China 			DRM_DEBUG("free status_gfx_addr %x", dev_priv->status_gfx_addr);
123d0231070Smiao chen - Sun Microsystems - Beijing China 			dev_priv->status_gfx_addr = 0;
124d0231070Smiao chen - Sun Microsystems - Beijing China 			drm_core_ioremapfree(&dev_priv->hws_map, dev);
125d0231070Smiao chen - Sun Microsystems - Beijing China 			I915_WRITE(HWS_PGA, 0x1ffff000);
126d0231070Smiao chen - Sun Microsystems - Beijing China 		}
127d0231070Smiao chen - Sun Microsystems - Beijing China 	}
128d0231070Smiao chen - Sun Microsystems - Beijing China 
129d0231070Smiao chen - Sun Microsystems - Beijing China }
130d0231070Smiao chen - Sun Microsystems - Beijing China 
i915_kernel_lost_context(drm_device_t * dev)131ae115bc7Smrj void i915_kernel_lost_context(drm_device_t * dev)
132ae115bc7Smrj {
133ae115bc7Smrj 	drm_i915_private_t *dev_priv = dev->dev_private;
134ae115bc7Smrj 	drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
135ae115bc7Smrj 
136d0231070Smiao chen - Sun Microsystems - Beijing China        ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
137d0231070Smiao chen - Sun Microsystems - Beijing China        ring->tail = I915_READ(PRB0_TAIL) & TAIL_ADDR;
138ae115bc7Smrj 	ring->space = ring->head - (ring->tail + 8);
139ae115bc7Smrj 	if (ring->space < 0)
140ae115bc7Smrj 		ring->space += ring->Size;
141ae115bc7Smrj 
142ae115bc7Smrj }
143ae115bc7Smrj 
i915_dma_cleanup(drm_device_t * dev)144ae115bc7Smrj static int i915_dma_cleanup(drm_device_t * dev)
145ae115bc7Smrj {
14691fae470Scg149915 	drm_i915_private_t *dev_priv =
14791fae470Scg149915 		    (drm_i915_private_t *) dev->dev_private;
14891fae470Scg149915 
149ae115bc7Smrj 	/* Make sure interrupts are disabled here because the uninstall ioctl
150ae115bc7Smrj 	 * may not have been called from userspace and after dev_private
151ae115bc7Smrj 	 * is freed, it's too late.
152ae115bc7Smrj 	 */
153d0231070Smiao chen - Sun Microsystems - Beijing China 	if (dev->irq_enabled)
154ae115bc7Smrj 		(void) drm_irq_uninstall(dev);
155ae115bc7Smrj 
156ae115bc7Smrj 	if (dev_priv->ring.virtual_start) {
157ae115bc7Smrj 		drm_core_ioremapfree(&dev_priv->ring.map, dev);
15891fae470Scg149915 		dev_priv->ring.virtual_start = 0;
15991fae470Scg149915 		dev_priv->ring.map.handle = 0;
16091fae470Scg149915 		dev_priv->ring.map.size = 0;
161ae115bc7Smrj 	}
162ae115bc7Smrj 
1630035d21cSmiao chen - Sun Microsystems - Beijing China #ifdef I915_HAVE_GEM
1640035d21cSmiao chen - Sun Microsystems - Beijing China 	if (I915_NEED_GFX_HWS(dev))
1650035d21cSmiao chen - Sun Microsystems - Beijing China #endif
166d0231070Smiao chen - Sun Microsystems - Beijing China 	i915_free_hardware_status(dev);
167d0538f66Scg149915 
168d0231070Smiao chen - Sun Microsystems - Beijing China 	dev_priv->sarea = NULL;
169d0231070Smiao chen - Sun Microsystems - Beijing China 	dev_priv->sarea_priv = NULL;
170dc8c6b69Sms148562 
171ae115bc7Smrj 	return 0;
172ae115bc7Smrj }
173ae115bc7Smrj 
i915_initialize(drm_device_t * dev,drm_i915_init_t * init)174ae115bc7Smrj static int i915_initialize(drm_device_t * dev,
175ae115bc7Smrj 			   drm_i915_init_t * init)
176ae115bc7Smrj {
17791fae470Scg149915 	drm_i915_private_t *dev_priv =
17891fae470Scg149915 	    (drm_i915_private_t *)dev->dev_private;
179ae115bc7Smrj 
180ae115bc7Smrj 	DRM_GETSAREA();
181ae115bc7Smrj 	if (!dev_priv->sarea) {
182ae115bc7Smrj 		DRM_ERROR("can not find sarea!\n");
183ae115bc7Smrj 		dev->dev_private = (void *)dev_priv;
184ae115bc7Smrj 		(void) i915_dma_cleanup(dev);
185d0538f66Scg149915 		return (EINVAL);
186ae115bc7Smrj 	}
187ae115bc7Smrj 
1880035d21cSmiao chen - Sun Microsystems - Beijing China 	dev_priv->sarea_priv = (drm_i915_sarea_t *)(uintptr_t)
1890035d21cSmiao chen - Sun Microsystems - Beijing China 			((u8 *) dev_priv->sarea->handle +
190d0231070Smiao chen - Sun Microsystems - Beijing China 			 init->sarea_priv_offset);
191ae115bc7Smrj 
192d0231070Smiao chen - Sun Microsystems - Beijing China 	if (init->ring_size != 0) {
1930035d21cSmiao chen - Sun Microsystems - Beijing China 		if (dev_priv->ring.ring_obj != NULL) {
1940035d21cSmiao chen - Sun Microsystems - Beijing China 			(void) i915_dma_cleanup(dev);
1950035d21cSmiao chen - Sun Microsystems - Beijing China 			DRM_ERROR("Client tried to initialize ringbuffer in "
1960035d21cSmiao chen - Sun Microsystems - Beijing China 				  "GEM mode\n");
1970035d21cSmiao chen - Sun Microsystems - Beijing China 			return -EINVAL;
1980035d21cSmiao chen - Sun Microsystems - Beijing China 		}
1990035d21cSmiao chen - Sun Microsystems - Beijing China 
200ae115bc7Smrj 		dev_priv->ring.Size = init->ring_size;
201ae115bc7Smrj 		dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
202ae115bc7Smrj 
203d0538f66Scg149915 		dev_priv->ring.map.offset = (u_offset_t)init->ring_start;
204ae115bc7Smrj 		dev_priv->ring.map.size = init->ring_size;
205ae115bc7Smrj 		dev_priv->ring.map.type = 0;
206ae115bc7Smrj 		dev_priv->ring.map.flags = 0;
207ae115bc7Smrj 		dev_priv->ring.map.mtrr = 0;
208ae115bc7Smrj 
209ae115bc7Smrj 		drm_core_ioremap(&dev_priv->ring.map, dev);
210ae115bc7Smrj 
211ae115bc7Smrj 		if (dev_priv->ring.map.handle == NULL) {
212ae115bc7Smrj 			(void) i915_dma_cleanup(dev);
213ae115bc7Smrj 			DRM_ERROR("can not ioremap virtual address for"
214ae115bc7Smrj 			  " ring buffer\n");
215d0538f66Scg149915 			return (ENOMEM);
216ae115bc7Smrj 		}
217d0231070Smiao chen - Sun Microsystems - Beijing China 	}
218ae115bc7Smrj 
2190035d21cSmiao chen - Sun Microsystems - Beijing China 	dev_priv->ring.virtual_start = (u8 *)dev_priv->ring.map.dev_addr;
220e92e3a86Szw161486 	dev_priv->cpp = init->cpp;
2210035d21cSmiao chen - Sun Microsystems - Beijing China 	dev_priv->back_offset = init->back_offset;
2220035d21cSmiao chen - Sun Microsystems - Beijing China 	dev_priv->front_offset = init->front_offset;
2230035d21cSmiao chen - Sun Microsystems - Beijing China 	dev_priv->current_page = 0;
2240035d21cSmiao chen - Sun Microsystems - Beijing China 	dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
225ae115bc7Smrj 
226ae115bc7Smrj 	/* Allow hardware batchbuffers unless told otherwise.
227ae115bc7Smrj 	 */
228ae115bc7Smrj 	dev_priv->allow_batchbuffer = 1;
229ae115bc7Smrj 	return 0;
230ae115bc7Smrj }
231ae115bc7Smrj 
i915_dma_resume(drm_device_t * dev)232ae115bc7Smrj static int i915_dma_resume(drm_device_t * dev)
233ae115bc7Smrj {
234ae115bc7Smrj 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
235ae115bc7Smrj 
236ae115bc7Smrj 	if (!dev_priv->sarea) {
237ae115bc7Smrj 		DRM_ERROR("can not find sarea!\n");
238d0538f66Scg149915 		return (EINVAL);
239ae115bc7Smrj 	}
240ae115bc7Smrj 
241ae115bc7Smrj 	if (dev_priv->ring.map.handle == NULL) {
242ae115bc7Smrj 		DRM_ERROR("can not ioremap virtual address for"
243ae115bc7Smrj 			  " ring buffer\n");
244d0538f66Scg149915 		return (ENOMEM);
245ae115bc7Smrj 	}
246ae115bc7Smrj 
247ae115bc7Smrj 	/* Program Hardware Status Page */
248ae115bc7Smrj 	if (!dev_priv->hw_status_page) {
249ae115bc7Smrj 		DRM_ERROR("Can not find hardware status page\n");
250d0538f66Scg149915 		return (EINVAL);
251ae115bc7Smrj 	}
2520035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_DEBUG("i915_dma_resume hw status page @ %p\n", dev_priv->hw_status_page);
253ae115bc7Smrj 
254fc6df3bdSmiao chen - Sun Microsystems - Beijing China 	if (!I915_NEED_GFX_HWS(dev))
255d0231070Smiao chen - Sun Microsystems - Beijing China 		I915_WRITE(HWS_PGA, dev_priv->dma_status_page);
256fc6df3bdSmiao chen - Sun Microsystems - Beijing China 	else
257d0231070Smiao chen - Sun Microsystems - Beijing China 		I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
258ae115bc7Smrj 	DRM_DEBUG("Enabled hardware status page\n");
259ae115bc7Smrj 
260ae115bc7Smrj 	return 0;
261ae115bc7Smrj }
262ae115bc7Smrj 
263ae115bc7Smrj /*ARGSUSED*/
i915_dma_init(DRM_IOCTL_ARGS)264ae115bc7Smrj static int i915_dma_init(DRM_IOCTL_ARGS)
265ae115bc7Smrj {
266ae115bc7Smrj 	DRM_DEVICE;
267ae115bc7Smrj 	drm_i915_init_t init;
268ae115bc7Smrj 	int retcode = 0;
269ae115bc7Smrj 
270d0538f66Scg149915 	DRM_COPYFROM_WITH_RETURN(&init, (drm_i915_init_t *)data, sizeof(init));
271ae115bc7Smrj 
272ae115bc7Smrj 	switch (init.func) {
273ae115bc7Smrj 	case I915_INIT_DMA:
27491fae470Scg149915 		retcode = i915_initialize(dev, &init);
275ae115bc7Smrj 		break;
276ae115bc7Smrj 	case I915_CLEANUP_DMA:
277ae115bc7Smrj 		retcode = i915_dma_cleanup(dev);
278ae115bc7Smrj 		break;
279ae115bc7Smrj 	case I915_RESUME_DMA:
280ae115bc7Smrj 		retcode = i915_dma_resume(dev);
281ae115bc7Smrj 		break;
282ae115bc7Smrj 	default:
283d0538f66Scg149915 		retcode = EINVAL;
284ae115bc7Smrj 		break;
285ae115bc7Smrj 	}
286ae115bc7Smrj 
287ae115bc7Smrj 	return retcode;
288ae115bc7Smrj }
289ae115bc7Smrj 
290ae115bc7Smrj /* Implement basically the same security restrictions as hardware does
291ae115bc7Smrj  * for MI_BATCH_NON_SECURE.  These can be made stricter at any time.
292ae115bc7Smrj  *
293ae115bc7Smrj  * Most of the calculations below involve calculating the size of a
294ae115bc7Smrj  * particular instruction.  It's important to get the size right as
295ae115bc7Smrj  * that tells us where the next instruction to check is.  Any illegal
296ae115bc7Smrj  * instruction detected will be given a size of zero, which is a
297ae115bc7Smrj  * signal to abort the rest of the buffer.
298ae115bc7Smrj  */
do_validate_cmd(int cmd)299ae115bc7Smrj static int do_validate_cmd(int cmd)
300ae115bc7Smrj {
301ae115bc7Smrj 	switch (((cmd >> 29) & 0x7)) {
302ae115bc7Smrj 	case 0x0:
303ae115bc7Smrj 		switch ((cmd >> 23) & 0x3f) {
304ae115bc7Smrj 		case 0x0:
305ae115bc7Smrj 			return 1;	/* MI_NOOP */
306ae115bc7Smrj 		case 0x4:
307ae115bc7Smrj 			return 1;	/* MI_FLUSH */
308ae115bc7Smrj 		default:
309ae115bc7Smrj 			return 0;	/* disallow everything else */
310ae115bc7Smrj 		}
311ae115bc7Smrj #ifndef __SUNPRO_C
312ae115bc7Smrj 		break;
313ae115bc7Smrj #endif
314ae115bc7Smrj 	case 0x1:
315ae115bc7Smrj 		return 0;	/* reserved */
316ae115bc7Smrj 	case 0x2:
317ae115bc7Smrj 		return (cmd & 0xff) + 2;	/* 2d commands */
318ae115bc7Smrj 	case 0x3:
319ae115bc7Smrj 		if (((cmd >> 24) & 0x1f) <= 0x18)
320ae115bc7Smrj 			return 1;
321ae115bc7Smrj 
322ae115bc7Smrj 		switch ((cmd >> 24) & 0x1f) {
323ae115bc7Smrj 		case 0x1c:
324ae115bc7Smrj 			return 1;
325ae115bc7Smrj 		case 0x1d:
326ae115bc7Smrj 			switch ((cmd >> 16) & 0xff) {
327ae115bc7Smrj 			case 0x3:
328ae115bc7Smrj 				return (cmd & 0x1f) + 2;
329ae115bc7Smrj 			case 0x4:
330ae115bc7Smrj 				return (cmd & 0xf) + 2;
331ae115bc7Smrj 			default:
332ae115bc7Smrj 				return (cmd & 0xffff) + 2;
333ae115bc7Smrj 			}
334ae115bc7Smrj 		case 0x1e:
335ae115bc7Smrj 			if (cmd & (1 << 23))
336ae115bc7Smrj 				return (cmd & 0xffff) + 1;
337ae115bc7Smrj 			else
338ae115bc7Smrj 				return 1;
339ae115bc7Smrj 		case 0x1f:
340ae115bc7Smrj 			if ((cmd & (1 << 23)) == 0)	/* inline vertices */
341ae115bc7Smrj 				return (cmd & 0x1ffff) + 2;
342ae115bc7Smrj 			else if (cmd & (1 << 17))	/* indirect random */
343ae115bc7Smrj 				if ((cmd & 0xffff) == 0)
344ae115bc7Smrj 					return 0;	/* unknown length, too hard */
345ae115bc7Smrj 				else
346ae115bc7Smrj 					return (((cmd & 0xffff) + 1) / 2) + 1;
347ae115bc7Smrj 			else
348ae115bc7Smrj 				return 2;	/* indirect sequential */
349ae115bc7Smrj 		default:
350ae115bc7Smrj 			return 0;
351ae115bc7Smrj 		}
352ae115bc7Smrj 	default:
353ae115bc7Smrj 		return 0;
354ae115bc7Smrj 	}
355ae115bc7Smrj 
356ae115bc7Smrj #ifndef __SUNPRO_C
357ae115bc7Smrj 	return 0;
358ae115bc7Smrj #endif
359ae115bc7Smrj }
360ae115bc7Smrj 
validate_cmd(int cmd)361ae115bc7Smrj static int validate_cmd(int cmd)
362ae115bc7Smrj {
363ae115bc7Smrj 	int ret = do_validate_cmd(cmd);
364ae115bc7Smrj 
365ae115bc7Smrj /* 	printk("validate_cmd( %x ): %d\n", cmd, ret); */
366ae115bc7Smrj 
367ae115bc7Smrj 	return ret;
368ae115bc7Smrj }
369ae115bc7Smrj 
i915_emit_cmds(drm_device_t * dev,int __user * buffer,int dwords)370d0538f66Scg149915 static int i915_emit_cmds(drm_device_t * dev, int __user * buffer, int dwords)
371ae115bc7Smrj {
372ae115bc7Smrj 	drm_i915_private_t *dev_priv = dev->dev_private;
373ae115bc7Smrj 	int i;
374ae115bc7Smrj 	RING_LOCALS;
375ae115bc7Smrj 
3760035d21cSmiao chen - Sun Microsystems - Beijing China 	if ((dwords+1) * sizeof(int) >= dev_priv->ring.Size - 8) {
3770035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR(" emit cmds invalid arg");
378d0538f66Scg149915 		return (EINVAL);
3790035d21cSmiao chen - Sun Microsystems - Beijing China 	}
380e92e3a86Szw161486 	BEGIN_LP_RING((dwords+1)&~1);
381e92e3a86Szw161486 
382ae115bc7Smrj 	for (i = 0; i < dwords;) {
383ae115bc7Smrj 		int cmd, sz;
384ae115bc7Smrj 
3850035d21cSmiao chen - Sun Microsystems - Beijing China 		if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i], sizeof(cmd))) {
3860035d21cSmiao chen - Sun Microsystems - Beijing China 			DRM_ERROR("emit cmds failed to get cmd from user");
387d0538f66Scg149915 			return (EINVAL);
3880035d21cSmiao chen - Sun Microsystems - Beijing China 		}
389ae115bc7Smrj 
3900035d21cSmiao chen - Sun Microsystems - Beijing China 		if ((sz = validate_cmd(cmd)) == 0 || i + sz > dwords) {
3910035d21cSmiao chen - Sun Microsystems - Beijing China 			DRM_ERROR("emit cmds invalid");
392d0538f66Scg149915 			return (EINVAL);
3930035d21cSmiao chen - Sun Microsystems - Beijing China 		}
394ae115bc7Smrj 		OUT_RING(cmd);
395ae115bc7Smrj 
396ae115bc7Smrj 		while (++i, --sz) {
397ae115bc7Smrj 			if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i],
398ae115bc7Smrj 							 sizeof(cmd))) {
3990035d21cSmiao chen - Sun Microsystems - Beijing China 				DRM_ERROR("emit cmds failed get cmds");
400d0538f66Scg149915 				return (EINVAL);
401ae115bc7Smrj 			}
402ae115bc7Smrj 			OUT_RING(cmd);
403ae115bc7Smrj 		}
404ae115bc7Smrj 	}
405ae115bc7Smrj 
406e92e3a86Szw161486 	if (dwords & 1)
407e92e3a86Szw161486 		OUT_RING(0);
408e92e3a86Szw161486 
409e92e3a86Szw161486 	ADVANCE_LP_RING();
410e92e3a86Szw161486 
411ae115bc7Smrj 	return 0;
412ae115bc7Smrj }
413ae115bc7Smrj 
i915_emit_box(drm_device_t * dev,drm_clip_rect_t __user * boxes,int i,int DR1,int DR4)414d0231070Smiao chen - Sun Microsystems - Beijing China int i915_emit_box(drm_device_t * dev,
415ae115bc7Smrj 			 drm_clip_rect_t __user * boxes,
416d0538f66Scg149915 			 int i, int DR1, int DR4)
417ae115bc7Smrj {
418ae115bc7Smrj 	drm_i915_private_t *dev_priv = dev->dev_private;
419ae115bc7Smrj 	drm_clip_rect_t box;
420ae115bc7Smrj 	RING_LOCALS;
421ae115bc7Smrj 
422ae115bc7Smrj 	if (DRM_COPY_FROM_USER_UNCHECKED(&box, &boxes[i], sizeof(box))) {
4230035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("emit box failed to copy from user");
424d0538f66Scg149915 		return (EFAULT);
425ae115bc7Smrj 	}
426ae115bc7Smrj 
4270bdffa0fShh224818 	if (box.y2 <= box.y1 || box.x2 <= box.x1) {
428ae115bc7Smrj 		DRM_ERROR("Bad box %d,%d..%d,%d\n",
429ae115bc7Smrj 			  box.x1, box.y1, box.x2, box.y2);
430d0538f66Scg149915 		return (EINVAL);
431ae115bc7Smrj 	}
432ae115bc7Smrj 
433e92e3a86Szw161486 	if (IS_I965G(dev)) {
434e92e3a86Szw161486 		BEGIN_LP_RING(4);
435e92e3a86Szw161486 		OUT_RING(GFX_OP_DRAWRECT_INFO_I965);
436e92e3a86Szw161486 		OUT_RING((box.x1 & 0xffff) | (box.y1 << 16));
437e92e3a86Szw161486 		OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16));
438e92e3a86Szw161486 		OUT_RING(DR4);
439e92e3a86Szw161486 		ADVANCE_LP_RING();
440e92e3a86Szw161486 	} else {
441ae115bc7Smrj 		BEGIN_LP_RING(6);
442ae115bc7Smrj 		OUT_RING(GFX_OP_DRAWRECT_INFO);
443ae115bc7Smrj 		OUT_RING(DR1);
444ae115bc7Smrj 		OUT_RING((box.x1 & 0xffff) | (box.y1 << 16));
445ae115bc7Smrj 		OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16));
446ae115bc7Smrj 		OUT_RING(DR4);
447ae115bc7Smrj 		OUT_RING(0);
448ae115bc7Smrj 		ADVANCE_LP_RING();
449e92e3a86Szw161486 	}
450e92e3a86Szw161486 
451e92e3a86Szw161486 	return 0;
452e92e3a86Szw161486 }
453e92e3a86Szw161486 
454e92e3a86Szw161486 /* XXX: Emitting the counter should really be moved to part of the IRQ
455e92e3a86Szw161486  * emit.  For now, do it in both places:
456e92e3a86Szw161486  */
457e92e3a86Szw161486 
i915_emit_breadcrumb(drm_device_t * dev)458d0231070Smiao chen - Sun Microsystems - Beijing China void i915_emit_breadcrumb(drm_device_t *dev)
459e92e3a86Szw161486 {
460e92e3a86Szw161486 	drm_i915_private_t *dev_priv = dev->dev_private;
461e92e3a86Szw161486 	RING_LOCALS;
462e92e3a86Szw161486 
4630035d21cSmiao chen - Sun Microsystems - Beijing China 	dev_priv->counter++;
4640035d21cSmiao chen - Sun Microsystems - Beijing China 	if (dev_priv->counter > 0x7FFFFFFFUL)
4650035d21cSmiao chen - Sun Microsystems - Beijing China 		dev_priv->counter = 0;
466d0231070Smiao chen - Sun Microsystems - Beijing China 	if (dev_priv->sarea_priv)
467d0231070Smiao chen - Sun Microsystems - Beijing China 		dev_priv->sarea_priv->last_enqueue = dev_priv->counter;
468d0231070Smiao chen - Sun Microsystems - Beijing China 
469e92e3a86Szw161486 
470e92e3a86Szw161486 	BEGIN_LP_RING(4);
471d0231070Smiao chen - Sun Microsystems - Beijing China 	OUT_RING(MI_STORE_DWORD_INDEX);
4720035d21cSmiao chen - Sun Microsystems - Beijing China 	OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
473e92e3a86Szw161486 	OUT_RING(dev_priv->counter);
474e92e3a86Szw161486 	OUT_RING(0);
475e92e3a86Szw161486 	ADVANCE_LP_RING();
476d0231070Smiao chen - Sun Microsystems - Beijing China 
477e92e3a86Szw161486 }
478e92e3a86Szw161486 
i915_dispatch_cmdbuffer(drm_device_t * dev,drm_i915_cmdbuffer_t * cmd)479ae115bc7Smrj static int i915_dispatch_cmdbuffer(drm_device_t * dev,
480d0538f66Scg149915 				   drm_i915_cmdbuffer_t * cmd)
481ae115bc7Smrj {
482ae115bc7Smrj 	int nbox = cmd->num_cliprects;
483ae115bc7Smrj 	int i = 0, count, ret;
484ae115bc7Smrj 
485ae115bc7Smrj 	if (cmd->sz & 0x3) {
486ae115bc7Smrj 		DRM_ERROR("alignment");
487d0538f66Scg149915 		return (EINVAL);
488ae115bc7Smrj 	}
489ae115bc7Smrj 
490ae115bc7Smrj 	i915_kernel_lost_context(dev);
491ae115bc7Smrj 
492ae115bc7Smrj 	count = nbox ? nbox : 1;
493ae115bc7Smrj 
494ae115bc7Smrj 	for (i = 0; i < count; i++) {
495ae115bc7Smrj 		if (i < nbox) {
496ae115bc7Smrj 			ret = i915_emit_box(dev, cmd->cliprects, i,
497d0538f66Scg149915 					    cmd->DR1, cmd->DR4);
498ae115bc7Smrj 			if (ret)
499ae115bc7Smrj 				return ret;
500ae115bc7Smrj 		}
501ae115bc7Smrj 
5020bdffa0fShh224818 		ret = i915_emit_cmds(dev, (int __user *)(void *)cmd->buf, cmd->sz / 4);
503ae115bc7Smrj 		if (ret)
504ae115bc7Smrj 			return ret;
505ae115bc7Smrj 	}
506ae115bc7Smrj 
507e92e3a86Szw161486 	i915_emit_breadcrumb( dev );
508ae115bc7Smrj 	return 0;
509ae115bc7Smrj }
510ae115bc7Smrj 
i915_dispatch_batchbuffer(drm_device_t * dev,drm_i915_batchbuffer_t * batch)511ae115bc7Smrj static int i915_dispatch_batchbuffer(drm_device_t * dev,
512d0538f66Scg149915 				     drm_i915_batchbuffer_t * batch)
513ae115bc7Smrj {
514ae115bc7Smrj 	drm_i915_private_t *dev_priv = dev->dev_private;
515ae115bc7Smrj 	drm_clip_rect_t __user *boxes = batch->cliprects;
516ae115bc7Smrj 	int nbox = batch->num_cliprects;
517ae115bc7Smrj 	int i = 0, count;
518ae115bc7Smrj 	RING_LOCALS;
519ae115bc7Smrj 
520ae115bc7Smrj 	if ((batch->start | batch->used) & 0x7) {
521ae115bc7Smrj 		DRM_ERROR("alignment");
522d0538f66Scg149915 		return (EINVAL);
523ae115bc7Smrj 	}
524ae115bc7Smrj 
525ae115bc7Smrj 	i915_kernel_lost_context(dev);
526ae115bc7Smrj 
527ae115bc7Smrj 	count = nbox ? nbox : 1;
528ae115bc7Smrj 
529ae115bc7Smrj 	for (i = 0; i < count; i++) {
530ae115bc7Smrj 		if (i < nbox) {
531ae115bc7Smrj 			int ret = i915_emit_box(dev, boxes, i,
532d0538f66Scg149915 						batch->DR1, batch->DR4);
533ae115bc7Smrj 			if (ret)
534ae115bc7Smrj 				return ret;
535ae115bc7Smrj 		}
536ae115bc7Smrj 
537d0231070Smiao chen - Sun Microsystems - Beijing China 		if (IS_I830(dev) || IS_845G(dev)) {
538ae115bc7Smrj 			BEGIN_LP_RING(4);
539ae115bc7Smrj 			OUT_RING(MI_BATCH_BUFFER);
540ae115bc7Smrj 			OUT_RING(batch->start | MI_BATCH_NON_SECURE);
541ae115bc7Smrj 			OUT_RING(batch->start + batch->used - 4);
542ae115bc7Smrj 			OUT_RING(0);
543ae115bc7Smrj 			ADVANCE_LP_RING();
544d0231070Smiao chen - Sun Microsystems - Beijing China 		} else {
545d0231070Smiao chen - Sun Microsystems - Beijing China 			BEGIN_LP_RING(2);
546d0231070Smiao chen - Sun Microsystems - Beijing China 			if (IS_I965G(dev)) {
547d0231070Smiao chen - Sun Microsystems - Beijing China 				OUT_RING(MI_BATCH_BUFFER_START | (2 << 6) | MI_BATCH_NON_SECURE_I965);
548d0231070Smiao chen - Sun Microsystems - Beijing China 				OUT_RING(batch->start);
549d0231070Smiao chen - Sun Microsystems - Beijing China 			} else {
550d0231070Smiao chen - Sun Microsystems - Beijing China 				OUT_RING(MI_BATCH_BUFFER_START | (2 << 6));
551d0231070Smiao chen - Sun Microsystems - Beijing China 				OUT_RING(batch->start | MI_BATCH_NON_SECURE);
552d0231070Smiao chen - Sun Microsystems - Beijing China 			}
553d0231070Smiao chen - Sun Microsystems - Beijing China 			ADVANCE_LP_RING();
554ae115bc7Smrj 		}
555ae115bc7Smrj 	}
556ae115bc7Smrj 
557e92e3a86Szw161486 	i915_emit_breadcrumb( dev );
558ae115bc7Smrj 
559ae115bc7Smrj 	return 0;
560ae115bc7Smrj }
561ae115bc7Smrj 
i915_dispatch_flip(struct drm_device * dev,int planes)5620035d21cSmiao chen - Sun Microsystems - Beijing China static int i915_dispatch_flip(struct drm_device * dev, int planes)
563ae115bc7Smrj {
564ae115bc7Smrj 	drm_i915_private_t *dev_priv = dev->dev_private;
565ae115bc7Smrj 	RING_LOCALS;
566ae115bc7Smrj 
5670035d21cSmiao chen - Sun Microsystems - Beijing China 	if (!dev_priv->sarea_priv)
5680035d21cSmiao chen - Sun Microsystems - Beijing China 		return -EINVAL;
569d0231070Smiao chen - Sun Microsystems - Beijing China 
570d0231070Smiao chen - Sun Microsystems - Beijing China 	DRM_DEBUG("planes=0x%x pfCurrentPage=%d\n",
571d0231070Smiao chen - Sun Microsystems - Beijing China 		planes, dev_priv->sarea_priv->pf_current_page);
572d0231070Smiao chen - Sun Microsystems - Beijing China 
5730035d21cSmiao chen - Sun Microsystems - Beijing China 	i915_kernel_lost_context(dev);
574d0231070Smiao chen - Sun Microsystems - Beijing China 
5750035d21cSmiao chen - Sun Microsystems - Beijing China 	BEGIN_LP_RING(2);
5760035d21cSmiao chen - Sun Microsystems - Beijing China 	OUT_RING(MI_FLUSH | MI_READ_FLUSH);
5770035d21cSmiao chen - Sun Microsystems - Beijing China 	OUT_RING(0);
5780035d21cSmiao chen - Sun Microsystems - Beijing China 	ADVANCE_LP_RING();
579d0231070Smiao chen - Sun Microsystems - Beijing China 
5800035d21cSmiao chen - Sun Microsystems - Beijing China 	BEGIN_LP_RING(6);
5810035d21cSmiao chen - Sun Microsystems - Beijing China 	OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP);
5820035d21cSmiao chen - Sun Microsystems - Beijing China 	OUT_RING(0);
5830035d21cSmiao chen - Sun Microsystems - Beijing China 	if (dev_priv->current_page == 0) {
5840035d21cSmiao chen - Sun Microsystems - Beijing China 		OUT_RING(dev_priv->back_offset);
5850035d21cSmiao chen - Sun Microsystems - Beijing China 		dev_priv->current_page = 1;
5860035d21cSmiao chen - Sun Microsystems - Beijing China 	} else {
5870035d21cSmiao chen - Sun Microsystems - Beijing China 		OUT_RING(dev_priv->front_offset);
5880035d21cSmiao chen - Sun Microsystems - Beijing China 		dev_priv->current_page = 0;
5890035d21cSmiao chen - Sun Microsystems - Beijing China 	}
5900035d21cSmiao chen - Sun Microsystems - Beijing China 	OUT_RING(0);
5910035d21cSmiao chen - Sun Microsystems - Beijing China 	ADVANCE_LP_RING();
592d0231070Smiao chen - Sun Microsystems - Beijing China 
5930035d21cSmiao chen - Sun Microsystems - Beijing China 	BEGIN_LP_RING(2);
5940035d21cSmiao chen - Sun Microsystems - Beijing China 	OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP);
5950035d21cSmiao chen - Sun Microsystems - Beijing China 	OUT_RING(0);
5960035d21cSmiao chen - Sun Microsystems - Beijing China 	ADVANCE_LP_RING();
5970035d21cSmiao chen - Sun Microsystems - Beijing China 
5980035d21cSmiao chen - Sun Microsystems - Beijing China 	dev_priv->sarea_priv->last_enqueue = dev_priv->counter++;
5990035d21cSmiao chen - Sun Microsystems - Beijing China 
6000035d21cSmiao chen - Sun Microsystems - Beijing China 	BEGIN_LP_RING(4);
6010035d21cSmiao chen - Sun Microsystems - Beijing China 	OUT_RING(MI_STORE_DWORD_INDEX);
6020035d21cSmiao chen - Sun Microsystems - Beijing China 	OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
6030035d21cSmiao chen - Sun Microsystems - Beijing China 	OUT_RING(dev_priv->counter);
6040035d21cSmiao chen - Sun Microsystems - Beijing China 	OUT_RING(0);
6050035d21cSmiao chen - Sun Microsystems - Beijing China 	ADVANCE_LP_RING();
6060035d21cSmiao chen - Sun Microsystems - Beijing China 
6070035d21cSmiao chen - Sun Microsystems - Beijing China 	dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
6080035d21cSmiao chen - Sun Microsystems - Beijing China 	return 0;
609ae115bc7Smrj }
610ae115bc7Smrj 
i915_quiescent(drm_device_t * dev)611ae115bc7Smrj static int i915_quiescent(drm_device_t * dev)
612ae115bc7Smrj {
613ae115bc7Smrj 	drm_i915_private_t *dev_priv = dev->dev_private;
614d0231070Smiao chen - Sun Microsystems - Beijing China 	int ret;
615ae115bc7Smrj 	i915_kernel_lost_context(dev);
616d0231070Smiao chen - Sun Microsystems - Beijing China 	ret = i915_wait_ring(dev, dev_priv->ring.Size - 8, __FUNCTION__);
617d0231070Smiao chen - Sun Microsystems - Beijing China 
618d0231070Smiao chen - Sun Microsystems - Beijing China 	if (ret)
619d0231070Smiao chen - Sun Microsystems - Beijing China 	{
620d0231070Smiao chen - Sun Microsystems - Beijing China 		i915_kernel_lost_context (dev);
621d0231070Smiao chen - Sun Microsystems - Beijing China 		DRM_ERROR ("not quiescent head %08x tail %08x space %08x\n",
622d0231070Smiao chen - Sun Microsystems - Beijing China 			   dev_priv->ring.head,
623d0231070Smiao chen - Sun Microsystems - Beijing China 			   dev_priv->ring.tail,
624d0231070Smiao chen - Sun Microsystems - Beijing China 			   dev_priv->ring.space);
625d0231070Smiao chen - Sun Microsystems - Beijing China 	}
626d0231070Smiao chen - Sun Microsystems - Beijing China 	return ret;
627ae115bc7Smrj }
628ae115bc7Smrj 
629ae115bc7Smrj /*ARGSUSED*/
i915_flush_ioctl(DRM_IOCTL_ARGS)630ae115bc7Smrj static int i915_flush_ioctl(DRM_IOCTL_ARGS)
631ae115bc7Smrj {
6320035d21cSmiao chen - Sun Microsystems - Beijing China 	int ret;
633ae115bc7Smrj 	DRM_DEVICE;
634ae115bc7Smrj 
635d0538f66Scg149915 	LOCK_TEST_WITH_RETURN(dev, fpriv);
636ae115bc7Smrj 
6370035d21cSmiao chen - Sun Microsystems - Beijing China 	spin_lock(&dev->struct_mutex);
6380035d21cSmiao chen - Sun Microsystems - Beijing China 	ret = i915_quiescent(dev);
6390035d21cSmiao chen - Sun Microsystems - Beijing China 	spin_unlock(&dev->struct_mutex);
6400035d21cSmiao chen - Sun Microsystems - Beijing China 
6410035d21cSmiao chen - Sun Microsystems - Beijing China 	return ret;
642ae115bc7Smrj }
643ae115bc7Smrj 
644ae115bc7Smrj /*ARGSUSED*/
i915_batchbuffer(DRM_IOCTL_ARGS)645ae115bc7Smrj static int i915_batchbuffer(DRM_IOCTL_ARGS)
646ae115bc7Smrj {
647ae115bc7Smrj 	DRM_DEVICE;
648ae115bc7Smrj 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
649ae115bc7Smrj 	drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
650ae115bc7Smrj 	    dev_priv->sarea_priv;
651ae115bc7Smrj 	drm_i915_batchbuffer_t batch;
652ae115bc7Smrj 	int ret;
653ae115bc7Smrj 
654ae115bc7Smrj 	if (!dev_priv->allow_batchbuffer) {
655ae115bc7Smrj 		DRM_ERROR("Batchbuffer ioctl disabled\n");
656d0538f66Scg149915 		return (EINVAL);
657ae115bc7Smrj 	}
658ae115bc7Smrj 
659ae115bc7Smrj 	if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
660ae115bc7Smrj 		drm_i915_batchbuffer32_t batchbuffer32_t;
661ae115bc7Smrj 
662d0538f66Scg149915 		DRM_COPYFROM_WITH_RETURN(&batchbuffer32_t,
663d0538f66Scg149915 			(void *) data, sizeof (batchbuffer32_t));
664ae115bc7Smrj 
665ae115bc7Smrj 		batch.start = batchbuffer32_t.start;
666ae115bc7Smrj 		batch.used = batchbuffer32_t.used;
667ae115bc7Smrj 		batch.DR1 = batchbuffer32_t.DR1;
668ae115bc7Smrj 		batch.DR4 = batchbuffer32_t.DR4;
669ae115bc7Smrj 		batch.num_cliprects = batchbuffer32_t.num_cliprects;
670ae115bc7Smrj 		batch.cliprects = (drm_clip_rect_t __user *)
671ae115bc7Smrj 			(uintptr_t)batchbuffer32_t.cliprects;
672ae115bc7Smrj 	} else
673d0538f66Scg149915 		DRM_COPYFROM_WITH_RETURN(&batch, (void *) data,
674ae115bc7Smrj 			sizeof(batch));
675ae115bc7Smrj 
676d0231070Smiao chen - Sun Microsystems - Beijing China 	DRM_DEBUG("i915 batchbuffer, start %x used %d cliprects %d, counter %d\n",
677d0231070Smiao chen - Sun Microsystems - Beijing China 		  batch.start, batch.used, batch.num_cliprects, dev_priv->counter);
678ae115bc7Smrj 
679d0538f66Scg149915 	LOCK_TEST_WITH_RETURN(dev, fpriv);
680ae115bc7Smrj 
681d0231070Smiao chen - Sun Microsystems - Beijing China /*
682ae115bc7Smrj 	if (batch.num_cliprects && DRM_VERIFYAREA_READ(batch.cliprects,
683ae115bc7Smrj 						       batch.num_cliprects *
684ae115bc7Smrj 						       sizeof(drm_clip_rect_t)))
685d0538f66Scg149915 		return (EFAULT);
6860035d21cSmiao chen - Sun Microsystems - Beijing China 
687ae115bc7Smrj */
688ae115bc7Smrj 
6890035d21cSmiao chen - Sun Microsystems - Beijing China 	spin_lock(&dev->struct_mutex);
690d0231070Smiao chen - Sun Microsystems - Beijing China 	ret = i915_dispatch_batchbuffer(dev, &batch);
6910035d21cSmiao chen - Sun Microsystems - Beijing China 	spin_unlock(&dev->struct_mutex);
692d0231070Smiao chen - Sun Microsystems - Beijing China 	sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
693d0231070Smiao chen - Sun Microsystems - Beijing China 
694ae115bc7Smrj 	return ret;
695ae115bc7Smrj }
696ae115bc7Smrj 
697ae115bc7Smrj /*ARGSUSED*/
i915_cmdbuffer(DRM_IOCTL_ARGS)698ae115bc7Smrj static int i915_cmdbuffer(DRM_IOCTL_ARGS)
699ae115bc7Smrj {
700ae115bc7Smrj 	DRM_DEVICE;
701ae115bc7Smrj 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
702ae115bc7Smrj 	drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
703ae115bc7Smrj 	    dev_priv->sarea_priv;
704ae115bc7Smrj 	drm_i915_cmdbuffer_t cmdbuf;
705ae115bc7Smrj 	int ret;
706ae115bc7Smrj 
707ae115bc7Smrj 	if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
708ae115bc7Smrj 		drm_i915_cmdbuffer32_t cmdbuffer32_t;
709ae115bc7Smrj 
710d0538f66Scg149915 		DRM_COPYFROM_WITH_RETURN(&cmdbuffer32_t,
711ae115bc7Smrj 			(drm_i915_cmdbuffer32_t __user *) data,
712ae115bc7Smrj 			sizeof (drm_i915_cmdbuffer32_t));
713ae115bc7Smrj 
714ae115bc7Smrj 		cmdbuf.buf = (char __user *)(uintptr_t)cmdbuffer32_t.buf;
715ae115bc7Smrj 		cmdbuf.sz = cmdbuffer32_t.sz;
716ae115bc7Smrj 		cmdbuf.DR1 = cmdbuffer32_t.DR1;
717ae115bc7Smrj 		cmdbuf.DR4 = cmdbuffer32_t.DR4;
718ae115bc7Smrj 		cmdbuf.num_cliprects = cmdbuffer32_t.num_cliprects;
719ae115bc7Smrj 		cmdbuf.cliprects = (drm_clip_rect_t __user *)
720ae115bc7Smrj 			(uintptr_t)cmdbuffer32_t.cliprects;
721ae115bc7Smrj 	} else
722d0538f66Scg149915 		DRM_COPYFROM_WITH_RETURN(&cmdbuf, (void *) data,
723ae115bc7Smrj 			sizeof(cmdbuf));
724ae115bc7Smrj 
725ae115bc7Smrj 	DRM_DEBUG("i915 cmdbuffer, buf %p sz %d cliprects %d\n",
726ae115bc7Smrj 		  cmdbuf.buf, cmdbuf.sz, cmdbuf.num_cliprects);
727ae115bc7Smrj 
728d0538f66Scg149915 	LOCK_TEST_WITH_RETURN(dev, fpriv);
729ae115bc7Smrj 
730d0231070Smiao chen - Sun Microsystems - Beijing China /*
731ae115bc7Smrj 	if (cmdbuf.num_cliprects &&
732ae115bc7Smrj 	    DRM_VERIFYAREA_READ(cmdbuf.cliprects,
733ae115bc7Smrj 				cmdbuf.num_cliprects *
734ae115bc7Smrj 				sizeof(drm_clip_rect_t))) {
735ae115bc7Smrj 		DRM_ERROR("Fault accessing cliprects\n");
736d0538f66Scg149915 		return (EFAULT);
737ae115bc7Smrj 	}
738ae115bc7Smrj */
739ae115bc7Smrj 
7400035d21cSmiao chen - Sun Microsystems - Beijing China 	spin_lock(&dev->struct_mutex);
741d0538f66Scg149915 	ret = i915_dispatch_cmdbuffer(dev, &cmdbuf);
7420035d21cSmiao chen - Sun Microsystems - Beijing China 	spin_unlock(&dev->struct_mutex);
743ae115bc7Smrj 	if (ret) {
744ae115bc7Smrj 		DRM_ERROR("i915_dispatch_cmdbuffer failed\n");
745ae115bc7Smrj 		return ret;
746ae115bc7Smrj 	}
747ae115bc7Smrj 
748d0231070Smiao chen - Sun Microsystems - Beijing China 	sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
749ae115bc7Smrj 	return 0;
750ae115bc7Smrj }
751ae115bc7Smrj 
752ae115bc7Smrj /*ARGSUSED*/
i915_flip_bufs(DRM_IOCTL_ARGS)753ae115bc7Smrj static int i915_flip_bufs(DRM_IOCTL_ARGS)
754ae115bc7Smrj {
755ae115bc7Smrj 	DRM_DEVICE;
756d0231070Smiao chen - Sun Microsystems - Beijing China 	drm_i915_flip_t param;
7570035d21cSmiao chen - Sun Microsystems - Beijing China 	int ret;
758d0231070Smiao chen - Sun Microsystems - Beijing China         DRM_COPYFROM_WITH_RETURN(&param, (drm_i915_flip_t *) data,
759d0231070Smiao chen - Sun Microsystems - Beijing China                                  sizeof(param));
760ae115bc7Smrj 
761d0231070Smiao chen - Sun Microsystems - Beijing China 	DRM_DEBUG("i915_flip_bufs\n");
762ae115bc7Smrj 
763d0538f66Scg149915 	LOCK_TEST_WITH_RETURN(dev, fpriv);
7640035d21cSmiao chen - Sun Microsystems - Beijing China 
7650035d21cSmiao chen - Sun Microsystems - Beijing China 	spin_lock(&dev->struct_mutex);
7660035d21cSmiao chen - Sun Microsystems - Beijing China 	ret = i915_dispatch_flip(dev, param.pipes);
7670035d21cSmiao chen - Sun Microsystems - Beijing China 	spin_unlock(&dev->struct_mutex);
7680035d21cSmiao chen - Sun Microsystems - Beijing China 	return ret;
769ae115bc7Smrj }
770ae115bc7Smrj 
771ae115bc7Smrj /*ARGSUSED*/
i915_getparam(DRM_IOCTL_ARGS)772ae115bc7Smrj static int i915_getparam(DRM_IOCTL_ARGS)
773ae115bc7Smrj {
774ae115bc7Smrj 	DRM_DEVICE;
775ae115bc7Smrj 	drm_i915_private_t *dev_priv = dev->dev_private;
776ae115bc7Smrj 	drm_i915_getparam_t param;
777ae115bc7Smrj 	int value;
778ae115bc7Smrj 
779ae115bc7Smrj 	if (!dev_priv) {
780ae115bc7Smrj 		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
781d0538f66Scg149915 		return (EINVAL);
782ae115bc7Smrj 	}
783ae115bc7Smrj 
784ae115bc7Smrj 	if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
785ae115bc7Smrj 		drm_i915_getparam32_t getparam32_t;
786ae115bc7Smrj 
787d0538f66Scg149915 		DRM_COPYFROM_WITH_RETURN(&getparam32_t,
788ae115bc7Smrj 			(drm_i915_getparam32_t __user *) data,
789ae115bc7Smrj 			sizeof (drm_i915_getparam32_t));
790ae115bc7Smrj 
791ae115bc7Smrj 		param.param = getparam32_t.param;
792ae115bc7Smrj 		param.value = (int __user *)(uintptr_t)getparam32_t.value;
793ae115bc7Smrj 	} else
794d0538f66Scg149915 		DRM_COPYFROM_WITH_RETURN(&param,
795d0538f66Scg149915 		    (drm_i915_getparam_t *) data, sizeof(param));
796ae115bc7Smrj 
797ae115bc7Smrj 	switch (param.param) {
798ae115bc7Smrj 	case I915_PARAM_IRQ_ACTIVE:
799d0231070Smiao chen - Sun Microsystems - Beijing China 		value = dev->irq_enabled ? 1 : 0;
800ae115bc7Smrj 		break;
801ae115bc7Smrj 	case I915_PARAM_ALLOW_BATCHBUFFER:
802ae115bc7Smrj 		value = dev_priv->allow_batchbuffer ? 1 : 0;
803ae115bc7Smrj 		break;
804e92e3a86Szw161486 	case I915_PARAM_LAST_DISPATCH:
805e92e3a86Szw161486 		value = READ_BREADCRUMB(dev_priv);
806e92e3a86Szw161486 		break;
807d0231070Smiao chen - Sun Microsystems - Beijing China 	case I915_PARAM_CHIPSET_ID:
808d0231070Smiao chen - Sun Microsystems - Beijing China 		value = dev->pci_device;
809d0231070Smiao chen - Sun Microsystems - Beijing China 		break;
8100035d21cSmiao chen - Sun Microsystems - Beijing China 	case I915_PARAM_HAS_GEM:
8110035d21cSmiao chen - Sun Microsystems - Beijing China 		value = dev->driver->use_gem;
8120035d21cSmiao chen - Sun Microsystems - Beijing China 		break;
813ae115bc7Smrj 	default:
8140035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("Unknown get parameter %d\n", param.param);
815d0538f66Scg149915 		return (EINVAL);
816ae115bc7Smrj 	}
817ae115bc7Smrj 
818ae115bc7Smrj 	if (DRM_COPY_TO_USER(param.value, &value, sizeof(int))) {
819ae115bc7Smrj 		DRM_ERROR("i915_getparam failed\n");
820d0538f66Scg149915 		return (EFAULT);
821ae115bc7Smrj 	}
822ae115bc7Smrj 	return 0;
823ae115bc7Smrj }
824ae115bc7Smrj 
825ae115bc7Smrj /*ARGSUSED*/
i915_setparam(DRM_IOCTL_ARGS)826ae115bc7Smrj static int i915_setparam(DRM_IOCTL_ARGS)
827ae115bc7Smrj {
828ae115bc7Smrj 	DRM_DEVICE;
829ae115bc7Smrj 	drm_i915_private_t *dev_priv = dev->dev_private;
830ae115bc7Smrj 	drm_i915_setparam_t param;
831ae115bc7Smrj 
832ae115bc7Smrj 	if (!dev_priv) {
833ae115bc7Smrj 		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
834d0538f66Scg149915 		return (EINVAL);
835ae115bc7Smrj 	}
836ae115bc7Smrj 
837d0538f66Scg149915 	DRM_COPYFROM_WITH_RETURN(&param, (drm_i915_setparam_t *) data,
838ae115bc7Smrj 				 sizeof(param));
839ae115bc7Smrj 
840ae115bc7Smrj 	switch (param.param) {
841ae115bc7Smrj 	case I915_SETPARAM_USE_MI_BATCHBUFFER_START:
842ae115bc7Smrj 		break;
843ae115bc7Smrj 	case I915_SETPARAM_TEX_LRU_LOG_GRANULARITY:
844ae115bc7Smrj 		dev_priv->tex_lru_log_granularity = param.value;
845ae115bc7Smrj 		break;
846ae115bc7Smrj 	case I915_SETPARAM_ALLOW_BATCHBUFFER:
847ae115bc7Smrj 		dev_priv->allow_batchbuffer = param.value;
848ae115bc7Smrj 		break;
849ae115bc7Smrj 	default:
8500035d21cSmiao chen - Sun Microsystems - Beijing China 		DRM_ERROR("unknown set parameter %d\n", param.param);
851d0538f66Scg149915 		return (EINVAL);
852ae115bc7Smrj 	}
853ae115bc7Smrj 
854ae115bc7Smrj 	return 0;
855ae115bc7Smrj }
856ae115bc7Smrj 
857ae115bc7Smrj /*ARGSUSED*/
i915_set_status_page(DRM_IOCTL_ARGS)858dc8c6b69Sms148562 static int i915_set_status_page(DRM_IOCTL_ARGS)
859dc8c6b69Sms148562 {
860dc8c6b69Sms148562 	DRM_DEVICE;
861dc8c6b69Sms148562 	drm_i915_private_t *dev_priv = dev->dev_private;
862dc8c6b69Sms148562 	drm_i915_hws_addr_t hws;
863dc8c6b69Sms148562 
864fc6df3bdSmiao chen - Sun Microsystems - Beijing China 	if (!I915_NEED_GFX_HWS(dev))
865fc6df3bdSmiao chen - Sun Microsystems - Beijing China 		return (EINVAL);
866fc6df3bdSmiao chen - Sun Microsystems - Beijing China 
867dc8c6b69Sms148562 	if (!dev_priv) {
868dc8c6b69Sms148562 		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
869dc8c6b69Sms148562 		return (EINVAL);
870dc8c6b69Sms148562 	}
871dc8c6b69Sms148562 	DRM_COPYFROM_WITH_RETURN(&hws, (drm_i915_hws_addr_t __user *) data,
872dc8c6b69Sms148562 			sizeof(hws));
8730035d21cSmiao chen - Sun Microsystems - Beijing China DRM_ERROR("i915_set_status_page set status page addr 0x%08x\n", (u32)hws.addr);
874dc8c6b69Sms148562 
875dc8c6b69Sms148562 	dev_priv->status_gfx_addr = hws.addr & (0x1ffff<<12);
876dc8c6b69Sms148562 	DRM_DEBUG("set gfx_addr 0x%08x\n", dev_priv->status_gfx_addr);
877dc8c6b69Sms148562 
878dc8c6b69Sms148562 	dev_priv->hws_map.offset =
879dc8c6b69Sms148562 	    (u_offset_t)dev->agp->agp_info.agpi_aperbase + hws.addr;
880d0231070Smiao chen - Sun Microsystems - Beijing China 	dev_priv->hws_map.size = 4 * 1024; /* 4K pages */
881d0231070Smiao chen - Sun Microsystems - Beijing China 	dev_priv->hws_map.type = 0;
882dc8c6b69Sms148562 	dev_priv->hws_map.flags = 0;
883dc8c6b69Sms148562 	dev_priv->hws_map.mtrr = 0;
884dc8c6b69Sms148562 
885dc8c6b69Sms148562 	DRM_DEBUG("set status page: i915_set_status_page: mapoffset 0x%llx\n",
886dc8c6b69Sms148562 	    dev_priv->hws_map.offset);
887dc8c6b69Sms148562 	drm_core_ioremap(&dev_priv->hws_map, dev);
888dc8c6b69Sms148562 	if (dev_priv->hws_map.handle == NULL) {
889dc8c6b69Sms148562 		dev->dev_private = (void *)dev_priv;
890dc8c6b69Sms148562 		(void) i915_dma_cleanup(dev);
891dc8c6b69Sms148562 		dev_priv->status_gfx_addr = 0;
892dc8c6b69Sms148562 		DRM_ERROR("can not ioremap virtual address for"
893dc8c6b69Sms148562 				" G33 hw status page\n");
894dc8c6b69Sms148562 		return (ENOMEM);
895dc8c6b69Sms148562 	}
896dc8c6b69Sms148562 	dev_priv->hw_status_page = dev_priv->hws_map.dev_addr;
897dc8c6b69Sms148562 
898dc8c6b69Sms148562 	(void) memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
899d0231070Smiao chen - Sun Microsystems - Beijing China 	I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
900dc8c6b69Sms148562 	DRM_DEBUG("load hws 0x2080 with gfx mem 0x%x\n",
901dc8c6b69Sms148562 			dev_priv->status_gfx_addr);
902dc8c6b69Sms148562 	DRM_DEBUG("load hws at %p\n", dev_priv->hw_status_page);
903dc8c6b69Sms148562 	return 0;
904dc8c6b69Sms148562 }
905dc8c6b69Sms148562 
906dc8c6b69Sms148562 /*ARGSUSED*/
i915_driver_load(drm_device_t * dev,unsigned long flags)907ae115bc7Smrj int i915_driver_load(drm_device_t *dev, unsigned long flags)
908ae115bc7Smrj {
90991fae470Scg149915 	struct drm_i915_private *dev_priv;
9100035d21cSmiao chen - Sun Microsystems - Beijing China 	unsigned long base, size;
9110035d21cSmiao chen - Sun Microsystems - Beijing China 	int ret = 0, mmio_bar = IS_I9XX(dev) ? 0 : 1;
91291fae470Scg149915 
913ae115bc7Smrj 	/* i915 has 4 more counters */
914ae115bc7Smrj 	dev->counters += 4;
915ae115bc7Smrj 	dev->types[6] = _DRM_STAT_IRQ;
916ae115bc7Smrj 	dev->types[7] = _DRM_STAT_PRIMARY;
917ae115bc7Smrj 	dev->types[8] = _DRM_STAT_SECONDARY;
918ae115bc7Smrj 	dev->types[9] = _DRM_STAT_DMA;
919ae115bc7Smrj 
92091fae470Scg149915 	dev_priv = drm_alloc(sizeof(drm_i915_private_t), DRM_MEM_DRIVER);
92191fae470Scg149915 	if (dev_priv == NULL)
92291fae470Scg149915 		return ENOMEM;
92391fae470Scg149915 
92491fae470Scg149915 	(void) memset(dev_priv, 0, sizeof(drm_i915_private_t));
92591fae470Scg149915 	dev->dev_private = (void *)dev_priv;
926d0231070Smiao chen - Sun Microsystems - Beijing China 	dev_priv->dev = dev;
92791fae470Scg149915 
9280035d21cSmiao chen - Sun Microsystems - Beijing China 	/* Add register map (needed for suspend/resume) */
9290035d21cSmiao chen - Sun Microsystems - Beijing China 
9300035d21cSmiao chen - Sun Microsystems - Beijing China 	base = drm_get_resource_start(dev, mmio_bar);
9310035d21cSmiao chen - Sun Microsystems - Beijing China 	size = drm_get_resource_len(dev, mmio_bar);
9320035d21cSmiao chen - Sun Microsystems - Beijing China 	dev_priv->mmio_map = drm_alloc(sizeof (drm_local_map_t), DRM_MEM_MAPS);
9330035d21cSmiao chen - Sun Microsystems - Beijing China 	dev_priv->mmio_map->offset = base;
9340035d21cSmiao chen - Sun Microsystems - Beijing China 	dev_priv->mmio_map->size = size;
9350035d21cSmiao chen - Sun Microsystems - Beijing China 	dev_priv->mmio_map->type = _DRM_REGISTERS;
9360035d21cSmiao chen - Sun Microsystems - Beijing China 	dev_priv->mmio_map->flags = _DRM_REMOVABLE;
937*c1374a13SSurya Prakki 	(void) drm_ioremap(dev, dev_priv->mmio_map);
9380035d21cSmiao chen - Sun Microsystems - Beijing China 
9390035d21cSmiao chen - Sun Microsystems - Beijing China 	DRM_DEBUG("i915_driverload mmio %p mmio_map->dev_addr %x", dev_priv->mmio_map, dev_priv->mmio_map->dev_addr);
9400035d21cSmiao chen - Sun Microsystems - Beijing China 
9410035d21cSmiao chen - Sun Microsystems - Beijing China #if defined(__i386)
9420035d21cSmiao chen - Sun Microsystems - Beijing China 	dev->driver->use_gem = 0;
9430035d21cSmiao chen - Sun Microsystems - Beijing China #else
9440035d21cSmiao chen - Sun Microsystems - Beijing China 	if (IS_I965G(dev)) {
9450035d21cSmiao chen - Sun Microsystems - Beijing China 		dev->driver->use_gem = 1;
9460035d21cSmiao chen - Sun Microsystems - Beijing China 	} else {
9470035d21cSmiao chen - Sun Microsystems - Beijing China 		dev->driver->use_gem = 0;
9480035d21cSmiao chen - Sun Microsystems - Beijing China 	}
9490035d21cSmiao chen - Sun Microsystems - Beijing China #endif	/* __i386 */
9500035d21cSmiao chen - Sun Microsystems - Beijing China 
9510035d21cSmiao chen - Sun Microsystems - Beijing China 	dev->driver->get_vblank_counter = i915_get_vblank_counter;
9520035d21cSmiao chen - Sun Microsystems - Beijing China 	dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
9530035d21cSmiao chen - Sun Microsystems - Beijing China #if defined(__i386)
9542e6e901dSmiao chen - Sun Microsystems - Beijing China 	if (IS_G4X(dev) || IS_IGDNG(dev) || IS_GM45(dev))
9550035d21cSmiao chen - Sun Microsystems - Beijing China #else
9562e6e901dSmiao chen - Sun Microsystems - Beijing China 	if (IS_G4X(dev) || IS_IGDNG(dev))
9570035d21cSmiao chen - Sun Microsystems - Beijing China #endif
9580035d21cSmiao chen - Sun Microsystems - Beijing China 	{
9590035d21cSmiao chen - Sun Microsystems - Beijing China 		dev->max_vblank_count = 0xffffffff; /* full 32 bit counter */
9600035d21cSmiao chen - Sun Microsystems - Beijing China 		dev->driver->get_vblank_counter = gm45_get_vblank_counter;
9610035d21cSmiao chen - Sun Microsystems - Beijing China 	}
9620035d21cSmiao chen - Sun Microsystems - Beijing China 
9630035d21cSmiao chen - Sun Microsystems - Beijing China 
9640035d21cSmiao chen - Sun Microsystems - Beijing China #ifdef I915_HAVE_GEM
9650035d21cSmiao chen - Sun Microsystems - Beijing China 	i915_gem_load(dev);
9660035d21cSmiao chen - Sun Microsystems - Beijing China #endif
9670035d21cSmiao chen - Sun Microsystems - Beijing China 
9680035d21cSmiao chen - Sun Microsystems - Beijing China 	if (!I915_NEED_GFX_HWS(dev)) {
9690035d21cSmiao chen - Sun Microsystems - Beijing China 		ret = i915_init_hardware_status(dev);
9700035d21cSmiao chen - Sun Microsystems - Beijing China 		if(ret)
9710035d21cSmiao chen - Sun Microsystems - Beijing China 			return ret;
9720035d21cSmiao chen - Sun Microsystems - Beijing China 	}
9730035d21cSmiao chen - Sun Microsystems - Beijing China 
974d0231070Smiao chen - Sun Microsystems - Beijing China 	mutex_init(&dev_priv->user_irq_lock, "userirq", MUTEX_DRIVER, NULL);
9750035d21cSmiao chen - Sun Microsystems - Beijing China 	mutex_init(&dev_priv->error_lock, "error_lock", MUTEX_DRIVER, NULL);
976d0231070Smiao chen - Sun Microsystems - Beijing China 
9778566479dSEdward Shu 	ret = drm_vblank_init(dev, I915_NUM_PIPE);
9788566479dSEdward Shu 	if (ret) {
9798566479dSEdward Shu 		(void) i915_driver_unload(dev);
9808566479dSEdward Shu 		return ret;
9818566479dSEdward Shu 	}
9828566479dSEdward Shu 
983d0231070Smiao chen - Sun Microsystems - Beijing China 	return ret;
984ae115bc7Smrj }
985ae115bc7Smrj 
i915_driver_unload(struct drm_device * dev)98691fae470Scg149915 int i915_driver_unload(struct drm_device *dev)
98791fae470Scg149915 {
988d0231070Smiao chen - Sun Microsystems - Beijing China        drm_i915_private_t *dev_priv = dev->dev_private;
989d0231070Smiao chen - Sun Microsystems - Beijing China 
990d0231070Smiao chen - Sun Microsystems - Beijing China        i915_free_hardware_status(dev);
991d0231070Smiao chen - Sun Microsystems - Beijing China 
9920035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_rmmap(dev, dev_priv->mmio_map);
9930035d21cSmiao chen - Sun Microsystems - Beijing China 
994d0231070Smiao chen - Sun Microsystems - Beijing China         mutex_destroy(&dev_priv->user_irq_lock);
995d0231070Smiao chen - Sun Microsystems - Beijing China 
99691fae470Scg149915 	drm_free(dev->dev_private, sizeof(drm_i915_private_t),
99791fae470Scg149915 	    DRM_MEM_DRIVER);
998d0231070Smiao chen - Sun Microsystems - Beijing China 	dev->dev_private = NULL;
99991fae470Scg149915 
100091fae470Scg149915 	return 0;
100191fae470Scg149915 }
100291fae470Scg149915 
10030035d21cSmiao chen - Sun Microsystems - Beijing China /*ARGSUSED*/
i915_driver_open(drm_device_t * dev,struct drm_file * file_priv)10040035d21cSmiao chen - Sun Microsystems - Beijing China int i915_driver_open(drm_device_t * dev, struct drm_file *file_priv)
10050035d21cSmiao chen - Sun Microsystems - Beijing China {
10060035d21cSmiao chen - Sun Microsystems - Beijing China         struct drm_i915_file_private *i915_file_priv;
10070035d21cSmiao chen - Sun Microsystems - Beijing China 
10080035d21cSmiao chen - Sun Microsystems - Beijing China         DRM_DEBUG("\n");
10090035d21cSmiao chen - Sun Microsystems - Beijing China         i915_file_priv = (struct drm_i915_file_private *)
10100035d21cSmiao chen - Sun Microsystems - Beijing China             drm_alloc(sizeof(*i915_file_priv), DRM_MEM_FILES);
10110035d21cSmiao chen - Sun Microsystems - Beijing China 
10120035d21cSmiao chen - Sun Microsystems - Beijing China         if (!i915_file_priv)
10130035d21cSmiao chen - Sun Microsystems - Beijing China                 return -ENOMEM;
10140035d21cSmiao chen - Sun Microsystems - Beijing China 
10150035d21cSmiao chen - Sun Microsystems - Beijing China         file_priv->driver_priv = i915_file_priv;
10160035d21cSmiao chen - Sun Microsystems - Beijing China 
10170035d21cSmiao chen - Sun Microsystems - Beijing China         i915_file_priv->mm.last_gem_seqno = 0;
10180035d21cSmiao chen - Sun Microsystems - Beijing China         i915_file_priv->mm.last_gem_throttle_seqno = 0;
10190035d21cSmiao chen - Sun Microsystems - Beijing China 
10200035d21cSmiao chen - Sun Microsystems - Beijing China         return 0;
10210035d21cSmiao chen - Sun Microsystems - Beijing China }
102291fae470Scg149915 
i915_driver_lastclose(drm_device_t * dev)1023ae115bc7Smrj void i915_driver_lastclose(drm_device_t * dev)
1024ae115bc7Smrj {
1025ae115bc7Smrj 	drm_i915_private_t *dev_priv = dev->dev_private;
1026d0231070Smiao chen - Sun Microsystems - Beijing China 
1027d0231070Smiao chen - Sun Microsystems - Beijing China 	/* agp off can use this to get called before dev_priv */
1028d0231070Smiao chen - Sun Microsystems - Beijing China 	if (!dev_priv)
1029d0231070Smiao chen - Sun Microsystems - Beijing China 		return;
1030d0231070Smiao chen - Sun Microsystems - Beijing China 
10310035d21cSmiao chen - Sun Microsystems - Beijing China #ifdef I915_HAVE_GEM
10320035d21cSmiao chen - Sun Microsystems - Beijing China 	i915_gem_lastclose(dev);
1033d0231070Smiao chen - Sun Microsystems - Beijing China #endif
1034d0231070Smiao chen - Sun Microsystems - Beijing China 
1035d0231070Smiao chen - Sun Microsystems - Beijing China 	DRM_GETSAREA();
1036d0231070Smiao chen - Sun Microsystems - Beijing China 	if (dev_priv->agp_heap)
1037d0231070Smiao chen - Sun Microsystems - Beijing China 		i915_mem_takedown(&(dev_priv->agp_heap));
1038ae115bc7Smrj 	(void) i915_dma_cleanup(dev);
1039ae115bc7Smrj }
1040ae115bc7Smrj 
i915_driver_preclose(drm_device_t * dev,drm_file_t * fpriv)1041d0538f66Scg149915 void i915_driver_preclose(drm_device_t * dev, drm_file_t *fpriv)
1042ae115bc7Smrj {
1043ae115bc7Smrj 	drm_i915_private_t *dev_priv = dev->dev_private;
1044d0538f66Scg149915 	i915_mem_release(dev, fpriv, dev_priv->agp_heap);
1045ae115bc7Smrj }
10460035d21cSmiao chen - Sun Microsystems - Beijing China 
10470035d21cSmiao chen - Sun Microsystems - Beijing China /*ARGSUSED*/
i915_driver_postclose(drm_device_t * dev,struct drm_file * file_priv)10480035d21cSmiao chen - Sun Microsystems - Beijing China void i915_driver_postclose(drm_device_t * dev, struct drm_file *file_priv)
10490035d21cSmiao chen - Sun Microsystems - Beijing China {
10500035d21cSmiao chen - Sun Microsystems - Beijing China 	struct drm_i915_file_private *i915_file_priv = file_priv->driver_priv;
10510035d21cSmiao chen - Sun Microsystems - Beijing China 
10520035d21cSmiao chen - Sun Microsystems - Beijing China 	drm_free(i915_file_priv, sizeof(*i915_file_priv), DRM_MEM_FILES);
1053ae115bc7Smrj }
1054ae115bc7Smrj 
1055ee33b1b8Smiao chen - Sun Microsystems - Beijing China drm_ioctl_desc_t i915_ioctls[] = {
1056ee33b1b8Smiao chen - Sun Microsystems - Beijing China 	[DRM_IOCTL_NR(DRM_I915_INIT)] =
1057ee33b1b8Smiao chen - Sun Microsystems - Beijing China 	    {i915_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
1058ee33b1b8Smiao chen - Sun Microsystems - Beijing China 	[DRM_IOCTL_NR(DRM_I915_FLUSH)] =
1059ee33b1b8Smiao chen - Sun Microsystems - Beijing China 	    {i915_flush_ioctl, DRM_AUTH},
1060ee33b1b8Smiao chen - Sun Microsystems - Beijing China 	[DRM_IOCTL_NR(DRM_I915_FLIP)] =
1061ee33b1b8Smiao chen - Sun Microsystems - Beijing China 	    {i915_flip_bufs, DRM_AUTH},
1062ee33b1b8Smiao chen - Sun Microsystems - Beijing China 	[DRM_IOCTL_NR(DRM_I915_BATCHBUFFER)] =
1063ee33b1b8Smiao chen - Sun Microsystems - Beijing China 	    {i915_batchbuffer, DRM_AUTH},
1064ee33b1b8Smiao chen - Sun Microsystems - Beijing China 	[DRM_IOCTL_NR(DRM_I915_IRQ_EMIT)] =
1065ee33b1b8Smiao chen - Sun Microsystems - Beijing China 	    {i915_irq_emit, DRM_AUTH},
1066ee33b1b8Smiao chen - Sun Microsystems - Beijing China 	[DRM_IOCTL_NR(DRM_I915_IRQ_WAIT)] =
1067ee33b1b8Smiao chen - Sun Microsystems - Beijing China 	    {i915_irq_wait, DRM_AUTH},
1068ee33b1b8Smiao chen - Sun Microsystems - Beijing China 	[DRM_IOCTL_NR(DRM_I915_GETPARAM)] =
1069ee33b1b8Smiao chen - Sun Microsystems - Beijing China 	    {i915_getparam, DRM_AUTH},
1070ee33b1b8Smiao chen - Sun Microsystems - Beijing China 	[DRM_IOCTL_NR(DRM_I915_SETPARAM)] =
1071ee33b1b8Smiao chen - Sun Microsystems - Beijing China 	    {i915_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
1072ee33b1b8Smiao chen - Sun Microsystems - Beijing China 	[DRM_IOCTL_NR(DRM_I915_ALLOC)] =
1073ee33b1b8Smiao chen - Sun Microsystems - Beijing China 	    {i915_mem_alloc, DRM_AUTH},
1074ee33b1b8Smiao chen - Sun Microsystems - Beijing China 	[DRM_IOCTL_NR(DRM_I915_FREE)] =
1075ee33b1b8Smiao chen - Sun Microsystems - Beijing China 	    {i915_mem_free, DRM_AUTH},
1076ee33b1b8Smiao chen - Sun Microsystems - Beijing China 	[DRM_IOCTL_NR(DRM_I915_INIT_HEAP)] =
1077ee33b1b8Smiao chen - Sun Microsystems - Beijing China 	    {i915_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
1078ee33b1b8Smiao chen - Sun Microsystems - Beijing China 	[DRM_IOCTL_NR(DRM_I915_CMDBUFFER)] =
1079ee33b1b8Smiao chen - Sun Microsystems - Beijing China 	    {i915_cmdbuffer, DRM_AUTH},
1080ee33b1b8Smiao chen - Sun Microsystems - Beijing China 	[DRM_IOCTL_NR(DRM_I915_DESTROY_HEAP)] =
1081ee33b1b8Smiao chen - Sun Microsystems - Beijing China 	    {i915_mem_destroy_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
1082d0231070Smiao chen - Sun Microsystems - Beijing China 	[DRM_IOCTL_NR(DRM_I915_SET_VBLANK_PIPE)] =
10830035d21cSmiao chen - Sun Microsystems - Beijing China 	    {i915_vblank_pipe_set, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
1084d0231070Smiao chen - Sun Microsystems - Beijing China 	[DRM_IOCTL_NR(DRM_I915_GET_VBLANK_PIPE)] =
1085d0231070Smiao chen - Sun Microsystems - Beijing China 	    {i915_vblank_pipe_get, DRM_AUTH},
1086d0231070Smiao chen - Sun Microsystems - Beijing China 	[DRM_IOCTL_NR(DRM_I915_VBLANK_SWAP)] =
1087d0231070Smiao chen - Sun Microsystems - Beijing China 	    {i915_vblank_swap, DRM_AUTH},
1088ee33b1b8Smiao chen - Sun Microsystems - Beijing China 	[DRM_IOCTL_NR(DRM_I915_HWS_ADDR)] =
1089ee33b1b8Smiao chen - Sun Microsystems - Beijing China 	    {i915_set_status_page, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
10900035d21cSmiao chen - Sun Microsystems - Beijing China #ifdef I915_HAVE_GEM
10910035d21cSmiao chen - Sun Microsystems - Beijing China         [DRM_IOCTL_NR(DRM_I915_GEM_INIT)] =
10920035d21cSmiao chen - Sun Microsystems - Beijing China             {i915_gem_init_ioctl, DRM_AUTH},
10930035d21cSmiao chen - Sun Microsystems - Beijing China         [DRM_IOCTL_NR(DRM_I915_GEM_EXECBUFFER)] =
10940035d21cSmiao chen - Sun Microsystems - Beijing China             {i915_gem_execbuffer, DRM_AUTH},
10950035d21cSmiao chen - Sun Microsystems - Beijing China         [DRM_IOCTL_NR(DRM_I915_GEM_PIN)] =
10960035d21cSmiao chen - Sun Microsystems - Beijing China             {i915_gem_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY},
10970035d21cSmiao chen - Sun Microsystems - Beijing China         [DRM_IOCTL_NR(DRM_I915_GEM_UNPIN)] =
10980035d21cSmiao chen - Sun Microsystems - Beijing China             {i915_gem_unpin_ioctl, DRM_AUTH|DRM_ROOT_ONLY},
10990035d21cSmiao chen - Sun Microsystems - Beijing China         [DRM_IOCTL_NR(DRM_I915_GEM_BUSY)] =
11000035d21cSmiao chen - Sun Microsystems - Beijing China             {i915_gem_busy_ioctl, DRM_AUTH},
11010035d21cSmiao chen - Sun Microsystems - Beijing China         [DRM_IOCTL_NR(DRM_I915_GEM_THROTTLE)] =
11020035d21cSmiao chen - Sun Microsystems - Beijing China             {i915_gem_throttle_ioctl, DRM_AUTH},
11030035d21cSmiao chen - Sun Microsystems - Beijing China         [DRM_IOCTL_NR(DRM_I915_GEM_ENTERVT)] =
11040035d21cSmiao chen - Sun Microsystems - Beijing China             {i915_gem_entervt_ioctl, DRM_AUTH},
11050035d21cSmiao chen - Sun Microsystems - Beijing China         [DRM_IOCTL_NR(DRM_I915_GEM_LEAVEVT)] =
11060035d21cSmiao chen - Sun Microsystems - Beijing China             {i915_gem_leavevt_ioctl, DRM_AUTH},
11070035d21cSmiao chen - Sun Microsystems - Beijing China         [DRM_IOCTL_NR(DRM_I915_GEM_CREATE)] =
11080035d21cSmiao chen - Sun Microsystems - Beijing China             {i915_gem_create_ioctl, 0},
11090035d21cSmiao chen - Sun Microsystems - Beijing China         [DRM_IOCTL_NR(DRM_I915_GEM_PREAD)] =
11100035d21cSmiao chen - Sun Microsystems - Beijing China             {i915_gem_pread_ioctl, 0},
11110035d21cSmiao chen - Sun Microsystems - Beijing China         [DRM_IOCTL_NR(DRM_I915_GEM_PWRITE)] =
11120035d21cSmiao chen - Sun Microsystems - Beijing China             {i915_gem_pwrite_ioctl, 0},
11130035d21cSmiao chen - Sun Microsystems - Beijing China         [DRM_IOCTL_NR(DRM_I915_GEM_MMAP)] =
11140035d21cSmiao chen - Sun Microsystems - Beijing China             {i915_gem_mmap_ioctl, 0},
11150035d21cSmiao chen - Sun Microsystems - Beijing China         [DRM_IOCTL_NR(DRM_I915_GEM_SET_DOMAIN)] =
11160035d21cSmiao chen - Sun Microsystems - Beijing China             {i915_gem_set_domain_ioctl, 0},
11170035d21cSmiao chen - Sun Microsystems - Beijing China         [DRM_IOCTL_NR(DRM_I915_GEM_SW_FINISH)] =
11180035d21cSmiao chen - Sun Microsystems - Beijing China             {i915_gem_sw_finish_ioctl, 0},
11190035d21cSmiao chen - Sun Microsystems - Beijing China         [DRM_IOCTL_NR(DRM_I915_GEM_SET_TILING)] =
11200035d21cSmiao chen - Sun Microsystems - Beijing China             {i915_gem_set_tiling, 0},
11210035d21cSmiao chen - Sun Microsystems - Beijing China         [DRM_IOCTL_NR(DRM_I915_GEM_GET_TILING)] =
11220035d21cSmiao chen - Sun Microsystems - Beijing China             {i915_gem_get_tiling, 0},
11230035d21cSmiao chen - Sun Microsystems - Beijing China         [DRM_IOCTL_NR(DRM_I915_GEM_GET_APERTURE)] =
11240035d21cSmiao chen - Sun Microsystems - Beijing China             {i915_gem_get_aperture_ioctl, 0},
11250035d21cSmiao chen - Sun Microsystems - Beijing China #endif
1126ee33b1b8Smiao chen - Sun Microsystems - Beijing China };
1127ae115bc7Smrj 
1128ee33b1b8Smiao chen - Sun Microsystems - Beijing China int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
1129ee33b1b8Smiao chen - Sun Microsystems - Beijing China 
1130ae115bc7Smrj /**
1131ae115bc7Smrj  * Determine if the device really is AGP or not.
1132ae115bc7Smrj  *
1133ae115bc7Smrj  * All Intel graphics chipsets are treated as AGP, even if they are really
1134ae115bc7Smrj  * PCI-e.
1135ae115bc7Smrj  *
1136ae115bc7Smrj  * \param dev   The device to be tested.
1137ae115bc7Smrj  *
1138ae115bc7Smrj  * \returns
1139ae115bc7Smrj  * A value of 1 is always retured to indictate every i9x5 is AGP.
1140ae115bc7Smrj  */
1141ae115bc7Smrj /*ARGSUSED*/
i915_driver_device_is_agp(drm_device_t * dev)1142ae115bc7Smrj int i915_driver_device_is_agp(drm_device_t * dev)
1143ae115bc7Smrj {
1144ae115bc7Smrj 	return 1;
1145ae115bc7Smrj }
1146d0231070Smiao chen - Sun Microsystems - Beijing China 
1147