From 136e86822aa82efd73115bd85df7d30db9c931ae Mon Sep 17 00:00:00 2001 From: Jeff Hartmann Date: Thu, 6 Apr 2000 21:42:20 +0000 Subject: [PATCH] Initial checkin of mmap security model --- linux-core/i810_dma.c | 159 ++++++++++++++++++++++++++---------------- linux-core/i810_drm.h | 7 ++ linux-core/i810_drv.c | 5 +- linux-core/i810_drv.h | 15 ++-- linux/drm.h | 2 +- linux/i810_bufs.c | 110 ----------------------------- linux/i810_dma.c | 159 ++++++++++++++++++++++++++---------------- linux/i810_drm.h | 7 ++ linux/i810_drv.c | 5 +- linux/i810_drv.h | 15 ++-- shared-core/drm.h | 2 +- shared/drm.h | 2 +- 12 files changed, 227 insertions(+), 261 deletions(-) diff --git a/linux-core/i810_dma.c b/linux-core/i810_dma.c index 6ac4d2ee..90c7eb15 100644 --- a/linux-core/i810_dma.c +++ b/linux-core/i810_dma.c @@ -40,6 +40,9 @@ #define I810_BUF_FREE 1 #define I810_BUF_USED 0 +#define I810_BUF_UNMAPPED 0 +#define I810_BUF_MAPPED 1 + #define I810_REG(reg) 2 #define I810_BASE(reg) ((unsigned long) \ dev->maplist[I810_REG(reg)]->handle) @@ -135,28 +138,87 @@ static int i810_freelist_put(drm_device_t *dev, drm_buf_t *buf) return 0; } -static int i810_dma_get_buffers(drm_device_t *dev, drm_dma_t *d) +int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma) { - int i; - drm_buf_t *buf; - - for (i = d->granted_count; i < d->request_count; i++) { - buf = i810_freelist_get(dev); - if (!buf) break; - buf->pid = current->pid; - copy_to_user_ret(&d->request_indices[i], - &buf->idx, - sizeof(buf->idx), - -EFAULT); - copy_to_user_ret(&d->request_sizes[i], - &buf->total, - sizeof(buf->total), - -EFAULT); - ++d->granted_count; - } + vma->vm_flags |= VM_IO; + if (remap_page_range(vma->vm_start, + VM_OFFSET(vma), + vma->vm_end - vma->vm_start, + vma->vm_page_prot)) return -EAGAIN; return 0; } +static int i810_map_buffer(drm_buf_t *buf, struct file *filp) +{ + drm_i810_buf_priv_t *buf_priv = buf->dev_private; + int retcode = 0; + + if(buf_priv->currently_mapped == I810_BUF_MAPPED) return -EINVAL; + down(¤t->mm->mmap_sem); + filp->f_op->mmap = i810_mmap_buffers; + buf_priv->virtual = (void *)do_mmap(filp, 0, buf->total, + PROT_READ|PROT_WRITE, + MAP_SHARED, + buf->bus_address); + filp->f_op->mmap = drm_mmap; + if ((unsigned long)buf_priv->virtual > -1024UL) { + /* Real error */ + DRM_DEBUG("mmap error\n"); + retcode = (signed int)buf_priv->virtual; + } else { + buf_priv->currently_mapped = I810_BUF_MAPPED; + } + up(¤t->mm->mmap_sem); + return retcode; +} + +static int i810_unmap_buffer(drm_buf_t *buf) +{ + drm_i810_buf_priv_t *buf_priv = buf->dev_private; + int retcode = 0; + + if(buf_priv->currently_mapped != I810_BUF_MAPPED) return -EINVAL; + down(¤t->mm->mmap_sem); + retcode = do_munmap((unsigned long)buf_priv->virtual, + (size_t) buf->total); + buf_priv->currently_mapped = I810_BUF_UNMAPPED; + buf_priv->virtual = 0; + up(¤t->mm->mmap_sem); + + return retcode; +} + +static int i810_dma_get_buffer(drm_device_t *dev, drm_i810_dma_t *d, + struct file *filp) +{ + drm_buf_t *buf; + drm_i810_buf_priv_t *buf_priv; + int retcode = 0; + + buf = i810_freelist_get(dev); + if (!buf) { + retcode = -ENOMEM; + DRM_DEBUG("%s retcode %d\n", __FUNCTION__, retcode); + goto out_get_buf; + } + + retcode = i810_map_buffer(buf, filp); + if(retcode) { + i810_freelist_put(dev, buf); + DRM_DEBUG("mapbuf failed in %s retcode %d\n", __FUNCTION__, retcode); + goto out_get_buf; + } + buf->pid = current->pid; + buf_priv = buf->dev_private; + d->granted = 1; + d->request_idx = buf->idx; + d->request_size = buf->total; + d->virtual = buf_priv->virtual; + +out_get_buf: + return retcode; +} + static unsigned long i810_alloc_page(drm_device_t *dev) { unsigned long address; @@ -395,6 +457,9 @@ static void i810_dma_dispatch_general(drm_device_t *dev, drm_buf_t *buf, OUT_RING( I810_BUF_FREE ); OUT_RING( CMD_REPORT_HEAD ); ADVANCE_LP_RING(); + if(buf_priv->currently_mapped == I810_BUF_MAPPED) { + i810_unmap_buffer(buf); + } } static void i810_dma_dispatch_vertex(drm_device_t *dev, @@ -465,6 +530,9 @@ static void i810_dma_dispatch_vertex(drm_device_t *dev, OUT_RING( CMD_REPORT_HEAD ); OUT_RING( 0 ); ADVANCE_LP_RING(); + if(buf_priv->currently_mapped == I810_BUF_MAPPED) { + i810_unmap_buffer(buf); + } } @@ -727,6 +795,9 @@ void i810_reclaim_buffers(drm_device_t *dev, pid_t pid) if (buf->pid == pid && buf_priv) { cmpxchg(buf_priv->in_use, I810_BUF_USED, I810_BUF_FREE); + if(buf_priv->currently_mapped == I810_BUF_MAPPED) { + buf_priv->currently_mapped = I810_BUF_UNMAPPED; + } } } } @@ -760,19 +831,6 @@ int i810_lock(struct inode *inode, struct file *filp, unsigned int cmd, */ if (!ret) { -#if 0 - if (_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock) - != lock.context) { - long j = jiffies - dev->lock.lock_time; - - if (j > 0 && j <= DRM_LOCK_SLICE) { - /* Can't take lock if we just had it and - there is contention. */ - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(j); - } - } -#endif add_wait_queue(&dev->lock.lock_queue, &entry); for (;;) { if (!dev->lock.hw_lock) { @@ -929,53 +987,32 @@ int i810_getage(struct inode *inode, struct file *filp, unsigned int cmd, return 0; } -int i810_dma(struct inode *inode, struct file *filp, unsigned int cmd, - unsigned long arg) +int i810_getbuf(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg) { drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; - drm_device_dma_t *dma = dev->dma; int retcode = 0; - drm_dma_t d; + drm_i810_dma_t d; drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; u32 *hw_status = (u32 *)dev_priv->hw_status_page; drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *) dev_priv->sarea_priv; - - copy_from_user_ret(&d, (drm_dma_t *)arg, sizeof(d), -EFAULT); - DRM_DEBUG("%d %d: %d send, %d req\n", - current->pid, d.context, d.send_count, d.request_count); + DRM_DEBUG("getbuf\n"); + copy_from_user_ret(&d, (drm_i810_dma_t *)arg, sizeof(d), -EFAULT); if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { DRM_ERROR("i810_dma called without lock held\n"); return -EINVAL; } - - /* Please don't send us buffers. - */ - if (d.send_count != 0) { - DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n", - current->pid, d.send_count); - return -EINVAL; - } - /* We'll send you buffers. - */ - if (d.request_count < 0 || d.request_count > dma->buf_count) { - DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n", - current->pid, d.request_count, dma->buf_count); - return -EINVAL; - } - - d.granted_count = 0; + d.granted = 0; - if (!retcode && d.request_count) { - retcode = i810_dma_get_buffers(dev, &d); - } + retcode = i810_dma_get_buffer(dev, &d, filp); - DRM_DEBUG("i810_dma: %d returning, granted = %d\n", - current->pid, d.granted_count); + DRM_DEBUG("i810_dma: %d returning %d, granted = %d\n", + current->pid, retcode, d.granted); copy_to_user_ret((drm_dma_t *)arg, &d, sizeof(d), -EFAULT); sarea_priv->last_dispatch = (int) hw_status[5]; diff --git a/linux-core/i810_drm.h b/linux-core/i810_drm.h index 0754874c..7e435879 100644 --- a/linux-core/i810_drm.h +++ b/linux-core/i810_drm.h @@ -90,4 +90,11 @@ typedef struct _drm_i810_vertex { int discard; /* client is finished with the buffer? */ } drm_i810_vertex_t; +typedef struct drm_i810_dma { + void *virtual; + int request_idx; + int request_size; + int granted; +} drm_i810_dma_t; + #endif /* _I810_DRM_H_ */ diff --git a/linux-core/i810_drv.c b/linux-core/i810_drv.c index f1c83250..03585bdf 100644 --- a/linux-core/i810_drv.c +++ b/linux-core/i810_drv.c @@ -80,7 +80,6 @@ static drm_ioctl_desc_t i810_ioctls[] = { [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = { i810_addbufs, 1, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = { i810_markbufs, 1, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = { i810_infobufs, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = { i810_mapbufs, 1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = { i810_freebufs, 1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = { i810_addctx, 1, 1 }, @@ -93,8 +92,6 @@ static drm_ioctl_desc_t i810_ioctls[] = { [DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = { drm_adddraw, 1, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = { drm_rmdraw, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { i810_dma, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = { i810_lock, 1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = { i810_unlock, 1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = { drm_finish, 1, 0 }, @@ -107,11 +104,13 @@ static drm_ioctl_desc_t i810_ioctls[] = { [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = { drm_agp_free, 1, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { drm_agp_bind, 1, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { drm_agp_unbind, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_I810_INIT)] = { i810_dma_init, 1, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_I810_VERTEX)] = { i810_dma_vertex, 1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_I810_DMA)] = { i810_dma_general,1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_I810_FLUSH)] = { i810_flush_ioctl,1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_I810_GETAGE)] = { i810_getage, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_I810_GETBUF)] = { i810_getbuf, 1, 0 }, }; #define I810_IOCTL_COUNT DRM_ARRAY_SIZE(i810_ioctls) diff --git a/linux-core/i810_drv.h b/linux-core/i810_drv.h index 1badd36b..a4e4d6c7 100644 --- a/linux-core/i810_drv.h +++ b/linux-core/i810_drv.h @@ -71,8 +71,8 @@ extern int i810_unlock(struct inode *inode, struct file *filp, /* i810_dma.c */ extern int i810_dma_schedule(drm_device_t *dev, int locked); -extern int i810_dma(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); +extern int i810_getbuf(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); extern int i810_irq_install(drm_device_t *dev, int irq); extern int i810_irq_uninstall(drm_device_t *dev); extern int i810_control(struct inode *inode, struct file *filp, @@ -97,8 +97,6 @@ extern int i810_markbufs(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); extern int i810_freebufs(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); -extern int i810_mapbufs(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); extern int i810_addmap(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); @@ -124,16 +122,13 @@ extern int i810_context_switch_complete(drm_device_t *dev, int new); -/* Copy the outstanding cliprects for every I810_DMA_VERTEX buffer. - * This can be fixed by emitting directly to the ringbuffer in the - * 'vertex_dma' ioctl. -*/ -typedef struct { +typedef struct drm_i810_buf_priv { u32 *in_use; int my_use_idx; + int currently_mapped; + void *virtual; } drm_i810_buf_priv_t; - #define I810_DMA_GENERAL 0 #define I810_DMA_VERTEX 1 #define I810_DMA_DISCARD 2 /* not used */ diff --git a/linux/drm.h b/linux/drm.h index ae4c65ca..86ab0410 100644 --- a/linux/drm.h +++ b/linux/drm.h @@ -348,5 +348,5 @@ typedef struct drm_agp_info { #define DRM_IOCTL_I810_DMA DRM_IOW( 0x42, drm_i810_general_t) #define DRM_IOCTL_I810_FLUSH DRM_IO ( 0x43) #define DRM_IOCTL_I810_GETAGE DRM_IO ( 0x44) - +#define DRM_IOCTL_I810_GETBUF DRM_IOW( 0x45, drm_i810_dma_t) #endif diff --git a/linux/i810_bufs.c b/linux/i810_bufs.c index c025e400..5215f135 100644 --- a/linux/i810_bufs.c +++ b/linux/i810_bufs.c @@ -332,113 +332,3 @@ int i810_freebufs(struct inode *inode, struct file *filp, unsigned int cmd, return 0; } -int i810_mapbufs(struct inode *inode, struct file *filp, unsigned int cmd, - unsigned long arg) -{ - drm_file_t *priv = filp->private_data; - drm_device_t *dev = priv->dev; - drm_device_dma_t *dma = dev->dma; - int retcode = 0; - const int zero = 0; - unsigned long virtual; - unsigned long address; - drm_buf_map_t request; - int i; - - if (!dma) return -EINVAL; - - DRM_DEBUG("\n"); - - spin_lock(&dev->count_lock); - if (atomic_read(&dev->buf_alloc)) { - spin_unlock(&dev->count_lock); - DRM_DEBUG("Busy\n"); - return -EBUSY; - } - ++dev->buf_use; /* Can't allocate more after this call */ - spin_unlock(&dev->count_lock); - - copy_from_user_ret(&request, - (drm_buf_map_t *)arg, - sizeof(request), - -EFAULT); - DRM_DEBUG("dma->flags : %lx\n", dma->flags); - if (request.count >= dma->buf_count) { - if(dma->flags & _DRM_DMA_USE_AGP) { - drm_i810_private_t *dev_priv = - (drm_i810_private_t *)dev->dev_private; - drm_map_t *map = NULL; - - map = dev->maplist[dev_priv->buffer_map_idx]; - if (!map) { - DRM_DEBUG("map is null\n"); - retcode = -EINVAL; - goto done; - } - DRM_DEBUG("map->offset : %lx\n", map->offset); - DRM_DEBUG("map->size : %lx\n", map->size); - DRM_DEBUG("map->type : %d\n", map->type); - DRM_DEBUG("map->flags : %x\n", map->flags); - DRM_DEBUG("map->handle : %lx\n", map->handle); - DRM_DEBUG("map->mtrr : %d\n", map->mtrr); - down(¤t->mm->mmap_sem); - virtual = do_mmap(filp, 0, map->size, - PROT_READ|PROT_WRITE, - MAP_SHARED, - (unsigned long)map->offset); - - up(¤t->mm->mmap_sem); - } else { - down(¤t->mm->mmap_sem); - virtual = do_mmap(filp, 0, dma->byte_count, - PROT_READ|PROT_WRITE, MAP_SHARED, 0); - up(¤t->mm->mmap_sem); - } - if (virtual > -1024UL) { - /* Real error */ - DRM_DEBUG("mmap error\n"); - retcode = (signed long)virtual; - goto done; - } - request.virtual = (void *)virtual; - - for (i = 0; i < dma->buf_count; i++) { - if (copy_to_user(&request.list[i].idx, - &dma->buflist[i]->idx, - sizeof(request.list[0].idx))) { - retcode = -EFAULT; - goto done; - } - if (copy_to_user(&request.list[i].total, - &dma->buflist[i]->total, - sizeof(request.list[0].total))) { - retcode = -EFAULT; - goto done; - } - if (copy_to_user(&request.list[i].used, - &zero, - sizeof(zero))) { - retcode = -EFAULT; - goto done; - } - address = virtual + dma->buflist[i]->offset; - if (copy_to_user(&request.list[i].address, - &address, - sizeof(address))) { - retcode = -EFAULT; - goto done; - } - } - } - done: - request.count = dma->buf_count; - DRM_DEBUG("%d buffers, retcode = %d\n", request.count, retcode); - - copy_to_user_ret((drm_buf_map_t *)arg, - &request, - sizeof(request), - -EFAULT); - - DRM_DEBUG("retcode : %d\n", retcode); - return retcode; -} diff --git a/linux/i810_dma.c b/linux/i810_dma.c index 6ac4d2ee..90c7eb15 100644 --- a/linux/i810_dma.c +++ b/linux/i810_dma.c @@ -40,6 +40,9 @@ #define I810_BUF_FREE 1 #define I810_BUF_USED 0 +#define I810_BUF_UNMAPPED 0 +#define I810_BUF_MAPPED 1 + #define I810_REG(reg) 2 #define I810_BASE(reg) ((unsigned long) \ dev->maplist[I810_REG(reg)]->handle) @@ -135,28 +138,87 @@ static int i810_freelist_put(drm_device_t *dev, drm_buf_t *buf) return 0; } -static int i810_dma_get_buffers(drm_device_t *dev, drm_dma_t *d) +int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma) { - int i; - drm_buf_t *buf; - - for (i = d->granted_count; i < d->request_count; i++) { - buf = i810_freelist_get(dev); - if (!buf) break; - buf->pid = current->pid; - copy_to_user_ret(&d->request_indices[i], - &buf->idx, - sizeof(buf->idx), - -EFAULT); - copy_to_user_ret(&d->request_sizes[i], - &buf->total, - sizeof(buf->total), - -EFAULT); - ++d->granted_count; - } + vma->vm_flags |= VM_IO; + if (remap_page_range(vma->vm_start, + VM_OFFSET(vma), + vma->vm_end - vma->vm_start, + vma->vm_page_prot)) return -EAGAIN; return 0; } +static int i810_map_buffer(drm_buf_t *buf, struct file *filp) +{ + drm_i810_buf_priv_t *buf_priv = buf->dev_private; + int retcode = 0; + + if(buf_priv->currently_mapped == I810_BUF_MAPPED) return -EINVAL; + down(¤t->mm->mmap_sem); + filp->f_op->mmap = i810_mmap_buffers; + buf_priv->virtual = (void *)do_mmap(filp, 0, buf->total, + PROT_READ|PROT_WRITE, + MAP_SHARED, + buf->bus_address); + filp->f_op->mmap = drm_mmap; + if ((unsigned long)buf_priv->virtual > -1024UL) { + /* Real error */ + DRM_DEBUG("mmap error\n"); + retcode = (signed int)buf_priv->virtual; + } else { + buf_priv->currently_mapped = I810_BUF_MAPPED; + } + up(¤t->mm->mmap_sem); + return retcode; +} + +static int i810_unmap_buffer(drm_buf_t *buf) +{ + drm_i810_buf_priv_t *buf_priv = buf->dev_private; + int retcode = 0; + + if(buf_priv->currently_mapped != I810_BUF_MAPPED) return -EINVAL; + down(¤t->mm->mmap_sem); + retcode = do_munmap((unsigned long)buf_priv->virtual, + (size_t) buf->total); + buf_priv->currently_mapped = I810_BUF_UNMAPPED; + buf_priv->virtual = 0; + up(¤t->mm->mmap_sem); + + return retcode; +} + +static int i810_dma_get_buffer(drm_device_t *dev, drm_i810_dma_t *d, + struct file *filp) +{ + drm_buf_t *buf; + drm_i810_buf_priv_t *buf_priv; + int retcode = 0; + + buf = i810_freelist_get(dev); + if (!buf) { + retcode = -ENOMEM; + DRM_DEBUG("%s retcode %d\n", __FUNCTION__, retcode); + goto out_get_buf; + } + + retcode = i810_map_buffer(buf, filp); + if(retcode) { + i810_freelist_put(dev, buf); + DRM_DEBUG("mapbuf failed in %s retcode %d\n", __FUNCTION__, retcode); + goto out_get_buf; + } + buf->pid = current->pid; + buf_priv = buf->dev_private; + d->granted = 1; + d->request_idx = buf->idx; + d->request_size = buf->total; + d->virtual = buf_priv->virtual; + +out_get_buf: + return retcode; +} + static unsigned long i810_alloc_page(drm_device_t *dev) { unsigned long address; @@ -395,6 +457,9 @@ static void i810_dma_dispatch_general(drm_device_t *dev, drm_buf_t *buf, OUT_RING( I810_BUF_FREE ); OUT_RING( CMD_REPORT_HEAD ); ADVANCE_LP_RING(); + if(buf_priv->currently_mapped == I810_BUF_MAPPED) { + i810_unmap_buffer(buf); + } } static void i810_dma_dispatch_vertex(drm_device_t *dev, @@ -465,6 +530,9 @@ static void i810_dma_dispatch_vertex(drm_device_t *dev, OUT_RING( CMD_REPORT_HEAD ); OUT_RING( 0 ); ADVANCE_LP_RING(); + if(buf_priv->currently_mapped == I810_BUF_MAPPED) { + i810_unmap_buffer(buf); + } } @@ -727,6 +795,9 @@ void i810_reclaim_buffers(drm_device_t *dev, pid_t pid) if (buf->pid == pid && buf_priv) { cmpxchg(buf_priv->in_use, I810_BUF_USED, I810_BUF_FREE); + if(buf_priv->currently_mapped == I810_BUF_MAPPED) { + buf_priv->currently_mapped = I810_BUF_UNMAPPED; + } } } } @@ -760,19 +831,6 @@ int i810_lock(struct inode *inode, struct file *filp, unsigned int cmd, */ if (!ret) { -#if 0 - if (_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock) - != lock.context) { - long j = jiffies - dev->lock.lock_time; - - if (j > 0 && j <= DRM_LOCK_SLICE) { - /* Can't take lock if we just had it and - there is contention. */ - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(j); - } - } -#endif add_wait_queue(&dev->lock.lock_queue, &entry); for (;;) { if (!dev->lock.hw_lock) { @@ -929,53 +987,32 @@ int i810_getage(struct inode *inode, struct file *filp, unsigned int cmd, return 0; } -int i810_dma(struct inode *inode, struct file *filp, unsigned int cmd, - unsigned long arg) +int i810_getbuf(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg) { drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; - drm_device_dma_t *dma = dev->dma; int retcode = 0; - drm_dma_t d; + drm_i810_dma_t d; drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; u32 *hw_status = (u32 *)dev_priv->hw_status_page; drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *) dev_priv->sarea_priv; - - copy_from_user_ret(&d, (drm_dma_t *)arg, sizeof(d), -EFAULT); - DRM_DEBUG("%d %d: %d send, %d req\n", - current->pid, d.context, d.send_count, d.request_count); + DRM_DEBUG("getbuf\n"); + copy_from_user_ret(&d, (drm_i810_dma_t *)arg, sizeof(d), -EFAULT); if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { DRM_ERROR("i810_dma called without lock held\n"); return -EINVAL; } - - /* Please don't send us buffers. - */ - if (d.send_count != 0) { - DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n", - current->pid, d.send_count); - return -EINVAL; - } - /* We'll send you buffers. - */ - if (d.request_count < 0 || d.request_count > dma->buf_count) { - DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n", - current->pid, d.request_count, dma->buf_count); - return -EINVAL; - } - - d.granted_count = 0; + d.granted = 0; - if (!retcode && d.request_count) { - retcode = i810_dma_get_buffers(dev, &d); - } + retcode = i810_dma_get_buffer(dev, &d, filp); - DRM_DEBUG("i810_dma: %d returning, granted = %d\n", - current->pid, d.granted_count); + DRM_DEBUG("i810_dma: %d returning %d, granted = %d\n", + current->pid, retcode, d.granted); copy_to_user_ret((drm_dma_t *)arg, &d, sizeof(d), -EFAULT); sarea_priv->last_dispatch = (int) hw_status[5]; diff --git a/linux/i810_drm.h b/linux/i810_drm.h index 0754874c..7e435879 100644 --- a/linux/i810_drm.h +++ b/linux/i810_drm.h @@ -90,4 +90,11 @@ typedef struct _drm_i810_vertex { int discard; /* client is finished with the buffer? */ } drm_i810_vertex_t; +typedef struct drm_i810_dma { + void *virtual; + int request_idx; + int request_size; + int granted; +} drm_i810_dma_t; + #endif /* _I810_DRM_H_ */ diff --git a/linux/i810_drv.c b/linux/i810_drv.c index f1c83250..03585bdf 100644 --- a/linux/i810_drv.c +++ b/linux/i810_drv.c @@ -80,7 +80,6 @@ static drm_ioctl_desc_t i810_ioctls[] = { [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = { i810_addbufs, 1, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = { i810_markbufs, 1, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = { i810_infobufs, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = { i810_mapbufs, 1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = { i810_freebufs, 1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = { i810_addctx, 1, 1 }, @@ -93,8 +92,6 @@ static drm_ioctl_desc_t i810_ioctls[] = { [DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = { drm_adddraw, 1, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = { drm_rmdraw, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { i810_dma, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = { i810_lock, 1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = { i810_unlock, 1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = { drm_finish, 1, 0 }, @@ -107,11 +104,13 @@ static drm_ioctl_desc_t i810_ioctls[] = { [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = { drm_agp_free, 1, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { drm_agp_bind, 1, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { drm_agp_unbind, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_I810_INIT)] = { i810_dma_init, 1, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_I810_VERTEX)] = { i810_dma_vertex, 1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_I810_DMA)] = { i810_dma_general,1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_I810_FLUSH)] = { i810_flush_ioctl,1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_I810_GETAGE)] = { i810_getage, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_I810_GETBUF)] = { i810_getbuf, 1, 0 }, }; #define I810_IOCTL_COUNT DRM_ARRAY_SIZE(i810_ioctls) diff --git a/linux/i810_drv.h b/linux/i810_drv.h index 1badd36b..a4e4d6c7 100644 --- a/linux/i810_drv.h +++ b/linux/i810_drv.h @@ -71,8 +71,8 @@ extern int i810_unlock(struct inode *inode, struct file *filp, /* i810_dma.c */ extern int i810_dma_schedule(drm_device_t *dev, int locked); -extern int i810_dma(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); +extern int i810_getbuf(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); extern int i810_irq_install(drm_device_t *dev, int irq); extern int i810_irq_uninstall(drm_device_t *dev); extern int i810_control(struct inode *inode, struct file *filp, @@ -97,8 +97,6 @@ extern int i810_markbufs(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); extern int i810_freebufs(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); -extern int i810_mapbufs(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); extern int i810_addmap(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); @@ -124,16 +122,13 @@ extern int i810_context_switch_complete(drm_device_t *dev, int new); -/* Copy the outstanding cliprects for every I810_DMA_VERTEX buffer. - * This can be fixed by emitting directly to the ringbuffer in the - * 'vertex_dma' ioctl. -*/ -typedef struct { +typedef struct drm_i810_buf_priv { u32 *in_use; int my_use_idx; + int currently_mapped; + void *virtual; } drm_i810_buf_priv_t; - #define I810_DMA_GENERAL 0 #define I810_DMA_VERTEX 1 #define I810_DMA_DISCARD 2 /* not used */ diff --git a/shared-core/drm.h b/shared-core/drm.h index ae4c65ca..86ab0410 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -348,5 +348,5 @@ typedef struct drm_agp_info { #define DRM_IOCTL_I810_DMA DRM_IOW( 0x42, drm_i810_general_t) #define DRM_IOCTL_I810_FLUSH DRM_IO ( 0x43) #define DRM_IOCTL_I810_GETAGE DRM_IO ( 0x44) - +#define DRM_IOCTL_I810_GETBUF DRM_IOW( 0x45, drm_i810_dma_t) #endif diff --git a/shared/drm.h b/shared/drm.h index ae4c65ca..86ab0410 100644 --- a/shared/drm.h +++ b/shared/drm.h @@ -348,5 +348,5 @@ typedef struct drm_agp_info { #define DRM_IOCTL_I810_DMA DRM_IOW( 0x42, drm_i810_general_t) #define DRM_IOCTL_I810_FLUSH DRM_IO ( 0x43) #define DRM_IOCTL_I810_GETAGE DRM_IO ( 0x44) - +#define DRM_IOCTL_I810_GETBUF DRM_IOW( 0x45, drm_i810_dma_t) #endif