diff options
Diffstat (limited to 'sys/dev/drm2/i915/i915_dma.c')
-rw-r--r-- | sys/dev/drm2/i915/i915_dma.c | 881 |
1 files changed, 569 insertions, 312 deletions
diff --git a/sys/dev/drm2/i915/i915_dma.c b/sys/dev/drm2/i915/i915_dma.c index ad2c147ada00..e2d8e4c918e0 100644 --- a/sys/dev/drm2/i915/i915_dma.c +++ b/sys/dev/drm2/i915/i915_dma.c @@ -29,14 +29,16 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <dev/drm2/drmP.h> -#include <dev/drm2/drm.h> +#include <dev/drm2/drm_crtc_helper.h> +#include <dev/drm2/drm_fb_helper.h> +#include <dev/drm2/i915/intel_drv.h> #include <dev/drm2/i915/i915_drm.h> #include <dev/drm2/i915/i915_drv.h> -#include <dev/drm2/i915/intel_drv.h> -#include <dev/drm2/i915/intel_ringbuffer.h> -#define LP_RING(d) (&((struct drm_i915_private *)(d))->rings[RCS]) +#define LP_RING(d) (&((struct drm_i915_private *)(d))->ring[RCS]) #define BEGIN_LP_RING(n) \ intel_ring_begin(LP_RING(dev_priv), (n)) @@ -62,7 +64,7 @@ static inline u32 intel_read_legacy_status_page(struct drm_i915_private *dev_priv, int reg) { if (I915_NEED_GFX_HWS(dev_priv->dev)) - return ((volatile u32*)(dev_priv->dri1.gfx_hws_cpu_addr))[reg]; + return ioread32(dev_priv->dri1.gfx_hws_cpu_addr + reg); else return intel_read_status_page(LP_RING(dev_priv), reg); } @@ -96,39 +98,6 @@ static void i915_write_hws_pga(struct drm_device *dev) } /** - * Sets up the hardware status page for devices that need a physical address - * in the register. - */ -static int i915_init_phys_hws(struct drm_device *dev) -{ - drm_i915_private_t *dev_priv = dev->dev_private; - struct intel_ring_buffer *ring = LP_RING(dev_priv); - - /* - * Program Hardware Status Page - * XXXKIB Keep 4GB limit for allocation for now. This method - * of allocation is used on <= 965 hardware, that has several - * erratas regarding the use of physical memory > 4 GB. - */ - dev_priv->status_page_dmah = - drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, BUS_SPACE_MAXADDR); - if (!dev_priv->status_page_dmah) { - DRM_ERROR("Can not allocate hardware status page\n"); - return -ENOMEM; - } - ring->status_page.page_addr = dev_priv->hw_status_page = - dev_priv->status_page_dmah->vaddr; - dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr; - - memset(dev_priv->hw_status_page, 0, PAGE_SIZE); - - i915_write_hws_pga(dev); - DRM_DEBUG("Enabled hardware status page, phys %jx\n", - (uintmax_t)dev_priv->dma_status_page); - return 0; -} - -/** * Frees the hardware status page, whether it's a physical address or a virtual * address set up by the X Server. */ @@ -142,8 +111,7 @@ static void i915_free_hws(struct drm_device *dev) dev_priv->status_page_dmah = NULL; } - if (dev_priv->status_gfx_addr) { - dev_priv->status_gfx_addr = 0; + if (ring->status_page.gfx_addr) { ring->status_page.gfx_addr = 0; pmap_unmapdev((vm_offset_t)dev_priv->dri1.gfx_hws_cpu_addr, PAGE_SIZE); @@ -168,7 +136,7 @@ void i915_kernel_lost_context(struct drm_device * dev) ring->head = I915_READ_HEAD(ring) & HEAD_ADDR; ring->tail = I915_READ_TAIL(ring) & TAIL_ADDR; - ring->space = ring->head - (ring->tail + 8); + ring->space = ring->head - (ring->tail + I915_RING_FREE_SPACE); if (ring->space < 0) ring->space += ring->size; @@ -194,7 +162,7 @@ static int i915_dma_cleanup(struct drm_device * dev) DRM_LOCK(dev); for (i = 0; i < I915_NUM_RINGS; i++) - intel_cleanup_ring_buffer(&dev_priv->rings[i]); + intel_cleanup_ring_buffer(&dev_priv->ring[i]); DRM_UNLOCK(dev); /* Clear the HWS virtual address at teardown */ @@ -235,10 +203,10 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init) } } - dev_priv->cpp = init->cpp; - dev_priv->back_offset = init->back_offset; - dev_priv->front_offset = init->front_offset; - dev_priv->current_page = 0; + dev_priv->dri1.cpp = init->cpp; + dev_priv->dri1.back_offset = init->back_offset; + dev_priv->dri1.front_offset = init->front_offset; + dev_priv->dri1.current_page = 0; if (master_priv->sarea_priv) master_priv->sarea_priv->pf_current_page = 0; @@ -376,33 +344,24 @@ static int validate_cmd(int cmd) static int i915_emit_cmds(struct drm_device * dev, int *buffer, int dwords) { drm_i915_private_t *dev_priv = dev->dev_private; - int i; + int i, ret; if ((dwords+1) * sizeof(int) >= LP_RING(dev_priv)->size - 8) return -EINVAL; - BEGIN_LP_RING((dwords+1)&~1); - for (i = 0; i < dwords;) { - int cmd, sz; - - if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i], sizeof(cmd))) + int sz = validate_cmd(buffer[i]); + if (sz == 0 || i + sz > dwords) return -EINVAL; - - if ((sz = validate_cmd(cmd)) == 0 || i + sz > dwords) - return -EINVAL; - - OUT_RING(cmd); - - while (++i, --sz) { - if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i], - sizeof(cmd))) { - return -EINVAL; - } - OUT_RING(cmd); - } + i += sz; } + ret = BEGIN_LP_RING((dwords+1)&~1); + if (ret) + return ret; + + for (i = 0; i < dwords; i++) + OUT_RING(buffer[i]); if (dwords & 1) OUT_RING(0); @@ -461,15 +420,16 @@ static void i915_emit_breadcrumb(struct drm_device *dev) drm_i915_private_t *dev_priv = dev->dev_private; struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; - if (++dev_priv->counter > 0x7FFFFFFFUL) - dev_priv->counter = 0; + dev_priv->dri1.counter++; + if (dev_priv->dri1.counter > 0x7FFFFFFFUL) + dev_priv->dri1.counter = 0; if (master_priv->sarea_priv) - master_priv->sarea_priv->last_enqueue = dev_priv->counter; + master_priv->sarea_priv->last_enqueue = dev_priv->dri1.counter; if (BEGIN_LP_RING(4) == 0) { OUT_RING(MI_STORE_DWORD_INDEX); OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT); - OUT_RING(dev_priv->counter); + OUT_RING(dev_priv->dri1.counter); OUT_RING(0); ADVANCE_LP_RING(); } @@ -484,7 +444,7 @@ static int i915_dispatch_cmdbuffer(struct drm_device * dev, int i = 0, count, ret; if (cmd->sz & 0x3) { - DRM_ERROR("alignment\n"); + DRM_ERROR("alignment"); return -EINVAL; } @@ -517,11 +477,8 @@ static int i915_dispatch_batchbuffer(struct drm_device * dev, int nbox = batch->num_cliprects; int i, count, ret; - if (drm_core_check_feature(dev, DRIVER_MODESET)) - return -ENODEV; - if ((batch->start | batch->used) & 0x7) { - DRM_ERROR("alignment\n"); + DRM_ERROR("alignment"); return -EINVAL; } @@ -561,6 +518,15 @@ static int i915_dispatch_batchbuffer(struct drm_device * dev, ADVANCE_LP_RING(); } + + if (IS_G4X(dev) || IS_GEN5(dev)) { + if (BEGIN_LP_RING(2) == 0) { + OUT_RING(MI_FLUSH | MI_NO_WRITE_FLUSH | MI_INVALIDATE_ISP); + OUT_RING(MI_NOOP); + ADVANCE_LP_RING(); + } + } + i915_emit_breadcrumb(dev); return 0; } @@ -577,7 +543,7 @@ static int i915_dispatch_flip(struct drm_device * dev) DRM_DEBUG_DRIVER("%s: page=%d pfCurrentPage=%d\n", __func__, - dev_priv->current_page, + dev_priv->dri1.current_page, master_priv->sarea_priv->pf_current_page); i915_kernel_lost_context(dev); @@ -591,12 +557,12 @@ static int i915_dispatch_flip(struct drm_device * dev) OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP); OUT_RING(0); - if (dev_priv->current_page == 0) { - OUT_RING(dev_priv->back_offset); - dev_priv->current_page = 1; + if (dev_priv->dri1.current_page == 0) { + OUT_RING(dev_priv->dri1.back_offset); + dev_priv->dri1.current_page = 1; } else { - OUT_RING(dev_priv->front_offset); - dev_priv->current_page = 0; + OUT_RING(dev_priv->dri1.front_offset); + dev_priv->dri1.current_page = 0; } OUT_RING(0); @@ -605,24 +571,24 @@ static int i915_dispatch_flip(struct drm_device * dev) ADVANCE_LP_RING(); - master_priv->sarea_priv->last_enqueue = dev_priv->counter++; + master_priv->sarea_priv->last_enqueue = dev_priv->dri1.counter++; if (BEGIN_LP_RING(4) == 0) { OUT_RING(MI_STORE_DWORD_INDEX); OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT); - OUT_RING(dev_priv->counter); + OUT_RING(dev_priv->dri1.counter); OUT_RING(0); ADVANCE_LP_RING(); } - master_priv->sarea_priv->pf_current_page = dev_priv->current_page; + master_priv->sarea_priv->pf_current_page = dev_priv->dri1.current_page; return 0; } static int i915_quiescent(struct drm_device *dev) { i915_kernel_lost_context(dev); - return intel_wait_ring_idle(LP_RING(dev->dev_private)); + return intel_ring_idle(LP_RING(dev->dev_private)); } static int i915_flush_ioctl(struct drm_device *dev, void *data, @@ -650,10 +616,12 @@ int i915_batchbuffer(struct drm_device *dev, void *data, drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *) master_priv->sarea_priv; drm_i915_batchbuffer_t *batch = data; - size_t cliplen; int ret; struct drm_clip_rect *cliprects = NULL; + if (drm_core_check_feature(dev, DRIVER_MODESET)) + return -ENODEV; + if (!dev_priv->dri1.allow_batchbuffer) { DRM_ERROR("Batchbuffer ioctl disabled\n"); return -EINVAL; @@ -662,24 +630,28 @@ int i915_batchbuffer(struct drm_device *dev, void *data, DRM_DEBUG_DRIVER("i915 batchbuffer, start %x used %d cliprects %d\n", batch->start, batch->used, batch->num_cliprects); - cliplen = batch->num_cliprects * sizeof(struct drm_clip_rect); + RING_LOCK_TEST_WITH_RETURN(dev, file_priv); + if (batch->num_cliprects < 0) - return -EFAULT; - if (batch->num_cliprects != 0) { + return -EINVAL; + + if (batch->num_cliprects) { cliprects = malloc(batch->num_cliprects * sizeof(struct drm_clip_rect), DRM_MEM_DMA, M_WAITOK | M_ZERO); + if (cliprects == NULL) + return -ENOMEM; - ret = -copyin(batch->cliprects, cliprects, + ret = copy_from_user(cliprects, batch->cliprects, batch->num_cliprects * sizeof(struct drm_clip_rect)); - if (ret != 0) + if (ret != 0) { + ret = -EFAULT; goto fail_free; - } else - cliprects = NULL; + } + } DRM_LOCK(dev); - RING_LOCK_TEST_WITH_RETURN(dev, file_priv); ret = i915_dispatch_batchbuffer(dev, batch, cliprects); DRM_UNLOCK(dev); @@ -710,27 +682,39 @@ int i915_cmdbuffer(struct drm_device *dev, void *data, if (drm_core_check_feature(dev, DRIVER_MODESET)) return -ENODEV; + RING_LOCK_TEST_WITH_RETURN(dev, file_priv); + if (cmdbuf->num_cliprects < 0) return -EINVAL; batch_data = malloc(cmdbuf->sz, DRM_MEM_DMA, M_WAITOK); + if (batch_data == NULL) + return -ENOMEM; - ret = -copyin(cmdbuf->buf, batch_data, cmdbuf->sz); - if (ret != 0) + ret = copy_from_user(batch_data, cmdbuf->buf, cmdbuf->sz); + if (ret != 0) { + ret = -EFAULT; goto fail_batch_free; + } if (cmdbuf->num_cliprects) { cliprects = malloc(cmdbuf->num_cliprects * sizeof(struct drm_clip_rect), DRM_MEM_DMA, M_WAITOK | M_ZERO); - ret = -copyin(cmdbuf->cliprects, cliprects, + if (cliprects == NULL) { + ret = -ENOMEM; + goto fail_batch_free; + } + + ret = copy_from_user(cliprects, cmdbuf->cliprects, cmdbuf->num_cliprects * sizeof(struct drm_clip_rect)); - if (ret != 0) + if (ret != 0) { + ret = -EFAULT; goto fail_clip_free; + } } DRM_LOCK(dev); - RING_LOCK_TEST_WITH_RETURN(dev, file_priv); ret = i915_dispatch_cmdbuffer(dev, cmdbuf, cliprects, batch_data); DRM_UNLOCK(dev); if (ret) { @@ -758,21 +742,21 @@ static int i915_emit_irq(struct drm_device * dev) DRM_DEBUG_DRIVER("\n"); - dev_priv->counter++; - if (dev_priv->counter > 0x7FFFFFFFUL) - dev_priv->counter = 1; + dev_priv->dri1.counter++; + if (dev_priv->dri1.counter > 0x7FFFFFFFUL) + dev_priv->dri1.counter = 1; if (master_priv->sarea_priv) - master_priv->sarea_priv->last_enqueue = dev_priv->counter; + master_priv->sarea_priv->last_enqueue = dev_priv->dri1.counter; if (BEGIN_LP_RING(4) == 0) { OUT_RING(MI_STORE_DWORD_INDEX); OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT); - OUT_RING(dev_priv->counter); + OUT_RING(dev_priv->dri1.counter); OUT_RING(MI_USER_INTERRUPT); ADVANCE_LP_RING(); } - return dev_priv->counter; + return dev_priv->dri1.counter; } static int i915_wait_irq(struct drm_device * dev, int irq_nr) @@ -794,27 +778,22 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr) if (master_priv->sarea_priv) master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT; - ret = 0; - mtx_lock(&dev_priv->irq_lock); if (ring->irq_get(ring)) { + mtx_lock(&dev_priv->irq_lock); while (ret == 0 && READ_BREADCRUMB(dev_priv) < irq_nr) { - ret = -msleep(ring, &dev_priv->irq_lock, PCATCH, - "915wtq", 3 * hz); + ret = -msleep(&ring->irq_queue, &dev_priv->irq_lock, + PCATCH, "915wtq", 3 * DRM_HZ); if (ret == -ERESTART) ret = -ERESTARTSYS; } - ring->irq_put(ring); - mtx_unlock(&dev_priv->irq_lock); - } else { mtx_unlock(&dev_priv->irq_lock); - if (_intel_wait_for(dev, READ_BREADCRUMB(dev_priv) >= irq_nr, - 3000, 1, "915wir")) - ret = -EBUSY; - } + ring->irq_put(ring); + } else if (wait_for(READ_BREADCRUMB(dev_priv) >= irq_nr, 3000)) + ret = -EBUSY; if (ret == -EBUSY) { DRM_ERROR("EBUSY -- rec: %d emitted: %d\n", - READ_BREADCRUMB(dev_priv), (int)dev_priv->counter); + READ_BREADCRUMB(dev_priv), (int)dev_priv->dri1.counter); } return ret; @@ -969,13 +948,14 @@ int i915_getparam(struct drm_device *dev, void *data, value = 1; break; case I915_PARAM_HAS_EXECBUF2: + /* depends on GEM */ value = 1; break; case I915_PARAM_HAS_BSD: - value = intel_ring_initialized(&dev_priv->rings[VCS]); + value = intel_ring_initialized(&dev_priv->ring[VCS]); break; case I915_PARAM_HAS_BLT: - value = intel_ring_initialized(&dev_priv->rings[BCS]); + value = intel_ring_initialized(&dev_priv->ring[BCS]); break; case I915_PARAM_HAS_RELAXED_FENCING: value = 1; @@ -998,6 +978,23 @@ int i915_getparam(struct drm_device *dev, void *data, case I915_PARAM_HAS_ALIASING_PPGTT: value = dev_priv->mm.aliasing_ppgtt ? 1 : 0; break; + case I915_PARAM_HAS_WAIT_TIMEOUT: + value = 1; + break; + case I915_PARAM_HAS_SEMAPHORES: + value = i915_semaphore_is_enabled(dev); + break; + case I915_PARAM_HAS_PRIME_VMAP_FLUSH: + value = 1; + break; + case I915_PARAM_HAS_SECURE_BATCHES: + /* FIXME Linux<->FreeBSD: Is there a better choice than + * curthread? */ + value = DRM_SUSER(curthread); + break; + case I915_PARAM_HAS_PINNED_BATCHES: + value = 1; + break; default: DRM_DEBUG_DRIVER("Unknown parameter %d\n", param->param); @@ -1066,34 +1063,33 @@ static int i915_set_status_page(struct drm_device *dev, void *data, } if (drm_core_check_feature(dev, DRIVER_MODESET)) { - DRM_ERROR("tried to set status page when mode setting active\n"); + WARN(1, "tried to set status page when mode setting active\n"); return 0; } DRM_DEBUG_DRIVER("set status page addr 0x%08x\n", (u32)hws->addr); ring = LP_RING(dev_priv); - ring->status_page.gfx_addr = dev_priv->status_gfx_addr = - hws->addr & (0x1ffff<<12); + ring->status_page.gfx_addr = hws->addr & (0x1ffff<<12); dev_priv->dri1.gfx_hws_cpu_addr = - pmap_mapdev_attr(dev->agp->base + hws->addr, PAGE_SIZE, + pmap_mapdev_attr(dev_priv->mm.gtt_base_addr + hws->addr, PAGE_SIZE, VM_MEMATTR_WRITE_COMBINING); if (dev_priv->dri1.gfx_hws_cpu_addr == NULL) { i915_dma_cleanup(dev); - ring->status_page.gfx_addr = dev_priv->status_gfx_addr = 0; + ring->status_page.gfx_addr = 0; DRM_ERROR("can not ioremap virtual address for" " G33 hw status page\n"); return -ENOMEM; } - memset(dev_priv->dri1.gfx_hws_cpu_addr, 0, PAGE_SIZE); - I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr); + memset_io(dev_priv->dri1.gfx_hws_cpu_addr, 0, PAGE_SIZE); + I915_WRITE(HWS_PGA, ring->status_page.gfx_addr); DRM_DEBUG_DRIVER("load hws HWS_PGA with gfx mem 0x%x\n", - dev_priv->status_gfx_addr); + ring->status_page.gfx_addr); DRM_DEBUG_DRIVER("load hws at %p\n", - dev_priv->hw_status_page); + ring->status_page.page_addr); return 0; } @@ -1101,7 +1097,7 @@ static int i915_get_bridge_dev(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - dev_priv->bridge_dev = intel_gtt_get_bridge_device(); + dev_priv->bridge_dev = pci_find_dbsf(0, 0, 0, 0); if (!dev_priv->bridge_dev) { DRM_ERROR("bridge device not found\n"); return -1; @@ -1123,15 +1119,15 @@ intel_alloc_mchbar_resource(struct drm_device *dev) drm_i915_private_t *dev_priv = dev->dev_private; int reg = INTEL_INFO(dev)->gen >= 4 ? MCHBAR_I965 : MCHBAR_I915; u32 temp_lo, temp_hi = 0; - u64 mchbar_addr, temp; + u64 mchbar_addr; if (INTEL_INFO(dev)->gen >= 4) - temp_hi = pci_read_config(dev_priv->bridge_dev, reg + 4, 4); - temp_lo = pci_read_config(dev_priv->bridge_dev, reg, 4); + pci_read_config_dword(dev_priv->bridge_dev, reg + 4, &temp_hi); + pci_read_config_dword(dev_priv->bridge_dev, reg, &temp_lo); mchbar_addr = ((u64)temp_hi << 32) | temp_lo; /* If ACPI doesn't have it, assume we need to allocate it ourselves */ -#ifdef XXX_CONFIG_PNP +#ifdef CONFIG_PNP if (mchbar_addr && pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE)) return 0; @@ -1149,16 +1145,16 @@ intel_alloc_mchbar_resource(struct drm_device *dev) return -ENOMEM; } - if (INTEL_INFO(dev)->gen >= 4) { - temp = rman_get_start(dev_priv->mch_res); - temp >>= 32; - pci_write_config(dev_priv->bridge_dev, reg + 4, temp, 4); - } - pci_write_config(dev_priv->bridge_dev, reg, - rman_get_start(dev_priv->mch_res) & UINT32_MAX, 4); + if (INTEL_INFO(dev)->gen >= 4) + pci_write_config_dword(dev_priv->bridge_dev, reg + 4, + upper_32_bits(rman_get_start(dev_priv->mch_res))); + + pci_write_config_dword(dev_priv->bridge_dev, reg, + lower_32_bits(rman_get_start(dev_priv->mch_res))); return 0; } +/* Setup MCHBAR if possible, return true if we should disable it again */ static void intel_setup_mchbar(struct drm_device *dev) { @@ -1170,18 +1166,16 @@ intel_setup_mchbar(struct drm_device *dev) dev_priv->mchbar_need_disable = false; if (IS_I915G(dev) || IS_I915GM(dev)) { - temp = pci_read_config(dev_priv->bridge_dev, DEVEN_REG, 4); - enabled = (temp & DEVEN_MCHBAR_EN) != 0; + pci_read_config_dword(dev_priv->bridge_dev, DEVEN_REG, &temp); + enabled = !!(temp & DEVEN_MCHBAR_EN); } else { - temp = pci_read_config(dev_priv->bridge_dev, mchbar_reg, 4); + pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp); enabled = temp & 1; } /* If it's already enabled, don't have to do anything */ - if (enabled) { - DRM_DEBUG("mchbar already enabled\n"); + if (enabled) return; - } if (intel_alloc_mchbar_resource(dev)) return; @@ -1190,11 +1184,11 @@ intel_setup_mchbar(struct drm_device *dev) /* Space is allocated or reserved, so enable it. */ if (IS_I915G(dev) || IS_I915GM(dev)) { - pci_write_config(dev_priv->bridge_dev, DEVEN_REG, - temp | DEVEN_MCHBAR_EN, 4); + pci_write_config_dword(dev_priv->bridge_dev, DEVEN_REG, + temp | DEVEN_MCHBAR_EN); } else { - temp = pci_read_config(dev_priv->bridge_dev, mchbar_reg, 4); - pci_write_config(dev_priv->bridge_dev, mchbar_reg, temp | 1, 4); + pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp); + pci_write_config_dword(dev_priv->bridge_dev, mchbar_reg, temp | 1); } } @@ -1207,17 +1201,13 @@ intel_teardown_mchbar(struct drm_device *dev) if (dev_priv->mchbar_need_disable) { if (IS_I915G(dev) || IS_I915GM(dev)) { - temp = pci_read_config(dev_priv->bridge_dev, - DEVEN_REG, 4); + pci_read_config_dword(dev_priv->bridge_dev, DEVEN_REG, &temp); temp &= ~DEVEN_MCHBAR_EN; - pci_write_config(dev_priv->bridge_dev, DEVEN_REG, - temp, 4); + pci_write_config_dword(dev_priv->bridge_dev, DEVEN_REG, temp); } else { - temp = pci_read_config(dev_priv->bridge_dev, - mchbar_reg, 4); + pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp); temp &= ~1; - pci_write_config(dev_priv->bridge_dev, mchbar_reg, - temp, 4); + pci_write_config_dword(dev_priv->bridge_dev, mchbar_reg, temp); } } @@ -1232,6 +1222,57 @@ intel_teardown_mchbar(struct drm_device *dev) } } +#ifdef __linux__ +/* true = enable decode, false = disable decoder */ +static unsigned int i915_vga_set_decode(void *cookie, bool state) +{ + struct drm_device *dev = cookie; + + intel_modeset_vga_set_state(dev, state); + if (state) + return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM | + VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; + else + return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; +} + +static void i915_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state) +{ + struct drm_device *dev = pci_get_drvdata(pdev); + pm_message_t pmm = { .event = PM_EVENT_SUSPEND }; + if (state == VGA_SWITCHEROO_ON) { + pr_info("switched on\n"); + dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; + /* i915 resume handler doesn't set to D0 */ + pci_set_power_state(dev->pdev, PCI_D0); + i915_resume(dev); + dev->switch_power_state = DRM_SWITCH_POWER_ON; + } else { + pr_err("switched off\n"); + dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; + i915_suspend(dev, pmm); + dev->switch_power_state = DRM_SWITCH_POWER_OFF; + } +} + +static bool i915_switcheroo_can_switch(struct pci_dev *pdev) +{ + struct drm_device *dev = pci_get_drvdata(pdev); + bool can_switch; + + spin_lock(&dev->count_lock); + can_switch = (dev->open_count == 0); + spin_unlock(&dev->count_lock); + return can_switch; +} + +static const struct vga_switcheroo_client_ops i915_switcheroo_ops = { + .set_gpu_state = i915_switcheroo_set_state, + .reprobe = NULL, + .can_switch = i915_switcheroo_can_switch, +}; +#endif + static int i915_load_modeset_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -1241,8 +1282,23 @@ static int i915_load_modeset_init(struct drm_device *dev) if (ret) DRM_INFO("failed to find VBIOS tables\n"); -#if 0 +#ifdef __linux__ + /* If we have > 1 VGA cards, then we need to arbitrate access + * to the common VGA resources. + * + * If we are a secondary display controller (!PCI_DISPLAY_CLASS_VGA), + * then we do not take part in VGA arbitration and the + * vga_client_register() fails with -ENODEV. + */ + ret = vga_client_register(dev->pdev, dev, NULL, i915_vga_set_decode); + if (ret && ret != -ENODEV) + goto out; + intel_register_dsm_handler(); + + ret = vga_switcheroo_register_client(dev->pdev, &i915_switcheroo_ops); + if (ret) + goto cleanup_vga_client; #endif /* Initialise stolen first so that we may reserve preallocated @@ -1260,15 +1316,20 @@ static int i915_load_modeset_init(struct drm_device *dev) intel_modeset_gem_init(dev); + TASK_INIT(&dev_priv->console_resume_work, 0, intel_console_resume, + dev->dev_private); + ret = drm_irq_install(dev); if (ret) goto cleanup_gem; + /* Always safe in the mode setting case. */ + /* FIXME: do pre/post-mode set stuff in core KMS code */ dev->vblank_disable_allowed = 1; ret = intel_fbdev_init(dev); if (ret) - goto cleanup_gem; + goto cleanup_irq; drm_kms_helper_poll_init(dev); @@ -1277,6 +1338,8 @@ static int i915_load_modeset_init(struct drm_device *dev) return 0; +cleanup_irq: + drm_irq_uninstall(dev); cleanup_gem: DRM_LOCK(dev); i915_gem_cleanup_ringbuffer(dev); @@ -1285,6 +1348,13 @@ cleanup_gem: cleanup_gem_stolen: i915_gem_cleanup_stolen(dev); cleanup_vga_switcheroo: +#ifdef __linux__ + vga_switcheroo_unregister_client(dev->pdev); +cleanup_vga_client: + vga_client_register(dev->pdev, NULL, NULL, NULL); +out: +#endif + intel_free_parsed_bios_data(dev); return ret; } @@ -1292,7 +1362,7 @@ int i915_master_create(struct drm_device *dev, struct drm_master *master) { struct drm_i915_master_private *master_priv; - master_priv = malloc(sizeof(*master_priv), DRM_MEM_DMA, M_NOWAIT | M_ZERO); + master_priv = malloc(sizeof(*master_priv), DRM_MEM_DMA, M_WAITOK | M_ZERO); if (!master_priv) return -ENOMEM; @@ -1312,6 +1382,67 @@ void i915_master_destroy(struct drm_device *dev, struct drm_master *master) master->driver_priv = NULL; } +static void +i915_mtrr_setup(struct drm_i915_private *dev_priv, unsigned long base, + unsigned long size) +{ + dev_priv->mm.gtt_mtrr = -1; + +#if defined(CONFIG_X86_PAT) + if (cpu_has_pat) + return; +#endif + + /* Set up a WC MTRR for non-PAT systems. This is more common than + * one would think, because the kernel disables PAT on first + * generation Core chips because WC PAT gets overridden by a UC + * MTRR if present. Even if a UC MTRR isn't present. + */ + dev_priv->mm.gtt_mtrr = drm_mtrr_add(base, size, DRM_MTRR_WC); + if (dev_priv->mm.gtt_mtrr < 0) { + DRM_INFO("MTRR allocation failed. Graphics " + "performance may suffer.\n"); + } +} + +#ifdef __linux__ +static void i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv) +{ + struct apertures_struct *ap; + struct pci_dev *pdev = dev_priv->dev->pdev; + bool primary; + + ap = alloc_apertures(1); + if (!ap) + return; + + ap->ranges[0].base = dev_priv->mm.gtt->gma_bus_addr; + ap->ranges[0].size = + dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT; + primary = + pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW; + + remove_conflicting_framebuffers(ap, "inteldrmfb", primary); + + kfree(ap); +} +#endif + +static void i915_dump_device_info(struct drm_i915_private *dev_priv) +{ + const struct intel_device_info *info = dev_priv->info; + +#define DEV_INFO_FLAG(name) info->name ? #name "," : "" +#define DEV_INFO_SEP , + DRM_DEBUG_DRIVER("i915 device info: gen=%i, pciid=0x%04x flags=" + "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + info->gen, + dev_priv->dev->pci_device, + DEV_INFO_FLAGS); +#undef DEV_INFO_FLAG +#undef DEV_INFO_SEP +} + /** * i915_driver_load - setup chip and create an initial config * @dev: DRM device @@ -1327,8 +1458,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) { struct drm_i915_private *dev_priv; const struct intel_device_info *info; - unsigned long base, size; - int ret = 0, mmio_bar; + int ret = 0, mmio_bar, mmio_size; + uint32_t aperture_size; info = i915_get_device_id(dev->pci_device); @@ -1345,42 +1476,113 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) dev_priv = malloc(sizeof(drm_i915_private_t), DRM_MEM_DRIVER, M_WAITOK | M_ZERO); + if (dev_priv == NULL) + return -ENOMEM; dev->dev_private = (void *)dev_priv; dev_priv->dev = dev; dev_priv->info = info; + i915_dump_device_info(dev_priv); + if (i915_get_bridge_dev(dev)) { - free(dev_priv, DRM_MEM_DRIVER); - return -EIO; + ret = -EIO; + goto free_priv; } - dev_priv->mm.gtt = intel_gtt_get(); - /* Add register map (needed for suspend/resume) */ + ret = i915_gem_gtt_init(dev); + if (ret) + goto put_bridge; + +#ifdef __linux__ + if (drm_core_check_feature(dev, DRIVER_MODESET)) + i915_kick_out_firmware_fb(dev_priv); + + pci_set_master(dev->pdev); + + /* overlay on gen2 is broken and can't address above 1G */ + if (IS_GEN2(dev)) + dma_set_coherent_mask(&dev->pdev->dev, DMA_BIT_MASK(30)); + + /* 965GM sometimes incorrectly writes to hardware status page (HWS) + * using 32bit addressing, overwriting memory if HWS is located + * above 4GB. + * + * The documentation also mentions an issue with undefined + * behaviour if any general state is accessed within a page above 4GB, + * which also needs to be handled carefully. + */ + if (IS_BROADWATER(dev) || IS_CRESTLINE(dev)) + dma_set_coherent_mask(&dev->pdev->dev, DMA_BIT_MASK(32)); +#endif + mmio_bar = IS_GEN2(dev) ? 1 : 0; - base = drm_get_resource_start(dev, mmio_bar); - size = drm_get_resource_len(dev, mmio_bar); + /* Before gen4, the registers and the GTT are behind different BARs. + * However, from gen4 onwards, the registers and the GTT are shared + * in the same BAR, so we want to restrict this ioremap from + * clobbering the GTT which we want ioremap_wc instead. Fortunately, + * the register BAR remains the same size for all the earlier + * generations up to Ironlake. + */ + if (info->gen < 5) + mmio_size = 512*1024; + else + mmio_size = 2*1024*1024; ret = drm_addmap(dev, - base, size, + drm_get_resource_start(dev, mmio_bar), mmio_size, _DRM_REGISTERS, _DRM_KERNEL | _DRM_DRIVER, &dev_priv->mmio_map); if (ret != 0) { - DRM_ERROR("Failed to allocate mmio_map: %d\n", ret); - free(dev_priv, DRM_MEM_DRIVER); - return ret; + DRM_ERROR("failed to map registers\n"); + ret = -EIO; + goto put_gmch; } - dev_priv->tq = taskqueue_create("915", M_WAITOK, - taskqueue_thread_enqueue, &dev_priv->tq); - taskqueue_start_threads(&dev_priv->tq, 1, PWAIT, "i915 taskq"); - mtx_init(&dev_priv->gt_lock, "915gt", NULL, MTX_DEF); - mtx_init(&dev_priv->error_lock, "915err", NULL, MTX_DEF); - mtx_init(&dev_priv->error_completion_lock, "915cmp", NULL, MTX_DEF); - mtx_init(&dev_priv->rps_lock, "915rps", NULL, MTX_DEF); - mtx_init(&dev_priv->dpio_lock, "915dpi", NULL, MTX_DEF); + aperture_size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT; + dev_priv->mm.gtt_base_addr = dev_priv->mm.gtt->gma_bus_addr; + +#ifdef __linux__ + dev_priv->mm.gtt_mapping = + io_mapping_create_wc(dev_priv->mm.gtt_base_addr, + aperture_size); + if (dev_priv->mm.gtt_mapping == NULL) { + ret = -EIO; + goto out_rmmap; + } +#endif + + i915_mtrr_setup(dev_priv, dev_priv->mm.gtt_base_addr, + aperture_size); + + /* The i915 workqueue is primarily used for batched retirement of + * requests (and thus managing bo) once the task has been completed + * by the GPU. i915_gem_retire_requests() is called directly when we + * need high-priority retirement, such as waiting for an explicit + * bo. + * + * It is also used for periodic low-priority events, such as + * idle-timers and recording error state. + * + * All tasks on the workqueue are expected to acquire the dev mutex + * so there is no point in running more than one instance of the + * workqueue at any time. Use an ordered one. + */ + dev_priv->wq = taskqueue_create("915", M_WAITOK, + taskqueue_thread_enqueue, &dev_priv->wq); + if (dev_priv->wq == NULL) { + DRM_ERROR("Failed to create our workqueue.\n"); + ret = -ENOMEM; + goto out_mtrrfree; + } + taskqueue_start_threads(&dev_priv->wq, 1, PWAIT, "i915 taskq"); + + /* This must be called before any calls to HAS_PCH_* */ + intel_detect_pch(dev); intel_irq_init(dev); + intel_gt_init(dev); + /* Try to make sure MCHBAR is enabled before poking at it */ intel_setup_mchbar(dev); intel_setup_gmbus(dev); intel_opregion_setup(dev); @@ -1403,17 +1605,12 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) if (!IS_I945G(dev) && !IS_I945GM(dev)) drm_pci_enable_msi(dev); - /* Init HWS */ - if (!I915_NEED_GFX_HWS(dev)) { - ret = i915_init_phys_hws(dev); - if (ret != 0) { - drm_rmmap(dev, dev_priv->mmio_map); - free(dev_priv, DRM_MEM_DRIVER); - return ret; - } - } - mtx_init(&dev_priv->irq_lock, "userirq", NULL, MTX_DEF); + mtx_init(&dev_priv->error_lock, "915err", NULL, MTX_DEF); + mtx_init(&dev_priv->rps.lock, "915rps", NULL, MTX_DEF); + sx_init(&dev_priv->dpio_lock, "915dpi"); + + sx_init(&dev_priv->rps.hw_lock, "915rpshw"); if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) dev_priv->num_pipe = 3; @@ -1429,8 +1626,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) /* Start out suspended */ dev_priv->mm.suspended = 1; - intel_detect_pch(dev); - if (drm_core_check_feature(dev, DRIVER_MODESET)) { ret = i915_load_modeset_init(dev); if (ret < 0) { @@ -1441,7 +1636,15 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) pci_enable_busmaster(dev->dev); +#ifdef __linux__ + i915_setup_sysfs(dev); +#endif + + /* Must be done after probing outputs */ intel_opregion_init(dev); +#ifdef __linux__ + acpi_video_register(); +#endif callout_init(&dev_priv->hangcheck_timer, 1); callout_reset(&dev_priv->hangcheck_timer, DRM_I915_HANGCHECK_PERIOD, @@ -1453,9 +1656,48 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) return 0; out_gem_unload: - /* XXXKIB */ - (void) i915_driver_unload(dev); - return (ret); + EVENTHANDLER_DEREGISTER(vm_lowmem, dev_priv->mm.inactive_shrinker); + + free_completion(&dev_priv->error_completion); + mtx_destroy(&dev_priv->irq_lock); + mtx_destroy(&dev_priv->error_lock); + mtx_destroy(&dev_priv->rps.lock); + sx_destroy(&dev_priv->dpio_lock); + + sx_destroy(&dev_priv->rps.hw_lock); + + if (dev->msi_enabled) + drm_pci_disable_msi(dev); + + intel_teardown_gmbus(dev); + intel_teardown_mchbar(dev); + if (dev_priv->wq != NULL) { + taskqueue_free(dev_priv->wq); + dev_priv->wq = NULL; + } +out_mtrrfree: + if (dev_priv->mm.gtt_mtrr >= 0) { + drm_mtrr_del(dev_priv->mm.gtt_mtrr, + dev_priv->mm.gtt_base_addr, + aperture_size, + DRM_MTRR_WC); + dev_priv->mm.gtt_mtrr = -1; + } +#ifdef __linux__ + io_mapping_free(dev_priv->mm.gtt_mapping); +out_rmmap: +#endif + if (dev_priv->mmio_map != NULL) + drm_rmmap(dev, dev_priv->mmio_map); +put_gmch: + i915_gem_gtt_fini(dev); +put_bridge: +#ifdef __linux__ + pci_dev_put(dev_priv->bridge_dev); +#endif +free_priv: + free(dev_priv, DRM_MEM_DRIVER); + return ret; } int i915_driver_unload(struct drm_device *dev) @@ -1463,6 +1705,17 @@ int i915_driver_unload(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; int ret; + intel_gpu_ips_teardown(); + +#ifdef __linux__ + i915_teardown_sysfs(dev); + + if (dev_priv->mm.inactive_shrinker.shrink) + unregister_shrinker(&dev_priv->mm.inactive_shrinker); +#endif + + intel_free_parsed_bios_data(dev); + DRM_LOCK(dev); ret = i915_gpu_idle(dev); if (ret) @@ -1470,19 +1723,56 @@ int i915_driver_unload(struct drm_device *dev) i915_gem_retire_requests(dev); DRM_UNLOCK(dev); - i915_free_hws(dev); + /* Cancel the retire work handler, which should be idle now. */ + while (taskqueue_cancel_timeout(dev_priv->wq, + &dev_priv->mm.retire_work, NULL) != 0) + taskqueue_drain_timeout(dev_priv->wq, + &dev_priv->mm.retire_work); - intel_teardown_mchbar(dev); +#ifdef __linux__ + io_mapping_free(dev_priv->mm.gtt_mapping); +#endif + if (dev_priv->mm.gtt_mtrr >= 0) { + drm_mtrr_del(dev_priv->mm.gtt_mtrr, + dev_priv->mm.gtt_base_addr, + dev_priv->mm.gtt->gtt_mappable_entries * PAGE_SIZE, + DRM_MTRR_WC); + dev_priv->mm.gtt_mtrr = -1; + } + +#ifdef __linux__ + acpi_video_unregister(); +#endif if (drm_core_check_feature(dev, DRIVER_MODESET)) { intel_fbdev_fini(dev); intel_modeset_cleanup(dev); + while (taskqueue_cancel(dev_priv->wq, + &dev_priv->console_resume_work, NULL) != 0) + taskqueue_drain(dev_priv->wq, + &dev_priv->console_resume_work); + + /* + * free the memory space allocated for the child device + * config parsed from VBT + */ + if (dev_priv->child_dev && dev_priv->child_dev_num) { + free(dev_priv->child_dev, DRM_MEM_DRIVER); + dev_priv->child_dev = NULL; + dev_priv->child_dev_num = 0; + } + +#ifdef __linux__ + vga_switcheroo_unregister_client(dev->pdev); + vga_client_register(dev->pdev, NULL, NULL, NULL); +#endif } /* Free error state after interrupts are fully disabled. */ callout_stop(&dev_priv->hangcheck_timer); callout_drain(&dev_priv->hangcheck_timer); - + while (taskqueue_cancel(dev_priv->wq, &dev_priv->error_work, NULL) != 0) + taskqueue_drain(dev_priv->wq, &dev_priv->error_work); i915_destroy_error_state(dev); if (dev->msi_enabled) @@ -1491,18 +1781,16 @@ int i915_driver_unload(struct drm_device *dev) intel_opregion_fini(dev); if (drm_core_check_feature(dev, DRIVER_MODESET)) { + /* Flush any outstanding unpin_work. */ + taskqueue_drain_all(dev_priv->wq); + DRM_LOCK(dev); i915_gem_free_all_phys_object(dev); i915_gem_cleanup_ringbuffer(dev); i915_gem_context_fini(dev); DRM_UNLOCK(dev); i915_gem_cleanup_aliasing_ppgtt(dev); -#if 1 - KIB_NOTYET(); -#else - if (I915_HAS_FBC(dev) && i915_powersave) - i915_cleanup_compression(dev); -#endif + i915_gem_cleanup_stolen(dev); drm_mm_takedown(&dev_priv->mm.stolen); intel_cleanup_overlay(dev); @@ -1511,21 +1799,31 @@ int i915_driver_unload(struct drm_device *dev) i915_free_hws(dev); } - i915_gem_unload(dev); - - mtx_destroy(&dev_priv->irq_lock); + intel_teardown_gmbus(dev); + intel_teardown_mchbar(dev); - if (dev_priv->tq != NULL) - taskqueue_free(dev_priv->tq); + /* + * NOTE Linux<->FreeBSD: Free mmio_map after + * intel_teardown_gmbus(), because, on FreeBSD, + * intel_i2c_reset() is called during iicbus_detach(). + */ + if (dev_priv->mmio_map != NULL) + drm_rmmap(dev, dev_priv->mmio_map); - bus_generic_detach(dev->dev); - drm_rmmap(dev, dev_priv->mmio_map); - intel_teardown_gmbus(dev); + if (dev_priv->wq != NULL) + taskqueue_free(dev_priv->wq); - mtx_destroy(&dev_priv->dpio_lock); + free_completion(&dev_priv->error_completion); + mtx_destroy(&dev_priv->irq_lock); mtx_destroy(&dev_priv->error_lock); - mtx_destroy(&dev_priv->error_completion_lock); - mtx_destroy(&dev_priv->rps_lock); + mtx_destroy(&dev_priv->rps.lock); + sx_destroy(&dev_priv->dpio_lock); + + sx_destroy(&dev_priv->rps.hw_lock); + +#ifdef __linux__ + pci_dev_put(dev_priv->bridge_dev); +#endif free(dev->dev_private, DRM_MEM_DRIVER); return 0; @@ -1535,11 +1833,14 @@ int i915_driver_open(struct drm_device *dev, struct drm_file *file) { struct drm_i915_file_private *file_priv; + DRM_DEBUG_DRIVER("\n"); file_priv = malloc(sizeof(*file_priv), DRM_MEM_FILES, M_WAITOK | M_ZERO); + if (!file_priv) + return -ENOMEM; file->driver_priv = file_priv; - mtx_init(&file_priv->mm.lck, "915fp", NULL, MTX_DEF); + mtx_init(&file_priv->mm.lock, "915fp", NULL, MTX_DEF); INIT_LIST_HEAD(&file_priv->mm.request_list); drm_gem_names_init(&file_priv->context_idr); @@ -1570,10 +1871,8 @@ void i915_driver_lastclose(struct drm_device * dev) return; if (drm_core_check_feature(dev, DRIVER_MODESET)) { -#if 1 - KIB_NOTYET(); -#else - drm_fb_helper_restore(); + intel_fb_restore_mode(dev); +#ifdef __linux__ vga_switcheroo_process_delayed_switch(); #endif return; @@ -1594,104 +1893,62 @@ void i915_driver_postclose(struct drm_device *dev, struct drm_file *file) { struct drm_i915_file_private *file_priv = file->driver_priv; - mtx_destroy(&file_priv->mm.lck); + mtx_destroy(&file_priv->mm.lock); free(file_priv, DRM_MEM_FILES); } struct drm_ioctl_desc i915_ioctls[] = { - DRM_IOCTL_DEF(DRM_I915_INIT, i915_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_I915_FLUSH, i915_flush_ioctl, DRM_AUTH), - DRM_IOCTL_DEF(DRM_I915_FLIP, i915_flip_bufs, DRM_AUTH), - DRM_IOCTL_DEF(DRM_I915_BATCHBUFFER, i915_batchbuffer, DRM_AUTH), - DRM_IOCTL_DEF(DRM_I915_IRQ_EMIT, i915_irq_emit, DRM_AUTH), - DRM_IOCTL_DEF(DRM_I915_IRQ_WAIT, i915_irq_wait, DRM_AUTH), - DRM_IOCTL_DEF(DRM_I915_GETPARAM, i915_getparam, DRM_AUTH), - DRM_IOCTL_DEF(DRM_I915_SETPARAM, i915_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_I915_ALLOC, drm_noop, DRM_AUTH), - DRM_IOCTL_DEF(DRM_I915_FREE, drm_noop, DRM_AUTH), - DRM_IOCTL_DEF(DRM_I915_INIT_HEAP, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_I915_CMDBUFFER, i915_cmdbuffer, DRM_AUTH), - DRM_IOCTL_DEF(DRM_I915_DESTROY_HEAP, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY ), - DRM_IOCTL_DEF(DRM_I915_SET_VBLANK_PIPE, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY ), - DRM_IOCTL_DEF(DRM_I915_GET_VBLANK_PIPE, i915_vblank_pipe_get, DRM_AUTH ), - DRM_IOCTL_DEF(DRM_I915_VBLANK_SWAP, i915_vblank_swap, DRM_AUTH), - DRM_IOCTL_DEF(DRM_I915_HWS_ADDR, i915_set_status_page, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_I915_GEM_INIT, i915_gem_init_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I915_GEM_EXECBUFFER, i915_gem_execbuffer, DRM_AUTH | DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I915_GEM_EXECBUFFER2, i915_gem_execbuffer2, DRM_AUTH | DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I915_GEM_PIN, i915_gem_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I915_GEM_UNPIN, i915_gem_unpin_ioctl, DRM_AUTH|DRM_ROOT_ONLY|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I915_GEM_BUSY, i915_gem_busy_ioctl, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I915_GEM_THROTTLE, i915_gem_throttle_ioctl, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I915_GEM_ENTERVT, i915_gem_entervt_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I915_GEM_LEAVEVT, i915_gem_leavevt_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I915_GEM_CREATE, i915_gem_create_ioctl, DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I915_GEM_PREAD, i915_gem_pread_ioctl, DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I915_GEM_PWRITE, i915_gem_pwrite_ioctl, DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I915_GEM_MMAP, i915_gem_mmap_ioctl, DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I915_GEM_MMAP_GTT, i915_gem_mmap_gtt_ioctl, DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I915_GEM_SET_DOMAIN, i915_gem_set_domain_ioctl, DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I915_GEM_SW_FINISH, i915_gem_sw_finish_ioctl, DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I915_GEM_SET_TILING, i915_gem_set_tiling, DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I915_GEM_GET_TILING, i915_gem_get_tiling, DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I915_GEM_GET_APERTURE, i915_gem_get_aperture_ioctl, DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I915_GET_PIPE_FROM_CRTC_ID, intel_get_pipe_from_crtc_id, DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I915_GEM_MADVISE, i915_gem_madvise_ioctl, DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I915_OVERLAY_PUT_IMAGE, intel_overlay_put_image, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I915_OVERLAY_ATTRS, intel_overlay_attrs, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I915_SET_SPRITE_COLORKEY, intel_sprite_set_colorkey, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I915_GET_SPRITE_COLORKEY, intel_sprite_get_colorkey, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I915_GEM_CONTEXT_CREATE, i915_gem_context_create_ioctl, DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I915_GEM_CONTEXT_DESTROY, i915_gem_context_destroy_ioctl, DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_INIT, i915_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(I915_FLUSH, i915_flush_ioctl, DRM_AUTH), + DRM_IOCTL_DEF_DRV(I915_FLIP, i915_flip_bufs, DRM_AUTH), + DRM_IOCTL_DEF_DRV(I915_BATCHBUFFER, i915_batchbuffer, DRM_AUTH), + DRM_IOCTL_DEF_DRV(I915_IRQ_EMIT, i915_irq_emit, DRM_AUTH), + DRM_IOCTL_DEF_DRV(I915_IRQ_WAIT, i915_irq_wait, DRM_AUTH), + DRM_IOCTL_DEF_DRV(I915_GETPARAM, i915_getparam, DRM_AUTH), + DRM_IOCTL_DEF_DRV(I915_SETPARAM, i915_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(I915_ALLOC, drm_noop, DRM_AUTH), + DRM_IOCTL_DEF_DRV(I915_FREE, drm_noop, DRM_AUTH), + DRM_IOCTL_DEF_DRV(I915_INIT_HEAP, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(I915_CMDBUFFER, i915_cmdbuffer, DRM_AUTH), + DRM_IOCTL_DEF_DRV(I915_DESTROY_HEAP, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(I915_SET_VBLANK_PIPE, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(I915_GET_VBLANK_PIPE, i915_vblank_pipe_get, DRM_AUTH), + DRM_IOCTL_DEF_DRV(I915_VBLANK_SWAP, i915_vblank_swap, DRM_AUTH), + DRM_IOCTL_DEF_DRV(I915_HWS_ADDR, i915_set_status_page, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(I915_GEM_INIT, i915_gem_init_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_EXECBUFFER, i915_gem_execbuffer, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_EXECBUFFER2, i915_gem_execbuffer2, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_PIN, i915_gem_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_UNPIN, i915_gem_unpin_ioctl, DRM_AUTH|DRM_ROOT_ONLY|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_BUSY, i915_gem_busy_ioctl, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_SET_CACHING, i915_gem_set_caching_ioctl, DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_GET_CACHING, i915_gem_get_caching_ioctl, DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_THROTTLE, i915_gem_throttle_ioctl, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_ENTERVT, i915_gem_entervt_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_LEAVEVT, i915_gem_leavevt_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_CREATE, i915_gem_create_ioctl, DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_PREAD, i915_gem_pread_ioctl, DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_PWRITE, i915_gem_pwrite_ioctl, DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_MMAP, i915_gem_mmap_ioctl, DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_MMAP_GTT, i915_gem_mmap_gtt_ioctl, DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_SET_DOMAIN, i915_gem_set_domain_ioctl, DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_SW_FINISH, i915_gem_sw_finish_ioctl, DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_SET_TILING, i915_gem_set_tiling, DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_GET_TILING, i915_gem_get_tiling, DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_GET_APERTURE, i915_gem_get_aperture_ioctl, DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GET_PIPE_FROM_CRTC_ID, intel_get_pipe_from_crtc_id, DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_MADVISE, i915_gem_madvise_ioctl, DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_OVERLAY_PUT_IMAGE, intel_overlay_put_image, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_OVERLAY_ATTRS, intel_overlay_attrs, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_SET_SPRITE_COLORKEY, intel_sprite_set_colorkey, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GET_SPRITE_COLORKEY, intel_sprite_get_colorkey, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_WAIT, i915_gem_wait_ioctl, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_CREATE, i915_gem_context_create_ioctl, DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_DESTROY, i915_gem_context_destroy_ioctl, DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_REG_READ, i915_reg_read_ioctl, DRM_UNLOCKED), }; -#ifdef COMPAT_FREEBSD32 -extern struct drm_ioctl_desc i915_compat_ioctls[]; -extern int i915_compat_ioctls_nr; -#endif - -struct drm_driver i915_driver_info = { - /* - * FIXME Linux<->FreeBSD: DRIVER_USE_MTRR is commented out on - * Linux. - */ - .driver_features = - DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR | - DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM | DRIVER_PRIME, - - .buf_priv_size = sizeof(drm_i915_private_t), - .load = i915_driver_load, - .open = i915_driver_open, - .unload = i915_driver_unload, - .preclose = i915_driver_preclose, - .lastclose = i915_driver_lastclose, - .postclose = i915_driver_postclose, - .device_is_agp = i915_driver_device_is_agp, - .master_create = i915_master_create, - .master_destroy = i915_master_destroy, - .gem_init_object = i915_gem_init_object, - .gem_free_object = i915_gem_free_object, - .gem_pager_ops = &i915_gem_pager_ops, - .dumb_create = i915_gem_dumb_create, - .dumb_map_offset = i915_gem_mmap_gtt, - .dumb_destroy = i915_gem_dumb_destroy, - .sysctl_init = i915_sysctl_init, - .sysctl_cleanup = i915_sysctl_cleanup, - - .ioctls = i915_ioctls, -#ifdef COMPAT_FREEBSD32 - .compat_ioctls = i915_compat_ioctls, - .num_compat_ioctls = &i915_compat_ioctls_nr, -#endif - .num_ioctls = ARRAY_SIZE(i915_ioctls), - - .name = DRIVER_NAME, - .desc = DRIVER_DESC, - .date = DRIVER_DATE, - .major = DRIVER_MAJOR, - .minor = DRIVER_MINOR, - .patchlevel = DRIVER_PATCHLEVEL, -}; +int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); /* * This is really ugly: Because old userspace abused the linux agp interface to |