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

📄 planb.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
				case PLANBIOCGSTAT:		{			struct planb_stat_regs pstat;			DEBUG("PlanB: IOCTL PLANBIOCGSTAT\n");			pstat.ch1_stat = in_le32(&pb->planb_base->ch1.status);			pstat.ch2_stat = in_le32(&pb->planb_base->ch2.status);			pstat.saa_stat0 = saa_status(0, pb);			pstat.saa_stat1 = saa_status(1, pb);			if(copy_to_user((void *)arg, (void *)&pstat,							sizeof(pstat)))				return -EFAULT;			return 0;		}				case PLANBIOCSMODE: {			int v;			DEBUG("PlanB: IOCTL PLANBIOCSMODE\n");			if(copy_from_user(&v, arg, sizeof(v)))				return -EFAULT;			switch(v)			{			case PLANB_TV_MODE:				saa_set (SAA7196_STDC,					(saa_regs[pb->win.norm][SAA7196_STDC] &					  0x7f), pb);				break;			case PLANB_VTR_MODE:				saa_set (SAA7196_STDC,					(saa_regs[pb->win.norm][SAA7196_STDC] |					  0x80), pb);				break;			default:				return -EINVAL;				break;			}			pb->win.mode = v;			return 0;		}		case PLANBIOCGMODE: {			int v=pb->win.mode;			DEBUG("PlanB: IOCTL PLANBIOCGMODE\n");			if(copy_to_user(arg,&v,sizeof(v)))				return -EFAULT;			return 0;		}#ifdef PLANB_GSCANLINE		case PLANBG_GRAB_BPL: {			int v=pb->gbytes_per_line;			DEBUG("PlanB: IOCTL PLANBG_GRAB_BPL\n");			if(copy_to_user(arg,&v,sizeof(v)))				return -EFAULT;			return 0;		}#endif /* PLANB_GSCANLINE */		case PLANB_INTR_DEBUG: {			int i;			DEBUG("PlanB: IOCTL PLANB_INTR_DEBUG\n");			if(copy_from_user(&i, arg, sizeof(i)))				return -EFAULT;			/* avoid hang ups all together */			for (i = 0; i < MAX_GBUFFERS; i++) {				if(pb->frame_stat[i] == GBUFFER_GRABBING) {					pb->frame_stat[i] = GBUFFER_DONE;				}			}			if(pb->grabbing)				pb->grabbing--;			wake_up_interruptible(&pb->capq);			return 0;		}		case PLANB_INV_REGS: {			int i;			struct planb_any_regs any;			DEBUG("PlanB: IOCTL PLANB_INV_REGS\n");			if(copy_from_user(&any, arg, sizeof(any)))				return -EFAULT;			if(any.offset < 0 || any.offset + any.bytes > 0x400)				return -EINVAL;			if(any.bytes > 128)				return -EINVAL;			for (i = 0; i < any.bytes; i++) {				any.data[i] =					in_8((unsigned char *)pb->planb_base							+ any.offset + i);			}			if(copy_to_user(arg,&any,sizeof(any)))				return -EFAULT;			return 0;		}		default:		{			DEBUG("PlanB: Unimplemented IOCTL\n");			return -ENOIOCTLCMD;		}	/* Some IOCTLs are currently unsupported on PlanB */		case VIDIOCGTUNER: {		DEBUG("PlanB: IOCTL VIDIOCGTUNER\n");			goto unimplemented; }		case VIDIOCSTUNER: {		DEBUG("PlanB: IOCTL VIDIOCSTUNER\n");			goto unimplemented; }		case VIDIOCSFREQ: {		DEBUG("PlanB: IOCTL VIDIOCSFREQ\n");			goto unimplemented; }		case VIDIOCGFREQ: {		DEBUG("PlanB: IOCTL VIDIOCGFREQ\n");			goto unimplemented; }		case VIDIOCKEY: {		DEBUG("PlanB: IOCTL VIDIOCKEY\n");			goto unimplemented; }		case VIDIOCSAUDIO: {		DEBUG("PlanB: IOCTL VIDIOCSAUDIO\n");			goto unimplemented; }		case VIDIOCGAUDIO: {		DEBUG("PlanB: IOCTL VIDIOCGAUDIO\n");			goto unimplemented; }unimplemented:		DEBUG("       Unimplemented\n");			return -ENOIOCTLCMD;	}	return 0;}static int planb_mmap(struct vm_area_struct *vma, struct video_device *dev, const char *adr, unsigned long size){	int i;	struct planb *pb = (struct planb *)dev;        unsigned long start = (unsigned long)adr;	if (size > MAX_GBUFFERS * PLANB_MAX_FBUF)	        return -EINVAL;	if (!pb->rawbuf) {		int err;		if((err=grabbuf_alloc(pb)))			return err;	}	for (i = 0; i < pb->rawbuf_size; i++) {		unsigned long pfn;		pfn = virt_to_phys((void *)pb->rawbuf[i]) >> PAGE_SHIFT;		if (remap_pfn_range(vma, start, pfn, PAGE_SIZE, PAGE_SHARED))			return -EAGAIN;		start += PAGE_SIZE;		if (size <= PAGE_SIZE)			break;		size -= PAGE_SIZE;	}	return 0;}static struct video_device planb_template={	.owner		= THIS_MODULE,	.name		= PLANB_DEVICE_NAME,	.type		= VID_TYPE_OVERLAY,	.hardware	= VID_HARDWARE_PLANB,	.open		= planb_open,	.close		= planb_close,	.read		= planb_read,	.write		= planb_write,	.ioctl		= planb_ioctl,	.mmap		= planb_mmap,	/* mmap? */};static int init_planb(struct planb *pb){	unsigned char saa_rev;	int i, result;	memset ((void *) &pb->win, 0, sizeof (struct planb_window));	/* Simple sanity check */	if(def_norm >= NUM_SUPPORTED_NORM || def_norm < 0) {		printk(KERN_ERR "PlanB: Option(s) invalid\n");		return -2;	}	pb->win.norm = def_norm;	pb->win.mode = PLANB_TV_MODE;	/* TV mode */	pb->win.interlace=1;	pb->win.x=0;	pb->win.y=0;	pb->win.width=768; /* 640 */	pb->win.height=576; /* 480 */	pb->maxlines=576;#if 0	btv->win.cropwidth=768; /* 640 */	btv->win.cropheight=576; /* 480 */	btv->win.cropx=0;	btv->win.cropy=0;#endif	pb->win.pad=0;	pb->win.bpp=4;	pb->win.depth=32;	pb->win.color_fmt=PLANB_COLOUR32;	pb->win.bpl=1024*pb->win.bpp;	pb->win.swidth=1024;	pb->win.sheight=768;#ifdef PLANB_GSCANLINE	if((pb->gbytes_per_line = PLANB_MAXPIXELS * 4) > PAGE_SIZE				|| (pb->gbytes_per_line <= 0))		return -3;	else {		/* page align pb->gbytes_per_line for DMA purpose */		for(i = PAGE_SIZE; pb->gbytes_per_line < (i>>1);)			i>>=1;		pb->gbytes_per_line = i;	}#endif	pb->tab_size = PLANB_MAXLINES + 40;	pb->suspend = 0;	init_MUTEX(&pb->lock);	pb->ch1_cmd = 0;	pb->ch2_cmd = 0;	pb->mask = 0;	pb->priv_space = 0;	pb->offset = 0;	pb->user = 0;	pb->overlay = 0;	init_waitqueue_head(&pb->suspendq);	pb->cmd_buff_inited = 0;	pb->frame_buffer_phys = 0;	/* Reset DMA controllers */	planb_dbdma_stop(&pb->planb_base->ch2);	planb_dbdma_stop(&pb->planb_base->ch1);	saa_rev =  (saa_status(0, pb) & 0xf0) >> 4;	printk(KERN_INFO "PlanB: SAA7196 video processor rev. %d\n", saa_rev);	/* Initialize the SAA registers in memory and on chip */	saa_init_regs (pb);	/* clear interrupt mask */	pb->intr_mask = PLANB_CLR_IRQ;        result = request_irq(pb->irq, planb_irq, 0, "PlanB", (void *)pb);        if (result < 0) {	        if (result==-EINVAL)	                printk(KERN_ERR "PlanB: Bad irq number (%d) "						"or handler\n", (int)pb->irq);		else if (result==-EBUSY)			printk(KERN_ERR "PlanB: I don't know why, "					"but IRQ %d is busy\n", (int)pb->irq);		return result;	}	disable_irq(pb->irq);        	/* Now add the template and register the device unit. */	memcpy(&pb->video_dev,&planb_template,sizeof(planb_template));	pb->picture.brightness=0x90<<8;	pb->picture.contrast = 0x70 << 8;	pb->picture.colour = 0x70<<8;	pb->picture.hue = 0x8000;	pb->picture.whiteness = 0;	pb->picture.depth = pb->win.depth;	pb->frame_stat=NULL;	init_waitqueue_head(&pb->capq);	for(i=0; i<MAX_GBUFFERS; i++) {		pb->gbuf_idx[i] = PLANB_MAX_FBUF * i / PAGE_SIZE;		pb->gwidth[i]=0;		pb->gheight[i]=0;		pb->gfmt[i]=0;		pb->cap_cmd[i]=NULL;#ifndef PLANB_GSCANLINE		pb->l_fr_addr_idx[i] = MAX_GBUFFERS * (PLANB_MAX_FBUF						/ PAGE_SIZE + 1) + MAX_LNUM * i;		pb->lsize[i] = 0;		pb->lnum[i] = 0;#endif	}	pb->rawbuf=NULL;	pb->grabbing=0;	/* enable interrupts */	out_le32(&pb->planb_base->intr_stat, PLANB_CLR_IRQ);	pb->intr_mask = PLANB_FRM_IRQ;	enable_irq(pb->irq);	if(video_register_device(&pb->video_dev, VFL_TYPE_GRABBER, video_nr)<0)		return -1;	return 0;}/* *	Scan for a PlanB controller, request the irq and map the io memory  */static int find_planb(void){	struct planb		*pb;	struct device_node	*planb_devices;	unsigned char		dev_fn, confreg, bus;	unsigned int		old_base, new_base;	unsigned int		irq;	struct pci_dev 		*pdev;	int rc;	if (_machine != _MACH_Pmac)		return 0;	planb_devices = find_devices("planb");	if (planb_devices == 0) {		planb_num=0;		printk(KERN_WARNING "PlanB: no device found!\n");		return planb_num;	}	if (planb_devices->next != NULL)		printk(KERN_ERR "Warning: only using first PlanB device!\n");	pb = &planbs[0];	planb_num = 1;        if (planb_devices->n_addrs != 1) {                printk (KERN_WARNING "PlanB: expecting 1 address for planb "                	"(got %d)", planb_devices->n_addrs);		return 0;	}	if (planb_devices->n_intrs == 0) {		printk(KERN_WARNING "PlanB: no intrs for device %s\n",		       planb_devices->full_name);		return 0;	} else {		irq = planb_devices->intrs[0].line;	}	/* Initialize PlanB's PCI registers */	/* There is a bug with the way OF assigns addresses	   to the devices behind the chaos bridge.	   control needs only 0x1000 of space, but decodes only	   the upper 16 bits. It therefore occupies a full 64K.	   OF assigns the planb controller memory within this space;	   so we need to change that here in order to access planb. */	/* We remap to 0xf1000000 in hope that nobody uses it ! */	bus = (planb_devices->addrs[0].space >> 16) & 0xff;	dev_fn = (planb_devices->addrs[0].space >> 8) & 0xff;	confreg = planb_devices->addrs[0].space & 0xff;	old_base = planb_devices->addrs[0].address;	new_base = 0xf1000000;	DEBUG("PlanB: Found on bus %d, dev %d, func %d, "		"membase 0x%x (base reg. 0x%x)\n",		bus, PCI_SLOT(dev_fn), PCI_FUNC(dev_fn), old_base, confreg);	pdev = pci_find_slot (bus, dev_fn);	if (!pdev) {		printk(KERN_ERR "planb: cannot find slot\n");		goto err_out;	}	/* Enable response in memory space, bus mastering,	   use memory write and invalidate */	rc = pci_enable_device(pdev);	if (rc) {		printk(KERN_ERR "planb: cannot enable PCI device %s\n",		       pci_name(pdev));		goto err_out;	}	rc = pci_set_mwi(pdev);	if (rc) {		printk(KERN_ERR "planb: cannot enable MWI on PCI device %s\n",		       pci_name(pdev));		goto err_out_disable;	}	pci_set_master(pdev);	/* Set the new base address */	pci_write_config_dword (pdev, confreg, new_base);	planb_regs = (volatile struct planb_registers *)						ioremap (new_base, 0x400);	pb->planb_base = planb_regs;	pb->planb_base_phys = (struct planb_registers *)new_base;	pb->irq	= irq;		return planb_num;err_out_disable:	pci_disable_device(pdev);err_out:	/* FIXME handle error */   /* comment moved from pci_find_slot, above */	return 0;}static void release_planb(void){	int i;	struct planb *pb;	for (i=0;i<planb_num; i++) 	{		pb=&planbs[i];		/* stop and flash DMAs unconditionally */		planb_dbdma_stop(&pb->planb_base->ch2);		planb_dbdma_stop(&pb->planb_base->ch1);		/* clear and free interrupts */		pb->intr_mask = PLANB_CLR_IRQ;		out_le32 (&pb->planb_base->intr_stat, PLANB_CLR_IRQ);		free_irq(pb->irq, pb);		/* make sure all allocated memory are freed */		planb_prepare_close(pb);		printk(KERN_INFO "PlanB: unregistering with v4l\n");		video_unregister_device(&pb->video_dev);		/* note that iounmap() does nothing on the PPC right now */		iounmap ((void *)pb->planb_base);	}}static int __init init_planbs(void){	int i;  	if (find_planb()<=0)		return -EIO;	for (i=0; i<planb_num; i++) {		if (init_planb(&planbs[i])<0) {			printk(KERN_ERR "PlanB: error registering device %d"							" with v4l\n", i);			release_planb();			return -EIO;		} 		printk(KERN_INFO "PlanB: registered device %d with v4l\n", i);	}  	return 0;}static void __exit exit_planbs(void){	release_planb();}module_init(init_planbs);module_exit(exit_planbs);

⌨️ 快捷键说明

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