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