⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vfc_dev.c

📁 该文件是rt_linux
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * drivers/sbus/char/vfc_dev.c * * Driver for the Videopix Frame Grabber. *  * In order to use the VFC you need to program the video controller * chip. This chip is the Phillips SAA9051.  You need to call their * documentation ordering line to get the docs. * * There is very little documentation on the VFC itself.  There is * some useful info that can be found in the manuals that come with * the card.  I will hopefully write some better docs at a later date. * * Copyright (C) 1996 Manish Vachharajani (mvachhar@noc.rutgers.edu) * */#include <linux/module.h>#include <linux/kernel.h>#include <linux/string.h>#include <linux/slab.h>#include <linux/errno.h>#include <linux/sched.h>#include <linux/fs.h>#include <linux/smp_lock.h>#include <linux/delay.h>#include <linux/spinlock.h>#include <asm/openprom.h>#include <asm/oplib.h>#include <asm/io.h>#include <asm/system.h>#include <asm/sbus.h>#include <asm/page.h>#include <asm/pgtable.h>#include <asm/uaccess.h>#define VFC_MAJOR (60)#if 0#define VFC_IOCTL_DEBUG#endif#include "vfc.h"#include <asm/vfc_ioctls.h>static struct file_operations vfc_fops;static devfs_handle_t devfs_handle;  /*  For the directory  */struct vfc_dev **vfc_dev_lst;static char vfcstr[]="vfc";static unsigned char saa9051_init_array[VFC_SAA9051_NR] = {	0x00, 0x64, 0x72, 0x52,	0x36, 0x18, 0xff, 0x20,	0xfc, 0x77, 0xe3, 0x50,	0x3e};void vfc_lock_device(struct vfc_dev *dev){	down(&dev->device_lock_sem);}void vfc_unlock_device(struct vfc_dev *dev){	up(&dev->device_lock_sem);}void vfc_captstat_reset(struct vfc_dev *dev) {	dev->control_reg |= VFC_CONTROL_CAPTRESET;	sbus_writel(dev->control_reg, &dev->regs->control);	dev->control_reg &= ~VFC_CONTROL_CAPTRESET;	sbus_writel(dev->control_reg, &dev->regs->control);	dev->control_reg |= VFC_CONTROL_CAPTRESET;	sbus_writel(dev->control_reg, &dev->regs->control);}void vfc_memptr_reset(struct vfc_dev *dev) {	dev->control_reg |= VFC_CONTROL_MEMPTR;	sbus_writel(dev->control_reg, &dev->regs->control);	dev->control_reg &= ~VFC_CONTROL_MEMPTR;	sbus_writel(dev->control_reg, &dev->regs->control);	dev->control_reg |= VFC_CONTROL_MEMPTR; 	sbus_writel(dev->control_reg, &dev->regs->control);}int vfc_csr_init(struct vfc_dev *dev){	dev->control_reg = 0x80000000;	sbus_writel(dev->control_reg, &dev->regs->control);	udelay(200); 	dev->control_reg &= ~0x80000000;	sbus_writel(dev->control_reg, &dev->regs->control);	udelay(100); 	sbus_writel(0x0f000000, &dev->regs->i2c_magic2);	vfc_memptr_reset(dev);	dev->control_reg &= ~VFC_CONTROL_DIAGMODE;	dev->control_reg &= ~VFC_CONTROL_CAPTURE;	dev->control_reg |= 0x40000000;	sbus_writel(dev->control_reg, &dev->regs->control);	vfc_captstat_reset(dev);	return 0;}int vfc_saa9051_init(struct vfc_dev *dev){	int i;	for (i = 0; i < VFC_SAA9051_NR; i++)		dev->saa9051_state_array[i] = saa9051_init_array[i];	vfc_i2c_sendbuf(dev,VFC_SAA9051_ADDR,			dev->saa9051_state_array, VFC_SAA9051_NR);	return 0;}int init_vfc_hw(struct vfc_dev *dev) {	vfc_lock_device(dev);	vfc_csr_init(dev);	vfc_pcf8584_init(dev);	vfc_init_i2c_bus(dev); /* hopefully this doesn't undo the magic				  sun code above*/	vfc_saa9051_init(dev);	vfc_unlock_device(dev);	return 0; }int init_vfc_devstruct(struct vfc_dev *dev, int instance) {	dev->instance=instance;	init_MUTEX(&dev->device_lock_sem);	dev->control_reg=0;	init_waitqueue_head(&dev->poll_wait);	dev->busy=0;	return 0;}int init_vfc_device(struct sbus_dev *sdev,struct vfc_dev *dev, int instance){	char devname[8];	if(dev == NULL) {		printk(KERN_ERR "VFC: Bogus pointer passed\n");		return -ENOMEM;	}	printk("Initializing vfc%d\n",instance);	dev->regs = NULL;	dev->regs = (volatile struct vfc_regs *)		sbus_ioremap(&sdev->resource[0], 0,			     sizeof(struct vfc_regs), vfcstr);	dev->which_io = sdev->reg_addrs[0].which_io;	dev->phys_regs = (struct vfc_regs *) sdev->reg_addrs[0].phys_addr;	if (dev->regs == NULL)		return -EIO;	printk("vfc%d: registers mapped at phys_addr: 0x%lx\n    virt_addr: 0x%lx\n",	       instance,(unsigned long)sdev->reg_addrs[0].phys_addr,(unsigned long)dev->regs);	if (init_vfc_devstruct(dev, instance))		return -EINVAL;	if (init_vfc_hw(dev))		return -EIO;	sprintf (devname, "%d", instance);	dev->de = devfs_register (devfs_handle, devname, DEVFS_FL_DEFAULT,				  VFC_MAJOR, instance,				  S_IFCHR | S_IRUSR | S_IWUSR,				  &vfc_fops, NULL);	return 0;}struct vfc_dev *vfc_get_dev_ptr(int instance) {	return vfc_dev_lst[instance];}static spinlock_t vfc_dev_lock = SPIN_LOCK_UNLOCKED;static int vfc_open(struct inode *inode, struct file *file) {	struct vfc_dev *dev;	spin_lock(&vfc_dev_lock);	dev = vfc_get_dev_ptr(MINOR(inode->i_rdev));	if (dev == NULL) {		spin_unlock(&vfc_dev_lock);		return -ENODEV;	}	if (dev->busy) {		spin_unlock(&vfc_dev_lock);		return -EBUSY;	}	dev->busy = 1;	spin_unlock(&vfc_dev_lock);	vfc_lock_device(dev);		vfc_csr_init(dev);	vfc_pcf8584_init(dev);	vfc_init_i2c_bus(dev);	vfc_saa9051_init(dev);	vfc_memptr_reset(dev);	vfc_captstat_reset(dev);		vfc_unlock_device(dev);	return 0;}static int vfc_release(struct inode *inode,struct file *file) {	struct vfc_dev *dev;	spin_lock(&vfc_dev_lock);	dev = vfc_get_dev_ptr(MINOR(inode->i_rdev));	if (!dev || !dev->busy) {		spin_unlock(&vfc_dev_lock);		return -EINVAL;	}	dev->busy = 0;	spin_unlock(&vfc_dev_lock);	return 0;}static int vfc_debug(struct vfc_dev *dev, int cmd, unsigned long arg) {	struct vfc_debug_inout inout;	unsigned char *buffer;	if (!capable(CAP_SYS_ADMIN))		return -EPERM;	switch(cmd) {	case VFC_I2C_SEND:		if(copy_from_user(&inout, (void *)arg, sizeof(inout)))			return -EFAULT;		buffer = kmalloc(inout.len*sizeof(char), GFP_KERNEL);		if (buffer == NULL)			return -ENOMEM;		if(copy_from_user(buffer, inout.buffer, 				  inout.len*sizeof(char))) {			kfree(buffer);			return -EFAULT;		}				vfc_lock_device(dev);		inout.ret=			vfc_i2c_sendbuf(dev,inout.addr & 0xff,					inout.buffer,inout.len);		if (copy_to_user((void *)arg,&inout,sizeof(inout))) {			kfree(buffer);			return -EFAULT;		}		vfc_unlock_device(dev);		break;	case VFC_I2C_RECV:		if (copy_from_user(&inout, (void *)arg, sizeof(inout)))			return -EFAULT;		buffer = kmalloc(inout.len, GFP_KERNEL);		if (buffer == NULL)			return -ENOMEM;		memset(buffer,0,inout.len*sizeof(char));		vfc_lock_device(dev);		inout.ret=			vfc_i2c_recvbuf(dev,inout.addr & 0xff					,buffer,inout.len);		vfc_unlock_device(dev);				if (copy_to_user(inout.buffer, buffer, inout.len)) {			kfree(buffer);			return -EFAULT;		}		if (copy_to_user((void *)arg,&inout,sizeof(inout))) {			kfree(buffer);			return -EFAULT;		}		kfree(buffer);		break;	default:		return -EINVAL;	};	return 0;}int vfc_capture_start(struct vfc_dev *dev) {	vfc_captstat_reset(dev);	dev->control_reg = sbus_readl(&dev->regs->control);	if((dev->control_reg & VFC_STATUS_CAPTURE)) {		printk(KERN_ERR "vfc%d: vfc capture status not reset\n",		       dev->instance);		return -EIO;	}	vfc_lock_device(dev);	dev->control_reg &= ~VFC_CONTROL_CAPTURE;	sbus_writel(dev->control_reg, &dev->regs->control);	dev->control_reg |= VFC_CONTROL_CAPTURE;	sbus_writel(dev->control_reg, &dev->regs->control);	dev->control_reg &= ~VFC_CONTROL_CAPTURE;	sbus_writel(dev->control_reg, &dev->regs->control);	vfc_unlock_device(dev);	return 0;}int vfc_capture_poll(struct vfc_dev *dev) {	int timeout = 1000;	while (!timeout--) {		if (dev->regs->control & VFC_STATUS_CAPTURE)			break;		vfc_i2c_delay_no_busy(dev, 100);	}	if(!timeout) {		printk(KERN_WARNING "vfc%d: capture timed out\n",		       dev->instance);		return -ETIMEDOUT;	}	return 0;}static int vfc_set_control_ioctl(struct inode *inode, struct file *file, 			  struct vfc_dev *dev, unsigned long arg) {	int setcmd, ret = 0;	if (copy_from_user(&setcmd,(void *)arg,sizeof(unsigned int)))		return -EFAULT;	VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCSCTRL) arg=0x%x\n",				dev->instance,setcmd));	switch(setcmd) {	case MEMPRST:		vfc_lock_device(dev);		vfc_memptr_reset(dev);		vfc_unlock_device(dev);		ret=0;		break;	case CAPTRCMD:		vfc_capture_start(dev);		vfc_capture_poll(dev);		break;	case DIAGMODE:		if(capable(CAP_SYS_ADMIN)) {			vfc_lock_device(dev);			dev->control_reg |= VFC_CONTROL_DIAGMODE;			sbus_writel(dev->control_reg, &dev->regs->control);			vfc_unlock_device(dev);			ret = 0;		} else {			ret = -EPERM; 		}		break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -