/*
*
* generic helper functions for video4linux capture buffers, to handle
* memory management and PCI DMA. Right now bttv + saa7134 use it.
*
* 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 1.1
* as data often must be uncompressed by the drivers).
*
* (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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/vmalloc.h>
#include <linux/pagemap.h>
#include <linux/slab.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
#include <asm/page.h>
#include <asm/pgtable.h>
#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_param(debug, int, 0644);
MODULE_DESCRIPTION("helper module to manage video4linux pci dma buffers");
MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
MODULE_LICENSE("GPL");
#define dprintk(level, fmt, arg...) if (debug >= level) \
printk(KERN_DEBUG "vbuf: " fmt , ## arg)
struct scatterlist*
videobuf_vmalloc_to_sg(unsigned char *virt, int nr_pages)
{
struct scatterlist *sglist;
struct page *pg;
int i;
sglist = kmalloc(sizeof(struct scatterlist)*nr_pages, GFP_KERNEL);
if (NULL == sglist)
return NULL;
memset(sglist,0,sizeof(struct scatterlist)*nr_pages);
for (i = 0; i < nr_pages; i++, virt += PAGE_SIZE) {
pg = vmalloc_to_page(virt);
if (NULL == pg)
goto err;
if (PageHighMem(pg))
BUG();
sglist[i].page = pg;
sglist[i].length = PAGE_SIZE;
}
return sglist;
err:
kfree(sglist);
return NULL;
}
struct scatterlist*
videobuf_pages_to_sg(struct page **pages, int nr_pages, int offset)
{
struct scatterlist *sglist;
int i = 0;
if (NULL == pages[0])
return NULL;
sglist = kmalloc(sizeof(*sglist) * nr_pages, GFP_KERNEL);
if (NULL == sglist)
return NULL;
memset(sglist, 0, sizeof(*sglist) * nr_pages);
if (NULL == pages[0])
goto