i915_dma.c revision de151cf67ce52ed2d88083daa5e60c7858947329
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; 427c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drm_i915_ring_buffer_t *ring = &(dev_priv->ring); 44d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard u32 acthd_reg = IS_I965G(dev) ? ACTHD_I965 : ACTHD; 45d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard u32 last_acthd = I915_READ(acthd_reg); 46d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard u32 acthd; 47585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes u32 last_head = I915_READ(PRB0_HEAD) & HEAD_ADDR; 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 50d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard for (i = 0; i < 100000; i++) { 51585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR; 52d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard acthd = I915_READ(acthd_reg); 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ring->space = ring->head - (ring->tail + 8); 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ring->space < 0) 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ring->space += ring->Size; 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ring->space >= n) 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 597c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie if (master_priv->sarea_priv) 607c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT; 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ring->head != last_head) 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = 0; 64d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard if (acthd != last_acthd) 65d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard i = 0; 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds last_head = ring->head; 68d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard last_acthd = acthd; 69d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard msleep_interruptible(10); 70d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7320caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt return -EBUSY; 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 76398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard/** 77398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard * Sets up the hardware status page for devices that need a physical address 78398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard * in the register. 79398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard */ 803043c60c485ad694392d3f71bd7ef9f5c5f7cfddEric Anholtstatic int i915_init_phys_hws(struct drm_device *dev) 81398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard{ 82398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard drm_i915_private_t *dev_priv = dev->dev_private; 83398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard /* Program Hardware Status Page */ 84398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard dev_priv->status_page_dmah = 85398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff); 86398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard 87398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard if (!dev_priv->status_page_dmah) { 88398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard DRM_ERROR("Can not allocate hardware status page\n"); 89398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard return -ENOMEM; 90398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard } 91398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr; 92398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr; 93398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard 94398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard memset(dev_priv->hw_status_page, 0, PAGE_SIZE); 95398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard 96398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard I915_WRITE(HWS_PGA, dev_priv->dma_status_page); 97398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard DRM_DEBUG("Enabled hardware status page\n"); 98398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard return 0; 99398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard} 100398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard 101398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard/** 102398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard * Frees the hardware status page, whether it's a physical address or a virtual 103398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard * address set up by the X Server. 104398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard */ 1053043c60c485ad694392d3f71bd7ef9f5c5f7cfddEric Anholtstatic void i915_free_hws(struct drm_device *dev) 106398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard{ 107398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard drm_i915_private_t *dev_priv = dev->dev_private; 108398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard if (dev_priv->status_page_dmah) { 109398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard drm_pci_free(dev, dev_priv->status_page_dmah); 110398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard dev_priv->status_page_dmah = NULL; 111398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard } 112398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard 113398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard if (dev_priv->status_gfx_addr) { 114398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard dev_priv->status_gfx_addr = 0; 115398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard drm_core_ioremapfree(&dev_priv->hws_map, dev); 116398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard } 117398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard 118398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard /* Need to rewrite hardware status page */ 119398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard I915_WRITE(HWS_PGA, 0x1ffff000); 120398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard} 121398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard 12284b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airlievoid i915_kernel_lost_context(struct drm_device * dev) 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drm_i915_private_t *dev_priv = dev->dev_private; 1257c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie struct drm_i915_master_private *master_priv; 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drm_i915_ring_buffer_t *ring = &(dev_priv->ring); 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 128585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR; 129585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes ring->tail = I915_READ(PRB0_TAIL) & TAIL_ADDR; 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ring->space = ring->head - (ring->tail + 8); 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ring->space < 0) 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ring->space += ring->Size; 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1347c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie if (!dev->primary->master) 1357c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie return; 1367c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie 1377c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie master_priv = dev->primary->master->driver_priv; 1387c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie if (ring->head == ring->tail && master_priv->sarea_priv) 1397c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie master_priv->sarea_priv->perf_boxes |= I915_BOX_RING_EMPTY; 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14284b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airliestatic int i915_dma_cleanup(struct drm_device * dev) 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 144ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes drm_i915_private_t *dev_priv = dev->dev_private; 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Make sure interrupts are disabled here because the uninstall ioctl 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * may not have been called from userspace and after dev_private 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is freed, it's too late. 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 149ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt if (dev->irq_enabled) 150b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie drm_irq_uninstall(dev); 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 152ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes if (dev_priv->ring.virtual_start) { 153ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes drm_core_ioremapfree(&dev_priv->ring.map, dev); 1543043c60c485ad694392d3f71bd7ef9f5c5f7cfddEric Anholt dev_priv->ring.virtual_start = NULL; 1553043c60c485ad694392d3f71bd7ef9f5c5f7cfddEric Anholt dev_priv->ring.map.handle = NULL; 156ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes dev_priv->ring.map.size = 0; 157ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes } 158dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu 159398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard /* Clear the HWS virtual address at teardown */ 160398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard if (I915_NEED_GFX_HWS(dev)) 161398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard i915_free_hws(dev); 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 166ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnesstatic int i915_initialize(struct drm_device * dev, drm_i915_init_t * init) 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 168ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes drm_i915_private_t *dev_priv = dev->dev_private; 1697c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 171673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt if (init->ring_size != 0) { 172673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt if (dev_priv->ring.ring_obj != NULL) { 173673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt i915_dma_cleanup(dev); 174673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt DRM_ERROR("Client tried to initialize ringbuffer in " 175673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt "GEM mode\n"); 176673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt return -EINVAL; 177673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt } 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 179673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt dev_priv->ring.Size = init->ring_size; 180673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt dev_priv->ring.tail_mask = dev_priv->ring.Size - 1; 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 182673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt dev_priv->ring.map.offset = init->ring_start; 183673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt dev_priv->ring.map.size = init->ring_size; 184673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt dev_priv->ring.map.type = 0; 185673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt dev_priv->ring.map.flags = 0; 186673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt dev_priv->ring.map.mtrr = 0; 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 188673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt drm_core_ioremap(&dev_priv->ring.map, dev); 189673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt 190673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt if (dev_priv->ring.map.handle == NULL) { 191673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt i915_dma_cleanup(dev); 192673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt DRM_ERROR("can not ioremap virtual address for" 193673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt " ring buffer\n"); 194673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt return -ENOMEM; 195673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt } 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_priv->ring.virtual_start = dev_priv->ring.map.handle; 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 200a6b54f3f5050c0cbc0c35dd48064846c6302706bMichel Dänzer dev_priv->cpp = init->cpp; 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_priv->back_offset = init->back_offset; 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_priv->front_offset = init->front_offset; 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_priv->current_page = 0; 2047c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie if (master_priv->sarea_priv) 2057c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie master_priv->sarea_priv->pf_current_page = 0; 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Allow hardware batchbuffers unless told otherwise. 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_priv->allow_batchbuffer = 1; 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21484b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airliestatic int i915_dma_resume(struct drm_device * dev) 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 218bf9d89295233ae2ba7b312c78ee5657307b09f4cHarvey Harrison DRM_DEBUG("%s\n", __func__); 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev_priv->ring.map.handle == NULL) { 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DRM_ERROR("can not ioremap virtual address for" 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds " ring buffer\n"); 22320caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt return -ENOMEM; 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Program Hardware Status Page */ 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev_priv->hw_status_page) { 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DRM_ERROR("Can not find hardware status page\n"); 22920caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt return -EINVAL; 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page); 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 233dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu if (dev_priv->status_gfx_addr != 0) 234585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr); 235dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu else 236585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes I915_WRITE(HWS_PGA, dev_priv->dma_status_page); 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DRM_DEBUG("Enabled hardware status page\n"); 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 242c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_dma_init(struct drm_device *dev, void *data, 243c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt struct drm_file *file_priv) 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 245c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt drm_i915_init_t *init = data; 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retcode = 0; 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 248c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt switch (init->func) { 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case I915_INIT_DMA: 250ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes retcode = i915_initialize(dev, init); 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case I915_CLEANUP_DMA: 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retcode = i915_dma_cleanup(dev); 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case I915_RESUME_DMA: 2560d6aa60b4ac9689b750e35cd66f5d7c053aff0f4Dave Airlie retcode = i915_dma_resume(dev); 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 25920caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt retcode = -EINVAL; 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retcode; 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Implement basically the same security restrictions as hardware does 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * for MI_BATCH_NON_SECURE. These can be made stricter at any time. 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Most of the calculations below involve calculating the size of a 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * particular instruction. It's important to get the size right as 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * that tells us where the next instruction to check is. Any illegal 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * instruction detected will be given a size of zero, which is a 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * signal to abort the rest of the buffer. 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int do_validate_cmd(int cmd) 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (((cmd >> 29) & 0x7)) { 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x0: 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch ((cmd >> 23) & 0x3f) { 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x0: 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; /* MI_NOOP */ 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x4: 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; /* MI_FLUSH */ 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; /* disallow everything else */ 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x1: 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; /* reserved */ 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x2: 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (cmd & 0xff) + 2; /* 2d commands */ 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x3: 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (((cmd >> 24) & 0x1f) <= 0x18) 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch ((cmd >> 24) & 0x1f) { 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x1c: 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x1d: 300b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie switch ((cmd >> 16) & 0xff) { 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x3: 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (cmd & 0x1f) + 2; 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x4: 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (cmd & 0xf) + 2; 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (cmd & 0xffff) + 2; 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x1e: 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cmd & (1 << 23)) 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (cmd & 0xffff) + 1; 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x1f: 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((cmd & (1 << 23)) == 0) /* inline vertices */ 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (cmd & 0x1ffff) + 2; 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (cmd & (1 << 17)) /* indirect random */ 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((cmd & 0xffff) == 0) 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; /* unknown length, too hard */ 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (((cmd & 0xffff) + 1) / 2) + 1; 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 2; /* indirect sequential */ 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int validate_cmd(int cmd) 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = do_validate_cmd(cmd); 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 337bc5f4523f772cc7629c5c5a46cf4f2a07a5500b8Dave Airlie/* printk("validate_cmd( %x ): %d\n", cmd, ret); */ 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 34284b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airliestatic int i915_emit_cmds(struct drm_device * dev, int __user * buffer, int dwords) 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drm_i915_private_t *dev_priv = dev->dev_private; 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds RING_LOCALS; 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 348de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie if ((dwords+1) * sizeof(int) >= dev_priv->ring.Size - 8) 34920caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt return -EINVAL; 350de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie 351c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane BEGIN_LP_RING((dwords+1)&~1); 352de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < dwords;) { 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int cmd, sz; 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i], sizeof(cmd))) 35720caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt return -EINVAL; 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((sz = validate_cmd(cmd)) == 0 || i + sz > dwords) 36020caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt return -EINVAL; 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUT_RING(cmd); 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (++i, --sz) { 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i], 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof(cmd))) { 36720caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt return -EINVAL; 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUT_RING(cmd); 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 373de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie if (dwords & 1) 374de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie OUT_RING(0); 375de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie 376de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie ADVANCE_LP_RING(); 377de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 381673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholtint 382673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholti915_emit_box(struct drm_device *dev, 383673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt struct drm_clip_rect __user *boxes, 384673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt int i, int DR1, int DR4) 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drm_i915_private_t *dev_priv = dev->dev_private; 387c60ce623bd16137627009d05e311d877729f2ad6Dave Airlie struct drm_clip_rect box; 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds RING_LOCALS; 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (DRM_COPY_FROM_USER_UNCHECKED(&box, &boxes[i], sizeof(box))) { 39120caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt return -EFAULT; 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (box.y2 <= box.y1 || box.x2 <= box.x1 || box.y2 <= 0 || box.x2 <= 0) { 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DRM_ERROR("Bad box %d,%d..%d,%d\n", 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds box.x1, box.y1, box.x2, box.y2); 39720caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt return -EINVAL; 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 400c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane if (IS_I965G(dev)) { 401c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane BEGIN_LP_RING(4); 402c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane OUT_RING(GFX_OP_DRAWRECT_INFO_I965); 403c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane OUT_RING((box.x1 & 0xffff) | (box.y1 << 16)); 40478eca43d0391f59c3b1505bb7bd38ff45b650aabAndrew Morton OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16)); 405c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane OUT_RING(DR4); 406c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane ADVANCE_LP_RING(); 407c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane } else { 408c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane BEGIN_LP_RING(6); 409c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane OUT_RING(GFX_OP_DRAWRECT_INFO); 410c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane OUT_RING(DR1); 411c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane OUT_RING((box.x1 & 0xffff) | (box.y1 << 16)); 412c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16)); 413c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane OUT_RING(DR4); 414c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane OUT_RING(0); 415c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane ADVANCE_LP_RING(); 416c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane } 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 421c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane/* XXX: Emitting the counter should really be moved to part of the IRQ 422c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane * emit. For now, do it in both places: 423c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane */ 424c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane 42584b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airliestatic void i915_emit_breadcrumb(struct drm_device *dev) 426de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie{ 427de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie drm_i915_private_t *dev_priv = dev->dev_private; 4287c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; 429de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie RING_LOCALS; 430de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie 431c99b058f132388a666544d293392d52d1def6b12Kristian Høgsberg dev_priv->counter++; 432af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie if (dev_priv->counter > 0x7FFFFFFFUL) 433c99b058f132388a666544d293392d52d1def6b12Kristian Høgsberg dev_priv->counter = 0; 4347c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie if (master_priv->sarea_priv) 4357c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie master_priv->sarea_priv->last_enqueue = dev_priv->counter; 436de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie 437de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie BEGIN_LP_RING(4); 438585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes OUT_RING(MI_STORE_DWORD_INDEX); 4390baf823a10bd4131f70e9712d1f02de3c247f1dfKeith Packard OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT); 440de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie OUT_RING(dev_priv->counter); 441de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie OUT_RING(0); 442de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie ADVANCE_LP_RING(); 443de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie} 444de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie 44584b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airliestatic int i915_dispatch_cmdbuffer(struct drm_device * dev, 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drm_i915_cmdbuffer_t * cmd) 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int nbox = cmd->num_cliprects; 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i = 0, count, ret; 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cmd->sz & 0x3) { 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DRM_ERROR("alignment"); 45320caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt return -EINVAL; 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i915_kernel_lost_context(dev); 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count = nbox ? nbox : 1; 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < count; i++) { 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i < nbox) { 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = i915_emit_box(dev, cmd->cliprects, i, 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cmd->DR1, cmd->DR4); 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret) 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = i915_emit_cmds(dev, (int __user *)cmd->buf, cmd->sz / 4); 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret) 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 473de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie i915_emit_breadcrumb(dev); 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 47784b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airliestatic int i915_dispatch_batchbuffer(struct drm_device * dev, 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drm_i915_batchbuffer_t * batch) 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drm_i915_private_t *dev_priv = dev->dev_private; 481c60ce623bd16137627009d05e311d877729f2ad6Dave Airlie struct drm_clip_rect __user *boxes = batch->cliprects; 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int nbox = batch->num_cliprects; 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i = 0, count; 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds RING_LOCALS; 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((batch->start | batch->used) & 0x7) { 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DRM_ERROR("alignment"); 48820caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt return -EINVAL; 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i915_kernel_lost_context(dev); 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count = nbox ? nbox : 1; 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < count; i++) { 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i < nbox) { 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = i915_emit_box(dev, boxes, i, 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds batch->DR1, batch->DR4); 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret) 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5030790d5e148c0747499742a3c09ba5f1c07f9ed0dKeith Packard if (!IS_I830(dev) && !IS_845G(dev)) { 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BEGIN_LP_RING(2); 50521f16289270447673a7263ccc0b22d562fb01ecbDave Airlie if (IS_I965G(dev)) { 50621f16289270447673a7263ccc0b22d562fb01ecbDave Airlie OUT_RING(MI_BATCH_BUFFER_START | (2 << 6) | MI_BATCH_NON_SECURE_I965); 50721f16289270447673a7263ccc0b22d562fb01ecbDave Airlie OUT_RING(batch->start); 50821f16289270447673a7263ccc0b22d562fb01ecbDave Airlie } else { 50921f16289270447673a7263ccc0b22d562fb01ecbDave Airlie OUT_RING(MI_BATCH_BUFFER_START | (2 << 6)); 51021f16289270447673a7263ccc0b22d562fb01ecbDave Airlie OUT_RING(batch->start | MI_BATCH_NON_SECURE); 51121f16289270447673a7263ccc0b22d562fb01ecbDave Airlie } 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ADVANCE_LP_RING(); 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BEGIN_LP_RING(4); 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUT_RING(MI_BATCH_BUFFER); 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUT_RING(batch->start | MI_BATCH_NON_SECURE); 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUT_RING(batch->start + batch->used - 4); 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUT_RING(0); 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ADVANCE_LP_RING(); 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 523de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie i915_emit_breadcrumb(dev); 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 528af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airliestatic int i915_dispatch_flip(struct drm_device * dev) 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drm_i915_private_t *dev_priv = dev->dev_private; 5317c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie struct drm_i915_master_private *master_priv = 5327c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie dev->primary->master->driver_priv; 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds RING_LOCALS; 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5357c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie if (!master_priv->sarea_priv) 536c99b058f132388a666544d293392d52d1def6b12Kristian Høgsberg return -EINVAL; 537c99b058f132388a666544d293392d52d1def6b12Kristian Høgsberg 538af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n", 53980a914dc05683ecfc98f9e1887fd6564846ffbecHarvey Harrison __func__, 540af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie dev_priv->current_page, 5417c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie master_priv->sarea_priv->pf_current_page); 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 543af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie i915_kernel_lost_context(dev); 544af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie 545af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie BEGIN_LP_RING(2); 546585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes OUT_RING(MI_FLUSH | MI_READ_FLUSH); 547af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie OUT_RING(0); 548af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie ADVANCE_LP_RING(); 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 550af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie BEGIN_LP_RING(6); 551af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP); 552af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie OUT_RING(0); 553af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie if (dev_priv->current_page == 0) { 554af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie OUT_RING(dev_priv->back_offset); 555af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie dev_priv->current_page = 1; 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 557af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie OUT_RING(dev_priv->front_offset); 558af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie dev_priv->current_page = 0; 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 560af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie OUT_RING(0); 561af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie ADVANCE_LP_RING(); 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 563af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie BEGIN_LP_RING(2); 564af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP); 565af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie OUT_RING(0); 566af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie ADVANCE_LP_RING(); 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5687c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie master_priv->sarea_priv->last_enqueue = dev_priv->counter++; 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BEGIN_LP_RING(4); 571585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes OUT_RING(MI_STORE_DWORD_INDEX); 5720baf823a10bd4131f70e9712d1f02de3c247f1dfKeith Packard OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT); 573af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie OUT_RING(dev_priv->counter); 574af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie OUT_RING(0); 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ADVANCE_LP_RING(); 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5777c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie master_priv->sarea_priv->pf_current_page = dev_priv->current_page; 578af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie return 0; 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 58184b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airliestatic int i915_quiescent(struct drm_device * dev) 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drm_i915_private_t *dev_priv = dev->dev_private; 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i915_kernel_lost_context(dev); 586bf9d89295233ae2ba7b312c78ee5657307b09f4cHarvey Harrison return i915_wait_ring(dev, dev_priv->ring.Size - 8, __func__); 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 589c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_flush_ioctl(struct drm_device *dev, void *data, 590c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt struct drm_file *file_priv) 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 592546b0974c39657017407c86fe79811100b60700dEric Anholt int ret; 593546b0974c39657017407c86fe79811100b60700dEric Anholt 594546b0974c39657017407c86fe79811100b60700dEric Anholt RING_LOCK_TEST_WITH_RETURN(dev, file_priv); 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 596546b0974c39657017407c86fe79811100b60700dEric Anholt mutex_lock(&dev->struct_mutex); 597546b0974c39657017407c86fe79811100b60700dEric Anholt ret = i915_quiescent(dev); 598546b0974c39657017407c86fe79811100b60700dEric Anholt mutex_unlock(&dev->struct_mutex); 599546b0974c39657017407c86fe79811100b60700dEric Anholt 600546b0974c39657017407c86fe79811100b60700dEric Anholt return ret; 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 603c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_batchbuffer(struct drm_device *dev, void *data, 604c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt struct drm_file *file_priv) 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 6077c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *) 6097c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie master_priv->sarea_priv; 610c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt drm_i915_batchbuffer_t *batch = data; 6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev_priv->allow_batchbuffer) { 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DRM_ERROR("Batchbuffer ioctl disabled\n"); 61520caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt return -EINVAL; 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DRM_DEBUG("i915 batchbuffer, start %x used %d cliprects %d\n", 619c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt batch->start, batch->used, batch->num_cliprects); 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 621546b0974c39657017407c86fe79811100b60700dEric Anholt RING_LOCK_TEST_WITH_RETURN(dev, file_priv); 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 623c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt if (batch->num_cliprects && DRM_VERIFYAREA_READ(batch->cliprects, 624c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt batch->num_cliprects * 625c60ce623bd16137627009d05e311d877729f2ad6Dave Airlie sizeof(struct drm_clip_rect))) 62620caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt return -EFAULT; 6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 628546b0974c39657017407c86fe79811100b60700dEric Anholt mutex_lock(&dev->struct_mutex); 629c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt ret = i915_dispatch_batchbuffer(dev, batch); 630546b0974c39657017407c86fe79811100b60700dEric Anholt mutex_unlock(&dev->struct_mutex); 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 632c99b058f132388a666544d293392d52d1def6b12Kristian Høgsberg if (sarea_priv) 6330baf823a10bd4131f70e9712d1f02de3c247f1dfKeith Packard sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 637c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_cmdbuffer(struct drm_device *dev, void *data, 638c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt struct drm_file *file_priv) 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 6417c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *) 6437c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie master_priv->sarea_priv; 644c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt drm_i915_cmdbuffer_t *cmdbuf = data; 6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DRM_DEBUG("i915 cmdbuffer, buf %p sz %d cliprects %d\n", 648c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt cmdbuf->buf, cmdbuf->sz, cmdbuf->num_cliprects); 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 650546b0974c39657017407c86fe79811100b60700dEric Anholt RING_LOCK_TEST_WITH_RETURN(dev, file_priv); 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 652c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt if (cmdbuf->num_cliprects && 653c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt DRM_VERIFYAREA_READ(cmdbuf->cliprects, 654c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt cmdbuf->num_cliprects * 655c60ce623bd16137627009d05e311d877729f2ad6Dave Airlie sizeof(struct drm_clip_rect))) { 6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DRM_ERROR("Fault accessing cliprects\n"); 65720caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt return -EFAULT; 6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 660546b0974c39657017407c86fe79811100b60700dEric Anholt mutex_lock(&dev->struct_mutex); 661c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt ret = i915_dispatch_cmdbuffer(dev, cmdbuf); 662546b0974c39657017407c86fe79811100b60700dEric Anholt mutex_unlock(&dev->struct_mutex); 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret) { 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DRM_ERROR("i915_dispatch_cmdbuffer failed\n"); 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 668c99b058f132388a666544d293392d52d1def6b12Kristian Høgsberg if (sarea_priv) 6690baf823a10bd4131f70e9712d1f02de3c247f1dfKeith Packard sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 673c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_flip_bufs(struct drm_device *dev, void *data, 674c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt struct drm_file *file_priv) 6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 676546b0974c39657017407c86fe79811100b60700dEric Anholt int ret; 677546b0974c39657017407c86fe79811100b60700dEric Anholt 67880a914dc05683ecfc98f9e1887fd6564846ffbecHarvey Harrison DRM_DEBUG("%s\n", __func__); 6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 680546b0974c39657017407c86fe79811100b60700dEric Anholt RING_LOCK_TEST_WITH_RETURN(dev, file_priv); 6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 682546b0974c39657017407c86fe79811100b60700dEric Anholt mutex_lock(&dev->struct_mutex); 683546b0974c39657017407c86fe79811100b60700dEric Anholt ret = i915_dispatch_flip(dev); 684546b0974c39657017407c86fe79811100b60700dEric Anholt mutex_unlock(&dev->struct_mutex); 685546b0974c39657017407c86fe79811100b60700dEric Anholt 686546b0974c39657017407c86fe79811100b60700dEric Anholt return ret; 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 689c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_getparam(struct drm_device *dev, void *data, 690c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt struct drm_file *file_priv) 6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drm_i915_private_t *dev_priv = dev->dev_private; 693c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt drm_i915_getparam_t *param = data; 6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int value; 6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev_priv) { 6973e684eae586a9b210a4517da5637a255b1ff5a92Márton Németh DRM_ERROR("called with no initialization\n"); 69820caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt return -EINVAL; 6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 701c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt switch (param->param) { 7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case I915_PARAM_IRQ_ACTIVE: 7030a3e67a4caac273a3bfc4ced3da364830b1ab241Jesse Barnes value = dev->pdev->irq ? 1 : 0; 7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case I915_PARAM_ALLOW_BATCHBUFFER: 7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds value = dev_priv->allow_batchbuffer ? 1 : 0; 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7080d6aa60b4ac9689b750e35cd66f5d7c053aff0f4Dave Airlie case I915_PARAM_LAST_DISPATCH: 7090d6aa60b4ac9689b750e35cd66f5d7c053aff0f4Dave Airlie value = READ_BREADCRUMB(dev_priv); 7100d6aa60b4ac9689b750e35cd66f5d7c053aff0f4Dave Airlie break; 711ed4c9c4acf948b42b138747fcb8843ecb1a24ce4Kristian Høgsberg case I915_PARAM_CHIPSET_ID: 712ed4c9c4acf948b42b138747fcb8843ecb1a24ce4Kristian Høgsberg value = dev->pci_device; 713ed4c9c4acf948b42b138747fcb8843ecb1a24ce4Kristian Høgsberg break; 714673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt case I915_PARAM_HAS_GEM: 715ac5c4e76180a74c7f922f6fa71ace0cef45fa433Dave Airlie value = dev_priv->has_gem; 716673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt break; 7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 718c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt DRM_ERROR("Unknown parameter %d\n", param->param); 71920caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt return -EINVAL; 7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 722c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) { 7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DRM_ERROR("DRM_COPY_TO_USER failed\n"); 72420caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt return -EFAULT; 7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 730c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_setparam(struct drm_device *dev, void *data, 731c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt struct drm_file *file_priv) 7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drm_i915_private_t *dev_priv = dev->dev_private; 734c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt drm_i915_setparam_t *param = data; 7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev_priv) { 7373e684eae586a9b210a4517da5637a255b1ff5a92Márton Németh DRM_ERROR("called with no initialization\n"); 73820caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt return -EINVAL; 7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 741c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt switch (param->param) { 7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case I915_SETPARAM_USE_MI_BATCHBUFFER_START: 7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case I915_SETPARAM_TEX_LRU_LOG_GRANULARITY: 745c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt dev_priv->tex_lru_log_granularity = param->value; 7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case I915_SETPARAM_ALLOW_BATCHBUFFER: 748c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt dev_priv->allow_batchbuffer = param->value; 7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 751c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt DRM_ERROR("unknown parameter %d\n", param->param); 75220caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt return -EINVAL; 7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 758c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_set_status_page(struct drm_device *dev, void *data, 759c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt struct drm_file *file_priv) 760dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu{ 761dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu drm_i915_private_t *dev_priv = dev->dev_private; 762c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt drm_i915_hws_addr_t *hws = data; 763b39d50e53b1bb27f6c29f88a697a4af78427dffdZhenyu Wang 764b39d50e53b1bb27f6c29f88a697a4af78427dffdZhenyu Wang if (!I915_NEED_GFX_HWS(dev)) 765b39d50e53b1bb27f6c29f88a697a4af78427dffdZhenyu Wang return -EINVAL; 766dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu 767dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu if (!dev_priv) { 7683e684eae586a9b210a4517da5637a255b1ff5a92Márton Németh DRM_ERROR("called with no initialization\n"); 76920caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt return -EINVAL; 770dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu } 771dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu 772c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt printk(KERN_DEBUG "set status page addr 0x%08x\n", (u32)hws->addr); 773c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt 774c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt dev_priv->status_gfx_addr = hws->addr & (0x1ffff<<12); 775dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu 7768b40958032fd236194de57d29be9cf2c1f2643eeEric Anholt dev_priv->hws_map.offset = dev->agp->base + hws->addr; 777dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu dev_priv->hws_map.size = 4*1024; 778dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu dev_priv->hws_map.type = 0; 779dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu dev_priv->hws_map.flags = 0; 780dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu dev_priv->hws_map.mtrr = 0; 781dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu 782dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu drm_core_ioremap(&dev_priv->hws_map, dev); 783dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu if (dev_priv->hws_map.handle == NULL) { 784dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu i915_dma_cleanup(dev); 785dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu dev_priv->status_gfx_addr = 0; 786dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu DRM_ERROR("can not ioremap virtual address for" 787dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu " G33 hw status page\n"); 78820caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt return -ENOMEM; 789dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu } 790dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu dev_priv->hw_status_page = dev_priv->hws_map.handle; 791dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu 792dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu memset(dev_priv->hw_status_page, 0, PAGE_SIZE); 793585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr); 794585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes DRM_DEBUG("load hws HWS_PGA with gfx mem 0x%x\n", 795dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu dev_priv->status_gfx_addr); 796dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu DRM_DEBUG("load hws at %p\n", dev_priv->hw_status_page); 797dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu return 0; 798dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu} 799dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu 8007c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlieint i915_master_create(struct drm_device *dev, struct drm_master *master) 8017c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie{ 8027c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie struct drm_i915_master_private *master_priv; 8037c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie 8047c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie master_priv = drm_calloc(1, sizeof(*master_priv), DRM_MEM_DRIVER); 8057c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie if (!master_priv) 8067c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie return -ENOMEM; 8077c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie 8087c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie master->driver_priv = master_priv; 8097c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie return 0; 8107c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie} 8117c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie 8127c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlievoid i915_master_destroy(struct drm_device *dev, struct drm_master *master) 8137c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie{ 8147c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie struct drm_i915_master_private *master_priv = master->driver_priv; 8157c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie 8167c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie if (!master_priv) 8177c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie return; 8187c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie 8197c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie drm_free(master_priv, sizeof(*master_priv), DRM_MEM_DRIVER); 8207c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie 8217c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie master->driver_priv = NULL; 8227c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie} 8237c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie 82484b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airlieint i915_driver_load(struct drm_device *dev, unsigned long flags) 82522eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie{ 826ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes struct drm_i915_private *dev_priv = dev->dev_private; 827ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes unsigned long base, size; 828ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes int ret = 0, mmio_bar = IS_I9XX(dev) ? 0 : 1; 829ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes 83022eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie /* i915 has 4 more counters */ 83122eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie dev->counters += 4; 83222eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie dev->types[6] = _DRM_STAT_IRQ; 83322eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie dev->types[7] = _DRM_STAT_PRIMARY; 83422eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie dev->types[8] = _DRM_STAT_SECONDARY; 83522eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie dev->types[9] = _DRM_STAT_DMA; 83622eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie 837ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes dev_priv = drm_alloc(sizeof(drm_i915_private_t), DRM_MEM_DRIVER); 838ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes if (dev_priv == NULL) 839ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes return -ENOMEM; 840ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes 841ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes memset(dev_priv, 0, sizeof(drm_i915_private_t)); 842ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes 843ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes dev->dev_private = (void *)dev_priv; 844673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt dev_priv->dev = dev; 845ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes 846ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes /* Add register map (needed for suspend/resume) */ 847ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes base = drm_get_resource_start(dev, mmio_bar); 848ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes size = drm_get_resource_len(dev, mmio_bar); 849ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes 8503043c60c485ad694392d3f71bd7ef9f5c5f7cfddEric Anholt dev_priv->regs = ioremap(base, size); 851ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt 852ac5c4e76180a74c7f922f6fa71ace0cef45fa433Dave Airlie#ifdef CONFIG_HIGHMEM64G 853ac5c4e76180a74c7f922f6fa71ace0cef45fa433Dave Airlie /* don't enable GEM on PAE - needs agp + set_memory_* interface fixes */ 854ac5c4e76180a74c7f922f6fa71ace0cef45fa433Dave Airlie dev_priv->has_gem = 0; 855ac5c4e76180a74c7f922f6fa71ace0cef45fa433Dave Airlie#else 856ac5c4e76180a74c7f922f6fa71ace0cef45fa433Dave Airlie /* enable GEM by default */ 857ac5c4e76180a74c7f922f6fa71ace0cef45fa433Dave Airlie dev_priv->has_gem = 1; 858ac5c4e76180a74c7f922f6fa71ace0cef45fa433Dave Airlie#endif 859ac5c4e76180a74c7f922f6fa71ace0cef45fa433Dave Airlie 860673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt i915_gem_load(dev); 861673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt 862398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard /* Init HWS */ 863398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard if (!I915_NEED_GFX_HWS(dev)) { 864398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard ret = i915_init_phys_hws(dev); 865398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard if (ret != 0) 866398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard return ret; 867398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard } 868ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt 869ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt /* On the 945G/GM, the chipset reports the MSI capability on the 870ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt * integrated graphics even though the support isn't actually there 871ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt * according to the published specs. It doesn't appear to function 872ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt * correctly in testing on 945G. 873ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt * This may be a side effect of MSI having been made available for PEG 874ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt * and the registers being closely associated. 875d1ed629f44b3a4108d5c445971535f05f441fce7Keith Packard * 876d1ed629f44b3a4108d5c445971535f05f441fce7Keith Packard * According to chipset errata, on the 965GM, MSI interrupts may 877b60678a75d44fa9d5969f79781bd856ad5858609Keith Packard * be lost or delayed, but we use them anyways to avoid 878b60678a75d44fa9d5969f79781bd856ad5858609Keith Packard * stuck interrupts on some machines. 879ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt */ 880b60678a75d44fa9d5969f79781bd856ad5858609Keith Packard if (!IS_I945G(dev) && !IS_I945GM(dev)) 881d3e74d0237b102d34979015fbf6df02ca4413074Eric Anholt pci_enable_msi(dev->pdev); 882ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt 8838ee1c3db9075cb3211352e737e0feb98fd733b20Matthew Garrett intel_opregion_init(dev); 8848ee1c3db9075cb3211352e737e0feb98fd733b20Matthew Garrett 885ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt spin_lock_init(&dev_priv->user_irq_lock); 886ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt 88752440211dcdc52c0b757f8b34d122e11b12cdd50Keith Packard ret = drm_vblank_init(dev, I915_NUM_PIPE); 88852440211dcdc52c0b757f8b34d122e11b12cdd50Keith Packard 88952440211dcdc52c0b757f8b34d122e11b12cdd50Keith Packard if (ret) { 89052440211dcdc52c0b757f8b34d122e11b12cdd50Keith Packard (void) i915_driver_unload(dev); 89152440211dcdc52c0b757f8b34d122e11b12cdd50Keith Packard return ret; 89252440211dcdc52c0b757f8b34d122e11b12cdd50Keith Packard } 89352440211dcdc52c0b757f8b34d122e11b12cdd50Keith Packard 894ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes return ret; 895ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes} 896ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes 897ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnesint i915_driver_unload(struct drm_device *dev) 898ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes{ 899ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes struct drm_i915_private *dev_priv = dev->dev_private; 900ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes 901ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt if (dev->pdev->msi_enabled) 902ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt pci_disable_msi(dev->pdev); 903ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt 904398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard i915_free_hws(dev); 905398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard 9063043c60c485ad694392d3f71bd7ef9f5c5f7cfddEric Anholt if (dev_priv->regs != NULL) 9073043c60c485ad694392d3f71bd7ef9f5c5f7cfddEric Anholt iounmap(dev_priv->regs); 908ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes 9098ee1c3db9075cb3211352e737e0feb98fd733b20Matthew Garrett intel_opregion_free(dev); 9108ee1c3db9075cb3211352e737e0feb98fd733b20Matthew Garrett 911ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes drm_free(dev->dev_private, sizeof(drm_i915_private_t), 912ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes DRM_MEM_DRIVER); 913ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes 91422eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie return 0; 91522eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie} 91622eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie 917673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholtint i915_driver_open(struct drm_device *dev, struct drm_file *file_priv) 918673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt{ 919673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt struct drm_i915_file_private *i915_file_priv; 920673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt 921673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt DRM_DEBUG("\n"); 922673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt i915_file_priv = (struct drm_i915_file_private *) 923673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt drm_alloc(sizeof(*i915_file_priv), DRM_MEM_FILES); 924673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt 925673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt if (!i915_file_priv) 926673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt return -ENOMEM; 927673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt 928673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt file_priv->driver_priv = i915_file_priv; 929673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt 930673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt i915_file_priv->mm.last_gem_seqno = 0; 931673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt i915_file_priv->mm.last_gem_throttle_seqno = 0; 932673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt 933673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt return 0; 934673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt} 935673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt 93684b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airlievoid i915_driver_lastclose(struct drm_device * dev) 9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 938ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes drm_i915_private_t *dev_priv = dev->dev_private; 939ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes 940144a75fa1faa4a81530bded2e59872ef80d496b6Dave Airlie if (!dev_priv) 941144a75fa1faa4a81530bded2e59872ef80d496b6Dave Airlie return; 942144a75fa1faa4a81530bded2e59872ef80d496b6Dave Airlie 943673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt i915_gem_lastclose(dev); 944673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt 945ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes if (dev_priv->agp_heap) 946b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie i915_mem_takedown(&(dev_priv->agp_heap)); 947ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes 948b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie i915_dma_cleanup(dev); 9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9516c340eac0285f3d62406d2d902d0e96fbf2a5dc0Eric Anholtvoid i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv) 9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 953ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes drm_i915_private_t *dev_priv = dev->dev_private; 954ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes i915_mem_release(dev, file_priv, dev_priv->agp_heap); 9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 957673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholtvoid i915_driver_postclose(struct drm_device *dev, struct drm_file *file_priv) 958673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt{ 959673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt struct drm_i915_file_private *i915_file_priv = file_priv->driver_priv; 960673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt 961673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt drm_free(i915_file_priv, sizeof(*i915_file_priv), DRM_MEM_FILES); 962673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt} 963673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt 964c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstruct drm_ioctl_desc i915_ioctls[] = { 965c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt DRM_IOCTL_DEF(DRM_I915_INIT, i915_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 966c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt DRM_IOCTL_DEF(DRM_I915_FLUSH, i915_flush_ioctl, DRM_AUTH), 967c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt DRM_IOCTL_DEF(DRM_I915_FLIP, i915_flip_bufs, DRM_AUTH), 968c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt DRM_IOCTL_DEF(DRM_I915_BATCHBUFFER, i915_batchbuffer, DRM_AUTH), 969c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt DRM_IOCTL_DEF(DRM_I915_IRQ_EMIT, i915_irq_emit, DRM_AUTH), 970c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt DRM_IOCTL_DEF(DRM_I915_IRQ_WAIT, i915_irq_wait, DRM_AUTH), 971c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt DRM_IOCTL_DEF(DRM_I915_GETPARAM, i915_getparam, DRM_AUTH), 972c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt DRM_IOCTL_DEF(DRM_I915_SETPARAM, i915_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 973c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt DRM_IOCTL_DEF(DRM_I915_ALLOC, i915_mem_alloc, DRM_AUTH), 974c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt DRM_IOCTL_DEF(DRM_I915_FREE, i915_mem_free, DRM_AUTH), 975c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt DRM_IOCTL_DEF(DRM_I915_INIT_HEAP, i915_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 976c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt DRM_IOCTL_DEF(DRM_I915_CMDBUFFER, i915_cmdbuffer, DRM_AUTH), 977c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt DRM_IOCTL_DEF(DRM_I915_DESTROY_HEAP, i915_mem_destroy_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY ), 978c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt DRM_IOCTL_DEF(DRM_I915_SET_VBLANK_PIPE, i915_vblank_pipe_set, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY ), 979c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt DRM_IOCTL_DEF(DRM_I915_GET_VBLANK_PIPE, i915_vblank_pipe_get, DRM_AUTH ), 980c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt DRM_IOCTL_DEF(DRM_I915_VBLANK_SWAP, i915_vblank_swap, DRM_AUTH), 9814b40893918203ee1a1f6a114316c2a19c072e9bdMatthias Hopf DRM_IOCTL_DEF(DRM_I915_HWS_ADDR, i915_set_status_page, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 9822bdf00b22154023ac312481583603f4724eb1401Dave Airlie DRM_IOCTL_DEF(DRM_I915_GEM_INIT, i915_gem_init_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 983673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt DRM_IOCTL_DEF(DRM_I915_GEM_EXECBUFFER, i915_gem_execbuffer, DRM_AUTH), 984673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt DRM_IOCTL_DEF(DRM_I915_GEM_PIN, i915_gem_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY), 985673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt DRM_IOCTL_DEF(DRM_I915_GEM_UNPIN, i915_gem_unpin_ioctl, DRM_AUTH|DRM_ROOT_ONLY), 986673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt DRM_IOCTL_DEF(DRM_I915_GEM_BUSY, i915_gem_busy_ioctl, DRM_AUTH), 987673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt DRM_IOCTL_DEF(DRM_I915_GEM_THROTTLE, i915_gem_throttle_ioctl, DRM_AUTH), 9882bdf00b22154023ac312481583603f4724eb1401Dave Airlie DRM_IOCTL_DEF(DRM_I915_GEM_ENTERVT, i915_gem_entervt_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 9892bdf00b22154023ac312481583603f4724eb1401Dave Airlie DRM_IOCTL_DEF(DRM_I915_GEM_LEAVEVT, i915_gem_leavevt_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 990673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt DRM_IOCTL_DEF(DRM_I915_GEM_CREATE, i915_gem_create_ioctl, 0), 991673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt DRM_IOCTL_DEF(DRM_I915_GEM_PREAD, i915_gem_pread_ioctl, 0), 992673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt DRM_IOCTL_DEF(DRM_I915_GEM_PWRITE, i915_gem_pwrite_ioctl, 0), 993673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt DRM_IOCTL_DEF(DRM_I915_GEM_MMAP, i915_gem_mmap_ioctl, 0), 994de151cf67ce52ed2d88083daa5e60c7858947329Jesse Barnes DRM_IOCTL_DEF(DRM_I915_GEM_MMAP_GTT, i915_gem_mmap_gtt_ioctl, 0), 995673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt DRM_IOCTL_DEF(DRM_I915_GEM_SET_DOMAIN, i915_gem_set_domain_ioctl, 0), 996673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt DRM_IOCTL_DEF(DRM_I915_GEM_SW_FINISH, i915_gem_sw_finish_ioctl, 0), 997673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt DRM_IOCTL_DEF(DRM_I915_GEM_SET_TILING, i915_gem_set_tiling, 0), 998673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt DRM_IOCTL_DEF(DRM_I915_GEM_GET_TILING, i915_gem_get_tiling, 0), 9995a125c3c79167e78ba44efef03af7090ef28eeafEric Anholt DRM_IOCTL_DEF(DRM_I915_GEM_GET_APERTURE, i915_gem_get_aperture_ioctl, 0), 1000c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie}; 1001c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie 1002c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlieint i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); 1003cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie 1004cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie/** 1005cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie * Determine if the device really is AGP or not. 1006cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie * 1007cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie * All Intel graphics chipsets are treated as AGP, even if they are really 1008cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie * PCI-e. 1009cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie * 1010cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie * \param dev The device to be tested. 1011cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie * 1012cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie * \returns 1013cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie * A value of 1 is always retured to indictate every i9x5 is AGP. 1014cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie */ 101584b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airlieint i915_driver_device_is_agp(struct drm_device * dev) 1016cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie{ 1017cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie return 1; 1018cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie} 1019