* The functions expect the hardware being able to scatter gatter
* (i.e. the buffers are not linear in physical memory, but fragmented
* into PAGE_SIZE chunks). They also assume the driver does not need
- * to touch the video data (thus it is probably not useful for USB as
- * data often must be uncompressed by the drivers).
+ * to touch the video data (thus it is probably not useful for USB 1.1
+ * as data often must be uncompressed by the drivers).
*
- * (c) 2001,02 Gerd Knorr <kraxel@bytesex.org>
+ * (c) 2001-2004 Gerd Knorr <kraxel@bytesex.org> [SUSE Labs]
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#include <media/video-buf.h>
+#define MAGIC_DMABUF 0x19721112
+#define MAGIC_BUFFER 0x20040302
+#define MAGIC_CHECK(is,should) if (unlikely((is) != (should))) \
+ { printk(KERN_ERR "magic mismatch: %x (expected %x)\n",is,should); BUG(); }
+
static int debug = 0;
MODULE_DESCRIPTION("helper module to manage video4linux pci dma buffers");
/* --------------------------------------------------------------------- */
+void videobuf_dma_init(struct videobuf_dmabuf *dma)
+{
+ memset(dma,0,sizeof(*dma));
+ dma->magic = MAGIC_DMABUF;
+}
+
int videobuf_dma_init_user(struct videobuf_dmabuf *dma, int direction,
unsigned long data, unsigned long size)
{
int videobuf_dma_pci_map(struct pci_dev *dev, struct videobuf_dmabuf *dma)
{
- if (0 == dma->nr_pages)
- BUG();
+ MAGIC_CHECK(dma->magic,MAGIC_DMABUF);
+ BUG_ON(0 == dma->nr_pages);
if (dma->pages) {
dma->sglist = videobuf_pages_to_sg(dma->pages, dma->nr_pages,
int videobuf_dma_pci_sync(struct pci_dev *dev, struct videobuf_dmabuf *dma)
{
- if (!dma->sglen)
- BUG();
+ MAGIC_CHECK(dma->magic,MAGIC_DMABUF);
+ BUG_ON(!dma->sglen);
if (!dma->bus_addr)
pci_dma_sync_sg_for_cpu(dev,dma->sglist,dma->nr_pages,dma->direction);
int videobuf_dma_pci_unmap(struct pci_dev *dev, struct videobuf_dmabuf *dma)
{
+ MAGIC_CHECK(dma->magic,MAGIC_DMABUF);
if (!dma->sglen)
return 0;
int videobuf_dma_free(struct videobuf_dmabuf *dma)
{
- if (dma->sglen)
- BUG();
+ MAGIC_CHECK(dma->magic,MAGIC_DMABUF);
+ BUG_ON(dma->sglen);
if (dma->pages) {
int i;
vb = kmalloc(size,GFP_KERNEL);
if (NULL != vb) {
memset(vb,0,size);
+ videobuf_dma_init(&vb->dma);
init_waitqueue_head(&vb->done);
+ vb->magic = MAGIC_BUFFER;
}
return vb;
}
int retval = 0;
DECLARE_WAITQUEUE(wait, current);
+ MAGIC_CHECK(vb->magic,MAGIC_BUFFER);
add_wait_queue(&vb->done, &wait);
while (vb->state == STATE_ACTIVE || vb->state == STATE_QUEUED) {
if (non_blocking) {
int err,pages;
dma_addr_t bus;
+ MAGIC_CHECK(vb->magic,MAGIC_BUFFER);
switch (vb->memory) {
case V4L2_MEMORY_MMAP:
case V4L2_MEMORY_USERPTR:
videobuf_status(struct v4l2_buffer *b, struct videobuf_buffer *vb,
enum v4l2_buf_type type)
{
+ MAGIC_CHECK(vb->magic,MAGIC_BUFFER);
+
b->index = vb->i;
b->type = type;
break;
}
+ if (vb->input != UNSET) {
+ b->flags |= V4L2_BUF_FLAG_INPUT;
+ b->input = vb->input;
+ }
+
b->field = vb->field;
b->timestamp = vb->ts;
b->bytesused = vb->size;
req->memory != V4L2_MEMORY_OVERLAY)
return -EINVAL;
+ if (q->streaming)
+ return -EBUSY;
+ if (!list_empty(&q->stream))
+ return -EBUSY;
+
down(&q->lock);
count = req->count;
if (count > VIDEO_MAX_FRAME)
buf = q->bufs[b->index];
if (NULL == buf)
goto done;
+ MAGIC_CHECK(buf->magic,MAGIC_BUFFER);
if (buf->memory != b->memory)
goto done;
if (buf->state == STATE_QUEUED ||
buf->state == STATE_ACTIVE)
goto done;
+ if (b->flags & V4L2_BUF_FLAG_INPUT) {
+ if (b->input >= q->inputs)
+ goto done;
+ buf->input = b->input;
+ } else {
+ buf->input = UNSET;
+ }
+
switch (b->memory) {
case V4L2_MEMORY_MMAP:
if (0 == buf->baddr)
case V4L2_MEMORY_USERPTR:
if (b->length < buf->bsize)
goto done;
+ if (STATE_NEEDS_INIT != buf->state && buf->baddr != b->m.userptr)
+ q->ops->buf_release(file,buf);
buf->baddr = b->m.userptr;
break;
case V4L2_MEMORY_OVERLAY:
static ssize_t
videobuf_read_zerocopy(struct file *file, struct videobuf_queue *q,
- char *data, size_t count, loff_t *ppos)
+ char __user *data, size_t count, loff_t *ppos)
{
enum v4l2_field field;
unsigned long flags;
}
ssize_t videobuf_read_one(struct file *file, struct videobuf_queue *q,
- char *data, size_t count, loff_t *ppos)
+ char __user *data, size_t count, loff_t *ppos)
{
enum v4l2_field field;
unsigned long flags;
}
ssize_t videobuf_read_stream(struct file *file, struct videobuf_queue *q,
- char *data, size_t count, loff_t *ppos,
+ char __user *data, size_t count, loff_t *ppos,
int vbihack)
{
unsigned int *fc, bytes;
for (i = 0; i < bcount; i++) {
q->bufs[i] = videobuf_alloc(q->msize);
q->bufs[i]->i = i;
+ q->bufs[i]->input = UNSET;
q->bufs[i]->memory = memory;
q->bufs[i]->bsize = bsize;
switch (memory) {
case V4L2_MEMORY_OVERLAY:
/* nothing */
break;
- };
+ }
}
dprintk(1,"mmap setup: %d buffers, %d bytes each\n",
bcount,bsize);
map->end = vma->vm_end;
map->q = q;
vma->vm_ops = &videobuf_vm_ops;
- vma->vm_flags |= VM_DONTEXPAND;
+ vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED;
vma->vm_flags &= ~VM_IO; /* using shared anonymous pages */
vma->vm_private_data = map;
dprintk(1,"mmap %p: %08lx-%08lx pgoff %08lx bufs %d-%d\n",
EXPORT_SYMBOL_GPL(videobuf_vmalloc_to_sg);
+EXPORT_SYMBOL_GPL(videobuf_dma_init);
EXPORT_SYMBOL_GPL(videobuf_dma_init_user);
EXPORT_SYMBOL_GPL(videobuf_dma_init_kernel);
EXPORT_SYMBOL_GPL(videobuf_dma_init_overlay);