i915_dma.c revision 9216d44dc13b5e858253f06d83ceea25a9b72f4f
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"
32785b93ef8c309730c2de84ce9c229e40e2d01480Dave Airlie#include "drm_fb_helper.h"
3379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes#include "intel_drv.h"
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "i915_drm.h"
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "i915_drv.h"
361c5d22f76dc721f3acb7a3dadc657a221e487fb7Chris Wilson#include "i915_trace.h"
3728d520433b6375740990ab99d69b0d0067fd656bDave Airlie#include <linux/vgaarb.h>
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Really want an OS-independent resettable timer.  Would like to have
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * this loop run for (eg) 3 sec, but have the timer reset every time
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the head pointer changes, so that EBUSY only happens if the ring
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * actually stalls for (eg) 3 seconds.
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
4484b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airlieint i915_wait_ring(struct drm_device * dev, int n, const char *caller)
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = dev->dev_private;
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
48d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard	u32 acthd_reg = IS_I965G(dev) ? ACTHD_I965 : ACTHD;
49d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard	u32 last_acthd = I915_READ(acthd_reg);
50d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard	u32 acthd;
51585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes	u32 last_head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
541c5d22f76dc721f3acb7a3dadc657a221e487fb7Chris Wilson	trace_i915_ring_wait_begin (dev);
551c5d22f76dc721f3acb7a3dadc657a221e487fb7Chris Wilson
56d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard	for (i = 0; i < 100000; i++) {
57585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes		ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
58d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard		acthd = I915_READ(acthd_reg);
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ring->space = ring->head - (ring->tail + 8);
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ring->space < 0)
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ring->space += ring->Size;
621c5d22f76dc721f3acb7a3dadc657a221e487fb7Chris Wilson		if (ring->space >= n) {
631c5d22f76dc721f3acb7a3dadc657a221e487fb7Chris Wilson			trace_i915_ring_wait_end (dev);
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 0;
651c5d22f76dc721f3acb7a3dadc657a221e487fb7Chris Wilson		}
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6798787c057fdefdce6230ff46f2c1105835005a4cChris Wilson		if (dev->primary->master) {
6898787c057fdefdce6230ff46f2c1105835005a4cChris Wilson			struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
6998787c057fdefdce6230ff46f2c1105835005a4cChris Wilson			if (master_priv->sarea_priv)
7098787c057fdefdce6230ff46f2c1105835005a4cChris Wilson				master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
7198787c057fdefdce6230ff46f2c1105835005a4cChris Wilson		}
7298787c057fdefdce6230ff46f2c1105835005a4cChris Wilson
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ring->head != last_head)
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			i = 0;
76d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard		if (acthd != last_acthd)
77d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard			i = 0;
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		last_head = ring->head;
80d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard		last_acthd = acthd;
81d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard		msleep_interruptible(10);
82d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
851c5d22f76dc721f3acb7a3dadc657a221e487fb7Chris Wilson	trace_i915_ring_wait_end (dev);
8620caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt	return -EBUSY;
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
890ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson/* As a ringbuffer is only allowed to wrap between instructions, fill
900ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson * the tail with NOOPs.
910ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson */
920ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilsonint i915_wrap_ring(struct drm_device *dev)
930ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson{
940ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson	drm_i915_private_t *dev_priv = dev->dev_private;
950ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson	volatile unsigned int *virt;
960ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson	int rem;
970ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson
980ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson	rem = dev_priv->ring.Size - dev_priv->ring.tail;
990ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson	if (dev_priv->ring.space < rem) {
1000ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson		int ret = i915_wait_ring(dev, rem, __func__);
1010ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson		if (ret)
1020ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson			return ret;
1030ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson	}
1040ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson	dev_priv->ring.space -= rem;
1050ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson
1060ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson	virt = (unsigned int *)
1070ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson		(dev_priv->ring.virtual_start + dev_priv->ring.tail);
1080ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson	rem /= 4;
1090ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson	while (rem--)
1100ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson		*virt++ = MI_NOOP;
1110ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson
1120ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson	dev_priv->ring.tail = 0;
1130ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson
1140ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson	return 0;
1150ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson}
1160ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson
117398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard/**
118398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard * Sets up the hardware status page for devices that need a physical address
119398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard * in the register.
120398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard */
1213043c60c485ad694392d3f71bd7ef9f5c5f7cfddEric Anholtstatic int i915_init_phys_hws(struct drm_device *dev)
122398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard{
123398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	drm_i915_private_t *dev_priv = dev->dev_private;
124398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	/* Program Hardware Status Page */
125398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	dev_priv->status_page_dmah =
126398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard		drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff);
127398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard
128398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	if (!dev_priv->status_page_dmah) {
129398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard		DRM_ERROR("Can not allocate hardware status page\n");
130398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard		return -ENOMEM;
131398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	}
132398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr;
133398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
134398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard
135398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
136398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard
137398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	I915_WRITE(HWS_PGA, dev_priv->dma_status_page);
1388a4c47f346cc7a12d0897c05eb3cc1add26b487fZhao Yakui	DRM_DEBUG_DRIVER("Enabled hardware status page\n");
139398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	return 0;
140398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard}
141398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard
142398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard/**
143398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard * Frees the hardware status page, whether it's a physical address or a virtual
144398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard * address set up by the X Server.
145398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard */
1463043c60c485ad694392d3f71bd7ef9f5c5f7cfddEric Anholtstatic void i915_free_hws(struct drm_device *dev)
147398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard{
148398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	drm_i915_private_t *dev_priv = dev->dev_private;
149398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	if (dev_priv->status_page_dmah) {
150398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard		drm_pci_free(dev, dev_priv->status_page_dmah);
151398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard		dev_priv->status_page_dmah = NULL;
152398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	}
153398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard
154398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	if (dev_priv->status_gfx_addr) {
155398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard		dev_priv->status_gfx_addr = 0;
156398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard		drm_core_ioremapfree(&dev_priv->hws_map, dev);
157398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	}
158398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard
159398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	/* Need to rewrite hardware status page */
160398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	I915_WRITE(HWS_PGA, 0x1ffff000);
161398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard}
162398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard
16384b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airlievoid i915_kernel_lost_context(struct drm_device * dev)
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = dev->dev_private;
1667c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	struct drm_i915_master_private *master_priv;
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	/*
17079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	 * We should never lose context on the ring with modesetting
17179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	 * as we don't expose it to userspace
17279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	 */
17379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	if (drm_core_check_feature(dev, DRIVER_MODESET))
17479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		return;
17579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
176585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes	ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
177585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes	ring->tail = I915_READ(PRB0_TAIL) & TAIL_ADDR;
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ring->space = ring->head - (ring->tail + 8);
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ring->space < 0)
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ring->space += ring->Size;
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1827c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	if (!dev->primary->master)
1837c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie		return;
1847c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
1857c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	master_priv = dev->primary->master->driver_priv;
1867c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	if (ring->head == ring->tail && master_priv->sarea_priv)
1877c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie		master_priv->sarea_priv->perf_boxes |= I915_BOX_RING_EMPTY;
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19084b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airliestatic int i915_dma_cleanup(struct drm_device * dev)
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
192ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	drm_i915_private_t *dev_priv = dev->dev_private;
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Make sure interrupts are disabled here because the uninstall ioctl
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * may not have been called from userspace and after dev_private
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * is freed, it's too late.
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
197ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt	if (dev->irq_enabled)
198b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		drm_irq_uninstall(dev);
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
200ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	if (dev_priv->ring.virtual_start) {
201ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes		drm_core_ioremapfree(&dev_priv->ring.map, dev);
2023043c60c485ad694392d3f71bd7ef9f5c5f7cfddEric Anholt		dev_priv->ring.virtual_start = NULL;
2033043c60c485ad694392d3f71bd7ef9f5c5f7cfddEric Anholt		dev_priv->ring.map.handle = NULL;
204ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes		dev_priv->ring.map.size = 0;
205ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	}
206dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu
207398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	/* Clear the HWS virtual address at teardown */
208398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	if (I915_NEED_GFX_HWS(dev))
209398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard		i915_free_hws(dev);
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
214ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnesstatic int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
216ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	drm_i915_private_t *dev_priv = dev->dev_private;
2177c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2193a03ac1a0223f779a3de313523408ddb099e5679Dave Airlie	master_priv->sarea = drm_getsarea(dev);
2203a03ac1a0223f779a3de313523408ddb099e5679Dave Airlie	if (master_priv->sarea) {
2213a03ac1a0223f779a3de313523408ddb099e5679Dave Airlie		master_priv->sarea_priv = (drm_i915_sarea_t *)
2223a03ac1a0223f779a3de313523408ddb099e5679Dave Airlie			((u8 *)master_priv->sarea->handle + init->sarea_priv_offset);
2233a03ac1a0223f779a3de313523408ddb099e5679Dave Airlie	} else {
2248a4c47f346cc7a12d0897c05eb3cc1add26b487fZhao Yakui		DRM_DEBUG_DRIVER("sarea not found assuming DRI2 userspace\n");
2253a03ac1a0223f779a3de313523408ddb099e5679Dave Airlie	}
2263a03ac1a0223f779a3de313523408ddb099e5679Dave Airlie
227673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	if (init->ring_size != 0) {
228673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		if (dev_priv->ring.ring_obj != NULL) {
229673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt			i915_dma_cleanup(dev);
230673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt			DRM_ERROR("Client tried to initialize ringbuffer in "
231673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt				  "GEM mode\n");
232673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt			return -EINVAL;
233673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		}
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
235673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		dev_priv->ring.Size = init->ring_size;
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
237673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		dev_priv->ring.map.offset = init->ring_start;
238673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		dev_priv->ring.map.size = init->ring_size;
239673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		dev_priv->ring.map.type = 0;
240673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		dev_priv->ring.map.flags = 0;
241673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		dev_priv->ring.map.mtrr = 0;
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2436fb88588555a18792a27f483887fe1f2af5f9c9bJesse Barnes		drm_core_ioremap_wc(&dev_priv->ring.map, dev);
244673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt
245673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		if (dev_priv->ring.map.handle == NULL) {
246673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt			i915_dma_cleanup(dev);
247673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt			DRM_ERROR("can not ioremap virtual address for"
248673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt				  " ring buffer\n");
249673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt			return -ENOMEM;
250673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		}
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
255a6b54f3f5050c0cbc0c35dd48064846c6302706bMichel Dänzer	dev_priv->cpp = init->cpp;
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_priv->back_offset = init->back_offset;
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_priv->front_offset = init->front_offset;
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_priv->current_page = 0;
2597c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	if (master_priv->sarea_priv)
2607c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie		master_priv->sarea_priv->pf_current_page = 0;
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Allow hardware batchbuffers unless told otherwise.
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_priv->allow_batchbuffer = 1;
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26984b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airliestatic int i915_dma_resume(struct drm_device * dev)
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2738a4c47f346cc7a12d0897c05eb3cc1add26b487fZhao Yakui	DRM_DEBUG_DRIVER("%s\n", __func__);
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (dev_priv->ring.map.handle == NULL) {
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("can not ioremap virtual address for"
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			  " ring buffer\n");
27820caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -ENOMEM;
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Program Hardware Status Page */
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!dev_priv->hw_status_page) {
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("Can not find hardware status page\n");
28420caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2868a4c47f346cc7a12d0897c05eb3cc1add26b487fZhao Yakui	DRM_DEBUG_DRIVER("hw status page @ %p\n",
287be25ed9c5cc06e1d17aa97e41daf88f0b46143e6yakui_zhao				dev_priv->hw_status_page);
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
289dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	if (dev_priv->status_gfx_addr != 0)
290585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes		I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
291dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	else
292585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes		I915_WRITE(HWS_PGA, dev_priv->dma_status_page);
2938a4c47f346cc7a12d0897c05eb3cc1add26b487fZhao Yakui	DRM_DEBUG_DRIVER("Enabled hardware status page\n");
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
298c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_dma_init(struct drm_device *dev, void *data,
299c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt			 struct drm_file *file_priv)
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
301c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	drm_i915_init_t *init = data;
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int retcode = 0;
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
304c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	switch (init->func) {
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case I915_INIT_DMA:
306ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes		retcode = i915_initialize(dev, init);
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case I915_CLEANUP_DMA:
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		retcode = i915_dma_cleanup(dev);
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case I915_RESUME_DMA:
3120d6aa60b4ac9689b750e35cd66f5d7c053aff0f4Dave Airlie		retcode = i915_dma_resume(dev);
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
31520caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		retcode = -EINVAL;
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return retcode;
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Implement basically the same security restrictions as hardware does
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * for MI_BATCH_NON_SECURE.  These can be made stricter at any time.
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Most of the calculations below involve calculating the size of a
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * particular instruction.  It's important to get the size right as
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * that tells us where the next instruction to check is.  Any illegal
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * instruction detected will be given a size of zero, which is a
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * signal to abort the rest of the buffer.
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int do_validate_cmd(int cmd)
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (((cmd >> 29) & 0x7)) {
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 0x0:
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch ((cmd >> 23) & 0x3f) {
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x0:
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 1;	/* MI_NOOP */
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x4:
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 1;	/* MI_FLUSH */
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		default:
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 0;	/* disallow everything else */
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 0x1:
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;	/* reserved */
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 0x2:
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (cmd & 0xff) + 2;	/* 2d commands */
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 0x3:
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (((cmd >> 24) & 0x1f) <= 0x18)
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 1;
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch ((cmd >> 24) & 0x1f) {
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x1c:
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 1;
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x1d:
356b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			switch ((cmd >> 16) & 0xff) {
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case 0x3:
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return (cmd & 0x1f) + 2;
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case 0x4:
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return (cmd & 0xf) + 2;
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			default:
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return (cmd & 0xffff) + 2;
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x1e:
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (cmd & (1 << 23))
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return (cmd & 0xffff) + 1;
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return 1;
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x1f:
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if ((cmd & (1 << 23)) == 0)	/* inline vertices */
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return (cmd & 0x1ffff) + 2;
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else if (cmd & (1 << 17))	/* indirect random */
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if ((cmd & 0xffff) == 0)
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					return 0;	/* unknown length, too hard */
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				else
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					return (((cmd & 0xffff) + 1) / 2) + 1;
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return 2;	/* indirect sequential */
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		default:
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 0;
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int validate_cmd(int cmd)
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret = do_validate_cmd(cmd);
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
393bc5f4523f772cc7629c5c5a46cf4f2a07a5500b8Dave Airlie/*	printk("validate_cmd( %x ): %d\n", cmd, ret); */
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
398201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholtstatic int i915_emit_cmds(struct drm_device * dev, int *buffer, int dwords)
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = dev->dev_private;
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	RING_LOCALS;
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
404de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	if ((dwords+1) * sizeof(int) >= dev_priv->ring.Size - 8)
40520caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
406de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie
407c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane	BEGIN_LP_RING((dwords+1)&~1);
408de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < dwords;) {
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		int cmd, sz;
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
412201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt		cmd = buffer[i];
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((sz = validate_cmd(cmd)) == 0 || i + sz > dwords)
41520caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt			return -EINVAL;
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		OUT_RING(cmd);
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		while (++i, --sz) {
420201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt			OUT_RING(buffer[i]);
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
424de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	if (dwords & 1)
425de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie		OUT_RING(0);
426de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie
427de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	ADVANCE_LP_RING();
428de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
432673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholtint
433673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholti915_emit_box(struct drm_device *dev,
434201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt	      struct drm_clip_rect *boxes,
435673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	      int i, int DR1, int DR4)
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = dev->dev_private;
438201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt	struct drm_clip_rect box = boxes[i];
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	RING_LOCALS;
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (box.y2 <= box.y1 || box.x2 <= box.x1 || box.y2 <= 0 || box.x2 <= 0) {
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("Bad box %d,%d..%d,%d\n",
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			  box.x1, box.y1, box.x2, box.y2);
44420caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
447c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane	if (IS_I965G(dev)) {
448c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		BEGIN_LP_RING(4);
449c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		OUT_RING(GFX_OP_DRAWRECT_INFO_I965);
450c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		OUT_RING((box.x1 & 0xffff) | (box.y1 << 16));
45178eca43d0391f59c3b1505bb7bd38ff45b650aabAndrew Morton		OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16));
452c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		OUT_RING(DR4);
453c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		ADVANCE_LP_RING();
454c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane	} else {
455c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		BEGIN_LP_RING(6);
456c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		OUT_RING(GFX_OP_DRAWRECT_INFO);
457c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		OUT_RING(DR1);
458c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		OUT_RING((box.x1 & 0xffff) | (box.y1 << 16));
459c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16));
460c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		OUT_RING(DR4);
461c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		OUT_RING(0);
462c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		ADVANCE_LP_RING();
463c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane	}
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
468c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane/* XXX: Emitting the counter should really be moved to part of the IRQ
469c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane * emit. For now, do it in both places:
470c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane */
471c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane
47284b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airliestatic void i915_emit_breadcrumb(struct drm_device *dev)
473de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie{
474de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	drm_i915_private_t *dev_priv = dev->dev_private;
4757c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
476de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	RING_LOCALS;
477de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie
478c99b058f132388a666544d293392d52d1def6b12Kristian Høgsberg	dev_priv->counter++;
479af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	if (dev_priv->counter > 0x7FFFFFFFUL)
480c99b058f132388a666544d293392d52d1def6b12Kristian Høgsberg		dev_priv->counter = 0;
4817c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	if (master_priv->sarea_priv)
4827c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie		master_priv->sarea_priv->last_enqueue = dev_priv->counter;
483de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie
484de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	BEGIN_LP_RING(4);
485585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes	OUT_RING(MI_STORE_DWORD_INDEX);
4860baf823a10bd4131f70e9712d1f02de3c247f1dfKeith Packard	OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
487de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	OUT_RING(dev_priv->counter);
488de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	OUT_RING(0);
489de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	ADVANCE_LP_RING();
490de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie}
491de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie
49284b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airliestatic int i915_dispatch_cmdbuffer(struct drm_device * dev,
493201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt				   drm_i915_cmdbuffer_t *cmd,
494201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt				   struct drm_clip_rect *cliprects,
495201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt				   void *cmdbuf)
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int nbox = cmd->num_cliprects;
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i = 0, count, ret;
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (cmd->sz & 0x3) {
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("alignment");
50220caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	i915_kernel_lost_context(dev);
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	count = nbox ? nbox : 1;
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < count; i++) {
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (i < nbox) {
511201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt			ret = i915_emit_box(dev, cliprects, i,
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					    cmd->DR1, cmd->DR4);
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (ret)
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return ret;
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
517201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt		ret = i915_emit_cmds(dev, cmdbuf, cmd->sz / 4);
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ret)
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return ret;
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
522de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	i915_emit_breadcrumb(dev);
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
52684b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airliestatic int i915_dispatch_batchbuffer(struct drm_device * dev,
527201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt				     drm_i915_batchbuffer_t * batch,
528201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt				     struct drm_clip_rect *cliprects)
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = dev->dev_private;
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int nbox = batch->num_cliprects;
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i = 0, count;
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	RING_LOCALS;
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((batch->start | batch->used) & 0x7) {
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("alignment");
53720caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	i915_kernel_lost_context(dev);
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	count = nbox ? nbox : 1;
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < count; i++) {
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (i < nbox) {
546201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt			int ret = i915_emit_box(dev, cliprects, i,
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						batch->DR1, batch->DR4);
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (ret)
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return ret;
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5520790d5e148c0747499742a3c09ba5f1c07f9ed0dKeith Packard		if (!IS_I830(dev) && !IS_845G(dev)) {
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			BEGIN_LP_RING(2);
55421f16289270447673a7263ccc0b22d562fb01ecbDave Airlie			if (IS_I965G(dev)) {
55521f16289270447673a7263ccc0b22d562fb01ecbDave Airlie				OUT_RING(MI_BATCH_BUFFER_START | (2 << 6) | MI_BATCH_NON_SECURE_I965);
55621f16289270447673a7263ccc0b22d562fb01ecbDave Airlie				OUT_RING(batch->start);
55721f16289270447673a7263ccc0b22d562fb01ecbDave Airlie			} else {
55821f16289270447673a7263ccc0b22d562fb01ecbDave Airlie				OUT_RING(MI_BATCH_BUFFER_START | (2 << 6));
55921f16289270447673a7263ccc0b22d562fb01ecbDave Airlie				OUT_RING(batch->start | MI_BATCH_NON_SECURE);
56021f16289270447673a7263ccc0b22d562fb01ecbDave Airlie			}
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ADVANCE_LP_RING();
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			BEGIN_LP_RING(4);
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			OUT_RING(MI_BATCH_BUFFER);
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			OUT_RING(batch->start | MI_BATCH_NON_SECURE);
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			OUT_RING(batch->start + batch->used - 4);
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			OUT_RING(0);
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ADVANCE_LP_RING();
5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
572de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	i915_emit_breadcrumb(dev);
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
577af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airliestatic int i915_dispatch_flip(struct drm_device * dev)
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = dev->dev_private;
5807c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	struct drm_i915_master_private *master_priv =
5817c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie		dev->primary->master->driver_priv;
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	RING_LOCALS;
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5847c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	if (!master_priv->sarea_priv)
585c99b058f132388a666544d293392d52d1def6b12Kristian Høgsberg		return -EINVAL;
586c99b058f132388a666544d293392d52d1def6b12Kristian Høgsberg
5878a4c47f346cc7a12d0897c05eb3cc1add26b487fZhao Yakui	DRM_DEBUG_DRIVER("%s: page=%d pfCurrentPage=%d\n",
588be25ed9c5cc06e1d17aa97e41daf88f0b46143e6yakui_zhao			  __func__,
589be25ed9c5cc06e1d17aa97e41daf88f0b46143e6yakui_zhao			 dev_priv->current_page,
590be25ed9c5cc06e1d17aa97e41daf88f0b46143e6yakui_zhao			 master_priv->sarea_priv->pf_current_page);
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
592af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	i915_kernel_lost_context(dev);
593af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie
594af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	BEGIN_LP_RING(2);
595585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes	OUT_RING(MI_FLUSH | MI_READ_FLUSH);
596af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	OUT_RING(0);
597af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	ADVANCE_LP_RING();
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
599af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	BEGIN_LP_RING(6);
600af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP);
601af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	OUT_RING(0);
602af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	if (dev_priv->current_page == 0) {
603af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie		OUT_RING(dev_priv->back_offset);
604af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie		dev_priv->current_page = 1;
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
606af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie		OUT_RING(dev_priv->front_offset);
607af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie		dev_priv->current_page = 0;
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
609af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	OUT_RING(0);
610af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	ADVANCE_LP_RING();
6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
612af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	BEGIN_LP_RING(2);
613af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP);
614af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	OUT_RING(0);
615af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	ADVANCE_LP_RING();
6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6177c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	master_priv->sarea_priv->last_enqueue = dev_priv->counter++;
6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	BEGIN_LP_RING(4);
620585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes	OUT_RING(MI_STORE_DWORD_INDEX);
6210baf823a10bd4131f70e9712d1f02de3c247f1dfKeith Packard	OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
622af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	OUT_RING(dev_priv->counter);
623af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	OUT_RING(0);
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ADVANCE_LP_RING();
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6267c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	master_priv->sarea_priv->pf_current_page = dev_priv->current_page;
627af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	return 0;
6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
63084b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airliestatic int i915_quiescent(struct drm_device * dev)
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = dev->dev_private;
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	i915_kernel_lost_context(dev);
635bf9d89295233ae2ba7b312c78ee5657307b09f4cHarvey Harrison	return i915_wait_ring(dev, dev_priv->ring.Size - 8, __func__);
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
638c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_flush_ioctl(struct drm_device *dev, void *data,
639c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt			    struct drm_file *file_priv)
6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
641546b0974c39657017407c86fe79811100b60700dEric Anholt	int ret;
642546b0974c39657017407c86fe79811100b60700dEric Anholt
643546b0974c39657017407c86fe79811100b60700dEric Anholt	RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
645546b0974c39657017407c86fe79811100b60700dEric Anholt	mutex_lock(&dev->struct_mutex);
646546b0974c39657017407c86fe79811100b60700dEric Anholt	ret = i915_quiescent(dev);
647546b0974c39657017407c86fe79811100b60700dEric Anholt	mutex_unlock(&dev->struct_mutex);
648546b0974c39657017407c86fe79811100b60700dEric Anholt
649546b0974c39657017407c86fe79811100b60700dEric Anholt	return ret;
6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
652c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_batchbuffer(struct drm_device *dev, void *data,
653c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt			    struct drm_file *file_priv)
6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
6567c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
6587c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	    master_priv->sarea_priv;
659c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	drm_i915_batchbuffer_t *batch = data;
6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret;
661201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt	struct drm_clip_rect *cliprects = NULL;
6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!dev_priv->allow_batchbuffer) {
6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("Batchbuffer ioctl disabled\n");
66520caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6688a4c47f346cc7a12d0897c05eb3cc1add26b487fZhao Yakui	DRM_DEBUG_DRIVER("i915 batchbuffer, start %x used %d cliprects %d\n",
669be25ed9c5cc06e1d17aa97e41daf88f0b46143e6yakui_zhao			batch->start, batch->used, batch->num_cliprects);
6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
671546b0974c39657017407c86fe79811100b60700dEric Anholt	RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
673201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt	if (batch->num_cliprects < 0)
674201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt		return -EINVAL;
675201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt
676201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt	if (batch->num_cliprects) {
6779a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt		cliprects = kcalloc(batch->num_cliprects,
6789a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt				    sizeof(struct drm_clip_rect),
6799a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt				    GFP_KERNEL);
680201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt		if (cliprects == NULL)
681201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt			return -ENOMEM;
682201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt
683201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt		ret = copy_from_user(cliprects, batch->cliprects,
684201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt				     batch->num_cliprects *
685201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt				     sizeof(struct drm_clip_rect));
686201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt		if (ret != 0)
687201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt			goto fail_free;
688201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt	}
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
690546b0974c39657017407c86fe79811100b60700dEric Anholt	mutex_lock(&dev->struct_mutex);
691201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt	ret = i915_dispatch_batchbuffer(dev, batch, cliprects);
692546b0974c39657017407c86fe79811100b60700dEric Anholt	mutex_unlock(&dev->struct_mutex);
6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
694c99b058f132388a666544d293392d52d1def6b12Kristian Høgsberg	if (sarea_priv)
6950baf823a10bd4131f70e9712d1f02de3c247f1dfKeith Packard		sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
696201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt
697201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholtfail_free:
6989a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt	kfree(cliprects);
699201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt
7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
703c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_cmdbuffer(struct drm_device *dev, void *data,
704c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt			  struct drm_file *file_priv)
7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
7077c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
7097c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	    master_priv->sarea_priv;
710c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	drm_i915_cmdbuffer_t *cmdbuf = data;
711201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt	struct drm_clip_rect *cliprects = NULL;
712201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt	void *batch_data;
7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret;
7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7158a4c47f346cc7a12d0897c05eb3cc1add26b487fZhao Yakui	DRM_DEBUG_DRIVER("i915 cmdbuffer, buf %p sz %d cliprects %d\n",
716be25ed9c5cc06e1d17aa97e41daf88f0b46143e6yakui_zhao			cmdbuf->buf, cmdbuf->sz, cmdbuf->num_cliprects);
7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
718546b0974c39657017407c86fe79811100b60700dEric Anholt	RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
720201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt	if (cmdbuf->num_cliprects < 0)
721201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt		return -EINVAL;
722201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt
7239a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt	batch_data = kmalloc(cmdbuf->sz, GFP_KERNEL);
724201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt	if (batch_data == NULL)
725201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt		return -ENOMEM;
726201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt
727201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt	ret = copy_from_user(batch_data, cmdbuf->buf, cmdbuf->sz);
728201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt	if (ret != 0)
729201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt		goto fail_batch_free;
730201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt
731201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt	if (cmdbuf->num_cliprects) {
7329a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt		cliprects = kcalloc(cmdbuf->num_cliprects,
7339a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt				    sizeof(struct drm_clip_rect), GFP_KERNEL);
734201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt		if (cliprects == NULL)
735201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt			goto fail_batch_free;
736201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt
737201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt		ret = copy_from_user(cliprects, cmdbuf->cliprects,
738201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt				     cmdbuf->num_cliprects *
739201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt				     sizeof(struct drm_clip_rect));
740201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt		if (ret != 0)
741201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt			goto fail_clip_free;
7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
744546b0974c39657017407c86fe79811100b60700dEric Anholt	mutex_lock(&dev->struct_mutex);
745201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt	ret = i915_dispatch_cmdbuffer(dev, cmdbuf, cliprects, batch_data);
746546b0974c39657017407c86fe79811100b60700dEric Anholt	mutex_unlock(&dev->struct_mutex);
7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ret) {
7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("i915_dispatch_cmdbuffer failed\n");
749355d7f370b51bbb6f31aaf9f98861057e1e6bbb2Chris Wright		goto fail_clip_free;
7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
752c99b058f132388a666544d293392d52d1def6b12Kristian Høgsberg	if (sarea_priv)
7530baf823a10bd4131f70e9712d1f02de3c247f1dfKeith Packard		sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
754201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt
755201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholtfail_clip_free:
7569a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt	kfree(cliprects);
757355d7f370b51bbb6f31aaf9f98861057e1e6bbb2Chris Wrightfail_batch_free:
7589a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt	kfree(batch_data);
759201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt
760201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt	return ret;
7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
763c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_flip_bufs(struct drm_device *dev, void *data,
764c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt			  struct drm_file *file_priv)
7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
766546b0974c39657017407c86fe79811100b60700dEric Anholt	int ret;
767546b0974c39657017407c86fe79811100b60700dEric Anholt
7688a4c47f346cc7a12d0897c05eb3cc1add26b487fZhao Yakui	DRM_DEBUG_DRIVER("%s\n", __func__);
7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
770546b0974c39657017407c86fe79811100b60700dEric Anholt	RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
772546b0974c39657017407c86fe79811100b60700dEric Anholt	mutex_lock(&dev->struct_mutex);
773546b0974c39657017407c86fe79811100b60700dEric Anholt	ret = i915_dispatch_flip(dev);
774546b0974c39657017407c86fe79811100b60700dEric Anholt	mutex_unlock(&dev->struct_mutex);
775546b0974c39657017407c86fe79811100b60700dEric Anholt
776546b0974c39657017407c86fe79811100b60700dEric Anholt	return ret;
7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
779c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_getparam(struct drm_device *dev, void *data,
780c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt			 struct drm_file *file_priv)
7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = dev->dev_private;
783c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	drm_i915_getparam_t *param = data;
7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int value;
7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!dev_priv) {
7873e684eae586a9b210a4517da5637a255b1ff5a92Márton Németh		DRM_ERROR("called with no initialization\n");
78820caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
791c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	switch (param->param) {
7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case I915_PARAM_IRQ_ACTIVE:
7930a3e67a4caac273a3bfc4ced3da364830b1ab241Jesse Barnes		value = dev->pdev->irq ? 1 : 0;
7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case I915_PARAM_ALLOW_BATCHBUFFER:
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		value = dev_priv->allow_batchbuffer ? 1 : 0;
7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
7980d6aa60b4ac9689b750e35cd66f5d7c053aff0f4Dave Airlie	case I915_PARAM_LAST_DISPATCH:
7990d6aa60b4ac9689b750e35cd66f5d7c053aff0f4Dave Airlie		value = READ_BREADCRUMB(dev_priv);
8000d6aa60b4ac9689b750e35cd66f5d7c053aff0f4Dave Airlie		break;
801ed4c9c4acf948b42b138747fcb8843ecb1a24ce4Kristian Høgsberg	case I915_PARAM_CHIPSET_ID:
802ed4c9c4acf948b42b138747fcb8843ecb1a24ce4Kristian Høgsberg		value = dev->pci_device;
803ed4c9c4acf948b42b138747fcb8843ecb1a24ce4Kristian Høgsberg		break;
804673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	case I915_PARAM_HAS_GEM:
805ac5c4e76180a74c7f922f6fa71ace0cef45fa433Dave Airlie		value = dev_priv->has_gem;
806673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		break;
8070f973f27888e4664b253ab2cf69c67c2eb80ab1bJesse Barnes	case I915_PARAM_NUM_FENCES_AVAIL:
8080f973f27888e4664b253ab2cf69c67c2eb80ab1bJesse Barnes		value = dev_priv->num_fence_regs - dev_priv->fence_reg_start;
8090f973f27888e4664b253ab2cf69c67c2eb80ab1bJesse Barnes		break;
8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
8118a4c47f346cc7a12d0897c05eb3cc1add26b487fZhao Yakui		DRM_DEBUG_DRIVER("Unknown parameter %d\n",
812be25ed9c5cc06e1d17aa97e41daf88f0b46143e6yakui_zhao					param->param);
81320caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
816c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) {
8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("DRM_COPY_TO_USER failed\n");
81820caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EFAULT;
8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
824c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_setparam(struct drm_device *dev, void *data,
825c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt			 struct drm_file *file_priv)
8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = dev->dev_private;
828c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	drm_i915_setparam_t *param = data;
8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!dev_priv) {
8313e684eae586a9b210a4517da5637a255b1ff5a92Márton Németh		DRM_ERROR("called with no initialization\n");
83220caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
835c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	switch (param->param) {
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case I915_SETPARAM_USE_MI_BATCHBUFFER_START:
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case I915_SETPARAM_TEX_LRU_LOG_GRANULARITY:
839c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt		dev_priv->tex_lru_log_granularity = param->value;
8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case I915_SETPARAM_ALLOW_BATCHBUFFER:
842c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt		dev_priv->allow_batchbuffer = param->value;
8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
8440f973f27888e4664b253ab2cf69c67c2eb80ab1bJesse Barnes	case I915_SETPARAM_NUM_USED_FENCES:
8450f973f27888e4664b253ab2cf69c67c2eb80ab1bJesse Barnes		if (param->value > dev_priv->num_fence_regs ||
8460f973f27888e4664b253ab2cf69c67c2eb80ab1bJesse Barnes		    param->value < 0)
8470f973f27888e4664b253ab2cf69c67c2eb80ab1bJesse Barnes			return -EINVAL;
8480f973f27888e4664b253ab2cf69c67c2eb80ab1bJesse Barnes		/* Userspace can use first N regs */
8490f973f27888e4664b253ab2cf69c67c2eb80ab1bJesse Barnes		dev_priv->fence_reg_start = param->value;
8500f973f27888e4664b253ab2cf69c67c2eb80ab1bJesse Barnes		break;
8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
8528a4c47f346cc7a12d0897c05eb3cc1add26b487fZhao Yakui		DRM_DEBUG_DRIVER("unknown parameter %d\n",
853be25ed9c5cc06e1d17aa97e41daf88f0b46143e6yakui_zhao					param->param);
85420caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
860c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_set_status_page(struct drm_device *dev, void *data,
861c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt				struct drm_file *file_priv)
862dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu{
863dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	drm_i915_private_t *dev_priv = dev->dev_private;
864c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	drm_i915_hws_addr_t *hws = data;
865b39d50e53b1bb27f6c29f88a697a4af78427dffdZhenyu Wang
866b39d50e53b1bb27f6c29f88a697a4af78427dffdZhenyu Wang	if (!I915_NEED_GFX_HWS(dev))
867b39d50e53b1bb27f6c29f88a697a4af78427dffdZhenyu Wang		return -EINVAL;
868dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu
869dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	if (!dev_priv) {
8703e684eae586a9b210a4517da5637a255b1ff5a92Márton Németh		DRM_ERROR("called with no initialization\n");
87120caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
872dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	}
873dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu
87479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
87579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		WARN(1, "tried to set status page when mode setting active\n");
87679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		return 0;
87779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	}
87879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
8798a4c47f346cc7a12d0897c05eb3cc1add26b487fZhao Yakui	DRM_DEBUG_DRIVER("set status page addr 0x%08x\n", (u32)hws->addr);
880c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt
881c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	dev_priv->status_gfx_addr = hws->addr & (0x1ffff<<12);
882dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu
8838b40958032fd236194de57d29be9cf2c1f2643eeEric Anholt	dev_priv->hws_map.offset = dev->agp->base + hws->addr;
884dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	dev_priv->hws_map.size = 4*1024;
885dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	dev_priv->hws_map.type = 0;
886dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	dev_priv->hws_map.flags = 0;
887dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	dev_priv->hws_map.mtrr = 0;
888dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu
889dd0910b3c71b253c08111110f0399b924a8d5853Dave Airlie	drm_core_ioremap_wc(&dev_priv->hws_map, dev);
890dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	if (dev_priv->hws_map.handle == NULL) {
891dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu		i915_dma_cleanup(dev);
892dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu		dev_priv->status_gfx_addr = 0;
893dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu		DRM_ERROR("can not ioremap virtual address for"
894dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu				" G33 hw status page\n");
89520caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -ENOMEM;
896dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	}
897dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	dev_priv->hw_status_page = dev_priv->hws_map.handle;
898dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu
899dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
900585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes	I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
9018a4c47f346cc7a12d0897c05eb3cc1add26b487fZhao Yakui	DRM_DEBUG_DRIVER("load hws HWS_PGA with gfx mem 0x%x\n",
902be25ed9c5cc06e1d17aa97e41daf88f0b46143e6yakui_zhao				dev_priv->status_gfx_addr);
9038a4c47f346cc7a12d0897c05eb3cc1add26b487fZhao Yakui	DRM_DEBUG_DRIVER("load hws at %p\n",
904be25ed9c5cc06e1d17aa97e41daf88f0b46143e6yakui_zhao				dev_priv->hw_status_page);
905dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	return 0;
906dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu}
907dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu
908ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airliestatic int i915_get_bridge_dev(struct drm_device *dev)
909ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie{
910ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie	struct drm_i915_private *dev_priv = dev->dev_private;
911ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie
912ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie	dev_priv->bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
913ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie	if (!dev_priv->bridge_dev) {
914ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie		DRM_ERROR("bridge device not found\n");
915ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie		return -1;
916ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie	}
917ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie	return 0;
918ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie}
919ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie
92079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes/**
92179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * i915_probe_agp - get AGP bootup configuration
92279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * @pdev: PCI device
92379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * @aperture_size: returns AGP aperture configured size
92479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * @preallocated_size: returns size of BIOS preallocated AGP space
92579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes *
92679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * Since Intel integrated graphics are UMA, the BIOS has to set aside
92779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * some RAM for the framebuffer at early boot.  This code figures out
92879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * how much was set aside so we can use it for our own purposes.
92979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes */
9302a34f5e6b61c7e8f3b6f25847bcda88511b0ead4Eric Anholtstatic int i915_probe_agp(struct drm_device *dev, uint32_t *aperture_size,
9318082400327d8d2ca54254b593644942bed0edd25Jesse Barnes			  uint32_t *preallocated_size,
9328082400327d8d2ca54254b593644942bed0edd25Jesse Barnes			  uint32_t *start)
93379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes{
934ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie	struct drm_i915_private *dev_priv = dev->dev_private;
93579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	u16 tmp = 0;
93679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	unsigned long overhead;
937241fa85b2bb655224357d713c251077dee3585ceEric Anholt	unsigned long stolen;
93879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
93979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	/* Get the fb aperture size and "stolen" memory amount. */
940ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie	pci_read_config_word(dev_priv->bridge_dev, INTEL_GMCH_CTRL, &tmp);
94179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
94279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	*aperture_size = 1024 * 1024;
94379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	*preallocated_size = 1024 * 1024;
94479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
94560fd99e3682c5acc74d58ed61dac93526d6976f7Eric Anholt	switch (dev->pdev->device) {
94679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	case PCI_DEVICE_ID_INTEL_82830_CGC:
94779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	case PCI_DEVICE_ID_INTEL_82845G_IG:
94879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	case PCI_DEVICE_ID_INTEL_82855GM_IG:
94979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	case PCI_DEVICE_ID_INTEL_82865_IG:
95079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		if ((tmp & INTEL_GMCH_MEM_MASK) == INTEL_GMCH_MEM_64M)
95179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes			*aperture_size *= 64;
95279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		else
95379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes			*aperture_size *= 128;
95479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		break;
95579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	default:
95679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		/* 9xx supports large sizes, just look at the length */
95760fd99e3682c5acc74d58ed61dac93526d6976f7Eric Anholt		*aperture_size = pci_resource_len(dev->pdev, 2);
95879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		break;
95979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	}
96079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
96179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	/*
96279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	 * Some of the preallocated space is taken by the GTT
96379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	 * and popup.  GTT is 1K per MB of aperture size, and popup is 4K.
96479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	 */
9652c07245fb8f7f0a282282e5a9747e46defdb2cc7Zhenyu Wang	if (IS_G4X(dev) || IS_IGD(dev) || IS_IGDNG(dev))
96660fd99e3682c5acc74d58ed61dac93526d6976f7Eric Anholt		overhead = 4096;
96760fd99e3682c5acc74d58ed61dac93526d6976f7Eric Anholt	else
96860fd99e3682c5acc74d58ed61dac93526d6976f7Eric Anholt		overhead = (*aperture_size / 1024) + 4096;
96960fd99e3682c5acc74d58ed61dac93526d6976f7Eric Anholt
970241fa85b2bb655224357d713c251077dee3585ceEric Anholt	switch (tmp & INTEL_GMCH_GMS_MASK) {
971241fa85b2bb655224357d713c251077dee3585ceEric Anholt	case INTEL_855_GMCH_GMS_DISABLED:
972241fa85b2bb655224357d713c251077dee3585ceEric Anholt		DRM_ERROR("video memory is disabled\n");
973241fa85b2bb655224357d713c251077dee3585ceEric Anholt		return -1;
97479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	case INTEL_855_GMCH_GMS_STOLEN_1M:
975241fa85b2bb655224357d713c251077dee3585ceEric Anholt		stolen = 1 * 1024 * 1024;
976241fa85b2bb655224357d713c251077dee3585ceEric Anholt		break;
97779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	case INTEL_855_GMCH_GMS_STOLEN_4M:
978241fa85b2bb655224357d713c251077dee3585ceEric Anholt		stolen = 4 * 1024 * 1024;
97979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		break;
98079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	case INTEL_855_GMCH_GMS_STOLEN_8M:
981241fa85b2bb655224357d713c251077dee3585ceEric Anholt		stolen = 8 * 1024 * 1024;
98279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		break;
98379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	case INTEL_855_GMCH_GMS_STOLEN_16M:
984241fa85b2bb655224357d713c251077dee3585ceEric Anholt		stolen = 16 * 1024 * 1024;
98579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		break;
98679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	case INTEL_855_GMCH_GMS_STOLEN_32M:
987241fa85b2bb655224357d713c251077dee3585ceEric Anholt		stolen = 32 * 1024 * 1024;
98879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		break;
98979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	case INTEL_915G_GMCH_GMS_STOLEN_48M:
990241fa85b2bb655224357d713c251077dee3585ceEric Anholt		stolen = 48 * 1024 * 1024;
99179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		break;
99279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	case INTEL_915G_GMCH_GMS_STOLEN_64M:
993241fa85b2bb655224357d713c251077dee3585ceEric Anholt		stolen = 64 * 1024 * 1024;
994241fa85b2bb655224357d713c251077dee3585ceEric Anholt		break;
995241fa85b2bb655224357d713c251077dee3585ceEric Anholt	case INTEL_GMCH_GMS_STOLEN_128M:
996241fa85b2bb655224357d713c251077dee3585ceEric Anholt		stolen = 128 * 1024 * 1024;
997241fa85b2bb655224357d713c251077dee3585ceEric Anholt		break;
998241fa85b2bb655224357d713c251077dee3585ceEric Anholt	case INTEL_GMCH_GMS_STOLEN_256M:
999241fa85b2bb655224357d713c251077dee3585ceEric Anholt		stolen = 256 * 1024 * 1024;
1000241fa85b2bb655224357d713c251077dee3585ceEric Anholt		break;
1001241fa85b2bb655224357d713c251077dee3585ceEric Anholt	case INTEL_GMCH_GMS_STOLEN_96M:
1002241fa85b2bb655224357d713c251077dee3585ceEric Anholt		stolen = 96 * 1024 * 1024;
1003241fa85b2bb655224357d713c251077dee3585ceEric Anholt		break;
1004241fa85b2bb655224357d713c251077dee3585ceEric Anholt	case INTEL_GMCH_GMS_STOLEN_160M:
1005241fa85b2bb655224357d713c251077dee3585ceEric Anholt		stolen = 160 * 1024 * 1024;
1006241fa85b2bb655224357d713c251077dee3585ceEric Anholt		break;
1007241fa85b2bb655224357d713c251077dee3585ceEric Anholt	case INTEL_GMCH_GMS_STOLEN_224M:
1008241fa85b2bb655224357d713c251077dee3585ceEric Anholt		stolen = 224 * 1024 * 1024;
1009241fa85b2bb655224357d713c251077dee3585ceEric Anholt		break;
1010241fa85b2bb655224357d713c251077dee3585ceEric Anholt	case INTEL_GMCH_GMS_STOLEN_352M:
1011241fa85b2bb655224357d713c251077dee3585ceEric Anholt		stolen = 352 * 1024 * 1024;
101279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		break;
101379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	default:
101479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		DRM_ERROR("unexpected GMCH_GMS value: 0x%02x\n",
1015241fa85b2bb655224357d713c251077dee3585ceEric Anholt			tmp & INTEL_GMCH_GMS_MASK);
101679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		return -1;
101779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	}
1018241fa85b2bb655224357d713c251077dee3585ceEric Anholt	*preallocated_size = stolen - overhead;
10198082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	*start = overhead;
102079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
102179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	return 0;
102279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes}
102379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
10248082400327d8d2ca54254b593644942bed0edd25Jesse Barnes#define PTE_ADDRESS_MASK		0xfffff000
10258082400327d8d2ca54254b593644942bed0edd25Jesse Barnes#define PTE_ADDRESS_MASK_HIGH		0x000000f0 /* i915+ */
10268082400327d8d2ca54254b593644942bed0edd25Jesse Barnes#define PTE_MAPPING_TYPE_UNCACHED	(0 << 1)
10278082400327d8d2ca54254b593644942bed0edd25Jesse Barnes#define PTE_MAPPING_TYPE_DCACHE		(1 << 1) /* i830 only */
10288082400327d8d2ca54254b593644942bed0edd25Jesse Barnes#define PTE_MAPPING_TYPE_CACHED		(3 << 1)
10298082400327d8d2ca54254b593644942bed0edd25Jesse Barnes#define PTE_MAPPING_TYPE_MASK		(3 << 1)
10308082400327d8d2ca54254b593644942bed0edd25Jesse Barnes#define PTE_VALID			(1 << 0)
10318082400327d8d2ca54254b593644942bed0edd25Jesse Barnes
10328082400327d8d2ca54254b593644942bed0edd25Jesse Barnes/**
10338082400327d8d2ca54254b593644942bed0edd25Jesse Barnes * i915_gtt_to_phys - take a GTT address and turn it into a physical one
10348082400327d8d2ca54254b593644942bed0edd25Jesse Barnes * @dev: drm device
10358082400327d8d2ca54254b593644942bed0edd25Jesse Barnes * @gtt_addr: address to translate
10368082400327d8d2ca54254b593644942bed0edd25Jesse Barnes *
10378082400327d8d2ca54254b593644942bed0edd25Jesse Barnes * Some chip functions require allocations from stolen space but need the
10388082400327d8d2ca54254b593644942bed0edd25Jesse Barnes * physical address of the memory in question.  We use this routine
10398082400327d8d2ca54254b593644942bed0edd25Jesse Barnes * to get a physical address suitable for register programming from a given
10408082400327d8d2ca54254b593644942bed0edd25Jesse Barnes * GTT address.
10418082400327d8d2ca54254b593644942bed0edd25Jesse Barnes */
10428082400327d8d2ca54254b593644942bed0edd25Jesse Barnesstatic unsigned long i915_gtt_to_phys(struct drm_device *dev,
10438082400327d8d2ca54254b593644942bed0edd25Jesse Barnes				      unsigned long gtt_addr)
10448082400327d8d2ca54254b593644942bed0edd25Jesse Barnes{
10458082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	unsigned long *gtt;
10468082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	unsigned long entry, phys;
10478082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	int gtt_bar = IS_I9XX(dev) ? 0 : 1;
10488082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	int gtt_offset, gtt_size;
10498082400327d8d2ca54254b593644942bed0edd25Jesse Barnes
10508082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	if (IS_I965G(dev)) {
10518082400327d8d2ca54254b593644942bed0edd25Jesse Barnes		if (IS_G4X(dev) || IS_IGDNG(dev)) {
10528082400327d8d2ca54254b593644942bed0edd25Jesse Barnes			gtt_offset = 2*1024*1024;
10538082400327d8d2ca54254b593644942bed0edd25Jesse Barnes			gtt_size = 2*1024*1024;
10548082400327d8d2ca54254b593644942bed0edd25Jesse Barnes		} else {
10558082400327d8d2ca54254b593644942bed0edd25Jesse Barnes			gtt_offset = 512*1024;
10568082400327d8d2ca54254b593644942bed0edd25Jesse Barnes			gtt_size = 512*1024;
10578082400327d8d2ca54254b593644942bed0edd25Jesse Barnes		}
10588082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	} else {
10598082400327d8d2ca54254b593644942bed0edd25Jesse Barnes		gtt_bar = 3;
10608082400327d8d2ca54254b593644942bed0edd25Jesse Barnes		gtt_offset = 0;
10618082400327d8d2ca54254b593644942bed0edd25Jesse Barnes		gtt_size = pci_resource_len(dev->pdev, gtt_bar);
10628082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	}
10638082400327d8d2ca54254b593644942bed0edd25Jesse Barnes
10648082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	gtt = ioremap_wc(pci_resource_start(dev->pdev, gtt_bar) + gtt_offset,
10658082400327d8d2ca54254b593644942bed0edd25Jesse Barnes			 gtt_size);
10668082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	if (!gtt) {
10678082400327d8d2ca54254b593644942bed0edd25Jesse Barnes		DRM_ERROR("ioremap of GTT failed\n");
10688082400327d8d2ca54254b593644942bed0edd25Jesse Barnes		return 0;
10698082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	}
10708082400327d8d2ca54254b593644942bed0edd25Jesse Barnes
10718082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	entry = *(volatile u32 *)(gtt + (gtt_addr / 1024));
10728082400327d8d2ca54254b593644942bed0edd25Jesse Barnes
10738082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	DRM_DEBUG("GTT addr: 0x%08lx, PTE: 0x%08lx\n", gtt_addr, entry);
10748082400327d8d2ca54254b593644942bed0edd25Jesse Barnes
10758082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	/* Mask out these reserved bits on this hardware. */
10768082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	if (!IS_I9XX(dev) || IS_I915G(dev) || IS_I915GM(dev) ||
10778082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	    IS_I945G(dev) || IS_I945GM(dev)) {
10788082400327d8d2ca54254b593644942bed0edd25Jesse Barnes		entry &= ~PTE_ADDRESS_MASK_HIGH;
10798082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	}
10808082400327d8d2ca54254b593644942bed0edd25Jesse Barnes
10818082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	/* If it's not a mapping type we know, then bail. */
10828082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	if ((entry & PTE_MAPPING_TYPE_MASK) != PTE_MAPPING_TYPE_UNCACHED &&
10838082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	    (entry & PTE_MAPPING_TYPE_MASK) != PTE_MAPPING_TYPE_CACHED)	{
10848082400327d8d2ca54254b593644942bed0edd25Jesse Barnes		iounmap(gtt);
10858082400327d8d2ca54254b593644942bed0edd25Jesse Barnes		return 0;
10868082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	}
10878082400327d8d2ca54254b593644942bed0edd25Jesse Barnes
10888082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	if (!(entry & PTE_VALID)) {
10898082400327d8d2ca54254b593644942bed0edd25Jesse Barnes		DRM_ERROR("bad GTT entry in stolen space\n");
10908082400327d8d2ca54254b593644942bed0edd25Jesse Barnes		iounmap(gtt);
10918082400327d8d2ca54254b593644942bed0edd25Jesse Barnes		return 0;
10928082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	}
10938082400327d8d2ca54254b593644942bed0edd25Jesse Barnes
10948082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	iounmap(gtt);
10958082400327d8d2ca54254b593644942bed0edd25Jesse Barnes
10968082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	phys =(entry & PTE_ADDRESS_MASK) |
10978082400327d8d2ca54254b593644942bed0edd25Jesse Barnes		((uint64_t)(entry & PTE_ADDRESS_MASK_HIGH) << (32 - 4));
10988082400327d8d2ca54254b593644942bed0edd25Jesse Barnes
10998082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	DRM_DEBUG("GTT addr: 0x%08lx, phys addr: 0x%08lx\n", gtt_addr, phys);
11008082400327d8d2ca54254b593644942bed0edd25Jesse Barnes
11018082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	return phys;
11028082400327d8d2ca54254b593644942bed0edd25Jesse Barnes}
11038082400327d8d2ca54254b593644942bed0edd25Jesse Barnes
11048082400327d8d2ca54254b593644942bed0edd25Jesse Barnesstatic void i915_warn_stolen(struct drm_device *dev)
11058082400327d8d2ca54254b593644942bed0edd25Jesse Barnes{
11068082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	DRM_ERROR("not enough stolen space for compressed buffer, disabling\n");
11078082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	DRM_ERROR("hint: you may be able to increase stolen memory size in the BIOS to avoid this\n");
11088082400327d8d2ca54254b593644942bed0edd25Jesse Barnes}
11098082400327d8d2ca54254b593644942bed0edd25Jesse Barnes
11108082400327d8d2ca54254b593644942bed0edd25Jesse Barnesstatic void i915_setup_compression(struct drm_device *dev, int size)
11118082400327d8d2ca54254b593644942bed0edd25Jesse Barnes{
11128082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	struct drm_i915_private *dev_priv = dev->dev_private;
11138082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	struct drm_mm_node *compressed_fb, *compressed_llb;
11148082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	unsigned long cfb_base, ll_base;
11158082400327d8d2ca54254b593644942bed0edd25Jesse Barnes
11168082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	/* Leave 1M for line length buffer & misc. */
11178082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	compressed_fb = drm_mm_search_free(&dev_priv->vram, size, 4096, 0);
11188082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	if (!compressed_fb) {
11198082400327d8d2ca54254b593644942bed0edd25Jesse Barnes		i915_warn_stolen(dev);
11208082400327d8d2ca54254b593644942bed0edd25Jesse Barnes		return;
11218082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	}
11228082400327d8d2ca54254b593644942bed0edd25Jesse Barnes
11238082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	compressed_fb = drm_mm_get_block(compressed_fb, size, 4096);
11248082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	if (!compressed_fb) {
11258082400327d8d2ca54254b593644942bed0edd25Jesse Barnes		i915_warn_stolen(dev);
11268082400327d8d2ca54254b593644942bed0edd25Jesse Barnes		return;
11278082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	}
11288082400327d8d2ca54254b593644942bed0edd25Jesse Barnes
112974dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes	cfb_base = i915_gtt_to_phys(dev, compressed_fb->start);
113074dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes	if (!cfb_base) {
113174dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes		DRM_ERROR("failed to get stolen phys addr, disabling FBC\n");
113274dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes		drm_mm_put_block(compressed_fb);
11338082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	}
11348082400327d8d2ca54254b593644942bed0edd25Jesse Barnes
113574dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes	if (!IS_GM45(dev)) {
113674dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes		compressed_llb = drm_mm_search_free(&dev_priv->vram, 4096,
113774dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes						    4096, 0);
113874dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes		if (!compressed_llb) {
113974dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes			i915_warn_stolen(dev);
114074dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes			return;
114174dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes		}
114274dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes
114374dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes		compressed_llb = drm_mm_get_block(compressed_llb, 4096, 4096);
114474dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes		if (!compressed_llb) {
114574dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes			i915_warn_stolen(dev);
114674dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes			return;
114774dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes		}
114874dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes
114974dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes		ll_base = i915_gtt_to_phys(dev, compressed_llb->start);
115074dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes		if (!ll_base) {
115174dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes			DRM_ERROR("failed to get stolen phys addr, disabling FBC\n");
115274dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes			drm_mm_put_block(compressed_fb);
115374dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes			drm_mm_put_block(compressed_llb);
115474dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes		}
11558082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	}
11568082400327d8d2ca54254b593644942bed0edd25Jesse Barnes
11578082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	dev_priv->cfb_size = size;
11588082400327d8d2ca54254b593644942bed0edd25Jesse Barnes
115974dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes	if (IS_GM45(dev)) {
116074dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes		g4x_disable_fbc(dev);
116174dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes		I915_WRITE(DPFC_CB_BASE, compressed_fb->start);
116274dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes	} else {
116374dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes		i8xx_disable_fbc(dev);
116474dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes		I915_WRITE(FBC_CFB_BASE, cfb_base);
116574dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes		I915_WRITE(FBC_LL_BASE, ll_base);
11668082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	}
11678082400327d8d2ca54254b593644942bed0edd25Jesse Barnes
11688082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	DRM_DEBUG("FBC base 0x%08lx, ll base 0x%08lx, size %dM\n", cfb_base,
11698082400327d8d2ca54254b593644942bed0edd25Jesse Barnes		  ll_base, size >> 20);
11708082400327d8d2ca54254b593644942bed0edd25Jesse Barnes}
11718082400327d8d2ca54254b593644942bed0edd25Jesse Barnes
117228d520433b6375740990ab99d69b0d0067fd656bDave Airlie/* true = enable decode, false = disable decoder */
117328d520433b6375740990ab99d69b0d0067fd656bDave Airliestatic unsigned int i915_vga_set_decode(void *cookie, bool state)
117428d520433b6375740990ab99d69b0d0067fd656bDave Airlie{
117528d520433b6375740990ab99d69b0d0067fd656bDave Airlie	struct drm_device *dev = cookie;
117628d520433b6375740990ab99d69b0d0067fd656bDave Airlie
117728d520433b6375740990ab99d69b0d0067fd656bDave Airlie	intel_modeset_vga_set_state(dev, state);
117828d520433b6375740990ab99d69b0d0067fd656bDave Airlie	if (state)
117928d520433b6375740990ab99d69b0d0067fd656bDave Airlie		return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM |
118028d520433b6375740990ab99d69b0d0067fd656bDave Airlie		       VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
118128d520433b6375740990ab99d69b0d0067fd656bDave Airlie	else
118228d520433b6375740990ab99d69b0d0067fd656bDave Airlie		return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
118328d520433b6375740990ab99d69b0d0067fd656bDave Airlie}
118428d520433b6375740990ab99d69b0d0067fd656bDave Airlie
11852a34f5e6b61c7e8f3b6f25847bcda88511b0ead4Eric Anholtstatic int i915_load_modeset_init(struct drm_device *dev,
11868082400327d8d2ca54254b593644942bed0edd25Jesse Barnes				  unsigned long prealloc_start,
11872a34f5e6b61c7e8f3b6f25847bcda88511b0ead4Eric Anholt				  unsigned long prealloc_size,
11882a34f5e6b61c7e8f3b6f25847bcda88511b0ead4Eric Anholt				  unsigned long agp_size)
118979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes{
119079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	struct drm_i915_private *dev_priv = dev->dev_private;
119179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	int fb_bar = IS_I9XX(dev) ? 2 : 0;
119279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	int ret = 0;
119379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
119479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	dev->mode_config.fb_base = drm_get_resource_start(dev, fb_bar) &
119579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		0xff000000;
119679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
11972906f0258770d3a9c4e65364df8acc904e148bbeJesse Barnes	if (IS_MOBILE(dev) || IS_I9XX(dev))
119879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		dev_priv->cursor_needs_physical = true;
119979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	else
120079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		dev_priv->cursor_needs_physical = false;
120179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
12022906f0258770d3a9c4e65364df8acc904e148bbeJesse Barnes	if (IS_I965G(dev) || IS_G33(dev))
12032906f0258770d3a9c4e65364df8acc904e148bbeJesse Barnes		dev_priv->cursor_needs_physical = false;
12042906f0258770d3a9c4e65364df8acc904e148bbeJesse Barnes
120579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	/* Basic memrange allocator for stolen space (aka vram) */
120679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	drm_mm_init(&dev_priv->vram, 0, prealloc_size);
12078082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	DRM_INFO("set up %ldM of stolen space\n", prealloc_size / (1024*1024));
120879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
120911ed50ec2a316928c2bacc1149bded86c6a96068Ben Gamari	/* We're off and running w/KMS */
121011ed50ec2a316928c2bacc1149bded86c6a96068Ben Gamari	dev_priv->mm.suspended = 0;
121179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
121213f4c435ebf2a7c150ffa714f3b23b8e4e8cb42fEric Anholt	/* Let GEM Manage from end of prealloc space to end of aperture.
121313f4c435ebf2a7c150ffa714f3b23b8e4e8cb42fEric Anholt	 *
121413f4c435ebf2a7c150ffa714f3b23b8e4e8cb42fEric Anholt	 * However, leave one page at the end still bound to the scratch page.
121513f4c435ebf2a7c150ffa714f3b23b8e4e8cb42fEric Anholt	 * There are a number of places where the hardware apparently
121613f4c435ebf2a7c150ffa714f3b23b8e4e8cb42fEric Anholt	 * prefetches past the end of the object, and we've seen multiple
121713f4c435ebf2a7c150ffa714f3b23b8e4e8cb42fEric Anholt	 * hangs with the GPU head pointer stuck in a batchbuffer bound
121813f4c435ebf2a7c150ffa714f3b23b8e4e8cb42fEric Anholt	 * at the last page of the aperture.  One page should be enough to
121913f4c435ebf2a7c150ffa714f3b23b8e4e8cb42fEric Anholt	 * keep any prefetching inside of the aperture.
122013f4c435ebf2a7c150ffa714f3b23b8e4e8cb42fEric Anholt	 */
122113f4c435ebf2a7c150ffa714f3b23b8e4e8cb42fEric Anholt	i915_gem_do_init(dev, prealloc_size, agp_size - 4096);
122279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
122311ed50ec2a316928c2bacc1149bded86c6a96068Ben Gamari	mutex_lock(&dev->struct_mutex);
122479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	ret = i915_gem_init_ringbuffer(dev);
122511ed50ec2a316928c2bacc1149bded86c6a96068Ben Gamari	mutex_unlock(&dev->struct_mutex);
122679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	if (ret)
1227b8da7de56ca0ad34726478a50d138a29a9ff76cbDave Airlie		goto out;
122879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
12298082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	/* Try to set up FBC with a reasonable compressed buffer size */
12309216d44dc13b5e858253f06d83ceea25a9b72f4fShaohua Li	if (I915_HAS_FBC(dev) && i915_powersave) {
12318082400327d8d2ca54254b593644942bed0edd25Jesse Barnes		int cfb_size;
12328082400327d8d2ca54254b593644942bed0edd25Jesse Barnes
12338082400327d8d2ca54254b593644942bed0edd25Jesse Barnes		/* Try to get an 8M buffer... */
12348082400327d8d2ca54254b593644942bed0edd25Jesse Barnes		if (prealloc_size > (9*1024*1024))
12358082400327d8d2ca54254b593644942bed0edd25Jesse Barnes			cfb_size = 8*1024*1024;
12368082400327d8d2ca54254b593644942bed0edd25Jesse Barnes		else /* fall back to 7/8 of the stolen space */
12378082400327d8d2ca54254b593644942bed0edd25Jesse Barnes			cfb_size = prealloc_size * 7 / 8;
12388082400327d8d2ca54254b593644942bed0edd25Jesse Barnes		i915_setup_compression(dev, cfb_size);
12398082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	}
12408082400327d8d2ca54254b593644942bed0edd25Jesse Barnes
124179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	/* Allow hardware batchbuffers unless told otherwise.
124279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	 */
124379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	dev_priv->allow_batchbuffer = 1;
124479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
124579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	ret = intel_init_bios(dev);
124679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	if (ret)
124779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		DRM_INFO("failed to find VBIOS tables\n");
124879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
124928d520433b6375740990ab99d69b0d0067fd656bDave Airlie	/* if we have > 1 VGA cards, then disable the radeon VGA resources */
125028d520433b6375740990ab99d69b0d0067fd656bDave Airlie	ret = vga_client_register(dev->pdev, dev, NULL, i915_vga_set_decode);
125128d520433b6375740990ab99d69b0d0067fd656bDave Airlie	if (ret)
125228d520433b6375740990ab99d69b0d0067fd656bDave Airlie		goto destroy_ringbuffer;
125328d520433b6375740990ab99d69b0d0067fd656bDave Airlie
125479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	ret = drm_irq_install(dev);
125579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	if (ret)
125679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		goto destroy_ringbuffer;
125779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
125879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	/* Always safe in the mode setting case. */
125979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	/* FIXME: do pre/post-mode set stuff in core KMS code */
126079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	dev->vblank_disable_allowed = 1;
126179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
126279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	/*
126379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	 * Initialize the hardware status page IRQ location.
126479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	 */
126579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
126679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	I915_WRITE(INSTPM, (1 << 5) | (1 << 21));
126779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
126879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	intel_modeset_init(dev);
126979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
12707a1fb5d06d3936c0982e2cf8b53b046244a9aad6Jesse Barnes	drm_helper_initial_config(dev);
127179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
127279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	return 0;
127379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
127479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnesdestroy_ringbuffer:
127579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	i915_gem_cleanup_ringbuffer(dev);
127679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnesout:
127779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	return ret;
127879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes}
127979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
12807c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlieint i915_master_create(struct drm_device *dev, struct drm_master *master)
12817c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie{
12827c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	struct drm_i915_master_private *master_priv;
12837c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
12849a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt	master_priv = kzalloc(sizeof(*master_priv), GFP_KERNEL);
12857c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	if (!master_priv)
12867c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie		return -ENOMEM;
12877c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
12887c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	master->driver_priv = master_priv;
12897c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	return 0;
12907c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie}
12917c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
12927c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlievoid i915_master_destroy(struct drm_device *dev, struct drm_master *master)
12937c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie{
12947c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	struct drm_i915_master_private *master_priv = master->driver_priv;
12957c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
12967c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	if (!master_priv)
12977c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie		return;
12987c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
12999a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt	kfree(master_priv);
13007c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
13017c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	master->driver_priv = NULL;
13027c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie}
13037c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
13047662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Listatic void i915_get_mem_freq(struct drm_device *dev)
13057662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li{
13067662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li	drm_i915_private_t *dev_priv = dev->dev_private;
13077662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li	u32 tmp;
13087662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li
13097662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li	if (!IS_IGD(dev))
13107662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li		return;
13117662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li
13127662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li	tmp = I915_READ(CLKCFG);
13137662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li
13147662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li	switch (tmp & CLKCFG_FSB_MASK) {
13157662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li	case CLKCFG_FSB_533:
13167662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li		dev_priv->fsb_freq = 533; /* 133*4 */
13177662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li		break;
13187662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li	case CLKCFG_FSB_800:
13197662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li		dev_priv->fsb_freq = 800; /* 200*4 */
13207662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li		break;
13217662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li	case CLKCFG_FSB_667:
13227662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li		dev_priv->fsb_freq =  667; /* 167*4 */
13237662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li		break;
13247662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li	case CLKCFG_FSB_400:
13257662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li		dev_priv->fsb_freq = 400; /* 100*4 */
13267662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li		break;
13277662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li	}
13287662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li
13297662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li	switch (tmp & CLKCFG_MEM_MASK) {
13307662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li	case CLKCFG_MEM_533:
13317662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li		dev_priv->mem_freq = 533;
13327662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li		break;
13337662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li	case CLKCFG_MEM_667:
13347662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li		dev_priv->mem_freq = 667;
13357662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li		break;
13367662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li	case CLKCFG_MEM_800:
13377662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li		dev_priv->mem_freq = 800;
13387662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li		break;
13397662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li	}
13407662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li}
13417662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li
134279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes/**
134379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * i915_driver_load - setup chip and create an initial config
134479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * @dev: DRM device
134579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * @flags: startup flags
134679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes *
134779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * The driver load routine has to do several things:
134879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes *   - drive output discovery via intel_modeset_init()
134979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes *   - initialize the memory manager
135079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes *   - allocate initial config memory
135179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes *   - setup the DRM framebuffer with the allocated memory
135279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes */
135384b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airlieint i915_driver_load(struct drm_device *dev, unsigned long flags)
135422eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie{
1355ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	struct drm_i915_private *dev_priv = dev->dev_private;
1356d883f7f1b75c8dcafa891f7b9e69c5a2f0ff6d66Benjamin Herrenschmidt	resource_size_t base, size;
1357ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	int ret = 0, mmio_bar = IS_I9XX(dev) ? 0 : 1;
13588082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	uint32_t agp_size, prealloc_size, prealloc_start;
1359ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
136022eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie	/* i915 has 4 more counters */
136122eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie	dev->counters += 4;
136222eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie	dev->types[6] = _DRM_STAT_IRQ;
136322eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie	dev->types[7] = _DRM_STAT_PRIMARY;
136422eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie	dev->types[8] = _DRM_STAT_SECONDARY;
136522eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie	dev->types[9] = _DRM_STAT_DMA;
136622eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie
13679a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt	dev_priv = kzalloc(sizeof(drm_i915_private_t), GFP_KERNEL);
1368ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	if (dev_priv == NULL)
1369ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes		return -ENOMEM;
1370ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
1371ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	dev->dev_private = (void *)dev_priv;
1372673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	dev_priv->dev = dev;
1373ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
1374ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	/* Add register map (needed for suspend/resume) */
1375ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	base = drm_get_resource_start(dev, mmio_bar);
1376ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	size = drm_get_resource_len(dev, mmio_bar);
1377ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
1378ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie	if (i915_get_bridge_dev(dev)) {
1379ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie		ret = -EIO;
1380ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie		goto free_priv;
1381ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie	}
1382ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie
13833043c60c485ad694392d3f71bd7ef9f5c5f7cfddEric Anholt	dev_priv->regs = ioremap(base, size);
138479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	if (!dev_priv->regs) {
138579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		DRM_ERROR("failed to map registers\n");
138679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		ret = -EIO;
1387ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie		goto put_bridge;
138879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	}
1389ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt
1390ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt        dev_priv->mm.gtt_mapping =
1391ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt		io_mapping_create_wc(dev->agp->base,
1392ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt				     dev->agp->agp_info.aper_size * 1024*1024);
13936644107d57a8fa82b47e4c55da4d9d91a612f29cVenkatesh Pallipadi	if (dev_priv->mm.gtt_mapping == NULL) {
13946644107d57a8fa82b47e4c55da4d9d91a612f29cVenkatesh Pallipadi		ret = -EIO;
13956644107d57a8fa82b47e4c55da4d9d91a612f29cVenkatesh Pallipadi		goto out_rmmap;
13966644107d57a8fa82b47e4c55da4d9d91a612f29cVenkatesh Pallipadi	}
13976644107d57a8fa82b47e4c55da4d9d91a612f29cVenkatesh Pallipadi
1398ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt	/* Set up a WC MTRR for non-PAT systems.  This is more common than
1399ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt	 * one would think, because the kernel disables PAT on first
1400ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt	 * generation Core chips because WC PAT gets overridden by a UC
1401ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt	 * MTRR if present.  Even if a UC MTRR isn't present.
1402ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt	 */
1403ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt	dev_priv->mm.gtt_mtrr = mtrr_add(dev->agp->base,
1404ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt					 dev->agp->agp_info.aper_size *
1405ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt					 1024 * 1024,
1406ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt					 MTRR_TYPE_WRCOMB, 1);
1407ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt	if (dev_priv->mm.gtt_mtrr < 0) {
1408040aefa263aa9cd7bd5df50586c35e1e15e77f84Eric Anholt		DRM_INFO("MTRR allocation failed.  Graphics "
1409ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt			 "performance may suffer.\n");
1410ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt	}
1411ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt
14128082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	ret = i915_probe_agp(dev, &agp_size, &prealloc_size, &prealloc_start);
14132a34f5e6b61c7e8f3b6f25847bcda88511b0ead4Eric Anholt	if (ret)
14142a34f5e6b61c7e8f3b6f25847bcda88511b0ead4Eric Anholt		goto out_iomapfree;
14152a34f5e6b61c7e8f3b6f25847bcda88511b0ead4Eric Anholt
14169c9fe1f841745184bbc5460c6f3909fded3b929bEric Anholt	dev_priv->wq = create_workqueue("i915");
14179c9fe1f841745184bbc5460c6f3909fded3b929bEric Anholt	if (dev_priv->wq == NULL) {
14189c9fe1f841745184bbc5460c6f3909fded3b929bEric Anholt		DRM_ERROR("Failed to create our workqueue.\n");
14199c9fe1f841745184bbc5460c6f3909fded3b929bEric Anholt		ret = -ENOMEM;
14209c9fe1f841745184bbc5460c6f3909fded3b929bEric Anholt		goto out_iomapfree;
14219c9fe1f841745184bbc5460c6f3909fded3b929bEric Anholt	}
14229c9fe1f841745184bbc5460c6f3909fded3b929bEric Anholt
1423ac5c4e76180a74c7f922f6fa71ace0cef45fa433Dave Airlie	/* enable GEM by default */
1424ac5c4e76180a74c7f922f6fa71ace0cef45fa433Dave Airlie	dev_priv->has_gem = 1;
1425ac5c4e76180a74c7f922f6fa71ace0cef45fa433Dave Airlie
14262a34f5e6b61c7e8f3b6f25847bcda88511b0ead4Eric Anholt	if (prealloc_size > agp_size * 3 / 4) {
14272a34f5e6b61c7e8f3b6f25847bcda88511b0ead4Eric Anholt		DRM_ERROR("Detected broken video BIOS with %d/%dkB of video "
14282a34f5e6b61c7e8f3b6f25847bcda88511b0ead4Eric Anholt			  "memory stolen.\n",
14292a34f5e6b61c7e8f3b6f25847bcda88511b0ead4Eric Anholt			  prealloc_size / 1024, agp_size / 1024);
14302a34f5e6b61c7e8f3b6f25847bcda88511b0ead4Eric Anholt		DRM_ERROR("Disabling GEM. (try reducing stolen memory or "
14312a34f5e6b61c7e8f3b6f25847bcda88511b0ead4Eric Anholt			  "updating the BIOS to fix).\n");
14322a34f5e6b61c7e8f3b6f25847bcda88511b0ead4Eric Anholt		dev_priv->has_gem = 0;
14332a34f5e6b61c7e8f3b6f25847bcda88511b0ead4Eric Anholt	}
14342a34f5e6b61c7e8f3b6f25847bcda88511b0ead4Eric Anholt
14359880b7a527ffbb52f65c2de0a8d4eea86e24775eJesse Barnes	dev->driver->get_vblank_counter = i915_get_vblank_counter;
143642c2798b35b95c471877133e19ccc3cab00e9b65Jesse Barnes	dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
1437036a4a7d9272582fc7370359515d807393e2f728Zhenyu Wang	if (IS_G4X(dev) || IS_IGDNG(dev)) {
143842c2798b35b95c471877133e19ccc3cab00e9b65Jesse Barnes		dev->max_vblank_count = 0xffffffff; /* full 32 bit counter */
14399880b7a527ffbb52f65c2de0a8d4eea86e24775eJesse Barnes		dev->driver->get_vblank_counter = gm45_get_vblank_counter;
144042c2798b35b95c471877133e19ccc3cab00e9b65Jesse Barnes	}
14419880b7a527ffbb52f65c2de0a8d4eea86e24775eJesse Barnes
1442673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	i915_gem_load(dev);
1443673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt
1444398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	/* Init HWS */
1445398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	if (!I915_NEED_GFX_HWS(dev)) {
1446398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard		ret = i915_init_phys_hws(dev);
1447398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard		if (ret != 0)
14489c9fe1f841745184bbc5460c6f3909fded3b929bEric Anholt			goto out_workqueue_free;
1449398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	}
1450ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt
14517662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li	i915_get_mem_freq(dev);
14527662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li
1453ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt	/* On the 945G/GM, the chipset reports the MSI capability on the
1454ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt	 * integrated graphics even though the support isn't actually there
1455ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt	 * according to the published specs.  It doesn't appear to function
1456ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt	 * correctly in testing on 945G.
1457ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt	 * This may be a side effect of MSI having been made available for PEG
1458ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt	 * and the registers being closely associated.
1459d1ed629f44b3a4108d5c445971535f05f441fce7Keith Packard	 *
1460d1ed629f44b3a4108d5c445971535f05f441fce7Keith Packard	 * According to chipset errata, on the 965GM, MSI interrupts may
1461b60678a75d44fa9d5969f79781bd856ad5858609Keith Packard	 * be lost or delayed, but we use them anyways to avoid
1462b60678a75d44fa9d5969f79781bd856ad5858609Keith Packard	 * stuck interrupts on some machines.
1463ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt	 */
1464b60678a75d44fa9d5969f79781bd856ad5858609Keith Packard	if (!IS_I945G(dev) && !IS_I945GM(dev))
1465d3e74d0237b102d34979015fbf6df02ca4413074Eric Anholt		pci_enable_msi(dev->pdev);
1466ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt
1467ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt	spin_lock_init(&dev_priv->user_irq_lock);
146863eeaf38251183ec2b1caee11e4a2c040cb5ce6cJesse Barnes	spin_lock_init(&dev_priv->error_lock);
146979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	dev_priv->user_irq_refcount = 0;
14709d34e5db07303c9609053e2e651aa6d1fc74e923Chris Wilson	dev_priv->trace_irq_seqno = 0;
1471ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt
147252440211dcdc52c0b757f8b34d122e11b12cdd50Keith Packard	ret = drm_vblank_init(dev, I915_NUM_PIPE);
147352440211dcdc52c0b757f8b34d122e11b12cdd50Keith Packard
147452440211dcdc52c0b757f8b34d122e11b12cdd50Keith Packard	if (ret) {
147552440211dcdc52c0b757f8b34d122e11b12cdd50Keith Packard		(void) i915_driver_unload(dev);
147652440211dcdc52c0b757f8b34d122e11b12cdd50Keith Packard		return ret;
147752440211dcdc52c0b757f8b34d122e11b12cdd50Keith Packard	}
147852440211dcdc52c0b757f8b34d122e11b12cdd50Keith Packard
147911ed50ec2a316928c2bacc1149bded86c6a96068Ben Gamari	/* Start out suspended */
148011ed50ec2a316928c2bacc1149bded86c6a96068Ben Gamari	dev_priv->mm.suspended = 1;
148111ed50ec2a316928c2bacc1149bded86c6a96068Ben Gamari
148279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
14838082400327d8d2ca54254b593644942bed0edd25Jesse Barnes		ret = i915_load_modeset_init(dev, prealloc_start,
14848082400327d8d2ca54254b593644942bed0edd25Jesse Barnes					     prealloc_size, agp_size);
148579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		if (ret < 0) {
148679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes			DRM_ERROR("failed to init modeset\n");
14879c9fe1f841745184bbc5460c6f3909fded3b929bEric Anholt			goto out_workqueue_free;
148879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		}
148979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	}
149079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
149174a365b3f354fafc537efa5867deb7a9fadbfe27Matthew Garrett	/* Must be done after probing outputs */
1492e170b030dcd6aed11dde2d124c09991ec771f529Zhenyu Wang	/* FIXME: verify on IGDNG */
1493e170b030dcd6aed11dde2d124c09991ec771f529Zhenyu Wang	if (!IS_IGDNG(dev))
1494e170b030dcd6aed11dde2d124c09991ec771f529Zhenyu Wang		intel_opregion_init(dev, 0);
149574a365b3f354fafc537efa5867deb7a9fadbfe27Matthew Garrett
1496f65d94211e2bcba17faf05a6a3809af0e4217767Ben Gamari	setup_timer(&dev_priv->hangcheck_timer, i915_hangcheck_elapsed,
1497f65d94211e2bcba17faf05a6a3809af0e4217767Ben Gamari		    (unsigned long) dev);
149879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	return 0;
149979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
15009c9fe1f841745184bbc5460c6f3909fded3b929bEric Anholtout_workqueue_free:
15019c9fe1f841745184bbc5460c6f3909fded3b929bEric Anholt	destroy_workqueue(dev_priv->wq);
15026644107d57a8fa82b47e4c55da4d9d91a612f29cVenkatesh Pallipadiout_iomapfree:
15036644107d57a8fa82b47e4c55da4d9d91a612f29cVenkatesh Pallipadi	io_mapping_free(dev_priv->mm.gtt_mapping);
150479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnesout_rmmap:
150579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	iounmap(dev_priv->regs);
1506ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlieput_bridge:
1507ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie	pci_dev_put(dev_priv->bridge_dev);
150879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnesfree_priv:
15099a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt	kfree(dev_priv);
1510ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	return ret;
1511ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes}
1512ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
1513ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnesint i915_driver_unload(struct drm_device *dev)
1514ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes{
1515ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	struct drm_i915_private *dev_priv = dev->dev_private;
1516ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
15179c9fe1f841745184bbc5460c6f3909fded3b929bEric Anholt	destroy_workqueue(dev_priv->wq);
1518f65d94211e2bcba17faf05a6a3809af0e4217767Ben Gamari	del_timer_sync(&dev_priv->hangcheck_timer);
15199c9fe1f841745184bbc5460c6f3909fded3b929bEric Anholt
1520ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt	io_mapping_free(dev_priv->mm.gtt_mapping);
1521ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt	if (dev_priv->mm.gtt_mtrr >= 0) {
1522ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt		mtrr_del(dev_priv->mm.gtt_mtrr, dev->agp->base,
1523ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt			 dev->agp->agp_info.aper_size * 1024 * 1024);
1524ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt		dev_priv->mm.gtt_mtrr = -1;
1525ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt	}
1526ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt
152779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
152879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		drm_irq_uninstall(dev);
152928d520433b6375740990ab99d69b0d0067fd656bDave Airlie		vga_client_register(dev->pdev, NULL, NULL, NULL);
153079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	}
153179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
1532ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt	if (dev->pdev->msi_enabled)
1533ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt		pci_disable_msi(dev->pdev);
1534ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt
15353043c60c485ad694392d3f71bd7ef9f5c5f7cfddEric Anholt	if (dev_priv->regs != NULL)
15363043c60c485ad694392d3f71bd7ef9f5c5f7cfddEric Anholt		iounmap(dev_priv->regs);
1537ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
1538e170b030dcd6aed11dde2d124c09991ec771f529Zhenyu Wang	if (!IS_IGDNG(dev))
1539e170b030dcd6aed11dde2d124c09991ec771f529Zhenyu Wang		intel_opregion_free(dev, 0);
15408ee1c3db9075cb3211352e737e0feb98fd733b20Matthew Garrett
154179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
154279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		intel_modeset_cleanup(dev);
154379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
154471acb5eb8d95b371f4cdd88a47f3c83c870d1c8fDave Airlie		i915_gem_free_all_phys_object(dev);
154571acb5eb8d95b371f4cdd88a47f3c83c870d1c8fDave Airlie
154679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		mutex_lock(&dev->struct_mutex);
154779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		i915_gem_cleanup_ringbuffer(dev);
154879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		mutex_unlock(&dev->struct_mutex);
154979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		drm_mm_takedown(&dev_priv->vram);
155079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		i915_gem_lastclose(dev);
155179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	}
155279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
1553ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie	pci_dev_put(dev_priv->bridge_dev);
15549a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt	kfree(dev->dev_private);
1555ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
155622eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie	return 0;
155722eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie}
155822eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie
1559673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholtint i915_driver_open(struct drm_device *dev, struct drm_file *file_priv)
1560673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt{
1561673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	struct drm_i915_file_private *i915_file_priv;
1562673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt
15638a4c47f346cc7a12d0897c05eb3cc1add26b487fZhao Yakui	DRM_DEBUG_DRIVER("\n");
1564673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	i915_file_priv = (struct drm_i915_file_private *)
15659a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt	    kmalloc(sizeof(*i915_file_priv), GFP_KERNEL);
1566673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt
1567673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	if (!i915_file_priv)
1568673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		return -ENOMEM;
1569673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt
1570673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	file_priv->driver_priv = i915_file_priv;
1571673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt
1572b962442e46a9340bdbc6711982c59ff0cc2b5afbEric Anholt	INIT_LIST_HEAD(&i915_file_priv->mm.request_list);
1573673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt
1574673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	return 0;
1575673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt}
1576673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt
157779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes/**
157879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * i915_driver_lastclose - clean up after all DRM clients have exited
157979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * @dev: DRM device
158079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes *
158179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * Take care of cleaning up after all DRM clients have exited.  In the
158279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * mode setting case, we want to restore the kernel's initial mode (just
158379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * in case the last client left us in a bad state).
158479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes *
158579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * Additionally, in the non-mode setting case, we'll tear down the AGP
158679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * and DMA structures, since the kernel won't be using them, and clea
158779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * up any GEM state.
158879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes */
158984b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airlievoid i915_driver_lastclose(struct drm_device * dev)
15901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1591ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	drm_i915_private_t *dev_priv = dev->dev_private;
1592ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
159379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	if (!dev_priv || drm_core_check_feature(dev, DRIVER_MODESET)) {
1594785b93ef8c309730c2de84ce9c229e40e2d01480Dave Airlie		drm_fb_helper_restore();
1595144a75fa1faa4a81530bded2e59872ef80d496b6Dave Airlie		return;
159679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	}
1597144a75fa1faa4a81530bded2e59872ef80d496b6Dave Airlie
1598673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	i915_gem_lastclose(dev);
1599673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt
1600ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	if (dev_priv->agp_heap)
1601b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		i915_mem_takedown(&(dev_priv->agp_heap));
1602ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
1603b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	i915_dma_cleanup(dev);
16041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
16051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16066c340eac0285f3d62406d2d902d0e96fbf2a5dc0Eric Anholtvoid i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv)
16071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1608ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	drm_i915_private_t *dev_priv = dev->dev_private;
1609b962442e46a9340bdbc6711982c59ff0cc2b5afbEric Anholt	i915_gem_release(dev, file_priv);
161079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	if (!drm_core_check_feature(dev, DRIVER_MODESET))
161179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		i915_mem_release(dev, file_priv, dev_priv->agp_heap);
16121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
16131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1614673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholtvoid i915_driver_postclose(struct drm_device *dev, struct drm_file *file_priv)
1615673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt{
1616673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	struct drm_i915_file_private *i915_file_priv = file_priv->driver_priv;
1617673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt
16189a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt	kfree(i915_file_priv);
1619673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt}
1620673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt
1621c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstruct drm_ioctl_desc i915_ioctls[] = {
1622c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_INIT, i915_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
1623c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_FLUSH, i915_flush_ioctl, DRM_AUTH),
1624c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_FLIP, i915_flip_bufs, DRM_AUTH),
1625c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_BATCHBUFFER, i915_batchbuffer, DRM_AUTH),
1626c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_IRQ_EMIT, i915_irq_emit, DRM_AUTH),
1627c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_IRQ_WAIT, i915_irq_wait, DRM_AUTH),
1628c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_GETPARAM, i915_getparam, DRM_AUTH),
1629c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_SETPARAM, i915_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
1630c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_ALLOC, i915_mem_alloc, DRM_AUTH),
1631c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_FREE, i915_mem_free, DRM_AUTH),
1632c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_INIT_HEAP, i915_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
1633c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_CMDBUFFER, i915_cmdbuffer, DRM_AUTH),
1634c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_DESTROY_HEAP,  i915_mem_destroy_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY ),
1635c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_SET_VBLANK_PIPE,  i915_vblank_pipe_set, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY ),
1636c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_GET_VBLANK_PIPE,  i915_vblank_pipe_get, DRM_AUTH ),
1637c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_VBLANK_SWAP, i915_vblank_swap, DRM_AUTH),
16384b40893918203ee1a1f6a114316c2a19c072e9bdMatthias Hopf	DRM_IOCTL_DEF(DRM_I915_HWS_ADDR, i915_set_status_page, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
16392bdf00b22154023ac312481583603f4724eb1401Dave Airlie	DRM_IOCTL_DEF(DRM_I915_GEM_INIT, i915_gem_init_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
1640673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	DRM_IOCTL_DEF(DRM_I915_GEM_EXECBUFFER, i915_gem_execbuffer, DRM_AUTH),
1641673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	DRM_IOCTL_DEF(DRM_I915_GEM_PIN, i915_gem_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY),
1642673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	DRM_IOCTL_DEF(DRM_I915_GEM_UNPIN, i915_gem_unpin_ioctl, DRM_AUTH|DRM_ROOT_ONLY),
1643673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	DRM_IOCTL_DEF(DRM_I915_GEM_BUSY, i915_gem_busy_ioctl, DRM_AUTH),
1644673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	DRM_IOCTL_DEF(DRM_I915_GEM_THROTTLE, i915_gem_throttle_ioctl, DRM_AUTH),
16452bdf00b22154023ac312481583603f4724eb1401Dave Airlie	DRM_IOCTL_DEF(DRM_I915_GEM_ENTERVT, i915_gem_entervt_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
16462bdf00b22154023ac312481583603f4724eb1401Dave Airlie	DRM_IOCTL_DEF(DRM_I915_GEM_LEAVEVT, i915_gem_leavevt_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
1647673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	DRM_IOCTL_DEF(DRM_I915_GEM_CREATE, i915_gem_create_ioctl, 0),
1648673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	DRM_IOCTL_DEF(DRM_I915_GEM_PREAD, i915_gem_pread_ioctl, 0),
1649673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	DRM_IOCTL_DEF(DRM_I915_GEM_PWRITE, i915_gem_pwrite_ioctl, 0),
1650673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	DRM_IOCTL_DEF(DRM_I915_GEM_MMAP, i915_gem_mmap_ioctl, 0),
1651de151cf67ce52ed2d88083daa5e60c7858947329Jesse Barnes	DRM_IOCTL_DEF(DRM_I915_GEM_MMAP_GTT, i915_gem_mmap_gtt_ioctl, 0),
1652673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	DRM_IOCTL_DEF(DRM_I915_GEM_SET_DOMAIN, i915_gem_set_domain_ioctl, 0),
1653673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	DRM_IOCTL_DEF(DRM_I915_GEM_SW_FINISH, i915_gem_sw_finish_ioctl, 0),
1654673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	DRM_IOCTL_DEF(DRM_I915_GEM_SET_TILING, i915_gem_set_tiling, 0),
1655673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	DRM_IOCTL_DEF(DRM_I915_GEM_GET_TILING, i915_gem_get_tiling, 0),
16565a125c3c79167e78ba44efef03af7090ef28eeafEric Anholt	DRM_IOCTL_DEF(DRM_I915_GEM_GET_APERTURE, i915_gem_get_aperture_ioctl, 0),
165708d7b3d1edff84bd673d9e9ab36b5aa62e1ba903Carl Worth	DRM_IOCTL_DEF(DRM_I915_GET_PIPE_FROM_CRTC_ID, intel_get_pipe_from_crtc_id, 0),
16583ef94daae7530b4ebcd2e5f48f1028cd2d2470baChris Wilson	DRM_IOCTL_DEF(DRM_I915_GEM_MADVISE, i915_gem_madvise_ioctl, 0),
1659c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie};
1660c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie
1661c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlieint i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
1662cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie
1663cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie/**
1664cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie * Determine if the device really is AGP or not.
1665cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie *
1666cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie * All Intel graphics chipsets are treated as AGP, even if they are really
1667cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie * PCI-e.
1668cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie *
1669cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie * \param dev   The device to be tested.
1670cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie *
1671cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie * \returns
1672cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie * A value of 1 is always retured to indictate every i9x5 is AGP.
1673cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie */
167484b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airlieint i915_driver_device_is_agp(struct drm_device * dev)
1675cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie{
1676cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie	return 1;
1677cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie}
1678