Commit 310b411f authored by Linus Torvalds's avatar Linus Torvalds

DRI CVS update: bump i810 driver to 1.4.

This fixes the DMA interface to be backwards compatible with older
XFree86 versions, by looking at the I810_INIT_DMA parameters and
figuring out old version semantics.
parent 31f673f0
......@@ -55,9 +55,10 @@
* 1.2.1 - Disable copying code (leave stub ioctls for backwards compatibility)
* - Remove requirement for interrupt (leave stubs again)
* 1.3 - Add page flipping.
* 1.4 - fix DRM interface
*/
#define DRIVER_MAJOR 1
#define DRIVER_MINOR 3
#define DRIVER_MINOR 4
#define DRIVER_PATCHLEVEL 0
#define DRIVER_IOCTLS \
......
......@@ -443,6 +443,49 @@ static int i810_dma_initialize(drm_device_t *dev,
return 0;
}
/* i810 DRM version 1.1 used a smaller init structure with different
* ordering of values than is currently used (drm >= 1.2). There is
* no defined way to detect the XFree version to correct this problem,
* however by checking using this procedure we can detect the correct
* thing to do.
*
* #1 Read the Smaller init structure from user-space
* #2 Verify the overlay_physical is a valid physical address, or NULL
* If it isn't then we have a v1.1 client. Fix up params.
* If it is, then we have a 1.2 client... get the rest of the data.
*/
int i810_dma_init_compat(drm_i810_init_t *init, unsigned long arg)
{
/* Get v1.1 init data */
if (copy_from_user(init, (drm_i810_pre12_init_t *)arg,
sizeof(drm_i810_pre12_init_t))) {
return -EFAULT;
}
if ((!init->overlay_physical) || (init->overlay_physical > 4096)) {
/* This is a v1.2 client, just get the v1.2 init data */
DRM_INFO("Using POST v1.2 init.\n");
if(copy_from_user(init, (drm_i810_init_t *)arg,
sizeof(drm_i810_init_t))) {
return -EFAULT;
}
} else {
/* This is a v1.1 client, fix the params */
DRM_INFO("Using PRE v1.2 init.\n");
init->pitch_bits = init->h;
init->pitch = init->w;
init->h = init->overlay_physical;
init->w = init->overlay_offset;
init->overlay_physical = 0;
init->overlay_offset = 0;
}
return 0;
}
int i810_dma_init(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
......@@ -452,22 +495,46 @@ int i810_dma_init(struct inode *inode, struct file *filp,
drm_i810_init_t init;
int retcode = 0;
if (copy_from_user(&init, (drm_i810_init_t *)arg, sizeof(init)))
/* Get only the init func */
if (copy_from_user(&init, (void *)arg, sizeof(drm_i810_init_func_t)))
return -EFAULT;
switch(init.func) {
case I810_INIT_DMA:
/* This case is for backward compatibility. It
* handles XFree 4.1.0 and 4.2.0, and has to
* do some parameter checking as described below.
* It will someday go away.
*/
retcode = i810_dma_init_compat(&init, arg);
if (retcode)
return retcode;
dev_priv = DRM(alloc)(sizeof(drm_i810_private_t),
DRM_MEM_DRIVER);
if(dev_priv == NULL) return -ENOMEM;
if (dev_priv == NULL)
return -ENOMEM;
retcode = i810_dma_initialize(dev, dev_priv, &init);
break;
default:
case I810_INIT_DMA_1_4:
DRM_INFO("Using v1.4 init.\n");
if (copy_from_user(&init, (drm_i810_init_t *)arg,
sizeof(drm_i810_init_t))) {
return -EFAULT;
}
dev_priv = DRM(alloc)(sizeof(drm_i810_private_t),
DRM_MEM_DRIVER);
if (dev_priv == NULL)
return -ENOMEM;
retcode = i810_dma_initialize(dev, dev_priv, &init);
break;
case I810_CLEANUP_DMA:
DRM_INFO("DMA Cleanup\n");
retcode = i810_dma_cleanup(dev);
break;
default:
retcode = -EINVAL;
break;
}
return retcode;
......@@ -477,12 +544,16 @@ int i810_dma_init(struct inode *inode, struct file *filp,
/* Most efficient way to verify state for the i810 is as it is
* emitted. Non-conformant state is silently dropped.
*
* Use 'volatile' & local var tmp to force the emitted values to be
* identical to the verified ones.
*/
static void i810EmitContextVerified( drm_device_t *dev,
unsigned int *code )
volatile unsigned int *code )
{
drm_i810_private_t *dev_priv = dev->dev_private;
int i, j = 0;
unsigned int tmp;
RING_LOCALS;
BEGIN_LP_RING( I810_CTX_SETUP_SIZE );
......@@ -494,10 +565,12 @@ static void i810EmitContextVerified( drm_device_t *dev,
OUT_RING( code[I810_CTXREG_ST1] );
for ( i = 4 ; i < I810_CTX_SETUP_SIZE ; i++ ) {
if ((code[i] & (7<<29)) == (3<<29) &&
(code[i] & (0x1f<<24)) < (0x1d<<24))
tmp = code[i];
if ((tmp & (7<<29)) == (3<<29) &&
(tmp & (0x1f<<24)) < (0x1d<<24))
{
OUT_RING( code[i] );
OUT_RING( tmp );
j++;
}
else printk("constext state dropped!!!\n");
......@@ -514,6 +587,7 @@ static void i810EmitTexVerified( drm_device_t *dev,
{
drm_i810_private_t *dev_priv = dev->dev_private;
int i, j = 0;
unsigned int tmp;
RING_LOCALS;
BEGIN_LP_RING( I810_TEX_SETUP_SIZE );
......@@ -524,11 +598,12 @@ static void i810EmitTexVerified( drm_device_t *dev,
OUT_RING( code[I810_TEXREG_MI3] );
for ( i = 4 ; i < I810_TEX_SETUP_SIZE ; i++ ) {
tmp = code[i];
if ((code[i] & (7<<29)) == (3<<29) &&
(code[i] & (0x1f<<24)) < (0x1d<<24))
if ((tmp & (7<<29)) == (3<<29) &&
(tmp & (0x1f<<24)) < (0x1d<<24))
{
OUT_RING( code[i] );
OUT_RING( tmp );
j++;
}
else printk("texture state dropped!!!\n");
......@@ -556,9 +631,9 @@ static void i810EmitDestVerified( drm_device_t *dev,
if (tmp == dev_priv->front_di1 || tmp == dev_priv->back_di1) {
OUT_RING( CMD_OP_DESTBUFFER_INFO );
OUT_RING( tmp );
}
else
printk("buffer state dropped\n");
} else
DRM_DEBUG("bad di1 %x (allow %x or %x)\n",
tmp, dev_priv->front_di1, dev_priv->back_di1);
/* invarient:
*/
......@@ -986,6 +1061,9 @@ int i810_dma_vertex(struct inode *inode, struct file *filp,
return -EINVAL;
}
DRM_DEBUG("i810 dma vertex, idx %d used %d discard %d\n",
vertex.idx, vertex.used, vertex.discard);
if(vertex.idx < 0 || vertex.idx > dma->buf_count) return -EINVAL;
i810_dma_dispatch_vertex( dev,
......@@ -1034,6 +1112,8 @@ int i810_swap_bufs(struct inode *inode, struct file *filp,
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->dev;
DRM_DEBUG("i810_swap_bufs\n");
if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
DRM_ERROR("i810_swap_buf called without lock held\n");
return -EINVAL;
......@@ -1081,6 +1161,9 @@ int i810_getbuf(struct inode *inode, struct file *filp, unsigned int cmd,
retcode = i810_dma_get_buffer(dev, &d, filp);
DRM_DEBUG("i810_dma: %d returning %d, granted = %d\n",
current->pid, retcode, d.granted);
if (copy_to_user((drm_dma_t *)arg, &d, sizeof(d)))
return -EFAULT;
sarea_priv->last_dispatch = (int) hw_status[5];
......
......@@ -94,12 +94,15 @@
#define I810_BACK 0x2
#define I810_DEPTH 0x4
typedef enum _drm_i810_init_func {
I810_INIT_DMA = 0x01,
I810_CLEANUP_DMA = 0x02,
I810_INIT_DMA_1_4 = 0x03
} drm_i810_init_func_t;
/* This is the init structure after v1.2 */
typedef struct _drm_i810_init {
enum {
I810_INIT_DMA = 0x01,
I810_CLEANUP_DMA = 0x02
} func;
drm_i810_init_func_t func;
#if CONFIG_XFREE86_VERSION < XFREE86_VERSION(4,1,0,0)
int ring_map_idx;
int buffer_map_idx;
......@@ -122,6 +125,24 @@ typedef struct _drm_i810_init {
unsigned int pitch_bits;
} drm_i810_init_t;
/* This is the init structure prior to v1.2 */
typedef struct _drm_i810_pre12_init {
drm_i810_init_func_t func;
unsigned int mmio_offset;
unsigned int buffers_offset;
int sarea_priv_offset;
unsigned int ring_start;
unsigned int ring_end;
unsigned int ring_size;
unsigned int front_offset;
unsigned int back_offset;
unsigned int depth_offset;
unsigned int w;
unsigned int h;
unsigned int pitch;
unsigned int pitch_bits;
} drm_i810_pre12_init_t;
/* Warning: If you change the SAREA structure you must change the Xserver
* structure as well */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment