return NULL;
memset(sglist, 0, sizeof(*sglist) * nr_pages);
+ if (NULL == pages[0])
+ goto nopage;
if (PageHighMem(pages[0]))
/* DMA to highmem pages might not work */
goto highmem;
for (i = 0; i < nr_pages; i++)
if (TryLockPage(pages[i]))
goto err;
- dprintk(2,"lock ok\n");
+ dprintk(2,"lock ok [%d pages]\n",nr_pages);
return 0;
err:
dprintk(2,"unlock start ...\n");
for (i = 0; i < nr_pages; i++)
unlock_page(pages[i]);
- dprintk(2,"unlock ok\n");
+ dprintk(2,"unlock ok [%d pages]\n",nr_pages);
return 0;
}
/* --------------------------------------------------------------------- */
-void* videobuf_alloc(int size)
+void* videobuf_alloc(unsigned int size)
{
struct videobuf_buffer *vb;
spinlock_t *irqlock,
enum v4l2_buf_type type,
enum v4l2_field field,
- int msize)
+ unsigned int msize)
{
memset(q,0,sizeof(*q));
if (V4L2_FIELD_ALTERNATE == field) {
if (V4L2_FIELD_TOP == q->last) {
- field = V4L2_FIELD_TOP;
- q->last = V4L2_FIELD_TOP;
- } else {
field = V4L2_FIELD_BOTTOM;
q->last = V4L2_FIELD_BOTTOM;
+ } else {
+ field = V4L2_FIELD_TOP;
+ q->last = V4L2_FIELD_TOP;
}
}
return field;
videobuf_reqbufs(struct file *file, struct videobuf_queue *q,
struct v4l2_requestbuffers *req)
{
- int size,count,retval;
+ unsigned int size,count;
+ int retval;
if (req->type != q->type)
return -EINVAL;
size = 0;
q->ops->buf_setup(file,&count,&size);
size = PAGE_ALIGN(size);
+ dprintk(1,"reqbufs: bufs=%d, size=0x%x [%d pages total]\n",
+ count, size, (count*size)>>PAGE_SHIFT);
retval = videobuf_mmap_setup(file,q,count,size);
if (retval < 0)
retval = videobuf_waiton(q->read_buf,0,0);
if (0 == retval) {
videobuf_dma_pci_sync(q->pci,&q->read_buf->dma);
- retval = q->read_buf->size;
+ if (STATE_ERROR == q->read_buf->state)
+ retval = -EIO;
+ else
+ retval = q->read_buf->size;
}
done:
{
enum v4l2_field field;
unsigned long flags;
- int retval, bytes, size, nbufs;
+ unsigned size, nbufs, bytes;
+ int retval;
down(&q->lock);
count >= size &&
!(file->f_flags & O_NONBLOCK)) {
retval = videobuf_read_zerocopy(file,q,data,count,ppos);
- if (retval >= 0)
+ if (retval >= 0 || retval == -EIO)
/* ok, all done */
goto done;
/* fallback to kernel bounce buffer on failures */
goto done;
videobuf_dma_pci_sync(q->pci,&q->read_buf->dma);
+ if (STATE_ERROR == q->read_buf->state) {
+ /* catch I/O errors */
+ q->ops->buf_release(file,q->read_buf);
+ kfree(q->read_buf);
+ q->read_buf = NULL;
+ retval = -EIO;
+ goto done;
+ }
+
/* copy to userspace */
bytes = count;
if (bytes > q->read_buf->size - q->read_off)
char *data, size_t count, loff_t *ppos,
int vbihack)
{
- unsigned int *fc;
- int err, bytes, retval;
+ unsigned int *fc, bytes;
+ int err, retval;
unsigned long flags;
down(&q->lock);
};
int videobuf_mmap_setup(struct file *file, struct videobuf_queue *q,
- int bcount, int bsize)
+ unsigned int bcount, unsigned int bsize)
{
- int i,err;
+ unsigned int i;
+ int err;
err = videobuf_mmap_free(file,q);
if (0 != err)
struct videobuf_queue *q)
{
struct videobuf_mapping *map;
- int first,last,size,i,retval;
+ unsigned int first,last,size,i;
+ int retval;
down(&q->lock);
retval = -EINVAL;
for (first = 0; first < VIDEO_MAX_FRAME; first++) {
if (NULL == q->bufs[first])
continue;
- if (q->bufs[first]->boff == (vma->vm_pgoff << PAGE_SHIFT))
+ if (q->bufs[first]->boff == (vma->vm_pgoff << PAGE_SHIFT))
break;
}
if (VIDEO_MAX_FRAME == first) {
struct videobuf_queue;
struct videobuf_mapping {
- int count;
+ unsigned int count;
int highmem_ok;
unsigned long start;
unsigned long end;
};
struct videobuf_buffer {
- int i;
+ unsigned int i;
/* info about the buffer */
- int width;
- int height;
- long size;
+ unsigned int width;
+ unsigned int height;
+ unsigned long size;
enum v4l2_field field;
enum videobuf_state state;
struct videobuf_dmabuf dma;
struct list_head stream; /* QBUF/DQBUF list */
/* for mmap'ed buffers */
- off_t boff; /* buffer offset (mmap) */
+ size_t boff; /* buffer offset (mmap) */
size_t bsize; /* buffer size */
unsigned long baddr; /* buffer addr (userland ptr!) */
struct videobuf_mapping *map;
/* touched by irq handler */
struct list_head queue;
wait_queue_head_t done;
- int field_count;
+ unsigned int field_count;
struct timeval ts;
};
struct videobuf_queue_ops {
- int (*buf_setup)(struct file *file, int *count, int *size);
+ int (*buf_setup)(struct file *file,
+ unsigned int *count, unsigned int *size);
int (*buf_prepare)(struct file *file,struct videobuf_buffer *vb,
enum v4l2_field field);
void (*buf_queue)(struct file *file,struct videobuf_buffer *vb);
struct pci_dev *pci;
enum v4l2_buf_type type;
- int msize;
+ unsigned int msize;
enum v4l2_field field;
enum v4l2_field last; /* for field=V4L2_FIELD_ALTERNATE */
struct videobuf_buffer *bufs[VIDEO_MAX_FRAME];
struct videobuf_queue_ops *ops;
/* capture via mmap() + ioctl(QBUF/DQBUF) */
- int streaming;
+ unsigned int streaming;
struct list_head stream;
/* capture via read() */
- int reading;
- int read_off;
+ unsigned int reading;
+ unsigned int read_off;
struct videobuf_buffer *read_buf;
};
-void* videobuf_alloc(int size);
+void* videobuf_alloc(unsigned int size);
int videobuf_waiton(struct videobuf_buffer *vb, int non_blocking, int intr);
int videobuf_iolock(struct pci_dev *pci, struct videobuf_buffer *vb);
struct videobuf_queue_ops *ops,
struct pci_dev *pci, spinlock_t *irqlock,
enum v4l2_buf_type type,
- enum v4l2_field field, int msize);
+ enum v4l2_field field,
+ unsigned int msize);
int videobuf_queue_is_busy(struct videobuf_queue *q);
void videobuf_queue_cancel(struct file *file, struct videobuf_queue *q);
poll_table *wait);
int videobuf_mmap_setup(struct file *file, struct videobuf_queue *q,
- int bcount, int bsize);
+ unsigned int bcount, unsigned int bsize);
int videobuf_mmap_free(struct file *file, struct videobuf_queue *q);
int videobuf_mmap_mapper(struct vm_area_struct *vma,
struct videobuf_queue *q);