summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorOwain Ainsworth <oga@cvs.openbsd.org>2010-05-25 17:15:50 +0000
committerOwain Ainsworth <oga@cvs.openbsd.org>2010-05-25 17:15:50 +0000
commit4937c85ccda075c7bb6de0539aaa7d576f0a6968 (patch)
tree6925b415bd06cb5ddb9c4ec4f770cfb18f4caea3 /sys/dev
parentcc4d50da37ea9825c7f663518e41b15a4b0f00df (diff)
Remove the DRI1 code paths from inteldrm as promised two weeks ago.
We no longer support these paths, only memory managed mode is now allowed.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/pci/drm/files.drm3
-rw-r--r--sys/dev/pci/drm/i915_dma.c694
-rw-r--r--sys/dev/pci/drm/i915_drv.c142
-rw-r--r--sys/dev/pci/drm/i915_drv.h87
-rw-r--r--sys/dev/pci/drm/i915_irq.c102
5 files changed, 131 insertions, 897 deletions
diff --git a/sys/dev/pci/drm/files.drm b/sys/dev/pci/drm/files.drm
index 6d42562f86d..f2624e45b6d 100644
--- a/sys/dev/pci/drm/files.drm
+++ b/sys/dev/pci/drm/files.drm
@@ -1,5 +1,5 @@
# $NetBSD: files.drm,v 1.2 2007/03/28 11:29:37 jmcneill Exp $
-# $OpenBSD: files.drm,v 1.19 2010/05/24 01:19:19 oga Exp $
+# $OpenBSD: files.drm,v 1.20 2010/05/25 17:15:49 oga Exp $
# direct rendering modules
define drmbase {}
@@ -17,7 +17,6 @@ file dev/pci/drm/drm_scatter.c drm
device inteldrm: drmbase
attach inteldrm at drmdev
file dev/pci/drm/i915_drv.c inteldrm
-file dev/pci/drm/i915_dma.c inteldrm
file dev/pci/drm/i915_irq.c inteldrm
device radeondrm: drmbase
diff --git a/sys/dev/pci/drm/i915_dma.c b/sys/dev/pci/drm/i915_dma.c
deleted file mode 100644
index bd11d01c46f..00000000000
--- a/sys/dev/pci/drm/i915_dma.c
+++ /dev/null
@@ -1,694 +0,0 @@
-/* i915_dma.c -- DMA support for the I915 -*- linux-c -*-
- */
-/*
- * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- */
-
-#include "drmP.h"
-#include "drm.h"
-#include "i915_drm.h"
-#include "i915_drv.h"
-
-int i915_dispatch_batchbuffer(struct drm_device *,
- drm_i915_batchbuffer_t *, struct drm_clip_rect *);
-int i915_dispatch_cmdbuffer(struct drm_device *,
- drm_i915_cmdbuffer_t *, struct drm_clip_rect *);
-
-/**
- * Sets up the hardware status page for devices that need a physical address
- * in the register.
- */
-int
-i915_init_phys_hws(drm_i915_private_t *dev_priv, bus_dma_tag_t dmat)
-{
- /* Program Hardware Status Page */
- if ((dev_priv->hws_dmamem = drm_dmamem_alloc(dmat, PAGE_SIZE,
- PAGE_SIZE, 1, PAGE_SIZE, 0, BUS_DMA_READ)) == NULL) {
- return (ENOMEM);
- }
-
- dev_priv->hw_status_page = dev_priv->hws_dmamem->kva;
-
- memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
-
- bus_dmamap_sync(dmat, dev_priv->hws_dmamem->map, 0, PAGE_SIZE,
- BUS_DMASYNC_PREREAD);
- I915_WRITE(HWS_PGA, dev_priv->hws_dmamem->map->dm_segs[0].ds_addr);
- DRM_DEBUG("Enabled hardware status page\n");
- return (0);
-}
-
-/**
- * Frees the hardware status page, whether it's a physical address of a virtual
- * address set up by the X Server.
- */
-void
-i915_free_hws(drm_i915_private_t *dev_priv, bus_dma_tag_t dmat)
-{
- if (dev_priv->hws_dmamem) {
- drm_dmamem_free(dmat, dev_priv->hws_dmamem);
- dev_priv->hws_dmamem = NULL;
- }
-
- if (dev_priv->status_gfx_addr) {
- dev_priv->status_gfx_addr = 0;
- bus_space_unmap(dev_priv->bst, dev_priv->hws_map.bsh, 4 * 1024);
- dev_priv->hws_map.bsh = NULL;
- }
-
- /* Need to rewrite hardware status page */
- I915_WRITE(HWS_PGA, 0x1ffff000);
- dev_priv->hw_status_page = NULL;
-}
-
-int
-i915_dma_cleanup(struct drm_device *dev)
-{
- drm_i915_private_t *dev_priv = dev->dev_private;
-
- if (dev_priv->ring.ring_obj == NULL && dev_priv->ring.bsh != NULL) {
- bus_space_unmap(dev_priv->bst, dev_priv->ring.bsh,
- dev_priv->ring.size);
- memset(&dev_priv->ring, 0, sizeof(dev_priv->ring));
- }
-
- /* Clear the HWS virtual address at teardown */
- if (dev_priv->hws_obj == NULL && I915_NEED_GFX_HWS(dev_priv))
- i915_free_hws(dev_priv, dev->dmat);
-
- return 0;
-}
-
-static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
-{
- drm_i915_private_t *dev_priv = dev->dev_private;
- int ret;
-
- dev_priv->sarea = drm_getsarea(dev);
- if (!dev_priv->sarea) {
- DRM_ERROR("can not find sarea!\n");
- i915_dma_cleanup(dev);
- return EINVAL;
- }
-
- if (init->sarea_priv_offset)
- dev_priv->sarea_priv = (drm_i915_sarea_t *)
- ((u8 *) dev_priv->sarea->handle + init->sarea_priv_offset);
- else {
- /* No sarea_priv for you! */
- dev_priv->sarea_priv = NULL;
- }
-
- if (init->ring_size != 0) {
- if (dev_priv->ring.ring_obj != NULL) {
- i915_dma_cleanup(dev);
- DRM_ERROR("Client tried to initialize ringbuffer in "
- "GEM mode\n");
- return (-EINVAL);
- }
- dev_priv->ring.size = init->ring_size;
-
- if ((ret = bus_space_map(dev_priv->bst, init->ring_start,
- init->ring_size, BUS_SPACE_MAP_PREFETCHABLE,
- &dev_priv->ring.bsh)) != 0) {
- DRM_INFO("can't map ringbuffer\n");
- i915_dma_cleanup(dev);
- return (ret);
- }
- }
-
- /* Allow hardware batchbuffers unless told otherwise.
- */
- dev_priv->allow_batchbuffer = 1;
-
- return 0;
-}
-
-static int i915_dma_resume(struct drm_device * dev)
-{
- drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-
- DRM_DEBUG("\n");
-
- if (!dev_priv->sarea) {
- DRM_ERROR("can not find sarea!\n");
- return EINVAL;
- }
-
- if (dev_priv->ring.bsh == NULL) {
- DRM_ERROR("dma_resume without mapped ring buffer\n");
- return ENOMEM;
- }
-
- /* Program Hardware Status Page */
- if (!dev_priv->hw_status_page) {
- DRM_ERROR("Can not find hardware status page\n");
- return EINVAL;
- }
- DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
-
- if (dev_priv->status_gfx_addr != 0)
- I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
- else {
- bus_dmamap_sync(dev->dmat, dev_priv->hws_dmamem->map, 0,
- PAGE_SIZE, BUS_DMASYNC_PREREAD);
- I915_WRITE(HWS_PGA,
- dev_priv->hws_dmamem->map->dm_segs[0].ds_addr);
- }
- DRM_DEBUG("Enabled hardware status page\n");
-
- return 0;
-}
-
-int i915_dma_init(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- drm_i915_init_t *init = data;
- int retcode = 0;
-
- switch (init->func) {
- case I915_INIT_DMA:
- retcode = i915_initialize(dev, init);
- break;
- case I915_CLEANUP_DMA:
- retcode = i915_dma_cleanup(dev);
- break;
- case I915_RESUME_DMA:
- retcode = i915_dma_resume(dev);
- break;
- default:
- retcode = EINVAL;
- break;
- }
-
- return retcode;
-}
-
-/* Implement basically the same security restrictions as hardware does
- * for MI_BATCH_NON_SECURE. These can be made stricter at any time.
- *
- * Most of the calculations below involve calculating the size of a
- * particular instruction. It's important to get the size right as
- * that tells us where the next instruction to check is. Any illegal
- * instruction detected will be given a size of zero, which is a
- * signal to abort the rest of the buffer.
- */
-static int validate_cmd(int cmd)
-{
- switch (((cmd >> 29) & 0x7)) {
- case 0x0:
- switch ((cmd >> 23) & 0x3f) {
- case 0x0:
- return 1; /* MI_NOOP */
- case 0x4:
- return 1; /* MI_FLUSH */
- default:
- return 0; /* disallow everything else */
- }
- break;
- case 0x1:
- return 0; /* reserved */
- case 0x2:
- return (cmd & 0xff) + 2; /* 2d commands */
- case 0x3:
- if (((cmd >> 24) & 0x1f) <= 0x18)
- return 1;
-
- switch ((cmd >> 24) & 0x1f) {
- case 0x1c:
- return 1;
- case 0x1d:
- switch ((cmd >> 16) & 0xff) {
- case 0x3:
- return (cmd & 0x1f) + 2;
- case 0x4:
- return (cmd & 0xf) + 2;
- default:
- return (cmd & 0xffff) + 2;
- }
- case 0x1e:
- if (cmd & (1 << 23))
- return (cmd & 0xffff) + 1;
- else
- return 1;
- case 0x1f:
- if ((cmd & (1 << 23)) == 0) /* inline vertices */
- return (cmd & 0x1ffff) + 2;
- else if (cmd & (1 << 17)) /* indirect random */
- if ((cmd & 0xffff) == 0)
- return 0; /* unknown length, too hard */
- else
- return (((cmd & 0xffff) + 1) / 2) + 1;
- else
- return 2; /* indirect sequential */
- default:
- return 0;
- }
- default:
- return 0;
- }
-
- return 0;
-}
-
-static int i915_emit_cmds(struct drm_device *dev, int __user *buffer,
- int dwords)
-{
- drm_i915_private_t *dev_priv = dev->dev_private;
- int i;
-
- if ((dwords + 1) * sizeof(u_int32_t) >= dev_priv->ring.size - 8)
- return EINVAL;
-
- BEGIN_LP_RING((dwords+1)&~1);
-
- for (i = 0; i < dwords;) {
- int cmd, sz;
-
- if (DRM_COPY_FROM_USER(&cmd, &buffer[i], sizeof(cmd)))
- return EINVAL;
-
- if ((sz = validate_cmd(cmd)) == 0 || i + sz > dwords)
- return EINVAL;
-
- OUT_RING(cmd);
-
- while (++i, --sz) {
- if (DRM_COPY_FROM_USER(&cmd, &buffer[i], sizeof(cmd))) {
- return EINVAL;
- }
- OUT_RING(cmd);
- }
- }
-
- if (dwords & 1)
- OUT_RING(0);
-
- ADVANCE_LP_RING();
-
- return 0;
-}
-
-
-/*
- * Emit a box for a cliprect. cliprect must already have been copied in and
- * sanity checked (the reason for this is so that everything can be checked
- * before any gpu state is modified.
- */
-void
-i915_emit_box(struct drm_device * dev, struct drm_clip_rect *box,
- int DR1, int DR4)
-{
- drm_i915_private_t *dev_priv = dev->dev_private;
-
- if (IS_I965G(dev_priv)) {
- BEGIN_LP_RING(4);
- OUT_RING(GFX_OP_DRAWRECT_INFO_I965);
- OUT_RING((box->x1 & 0xffff) | (box->y1 << 16));
- OUT_RING(((box->x2 - 1) & 0xffff) | ((box->y2 - 1) << 16));
- OUT_RING(DR4);
- ADVANCE_LP_RING();
- } else {
- BEGIN_LP_RING(6);
- OUT_RING(GFX_OP_DRAWRECT_INFO);
- OUT_RING(DR1);
- OUT_RING((box->x1 & 0xffff) | (box->y1 << 16));
- OUT_RING(((box->x2 - 1) & 0xffff) | ((box->y2 - 1) << 16));
- OUT_RING(DR4);
- OUT_RING(0);
- ADVANCE_LP_RING();
- }
-}
-
-/* XXX: Emitting the counter should really be moved to part of the IRQ
- * emit. For now, do it in both places:
- */
-
-void i915_emit_breadcrumb(struct drm_device *dev)
-{
- drm_i915_private_t *dev_priv = dev->dev_private;
-
- if (++dev_priv->counter > BREADCRUMB_MASK) {
- dev_priv->counter = 1;
- DRM_DEBUG("Breadcrumb counter wrapped around\n");
- }
-
- if (dev_priv->sarea_priv)
- dev_priv->sarea_priv->last_enqueue = dev_priv->counter;
-
- BEGIN_LP_RING(4);
- OUT_RING(MI_STORE_DWORD_INDEX);
- OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
- OUT_RING(dev_priv->counter);
- OUT_RING(0);
- ADVANCE_LP_RING();
-}
-
-int
-i915_dispatch_cmdbuffer(struct drm_device * dev,
- drm_i915_cmdbuffer_t *cmd, struct drm_clip_rect *cliprects)
-{
- struct drm_i915_private *dev_priv = dev->dev_private;
- int nbox = cmd->num_cliprects;
- int i = 0, count, ret;
-
- if (cmd->sz <= 0 || (cmd->sz & 0x3) != 0) {
- DRM_ERROR("negative value or incorrect alignment\n");
- return EINVAL;
- }
-
- inteldrm_update_ring(dev_priv);
-
- count = nbox ? nbox : 1;
-
- for (i = 0; i < count; i++) {
- if (i < nbox)
- i915_emit_box(dev, &cliprects[i], cmd->DR1, cmd->DR4);
-
- ret = i915_emit_cmds(dev, (int __user *)cmd->buf, cmd->sz / 4);
- if (ret)
- return ret;
- }
-
- i915_emit_breadcrumb(dev);
- return 0;
-}
-
-int
-i915_dispatch_batchbuffer(struct drm_device *dev,
- drm_i915_batchbuffer_t *batch, struct drm_clip_rect *cliprects)
-{
- drm_i915_private_t *dev_priv = dev->dev_private;
- int nbox = batch->num_cliprects, i = 0, count;
-
- if ((batch->start | batch->used) & 0x7) {
- DRM_ERROR("alignment\n");
- return EINVAL;
- }
-
- inteldrm_update_ring(dev_priv);
-
- /* XXX use gem code */
- count = nbox ? nbox : 1;
-
- for (i = 0; i < count; i++) {
- if (i < nbox)
- i915_emit_box(dev, &cliprects[i],
- batch->DR1, batch->DR4);
-
- if (!IS_I830(dev_priv) && !IS_845G(dev_priv)) {
- BEGIN_LP_RING(2);
- if (IS_I965G(dev_priv)) {
- OUT_RING(MI_BATCH_BUFFER_START | (2 << 6) | MI_BATCH_NON_SECURE_I965);
- OUT_RING(batch->start);
- } else {
- OUT_RING(MI_BATCH_BUFFER_START | (2 << 6));
- OUT_RING(batch->start | MI_BATCH_NON_SECURE);
- }
- ADVANCE_LP_RING();
- } else {
- BEGIN_LP_RING(4);
- OUT_RING(MI_BATCH_BUFFER);
- OUT_RING(batch->start | MI_BATCH_NON_SECURE);
- OUT_RING(batch->start + batch->used - 4);
- OUT_RING(0);
- ADVANCE_LP_RING();
- }
- }
-
- i915_emit_breadcrumb(dev);
-
- return 0;
-}
-
-int i915_flush_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- drm_i915_private_t *dev_priv = dev->dev_private;
- int ret;
-
- RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
-
- DRM_LOCK();
- inteldrm_update_ring(dev_priv);
- ret = inteldrm_wait_ring(dev_priv, dev_priv->ring.size - 8);
- DRM_UNLOCK();
-
- return (ret);
-}
-
-int i915_batchbuffer(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_i915_private *dev_priv =
- (drm_i915_private_t *)dev->dev_private;
- drm_i915_batchbuffer_t *batch = data;
- struct drm_clip_rect *cliprects = NULL;
- int i, ret;
-
- if (!dev_priv->allow_batchbuffer) {
- DRM_ERROR("Batchbuffer ioctl disabled\n");
- return EINVAL;
- }
-
- DRM_DEBUG("i915 batchbuffer, start %x used %d cliprects %d\n",
- batch->start, batch->used, batch->num_cliprects);
-
- RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
-
- if (batch->num_cliprects < 0)
- return (EINVAL);
-
- if (batch->num_cliprects) {
- if (SIZE_MAX / batch->num_cliprects < sizeof(*cliprects))
- return (EINVAL);
- cliprects = drm_alloc(batch->num_cliprects *
- sizeof(*cliprects));
- if (cliprects == NULL)
- return (ENOMEM);
-
- ret = copyin((void *)(uintptr_t)batch->cliprects, cliprects,
- sizeof(*cliprects) * batch->num_cliprects);
- if (ret != 0)
- goto free_cliprects;
-
- for (i = 0; i < batch->num_cliprects; i++) {
- if (cliprects[i].y2 <= cliprects[i].y1 ||
- cliprects[i].x2 <= cliprects[i].x1 ||
- cliprects[i].y2 <= 0 || cliprects[i].x2 <= 0) {
- ret = EINVAL;
- goto free_cliprects;
- }
- }
- }
-
- DRM_LOCK();
- ret = i915_dispatch_batchbuffer(dev, batch, cliprects);
- DRM_UNLOCK();
-
- if (dev_priv->sarea_priv != NULL)
- dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
-free_cliprects:
- drm_free(cliprects);
- return (ret);
-}
-
-int i915_cmdbuffer(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_i915_private *dev_priv =
- (drm_i915_private_t *)dev->dev_private;
- drm_i915_cmdbuffer_t *cmdbuf = data;
- struct drm_clip_rect *cliprects = NULL;
- int i, ret;
-
- DRM_DEBUG("i915 cmdbuffer, buf %p sz %d cliprects %d\n",
- cmdbuf->buf, cmdbuf->sz, cmdbuf->num_cliprects);
-
- RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
-
- if (cmdbuf->num_cliprects < 0)
- return EINVAL;
-
- if (cmdbuf->num_cliprects) {
- if (SIZE_MAX / cmdbuf->num_cliprects < sizeof(*cliprects))
- return (EINVAL);
- cliprects = drm_alloc(cmdbuf->num_cliprects *
- sizeof(*cliprects));
- if (cliprects == NULL)
- return (ENOMEM);
-
- ret = copyin((void *)(uintptr_t)cmdbuf->cliprects, cliprects,
- sizeof(*cliprects) * cmdbuf->num_cliprects);
- if (ret != 0)
- goto free_cliprects;
-
- for (i = 0; i < cmdbuf->num_cliprects; i++) {
- if (cliprects[i].y2 <= cliprects[i].y1 ||
- cliprects[i].x2 <= cliprects[i].x1 ||
- cliprects[i].y2 <= 0 || cliprects[i].x2 <= 0) {
- ret = EINVAL;
- goto free_cliprects;
- }
- }
- }
-
- DRM_LOCK();
- ret = i915_dispatch_cmdbuffer(dev, cmdbuf, cliprects);
- DRM_UNLOCK();
- if (ret == 0 && dev_priv->sarea_priv != NULL)
- dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
-
-free_cliprects:
- drm_free(cliprects);
- return (ret);
-}
-
-int i915_getparam(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- drm_i915_private_t *dev_priv = dev->dev_private;
- drm_i915_getparam_t *param = data;
- int value;
-
- if (!dev_priv) {
- DRM_ERROR("called with no initialization\n");
- return EINVAL;
- }
-
- switch (param->param) {
- case I915_PARAM_IRQ_ACTIVE:
- value = dev->irq_enabled;
- break;
- case I915_PARAM_ALLOW_BATCHBUFFER:
- value = dev_priv->allow_batchbuffer ? 1 : 0;
- break;
- case I915_PARAM_LAST_DISPATCH:
- value = READ_BREADCRUMB(dev_priv);
- break;
- case I915_PARAM_CHIPSET_ID:
- value = dev_priv->pci_device;
- break;
- case I915_PARAM_HAS_GEM:
- value = 1;
- break;
- case I915_PARAM_NUM_FENCES_AVAIL:
- value = dev_priv->num_fence_regs - dev_priv->fence_reg_start;
- break;
- case I915_PARAM_HAS_EXECBUF2:
- value = 1;
- break;
- default:
- DRM_DEBUG("Unknown parameter %d\n", param->param);
- return EINVAL;
- }
-
- if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) {
- DRM_ERROR("DRM_COPY_TO_USER failed\n");
- return EFAULT;
- }
-
- return 0;
-}
-
-int i915_setparam(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- drm_i915_private_t *dev_priv = dev->dev_private;
- drm_i915_setparam_t *param = data;
-
- if (!dev_priv) {
- DRM_ERROR("called with no initialization\n");
- return EINVAL;
- }
-
- switch (param->param) {
- case I915_SETPARAM_USE_MI_BATCHBUFFER_START:
- break;
- case I915_SETPARAM_TEX_LRU_LOG_GRANULARITY:
- /* We really don't care anymore */
- break;
- case I915_SETPARAM_ALLOW_BATCHBUFFER:
- dev_priv->allow_batchbuffer = param->value;
- break;
- case I915_SETPARAM_NUM_USED_FENCES:
- if (param->value > dev_priv->num_fence_regs ||
- param->value < 0)
- return EINVAL;
- /* Userspace can use first N regs */
- dev_priv->fence_reg_start = param->value;
- break;
- default:
- DRM_DEBUG("unknown parameter %d\n", param->param);
- return EINVAL;
- }
-
- return 0;
-}
-
-int i915_set_status_page(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- drm_i915_private_t *dev_priv = dev->dev_private;
- drm_i915_hws_addr_t *hws = data;
- int ret;
-
- if (!I915_NEED_GFX_HWS(dev_priv))
- return EINVAL;
-
- if (!dev_priv) {
- DRM_ERROR("called with no initialization\n");
- return EINVAL;
- }
- DRM_DEBUG("set status page addr 0x%08x\n", (u32)hws->addr);
-
- dev_priv->status_gfx_addr = hws->addr & (0x1ffff<<12);
-
- dev_priv->hws_map.offset = dev->agp->base + hws->addr;
- if (dev_priv->hws_map.offset > (dev->agp->base +
- dev->agp->info.ai_aperture_size)) {
- DRM_INFO("tried to map hws past end of aperture!\n");
- return (EINVAL);
- }
- dev_priv->hws_map.size = 4*1024;
-
- if ((ret = bus_space_map(dev_priv->bst, dev_priv->hws_map.offset,
- dev_priv->hws_map.size, BUS_SPACE_MAP_LINEAR |
- BUS_SPACE_MAP_PREFETCHABLE, &dev_priv->hws_map.bsh)) != 0) {
- DRM_INFO("can't hws page\n");
- i915_dma_cleanup(dev);
- dev_priv->status_gfx_addr = 0;
- return (ret);
- }
- dev_priv->hw_status_page = bus_space_vaddr(dev_priv->bst,
- dev_priv->hws_map.bsh);
-
- memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
- I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
- DRM_DEBUG("load hws HWS_PGA with gfx mem 0x%x\n",
- dev_priv->status_gfx_addr);
- DRM_DEBUG("load hws at %p\n", dev_priv->hw_status_page);
- return 0;
-}
diff --git a/sys/dev/pci/drm/i915_drv.c b/sys/dev/pci/drm/i915_drv.c
index dc28673ee97..3c065de9c1b 100644
--- a/sys/dev/pci/drm/i915_drv.c
+++ b/sys/dev/pci/drm/i915_drv.c
@@ -113,6 +113,8 @@ void inteldrm_teardown_mchbar(struct drm_i915_private *,
struct pci_attach_args *, int);
/* Ioctls */
+int inteldrm_getparam(struct drm_i915_private *dev_priv, void *data);
+int inteldrm_setparam(struct drm_i915_private *dev_priv, void *data);
int i915_gem_init_ioctl(struct drm_device *, void *, struct drm_file *);
int i915_gem_create_ioctl(struct drm_device *, void *, struct drm_file *);
int i915_gem_pread_ioctl(struct drm_device *, void *, struct drm_file *);
@@ -489,7 +491,14 @@ inteldrm_detach(struct device *self, int flags)
dev_priv->drmdev = NULL;
}
- i915_free_hws(dev_priv, dev_priv->dmat);
+ if (!I915_NEED_GFX_HWS(dev_priv) && dev_priv->hws_dmamem) {
+ drm_dmamem_free(dev_priv->dmat, dev_priv->hws_dmamem);
+ dev_priv->hws_dmamem = NULL;
+ /* Need to rewrite hardware status page */
+ I915_WRITE(HWS_PGA, 0x1ffff000);
+ dev_priv->hw_status_page = NULL;
+ }
+
if (IS_I9XX(dev_priv) && dev_priv->ifp.i9xx.bsh != NULL) {
bus_space_unmap(dev_priv->ifp.i9xx.bst, dev_priv->ifp.i9xx.bsh,
@@ -539,22 +548,12 @@ int
inteldrm_ioctl(struct drm_device *dev, u_long cmd, caddr_t data,
struct drm_file *file_priv)
{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
if (file_priv->authenticated == 1) {
switch (cmd) {
- case DRM_IOCTL_I915_FLUSH:
- return (i915_flush_ioctl(dev, data, file_priv));
- case DRM_IOCTL_I915_BATCHBUFFER:
- return (i915_batchbuffer(dev, data, file_priv));
- case DRM_IOCTL_I915_IRQ_EMIT:
- return (i915_irq_emit(dev, data, file_priv));
- case DRM_IOCTL_I915_IRQ_WAIT:
- return (i915_irq_wait(dev, data, file_priv));
case DRM_IOCTL_I915_GETPARAM:
- return (i915_getparam(dev, data, file_priv));
- case DRM_IOCTL_I915_CMDBUFFER:
- return (i915_cmdbuffer(dev, data, file_priv));
- case DRM_IOCTL_I915_GET_VBLANK_PIPE:
- return (i915_vblank_pipe_get(dev, data, file_priv));
+ return (inteldrm_getparam(dev_priv, data));
case DRM_IOCTL_I915_GEM_EXECBUFFER2:
return (i915_gem_execbuffer2(dev, data, file_priv));
case DRM_IOCTL_I915_GEM_BUSY:
@@ -589,16 +588,7 @@ inteldrm_ioctl(struct drm_device *dev, u_long cmd, caddr_t data,
if (file_priv->master == 1) {
switch (cmd) {
case DRM_IOCTL_I915_SETPARAM:
- return (i915_setparam(dev, data, file_priv));
- case DRM_IOCTL_I915_INIT:
- return (i915_dma_init(dev, data, file_priv));
- case DRM_IOCTL_I915_HWS_ADDR:
- return (i915_set_status_page(dev, data, file_priv));
- /* Removed, but still used by userland, so just say `fine' */
- case DRM_IOCTL_I915_INIT_HEAP:
- case DRM_IOCTL_I915_DESTROY_HEAP:
- case DRM_IOCTL_I915_SET_VBLANK_PIPE:
- return (0);
+ return (inteldrm_setparam(dev_priv, data));
case DRM_IOCTL_I915_GEM_INIT:
return (i915_gem_init_ioctl(dev, data, file_priv));
case DRM_IOCTL_I915_GEM_ENTERVT:
@@ -651,9 +641,6 @@ inteldrm_intr(void *arg)
I915_WRITE(IIR, iir);
(void)I915_READ(IIR); /* Flush posted writes */
- if (dev_priv->sarea_priv != NULL)
- dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
-
if (iir & I915_USER_INTERRUPT) {
wakeup(dev_priv);
dev_priv->mm.hang_cnt = 0;
@@ -675,21 +662,25 @@ u_int32_t
inteldrm_read_hws(struct drm_i915_private *dev_priv, int reg)
{
struct drm_device *dev = (struct drm_device *)dev_priv->drmdev;
+ struct inteldrm_obj *obj_priv;
+ bus_dma_tag_t tag;
+ bus_dmamap_t map;
u_int32_t val;
- /*
- * When we eventually go GEM only we'll always have a dmamap, so this
- * madness won't be for long.
- */
- if (dev_priv->hws_dmamem)
- bus_dmamap_sync(dev->dmat, dev_priv->hws_dmamem->map, 0,
- PAGE_SIZE, BUS_DMASYNC_POSTREAD);
+ if (I915_NEED_GFX_HWS(dev_priv)) {
+ obj_priv = (struct inteldrm_obj *)dev_priv->hws_obj;
+ map = obj_priv->dmamap;
+ tag = dev_priv->agpdmat;
+ } else {
+ map = dev_priv->hws_dmamem->map;
+ tag = dev->dmat;
+ }
+
+ bus_dmamap_sync(tag, map, 0, PAGE_SIZE, BUS_DMASYNC_POSTREAD);
val = ((volatile u_int32_t *)(dev_priv->hw_status_page))[reg];
+ bus_dmamap_sync(tag, map, 0, PAGE_SIZE, BUS_DMASYNC_PREREAD);
- if (dev_priv->hws_dmamem)
- bus_dmamap_sync(dev->dmat, dev_priv->hws_dmamem->map, 0,
- PAGE_SIZE, BUS_DMASYNC_PREREAD);
return (val);
}
@@ -802,6 +793,30 @@ inteldrm_update_ring(struct drm_i915_private *dev_priv)
ring->head, ring->tail, ring->space);
}
+/*
+ * Sets up the hardware status page for devices that need a physical address
+ * in the register.
+ */
+int
+i915_init_phys_hws(drm_i915_private_t *dev_priv, bus_dma_tag_t dmat)
+{
+ /* Program Hardware Status Page */
+ if ((dev_priv->hws_dmamem = drm_dmamem_alloc(dmat, PAGE_SIZE,
+ PAGE_SIZE, 1, PAGE_SIZE, 0, BUS_DMA_READ)) == NULL) {
+ return (ENOMEM);
+ }
+
+ dev_priv->hw_status_page = dev_priv->hws_dmamem->kva;
+
+ memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
+
+ bus_dmamap_sync(dmat, dev_priv->hws_dmamem->map, 0, PAGE_SIZE,
+ BUS_DMASYNC_PREREAD);
+ I915_WRITE(HWS_PGA, dev_priv->hws_dmamem->map->dm_segs[0].ds_addr);
+ DRM_DEBUG("Enabled hardware status page\n");
+ return (0);
+}
+
void
i915_alloc_ifp(struct drm_i915_private *dev_priv, struct pci_attach_args *bpa)
{
@@ -919,11 +934,53 @@ inteldrm_lastclose(struct drm_device *dev)
dev_priv->agpdmat);
}
dev_priv->agpdmat = NULL;
+}
+int
+inteldrm_getparam(struct drm_i915_private *dev_priv, void *data)
+{
+ drm_i915_getparam_t *param = data;
+ int value;
- dev_priv->sarea_priv = NULL;
+ switch (param->param) {
+ case I915_PARAM_CHIPSET_ID:
+ value = dev_priv->pci_device;
+ break;
+ case I915_PARAM_HAS_GEM:
+ value = 1;
+ break;
+ case I915_PARAM_NUM_FENCES_AVAIL:
+ value = dev_priv->num_fence_regs - dev_priv->fence_reg_start;
+ break;
+ case I915_PARAM_HAS_EXECBUF2:
+ value = 1;
+ break;
+ default:
+ DRM_DEBUG("Unknown parameter %d\n", param->param);
+ return (EINVAL);
+ }
+ return (copyout(&value, param->value, sizeof(int)));
+}
- i915_dma_cleanup(dev);
+int
+inteldrm_setparam(struct drm_i915_private *dev_priv, void *data)
+{
+ drm_i915_setparam_t *param = data;
+
+ switch (param->param) {
+ case I915_SETPARAM_NUM_USED_FENCES:
+ if (param->value > dev_priv->num_fence_regs ||
+ param->value < 0)
+ return EINVAL;
+ /* Userspace can use first N regs */
+ dev_priv->fence_reg_start = param->value;
+ break;
+ default:
+ DRM_DEBUG("unknown parameter %d\n", param->param);
+ return (EINVAL);
+ }
+
+ return 0;
}
@@ -3775,7 +3832,6 @@ i915_gem_init_hws(struct drm_i915_private *dev_priv)
if (ret != 0) {
DRM_ERROR("Failed to map status page.\n");
obj->uao->pgops->pgo_detach(obj->uao);
- memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
i915_gem_object_unpin(obj);
drm_unhold_and_unref(obj);
return (EINVAL);
@@ -3795,21 +3851,19 @@ i915_gem_cleanup_hws(struct drm_i915_private *dev_priv)
{
struct drm_obj *obj;
- if (dev_priv->hws_obj == NULL)
+ if (!I915_NEED_GFX_HWS(dev_priv) || dev_priv->hws_obj == NULL)
return;
obj = dev_priv->hws_obj;
uvm_unmap(kernel_map, (vaddr_t)dev_priv->hw_status_page,
(vaddr_t)dev_priv->hw_status_page + PAGE_SIZE);
+ dev_priv->hw_status_page = NULL;
drm_hold_object(obj);
i915_gem_object_unpin(obj);
drm_unhold_and_unref(obj);
dev_priv->hws_obj = NULL;
- memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
- dev_priv->hw_status_page = NULL;
-
/* Write high address into HWS_PGA when disabling. */
I915_WRITE(HWS_PGA, 0x1ffff000);
}
diff --git a/sys/dev/pci/drm/i915_drv.h b/sys/dev/pci/drm/i915_drv.h
index 4586ef79ee6..faee5a65a07 100644
--- a/sys/dev/pci/drm/i915_drv.h
+++ b/sys/dev/pci/drm/i915_drv.h
@@ -102,9 +102,6 @@ typedef struct drm_i915_private {
struct vga_pci_bar *regs;
- struct drm_local_map *sarea;
- drm_i915_sarea_t *sarea_priv;
-
union flush {
struct {
bus_space_tag_t bst;
@@ -114,16 +111,17 @@ typedef struct drm_i915_private {
bus_dma_segment_t seg;
caddr_t kva;
} i8xx;
- } ifp;
+ } ifp;
struct inteldrm_ring ring;
struct workq *workq;
struct vm_page *pgs;
- struct drm_local_map hws_map;
- struct drm_obj *hws_obj;
- struct drm_dmamem *hws_dmamem;
+ union hws {
+ struct drm_obj *obj;
+ struct drm_dmamem *dmamem;
+ } hws;
+#define hws_obj hws.obj
+#define hws_dmamem hws.dmamem
void *hw_status_page;
- unsigned int status_gfx_addr;
- u_int32_t counter;
size_t max_gem_obj_size; /* XXX */
/* Protects user_irq_refcount and irq_mask reg */
@@ -134,8 +132,6 @@ typedef struct drm_i915_private {
u_int32_t irq_mask_reg;
u_int32_t pipestat[2];
- int allow_batchbuffer;
-
struct mutex fence_lock;
struct inteldrm_fence fence_regs[16]; /* 965 */
int fence_reg_start; /* 4 by default */
@@ -413,13 +409,6 @@ struct inteldrm_obj {
u_int32_t stride;
};
-#define inteldrm_is_active(obj_priv) (obj_priv->obj.do_flags & I915_ACTIVE)
-#define inteldrm_is_dirty(obj_priv) (obj_priv->obj.do_flags & I915_DIRTY)
-#define inteldrm_exec_needs_fence(obj_priv) \
- (obj_priv->obj.do_flags & I915_EXEC_NEEDS_FENCE)
-#define inteldrm_needs_fence(obj_priv) \
- (obj_priv->obj.do_flags & I915_FENCED_EXEC)
-
/**
* Request queue structure.
*
@@ -444,43 +433,18 @@ void inteldrm_advance_ring(struct drm_i915_private *);
void inteldrm_update_ring(struct drm_i915_private *);
void inteldrm_error(struct drm_i915_private *);
int inteldrm_pipe_enabled(struct drm_i915_private *, int);
-
- /* i915_dma.c */
-extern void i915_emit_breadcrumb(struct drm_device *dev);
-void i915_emit_box(struct drm_device * dev, struct drm_clip_rect * boxes,
- int DR1, int DR4);
-int i915_dma_cleanup(struct drm_device *);
-
-int i915_init_phys_hws(drm_i915_private_t *, bus_dma_tag_t);
-void i915_free_hws(drm_i915_private_t *, bus_dma_tag_t);
+int i915_init_phys_hws(drm_i915_private_t *, bus_dma_tag_t);
/* i915_irq.c */
-extern int i915_irq_emit(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-extern int i915_irq_wait(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
extern int i915_driver_irq_install(struct drm_device * dev);
extern void i915_driver_irq_uninstall(struct drm_device * dev);
-extern int i915_vblank_pipe_get(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-extern int i915_emit_irq(struct drm_device * dev);
-extern int i915_wait_irq(struct drm_device * dev, int irq_nr);
extern int i915_enable_vblank(struct drm_device *dev, int crtc);
extern void i915_disable_vblank(struct drm_device *dev, int crtc);
extern u32 i915_get_vblank_counter(struct drm_device *dev, int crtc);
extern void i915_user_irq_get(struct drm_i915_private *);
extern void i915_user_irq_put(struct drm_i915_private *);
-/* ioctls */
-extern int i915_dma_init(struct drm_device *, void *, struct drm_file *);
-extern int i915_flush_ioctl(struct drm_device *, void *, struct drm_file *);
-extern int i915_batchbuffer(struct drm_device *, void *, struct drm_file *);
-extern int i915_getparam(struct drm_device *, void *, struct drm_file *);
-extern int i915_setparam(struct drm_device *, void *, struct drm_file *);
-extern int i915_cmdbuffer(struct drm_device *, void *, struct drm_file *);
-extern int i915_set_status_page(struct drm_device *, void *, struct drm_file *);
-
/* XXX need bus_space_write_8, this evaluated arguments twice */
static __inline void
write64(struct drm_i915_private *dev_priv, bus_size_t off, u_int64_t reg)
@@ -520,12 +484,6 @@ read64(struct drm_i915_private *dev_priv, bus_size_t off)
dev_priv->regs->bsh, (reg))
#define I915_WRITE8(reg,val) bus_space_write_1(dev_priv->regs->bst, \
dev_priv->regs->bsh, (reg), (val))
-
-#define RING_LOCK_TEST_WITH_RETURN(dev, file_priv) do { \
- if (((drm_i915_private_t *)dev->dev_private)->ring.ring_obj == NULL) \
- LOCK_TEST_WITH_RETURN(dev, file_priv); \
-} while (0)
-
#define INTELDRM_VERBOSE 0
#if INTELDRM_VERBOSE > 0
#define INTELDRM_VPRINTF(fmt, args...) DRM_INFO(fmt, ##args)
@@ -653,9 +611,6 @@ read64(struct drm_i915_private *dev_priv, bus_size_t off)
#define MI_BATCH_NON_SECURE_I965 (1<<8)
#define MI_BATCH_BUFFER_START MI_INSTR(0x31, 0)
-#define BREADCRUMB_BITS 31
-#define BREADCRUMB_MASK ((1U << BREADCRUMB_BITS) - 1)
-
/**
* Reads a dword out of the status page, which is written to from the command
* queue by automatic updates, MI_REPORT_HEAD, MI_STORE_DATA_INDEX, or
@@ -672,9 +627,7 @@ read64(struct drm_i915_private *dev_priv, bus_size_t off)
* The area from dword 0x20 to 0x3ff is available for driver usage.
*/
#define READ_HWSP(dev_priv, reg) inteldrm_read_hws(dev_priv, reg)
-#define READ_BREADCRUMB(dev_priv) READ_HWSP(dev_priv, I915_BREADCRUMB_INDEX)
#define I915_GEM_HWS_INDEX 0x20
-#define I915_BREADCRUMB_INDEX 0x21
/*
* 3D instructions used by the kernel
@@ -2418,4 +2371,28 @@ i915_obj_purged(struct inteldrm_obj *obj_priv)
return (obj_priv->obj.do_flags & I915_PURGED);
}
+static __inline int
+inteldrm_is_active(struct inteldrm_obj *obj_priv)
+{
+ return (obj_priv->obj.do_flags & I915_ACTIVE);
+}
+
+static __inline int
+inteldrm_is_dirty(struct inteldrm_obj *obj_priv)
+{
+ return (obj_priv->obj.do_flags & I915_DIRTY);
+}
+
+static __inline int
+inteldrm_exec_needs_fence(struct inteldrm_obj *obj_priv)
+{
+ return (obj_priv->obj.do_flags & I915_EXEC_NEEDS_FENCE);
+}
+
+static __inline int
+inteldrm_needs_fence(struct inteldrm_obj *obj_priv)
+{
+ return (obj_priv->obj.do_flags & I915_FENCED_EXEC);
+}
+
#endif
diff --git a/sys/dev/pci/drm/i915_irq.c b/sys/dev/pci/drm/i915_irq.c
index 26ac30bcd0b..24add612c20 100644
--- a/sys/dev/pci/drm/i915_irq.c
+++ b/sys/dev/pci/drm/i915_irq.c
@@ -36,7 +36,6 @@ void i915_enable_irq(drm_i915_private_t *, u_int32_t);
void i915_disable_irq(drm_i915_private_t *, u_int32_t);
void i915_enable_pipestat(drm_i915_private_t *, int, u_int32_t);
void i915_disable_pipestat(drm_i915_private_t *, int, u_int32_t);
-int i915_wait_irq(struct drm_device *, int);
inline void
i915_enable_irq(drm_i915_private_t *dev_priv, u_int32_t mask)
@@ -122,25 +121,6 @@ i915_get_vblank_counter(struct drm_device *dev, int pipe)
return ((high1 << 8) | low);
}
-int
-i915_emit_irq(struct drm_device *dev)
-{
- drm_i915_private_t *dev_priv = dev->dev_private;
-
- inteldrm_update_ring(dev_priv);
-
- DRM_DEBUG("\n");
-
- i915_emit_breadcrumb(dev);
-
- BEGIN_LP_RING(2);
- OUT_RING(0);
- OUT_RING(MI_USER_INTERRUPT);
- ADVANCE_LP_RING();
-
- return (dev_priv->counter);
-}
-
void
i915_user_irq_get(struct drm_i915_private *dev_priv)
{
@@ -155,71 +135,6 @@ i915_user_irq_put(struct drm_i915_private *dev_priv)
i915_disable_irq(dev_priv, I915_USER_INTERRUPT);
}
-
-int
-i915_wait_irq(struct drm_device *dev, int irq_nr)
-{
- drm_i915_private_t *dev_priv = dev->dev_private;
- int ret = 0;
-
- DRM_DEBUG("irq_nr=%d breadcrumb=%d\n", irq_nr,
- READ_BREADCRUMB(dev_priv));
-
- mtx_enter(&dev_priv->user_irq_lock);
- i915_user_irq_get(dev_priv);
- while (ret == 0) {
- if (READ_BREADCRUMB(dev_priv) >= irq_nr)
- break;
- ret = msleep(dev_priv, &dev_priv->user_irq_lock,
- PZERO | PCATCH, "i915wt", 3 * hz);
- }
- i915_user_irq_put(dev_priv);
- mtx_leave(&dev_priv->user_irq_lock);
-
- if (dev_priv->sarea_priv != NULL)
- dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
- return (ret);
-}
-
-/* Needs the lock as it touches the ring.
- */
-int
-i915_irq_emit(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
- drm_i915_private_t *dev_priv = dev->dev_private;
- drm_i915_irq_emit_t *emit = data;
- int result;
-
- RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
-
- if (!dev_priv) {
- DRM_ERROR("called with no initialization\n");
- return EINVAL;
- }
-
- DRM_LOCK();
- result = i915_emit_irq(dev);
- DRM_UNLOCK();
-
- return (copyout(&result, emit->irq_seq, sizeof(result)));
-}
-
-/* Doesn't need the hardware lock.
- */
-int
-i915_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
- drm_i915_private_t *dev_priv = dev->dev_private;
- drm_i915_irq_wait_t *irqwait = data;
-
- if (!dev_priv) {
- DRM_ERROR("called with no initialization\n");
- return (EINVAL);
- }
-
- return (i915_wait_irq(dev, irqwait->irq_seq));
-}
-
int
i915_enable_vblank(struct drm_device *dev, int pipe)
{
@@ -247,23 +162,6 @@ i915_disable_vblank(struct drm_device *dev, int pipe)
mtx_leave(&dev_priv->user_irq_lock);
}
-int
-i915_vblank_pipe_get(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- drm_i915_private_t *dev_priv = dev->dev_private;
- drm_i915_vblank_pipe_t *pipe = data;
-
- if (!dev_priv) {
- DRM_ERROR("called with no initialization\n");
- return (EINVAL);
- }
-
- pipe->pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
-
- return (0);
-}
-
/* drm_dma.h hooks
*/
int