diff options
author | Owain Ainsworth <oga@cvs.openbsd.org> | 2010-05-25 17:15:50 +0000 |
---|---|---|
committer | Owain Ainsworth <oga@cvs.openbsd.org> | 2010-05-25 17:15:50 +0000 |
commit | 4937c85ccda075c7bb6de0539aaa7d576f0a6968 (patch) | |
tree | 6925b415bd06cb5ddb9c4ec4f770cfb18f4caea3 /sys/dev | |
parent | cc4d50da37ea9825c7f663518e41b15a4b0f00df (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.drm | 3 | ||||
-rw-r--r-- | sys/dev/pci/drm/i915_dma.c | 694 | ||||
-rw-r--r-- | sys/dev/pci/drm/i915_drv.c | 142 | ||||
-rw-r--r-- | sys/dev/pci/drm/i915_drv.h | 87 | ||||
-rw-r--r-- | sys/dev/pci/drm/i915_irq.c | 102 |
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 |