diff options
| -rw-r--r-- | shared-core/i915_dma.c | 94 | ||||
| -rw-r--r-- | shared-core/i915_drm.h | 8 | ||||
| -rw-r--r-- | shared-core/i915_drv.h | 4 | 
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;  | 
