mirror of
https://gitlab.freedesktop.org/mesa/drm.git
synced 2025-12-27 05:50:11 +01:00
Move i915 to "cleaner" ioctl interface
This is just an idea at this stage, some ioctls don't lend themselves to this type of thing, mostly ones which needs multiple levels of copy_from_user to bring across structs from userspace
This commit is contained in:
parent
feb6803778
commit
d21a889fe8
6 changed files with 606 additions and 403 deletions
|
|
@ -19,7 +19,7 @@ r128-objs := r128_drv.o r128_cce.o r128_state.o r128_irq.o
|
|||
mga-objs := mga_drv.o mga_dma.o mga_state.o mga_warp.o mga_irq.o
|
||||
i810-objs := i810_drv.o i810_dma.o
|
||||
i915-objs := i915_drv.o i915_dma.o i915_irq.o i915_mem.o i915_fence.o \
|
||||
i915_buffer.o
|
||||
i915_buffer.o i915_ioctl.o
|
||||
nouveau-objs := nouveau_drv.o nouveau_state.o nouveau_fifo.o nouveau_mem.o \
|
||||
nouveau_object.o nouveau_irq.o \
|
||||
nv04_timer.o \
|
||||
|
|
|
|||
440
linux-core/i915_ioctl.c
Normal file
440
linux-core/i915_ioctl.c
Normal file
|
|
@ -0,0 +1,440 @@
|
|||
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "i915_drm.h"
|
||||
#include "i915_drv.h"
|
||||
/* ioctl wrappers for Linux for i915 */
|
||||
|
||||
static int i915_dma_init_ioctl(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_i915_init_t init;
|
||||
drm_i915_init_t __user *argp = (void __user *)arg;
|
||||
int retcode = 0;
|
||||
|
||||
if (copy_from_user(&init, argp, sizeof(init)))
|
||||
return -EFAULT;
|
||||
|
||||
retcode = i915_dma_init(dev, &init);
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
||||
static int i915_flush_ioctl(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
|
||||
LOCK_TEST_WITH_RETURN(dev, filp);
|
||||
|
||||
return i915_quiescent(dev);
|
||||
}
|
||||
|
||||
static int i915_flip_ioctl(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_i915_flip_t param;
|
||||
drm_i915_flip_t __user *argp = (void __user *)arg;
|
||||
|
||||
DRM_DEBUG("%s\n", __FUNCTION__);
|
||||
|
||||
LOCK_TEST_WITH_RETURN(dev, filp);
|
||||
|
||||
if (copy_from_user(¶m, argp, sizeof(param)))
|
||||
return -EFAULT;
|
||||
|
||||
if (param.pipes & ~0x3) {
|
||||
DRM_ERROR("Invalid pipes 0x%x, only <= 0x3 is valid\n",
|
||||
param.pipes);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
i915_dispatch_flip(dev, param.pipes, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i915_batchbuffer_ioctl(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
drm_i915_batchbuffer_t batch;
|
||||
drm_i915_batchbuffer_t __user *argp = (void __user *)arg;
|
||||
int ret;
|
||||
|
||||
if (!dev_priv->allow_batchbuffer) {
|
||||
DRM_ERROR("Batchbuffer ioctl disabled\n");
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
if (copy_from_user(&batch, argp, sizeof(batch)))
|
||||
return -EFAULT;
|
||||
|
||||
DRM_DEBUG("i915 batchbuffer, start %x used %d cliprects %d\n",
|
||||
batch.start, batch.used, batch.num_cliprects);
|
||||
|
||||
LOCK_TEST_WITH_RETURN(dev, filp);
|
||||
|
||||
if (batch.num_cliprects)
|
||||
if (!access_ok(VERIFY_READ, batch.cliprects,
|
||||
batch.num_cliprects *
|
||||
sizeof(drm_clip_rect_t)))
|
||||
return -EFAULT;
|
||||
|
||||
ret = i915_dispatch_batchbuffer(dev, &batch);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int i915_cmdbuffer_ioctl(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_i915_cmdbuffer_t cmdbuf;
|
||||
drm_i915_cmdbuffer_t __user *argp = (void __user *)arg;
|
||||
|
||||
if (copy_from_user(&cmdbuf, argp, sizeof(cmdbuf)))
|
||||
return -EFAULT;
|
||||
|
||||
DRM_DEBUG("i915 cmdbuffer, buf %p sz %d cliprects %d\n",
|
||||
cmdbuf.buf, cmdbuf.sz, cmdbuf.num_cliprects);
|
||||
|
||||
LOCK_TEST_WITH_RETURN(dev, filp);
|
||||
|
||||
if (cmdbuf.num_cliprects)
|
||||
if (!access_ok(VERIFY_READ, cmdbuf.cliprects,
|
||||
cmdbuf.num_cliprects *
|
||||
sizeof(drm_clip_rect_t))) {
|
||||
DRM_ERROR("Fault accessing cliprects\n");
|
||||
return DRM_ERR(EFAULT);
|
||||
}
|
||||
|
||||
return i915_dispatch_cmdbuffer(dev, &cmdbuf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Needs the lock as it touches the ring.
|
||||
*/
|
||||
static int i915_irq_emit_ioctl(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
drm_i915_irq_emit_t emit;
|
||||
drm_i915_irq_emit_t __user *argp = (void __user *)arg;
|
||||
int result;
|
||||
|
||||
LOCK_TEST_WITH_RETURN(dev, filp);
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
if (copy_from_user(&emit, argp, sizeof(emit)))
|
||||
return -EFAULT;
|
||||
|
||||
result = i915_emit_irq(dev);
|
||||
|
||||
if (copy_to_user(emit.irq_seq, &result, sizeof(int)))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Doesn't need the hardware lock.
|
||||
*/
|
||||
static int i915_irq_wait_ioctl(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
drm_i915_irq_wait_t irqwait;
|
||||
drm_i915_irq_wait_t __user *argp = (void __user *)arg;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
if (copy_from_user(&irqwait, argp, sizeof(irqwait)))
|
||||
return -EFAULT;
|
||||
|
||||
return i915_wait_irq(dev, irqwait.irq_seq);
|
||||
}
|
||||
|
||||
static int i915_getparam_ioctl(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
drm_i915_getparam_t param;
|
||||
drm_i915_getparam_t __user *argp = (void __user *)arg;
|
||||
int retcode;
|
||||
int value;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (copy_from_user(¶m, argp, sizeof(param)))
|
||||
return -EFAULT;
|
||||
|
||||
retcode = i915_getparam(dev, ¶m, &value);
|
||||
if (!retcode) {
|
||||
if (copy_to_user(param.value, &value, sizeof(int)))
|
||||
return -EFAULT;
|
||||
}
|
||||
return retcode;
|
||||
}
|
||||
|
||||
static int i915_setparam_ioctl(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
drm_i915_setparam_t param;
|
||||
drm_i915_setparam_t __user *argp = (void __user *)arg;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (copy_from_user(¶m, argp, sizeof(param)))
|
||||
return -EFAULT;
|
||||
|
||||
return i915_setparam(dev, ¶m);
|
||||
}
|
||||
|
||||
static int i915_mmio_ioctl(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
drm_i915_mmio_t mmio;
|
||||
drm_i915_mmio_t __user *argp = (void __user *)arg;
|
||||
char buf[32];
|
||||
int retcode = 0;
|
||||
int size;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
if (copy_from_user(&mmio, argp, sizeof(mmio)))
|
||||
return -EFAULT;
|
||||
|
||||
if (i915_mmio_get_size(dev, &mmio, &size))
|
||||
return -EINVAL;
|
||||
|
||||
switch(mmio.read_write) {
|
||||
case I915_MMIO_READ:
|
||||
retcode = i915_mmio_read(dev, &mmio, buf);
|
||||
if (retcode)
|
||||
return retcode;
|
||||
if (copy_to_user(mmio.data, buf, size))
|
||||
return -EFAULT;
|
||||
break;
|
||||
case I915_MMIO_WRITE:
|
||||
if (copy_from_user(buf, mmio.data, size))
|
||||
return -EFAULT;
|
||||
retcode = i915_mmio_write(dev, &mmio, buf);
|
||||
}
|
||||
return retcode;
|
||||
}
|
||||
|
||||
static int i915_mem_alloc_ioctl(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
drm_i915_mem_alloc_t alloc;
|
||||
drm_i915_mem_alloc_t __user *argp = (void __user *)arg;
|
||||
int retcode;
|
||||
int start;
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if(copy_from_user(&alloc, argp, sizeof(alloc)))
|
||||
return -EFAULT;
|
||||
|
||||
retcode = i915_mem_alloc(dev, &alloc, filp, &start);
|
||||
|
||||
if (!retcode) {
|
||||
if (copy_to_user(alloc.region_offset, &start, sizeof(int)))
|
||||
return -EFAULT;
|
||||
}
|
||||
return retcode;
|
||||
}
|
||||
|
||||
static int i915_mem_free_ioctl(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
drm_i915_mem_free_t memfree;
|
||||
drm_i915_mem_free_t __user *argp = (void __user *)arg;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
if (copy_from_user(&memfree, argp, sizeof(memfree)))
|
||||
return -EFAULT;
|
||||
|
||||
return i915_mem_free(dev, &memfree, filp);
|
||||
}
|
||||
|
||||
static int i915_mem_init_heap_ioctl(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
drm_i915_mem_init_heap_t initheap;
|
||||
drm_i915_mem_init_heap_t __user *argp = (void __user *)arg;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
if (copy_from_user(&initheap, argp, sizeof(initheap)))
|
||||
return -EFAULT;
|
||||
|
||||
return i915_mem_init_heap(dev, &initheap);
|
||||
}
|
||||
|
||||
static int i915_mem_destroy_heap_ioctl(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
drm_i915_mem_destroy_heap_t destroyheap;
|
||||
drm_i915_mem_destroy_heap_t __user *argp = (void __user *)arg;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
if (copy_from_user(&destroyheap, argp, sizeof(destroyheap)))
|
||||
return -EFAULT;
|
||||
|
||||
return i915_mem_destroy_heap(dev, &destroyheap);
|
||||
}
|
||||
|
||||
static int i915_vblank_pipe_set_ioctl(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
drm_i915_vblank_pipe_t pipe;
|
||||
drm_i915_vblank_pipe_t __user *argp = (void __user *)arg;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
if (copy_from_user(&pipe, argp, sizeof(pipe)))
|
||||
return -EFAULT;
|
||||
|
||||
return i915_vblank_pipe_set(dev, &pipe);
|
||||
}
|
||||
|
||||
static int i915_vblank_pipe_get_ioctl(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
drm_i915_vblank_pipe_t pipe;
|
||||
drm_i915_vblank_pipe_t __user *argp = (void __user *)arg;
|
||||
int retcode;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
retcode = i915_vblank_pipe_get(dev, &pipe);
|
||||
|
||||
if (copy_to_user(argp, &pipe, sizeof(pipe)))
|
||||
return -EFAULT;
|
||||
return retcode;
|
||||
}
|
||||
|
||||
static int i915_vblank_swap_ioctl(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
drm_i915_vblank_swap_t swap;
|
||||
drm_i915_vblank_swap_t __user *argp = (void __user *)arg;
|
||||
int retcode;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (copy_from_user(&swap, argp, sizeof(swap)))
|
||||
return -EFAULT;
|
||||
|
||||
retcode = i915_vblank_swap(dev, &swap, filp);
|
||||
|
||||
if (!retcode) {
|
||||
if (copy_to_user(argp, &swap, sizeof(swap)))
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
||||
drm_ioctl_desc_t i915_ioctls[] = {
|
||||
[DRM_IOCTL_NR(DRM_I915_INIT)] = {i915_dma_init_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
|
||||
[DRM_IOCTL_NR(DRM_I915_FLUSH)] = {i915_flush_ioctl, DRM_AUTH},
|
||||
[DRM_IOCTL_NR(DRM_I915_FLIP)] = {i915_flip_ioctl, DRM_AUTH},
|
||||
[DRM_IOCTL_NR(DRM_I915_BATCHBUFFER)] = {i915_batchbuffer_ioctl, DRM_AUTH},
|
||||
[DRM_IOCTL_NR(DRM_I915_IRQ_EMIT)] = {i915_irq_emit_ioctl, DRM_AUTH},
|
||||
[DRM_IOCTL_NR(DRM_I915_IRQ_WAIT)] = {i915_irq_wait_ioctl, DRM_AUTH},
|
||||
[DRM_IOCTL_NR(DRM_I915_GETPARAM)] = {i915_getparam_ioctl, DRM_AUTH},
|
||||
[DRM_IOCTL_NR(DRM_I915_SETPARAM)] = {i915_setparam_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
|
||||
[DRM_IOCTL_NR(DRM_I915_ALLOC)] = {i915_mem_alloc_ioctl, DRM_AUTH},
|
||||
[DRM_IOCTL_NR(DRM_I915_FREE)] = {i915_mem_free_ioctl, DRM_AUTH},
|
||||
[DRM_IOCTL_NR(DRM_I915_INIT_HEAP)] = {i915_mem_init_heap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
|
||||
[DRM_IOCTL_NR(DRM_I915_CMDBUFFER)] = {i915_cmdbuffer_ioctl, DRM_AUTH},
|
||||
[DRM_IOCTL_NR(DRM_I915_DESTROY_HEAP)] = { i915_mem_destroy_heap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
|
||||
[DRM_IOCTL_NR(DRM_I915_SET_VBLANK_PIPE)] = { i915_vblank_pipe_set_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
|
||||
[DRM_IOCTL_NR(DRM_I915_GET_VBLANK_PIPE)] = { i915_vblank_pipe_get_ioctl, DRM_AUTH },
|
||||
[DRM_IOCTL_NR(DRM_I915_VBLANK_SWAP)] = {i915_vblank_swap_ioctl, DRM_AUTH},
|
||||
[DRM_IOCTL_NR(DRM_I915_MMIO)] = {i915_mmio_ioctl, DRM_AUTH},
|
||||
};
|
||||
|
||||
int i915_max_ioctl = ARRAY_SIZE(i915_ioctls);
|
||||
|
|
@ -234,23 +234,19 @@ static int i915_dma_resume(drm_device_t * dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int i915_dma_init(DRM_IOCTL_ARGS)
|
||||
int i915_dma_init(struct drm_device *dev, drm_i915_init_t *init)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_i915_private_t *dev_priv;
|
||||
drm_i915_init_t init;
|
||||
|
||||
int retcode = 0;
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL(init, (drm_i915_init_t __user *) data,
|
||||
sizeof(init));
|
||||
|
||||
switch (init.func) {
|
||||
switch (init->func) {
|
||||
case I915_INIT_DMA:
|
||||
dev_priv = drm_alloc(sizeof(drm_i915_private_t),
|
||||
DRM_MEM_DRIVER);
|
||||
if (dev_priv == NULL)
|
||||
return DRM_ERR(ENOMEM);
|
||||
retcode = i915_initialize(dev, dev_priv, &init);
|
||||
retcode = i915_initialize(dev, dev_priv, init);
|
||||
break;
|
||||
case I915_CLEANUP_DMA:
|
||||
retcode = i915_dma_cleanup(dev);
|
||||
|
|
@ -464,16 +460,19 @@ int i915_emit_mi_flush(drm_device_t *dev, uint32_t flush)
|
|||
}
|
||||
|
||||
|
||||
static int i915_dispatch_cmdbuffer(drm_device_t * dev,
|
||||
drm_i915_cmdbuffer_t * cmd)
|
||||
int i915_dispatch_cmdbuffer(drm_device_t * dev,
|
||||
drm_i915_cmdbuffer_t * cmd)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
int nbox = cmd->num_cliprects;
|
||||
int i = 0, count, ret;
|
||||
int i = 0, count, ret = 0;
|
||||
drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
|
||||
dev_priv->sarea_priv;
|
||||
|
||||
if (cmd->sz & 0x3) {
|
||||
DRM_ERROR("alignment");
|
||||
return DRM_ERR(EINVAL);
|
||||
ret = DRM_ERR(EINVAL);
|
||||
goto out;
|
||||
}
|
||||
|
||||
i915_kernel_lost_context(dev);
|
||||
|
|
@ -485,33 +484,38 @@ static int i915_dispatch_cmdbuffer(drm_device_t * dev,
|
|||
ret = i915_emit_box(dev, cmd->cliprects, i,
|
||||
cmd->DR1, cmd->DR4);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = i915_emit_cmds(dev, (int __user *)cmd->buf, cmd->sz / 4);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto out;
|
||||
}
|
||||
|
||||
i915_emit_breadcrumb( dev );
|
||||
#ifdef I915_HAVE_FENCE
|
||||
drm_fence_flush_old(dev, 0, dev_priv->counter);
|
||||
#endif
|
||||
return 0;
|
||||
out:
|
||||
sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int i915_dispatch_batchbuffer(drm_device_t * dev,
|
||||
drm_i915_batchbuffer_t * batch)
|
||||
int i915_dispatch_batchbuffer(drm_device_t * dev,
|
||||
drm_i915_batchbuffer_t * batch)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
|
||||
dev_priv->sarea_priv;
|
||||
drm_clip_rect_t __user *boxes = batch->cliprects;
|
||||
int nbox = batch->num_cliprects;
|
||||
int i = 0, count;
|
||||
int i = 0, count, ret = 0;
|
||||
RING_LOCALS;
|
||||
|
||||
if ((batch->start | batch->used) & 0x7) {
|
||||
DRM_ERROR("alignment");
|
||||
return DRM_ERR(EINVAL);
|
||||
ret = DRM_ERR(EINVAL);
|
||||
goto out;
|
||||
}
|
||||
|
||||
i915_kernel_lost_context(dev);
|
||||
|
|
@ -523,7 +527,7 @@ static int i915_dispatch_batchbuffer(drm_device_t * dev,
|
|||
int ret = i915_emit_box(dev, boxes, i,
|
||||
batch->DR1, batch->DR4);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (dev_priv->use_mi_batchbuffer_start) {
|
||||
|
|
@ -545,7 +549,9 @@ static int i915_dispatch_batchbuffer(drm_device_t * dev,
|
|||
#ifdef I915_HAVE_FENCE
|
||||
drm_fence_flush_old(dev, 0, dev_priv->counter);
|
||||
#endif
|
||||
return 0;
|
||||
out:
|
||||
sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void i915_do_dispatch_flip(drm_device_t * dev, int pipe, int sync)
|
||||
|
|
@ -622,7 +628,7 @@ void i915_dispatch_flip(drm_device_t * dev, int pipes, int sync)
|
|||
#endif
|
||||
}
|
||||
|
||||
static int i915_quiescent(drm_device_t * dev)
|
||||
int i915_quiescent(drm_device_t *dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
|
|
@ -630,82 +636,6 @@ static int i915_quiescent(drm_device_t * dev)
|
|||
return i915_wait_ring(dev, dev_priv->ring.Size - 8, __FUNCTION__);
|
||||
}
|
||||
|
||||
static int i915_flush_ioctl(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
|
||||
LOCK_TEST_WITH_RETURN(dev, filp);
|
||||
|
||||
return i915_quiescent(dev);
|
||||
}
|
||||
|
||||
static int i915_batchbuffer(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
|
||||
dev_priv->sarea_priv;
|
||||
drm_i915_batchbuffer_t batch;
|
||||
int ret;
|
||||
|
||||
if (!dev_priv->allow_batchbuffer) {
|
||||
DRM_ERROR("Batchbuffer ioctl disabled\n");
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL(batch, (drm_i915_batchbuffer_t __user *) data,
|
||||
sizeof(batch));
|
||||
|
||||
DRM_DEBUG("i915 batchbuffer, start %x used %d cliprects %d\n",
|
||||
batch.start, batch.used, batch.num_cliprects);
|
||||
|
||||
LOCK_TEST_WITH_RETURN(dev, filp);
|
||||
|
||||
if (batch.num_cliprects && DRM_VERIFYAREA_READ(batch.cliprects,
|
||||
batch.num_cliprects *
|
||||
sizeof(drm_clip_rect_t)))
|
||||
return DRM_ERR(EFAULT);
|
||||
|
||||
ret = i915_dispatch_batchbuffer(dev, &batch);
|
||||
|
||||
sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int i915_cmdbuffer(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
|
||||
dev_priv->sarea_priv;
|
||||
drm_i915_cmdbuffer_t cmdbuf;
|
||||
int ret;
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL(cmdbuf, (drm_i915_cmdbuffer_t __user *) data,
|
||||
sizeof(cmdbuf));
|
||||
|
||||
DRM_DEBUG("i915 cmdbuffer, buf %p sz %d cliprects %d\n",
|
||||
cmdbuf.buf, cmdbuf.sz, cmdbuf.num_cliprects);
|
||||
|
||||
LOCK_TEST_WITH_RETURN(dev, filp);
|
||||
|
||||
if (cmdbuf.num_cliprects &&
|
||||
DRM_VERIFYAREA_READ(cmdbuf.cliprects,
|
||||
cmdbuf.num_cliprects *
|
||||
sizeof(drm_clip_rect_t))) {
|
||||
DRM_ERROR("Fault accessing cliprects\n");
|
||||
return DRM_ERR(EFAULT);
|
||||
}
|
||||
|
||||
ret = i915_dispatch_cmdbuffer(dev, &cmdbuf);
|
||||
if (ret) {
|
||||
DRM_ERROR("i915_dispatch_cmdbuffer failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i915_do_cleanup_pageflip(drm_device_t * dev)
|
||||
{
|
||||
|
|
@ -729,46 +659,13 @@ static int i915_do_cleanup_pageflip(drm_device_t * dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int i915_flip_bufs(DRM_IOCTL_ARGS)
|
||||
int i915_getparam(struct drm_device *dev, drm_i915_getparam_t *param,
|
||||
int *value_p)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_i915_flip_t param;
|
||||
|
||||
DRM_DEBUG("%s\n", __FUNCTION__);
|
||||
|
||||
LOCK_TEST_WITH_RETURN(dev, filp);
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL(param, (drm_i915_flip_t __user *) data,
|
||||
sizeof(param));
|
||||
|
||||
if (param.pipes & ~0x3) {
|
||||
DRM_ERROR("Invalid pipes 0x%x, only <= 0x3 is valid\n",
|
||||
param.pipes);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
i915_dispatch_flip(dev, param.pipes, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int i915_getparam(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
drm_i915_getparam_t param;
|
||||
int value;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL(param, (drm_i915_getparam_t __user *) data,
|
||||
sizeof(param));
|
||||
|
||||
switch (param.param) {
|
||||
switch (param->param) {
|
||||
case I915_PARAM_IRQ_ACTIVE:
|
||||
value = dev->irq ? 1 : 0;
|
||||
break;
|
||||
|
|
@ -779,51 +676,36 @@ static int i915_getparam(DRM_IOCTL_ARGS)
|
|||
value = READ_BREADCRUMB(dev_priv);
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Unknown parameter %d\n", param.param);
|
||||
DRM_ERROR("Unknown parameter %d\n", param->param);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
if (DRM_COPY_TO_USER(param.value, &value, sizeof(int))) {
|
||||
DRM_ERROR("DRM_COPY_TO_USER failed\n");
|
||||
return DRM_ERR(EFAULT);
|
||||
}
|
||||
|
||||
*value_p = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i915_setparam(DRM_IOCTL_ARGS)
|
||||
int i915_setparam(struct drm_device *dev, drm_i915_setparam_t *param)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
drm_i915_setparam_t param;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL(param, (drm_i915_setparam_t __user *) data,
|
||||
sizeof(param));
|
||||
|
||||
switch (param.param) {
|
||||
switch (param->param) {
|
||||
case I915_SETPARAM_USE_MI_BATCHBUFFER_START:
|
||||
dev_priv->use_mi_batchbuffer_start = param.value;
|
||||
dev_priv->use_mi_batchbuffer_start = param->value;
|
||||
break;
|
||||
case I915_SETPARAM_TEX_LRU_LOG_GRANULARITY:
|
||||
dev_priv->tex_lru_log_granularity = param.value;
|
||||
dev_priv->tex_lru_log_granularity = param->value;
|
||||
break;
|
||||
case I915_SETPARAM_ALLOW_BATCHBUFFER:
|
||||
dev_priv->allow_batchbuffer = param.value;
|
||||
dev_priv->allow_batchbuffer = param->value;
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("unknown parameter %d\n", param.param);
|
||||
DRM_ERROR("unknown parameter %d\n", param->param);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
drm_i915_mmio_entry_t mmio_table[] = {
|
||||
static drm_i915_mmio_entry_t mmio_table[] = {
|
||||
[MMIO_REGS_PS_DEPTH_COUNT] = {
|
||||
I915_MMIO_MAY_READ|I915_MMIO_MAY_WRITE,
|
||||
0x2350,
|
||||
|
|
@ -833,48 +715,51 @@ drm_i915_mmio_entry_t mmio_table[] = {
|
|||
|
||||
static int mmio_table_size = sizeof(mmio_table)/sizeof(drm_i915_mmio_entry_t);
|
||||
|
||||
static int i915_mmio(DRM_IOCTL_ARGS)
|
||||
int i915_mmio_get_size(struct drm_device *dev, drm_i915_mmio_t *mmio, int *size)
|
||||
{
|
||||
drm_i915_mmio_entry_t *e;
|
||||
|
||||
if (mmio->reg >= mmio_table_size)
|
||||
return DRM_ERR(EINVAL);
|
||||
|
||||
e = &mmio_table[mmio->reg];
|
||||
*size = e->size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i915_mmio_read(struct drm_device *dev, drm_i915_mmio_t *mmio, char *buf)
|
||||
{
|
||||
char buf[32];
|
||||
DRM_DEVICE;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
drm_i915_mmio_entry_t *e;
|
||||
drm_i915_mmio_t mmio;
|
||||
void __iomem *base;
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
DRM_COPY_FROM_USER_IOCTL(mmio, (drm_i915_mmio_t __user *) data,
|
||||
sizeof(mmio));
|
||||
|
||||
if (mmio.reg >= mmio_table_size)
|
||||
return DRM_ERR(EINVAL);
|
||||
|
||||
e = &mmio_table[mmio.reg];
|
||||
e = &mmio_table[mmio->reg];
|
||||
base = dev_priv->mmio_map->handle + e->offset;
|
||||
|
||||
switch (mmio.read_write) {
|
||||
case I915_MMIO_READ:
|
||||
if (!(e->flag & I915_MMIO_MAY_READ))
|
||||
return DRM_ERR(EINVAL);
|
||||
memcpy_fromio(buf, base, e->size);
|
||||
if (DRM_COPY_TO_USER(mmio.data, buf, e->size)) {
|
||||
DRM_ERROR("DRM_COPY_TO_USER failed\n");
|
||||
return DRM_ERR(EFAULT);
|
||||
}
|
||||
break;
|
||||
if (!(e->flag & I915_MMIO_MAY_READ))
|
||||
return DRM_ERR(EINVAL);
|
||||
|
||||
case I915_MMIO_WRITE:
|
||||
if (!(e->flag & I915_MMIO_MAY_WRITE))
|
||||
return DRM_ERR(EINVAL);
|
||||
if(DRM_COPY_FROM_USER(buf, mmio.data, e->size)) {
|
||||
DRM_ERROR("DRM_COPY_TO_USER failed\n");
|
||||
return DRM_ERR(EFAULT);
|
||||
}
|
||||
memcpy_toio(base, buf, e->size);
|
||||
break;
|
||||
}
|
||||
memcpy_fromio(buf, base, e->size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int i915_mmio_write(struct drm_device *dev, drm_i915_mmio_t *mmio, char *buf)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
drm_i915_mmio_entry_t *e;
|
||||
void __iomem *base;
|
||||
|
||||
if (mmio->reg >= mmio_table_size)
|
||||
return DRM_ERR(EINVAL);
|
||||
|
||||
e = &mmio_table[mmio->reg];
|
||||
base = dev_priv->mmio_map->handle + e->offset;
|
||||
|
||||
if (!(e->flag & I915_MMIO_MAY_WRITE))
|
||||
return DRM_ERR(EINVAL);
|
||||
|
||||
memcpy_fromio(buf, base, e->size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -908,27 +793,6 @@ void i915_driver_preclose(drm_device_t * dev, DRMFILE filp)
|
|||
}
|
||||
}
|
||||
|
||||
drm_ioctl_desc_t i915_ioctls[] = {
|
||||
[DRM_IOCTL_NR(DRM_I915_INIT)] = {i915_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
|
||||
[DRM_IOCTL_NR(DRM_I915_FLUSH)] = {i915_flush_ioctl, DRM_AUTH},
|
||||
[DRM_IOCTL_NR(DRM_I915_FLIP)] = {i915_flip_bufs, DRM_AUTH},
|
||||
[DRM_IOCTL_NR(DRM_I915_BATCHBUFFER)] = {i915_batchbuffer, DRM_AUTH},
|
||||
[DRM_IOCTL_NR(DRM_I915_IRQ_EMIT)] = {i915_irq_emit, DRM_AUTH},
|
||||
[DRM_IOCTL_NR(DRM_I915_IRQ_WAIT)] = {i915_irq_wait, DRM_AUTH},
|
||||
[DRM_IOCTL_NR(DRM_I915_GETPARAM)] = {i915_getparam, DRM_AUTH},
|
||||
[DRM_IOCTL_NR(DRM_I915_SETPARAM)] = {i915_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
|
||||
[DRM_IOCTL_NR(DRM_I915_ALLOC)] = {i915_mem_alloc, DRM_AUTH},
|
||||
[DRM_IOCTL_NR(DRM_I915_FREE)] = {i915_mem_free, DRM_AUTH},
|
||||
[DRM_IOCTL_NR(DRM_I915_INIT_HEAP)] = {i915_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
|
||||
[DRM_IOCTL_NR(DRM_I915_CMDBUFFER)] = {i915_cmdbuffer, DRM_AUTH},
|
||||
[DRM_IOCTL_NR(DRM_I915_DESTROY_HEAP)] = { i915_mem_destroy_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
|
||||
[DRM_IOCTL_NR(DRM_I915_SET_VBLANK_PIPE)] = { i915_vblank_pipe_set, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
|
||||
[DRM_IOCTL_NR(DRM_I915_GET_VBLANK_PIPE)] = { i915_vblank_pipe_get, DRM_AUTH },
|
||||
[DRM_IOCTL_NR(DRM_I915_VBLANK_SWAP)] = {i915_vblank_swap, DRM_AUTH},
|
||||
[DRM_IOCTL_NR(DRM_I915_MMIO)] = {i915_mmio, DRM_AUTH},
|
||||
};
|
||||
|
||||
int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
|
||||
|
||||
/**
|
||||
* Determine if the device really is AGP or not.
|
||||
|
|
|
|||
|
|
@ -143,6 +143,25 @@ extern drm_ioctl_desc_t i915_ioctls[];
|
|||
extern int i915_max_ioctl;
|
||||
|
||||
/* i915_dma.c */
|
||||
extern int i915_dma_init(struct drm_device *dev, drm_i915_init_t *init);
|
||||
extern int i915_dispatch_batchbuffer(drm_device_t * dev,
|
||||
drm_i915_batchbuffer_t * batch);
|
||||
extern int i915_getparam(struct drm_device *dev, drm_i915_getparam_t *param,
|
||||
int *value_p);
|
||||
extern int i915_setparam(struct drm_device *dev, drm_i915_setparam_t *param);
|
||||
|
||||
extern int i915_quiescent(drm_device_t *dev);
|
||||
|
||||
extern int i915_mmio_get_size(struct drm_device *dev, drm_i915_mmio_t *mmio,
|
||||
int *size);
|
||||
extern int i915_mmio_read(struct drm_device *dev, drm_i915_mmio_t *mmio,
|
||||
char *buf);
|
||||
extern int i915_mmio_write(struct drm_device *dev, drm_i915_mmio_t *mmio,
|
||||
char *buf);
|
||||
|
||||
extern int i915_dispatch_cmdbuffer(drm_device_t * dev,
|
||||
drm_i915_cmdbuffer_t * cmd);
|
||||
|
||||
extern void i915_kernel_lost_context(drm_device_t * dev);
|
||||
extern int i915_driver_load(struct drm_device *, unsigned long flags);
|
||||
extern void i915_driver_lastclose(drm_device_t * dev);
|
||||
|
|
@ -156,8 +175,8 @@ extern int i915_emit_mi_flush(drm_device_t *dev, uint32_t flush);
|
|||
extern int i915_driver_firstopen(struct drm_device *dev);
|
||||
|
||||
/* i915_irq.c */
|
||||
extern int i915_irq_emit(DRM_IOCTL_ARGS);
|
||||
extern int i915_irq_wait(DRM_IOCTL_ARGS);
|
||||
extern int i915_wait_irq(drm_device_t * dev, int irq_nr);
|
||||
extern int i915_emit_irq(drm_device_t * dev);
|
||||
|
||||
extern int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence);
|
||||
extern int i915_driver_vblank_wait2(drm_device_t *dev, unsigned int *sequence);
|
||||
|
|
@ -165,18 +184,25 @@ extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);
|
|||
extern void i915_driver_irq_preinstall(drm_device_t * dev);
|
||||
extern void i915_driver_irq_postinstall(drm_device_t * dev);
|
||||
extern void i915_driver_irq_uninstall(drm_device_t * dev);
|
||||
extern int i915_vblank_pipe_set(DRM_IOCTL_ARGS);
|
||||
extern int i915_vblank_pipe_get(DRM_IOCTL_ARGS);
|
||||
extern int i915_vblank_pipe_set(struct drm_device *dev,
|
||||
drm_i915_vblank_pipe_t *pipe);
|
||||
extern int i915_vblank_pipe_get(struct drm_device *dev,
|
||||
drm_i915_vblank_pipe_t *pipe);
|
||||
extern int i915_emit_irq(drm_device_t * dev);
|
||||
extern void i915_user_irq_on(drm_i915_private_t *dev_priv);
|
||||
extern void i915_user_irq_off(drm_i915_private_t *dev_priv);
|
||||
extern int i915_vblank_swap(DRM_IOCTL_ARGS);
|
||||
|
||||
extern int i915_vblank_swap(struct drm_device *dev, drm_i915_vblank_swap_t *swap, DRMFILE filp);
|
||||
/* i915_mem.c */
|
||||
extern int i915_mem_alloc(DRM_IOCTL_ARGS);
|
||||
extern int i915_mem_free(DRM_IOCTL_ARGS);
|
||||
extern int i915_mem_init_heap(DRM_IOCTL_ARGS);
|
||||
extern int i915_mem_destroy_heap(DRM_IOCTL_ARGS);
|
||||
extern int i915_mem_alloc(struct drm_device *dev, drm_i915_mem_alloc_t *alloc,
|
||||
DRMFILE filp, int *start);
|
||||
extern int i915_mem_free(struct drm_device *dev, drm_i915_mem_free_t *memfree,
|
||||
DRMFILE filp);
|
||||
|
||||
extern int i915_mem_init_heap(struct drm_device *dev,
|
||||
drm_i915_mem_init_heap_t *initheap);
|
||||
extern int i915_mem_destroy_heap(struct drm_device *dev,
|
||||
drm_i915_mem_destroy_heap_t *destroyheap);
|
||||
|
||||
extern void i915_mem_takedown(struct mem_block **heap);
|
||||
extern void i915_mem_release(drm_device_t * dev,
|
||||
DRMFILE filp, struct mem_block *heap);
|
||||
|
|
|
|||
|
|
@ -389,7 +389,7 @@ static int wait_compare(struct drm_device *dev, void *priv)
|
|||
return (READ_BREADCRUMB(dev_priv) >= irq_nr);
|
||||
}
|
||||
|
||||
static int i915_wait_irq(drm_device_t * dev, int irq_nr)
|
||||
int i915_wait_irq(drm_device_t * dev, int irq_nr)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
int ret = 0;
|
||||
|
|
@ -448,54 +448,6 @@ int i915_driver_vblank_wait2(drm_device_t *dev, unsigned int *sequence)
|
|||
return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received2);
|
||||
}
|
||||
|
||||
/* Needs the lock as it touches the ring.
|
||||
*/
|
||||
int i915_irq_emit(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
drm_i915_irq_emit_t emit;
|
||||
int result;
|
||||
|
||||
LOCK_TEST_WITH_RETURN(dev, filp);
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL(emit, (drm_i915_irq_emit_t __user *) data,
|
||||
sizeof(emit));
|
||||
|
||||
result = i915_emit_irq(dev);
|
||||
|
||||
if (DRM_COPY_TO_USER(emit.irq_seq, &result, sizeof(int))) {
|
||||
DRM_ERROR("copy_to_user\n");
|
||||
return DRM_ERR(EFAULT);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Doesn't need the hardware lock.
|
||||
*/
|
||||
int i915_irq_wait(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
drm_i915_irq_wait_t irqwait;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL(irqwait, (drm_i915_irq_wait_t __user *) data,
|
||||
sizeof(irqwait));
|
||||
|
||||
return i915_wait_irq(dev, irqwait.irq_seq);
|
||||
}
|
||||
|
||||
static void i915_enable_interrupt (drm_device_t *dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
|
|
@ -512,92 +464,59 @@ static void i915_enable_interrupt (drm_device_t *dev)
|
|||
|
||||
/* Set the vblank monitor pipe
|
||||
*/
|
||||
int i915_vblank_pipe_set(DRM_IOCTL_ARGS)
|
||||
int i915_vblank_pipe_set(struct drm_device *dev, drm_i915_vblank_pipe_t *pipe)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
drm_i915_vblank_pipe_t pipe;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL(pipe, (drm_i915_vblank_pipe_t __user *) data,
|
||||
sizeof(pipe));
|
||||
|
||||
if (pipe.pipe & ~(DRM_I915_VBLANK_PIPE_A|DRM_I915_VBLANK_PIPE_B)) {
|
||||
if (pipe->pipe & ~(DRM_I915_VBLANK_PIPE_A|DRM_I915_VBLANK_PIPE_B)) {
|
||||
DRM_ERROR("%s called with invalid pipe 0x%x\n",
|
||||
__FUNCTION__, pipe.pipe);
|
||||
__FUNCTION__, pipe->pipe);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
dev_priv->vblank_pipe = pipe.pipe;
|
||||
dev_priv->vblank_pipe = pipe->pipe;
|
||||
|
||||
i915_enable_interrupt (dev);
|
||||
i915_enable_interrupt(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i915_vblank_pipe_get(DRM_IOCTL_ARGS)
|
||||
int i915_vblank_pipe_get(struct drm_device *dev, drm_i915_vblank_pipe_t *pipe)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
drm_i915_vblank_pipe_t pipe;
|
||||
u16 flag;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
flag = I915_READ(I915REG_INT_ENABLE_R);
|
||||
pipe.pipe = 0;
|
||||
pipe->pipe = 0;
|
||||
if (flag & VSYNC_PIPEA_FLAG)
|
||||
pipe.pipe |= DRM_I915_VBLANK_PIPE_A;
|
||||
pipe->pipe |= DRM_I915_VBLANK_PIPE_A;
|
||||
if (flag & VSYNC_PIPEB_FLAG)
|
||||
pipe.pipe |= DRM_I915_VBLANK_PIPE_B;
|
||||
DRM_COPY_TO_USER_IOCTL((drm_i915_vblank_pipe_t __user *) data, pipe,
|
||||
sizeof(pipe));
|
||||
pipe->pipe |= DRM_I915_VBLANK_PIPE_B;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedule buffer swap at given vertical blank.
|
||||
*/
|
||||
int i915_vblank_swap(DRM_IOCTL_ARGS)
|
||||
int i915_vblank_swap(struct drm_device *dev, drm_i915_vblank_swap_t *swap,
|
||||
DRMFILE filp)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
drm_i915_vblank_swap_t swap;
|
||||
drm_i915_vbl_swap_t *vbl_swap;
|
||||
unsigned int pipe, seqtype, curseq;
|
||||
unsigned long irqflags;
|
||||
struct list_head *list;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __func__);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
if (dev_priv->sarea_priv->rotation) {
|
||||
DRM_DEBUG("Rotation not supported\n");
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL(swap, (drm_i915_vblank_swap_t __user *) data,
|
||||
sizeof(swap));
|
||||
|
||||
if (swap.seqtype & ~(_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE |
|
||||
if (swap->seqtype & ~(_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE |
|
||||
_DRM_VBLANK_SECONDARY | _DRM_VBLANK_NEXTONMISS |
|
||||
_DRM_VBLANK_FLIP)) {
|
||||
DRM_ERROR("Invalid sequence type 0x%x\n", swap.seqtype);
|
||||
DRM_ERROR("Invalid sequence type 0x%x\n", swap->seqtype);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
pipe = (swap.seqtype & _DRM_VBLANK_SECONDARY) ? 1 : 0;
|
||||
pipe = (swap->seqtype & _DRM_VBLANK_SECONDARY) ? 1 : 0;
|
||||
|
||||
seqtype = swap.seqtype & (_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE);
|
||||
seqtype = swap->seqtype & (_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE);
|
||||
|
||||
if (!(dev_priv->vblank_pipe & (1 << pipe))) {
|
||||
DRM_ERROR("Invalid pipe %d\n", pipe);
|
||||
|
|
@ -606,9 +525,9 @@ int i915_vblank_swap(DRM_IOCTL_ARGS)
|
|||
|
||||
spin_lock_irqsave(&dev->drw_lock, irqflags);
|
||||
|
||||
if (!drm_get_drawable_info(dev, swap.drawable)) {
|
||||
if (!drm_get_drawable_info(dev, swap->drawable)) {
|
||||
spin_unlock_irqrestore(&dev->drw_lock, irqflags);
|
||||
DRM_DEBUG("Invalid drawable ID %d\n", swap.drawable);
|
||||
DRM_DEBUG("Invalid drawable ID %d\n", swap->drawable);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
|
|
@ -617,33 +536,33 @@ int i915_vblank_swap(DRM_IOCTL_ARGS)
|
|||
curseq = atomic_read(pipe ? &dev->vbl_received2 : &dev->vbl_received);
|
||||
|
||||
if (seqtype == _DRM_VBLANK_RELATIVE)
|
||||
swap.sequence += curseq;
|
||||
swap->sequence += curseq;
|
||||
|
||||
if ((curseq - swap.sequence) <= (1<<23)) {
|
||||
if (swap.seqtype & _DRM_VBLANK_NEXTONMISS) {
|
||||
swap.sequence = curseq + 1;
|
||||
if ((curseq - swap->sequence) <= (1<<23)) {
|
||||
if (swap->seqtype & _DRM_VBLANK_NEXTONMISS) {
|
||||
swap->sequence = curseq + 1;
|
||||
} else {
|
||||
DRM_DEBUG("Missed target sequence\n");
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
if (swap.seqtype & _DRM_VBLANK_FLIP) {
|
||||
swap.sequence--;
|
||||
if (swap->seqtype & _DRM_VBLANK_FLIP) {
|
||||
swap->sequence--;
|
||||
|
||||
if ((curseq - swap.sequence) <= (1<<23)) {
|
||||
if ((curseq - swap->sequence) <= (1<<23)) {
|
||||
drm_drawable_info_t *drw;
|
||||
|
||||
LOCK_TEST_WITH_RETURN(dev, filp);
|
||||
|
||||
spin_lock_irqsave(&dev->drw_lock, irqflags);
|
||||
|
||||
drw = drm_get_drawable_info(dev, swap.drawable);
|
||||
drw = drm_get_drawable_info(dev, swap->drawable);
|
||||
|
||||
if (!drw) {
|
||||
spin_unlock_irqrestore(&dev->drw_lock, irqflags);
|
||||
DRM_DEBUG("Invalid drawable ID %d\n",
|
||||
swap.drawable);
|
||||
swap->drawable);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
|
|
@ -660,10 +579,10 @@ int i915_vblank_swap(DRM_IOCTL_ARGS)
|
|||
list_for_each(list, &dev_priv->vbl_swaps.head) {
|
||||
vbl_swap = list_entry(list, drm_i915_vbl_swap_t, head);
|
||||
|
||||
if (vbl_swap->drw_id == swap.drawable &&
|
||||
if (vbl_swap->drw_id == swap->drawable &&
|
||||
vbl_swap->pipe == pipe &&
|
||||
vbl_swap->sequence == swap.sequence) {
|
||||
vbl_swap->flip = (swap.seqtype & _DRM_VBLANK_FLIP);
|
||||
vbl_swap->sequence == swap->sequence) {
|
||||
vbl_swap->flip = (swap->seqtype & _DRM_VBLANK_FLIP);
|
||||
spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
|
||||
DRM_DEBUG("Already scheduled\n");
|
||||
return 0;
|
||||
|
|
@ -686,13 +605,13 @@ int i915_vblank_swap(DRM_IOCTL_ARGS)
|
|||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
vbl_swap->drw_id = swap.drawable;
|
||||
vbl_swap->drw_id = swap->drawable;
|
||||
vbl_swap->pipe = pipe;
|
||||
vbl_swap->sequence = swap.sequence;
|
||||
vbl_swap->flip = (swap.seqtype & _DRM_VBLANK_FLIP);
|
||||
vbl_swap->sequence = swap->sequence;
|
||||
vbl_swap->flip = (swap->seqtype & _DRM_VBLANK_FLIP);
|
||||
|
||||
if (vbl_swap->flip)
|
||||
swap.sequence++;
|
||||
swap->sequence++;
|
||||
|
||||
spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
|
||||
|
||||
|
|
@ -700,10 +619,6 @@ int i915_vblank_swap(DRM_IOCTL_ARGS)
|
|||
dev_priv->swaps_pending++;
|
||||
|
||||
spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
|
||||
|
||||
DRM_COPY_TO_USER_IOCTL((drm_i915_vblank_swap_t __user *) data, swap,
|
||||
sizeof(swap));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -267,66 +267,44 @@ static struct mem_block **get_heap(drm_i915_private_t * dev_priv, int region)
|
|||
|
||||
/* IOCTL HANDLERS */
|
||||
|
||||
int i915_mem_alloc(DRM_IOCTL_ARGS)
|
||||
int i915_mem_alloc(struct drm_device *dev, drm_i915_mem_alloc_t *alloc,
|
||||
DRMFILE filp, int *start)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
drm_i915_mem_alloc_t alloc;
|
||||
struct mem_block *block, **heap;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL(alloc, (drm_i915_mem_alloc_t __user *) data,
|
||||
sizeof(alloc));
|
||||
|
||||
heap = get_heap(dev_priv, alloc.region);
|
||||
heap = get_heap(dev_priv, alloc->region);
|
||||
if (!heap || !*heap)
|
||||
return DRM_ERR(EFAULT);
|
||||
|
||||
/* Make things easier on ourselves: all allocations at least
|
||||
* 4k aligned.
|
||||
*/
|
||||
if (alloc.alignment < 12)
|
||||
alloc.alignment = 12;
|
||||
if (alloc->alignment < 12)
|
||||
alloc->alignment = 12;
|
||||
|
||||
block = alloc_block(*heap, alloc.size, alloc.alignment, filp);
|
||||
block = alloc_block(*heap, alloc->size, alloc->alignment, filp);
|
||||
|
||||
if (!block)
|
||||
return DRM_ERR(ENOMEM);
|
||||
|
||||
mark_block(dev, block, 1);
|
||||
|
||||
if (DRM_COPY_TO_USER(alloc.region_offset, &block->start, sizeof(int))) {
|
||||
DRM_ERROR("copy_to_user\n");
|
||||
return DRM_ERR(EFAULT);
|
||||
}
|
||||
|
||||
*start = block->start;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i915_mem_free(DRM_IOCTL_ARGS)
|
||||
int i915_mem_free(struct drm_device *dev, drm_i915_mem_free_t *memfree,
|
||||
DRMFILE filp)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
drm_i915_mem_free_t memfree;
|
||||
struct mem_block *block, **heap;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL(memfree, (drm_i915_mem_free_t __user *) data,
|
||||
sizeof(memfree));
|
||||
|
||||
heap = get_heap(dev_priv, memfree.region);
|
||||
heap = get_heap(dev_priv, memfree->region);
|
||||
if (!heap || !*heap)
|
||||
return DRM_ERR(EFAULT);
|
||||
|
||||
block = find_block(*heap, memfree.region_offset);
|
||||
block = find_block(*heap, memfree->region_offset);
|
||||
if (!block)
|
||||
return DRM_ERR(EFAULT);
|
||||
|
||||
|
|
@ -338,23 +316,12 @@ int i915_mem_free(DRM_IOCTL_ARGS)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int i915_mem_init_heap(DRM_IOCTL_ARGS)
|
||||
int i915_mem_init_heap(struct drm_device *dev, drm_i915_mem_init_heap_t *initheap)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
drm_i915_mem_init_heap_t initheap;
|
||||
struct mem_block **heap;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL(initheap,
|
||||
(drm_i915_mem_init_heap_t __user *) data,
|
||||
sizeof(initheap));
|
||||
|
||||
heap = get_heap(dev_priv, initheap.region);
|
||||
heap = get_heap(dev_priv, initheap->region);
|
||||
if (!heap)
|
||||
return DRM_ERR(EFAULT);
|
||||
|
||||
|
|
@ -363,25 +330,16 @@ int i915_mem_init_heap(DRM_IOCTL_ARGS)
|
|||
return DRM_ERR(EFAULT);
|
||||
}
|
||||
|
||||
return init_heap(heap, initheap.start, initheap.size);
|
||||
return init_heap(heap, initheap->start, initheap->size);
|
||||
}
|
||||
|
||||
int i915_mem_destroy_heap( DRM_IOCTL_ARGS )
|
||||
int i915_mem_destroy_heap(struct drm_device *dev,
|
||||
drm_i915_mem_destroy_heap_t *destroyheap)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
drm_i915_mem_destroy_heap_t destroyheap;
|
||||
struct mem_block **heap;
|
||||
|
||||
if ( !dev_priv ) {
|
||||
DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL( destroyheap, (drm_i915_mem_destroy_heap_t *)data,
|
||||
sizeof(destroyheap) );
|
||||
|
||||
heap = get_heap( dev_priv, destroyheap.region );
|
||||
heap = get_heap(dev_priv, destroyheap->region);
|
||||
if (!heap) {
|
||||
DRM_ERROR("get_heap failed");
|
||||
return DRM_ERR(EFAULT);
|
||||
|
|
@ -392,6 +350,6 @@ int i915_mem_destroy_heap( DRM_IOCTL_ARGS )
|
|||
return DRM_ERR(EFAULT);
|
||||
}
|
||||
|
||||
i915_mem_takedown( heap );
|
||||
i915_mem_takedown(heap);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue