i915_dma.c revision 80a914dc05683ecfc98f9e1887fd6564846ffbec
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* i915_dma.c -- DMA support for the I915 -*- linux-c -*-
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
30d6aa60b4ac9689b750e35cd66f5d7c053aff0f4Dave Airlie/*
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * All Rights Reserved.
6bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie *
7bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * Permission is hereby granted, free of charge, to any person obtaining a
8bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * copy of this software and associated documentation files (the
9bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * "Software"), to deal in the Software without restriction, including
10bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * without limitation the rights to use, copy, modify, merge, publish,
11bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * distribute, sub license, and/or sell copies of the Software, and to
12bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * permit persons to whom the Software is furnished to do so, subject to
13bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * the following conditions:
14bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie *
15bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * The above copyright notice and this permission notice (including the
16bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * next paragraph) shall be included in all copies or substantial portions
17bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * of the Software.
18bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie *
19bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
23bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie *
270d6aa60b4ac9689b750e35cd66f5d7c053aff0f4Dave Airlie */
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "drmP.h"
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "drm.h"
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "i915_drm.h"
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "i915_drv.h"
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Really want an OS-independent resettable timer.  Would like to have
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * this loop run for (eg) 3 sec, but have the timer reset every time
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the head pointer changes, so that EBUSY only happens if the ring
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * actually stalls for (eg) 3 seconds.
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
3984b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airlieint i915_wait_ring(struct drm_device * dev, int n, const char *caller)
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = dev->dev_private;
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 last_head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < 10000; i++) {
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ring->head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ring->space = ring->head - (ring->tail + 8);
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ring->space < 0)
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ring->space += ring->Size;
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ring->space >= n)
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 0;
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ring->head != last_head)
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			i = 0;
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		last_head = ring->head;
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6220caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt	return -EBUSY;
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6584b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airlievoid i915_kernel_lost_context(struct drm_device * dev)
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = dev->dev_private;
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ring->head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ring->tail = I915_READ(LP_RING + RING_TAIL) & TAIL_ADDR;
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ring->space = ring->head - (ring->tail + 8);
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ring->space < 0)
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ring->space += ring->Size;
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ring->head == ring->tail)
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_priv->sarea_priv->perf_boxes |= I915_BOX_RING_EMPTY;
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8084b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airliestatic int i915_dma_cleanup(struct drm_device * dev)
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
82ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	drm_i915_private_t *dev_priv = dev->dev_private;
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Make sure interrupts are disabled here because the uninstall ioctl
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * may not have been called from userspace and after dev_private
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * is freed, it's too late.
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (dev->irq)
88b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		drm_irq_uninstall(dev);
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
90ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	if (dev_priv->ring.virtual_start) {
91ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes		drm_core_ioremapfree(&dev_priv->ring.map, dev);
92ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes		dev_priv->ring.virtual_start = 0;
93ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes		dev_priv->ring.map.handle = 0;
94ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes		dev_priv->ring.map.size = 0;
95ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	}
96dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu
97ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	if (dev_priv->status_page_dmah) {
98ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes		drm_pci_free(dev, dev_priv->status_page_dmah);
99ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes		dev_priv->status_page_dmah = NULL;
100ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes		/* Need to rewrite hardware status page */
101ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes		I915_WRITE(0x02080, 0x1ffff000);
102ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	}
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
104ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	if (dev_priv->status_gfx_addr) {
105ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes		dev_priv->status_gfx_addr = 0;
106ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes		drm_core_ioremapfree(&dev_priv->hws_map, dev);
107ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes		I915_WRITE(0x2080, 0x1ffff000);
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
113ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnesstatic int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
115ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	drm_i915_private_t *dev_priv = dev->dev_private;
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
117da509d7a02cb54938776439edc81f057e39f81e0Dave Airlie	dev_priv->sarea = drm_getsarea(dev);
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!dev_priv->sarea) {
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("can not find sarea!\n");
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		i915_dma_cleanup(dev);
12120caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset);
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!dev_priv->mmio_map) {
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		i915_dma_cleanup(dev);
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("can not find mmio map!\n");
12820caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_priv->sarea_priv = (drm_i915_sarea_t *)
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    ((u8 *) dev_priv->sarea->handle + init->sarea_priv_offset);
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_priv->ring.Start = init->ring_start;
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_priv->ring.End = init->ring_end;
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_priv->ring.Size = init->ring_size;
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_priv->ring.map.offset = init->ring_start;
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_priv->ring.map.size = init->ring_size;
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_priv->ring.map.type = 0;
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_priv->ring.map.flags = 0;
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_priv->ring.map.mtrr = 0;
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
145b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	drm_core_ioremap(&dev_priv->ring.map, dev);
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (dev_priv->ring.map.handle == NULL) {
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		i915_dma_cleanup(dev);
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("can not ioremap virtual address for"
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			  " ring buffer\n");
15120caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -ENOMEM;
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
156a6b54f3f5050c0cbc0c35dd48064846c6302706bMichel Dänzer	dev_priv->cpp = init->cpp;
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_priv->back_offset = init->back_offset;
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_priv->front_offset = init->front_offset;
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_priv->current_page = 0;
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* We are using separate values as placeholders for mechanisms for
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * private backbuffer/depthbuffer usage.
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_priv->use_mi_batchbuffer_start = 0;
16621f16289270447673a7263ccc0b22d562fb01ecbDave Airlie	if (IS_I965G(dev)) /* 965 doesn't support older method */
16721f16289270447673a7263ccc0b22d562fb01ecbDave Airlie		dev_priv->use_mi_batchbuffer_start = 1;
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Allow hardware batchbuffers unless told otherwise.
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_priv->allow_batchbuffer = 1;
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Program Hardware Status Page */
174b39d50e53b1bb27f6c29f88a697a4af78427dffdZhenyu Wang	if (!I915_NEED_GFX_HWS(dev)) {
175dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu		dev_priv->status_page_dmah =
176dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu			drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff);
177dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu
178dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu		if (!dev_priv->status_page_dmah) {
179dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu			i915_dma_cleanup(dev);
180dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu			DRM_ERROR("Can not allocate hardware status page\n");
18120caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt			return -ENOMEM;
182dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu		}
183dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu		dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr;
184dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu		dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
186dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu		memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
187dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu		I915_WRITE(0x02080, dev_priv->dma_status_page);
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DRM_DEBUG("Enabled hardware status page\n");
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19384b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airliestatic int i915_dma_resume(struct drm_device * dev)
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
197bf9d89295233ae2ba7b312c78ee5657307b09f4cHarvey Harrison	DRM_DEBUG("%s\n", __func__);
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!dev_priv->sarea) {
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("can not find sarea!\n");
20120caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!dev_priv->mmio_map) {
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("can not find mmio map!\n");
20620caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (dev_priv->ring.map.handle == NULL) {
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("can not ioremap virtual address for"
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			  " ring buffer\n");
21220caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -ENOMEM;
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Program Hardware Status Page */
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!dev_priv->hw_status_page) {
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("Can not find hardware status page\n");
21820caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
222dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	if (dev_priv->status_gfx_addr != 0)
223dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu		I915_WRITE(0x02080, dev_priv->status_gfx_addr);
224dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	else
225dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu		I915_WRITE(0x02080, dev_priv->dma_status_page);
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DRM_DEBUG("Enabled hardware status page\n");
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
231c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_dma_init(struct drm_device *dev, void *data,
232c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt			 struct drm_file *file_priv)
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
234c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	drm_i915_init_t *init = data;
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int retcode = 0;
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
237c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	switch (init->func) {
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case I915_INIT_DMA:
239ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes		retcode = i915_initialize(dev, init);
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case I915_CLEANUP_DMA:
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		retcode = i915_dma_cleanup(dev);
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case I915_RESUME_DMA:
2450d6aa60b4ac9689b750e35cd66f5d7c053aff0f4Dave Airlie		retcode = i915_dma_resume(dev);
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
24820caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		retcode = -EINVAL;
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return retcode;
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Implement basically the same security restrictions as hardware does
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * for MI_BATCH_NON_SECURE.  These can be made stricter at any time.
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Most of the calculations below involve calculating the size of a
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * particular instruction.  It's important to get the size right as
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * that tells us where the next instruction to check is.  Any illegal
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * instruction detected will be given a size of zero, which is a
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * signal to abort the rest of the buffer.
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int do_validate_cmd(int cmd)
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (((cmd >> 29) & 0x7)) {
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 0x0:
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch ((cmd >> 23) & 0x3f) {
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x0:
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 1;	/* MI_NOOP */
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x4:
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 1;	/* MI_FLUSH */
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		default:
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 0;	/* disallow everything else */
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 0x1:
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;	/* reserved */
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 0x2:
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (cmd & 0xff) + 2;	/* 2d commands */
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 0x3:
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (((cmd >> 24) & 0x1f) <= 0x18)
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 1;
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch ((cmd >> 24) & 0x1f) {
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x1c:
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 1;
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x1d:
289b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			switch ((cmd >> 16) & 0xff) {
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case 0x3:
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return (cmd & 0x1f) + 2;
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case 0x4:
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return (cmd & 0xf) + 2;
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			default:
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return (cmd & 0xffff) + 2;
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x1e:
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (cmd & (1 << 23))
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return (cmd & 0xffff) + 1;
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return 1;
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x1f:
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if ((cmd & (1 << 23)) == 0)	/* inline vertices */
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return (cmd & 0x1ffff) + 2;
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else if (cmd & (1 << 17))	/* indirect random */
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if ((cmd & 0xffff) == 0)
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					return 0;	/* unknown length, too hard */
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				else
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					return (((cmd & 0xffff) + 1) / 2) + 1;
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return 2;	/* indirect sequential */
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		default:
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 0;
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int validate_cmd(int cmd)
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret = do_validate_cmd(cmd);
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
326bc5f4523f772cc7629c5c5a46cf4f2a07a5500b8Dave Airlie/*	printk("validate_cmd( %x ): %d\n", cmd, ret); */
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33184b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airliestatic int i915_emit_cmds(struct drm_device * dev, int __user * buffer, int dwords)
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = dev->dev_private;
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	RING_LOCALS;
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
337de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	if ((dwords+1) * sizeof(int) >= dev_priv->ring.Size - 8)
33820caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
339de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie
340c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane	BEGIN_LP_RING((dwords+1)&~1);
341de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < dwords;) {
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		int cmd, sz;
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i], sizeof(cmd)))
34620caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt			return -EINVAL;
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((sz = validate_cmd(cmd)) == 0 || i + sz > dwords)
34920caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt			return -EINVAL;
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		OUT_RING(cmd);
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		while (++i, --sz) {
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i],
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							 sizeof(cmd))) {
35620caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt				return -EINVAL;
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			OUT_RING(cmd);
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
362de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	if (dwords & 1)
363de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie		OUT_RING(0);
364de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie
365de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	ADVANCE_LP_RING();
366de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37084b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airliestatic int i915_emit_box(struct drm_device * dev,
371c60ce623bd16137627009d05e311d877729f2ad6Dave Airlie			 struct drm_clip_rect __user * boxes,
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 int i, int DR1, int DR4)
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = dev->dev_private;
375c60ce623bd16137627009d05e311d877729f2ad6Dave Airlie	struct drm_clip_rect box;
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	RING_LOCALS;
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (DRM_COPY_FROM_USER_UNCHECKED(&box, &boxes[i], sizeof(box))) {
37920caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EFAULT;
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (box.y2 <= box.y1 || box.x2 <= box.x1 || box.y2 <= 0 || box.x2 <= 0) {
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("Bad box %d,%d..%d,%d\n",
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			  box.x1, box.y1, box.x2, box.y2);
38520caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
388c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane	if (IS_I965G(dev)) {
389c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		BEGIN_LP_RING(4);
390c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		OUT_RING(GFX_OP_DRAWRECT_INFO_I965);
391c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		OUT_RING((box.x1 & 0xffff) | (box.y1 << 16));
39278eca43d0391f59c3b1505bb7bd38ff45b650aabAndrew Morton		OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16));
393c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		OUT_RING(DR4);
394c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		ADVANCE_LP_RING();
395c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane	} else {
396c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		BEGIN_LP_RING(6);
397c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		OUT_RING(GFX_OP_DRAWRECT_INFO);
398c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		OUT_RING(DR1);
399c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		OUT_RING((box.x1 & 0xffff) | (box.y1 << 16));
400c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16));
401c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		OUT_RING(DR4);
402c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		OUT_RING(0);
403c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		ADVANCE_LP_RING();
404c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane	}
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
409c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane/* XXX: Emitting the counter should really be moved to part of the IRQ
410c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane * emit. For now, do it in both places:
411c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane */
412c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane
41384b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airliestatic void i915_emit_breadcrumb(struct drm_device *dev)
414de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie{
415de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	drm_i915_private_t *dev_priv = dev->dev_private;
416de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	RING_LOCALS;
417de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie
418af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	dev_priv->sarea_priv->last_enqueue = ++dev_priv->counter;
419c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane
420af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	if (dev_priv->counter > 0x7FFFFFFFUL)
421af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie		dev_priv->sarea_priv->last_enqueue = dev_priv->counter = 1;
422de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie
423de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	BEGIN_LP_RING(4);
424de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	OUT_RING(CMD_STORE_DWORD_IDX);
425de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	OUT_RING(20);
426de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	OUT_RING(dev_priv->counter);
427de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	OUT_RING(0);
428de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	ADVANCE_LP_RING();
429de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie}
430de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie
43184b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airliestatic int i915_dispatch_cmdbuffer(struct drm_device * dev,
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   drm_i915_cmdbuffer_t * cmd)
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int nbox = cmd->num_cliprects;
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i = 0, count, ret;
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (cmd->sz & 0x3) {
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("alignment");
43920caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	i915_kernel_lost_context(dev);
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	count = nbox ? nbox : 1;
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < count; i++) {
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (i < nbox) {
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ret = i915_emit_box(dev, cmd->cliprects, i,
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					    cmd->DR1, cmd->DR4);
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (ret)
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return ret;
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = i915_emit_cmds(dev, (int __user *)cmd->buf, cmd->sz / 4);
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ret)
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return ret;
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
459de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	i915_emit_breadcrumb(dev);
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
46384b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airliestatic int i915_dispatch_batchbuffer(struct drm_device * dev,
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     drm_i915_batchbuffer_t * batch)
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = dev->dev_private;
467c60ce623bd16137627009d05e311d877729f2ad6Dave Airlie	struct drm_clip_rect __user *boxes = batch->cliprects;
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int nbox = batch->num_cliprects;
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i = 0, count;
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	RING_LOCALS;
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((batch->start | batch->used) & 0x7) {
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("alignment");
47420caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	i915_kernel_lost_context(dev);
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	count = nbox ? nbox : 1;
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < count; i++) {
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (i < nbox) {
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			int ret = i915_emit_box(dev, boxes, i,
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						batch->DR1, batch->DR4);
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (ret)
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return ret;
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (dev_priv->use_mi_batchbuffer_start) {
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			BEGIN_LP_RING(2);
49121f16289270447673a7263ccc0b22d562fb01ecbDave Airlie			if (IS_I965G(dev)) {
49221f16289270447673a7263ccc0b22d562fb01ecbDave Airlie				OUT_RING(MI_BATCH_BUFFER_START | (2 << 6) | MI_BATCH_NON_SECURE_I965);
49321f16289270447673a7263ccc0b22d562fb01ecbDave Airlie				OUT_RING(batch->start);
49421f16289270447673a7263ccc0b22d562fb01ecbDave Airlie			} else {
49521f16289270447673a7263ccc0b22d562fb01ecbDave Airlie				OUT_RING(MI_BATCH_BUFFER_START | (2 << 6));
49621f16289270447673a7263ccc0b22d562fb01ecbDave Airlie				OUT_RING(batch->start | MI_BATCH_NON_SECURE);
49721f16289270447673a7263ccc0b22d562fb01ecbDave Airlie			}
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ADVANCE_LP_RING();
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			BEGIN_LP_RING(4);
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			OUT_RING(MI_BATCH_BUFFER);
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			OUT_RING(batch->start | MI_BATCH_NON_SECURE);
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			OUT_RING(batch->start + batch->used - 4);
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			OUT_RING(0);
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ADVANCE_LP_RING();
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
509de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	i915_emit_breadcrumb(dev);
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
514af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airliestatic int i915_dispatch_flip(struct drm_device * dev)
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = dev->dev_private;
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	RING_LOCALS;
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
519af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
52080a914dc05683ecfc98f9e1887fd6564846ffbecHarvey Harrison		  __func__,
521af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie		  dev_priv->current_page,
522af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie		  dev_priv->sarea_priv->pf_current_page);
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
524af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	i915_kernel_lost_context(dev);
525af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie
526af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	BEGIN_LP_RING(2);
527af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
528af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	OUT_RING(0);
529af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	ADVANCE_LP_RING();
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
531af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	BEGIN_LP_RING(6);
532af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP);
533af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	OUT_RING(0);
534af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	if (dev_priv->current_page == 0) {
535af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie		OUT_RING(dev_priv->back_offset);
536af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie		dev_priv->current_page = 1;
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
538af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie		OUT_RING(dev_priv->front_offset);
539af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie		dev_priv->current_page = 0;
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
541af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	OUT_RING(0);
542af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	ADVANCE_LP_RING();
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
544af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	BEGIN_LP_RING(2);
545af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP);
546af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	OUT_RING(0);
547af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	ADVANCE_LP_RING();
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
549af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	dev_priv->sarea_priv->last_enqueue = dev_priv->counter++;
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	BEGIN_LP_RING(4);
552af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	OUT_RING(CMD_STORE_DWORD_IDX);
553af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	OUT_RING(20);
554af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	OUT_RING(dev_priv->counter);
555af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	OUT_RING(0);
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ADVANCE_LP_RING();
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
558af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
559af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	return 0;
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
56284b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airliestatic int i915_quiescent(struct drm_device * dev)
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = dev->dev_private;
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	i915_kernel_lost_context(dev);
567bf9d89295233ae2ba7b312c78ee5657307b09f4cHarvey Harrison	return i915_wait_ring(dev, dev_priv->ring.Size - 8, __func__);
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
570c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_flush_ioctl(struct drm_device *dev, void *data,
571c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt			    struct drm_file *file_priv)
5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5736c340eac0285f3d62406d2d902d0e96fbf2a5dc0Eric Anholt	LOCK_TEST_WITH_RETURN(dev, file_priv);
5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return i915_quiescent(dev);
5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
578c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_batchbuffer(struct drm_device *dev, void *data,
579c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt			    struct drm_file *file_priv)
5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
582af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	u32 *hw_status = dev_priv->hw_status_page;
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    dev_priv->sarea_priv;
585c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	drm_i915_batchbuffer_t *batch = data;
5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret;
5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!dev_priv->allow_batchbuffer) {
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("Batchbuffer ioctl disabled\n");
59020caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DRM_DEBUG("i915 batchbuffer, start %x used %d cliprects %d\n",
594c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt		  batch->start, batch->used, batch->num_cliprects);
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5966c340eac0285f3d62406d2d902d0e96fbf2a5dc0Eric Anholt	LOCK_TEST_WITH_RETURN(dev, file_priv);
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
598c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	if (batch->num_cliprects && DRM_VERIFYAREA_READ(batch->cliprects,
599c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt						       batch->num_cliprects *
600c60ce623bd16137627009d05e311d877729f2ad6Dave Airlie						       sizeof(struct drm_clip_rect)))
60120caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EFAULT;
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
603c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	ret = i915_dispatch_batchbuffer(dev, batch);
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
605af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	sarea_priv->last_dispatch = (int)hw_status[5];
6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
609c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_cmdbuffer(struct drm_device *dev, void *data,
610c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt			  struct drm_file *file_priv)
6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
613af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	u32 *hw_status = dev_priv->hw_status_page;
6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    dev_priv->sarea_priv;
616c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	drm_i915_cmdbuffer_t *cmdbuf = data;
6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret;
6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DRM_DEBUG("i915 cmdbuffer, buf %p sz %d cliprects %d\n",
620c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt		  cmdbuf->buf, cmdbuf->sz, cmdbuf->num_cliprects);
6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6226c340eac0285f3d62406d2d902d0e96fbf2a5dc0Eric Anholt	LOCK_TEST_WITH_RETURN(dev, file_priv);
6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
624c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	if (cmdbuf->num_cliprects &&
625c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	    DRM_VERIFYAREA_READ(cmdbuf->cliprects,
626c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt				cmdbuf->num_cliprects *
627c60ce623bd16137627009d05e311d877729f2ad6Dave Airlie				sizeof(struct drm_clip_rect))) {
6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("Fault accessing cliprects\n");
62920caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EFAULT;
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
632c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	ret = i915_dispatch_cmdbuffer(dev, cmdbuf);
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ret) {
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("i915_dispatch_cmdbuffer failed\n");
6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return ret;
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
638af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	sarea_priv->last_dispatch = (int)hw_status[5];
6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
642c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_flip_bufs(struct drm_device *dev, void *data,
643c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt			  struct drm_file *file_priv)
6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
64580a914dc05683ecfc98f9e1887fd6564846ffbecHarvey Harrison	DRM_DEBUG("%s\n", __func__);
6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6476c340eac0285f3d62406d2d902d0e96fbf2a5dc0Eric Anholt	LOCK_TEST_WITH_RETURN(dev, file_priv);
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
649af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	return i915_dispatch_flip(dev);
6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
652c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_getparam(struct drm_device *dev, void *data,
653c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt			 struct drm_file *file_priv)
6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = dev->dev_private;
656c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	drm_i915_getparam_t *param = data;
6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int value;
6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!dev_priv) {
6603e684eae586a9b210a4517da5637a255b1ff5a92Márton Németh		DRM_ERROR("called with no initialization\n");
66120caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
664c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	switch (param->param) {
6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case I915_PARAM_IRQ_ACTIVE:
6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		value = dev->irq ? 1 : 0;
6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case I915_PARAM_ALLOW_BATCHBUFFER:
6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		value = dev_priv->allow_batchbuffer ? 1 : 0;
6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
6710d6aa60b4ac9689b750e35cd66f5d7c053aff0f4Dave Airlie	case I915_PARAM_LAST_DISPATCH:
6720d6aa60b4ac9689b750e35cd66f5d7c053aff0f4Dave Airlie		value = READ_BREADCRUMB(dev_priv);
6730d6aa60b4ac9689b750e35cd66f5d7c053aff0f4Dave Airlie		break;
6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
675c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt		DRM_ERROR("Unknown parameter %d\n", param->param);
67620caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
679c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) {
6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("DRM_COPY_TO_USER failed\n");
68120caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EFAULT;
6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
687c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_setparam(struct drm_device *dev, void *data,
688c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt			 struct drm_file *file_priv)
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = dev->dev_private;
691c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	drm_i915_setparam_t *param = data;
6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!dev_priv) {
6943e684eae586a9b210a4517da5637a255b1ff5a92Márton Németh		DRM_ERROR("called with no initialization\n");
69520caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
698c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	switch (param->param) {
6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case I915_SETPARAM_USE_MI_BATCHBUFFER_START:
70021f16289270447673a7263ccc0b22d562fb01ecbDave Airlie		if (!IS_I965G(dev))
701c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt			dev_priv->use_mi_batchbuffer_start = param->value;
7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case I915_SETPARAM_TEX_LRU_LOG_GRANULARITY:
704c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt		dev_priv->tex_lru_log_granularity = param->value;
7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case I915_SETPARAM_ALLOW_BATCHBUFFER:
707c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt		dev_priv->allow_batchbuffer = param->value;
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
710c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt		DRM_ERROR("unknown parameter %d\n", param->param);
71120caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
717c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_set_status_page(struct drm_device *dev, void *data,
718c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt				struct drm_file *file_priv)
719dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu{
720dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	drm_i915_private_t *dev_priv = dev->dev_private;
721c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	drm_i915_hws_addr_t *hws = data;
722b39d50e53b1bb27f6c29f88a697a4af78427dffdZhenyu Wang
723b39d50e53b1bb27f6c29f88a697a4af78427dffdZhenyu Wang	if (!I915_NEED_GFX_HWS(dev))
724b39d50e53b1bb27f6c29f88a697a4af78427dffdZhenyu Wang		return -EINVAL;
725dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu
726dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	if (!dev_priv) {
7273e684eae586a9b210a4517da5637a255b1ff5a92Márton Németh		DRM_ERROR("called with no initialization\n");
72820caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
729dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	}
730dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu
731c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	printk(KERN_DEBUG "set status page addr 0x%08x\n", (u32)hws->addr);
732c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt
733c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	dev_priv->status_gfx_addr = hws->addr & (0x1ffff<<12);
734dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu
7358b40958032fd236194de57d29be9cf2c1f2643eeEric Anholt	dev_priv->hws_map.offset = dev->agp->base + hws->addr;
736dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	dev_priv->hws_map.size = 4*1024;
737dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	dev_priv->hws_map.type = 0;
738dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	dev_priv->hws_map.flags = 0;
739dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	dev_priv->hws_map.mtrr = 0;
740dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu
741dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	drm_core_ioremap(&dev_priv->hws_map, dev);
742dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	if (dev_priv->hws_map.handle == NULL) {
743dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu		i915_dma_cleanup(dev);
744dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu		dev_priv->status_gfx_addr = 0;
745dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu		DRM_ERROR("can not ioremap virtual address for"
746dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu				" G33 hw status page\n");
74720caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -ENOMEM;
748dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	}
749dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	dev_priv->hw_status_page = dev_priv->hws_map.handle;
750dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu
751dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
752dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	I915_WRITE(0x02080, dev_priv->status_gfx_addr);
753dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	DRM_DEBUG("load hws 0x2080 with gfx mem 0x%x\n",
754dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu			dev_priv->status_gfx_addr);
755dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	DRM_DEBUG("load hws at %p\n", dev_priv->hw_status_page);
756dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	return 0;
757dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu}
758dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu
75984b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airlieint i915_driver_load(struct drm_device *dev, unsigned long flags)
76022eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie{
761ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	struct drm_i915_private *dev_priv = dev->dev_private;
762ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	unsigned long base, size;
763ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	int ret = 0, mmio_bar = IS_I9XX(dev) ? 0 : 1;
764ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
76522eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie	/* i915 has 4 more counters */
76622eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie	dev->counters += 4;
76722eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie	dev->types[6] = _DRM_STAT_IRQ;
76822eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie	dev->types[7] = _DRM_STAT_PRIMARY;
76922eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie	dev->types[8] = _DRM_STAT_SECONDARY;
77022eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie	dev->types[9] = _DRM_STAT_DMA;
77122eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie
772ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	dev_priv = drm_alloc(sizeof(drm_i915_private_t), DRM_MEM_DRIVER);
773ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	if (dev_priv == NULL)
774ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes		return -ENOMEM;
775ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
776ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	memset(dev_priv, 0, sizeof(drm_i915_private_t));
777ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
778ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	dev->dev_private = (void *)dev_priv;
779ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
780ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	/* Add register map (needed for suspend/resume) */
781ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	base = drm_get_resource_start(dev, mmio_bar);
782ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	size = drm_get_resource_len(dev, mmio_bar);
783ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
784e3236a1173222ca209d20bb29f6c1cd3499aa845Dave Airlie	ret = drm_addmap(dev, base, size, _DRM_REGISTERS,
785e3236a1173222ca209d20bb29f6c1cd3499aa845Dave Airlie			 _DRM_KERNEL | _DRM_DRIVER,
786ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes			 &dev_priv->mmio_map);
787ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	return ret;
788ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes}
789ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
790ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnesint i915_driver_unload(struct drm_device *dev)
791ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes{
792ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	struct drm_i915_private *dev_priv = dev->dev_private;
793ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
794ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	if (dev_priv->mmio_map)
795ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes		drm_rmmap(dev, dev_priv->mmio_map);
796ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
797ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	drm_free(dev->dev_private, sizeof(drm_i915_private_t),
798ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes		 DRM_MEM_DRIVER);
799ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
80022eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie	return 0;
80122eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie}
80222eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie
80384b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airlievoid i915_driver_lastclose(struct drm_device * dev)
8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
805ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	drm_i915_private_t *dev_priv = dev->dev_private;
806ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
807144a75fa1faa4a81530bded2e59872ef80d496b6Dave Airlie	if (!dev_priv)
808144a75fa1faa4a81530bded2e59872ef80d496b6Dave Airlie		return;
809144a75fa1faa4a81530bded2e59872ef80d496b6Dave Airlie
810ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	if (dev_priv->agp_heap)
811b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		i915_mem_takedown(&(dev_priv->agp_heap));
812ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
813b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	i915_dma_cleanup(dev);
8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8166c340eac0285f3d62406d2d902d0e96fbf2a5dc0Eric Anholtvoid i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv)
8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
818ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	drm_i915_private_t *dev_priv = dev->dev_private;
819ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	i915_mem_release(dev, file_priv, dev_priv->agp_heap);
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
822c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstruct drm_ioctl_desc i915_ioctls[] = {
823c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_INIT, i915_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
824c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_FLUSH, i915_flush_ioctl, DRM_AUTH),
825c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_FLIP, i915_flip_bufs, DRM_AUTH),
826c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_BATCHBUFFER, i915_batchbuffer, DRM_AUTH),
827c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_IRQ_EMIT, i915_irq_emit, DRM_AUTH),
828c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_IRQ_WAIT, i915_irq_wait, DRM_AUTH),
829c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_GETPARAM, i915_getparam, DRM_AUTH),
830c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_SETPARAM, i915_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
831c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_ALLOC, i915_mem_alloc, DRM_AUTH),
832c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_FREE, i915_mem_free, DRM_AUTH),
833c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_INIT_HEAP, i915_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
834c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_CMDBUFFER, i915_cmdbuffer, DRM_AUTH),
835c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_DESTROY_HEAP,  i915_mem_destroy_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY ),
836c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_SET_VBLANK_PIPE,  i915_vblank_pipe_set, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY ),
837c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_GET_VBLANK_PIPE,  i915_vblank_pipe_get, DRM_AUTH ),
838c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_VBLANK_SWAP, i915_vblank_swap, DRM_AUTH),
839c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	DRM_IOCTL_DEF(DRM_I915_HWS_ADDR, i915_set_status_page, DRM_AUTH),
840c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie};
841c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie
842c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlieint i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
843cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie
844cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie/**
845cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie * Determine if the device really is AGP or not.
846cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie *
847cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie * All Intel graphics chipsets are treated as AGP, even if they are really
848cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie * PCI-e.
849cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie *
850cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie * \param dev   The device to be tested.
851cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie *
852cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie * \returns
853cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie * A value of 1 is always retured to indictate every i9x5 is AGP.
854cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie */
85584b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airlieint i915_driver_device_is_agp(struct drm_device * dev)
856cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie{
857cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie	return 1;
858cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie}
859