i915_dma.c revision ed4c9c4acf948b42b138747fcb8843ecb1a24ce4
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* i915_dma.c -- DMA support for the I915 -*- linux-c -*-
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
30d6aa60b4ac9689b750e35cd66f5d7c053aff0f4Dave Airlie/*
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * All Rights Reserved.
6bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie *
7bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * Permission is hereby granted, free of charge, to any person obtaining a
8bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * copy of this software and associated documentation files (the
9bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * "Software"), to deal in the Software without restriction, including
10bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * without limitation the rights to use, copy, modify, merge, publish,
11bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * distribute, sub license, and/or sell copies of the Software, and to
12bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * permit persons to whom the Software is furnished to do so, subject to
13bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * the following conditions:
14bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie *
15bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * The above copyright notice and this permission notice (including the
16bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * next paragraph) shall be included in all copies or substantial portions
17bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * of the Software.
18bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie *
19bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
23bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie *
270d6aa60b4ac9689b750e35cd66f5d7c053aff0f4Dave Airlie */
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "drmP.h"
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "drm.h"
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "i915_drm.h"
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "i915_drv.h"
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Really want an OS-independent resettable timer.  Would like to have
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * this loop run for (eg) 3 sec, but have the timer reset every time
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the head pointer changes, so that EBUSY only happens if the ring
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * actually stalls for (eg) 3 seconds.
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
3984b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airlieint i915_wait_ring(struct drm_device * dev, int n, const char *caller)
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = dev->dev_private;
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
43d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard	u32 acthd_reg = IS_I965G(dev) ? ACTHD_I965 : ACTHD;
44d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard	u32 last_acthd = I915_READ(acthd_reg);
45d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard	u32 acthd;
46585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes	u32 last_head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
49d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard	for (i = 0; i < 100000; i++) {
50585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes		ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
51d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard		acthd = I915_READ(acthd_reg);
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ring->space = ring->head - (ring->tail + 8);
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ring->space < 0)
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ring->space += ring->Size;
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ring->space >= n)
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 0;
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ring->head != last_head)
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			i = 0;
62d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard		if (acthd != last_acthd)
63d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard			i = 0;
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		last_head = ring->head;
66d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard		last_acthd = acthd;
67d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard		msleep_interruptible(10);
68d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7120caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt	return -EBUSY;
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
74398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard/**
75398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard * Sets up the hardware status page for devices that need a physical address
76398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard * in the register.
77398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard */
78398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packardint i915_init_phys_hws(struct drm_device *dev)
79398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard{
80398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	drm_i915_private_t *dev_priv = dev->dev_private;
81398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	/* Program Hardware Status Page */
82398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	dev_priv->status_page_dmah =
83398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard		drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff);
84398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard
85398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	if (!dev_priv->status_page_dmah) {
86398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard		DRM_ERROR("Can not allocate hardware status page\n");
87398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard		return -ENOMEM;
88398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	}
89398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr;
90398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
91398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard
92398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
93398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard
94398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	I915_WRITE(HWS_PGA, dev_priv->dma_status_page);
95398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	DRM_DEBUG("Enabled hardware status page\n");
96398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	return 0;
97398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard}
98398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard
99398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard/**
100398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard * Frees the hardware status page, whether it's a physical address or a virtual
101398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard * address set up by the X Server.
102398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard */
103398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packardvoid i915_free_hws(struct drm_device *dev)
104398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard{
105398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	drm_i915_private_t *dev_priv = dev->dev_private;
106398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	if (dev_priv->status_page_dmah) {
107398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard		drm_pci_free(dev, dev_priv->status_page_dmah);
108398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard		dev_priv->status_page_dmah = NULL;
109398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	}
110398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard
111398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	if (dev_priv->status_gfx_addr) {
112398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard		dev_priv->status_gfx_addr = 0;
113398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard		drm_core_ioremapfree(&dev_priv->hws_map, dev);
114398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	}
115398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard
116398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	/* Need to rewrite hardware status page */
117398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	I915_WRITE(HWS_PGA, 0x1ffff000);
118398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard}
119398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard
12084b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airlievoid i915_kernel_lost_context(struct drm_device * dev)
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = dev->dev_private;
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
125585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes	ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
126585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes	ring->tail = I915_READ(PRB0_TAIL) & TAIL_ADDR;
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ring->space = ring->head - (ring->tail + 8);
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ring->space < 0)
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ring->space += ring->Size;
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ring->head == ring->tail)
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_priv->sarea_priv->perf_boxes |= I915_BOX_RING_EMPTY;
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13584b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airliestatic int i915_dma_cleanup(struct drm_device * dev)
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
137ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	drm_i915_private_t *dev_priv = dev->dev_private;
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Make sure interrupts are disabled here because the uninstall ioctl
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * may not have been called from userspace and after dev_private
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * is freed, it's too late.
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
142ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt	if (dev->irq_enabled)
143b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		drm_irq_uninstall(dev);
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
145ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	if (dev_priv->ring.virtual_start) {
146ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes		drm_core_ioremapfree(&dev_priv->ring.map, dev);
147ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes		dev_priv->ring.virtual_start = 0;
148ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes		dev_priv->ring.map.handle = 0;
149ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes		dev_priv->ring.map.size = 0;
150ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	}
151dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu
152398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	/* Clear the HWS virtual address at teardown */
153398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	if (I915_NEED_GFX_HWS(dev))
154398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard		i915_free_hws(dev);
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
159ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnesstatic int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
161ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	drm_i915_private_t *dev_priv = dev->dev_private;
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
163da509d7a02cb54938776439edc81f057e39f81e0Dave Airlie	dev_priv->sarea = drm_getsarea(dev);
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!dev_priv->sarea) {
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("can not find sarea!\n");
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		i915_dma_cleanup(dev);
16720caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_priv->sarea_priv = (drm_i915_sarea_t *)
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    ((u8 *) dev_priv->sarea->handle + init->sarea_priv_offset);
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
173673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	if (init->ring_size != 0) {
174673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		if (dev_priv->ring.ring_obj != NULL) {
175673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt			i915_dma_cleanup(dev);
176673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt			DRM_ERROR("Client tried to initialize ringbuffer in "
177673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt				  "GEM mode\n");
178673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt			return -EINVAL;
179673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		}
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
181673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		dev_priv->ring.Size = init->ring_size;
182673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
184673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		dev_priv->ring.map.offset = init->ring_start;
185673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		dev_priv->ring.map.size = init->ring_size;
186673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		dev_priv->ring.map.type = 0;
187673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		dev_priv->ring.map.flags = 0;
188673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		dev_priv->ring.map.mtrr = 0;
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
190673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		drm_core_ioremap(&dev_priv->ring.map, dev);
191673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt
192673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		if (dev_priv->ring.map.handle == NULL) {
193673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt			i915_dma_cleanup(dev);
194673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt			DRM_ERROR("can not ioremap virtual address for"
195673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt				  " ring buffer\n");
196673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt			return -ENOMEM;
197673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		}
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
202a6b54f3f5050c0cbc0c35dd48064846c6302706bMichel Dänzer	dev_priv->cpp = init->cpp;
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_priv->back_offset = init->back_offset;
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_priv->front_offset = init->front_offset;
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_priv->current_page = 0;
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Allow hardware batchbuffers unless told otherwise.
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_priv->allow_batchbuffer = 1;
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21584b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airliestatic int i915_dma_resume(struct drm_device * dev)
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
219bf9d89295233ae2ba7b312c78ee5657307b09f4cHarvey Harrison	DRM_DEBUG("%s\n", __func__);
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!dev_priv->sarea) {
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("can not find sarea!\n");
22320caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (dev_priv->ring.map.handle == NULL) {
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("can not ioremap virtual address for"
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			  " ring buffer\n");
22920caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -ENOMEM;
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Program Hardware Status Page */
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!dev_priv->hw_status_page) {
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("Can not find hardware status page\n");
23520caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
239dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	if (dev_priv->status_gfx_addr != 0)
240585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes		I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
241dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	else
242585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes		I915_WRITE(HWS_PGA, dev_priv->dma_status_page);
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DRM_DEBUG("Enabled hardware status page\n");
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
248c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_dma_init(struct drm_device *dev, void *data,
249c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt			 struct drm_file *file_priv)
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
251c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	drm_i915_init_t *init = data;
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int retcode = 0;
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
254c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	switch (init->func) {
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case I915_INIT_DMA:
256ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes		retcode = i915_initialize(dev, init);
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case I915_CLEANUP_DMA:
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		retcode = i915_dma_cleanup(dev);
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case I915_RESUME_DMA:
2620d6aa60b4ac9689b750e35cd66f5d7c053aff0f4Dave Airlie		retcode = i915_dma_resume(dev);
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
26520caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		retcode = -EINVAL;
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return retcode;
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Implement basically the same security restrictions as hardware does
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * for MI_BATCH_NON_SECURE.  These can be made stricter at any time.
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Most of the calculations below involve calculating the size of a
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * particular instruction.  It's important to get the size right as
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * that tells us where the next instruction to check is.  Any illegal
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * instruction detected will be given a size of zero, which is a
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * signal to abort the rest of the buffer.
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int do_validate_cmd(int cmd)
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (((cmd >> 29) & 0x7)) {
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 0x0:
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch ((cmd >> 23) & 0x3f) {
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x0:
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 1;	/* MI_NOOP */
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x4:
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 1;	/* MI_FLUSH */
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		default:
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 0;	/* disallow everything else */
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 0x1:
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;	/* reserved */
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 0x2:
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (cmd & 0xff) + 2;	/* 2d commands */
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 0x3:
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (((cmd >> 24) & 0x1f) <= 0x18)
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 1;
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch ((cmd >> 24) & 0x1f) {
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x1c:
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 1;
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x1d:
306b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			switch ((cmd >> 16) & 0xff) {
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case 0x3:
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return (cmd & 0x1f) + 2;
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case 0x4:
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return (cmd & 0xf) + 2;
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			default:
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return (cmd & 0xffff) + 2;
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x1e:
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (cmd & (1 << 23))
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return (cmd & 0xffff) + 1;
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return 1;
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x1f:
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if ((cmd & (1 << 23)) == 0)	/* inline vertices */
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return (cmd & 0x1ffff) + 2;
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else if (cmd & (1 << 17))	/* indirect random */
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if ((cmd & 0xffff) == 0)
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					return 0;	/* unknown length, too hard */
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				else
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					return (((cmd & 0xffff) + 1) / 2) + 1;
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return 2;	/* indirect sequential */
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		default:
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 0;
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int validate_cmd(int cmd)
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret = do_validate_cmd(cmd);
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
343bc5f4523f772cc7629c5c5a46cf4f2a07a5500b8Dave Airlie/*	printk("validate_cmd( %x ): %d\n", cmd, ret); */
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34884b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airliestatic int i915_emit_cmds(struct drm_device * dev, int __user * buffer, int dwords)
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = dev->dev_private;
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	RING_LOCALS;
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
354de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	if ((dwords+1) * sizeof(int) >= dev_priv->ring.Size - 8)
35520caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
356de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie
357c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane	BEGIN_LP_RING((dwords+1)&~1);
358de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < dwords;) {
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		int cmd, sz;
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i], sizeof(cmd)))
36320caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt			return -EINVAL;
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((sz = validate_cmd(cmd)) == 0 || i + sz > dwords)
36620caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt			return -EINVAL;
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		OUT_RING(cmd);
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		while (++i, --sz) {
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i],
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							 sizeof(cmd))) {
37320caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt				return -EINVAL;
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			OUT_RING(cmd);
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
379de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	if (dwords & 1)
380de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie		OUT_RING(0);
381de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie
382de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	ADVANCE_LP_RING();
383de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
387673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholtint
388673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholti915_emit_box(struct drm_device *dev,
389673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	      struct drm_clip_rect __user *boxes,
390673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	      int i, int DR1, int DR4)
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = dev->dev_private;
393c60ce623bd16137627009d05e311d877729f2ad6Dave Airlie	struct drm_clip_rect box;
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	RING_LOCALS;
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (DRM_COPY_FROM_USER_UNCHECKED(&box, &boxes[i], sizeof(box))) {
39720caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EFAULT;
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (box.y2 <= box.y1 || box.x2 <= box.x1 || box.y2 <= 0 || box.x2 <= 0) {
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("Bad box %d,%d..%d,%d\n",
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			  box.x1, box.y1, box.x2, box.y2);
40320caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
406c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane	if (IS_I965G(dev)) {
407c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		BEGIN_LP_RING(4);
408c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		OUT_RING(GFX_OP_DRAWRECT_INFO_I965);
409c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		OUT_RING((box.x1 & 0xffff) | (box.y1 << 16));
41078eca43d0391f59c3b1505bb7bd38ff45b650aabAndrew Morton		OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16));
411c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		OUT_RING(DR4);
412c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		ADVANCE_LP_RING();
413c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane	} else {
414c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		BEGIN_LP_RING(6);
415c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		OUT_RING(GFX_OP_DRAWRECT_INFO);
416c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		OUT_RING(DR1);
417c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		OUT_RING((box.x1 & 0xffff) | (box.y1 << 16));
418c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16));
419c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		OUT_RING(DR4);
420c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		OUT_RING(0);
421c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		ADVANCE_LP_RING();
422c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane	}
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
427c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane/* XXX: Emitting the counter should really be moved to part of the IRQ
428c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane * emit. For now, do it in both places:
429c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane */
430c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane
43184b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airliestatic void i915_emit_breadcrumb(struct drm_device *dev)
432de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie{
433de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	drm_i915_private_t *dev_priv = dev->dev_private;
434de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	RING_LOCALS;
435de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie
436af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	dev_priv->sarea_priv->last_enqueue = ++dev_priv->counter;
437c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane
438af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	if (dev_priv->counter > 0x7FFFFFFFUL)
439af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie		dev_priv->sarea_priv->last_enqueue = dev_priv->counter = 1;
440de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie
441de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	BEGIN_LP_RING(4);
442585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes	OUT_RING(MI_STORE_DWORD_INDEX);
443585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes	OUT_RING(5 << MI_STORE_DWORD_INDEX_SHIFT);
444de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	OUT_RING(dev_priv->counter);
445de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	OUT_RING(0);
446de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	ADVANCE_LP_RING();
447de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie}
448de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie
44984b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airliestatic int i915_dispatch_cmdbuffer(struct drm_device * dev,
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   drm_i915_cmdbuffer_t * cmd)
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int nbox = cmd->num_cliprects;
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i = 0, count, ret;
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (cmd->sz & 0x3) {
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("alignment");
45720caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	i915_kernel_lost_context(dev);
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	count = nbox ? nbox : 1;
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < count; i++) {
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (i < nbox) {
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ret = i915_emit_box(dev, cmd->cliprects, i,
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					    cmd->DR1, cmd->DR4);
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (ret)
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return ret;
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = i915_emit_cmds(dev, (int __user *)cmd->buf, cmd->sz / 4);
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ret)
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return ret;
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
477de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	i915_emit_breadcrumb(dev);
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
48184b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airliestatic int i915_dispatch_batchbuffer(struct drm_device * dev,
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     drm_i915_batchbuffer_t * batch)
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = dev->dev_private;
485c60ce623bd16137627009d05e311d877729f2ad6Dave Airlie	struct drm_clip_rect __user *boxes = batch->cliprects;
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int nbox = batch->num_cliprects;
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i = 0, count;
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	RING_LOCALS;
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((batch->start | batch->used) & 0x7) {
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("alignment");
49220caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	i915_kernel_lost_context(dev);
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	count = nbox ? nbox : 1;
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < count; i++) {
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (i < nbox) {
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			int ret = i915_emit_box(dev, boxes, i,
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						batch->DR1, batch->DR4);
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (ret)
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return ret;
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5070790d5e148c0747499742a3c09ba5f1c07f9ed0dKeith Packard		if (!IS_I830(dev) && !IS_845G(dev)) {
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			BEGIN_LP_RING(2);
50921f16289270447673a7263ccc0b22d562fb01ecbDave Airlie			if (IS_I965G(dev)) {
51021f16289270447673a7263ccc0b22d562fb01ecbDave Airlie				OUT_RING(MI_BATCH_BUFFER_START | (2 << 6) | MI_BATCH_NON_SECURE_I965);
51121f16289270447673a7263ccc0b22d562fb01ecbDave Airlie				OUT_RING(batch->start);
51221f16289270447673a7263ccc0b22d562fb01ecbDave Airlie			} else {
51321f16289270447673a7263ccc0b22d562fb01ecbDave Airlie				OUT_RING(MI_BATCH_BUFFER_START | (2 << 6));
51421f16289270447673a7263ccc0b22d562fb01ecbDave Airlie				OUT_RING(batch->start | MI_BATCH_NON_SECURE);
51521f16289270447673a7263ccc0b22d562fb01ecbDave Airlie			}
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ADVANCE_LP_RING();
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			BEGIN_LP_RING(4);
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			OUT_RING(MI_BATCH_BUFFER);
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			OUT_RING(batch->start | MI_BATCH_NON_SECURE);
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			OUT_RING(batch->start + batch->used - 4);
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			OUT_RING(0);
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ADVANCE_LP_RING();
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
527de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	i915_emit_breadcrumb(dev);
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
532af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airliestatic int i915_dispatch_flip(struct drm_device * dev)
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = dev->dev_private;
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	RING_LOCALS;
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
537af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
53880a914dc05683ecfc98f9e1887fd6564846ffbecHarvey Harrison		  __func__,
539af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie		  dev_priv->current_page,
540af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie		  dev_priv->sarea_priv->pf_current_page);
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
542af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	i915_kernel_lost_context(dev);
543af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie
544af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	BEGIN_LP_RING(2);
545585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes	OUT_RING(MI_FLUSH | MI_READ_FLUSH);
546af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	OUT_RING(0);
547af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	ADVANCE_LP_RING();
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
549af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	BEGIN_LP_RING(6);
550af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP);
551af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	OUT_RING(0);
552af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	if (dev_priv->current_page == 0) {
553af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie		OUT_RING(dev_priv->back_offset);
554af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie		dev_priv->current_page = 1;
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
556af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie		OUT_RING(dev_priv->front_offset);
557af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie		dev_priv->current_page = 0;
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
559af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	OUT_RING(0);
560af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	ADVANCE_LP_RING();
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
562af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	BEGIN_LP_RING(2);
563af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP);
564af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	OUT_RING(0);
565af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	ADVANCE_LP_RING();
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
567af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	dev_priv->sarea_priv->last_enqueue = dev_priv->counter++;
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	BEGIN_LP_RING(4);
570585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes	OUT_RING(MI_STORE_DWORD_INDEX);
571585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes	OUT_RING(5 << MI_STORE_DWORD_INDEX_SHIFT);
572af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	OUT_RING(dev_priv->counter);
573af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	OUT_RING(0);
5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ADVANCE_LP_RING();
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
576af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
577af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	return 0;
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
58084b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airliestatic int i915_quiescent(struct drm_device * dev)
5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = dev->dev_private;
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	i915_kernel_lost_context(dev);
585bf9d89295233ae2ba7b312c78ee5657307b09f4cHarvey Harrison	return i915_wait_ring(dev, dev_priv->ring.Size - 8, __func__);
5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
588c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_flush_ioctl(struct drm_device *dev, void *data,
589c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt			    struct drm_file *file_priv)
5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5916c340eac0285f3d62406d2d902d0e96fbf2a5dc0Eric Anholt	LOCK_TEST_WITH_RETURN(dev, file_priv);
5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return i915_quiescent(dev);
5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
596c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_batchbuffer(struct drm_device *dev, void *data,
597c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt			    struct drm_file *file_priv)
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
600af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	u32 *hw_status = dev_priv->hw_status_page;
6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    dev_priv->sarea_priv;
603c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	drm_i915_batchbuffer_t *batch = data;
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret;
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!dev_priv->allow_batchbuffer) {
6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("Batchbuffer ioctl disabled\n");
60820caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DRM_DEBUG("i915 batchbuffer, start %x used %d cliprects %d\n",
612c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt		  batch->start, batch->used, batch->num_cliprects);
6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6146c340eac0285f3d62406d2d902d0e96fbf2a5dc0Eric Anholt	LOCK_TEST_WITH_RETURN(dev, file_priv);
6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
616c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	if (batch->num_cliprects && DRM_VERIFYAREA_READ(batch->cliprects,
617c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt						       batch->num_cliprects *
618c60ce623bd16137627009d05e311d877729f2ad6Dave Airlie						       sizeof(struct drm_clip_rect)))
61920caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EFAULT;
6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
621c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	ret = i915_dispatch_batchbuffer(dev, batch);
6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
623af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	sarea_priv->last_dispatch = (int)hw_status[5];
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
627c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_cmdbuffer(struct drm_device *dev, void *data,
628c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt			  struct drm_file *file_priv)
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
631af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	u32 *hw_status = dev_priv->hw_status_page;
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    dev_priv->sarea_priv;
634c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	drm_i915_cmdbuffer_t *cmdbuf = data;
6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret;
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DRM_DEBUG("i915 cmdbuffer, buf %p sz %d cliprects %d\n",
638c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt		  cmdbuf->buf, cmdbuf->sz, cmdbuf->num_cliprects);
6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6406c340eac0285f3d62406d2d902d0e96fbf2a5dc0Eric Anholt	LOCK_TEST_WITH_RETURN(dev, file_priv);
6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
642c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	if (cmdbuf->num_cliprects &&
643c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	    DRM_VERIFYAREA_READ(cmdbuf->cliprects,
644c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt				cmdbuf->num_cliprects *
645c60ce623bd16137627009d05e311d877729f2ad6Dave Airlie				sizeof(struct drm_clip_rect))) {
6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("Fault accessing cliprects\n");
64720caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EFAULT;
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
650c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	ret = i915_dispatch_cmdbuffer(dev, cmdbuf);
6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ret) {
6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("i915_dispatch_cmdbuffer failed\n");
6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return ret;
6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
656af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	sarea_priv->last_dispatch = (int)hw_status[5];
6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
660c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_flip_bufs(struct drm_device *dev, void *data,
661c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt			  struct drm_file *file_priv)
6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
66380a914dc05683ecfc98f9e1887fd6564846ffbecHarvey Harrison	DRM_DEBUG("%s\n", __func__);
6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6656c340eac0285f3d62406d2d902d0e96fbf2a5dc0Eric Anholt	LOCK_TEST_WITH_RETURN(dev, file_priv);
6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
667af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	return i915_dispatch_flip(dev);
6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
670c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_getparam(struct drm_device *dev, void *data,
671c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt			 struct drm_file *file_priv)
6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = dev->dev_private;
674c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	drm_i915_getparam_t *param = data;
6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int value;
6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!dev_priv) {
6783e684eae586a9b210a4517da5637a255b1ff5a92Márton Németh		DRM_ERROR("called with no initialization\n");
67920caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
682c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	switch (param->param) {
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case I915_PARAM_IRQ_ACTIVE:
6840a3e67a4caac273a3bfc4ced3da364830b1ab241Jesse Barnes		value = dev->pdev->irq ? 1 : 0;
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case I915_PARAM_ALLOW_BATCHBUFFER:
6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		value = dev_priv->allow_batchbuffer ? 1 : 0;
6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
6890d6aa60b4ac9689b750e35cd66f5d7c053aff0f4Dave Airlie	case I915_PARAM_LAST_DISPATCH:
6900d6aa60b4ac9689b750e35cd66f5d7c053aff0f4Dave Airlie		value = READ_BREADCRUMB(dev_priv);
6910d6aa60b4ac9689b750e35cd66f5d7c053aff0f4Dave Airlie		break;
692ed4c9c4acf948b42b138747fcb8843ecb1a24ce4Kristian Høgsberg	case I915_PARAM_CHIPSET_ID:
693ed4c9c4acf948b42b138747fcb8843ecb1a24ce4Kristian Høgsberg		value = dev->pci_device;
694ed4c9c4acf948b42b138747fcb8843ecb1a24ce4Kristian Høgsberg		break;
695673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	case I915_PARAM_HAS_GEM:
696673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		value = 1;
697673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		break;
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
699c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt		DRM_ERROR("Unknown parameter %d\n", param->param);
70020caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
703c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) {
7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("DRM_COPY_TO_USER failed\n");
70520caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EFAULT;
7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
711c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_setparam(struct drm_device *dev, void *data,
712c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt			 struct drm_file *file_priv)
7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = dev->dev_private;
715c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	drm_i915_setparam_t *param = data;
7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!dev_priv) {
7183e684eae586a9b210a4517da5637a255b1ff5a92Márton Németh		DRM_ERROR("called with no initialization\n");
71920caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
722c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	switch (param->param) {
7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case I915_SETPARAM_USE_MI_BATCHBUFFER_START:
7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case I915_SETPARAM_TEX_LRU_LOG_GRANULARITY:
726c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt		dev_priv->tex_lru_log_granularity = param->value;
7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case I915_SETPARAM_ALLOW_BATCHBUFFER:
729c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt		dev_priv->allow_batchbuffer = param->value;
7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
732c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt		DRM_ERROR("unknown parameter %d\n", param->param);
73320caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
739c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_set_status_page(struct drm_device *dev, void *data,
740c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt				struct drm_file *file_priv)
741dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu{
742dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	drm_i915_private_t *dev_priv = dev->dev_private;
743c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	drm_i915_hws_addr_t *hws = data;
744b39d50e53b1bb27f6c29f88a697a4af78427dffdZhenyu Wang
745b39d50e53b1bb27f6c29f88a697a4af78427dffdZhenyu Wang	if (!I915_NEED_GFX_HWS(dev))
746b39d50e53b1bb27f6c29f88a697a4af78427dffdZhenyu Wang		return -EINVAL;
747dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu
748dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	if (!dev_priv) {
7493e684eae586a9b210a4517da5637a255b1ff5a92Márton Németh		DRM_ERROR("called with no initialization\n");
75020caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
751dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	}
752dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu
753c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	printk(KERN_DEBUG "set status page addr 0x%08x\n", (u32)hws->addr);
754c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt
755c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	dev_priv->status_gfx_addr = hws->addr & (0x1ffff<<12);
756dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu
7578b40958032fd236194de57d29be9cf2c1f2643eeEric Anholt	dev_priv->hws_map.offset = dev->agp->base + hws->addr;
758dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	dev_priv->hws_map.size = 4*1024;
759dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	dev_priv->hws_map.type = 0;
760dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	dev_priv->hws_map.flags = 0;
761dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	dev_priv->hws_map.mtrr = 0;
762dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu
763dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	drm_core_ioremap(&dev_priv->hws_map, dev);
764dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	if (dev_priv->hws_map.handle == NULL) {
765dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu		i915_dma_cleanup(dev);
766dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu		dev_priv->status_gfx_addr = 0;
767dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu		DRM_ERROR("can not ioremap virtual address for"
768dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu				" G33 hw status page\n");
76920caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -ENOMEM;
770dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	}
771dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	dev_priv->hw_status_page = dev_priv->hws_map.handle;
772dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu
773dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
774585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes	I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
775585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes	DRM_DEBUG("load hws HWS_PGA with gfx mem 0x%x\n",
776dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu			dev_priv->status_gfx_addr);
777dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	DRM_DEBUG("load hws at %p\n", dev_priv->hw_status_page);
778dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	return 0;
779dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu}
780dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu
78184b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airlieint i915_driver_load(struct drm_device *dev, unsigned long flags)
78222eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie{
783ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	struct drm_i915_private *dev_priv = dev->dev_private;
784ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	unsigned long base, size;
785ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	int ret = 0, mmio_bar = IS_I9XX(dev) ? 0 : 1;
786ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
78722eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie	/* i915 has 4 more counters */
78822eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie	dev->counters += 4;
78922eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie	dev->types[6] = _DRM_STAT_IRQ;
79022eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie	dev->types[7] = _DRM_STAT_PRIMARY;
79122eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie	dev->types[8] = _DRM_STAT_SECONDARY;
79222eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie	dev->types[9] = _DRM_STAT_DMA;
79322eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie
794ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	dev_priv = drm_alloc(sizeof(drm_i915_private_t), DRM_MEM_DRIVER);
795ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	if (dev_priv == NULL)
796ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes		return -ENOMEM;
797ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
798ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	memset(dev_priv, 0, sizeof(drm_i915_private_t));
799ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
800ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	dev->dev_private = (void *)dev_priv;
801673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	dev_priv->dev = dev;
802ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
803ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	/* Add register map (needed for suspend/resume) */
804ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	base = drm_get_resource_start(dev, mmio_bar);
805ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	size = drm_get_resource_len(dev, mmio_bar);
806ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
807e3236a1173222ca209d20bb29f6c1cd3499aa845Dave Airlie	ret = drm_addmap(dev, base, size, _DRM_REGISTERS,
808e3236a1173222ca209d20bb29f6c1cd3499aa845Dave Airlie			 _DRM_KERNEL | _DRM_DRIVER,
809ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes			 &dev_priv->mmio_map);
810ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt
811673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	i915_gem_load(dev);
812673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt
813398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	/* Init HWS */
814398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	if (!I915_NEED_GFX_HWS(dev)) {
815398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard		ret = i915_init_phys_hws(dev);
816398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard		if (ret != 0)
817398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard			return ret;
818398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	}
819ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt
820ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt	/* On the 945G/GM, the chipset reports the MSI capability on the
821ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt	 * integrated graphics even though the support isn't actually there
822ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt	 * according to the published specs.  It doesn't appear to function
823ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt	 * correctly in testing on 945G.
824ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt	 * This may be a side effect of MSI having been made available for PEG
825ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt	 * and the registers being closely associated.
826ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt	 */
827ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt	if (!IS_I945G(dev) && !IS_I945GM(dev))
8280a3e67a4caac273a3bfc4ced3da364830b1ab241Jesse Barnes		if (pci_enable_msi(dev->pdev))
8290a3e67a4caac273a3bfc4ced3da364830b1ab241Jesse Barnes			DRM_ERROR("failed to enable MSI\n");
830ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt
8318ee1c3db9075cb3211352e737e0feb98fd733b20Matthew Garrett	intel_opregion_init(dev);
8328ee1c3db9075cb3211352e737e0feb98fd733b20Matthew Garrett
833ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt	spin_lock_init(&dev_priv->user_irq_lock);
834ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt
835ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	return ret;
836ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes}
837ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
838ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnesint i915_driver_unload(struct drm_device *dev)
839ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes{
840ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	struct drm_i915_private *dev_priv = dev->dev_private;
841ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
842ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt	if (dev->pdev->msi_enabled)
843ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt		pci_disable_msi(dev->pdev);
844ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt
845398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	i915_free_hws(dev);
846398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard
847ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	if (dev_priv->mmio_map)
848ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes		drm_rmmap(dev, dev_priv->mmio_map);
849ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
8508ee1c3db9075cb3211352e737e0feb98fd733b20Matthew Garrett	intel_opregion_free(dev);
8518ee1c3db9075cb3211352e737e0feb98fd733b20Matthew Garrett
852ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	drm_free(dev->dev_private, sizeof(drm_i915_private_t),
853ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes		 DRM_MEM_DRIVER);
854ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
85522eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie	return 0;
85622eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie}
85722eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie
858673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholtint i915_driver_open(struct drm_device *dev, struct drm_file *file_priv)
859673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt{
860673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	struct drm_i915_file_private *i915_file_priv;
861673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt
862673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	DRM_DEBUG("\n");
863673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	i915_file_priv = (struct drm_i915_file_private *)
864673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	    drm_alloc(sizeof(*i915_file_priv), DRM_MEM_FILES);
865673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt
866673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	if (!i915_file_priv)
867673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		return -ENOMEM;
868673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt
869673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	file_priv->driver_priv = i915_file_priv;
870673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt
871673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	i915_file_priv->mm.last_gem_seqno = 0;
872673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	i915_file_priv->mm.last_gem_throttle_seqno = 0;
873673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt
874673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	return 0;
875673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt}
876673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt
87784b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airlievoid i915_driver_lastclose(struct drm_device * dev)
8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
879ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	drm_i915_private_t *dev_priv = dev->dev_private;
880ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
881144a75fa1faa4a81530bded2e59872ef80d496b6Dave Airlie	if (!dev_priv)
882144a75fa1faa4a81530bded2e59872ef80d496b6Dave Airlie		return;
883144a75fa1faa4a81530bded2e59872ef80d496b6Dave Airlie
884673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	i915_gem_lastclose(dev);
885673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt
886ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	if (dev_priv->agp_heap)
887b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		i915_mem_takedown(&(dev_priv->agp_heap));
888ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
889b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	i915_dma_cleanup(dev);
8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8926c340eac0285f3d62406d2d902d0e96fbf2a5dc0Eric Anholtvoid i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv)
8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
894ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	drm_i915_private_t *dev_priv = dev->dev_private;
895ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	i915_mem_release(dev, file_priv, dev_priv->agp_heap);
8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
898673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholtvoid i915_driver_postclose(struct drm_device *dev, struct drm_file *file_priv)
899673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt{
900673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	struct drm_i915_file_private *i915_file_priv = file_priv->driver_priv;
901673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt
902673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	drm_free(i915_file_priv, sizeof(*i915_file_priv), DRM_MEM_FILES);
903673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt}
904673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt
905c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstruct drm_ioctl_desc i915_ioctls[] = {
906c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_INIT, i915_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
907c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_FLUSH, i915_flush_ioctl, DRM_AUTH),
908c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_FLIP, i915_flip_bufs, DRM_AUTH),
909c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_BATCHBUFFER, i915_batchbuffer, DRM_AUTH),
910c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_IRQ_EMIT, i915_irq_emit, DRM_AUTH),
911c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_IRQ_WAIT, i915_irq_wait, DRM_AUTH),
912c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_GETPARAM, i915_getparam, DRM_AUTH),
913c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_SETPARAM, i915_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
914c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_ALLOC, i915_mem_alloc, DRM_AUTH),
915c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_FREE, i915_mem_free, DRM_AUTH),
916c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_INIT_HEAP, i915_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
917c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_CMDBUFFER, i915_cmdbuffer, DRM_AUTH),
918c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_DESTROY_HEAP,  i915_mem_destroy_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY ),
919c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_SET_VBLANK_PIPE,  i915_vblank_pipe_set, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY ),
920c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_GET_VBLANK_PIPE,  i915_vblank_pipe_get, DRM_AUTH ),
921c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_VBLANK_SWAP, i915_vblank_swap, DRM_AUTH),
922c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_HWS_ADDR, i915_set_status_page, DRM_AUTH),
923673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	DRM_IOCTL_DEF(DRM_I915_GEM_INIT, i915_gem_init_ioctl, DRM_AUTH),
924673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	DRM_IOCTL_DEF(DRM_I915_GEM_EXECBUFFER, i915_gem_execbuffer, DRM_AUTH),
925673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	DRM_IOCTL_DEF(DRM_I915_GEM_PIN, i915_gem_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY),
926673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	DRM_IOCTL_DEF(DRM_I915_GEM_UNPIN, i915_gem_unpin_ioctl, DRM_AUTH|DRM_ROOT_ONLY),
927673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	DRM_IOCTL_DEF(DRM_I915_GEM_BUSY, i915_gem_busy_ioctl, DRM_AUTH),
928673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	DRM_IOCTL_DEF(DRM_I915_GEM_THROTTLE, i915_gem_throttle_ioctl, DRM_AUTH),
929673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	DRM_IOCTL_DEF(DRM_I915_GEM_ENTERVT, i915_gem_entervt_ioctl, DRM_AUTH),
930673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	DRM_IOCTL_DEF(DRM_I915_GEM_LEAVEVT, i915_gem_leavevt_ioctl, DRM_AUTH),
931673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	DRM_IOCTL_DEF(DRM_I915_GEM_CREATE, i915_gem_create_ioctl, 0),
932673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	DRM_IOCTL_DEF(DRM_I915_GEM_PREAD, i915_gem_pread_ioctl, 0),
933673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	DRM_IOCTL_DEF(DRM_I915_GEM_PWRITE, i915_gem_pwrite_ioctl, 0),
934673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	DRM_IOCTL_DEF(DRM_I915_GEM_MMAP, i915_gem_mmap_ioctl, 0),
935673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	DRM_IOCTL_DEF(DRM_I915_GEM_SET_DOMAIN, i915_gem_set_domain_ioctl, 0),
936673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	DRM_IOCTL_DEF(DRM_I915_GEM_SW_FINISH, i915_gem_sw_finish_ioctl, 0),
937673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	DRM_IOCTL_DEF(DRM_I915_GEM_SET_TILING, i915_gem_set_tiling, 0),
938673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	DRM_IOCTL_DEF(DRM_I915_GEM_GET_TILING, i915_gem_get_tiling, 0),
939c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie};
940c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie
941c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlieint i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
942cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie
943cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie/**
944cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie * Determine if the device really is AGP or not.
945cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie *
946cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie * All Intel graphics chipsets are treated as AGP, even if they are really
947cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie * PCI-e.
948cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie *
949cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie * \param dev   The device to be tested.
950cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie *
951cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie * \returns
952cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie * A value of 1 is always retured to indictate every i9x5 is AGP.
953cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie */
95484b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airlieint i915_driver_device_is_agp(struct drm_device * dev)
955cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie{
956cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie	return 1;
957cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie}
958