i915_dma.c revision 08d7b3d1edff84bd673d9e9ab36b5aa62e1ba903
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"
3179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes#include "drm_crtc_helper.h"
3279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes#include "intel_drv.h"
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "i915_drm.h"
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "i915_drv.h"
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Really want an OS-independent resettable timer.  Would like to have
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * this loop run for (eg) 3 sec, but have the timer reset every time
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the head pointer changes, so that EBUSY only happens if the ring
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * actually stalls for (eg) 3 seconds.
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
4184b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airlieint i915_wait_ring(struct drm_device * dev, int n, const char *caller)
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = dev->dev_private;
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
45d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard	u32 acthd_reg = IS_I965G(dev) ? ACTHD_I965 : ACTHD;
46d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard	u32 last_acthd = I915_READ(acthd_reg);
47d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard	u32 acthd;
48585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes	u32 last_head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
51d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard	for (i = 0; i < 100000; i++) {
52585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes		ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
53d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard		acthd = I915_READ(acthd_reg);
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ring->space = ring->head - (ring->tail + 8);
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ring->space < 0)
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ring->space += ring->Size;
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ring->space >= n)
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 0;
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6098787c057fdefdce6230ff46f2c1105835005a4cChris Wilson		if (dev->primary->master) {
6198787c057fdefdce6230ff46f2c1105835005a4cChris Wilson			struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
6298787c057fdefdce6230ff46f2c1105835005a4cChris Wilson			if (master_priv->sarea_priv)
6398787c057fdefdce6230ff46f2c1105835005a4cChris Wilson				master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
6498787c057fdefdce6230ff46f2c1105835005a4cChris Wilson		}
6598787c057fdefdce6230ff46f2c1105835005a4cChris Wilson
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ring->head != last_head)
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			i = 0;
69d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard		if (acthd != last_acthd)
70d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard			i = 0;
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		last_head = ring->head;
73d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard		last_acthd = acthd;
74d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard		msleep_interruptible(10);
75d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7820caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt	return -EBUSY;
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
81398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard/**
82398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard * Sets up the hardware status page for devices that need a physical address
83398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard * in the register.
84398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard */
853043c60c485ad694392d3f71bd7ef9f5c5f7cfddEric Anholtstatic int i915_init_phys_hws(struct drm_device *dev)
86398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard{
87398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	drm_i915_private_t *dev_priv = dev->dev_private;
88398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	/* Program Hardware Status Page */
89398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	dev_priv->status_page_dmah =
90398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard		drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff);
91398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard
92398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	if (!dev_priv->status_page_dmah) {
93398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard		DRM_ERROR("Can not allocate hardware status page\n");
94398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard		return -ENOMEM;
95398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	}
96398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr;
97398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
98398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard
99398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
100398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard
101398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	I915_WRITE(HWS_PGA, dev_priv->dma_status_page);
102398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	DRM_DEBUG("Enabled hardware status page\n");
103398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	return 0;
104398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard}
105398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard
106398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard/**
107398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard * Frees the hardware status page, whether it's a physical address or a virtual
108398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard * address set up by the X Server.
109398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard */
1103043c60c485ad694392d3f71bd7ef9f5c5f7cfddEric Anholtstatic void i915_free_hws(struct drm_device *dev)
111398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard{
112398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	drm_i915_private_t *dev_priv = dev->dev_private;
113398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	if (dev_priv->status_page_dmah) {
114398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard		drm_pci_free(dev, dev_priv->status_page_dmah);
115398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard		dev_priv->status_page_dmah = NULL;
116398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	}
117398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard
118398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	if (dev_priv->status_gfx_addr) {
119398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard		dev_priv->status_gfx_addr = 0;
120398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard		drm_core_ioremapfree(&dev_priv->hws_map, dev);
121398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	}
122398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard
123398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	/* Need to rewrite hardware status page */
124398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	I915_WRITE(HWS_PGA, 0x1ffff000);
125398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard}
126398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard
12784b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airlievoid i915_kernel_lost_context(struct drm_device * dev)
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = dev->dev_private;
1307c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	struct drm_i915_master_private *master_priv;
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	/*
13479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	 * We should never lose context on the ring with modesetting
13579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	 * as we don't expose it to userspace
13679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	 */
13779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	if (drm_core_check_feature(dev, DRIVER_MODESET))
13879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		return;
13979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
140585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes	ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
141585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes	ring->tail = I915_READ(PRB0_TAIL) & TAIL_ADDR;
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ring->space = ring->head - (ring->tail + 8);
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ring->space < 0)
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ring->space += ring->Size;
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1467c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	if (!dev->primary->master)
1477c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie		return;
1487c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
1497c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	master_priv = dev->primary->master->driver_priv;
1507c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	if (ring->head == ring->tail && master_priv->sarea_priv)
1517c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie		master_priv->sarea_priv->perf_boxes |= I915_BOX_RING_EMPTY;
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15484b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airliestatic int i915_dma_cleanup(struct drm_device * dev)
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
156ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	drm_i915_private_t *dev_priv = dev->dev_private;
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Make sure interrupts are disabled here because the uninstall ioctl
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * may not have been called from userspace and after dev_private
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * is freed, it's too late.
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
161ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt	if (dev->irq_enabled)
162b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		drm_irq_uninstall(dev);
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
164ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	if (dev_priv->ring.virtual_start) {
165ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes		drm_core_ioremapfree(&dev_priv->ring.map, dev);
1663043c60c485ad694392d3f71bd7ef9f5c5f7cfddEric Anholt		dev_priv->ring.virtual_start = NULL;
1673043c60c485ad694392d3f71bd7ef9f5c5f7cfddEric Anholt		dev_priv->ring.map.handle = NULL;
168ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes		dev_priv->ring.map.size = 0;
169ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	}
170dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu
171398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	/* Clear the HWS virtual address at teardown */
172398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	if (I915_NEED_GFX_HWS(dev))
173398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard		i915_free_hws(dev);
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
178ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnesstatic int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
180ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	drm_i915_private_t *dev_priv = dev->dev_private;
1817c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1833a03ac1a0223f779a3de313523408ddb099e5679Dave Airlie	master_priv->sarea = drm_getsarea(dev);
1843a03ac1a0223f779a3de313523408ddb099e5679Dave Airlie	if (master_priv->sarea) {
1853a03ac1a0223f779a3de313523408ddb099e5679Dave Airlie		master_priv->sarea_priv = (drm_i915_sarea_t *)
1863a03ac1a0223f779a3de313523408ddb099e5679Dave Airlie			((u8 *)master_priv->sarea->handle + init->sarea_priv_offset);
1873a03ac1a0223f779a3de313523408ddb099e5679Dave Airlie	} else {
1883a03ac1a0223f779a3de313523408ddb099e5679Dave Airlie		DRM_DEBUG("sarea not found assuming DRI2 userspace\n");
1893a03ac1a0223f779a3de313523408ddb099e5679Dave Airlie	}
1903a03ac1a0223f779a3de313523408ddb099e5679Dave Airlie
191673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	if (init->ring_size != 0) {
192673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		if (dev_priv->ring.ring_obj != NULL) {
193673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt			i915_dma_cleanup(dev);
194673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt			DRM_ERROR("Client tried to initialize ringbuffer in "
195673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt				  "GEM mode\n");
196673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt			return -EINVAL;
197673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		}
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
199673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		dev_priv->ring.Size = init->ring_size;
200673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
202673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		dev_priv->ring.map.offset = init->ring_start;
203673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		dev_priv->ring.map.size = init->ring_size;
204673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		dev_priv->ring.map.type = 0;
205673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		dev_priv->ring.map.flags = 0;
206673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		dev_priv->ring.map.mtrr = 0;
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2086fb88588555a18792a27f483887fe1f2af5f9c9bJesse Barnes		drm_core_ioremap_wc(&dev_priv->ring.map, dev);
209673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt
210673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		if (dev_priv->ring.map.handle == NULL) {
211673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt			i915_dma_cleanup(dev);
212673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt			DRM_ERROR("can not ioremap virtual address for"
213673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt				  " ring buffer\n");
214673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt			return -ENOMEM;
215673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		}
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
220a6b54f3f5050c0cbc0c35dd48064846c6302706bMichel Dänzer	dev_priv->cpp = init->cpp;
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_priv->back_offset = init->back_offset;
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_priv->front_offset = init->front_offset;
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_priv->current_page = 0;
2247c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	if (master_priv->sarea_priv)
2257c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie		master_priv->sarea_priv->pf_current_page = 0;
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Allow hardware batchbuffers unless told otherwise.
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_priv->allow_batchbuffer = 1;
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23484b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airliestatic int i915_dma_resume(struct drm_device * dev)
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
238bf9d89295233ae2ba7b312c78ee5657307b09f4cHarvey Harrison	DRM_DEBUG("%s\n", __func__);
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (dev_priv->ring.map.handle == NULL) {
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("can not ioremap virtual address for"
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			  " ring buffer\n");
24320caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -ENOMEM;
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Program Hardware Status Page */
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!dev_priv->hw_status_page) {
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("Can not find hardware status page\n");
24920caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
253dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	if (dev_priv->status_gfx_addr != 0)
254585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes		I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
255dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	else
256585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes		I915_WRITE(HWS_PGA, dev_priv->dma_status_page);
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DRM_DEBUG("Enabled hardware status page\n");
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
262c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_dma_init(struct drm_device *dev, void *data,
263c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt			 struct drm_file *file_priv)
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
265c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	drm_i915_init_t *init = data;
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int retcode = 0;
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
268c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	switch (init->func) {
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case I915_INIT_DMA:
270ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes		retcode = i915_initialize(dev, init);
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case I915_CLEANUP_DMA:
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		retcode = i915_dma_cleanup(dev);
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case I915_RESUME_DMA:
2760d6aa60b4ac9689b750e35cd66f5d7c053aff0f4Dave Airlie		retcode = i915_dma_resume(dev);
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
27920caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		retcode = -EINVAL;
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return retcode;
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Implement basically the same security restrictions as hardware does
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * for MI_BATCH_NON_SECURE.  These can be made stricter at any time.
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Most of the calculations below involve calculating the size of a
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * particular instruction.  It's important to get the size right as
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * that tells us where the next instruction to check is.  Any illegal
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * instruction detected will be given a size of zero, which is a
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * signal to abort the rest of the buffer.
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int do_validate_cmd(int cmd)
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (((cmd >> 29) & 0x7)) {
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 0x0:
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch ((cmd >> 23) & 0x3f) {
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x0:
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 1;	/* MI_NOOP */
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x4:
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 1;	/* MI_FLUSH */
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		default:
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 0;	/* disallow everything else */
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 0x1:
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;	/* reserved */
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 0x2:
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (cmd & 0xff) + 2;	/* 2d commands */
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 0x3:
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (((cmd >> 24) & 0x1f) <= 0x18)
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 1;
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch ((cmd >> 24) & 0x1f) {
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x1c:
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 1;
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x1d:
320b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			switch ((cmd >> 16) & 0xff) {
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case 0x3:
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return (cmd & 0x1f) + 2;
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case 0x4:
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return (cmd & 0xf) + 2;
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			default:
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return (cmd & 0xffff) + 2;
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x1e:
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (cmd & (1 << 23))
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return (cmd & 0xffff) + 1;
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return 1;
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x1f:
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if ((cmd & (1 << 23)) == 0)	/* inline vertices */
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return (cmd & 0x1ffff) + 2;
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else if (cmd & (1 << 17))	/* indirect random */
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if ((cmd & 0xffff) == 0)
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					return 0;	/* unknown length, too hard */
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				else
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					return (((cmd & 0xffff) + 1) / 2) + 1;
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return 2;	/* indirect sequential */
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		default:
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 0;
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int validate_cmd(int cmd)
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret = do_validate_cmd(cmd);
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
357bc5f4523f772cc7629c5c5a46cf4f2a07a5500b8Dave Airlie/*	printk("validate_cmd( %x ): %d\n", cmd, ret); */
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
362201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholtstatic int i915_emit_cmds(struct drm_device * dev, int *buffer, int dwords)
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = dev->dev_private;
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	RING_LOCALS;
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
368de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	if ((dwords+1) * sizeof(int) >= dev_priv->ring.Size - 8)
36920caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
370de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie
371c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane	BEGIN_LP_RING((dwords+1)&~1);
372de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < dwords;) {
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		int cmd, sz;
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
376201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt		cmd = buffer[i];
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((sz = validate_cmd(cmd)) == 0 || i + sz > dwords)
37920caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt			return -EINVAL;
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		OUT_RING(cmd);
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		while (++i, --sz) {
384201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt			OUT_RING(buffer[i]);
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
388de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	if (dwords & 1)
389de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie		OUT_RING(0);
390de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie
391de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	ADVANCE_LP_RING();
392de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
396673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholtint
397673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholti915_emit_box(struct drm_device *dev,
398201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt	      struct drm_clip_rect *boxes,
399673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	      int i, int DR1, int DR4)
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = dev->dev_private;
402201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt	struct drm_clip_rect box = boxes[i];
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	RING_LOCALS;
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (box.y2 <= box.y1 || box.x2 <= box.x1 || box.y2 <= 0 || box.x2 <= 0) {
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("Bad box %d,%d..%d,%d\n",
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			  box.x1, box.y1, box.x2, box.y2);
40820caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
411c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane	if (IS_I965G(dev)) {
412c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		BEGIN_LP_RING(4);
413c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		OUT_RING(GFX_OP_DRAWRECT_INFO_I965);
414c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		OUT_RING((box.x1 & 0xffff) | (box.y1 << 16));
41578eca43d0391f59c3b1505bb7bd38ff45b650aabAndrew Morton		OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16));
416c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		OUT_RING(DR4);
417c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		ADVANCE_LP_RING();
418c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane	} else {
419c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		BEGIN_LP_RING(6);
420c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		OUT_RING(GFX_OP_DRAWRECT_INFO);
421c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		OUT_RING(DR1);
422c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		OUT_RING((box.x1 & 0xffff) | (box.y1 << 16));
423c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16));
424c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		OUT_RING(DR4);
425c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		OUT_RING(0);
426c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		ADVANCE_LP_RING();
427c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane	}
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
432c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane/* XXX: Emitting the counter should really be moved to part of the IRQ
433c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane * emit. For now, do it in both places:
434c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane */
435c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane
43684b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airliestatic void i915_emit_breadcrumb(struct drm_device *dev)
437de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie{
438de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	drm_i915_private_t *dev_priv = dev->dev_private;
4397c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
440de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	RING_LOCALS;
441de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie
442c99b058f132388a666544d293392d52d1def6b12Kristian Høgsberg	dev_priv->counter++;
443af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	if (dev_priv->counter > 0x7FFFFFFFUL)
444c99b058f132388a666544d293392d52d1def6b12Kristian Høgsberg		dev_priv->counter = 0;
4457c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	if (master_priv->sarea_priv)
4467c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie		master_priv->sarea_priv->last_enqueue = dev_priv->counter;
447de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie
448de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	BEGIN_LP_RING(4);
449585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes	OUT_RING(MI_STORE_DWORD_INDEX);
4500baf823a10bd4131f70e9712d1f02de3c247f1dfKeith Packard	OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
451de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	OUT_RING(dev_priv->counter);
452de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	OUT_RING(0);
453de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	ADVANCE_LP_RING();
454de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie}
455de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie
45684b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airliestatic int i915_dispatch_cmdbuffer(struct drm_device * dev,
457201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt				   drm_i915_cmdbuffer_t *cmd,
458201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt				   struct drm_clip_rect *cliprects,
459201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt				   void *cmdbuf)
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int nbox = cmd->num_cliprects;
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i = 0, count, ret;
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (cmd->sz & 0x3) {
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("alignment");
46620caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	i915_kernel_lost_context(dev);
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	count = nbox ? nbox : 1;
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < count; i++) {
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (i < nbox) {
475201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt			ret = i915_emit_box(dev, cliprects, i,
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					    cmd->DR1, cmd->DR4);
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (ret)
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return ret;
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
481201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt		ret = i915_emit_cmds(dev, cmdbuf, cmd->sz / 4);
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ret)
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return ret;
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
486de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	i915_emit_breadcrumb(dev);
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
49084b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airliestatic int i915_dispatch_batchbuffer(struct drm_device * dev,
491201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt				     drm_i915_batchbuffer_t * batch,
492201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt				     struct drm_clip_rect *cliprects)
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = dev->dev_private;
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int nbox = batch->num_cliprects;
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i = 0, count;
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	RING_LOCALS;
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((batch->start | batch->used) & 0x7) {
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("alignment");
50120caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	i915_kernel_lost_context(dev);
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	count = nbox ? nbox : 1;
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < count; i++) {
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (i < nbox) {
510201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt			int ret = i915_emit_box(dev, cliprects, i,
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						batch->DR1, batch->DR4);
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (ret)
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return ret;
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5160790d5e148c0747499742a3c09ba5f1c07f9ed0dKeith Packard		if (!IS_I830(dev) && !IS_845G(dev)) {
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			BEGIN_LP_RING(2);
51821f16289270447673a7263ccc0b22d562fb01ecbDave Airlie			if (IS_I965G(dev)) {
51921f16289270447673a7263ccc0b22d562fb01ecbDave Airlie				OUT_RING(MI_BATCH_BUFFER_START | (2 << 6) | MI_BATCH_NON_SECURE_I965);
52021f16289270447673a7263ccc0b22d562fb01ecbDave Airlie				OUT_RING(batch->start);
52121f16289270447673a7263ccc0b22d562fb01ecbDave Airlie			} else {
52221f16289270447673a7263ccc0b22d562fb01ecbDave Airlie				OUT_RING(MI_BATCH_BUFFER_START | (2 << 6));
52321f16289270447673a7263ccc0b22d562fb01ecbDave Airlie				OUT_RING(batch->start | MI_BATCH_NON_SECURE);
52421f16289270447673a7263ccc0b22d562fb01ecbDave Airlie			}
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ADVANCE_LP_RING();
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			BEGIN_LP_RING(4);
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			OUT_RING(MI_BATCH_BUFFER);
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			OUT_RING(batch->start | MI_BATCH_NON_SECURE);
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			OUT_RING(batch->start + batch->used - 4);
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			OUT_RING(0);
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ADVANCE_LP_RING();
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
536de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	i915_emit_breadcrumb(dev);
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
541af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airliestatic int i915_dispatch_flip(struct drm_device * dev)
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = dev->dev_private;
5447c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	struct drm_i915_master_private *master_priv =
5457c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie		dev->primary->master->driver_priv;
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	RING_LOCALS;
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5487c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	if (!master_priv->sarea_priv)
549c99b058f132388a666544d293392d52d1def6b12Kristian Høgsberg		return -EINVAL;
550c99b058f132388a666544d293392d52d1def6b12Kristian Høgsberg
551af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
55280a914dc05683ecfc98f9e1887fd6564846ffbecHarvey Harrison		  __func__,
553af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie		  dev_priv->current_page,
5547c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie		  master_priv->sarea_priv->pf_current_page);
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
556af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	i915_kernel_lost_context(dev);
557af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie
558af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	BEGIN_LP_RING(2);
559585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes	OUT_RING(MI_FLUSH | MI_READ_FLUSH);
560af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	OUT_RING(0);
561af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	ADVANCE_LP_RING();
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
563af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	BEGIN_LP_RING(6);
564af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP);
565af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	OUT_RING(0);
566af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	if (dev_priv->current_page == 0) {
567af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie		OUT_RING(dev_priv->back_offset);
568af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie		dev_priv->current_page = 1;
5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
570af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie		OUT_RING(dev_priv->front_offset);
571af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie		dev_priv->current_page = 0;
5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
573af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	OUT_RING(0);
574af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	ADVANCE_LP_RING();
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
576af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	BEGIN_LP_RING(2);
577af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP);
578af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	OUT_RING(0);
579af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	ADVANCE_LP_RING();
5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5817c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	master_priv->sarea_priv->last_enqueue = dev_priv->counter++;
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	BEGIN_LP_RING(4);
584585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes	OUT_RING(MI_STORE_DWORD_INDEX);
5850baf823a10bd4131f70e9712d1f02de3c247f1dfKeith Packard	OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
586af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	OUT_RING(dev_priv->counter);
587af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	OUT_RING(0);
5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ADVANCE_LP_RING();
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5907c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	master_priv->sarea_priv->pf_current_page = dev_priv->current_page;
591af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	return 0;
5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
59484b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airliestatic int i915_quiescent(struct drm_device * dev)
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = dev->dev_private;
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	i915_kernel_lost_context(dev);
599bf9d89295233ae2ba7b312c78ee5657307b09f4cHarvey Harrison	return i915_wait_ring(dev, dev_priv->ring.Size - 8, __func__);
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
602c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_flush_ioctl(struct drm_device *dev, void *data,
603c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt			    struct drm_file *file_priv)
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
605546b0974c39657017407c86fe79811100b60700dEric Anholt	int ret;
606546b0974c39657017407c86fe79811100b60700dEric Anholt
607546b0974c39657017407c86fe79811100b60700dEric Anholt	RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
609546b0974c39657017407c86fe79811100b60700dEric Anholt	mutex_lock(&dev->struct_mutex);
610546b0974c39657017407c86fe79811100b60700dEric Anholt	ret = i915_quiescent(dev);
611546b0974c39657017407c86fe79811100b60700dEric Anholt	mutex_unlock(&dev->struct_mutex);
612546b0974c39657017407c86fe79811100b60700dEric Anholt
613546b0974c39657017407c86fe79811100b60700dEric Anholt	return ret;
6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
616c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_batchbuffer(struct drm_device *dev, void *data,
617c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt			    struct drm_file *file_priv)
6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
6207c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
6227c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	    master_priv->sarea_priv;
623c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	drm_i915_batchbuffer_t *batch = data;
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret;
625201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt	struct drm_clip_rect *cliprects = NULL;
6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!dev_priv->allow_batchbuffer) {
6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("Batchbuffer ioctl disabled\n");
62920caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DRM_DEBUG("i915 batchbuffer, start %x used %d cliprects %d\n",
633c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt		  batch->start, batch->used, batch->num_cliprects);
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
635546b0974c39657017407c86fe79811100b60700dEric Anholt	RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
637201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt	if (batch->num_cliprects < 0)
638201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt		return -EINVAL;
639201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt
640201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt	if (batch->num_cliprects) {
641201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt		cliprects = drm_calloc(batch->num_cliprects,
642201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt				       sizeof(struct drm_clip_rect),
643201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt				       DRM_MEM_DRIVER);
644201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt		if (cliprects == NULL)
645201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt			return -ENOMEM;
646201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt
647201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt		ret = copy_from_user(cliprects, batch->cliprects,
648201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt				     batch->num_cliprects *
649201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt				     sizeof(struct drm_clip_rect));
650201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt		if (ret != 0)
651201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt			goto fail_free;
652201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt	}
6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
654546b0974c39657017407c86fe79811100b60700dEric Anholt	mutex_lock(&dev->struct_mutex);
655201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt	ret = i915_dispatch_batchbuffer(dev, batch, cliprects);
656546b0974c39657017407c86fe79811100b60700dEric Anholt	mutex_unlock(&dev->struct_mutex);
6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
658c99b058f132388a666544d293392d52d1def6b12Kristian Høgsberg	if (sarea_priv)
6590baf823a10bd4131f70e9712d1f02de3c247f1dfKeith Packard		sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
660201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt
661201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholtfail_free:
662201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt	drm_free(cliprects,
663201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt		 batch->num_cliprects * sizeof(struct drm_clip_rect),
664201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt		 DRM_MEM_DRIVER);
665201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt
6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
669c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_cmdbuffer(struct drm_device *dev, void *data,
670c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt			  struct drm_file *file_priv)
6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
6737c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
6757c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	    master_priv->sarea_priv;
676c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	drm_i915_cmdbuffer_t *cmdbuf = data;
677201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt	struct drm_clip_rect *cliprects = NULL;
678201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt	void *batch_data;
6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret;
6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DRM_DEBUG("i915 cmdbuffer, buf %p sz %d cliprects %d\n",
682c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt		  cmdbuf->buf, cmdbuf->sz, cmdbuf->num_cliprects);
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
684546b0974c39657017407c86fe79811100b60700dEric Anholt	RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
686201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt	if (cmdbuf->num_cliprects < 0)
687201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt		return -EINVAL;
688201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt
689201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt	batch_data = drm_alloc(cmdbuf->sz, DRM_MEM_DRIVER);
690201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt	if (batch_data == NULL)
691201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt		return -ENOMEM;
692201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt
693201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt	ret = copy_from_user(batch_data, cmdbuf->buf, cmdbuf->sz);
694201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt	if (ret != 0)
695201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt		goto fail_batch_free;
696201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt
697201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt	if (cmdbuf->num_cliprects) {
698201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt		cliprects = drm_calloc(cmdbuf->num_cliprects,
699201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt				       sizeof(struct drm_clip_rect),
700201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt				       DRM_MEM_DRIVER);
701201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt		if (cliprects == NULL)
702201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt			goto fail_batch_free;
703201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt
704201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt		ret = copy_from_user(cliprects, cmdbuf->cliprects,
705201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt				     cmdbuf->num_cliprects *
706201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt				     sizeof(struct drm_clip_rect));
707201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt		if (ret != 0)
708201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt			goto fail_clip_free;
7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
711546b0974c39657017407c86fe79811100b60700dEric Anholt	mutex_lock(&dev->struct_mutex);
712201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt	ret = i915_dispatch_cmdbuffer(dev, cmdbuf, cliprects, batch_data);
713546b0974c39657017407c86fe79811100b60700dEric Anholt	mutex_unlock(&dev->struct_mutex);
7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ret) {
7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("i915_dispatch_cmdbuffer failed\n");
716355d7f370b51bbb6f31aaf9f98861057e1e6bbb2Chris Wright		goto fail_clip_free;
7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
719c99b058f132388a666544d293392d52d1def6b12Kristian Høgsberg	if (sarea_priv)
7200baf823a10bd4131f70e9712d1f02de3c247f1dfKeith Packard		sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
721201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt
722201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholtfail_clip_free:
723201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt	drm_free(cliprects,
724201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt		 cmdbuf->num_cliprects * sizeof(struct drm_clip_rect),
725201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt		 DRM_MEM_DRIVER);
726355d7f370b51bbb6f31aaf9f98861057e1e6bbb2Chris Wrightfail_batch_free:
727355d7f370b51bbb6f31aaf9f98861057e1e6bbb2Chris Wright	drm_free(batch_data, cmdbuf->sz, DRM_MEM_DRIVER);
728201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt
729201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt	return ret;
7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
732c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_flip_bufs(struct drm_device *dev, void *data,
733c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt			  struct drm_file *file_priv)
7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
735546b0974c39657017407c86fe79811100b60700dEric Anholt	int ret;
736546b0974c39657017407c86fe79811100b60700dEric Anholt
73780a914dc05683ecfc98f9e1887fd6564846ffbecHarvey Harrison	DRM_DEBUG("%s\n", __func__);
7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
739546b0974c39657017407c86fe79811100b60700dEric Anholt	RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
741546b0974c39657017407c86fe79811100b60700dEric Anholt	mutex_lock(&dev->struct_mutex);
742546b0974c39657017407c86fe79811100b60700dEric Anholt	ret = i915_dispatch_flip(dev);
743546b0974c39657017407c86fe79811100b60700dEric Anholt	mutex_unlock(&dev->struct_mutex);
744546b0974c39657017407c86fe79811100b60700dEric Anholt
745546b0974c39657017407c86fe79811100b60700dEric Anholt	return ret;
7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
748c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_getparam(struct drm_device *dev, void *data,
749c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt			 struct drm_file *file_priv)
7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = dev->dev_private;
752c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	drm_i915_getparam_t *param = data;
7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int value;
7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!dev_priv) {
7563e684eae586a9b210a4517da5637a255b1ff5a92Márton Németh		DRM_ERROR("called with no initialization\n");
75720caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
760c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	switch (param->param) {
7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case I915_PARAM_IRQ_ACTIVE:
7620a3e67a4caac273a3bfc4ced3da364830b1ab241Jesse Barnes		value = dev->pdev->irq ? 1 : 0;
7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case I915_PARAM_ALLOW_BATCHBUFFER:
7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		value = dev_priv->allow_batchbuffer ? 1 : 0;
7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
7670d6aa60b4ac9689b750e35cd66f5d7c053aff0f4Dave Airlie	case I915_PARAM_LAST_DISPATCH:
7680d6aa60b4ac9689b750e35cd66f5d7c053aff0f4Dave Airlie		value = READ_BREADCRUMB(dev_priv);
7690d6aa60b4ac9689b750e35cd66f5d7c053aff0f4Dave Airlie		break;
770ed4c9c4acf948b42b138747fcb8843ecb1a24ce4Kristian Høgsberg	case I915_PARAM_CHIPSET_ID:
771ed4c9c4acf948b42b138747fcb8843ecb1a24ce4Kristian Høgsberg		value = dev->pci_device;
772ed4c9c4acf948b42b138747fcb8843ecb1a24ce4Kristian Høgsberg		break;
773673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	case I915_PARAM_HAS_GEM:
774ac5c4e76180a74c7f922f6fa71ace0cef45fa433Dave Airlie		value = dev_priv->has_gem;
775673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		break;
7760f973f27888e4664b253ab2cf69c67c2eb80ab1bJesse Barnes	case I915_PARAM_NUM_FENCES_AVAIL:
7770f973f27888e4664b253ab2cf69c67c2eb80ab1bJesse Barnes		value = dev_priv->num_fence_regs - dev_priv->fence_reg_start;
7780f973f27888e4664b253ab2cf69c67c2eb80ab1bJesse Barnes		break;
7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
780122ee2a63bc49d21f402f6b6d2208306cdcc98c1Eric Anholt		DRM_DEBUG("Unknown parameter %d\n", param->param);
78120caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
784c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) {
7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("DRM_COPY_TO_USER failed\n");
78620caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EFAULT;
7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
792c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_setparam(struct drm_device *dev, void *data,
793c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt			 struct drm_file *file_priv)
7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = dev->dev_private;
796c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	drm_i915_setparam_t *param = data;
7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!dev_priv) {
7993e684eae586a9b210a4517da5637a255b1ff5a92Márton Németh		DRM_ERROR("called with no initialization\n");
80020caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
803c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	switch (param->param) {
8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case I915_SETPARAM_USE_MI_BATCHBUFFER_START:
8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case I915_SETPARAM_TEX_LRU_LOG_GRANULARITY:
807c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt		dev_priv->tex_lru_log_granularity = param->value;
8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case I915_SETPARAM_ALLOW_BATCHBUFFER:
810c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt		dev_priv->allow_batchbuffer = param->value;
8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
8120f973f27888e4664b253ab2cf69c67c2eb80ab1bJesse Barnes	case I915_SETPARAM_NUM_USED_FENCES:
8130f973f27888e4664b253ab2cf69c67c2eb80ab1bJesse Barnes		if (param->value > dev_priv->num_fence_regs ||
8140f973f27888e4664b253ab2cf69c67c2eb80ab1bJesse Barnes		    param->value < 0)
8150f973f27888e4664b253ab2cf69c67c2eb80ab1bJesse Barnes			return -EINVAL;
8160f973f27888e4664b253ab2cf69c67c2eb80ab1bJesse Barnes		/* Userspace can use first N regs */
8170f973f27888e4664b253ab2cf69c67c2eb80ab1bJesse Barnes		dev_priv->fence_reg_start = param->value;
8180f973f27888e4664b253ab2cf69c67c2eb80ab1bJesse Barnes		break;
8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
820122ee2a63bc49d21f402f6b6d2208306cdcc98c1Eric Anholt		DRM_DEBUG("unknown parameter %d\n", param->param);
82120caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
827c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_set_status_page(struct drm_device *dev, void *data,
828c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt				struct drm_file *file_priv)
829dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu{
830dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	drm_i915_private_t *dev_priv = dev->dev_private;
831c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	drm_i915_hws_addr_t *hws = data;
832b39d50e53b1bb27f6c29f88a697a4af78427dffdZhenyu Wang
833b39d50e53b1bb27f6c29f88a697a4af78427dffdZhenyu Wang	if (!I915_NEED_GFX_HWS(dev))
834b39d50e53b1bb27f6c29f88a697a4af78427dffdZhenyu Wang		return -EINVAL;
835dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu
836dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	if (!dev_priv) {
8373e684eae586a9b210a4517da5637a255b1ff5a92Márton Németh		DRM_ERROR("called with no initialization\n");
83820caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
839dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	}
840dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu
84179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
84279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		WARN(1, "tried to set status page when mode setting active\n");
84379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		return 0;
84479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	}
84579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
846c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	printk(KERN_DEBUG "set status page addr 0x%08x\n", (u32)hws->addr);
847c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt
848c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	dev_priv->status_gfx_addr = hws->addr & (0x1ffff<<12);
849dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu
8508b40958032fd236194de57d29be9cf2c1f2643eeEric Anholt	dev_priv->hws_map.offset = dev->agp->base + hws->addr;
851dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	dev_priv->hws_map.size = 4*1024;
852dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	dev_priv->hws_map.type = 0;
853dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	dev_priv->hws_map.flags = 0;
854dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	dev_priv->hws_map.mtrr = 0;
855dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu
856dd0910b3c71b253c08111110f0399b924a8d5853Dave Airlie	drm_core_ioremap_wc(&dev_priv->hws_map, dev);
857dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	if (dev_priv->hws_map.handle == NULL) {
858dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu		i915_dma_cleanup(dev);
859dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu		dev_priv->status_gfx_addr = 0;
860dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu		DRM_ERROR("can not ioremap virtual address for"
861dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu				" G33 hw status page\n");
86220caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -ENOMEM;
863dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	}
864dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	dev_priv->hw_status_page = dev_priv->hws_map.handle;
865dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu
866dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
867585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes	I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
868585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes	DRM_DEBUG("load hws HWS_PGA with gfx mem 0x%x\n",
869dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu			dev_priv->status_gfx_addr);
870dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	DRM_DEBUG("load hws at %p\n", dev_priv->hw_status_page);
871dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	return 0;
872dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu}
873dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu
87479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes/**
87579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * i915_probe_agp - get AGP bootup configuration
87679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * @pdev: PCI device
87779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * @aperture_size: returns AGP aperture configured size
87879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * @preallocated_size: returns size of BIOS preallocated AGP space
87979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes *
88079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * Since Intel integrated graphics are UMA, the BIOS has to set aside
88179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * some RAM for the framebuffer at early boot.  This code figures out
88279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * how much was set aside so we can use it for our own purposes.
88379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes */
884b358d0a6252d8ed16afb20caaec35b24c76074bbHannes Ederstatic int i915_probe_agp(struct drm_device *dev, unsigned long *aperture_size,
885b358d0a6252d8ed16afb20caaec35b24c76074bbHannes Eder			  unsigned long *preallocated_size)
88679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes{
88779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	struct pci_dev *bridge_dev;
88879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	u16 tmp = 0;
88979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	unsigned long overhead;
890241fa85b2bb655224357d713c251077dee3585ceEric Anholt	unsigned long stolen;
89179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
89279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
89379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	if (!bridge_dev) {
89479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		DRM_ERROR("bridge device not found\n");
89579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		return -1;
89679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	}
89779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
89879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	/* Get the fb aperture size and "stolen" memory amount. */
89979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	pci_read_config_word(bridge_dev, INTEL_GMCH_CTRL, &tmp);
90079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	pci_dev_put(bridge_dev);
90179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
90279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	*aperture_size = 1024 * 1024;
90379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	*preallocated_size = 1024 * 1024;
90479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
90560fd99e3682c5acc74d58ed61dac93526d6976f7Eric Anholt	switch (dev->pdev->device) {
90679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	case PCI_DEVICE_ID_INTEL_82830_CGC:
90779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	case PCI_DEVICE_ID_INTEL_82845G_IG:
90879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	case PCI_DEVICE_ID_INTEL_82855GM_IG:
90979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	case PCI_DEVICE_ID_INTEL_82865_IG:
91079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		if ((tmp & INTEL_GMCH_MEM_MASK) == INTEL_GMCH_MEM_64M)
91179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes			*aperture_size *= 64;
91279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		else
91379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes			*aperture_size *= 128;
91479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		break;
91579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	default:
91679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		/* 9xx supports large sizes, just look at the length */
91760fd99e3682c5acc74d58ed61dac93526d6976f7Eric Anholt		*aperture_size = pci_resource_len(dev->pdev, 2);
91879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		break;
91979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	}
92079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
92179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	/*
92279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	 * Some of the preallocated space is taken by the GTT
92379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	 * and popup.  GTT is 1K per MB of aperture size, and popup is 4K.
92479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	 */
9254a8df45894d26dc503013ea630927731c24be6b8Shaohua Li	if (IS_G4X(dev) || IS_IGD(dev))
92660fd99e3682c5acc74d58ed61dac93526d6976f7Eric Anholt		overhead = 4096;
92760fd99e3682c5acc74d58ed61dac93526d6976f7Eric Anholt	else
92860fd99e3682c5acc74d58ed61dac93526d6976f7Eric Anholt		overhead = (*aperture_size / 1024) + 4096;
92960fd99e3682c5acc74d58ed61dac93526d6976f7Eric Anholt
930241fa85b2bb655224357d713c251077dee3585ceEric Anholt	switch (tmp & INTEL_GMCH_GMS_MASK) {
931241fa85b2bb655224357d713c251077dee3585ceEric Anholt	case INTEL_855_GMCH_GMS_DISABLED:
932241fa85b2bb655224357d713c251077dee3585ceEric Anholt		DRM_ERROR("video memory is disabled\n");
933241fa85b2bb655224357d713c251077dee3585ceEric Anholt		return -1;
93479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	case INTEL_855_GMCH_GMS_STOLEN_1M:
935241fa85b2bb655224357d713c251077dee3585ceEric Anholt		stolen = 1 * 1024 * 1024;
936241fa85b2bb655224357d713c251077dee3585ceEric Anholt		break;
93779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	case INTEL_855_GMCH_GMS_STOLEN_4M:
938241fa85b2bb655224357d713c251077dee3585ceEric Anholt		stolen = 4 * 1024 * 1024;
93979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		break;
94079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	case INTEL_855_GMCH_GMS_STOLEN_8M:
941241fa85b2bb655224357d713c251077dee3585ceEric Anholt		stolen = 8 * 1024 * 1024;
94279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		break;
94379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	case INTEL_855_GMCH_GMS_STOLEN_16M:
944241fa85b2bb655224357d713c251077dee3585ceEric Anholt		stolen = 16 * 1024 * 1024;
94579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		break;
94679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	case INTEL_855_GMCH_GMS_STOLEN_32M:
947241fa85b2bb655224357d713c251077dee3585ceEric Anholt		stolen = 32 * 1024 * 1024;
94879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		break;
94979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	case INTEL_915G_GMCH_GMS_STOLEN_48M:
950241fa85b2bb655224357d713c251077dee3585ceEric Anholt		stolen = 48 * 1024 * 1024;
95179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		break;
95279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	case INTEL_915G_GMCH_GMS_STOLEN_64M:
953241fa85b2bb655224357d713c251077dee3585ceEric Anholt		stolen = 64 * 1024 * 1024;
954241fa85b2bb655224357d713c251077dee3585ceEric Anholt		break;
955241fa85b2bb655224357d713c251077dee3585ceEric Anholt	case INTEL_GMCH_GMS_STOLEN_128M:
956241fa85b2bb655224357d713c251077dee3585ceEric Anholt		stolen = 128 * 1024 * 1024;
957241fa85b2bb655224357d713c251077dee3585ceEric Anholt		break;
958241fa85b2bb655224357d713c251077dee3585ceEric Anholt	case INTEL_GMCH_GMS_STOLEN_256M:
959241fa85b2bb655224357d713c251077dee3585ceEric Anholt		stolen = 256 * 1024 * 1024;
960241fa85b2bb655224357d713c251077dee3585ceEric Anholt		break;
961241fa85b2bb655224357d713c251077dee3585ceEric Anholt	case INTEL_GMCH_GMS_STOLEN_96M:
962241fa85b2bb655224357d713c251077dee3585ceEric Anholt		stolen = 96 * 1024 * 1024;
963241fa85b2bb655224357d713c251077dee3585ceEric Anholt		break;
964241fa85b2bb655224357d713c251077dee3585ceEric Anholt	case INTEL_GMCH_GMS_STOLEN_160M:
965241fa85b2bb655224357d713c251077dee3585ceEric Anholt		stolen = 160 * 1024 * 1024;
966241fa85b2bb655224357d713c251077dee3585ceEric Anholt		break;
967241fa85b2bb655224357d713c251077dee3585ceEric Anholt	case INTEL_GMCH_GMS_STOLEN_224M:
968241fa85b2bb655224357d713c251077dee3585ceEric Anholt		stolen = 224 * 1024 * 1024;
969241fa85b2bb655224357d713c251077dee3585ceEric Anholt		break;
970241fa85b2bb655224357d713c251077dee3585ceEric Anholt	case INTEL_GMCH_GMS_STOLEN_352M:
971241fa85b2bb655224357d713c251077dee3585ceEric Anholt		stolen = 352 * 1024 * 1024;
97279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		break;
97379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	default:
97479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		DRM_ERROR("unexpected GMCH_GMS value: 0x%02x\n",
975241fa85b2bb655224357d713c251077dee3585ceEric Anholt			tmp & INTEL_GMCH_GMS_MASK);
97679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		return -1;
97779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	}
978241fa85b2bb655224357d713c251077dee3585ceEric Anholt	*preallocated_size = stolen - overhead;
97979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
98079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	return 0;
98179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes}
98279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
98379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnesstatic int i915_load_modeset_init(struct drm_device *dev)
98479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes{
98579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	struct drm_i915_private *dev_priv = dev->dev_private;
98679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	unsigned long agp_size, prealloc_size;
98779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	int fb_bar = IS_I9XX(dev) ? 2 : 0;
98879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	int ret = 0;
98979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
990aa5966296675a5092505f68d72563d5939a92353Dave Airlie	dev->devname = kstrdup(DRIVER_NAME, GFP_KERNEL);
991aa5966296675a5092505f68d72563d5939a92353Dave Airlie	if (!dev->devname) {
992aa5966296675a5092505f68d72563d5939a92353Dave Airlie		ret = -ENOMEM;
993aa5966296675a5092505f68d72563d5939a92353Dave Airlie		goto out;
994aa5966296675a5092505f68d72563d5939a92353Dave Airlie	}
995aa5966296675a5092505f68d72563d5939a92353Dave Airlie
99679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	dev->mode_config.fb_base = drm_get_resource_start(dev, fb_bar) &
99779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		0xff000000;
99879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
9992906f0258770d3a9c4e65364df8acc904e148bbeJesse Barnes	if (IS_MOBILE(dev) || IS_I9XX(dev))
100079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		dev_priv->cursor_needs_physical = true;
100179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	else
100279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		dev_priv->cursor_needs_physical = false;
100379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
10042906f0258770d3a9c4e65364df8acc904e148bbeJesse Barnes	if (IS_I965G(dev) || IS_G33(dev))
10052906f0258770d3a9c4e65364df8acc904e148bbeJesse Barnes		dev_priv->cursor_needs_physical = false;
10062906f0258770d3a9c4e65364df8acc904e148bbeJesse Barnes
1007aa5966296675a5092505f68d72563d5939a92353Dave Airlie	ret = i915_probe_agp(dev, &agp_size, &prealloc_size);
1008aa5966296675a5092505f68d72563d5939a92353Dave Airlie	if (ret)
1009aa5966296675a5092505f68d72563d5939a92353Dave Airlie		goto kfree_devname;
101079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
101179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	/* Basic memrange allocator for stolen space (aka vram) */
101279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	drm_mm_init(&dev_priv->vram, 0, prealloc_size);
101379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
101413f4c435ebf2a7c150ffa714f3b23b8e4e8cb42fEric Anholt	/* Let GEM Manage from end of prealloc space to end of aperture.
101513f4c435ebf2a7c150ffa714f3b23b8e4e8cb42fEric Anholt	 *
101613f4c435ebf2a7c150ffa714f3b23b8e4e8cb42fEric Anholt	 * However, leave one page at the end still bound to the scratch page.
101713f4c435ebf2a7c150ffa714f3b23b8e4e8cb42fEric Anholt	 * There are a number of places where the hardware apparently
101813f4c435ebf2a7c150ffa714f3b23b8e4e8cb42fEric Anholt	 * prefetches past the end of the object, and we've seen multiple
101913f4c435ebf2a7c150ffa714f3b23b8e4e8cb42fEric Anholt	 * hangs with the GPU head pointer stuck in a batchbuffer bound
102013f4c435ebf2a7c150ffa714f3b23b8e4e8cb42fEric Anholt	 * at the last page of the aperture.  One page should be enough to
102113f4c435ebf2a7c150ffa714f3b23b8e4e8cb42fEric Anholt	 * keep any prefetching inside of the aperture.
102213f4c435ebf2a7c150ffa714f3b23b8e4e8cb42fEric Anholt	 */
102313f4c435ebf2a7c150ffa714f3b23b8e4e8cb42fEric Anholt	i915_gem_do_init(dev, prealloc_size, agp_size - 4096);
102479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
102579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	ret = i915_gem_init_ringbuffer(dev);
102679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	if (ret)
1027aa5966296675a5092505f68d72563d5939a92353Dave Airlie		goto kfree_devname;
102879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
102979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	/* Allow hardware batchbuffers unless told otherwise.
103079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	 */
103179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	dev_priv->allow_batchbuffer = 1;
103279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
103379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	ret = intel_init_bios(dev);
103479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	if (ret)
103579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		DRM_INFO("failed to find VBIOS tables\n");
103679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
103779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	ret = drm_irq_install(dev);
103879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	if (ret)
103979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		goto destroy_ringbuffer;
104079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
104179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	/* Always safe in the mode setting case. */
104279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	/* FIXME: do pre/post-mode set stuff in core KMS code */
104379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	dev->vblank_disable_allowed = 1;
104479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
104579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	/*
104679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	 * Initialize the hardware status page IRQ location.
104779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	 */
104879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
104979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	I915_WRITE(INSTPM, (1 << 5) | (1 << 21));
105079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
105179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	intel_modeset_init(dev);
105279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
10537a1fb5d06d3936c0982e2cf8b53b046244a9aad6Jesse Barnes	drm_helper_initial_config(dev);
105479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
105579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	return 0;
105679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
105779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnesdestroy_ringbuffer:
105879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	i915_gem_cleanup_ringbuffer(dev);
1059aa5966296675a5092505f68d72563d5939a92353Dave Airliekfree_devname:
1060aa5966296675a5092505f68d72563d5939a92353Dave Airlie	kfree(dev->devname);
106179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnesout:
106279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	return ret;
106379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes}
106479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
10657c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlieint i915_master_create(struct drm_device *dev, struct drm_master *master)
10667c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie{
10677c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	struct drm_i915_master_private *master_priv;
10687c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
10697c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	master_priv = drm_calloc(1, sizeof(*master_priv), DRM_MEM_DRIVER);
10707c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	if (!master_priv)
10717c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie		return -ENOMEM;
10727c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
10737c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	master->driver_priv = master_priv;
10747c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	return 0;
10757c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie}
10767c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
10777c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlievoid i915_master_destroy(struct drm_device *dev, struct drm_master *master)
10787c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie{
10797c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	struct drm_i915_master_private *master_priv = master->driver_priv;
10807c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
10817c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	if (!master_priv)
10827c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie		return;
10837c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
10847c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	drm_free(master_priv, sizeof(*master_priv), DRM_MEM_DRIVER);
10857c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
10867c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	master->driver_priv = NULL;
10877c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie}
10887c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
108979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes/**
109079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * i915_driver_load - setup chip and create an initial config
109179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * @dev: DRM device
109279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * @flags: startup flags
109379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes *
109479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * The driver load routine has to do several things:
109579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes *   - drive output discovery via intel_modeset_init()
109679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes *   - initialize the memory manager
109779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes *   - allocate initial config memory
109879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes *   - setup the DRM framebuffer with the allocated memory
109979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes */
110084b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airlieint i915_driver_load(struct drm_device *dev, unsigned long flags)
110122eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie{
1102ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	struct drm_i915_private *dev_priv = dev->dev_private;
1103d883f7f1b75c8dcafa891f7b9e69c5a2f0ff6d66Benjamin Herrenschmidt	resource_size_t base, size;
1104ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	int ret = 0, mmio_bar = IS_I9XX(dev) ? 0 : 1;
1105ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
110622eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie	/* i915 has 4 more counters */
110722eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie	dev->counters += 4;
110822eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie	dev->types[6] = _DRM_STAT_IRQ;
110922eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie	dev->types[7] = _DRM_STAT_PRIMARY;
111022eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie	dev->types[8] = _DRM_STAT_SECONDARY;
111122eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie	dev->types[9] = _DRM_STAT_DMA;
111222eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie
1113ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	dev_priv = drm_alloc(sizeof(drm_i915_private_t), DRM_MEM_DRIVER);
1114ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	if (dev_priv == NULL)
1115ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes		return -ENOMEM;
1116ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
1117ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	memset(dev_priv, 0, sizeof(drm_i915_private_t));
1118ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
1119ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	dev->dev_private = (void *)dev_priv;
1120673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	dev_priv->dev = dev;
1121ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
1122ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	/* Add register map (needed for suspend/resume) */
1123ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	base = drm_get_resource_start(dev, mmio_bar);
1124ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	size = drm_get_resource_len(dev, mmio_bar);
1125ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
11263043c60c485ad694392d3f71bd7ef9f5c5f7cfddEric Anholt	dev_priv->regs = ioremap(base, size);
112779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	if (!dev_priv->regs) {
112879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		DRM_ERROR("failed to map registers\n");
112979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		ret = -EIO;
113079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		goto free_priv;
113179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	}
1132ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt
1133ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt        dev_priv->mm.gtt_mapping =
1134ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt		io_mapping_create_wc(dev->agp->base,
1135ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt				     dev->agp->agp_info.aper_size * 1024*1024);
11366644107d57a8fa82b47e4c55da4d9d91a612f29cVenkatesh Pallipadi	if (dev_priv->mm.gtt_mapping == NULL) {
11376644107d57a8fa82b47e4c55da4d9d91a612f29cVenkatesh Pallipadi		ret = -EIO;
11386644107d57a8fa82b47e4c55da4d9d91a612f29cVenkatesh Pallipadi		goto out_rmmap;
11396644107d57a8fa82b47e4c55da4d9d91a612f29cVenkatesh Pallipadi	}
11406644107d57a8fa82b47e4c55da4d9d91a612f29cVenkatesh Pallipadi
1141ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt	/* Set up a WC MTRR for non-PAT systems.  This is more common than
1142ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt	 * one would think, because the kernel disables PAT on first
1143ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt	 * generation Core chips because WC PAT gets overridden by a UC
1144ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt	 * MTRR if present.  Even if a UC MTRR isn't present.
1145ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt	 */
1146ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt	dev_priv->mm.gtt_mtrr = mtrr_add(dev->agp->base,
1147ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt					 dev->agp->agp_info.aper_size *
1148ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt					 1024 * 1024,
1149ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt					 MTRR_TYPE_WRCOMB, 1);
1150ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt	if (dev_priv->mm.gtt_mtrr < 0) {
1151040aefa263aa9cd7bd5df50586c35e1e15e77f84Eric Anholt		DRM_INFO("MTRR allocation failed.  Graphics "
1152ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt			 "performance may suffer.\n");
1153ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt	}
1154ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt
1155ac5c4e76180a74c7f922f6fa71ace0cef45fa433Dave Airlie#ifdef CONFIG_HIGHMEM64G
1156ac5c4e76180a74c7f922f6fa71ace0cef45fa433Dave Airlie	/* don't enable GEM on PAE - needs agp + set_memory_* interface fixes */
1157ac5c4e76180a74c7f922f6fa71ace0cef45fa433Dave Airlie	dev_priv->has_gem = 0;
1158ac5c4e76180a74c7f922f6fa71ace0cef45fa433Dave Airlie#else
1159ac5c4e76180a74c7f922f6fa71ace0cef45fa433Dave Airlie	/* enable GEM by default */
1160ac5c4e76180a74c7f922f6fa71ace0cef45fa433Dave Airlie	dev_priv->has_gem = 1;
1161ac5c4e76180a74c7f922f6fa71ace0cef45fa433Dave Airlie#endif
1162ac5c4e76180a74c7f922f6fa71ace0cef45fa433Dave Airlie
11639880b7a527ffbb52f65c2de0a8d4eea86e24775eJesse Barnes	dev->driver->get_vblank_counter = i915_get_vblank_counter;
11649880b7a527ffbb52f65c2de0a8d4eea86e24775eJesse Barnes	if (IS_GM45(dev))
11659880b7a527ffbb52f65c2de0a8d4eea86e24775eJesse Barnes		dev->driver->get_vblank_counter = gm45_get_vblank_counter;
11669880b7a527ffbb52f65c2de0a8d4eea86e24775eJesse Barnes
1167673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	i915_gem_load(dev);
1168673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt
1169398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	/* Init HWS */
1170398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	if (!I915_NEED_GFX_HWS(dev)) {
1171398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard		ret = i915_init_phys_hws(dev);
1172398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard		if (ret != 0)
11736644107d57a8fa82b47e4c55da4d9d91a612f29cVenkatesh Pallipadi			goto out_iomapfree;
1174398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	}
1175ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt
1176ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt	/* On the 945G/GM, the chipset reports the MSI capability on the
1177ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt	 * integrated graphics even though the support isn't actually there
1178ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt	 * according to the published specs.  It doesn't appear to function
1179ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt	 * correctly in testing on 945G.
1180ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt	 * This may be a side effect of MSI having been made available for PEG
1181ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt	 * and the registers being closely associated.
1182d1ed629f44b3a4108d5c445971535f05f441fce7Keith Packard	 *
1183d1ed629f44b3a4108d5c445971535f05f441fce7Keith Packard	 * According to chipset errata, on the 965GM, MSI interrupts may
1184b60678a75d44fa9d5969f79781bd856ad5858609Keith Packard	 * be lost or delayed, but we use them anyways to avoid
1185b60678a75d44fa9d5969f79781bd856ad5858609Keith Packard	 * stuck interrupts on some machines.
1186ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt	 */
1187b60678a75d44fa9d5969f79781bd856ad5858609Keith Packard	if (!IS_I945G(dev) && !IS_I945GM(dev))
1188d3e74d0237b102d34979015fbf6df02ca4413074Eric Anholt		pci_enable_msi(dev->pdev);
1189ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt
1190ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt	spin_lock_init(&dev_priv->user_irq_lock);
119179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	dev_priv->user_irq_refcount = 0;
1192ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt
119352440211dcdc52c0b757f8b34d122e11b12cdd50Keith Packard	ret = drm_vblank_init(dev, I915_NUM_PIPE);
119452440211dcdc52c0b757f8b34d122e11b12cdd50Keith Packard
119552440211dcdc52c0b757f8b34d122e11b12cdd50Keith Packard	if (ret) {
119652440211dcdc52c0b757f8b34d122e11b12cdd50Keith Packard		(void) i915_driver_unload(dev);
119752440211dcdc52c0b757f8b34d122e11b12cdd50Keith Packard		return ret;
119852440211dcdc52c0b757f8b34d122e11b12cdd50Keith Packard	}
119952440211dcdc52c0b757f8b34d122e11b12cdd50Keith Packard
120079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
120179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		ret = i915_load_modeset_init(dev);
120279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		if (ret < 0) {
120379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes			DRM_ERROR("failed to init modeset\n");
120479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes			goto out_rmmap;
120579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		}
120679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	}
120779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
120874a365b3f354fafc537efa5867deb7a9fadbfe27Matthew Garrett	/* Must be done after probing outputs */
120974a365b3f354fafc537efa5867deb7a9fadbfe27Matthew Garrett	intel_opregion_init(dev, 0);
121074a365b3f354fafc537efa5867deb7a9fadbfe27Matthew Garrett
121179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	return 0;
121279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
12136644107d57a8fa82b47e4c55da4d9d91a612f29cVenkatesh Pallipadiout_iomapfree:
12146644107d57a8fa82b47e4c55da4d9d91a612f29cVenkatesh Pallipadi	io_mapping_free(dev_priv->mm.gtt_mapping);
121579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnesout_rmmap:
121679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	iounmap(dev_priv->regs);
121779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnesfree_priv:
121879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	drm_free(dev_priv, sizeof(struct drm_i915_private), DRM_MEM_DRIVER);
1219ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	return ret;
1220ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes}
1221ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
1222ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnesint i915_driver_unload(struct drm_device *dev)
1223ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes{
1224ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	struct drm_i915_private *dev_priv = dev->dev_private;
1225ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
1226ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt	io_mapping_free(dev_priv->mm.gtt_mapping);
1227ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt	if (dev_priv->mm.gtt_mtrr >= 0) {
1228ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt		mtrr_del(dev_priv->mm.gtt_mtrr, dev->agp->base,
1229ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt			 dev->agp->agp_info.aper_size * 1024 * 1024);
1230ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt		dev_priv->mm.gtt_mtrr = -1;
1231ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt	}
1232ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt
123379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
123479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		drm_irq_uninstall(dev);
123579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	}
123679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
1237ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt	if (dev->pdev->msi_enabled)
1238ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt		pci_disable_msi(dev->pdev);
1239ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt
12403043c60c485ad694392d3f71bd7ef9f5c5f7cfddEric Anholt	if (dev_priv->regs != NULL)
12413043c60c485ad694392d3f71bd7ef9f5c5f7cfddEric Anholt		iounmap(dev_priv->regs);
1242ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
12433b1c1c1118880921da1188b7245e0470742802f8Matthew Garrett	intel_opregion_free(dev, 0);
12448ee1c3db9075cb3211352e737e0feb98fd733b20Matthew Garrett
124579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
124679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		intel_modeset_cleanup(dev);
124779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
124871acb5eb8d95b371f4cdd88a47f3c83c870d1c8fDave Airlie		i915_gem_free_all_phys_object(dev);
124971acb5eb8d95b371f4cdd88a47f3c83c870d1c8fDave Airlie
125079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		mutex_lock(&dev->struct_mutex);
125179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		i915_gem_cleanup_ringbuffer(dev);
125279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		mutex_unlock(&dev->struct_mutex);
125379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		drm_mm_takedown(&dev_priv->vram);
125479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		i915_gem_lastclose(dev);
125579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	}
125679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
1257ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	drm_free(dev->dev_private, sizeof(drm_i915_private_t),
1258ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes		 DRM_MEM_DRIVER);
1259ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
126022eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie	return 0;
126122eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie}
126222eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie
1263673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholtint i915_driver_open(struct drm_device *dev, struct drm_file *file_priv)
1264673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt{
1265673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	struct drm_i915_file_private *i915_file_priv;
1266673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt
1267673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	DRM_DEBUG("\n");
1268673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	i915_file_priv = (struct drm_i915_file_private *)
1269673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	    drm_alloc(sizeof(*i915_file_priv), DRM_MEM_FILES);
1270673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt
1271673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	if (!i915_file_priv)
1272673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		return -ENOMEM;
1273673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt
1274673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	file_priv->driver_priv = i915_file_priv;
1275673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt
1276673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	i915_file_priv->mm.last_gem_seqno = 0;
1277673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	i915_file_priv->mm.last_gem_throttle_seqno = 0;
1278673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt
1279673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	return 0;
1280673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt}
1281673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt
128279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes/**
128379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * i915_driver_lastclose - clean up after all DRM clients have exited
128479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * @dev: DRM device
128579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes *
128679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * Take care of cleaning up after all DRM clients have exited.  In the
128779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * mode setting case, we want to restore the kernel's initial mode (just
128879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * in case the last client left us in a bad state).
128979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes *
129079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * Additionally, in the non-mode setting case, we'll tear down the AGP
129179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * and DMA structures, since the kernel won't be using them, and clea
129279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * up any GEM state.
129379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes */
129484b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airlievoid i915_driver_lastclose(struct drm_device * dev)
12951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1296ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	drm_i915_private_t *dev_priv = dev->dev_private;
1297ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
129879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	if (!dev_priv || drm_core_check_feature(dev, DRIVER_MODESET)) {
129979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		intelfb_restore();
1300144a75fa1faa4a81530bded2e59872ef80d496b6Dave Airlie		return;
130179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	}
1302144a75fa1faa4a81530bded2e59872ef80d496b6Dave Airlie
1303673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	i915_gem_lastclose(dev);
1304673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt
1305ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	if (dev_priv->agp_heap)
1306b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		i915_mem_takedown(&(dev_priv->agp_heap));
1307ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
1308b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	i915_dma_cleanup(dev);
13091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13116c340eac0285f3d62406d2d902d0e96fbf2a5dc0Eric Anholtvoid i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv)
13121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1313ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	drm_i915_private_t *dev_priv = dev->dev_private;
131479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	if (!drm_core_check_feature(dev, DRIVER_MODESET))
131579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		i915_mem_release(dev, file_priv, dev_priv->agp_heap);
13161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1318673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholtvoid i915_driver_postclose(struct drm_device *dev, struct drm_file *file_priv)
1319673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt{
1320673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	struct drm_i915_file_private *i915_file_priv = file_priv->driver_priv;
1321673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt
1322673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	drm_free(i915_file_priv, sizeof(*i915_file_priv), DRM_MEM_FILES);
1323673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt}
1324673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt
1325c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstruct drm_ioctl_desc i915_ioctls[] = {
1326c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_INIT, i915_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
1327c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_FLUSH, i915_flush_ioctl, DRM_AUTH),
1328c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_FLIP, i915_flip_bufs, DRM_AUTH),
1329c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_BATCHBUFFER, i915_batchbuffer, DRM_AUTH),
1330c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_IRQ_EMIT, i915_irq_emit, DRM_AUTH),
1331c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_IRQ_WAIT, i915_irq_wait, DRM_AUTH),
1332c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_GETPARAM, i915_getparam, DRM_AUTH),
1333c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_SETPARAM, i915_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
1334c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_ALLOC, i915_mem_alloc, DRM_AUTH),
1335c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_FREE, i915_mem_free, DRM_AUTH),
1336c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_INIT_HEAP, i915_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
1337c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_CMDBUFFER, i915_cmdbuffer, DRM_AUTH),
1338c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_DESTROY_HEAP,  i915_mem_destroy_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY ),
1339c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_SET_VBLANK_PIPE,  i915_vblank_pipe_set, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY ),
1340c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_GET_VBLANK_PIPE,  i915_vblank_pipe_get, DRM_AUTH ),
1341c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_VBLANK_SWAP, i915_vblank_swap, DRM_AUTH),
13424b40893918203ee1a1f6a114316c2a19c072e9bdMatthias Hopf	DRM_IOCTL_DEF(DRM_I915_HWS_ADDR, i915_set_status_page, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
13432bdf00b22154023ac312481583603f4724eb1401Dave Airlie	DRM_IOCTL_DEF(DRM_I915_GEM_INIT, i915_gem_init_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
1344673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	DRM_IOCTL_DEF(DRM_I915_GEM_EXECBUFFER, i915_gem_execbuffer, DRM_AUTH),
1345673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	DRM_IOCTL_DEF(DRM_I915_GEM_PIN, i915_gem_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY),
1346673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	DRM_IOCTL_DEF(DRM_I915_GEM_UNPIN, i915_gem_unpin_ioctl, DRM_AUTH|DRM_ROOT_ONLY),
1347673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	DRM_IOCTL_DEF(DRM_I915_GEM_BUSY, i915_gem_busy_ioctl, DRM_AUTH),
1348673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	DRM_IOCTL_DEF(DRM_I915_GEM_THROTTLE, i915_gem_throttle_ioctl, DRM_AUTH),
13492bdf00b22154023ac312481583603f4724eb1401Dave Airlie	DRM_IOCTL_DEF(DRM_I915_GEM_ENTERVT, i915_gem_entervt_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
13502bdf00b22154023ac312481583603f4724eb1401Dave Airlie	DRM_IOCTL_DEF(DRM_I915_GEM_LEAVEVT, i915_gem_leavevt_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
1351673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	DRM_IOCTL_DEF(DRM_I915_GEM_CREATE, i915_gem_create_ioctl, 0),
1352673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	DRM_IOCTL_DEF(DRM_I915_GEM_PREAD, i915_gem_pread_ioctl, 0),
1353673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	DRM_IOCTL_DEF(DRM_I915_GEM_PWRITE, i915_gem_pwrite_ioctl, 0),
1354673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	DRM_IOCTL_DEF(DRM_I915_GEM_MMAP, i915_gem_mmap_ioctl, 0),
1355de151cf67ce52ed2d88083daa5e60c7858947329Jesse Barnes	DRM_IOCTL_DEF(DRM_I915_GEM_MMAP_GTT, i915_gem_mmap_gtt_ioctl, 0),
1356673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	DRM_IOCTL_DEF(DRM_I915_GEM_SET_DOMAIN, i915_gem_set_domain_ioctl, 0),
1357673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	DRM_IOCTL_DEF(DRM_I915_GEM_SW_FINISH, i915_gem_sw_finish_ioctl, 0),
1358673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	DRM_IOCTL_DEF(DRM_I915_GEM_SET_TILING, i915_gem_set_tiling, 0),
1359673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	DRM_IOCTL_DEF(DRM_I915_GEM_GET_TILING, i915_gem_get_tiling, 0),
13605a125c3c79167e78ba44efef03af7090ef28eeafEric Anholt	DRM_IOCTL_DEF(DRM_I915_GEM_GET_APERTURE, i915_gem_get_aperture_ioctl, 0),
136108d7b3d1edff84bd673d9e9ab36b5aa62e1ba903Carl Worth	DRM_IOCTL_DEF(DRM_I915_GET_PIPE_FROM_CRTC_ID, intel_get_pipe_from_crtc_id, 0),
1362c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie};
1363c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie
1364c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlieint i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
1365cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie
1366cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie/**
1367cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie * Determine if the device really is AGP or not.
1368cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie *
1369cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie * All Intel graphics chipsets are treated as AGP, even if they are really
1370cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie * PCI-e.
1371cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie *
1372cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie * \param dev   The device to be tested.
1373cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie *
1374cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie * \returns
1375cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie * A value of 1 is always retured to indictate every i9x5 is AGP.
1376cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie */
137784b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airlieint i915_driver_device_is_agp(struct drm_device * dev)
1378cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie{
1379cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie	return 1;
1380cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie}
1381