summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@redhat.com>2008-02-05 13:27:16 -0500
committerKristian Høgsberg <krh@sasori.boston.redhat.com>2008-02-13 13:34:02 -0500
commit373dbcf8b25750967e9ba24433cff872df41cb74 (patch)
treee063d32f1825fc96e71c76bd4ed808f4b534276b
parentdb3f03ae3538bea3d29ef66ac24d9a1f54cff418 (diff)
i915: Add a dri2 init path that gets the lock from the dri2 sarea.
-rw-r--r--shared-core/i915_dma.c94
-rw-r--r--shared-core/i915_drm.h8
-rw-r--r--shared-core/i915_drv.h4
3 files changed, 103 insertions, 3 deletions
diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c
index fc009204..3874ed58 100644
--- a/shared-core/i915_dma.c
+++ b/shared-core/i915_dma.c
@@ -106,9 +106,73 @@ static int i915_dma_cleanup(struct drm_device * dev)
return 0;
}
-static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
+
+#define DRI2_SAREA_BLOCK_TYPE(b) ((b) >> 16)
+#define DRI2_SAREA_BLOCK_SIZE(b) ((b) & 0xffff)
+#define DRI2_SAREA_BLOCK_NEXT(p) \
+ ((void *) ((unsigned char *) (p) + \
+ DRI2_SAREA_BLOCK_SIZE(*(unsigned int *) p)))
+
+#define DRI2_SAREA_BLOCK_END 0x0000
+#define DRI2_SAREA_BLOCK_LOCK 0x0001
+#define DRI2_SAREA_BLOCK_EVENT_BUFFER 0x0002
+
+static int
+setup_dri2_sarea(struct drm_device * dev,
+ struct drm_file *file_priv,
+ drm_i915_init_t * init)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ int ret;
+ unsigned int *p, *end, *next;
+
+ mutex_lock(&dev->struct_mutex);
+ dev_priv->sarea_bo =
+ drm_lookup_buffer_object(file_priv,
+ init->sarea_handle, 1);
+ mutex_unlock(&dev->struct_mutex);
+
+ if (!dev_priv->sarea_bo) {
+ DRM_ERROR("did not find sarea bo\n");
+ return -EINVAL;
+ }
+
+ ret = drm_bo_kmap(dev_priv->sarea_bo, 0,
+ dev_priv->sarea_bo->num_pages,
+ &dev_priv->sarea_kmap);
+ if (ret) {
+ DRM_ERROR("could not map sarea bo\n");
+ return ret;
+ }
+
+ p = dev_priv->sarea_kmap.virtual;
+ end = (void *) p + (dev_priv->sarea_bo->num_pages << PAGE_SHIFT);
+ while (p < end && DRI2_SAREA_BLOCK_TYPE(*p) != DRI2_SAREA_BLOCK_END) {
+ switch (DRI2_SAREA_BLOCK_TYPE(*p)) {
+ case DRI2_SAREA_BLOCK_LOCK:
+ dev->lock.hw_lock = (void *) (p + 1);
+ dev->sigdata.lock = dev->lock.hw_lock;
+ break;
+ }
+ next = DRI2_SAREA_BLOCK_NEXT(p);
+ if (next <= p || end < next) {
+ DRM_ERROR("malformed dri2 sarea: next is %p should be within %p-%p\n",
+ next, p, end);
+ return -EINVAL;
+ }
+ p = next;
+ }
+
+ return 0;
+}
+
+
+static int i915_initialize(struct drm_device * dev,
+ struct drm_file *file_priv,
+ 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) {
@@ -201,6 +265,17 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
#ifdef I915_HAVE_BUFFER
mutex_init(&dev_priv->cmdbuf_mutex);
#endif
+
+ if (init->func == I915_INIT_DMA2) {
+ ret = setup_dri2_sarea(dev, file_priv, init);
+ if (ret) {
+ i915_dma_cleanup(dev);
+ DRM_ERROR("could not set up dri2 sarea\n");
+ return ret;
+ }
+ }
+
+
return 0;
}
@@ -250,7 +325,8 @@ static int i915_dma_init(struct drm_device *dev, void *data,
switch (init->func) {
case I915_INIT_DMA:
- retcode = i915_initialize(dev, init);
+ case I915_INIT_DMA2:
+ retcode = i915_initialize(dev, file_priv, init);
break;
case I915_CLEANUP_DMA:
retcode = i915_dma_cleanup(dev);
@@ -1415,6 +1491,20 @@ void i915_driver_lastclose(struct drm_device * dev)
if (dev_priv->agp_heap)
i915_mem_takedown(&(dev_priv->agp_heap));
+ if (dev_priv->sarea_kmap.virtual) {
+ drm_bo_kunmap(&dev_priv->sarea_kmap);
+ dev_priv->sarea_kmap.virtual = NULL;
+ dev->lock.hw_lock = NULL;
+ dev->sigdata.lock = NULL;
+ }
+
+ if (dev_priv->sarea_bo) {
+ mutex_lock(&dev->struct_mutex);
+ drm_bo_usage_deref_locked(&dev_priv->sarea_bo);
+ mutex_unlock(&dev->struct_mutex);
+ dev_priv->sarea_bo = NULL;
+ }
+
i915_dma_cleanup(dev);
}
diff --git a/shared-core/i915_drm.h b/shared-core/i915_drm.h
index ad0797c2..b889a303 100644
--- a/shared-core/i915_drm.h
+++ b/shared-core/i915_drm.h
@@ -43,7 +43,12 @@ typedef struct _drm_i915_init {
enum {
I915_INIT_DMA = 0x01,
I915_CLEANUP_DMA = 0x02,
- I915_RESUME_DMA = 0x03
+ I915_RESUME_DMA = 0x03,
+
+ /* Since this struct isn't versioned, just used a new
+ * 'func' code to indicate the presence of dri2 sarea
+ * info. */
+ I915_INIT_DMA2 = 0x04
} func;
unsigned int mmio_offset;
int sarea_priv_offset;
@@ -61,6 +66,7 @@ typedef struct _drm_i915_init {
unsigned int depth_pitch;
unsigned int cpp;
unsigned int chipset;
+ unsigned int sarea_handle;
} drm_i915_init_t;
typedef struct _drm_i915_sarea {
diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h
index d08fdf40..76116df5 100644
--- a/shared-core/i915_drv.h
+++ b/shared-core/i915_drv.h
@@ -147,6 +147,10 @@ typedef struct drm_i915_private {
drm_i915_vbl_swap_t vbl_swaps;
unsigned int swaps_pending;
+ /* DRI2 sarea */
+ struct drm_buffer_object *sarea_bo;
+ struct drm_bo_kmap_obj sarea_kmap;
+
/* Register state */
u8 saveLBB;
u32 saveDSPACNTR;