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

📄 saa7146_core.c

📁 linux环境下的dvb驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/*    saa7146.o - driver for generic saa7146-based hardware    Copyright (C) 1998-2003 Michael Hunold <michael@mihu.de>    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.    This program is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details.    You should have received a copy of the GNU General Public License    along with this program; if not, write to the Free Software    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/#include <media/saa7146.h>/* global variables */struct list_head saa7146_devices;struct semaphore saa7146_devices_lock;static int initialized = 0;int saa7146_num = 0;unsigned int saa7146_debug = 0;MODULE_PARM(saa7146_debug,"i");MODULE_PARM_DESC(saa7146_debug, "debug level (default: 0)");#if 0static void dump_registers(struct saa7146_dev* dev){	int i = 0;	INFO((" @ %li jiffies:\n",jiffies));	for(i = 0; i <= 0x148; i+=4) {		printk("0x%03x: 0x%08x\n",i,saa7146_read(dev,i));	}}#endif/**************************************************************************** * gpio and debi helper functions ****************************************************************************//* write "data" to the gpio-pin "pin" */void saa7146_set_gpio(struct saa7146_dev *dev, u8 pin, u8 data){	u32 value = 0;	/* sanity check */	if(pin > 3)		return;	/* read old register contents */	value = saa7146_read(dev, GPIO_CTRL );		value &= ~(0xff << (8*pin));	value |= (data << (8*pin));	saa7146_write(dev, GPIO_CTRL, value);}/* This DEBI code is based on the saa7146 Stradis driver by Nathan Laredo */int saa7146_wait_for_debi_done(struct saa7146_dev *dev){	unsigned long start;	/* wait for registers to be programmed */	start = jiffies;	while (1) {                if (saa7146_read(dev, MC2) & 2)                        break;		if (time_after(jiffies, start + HZ/20)) {			DEB_S(("timed out while waiting for registers getting programmed\n"));			return -ETIMEDOUT;		}	}	/* wait for transfer to complete */	start = jiffies;	while (1) {		if (!(saa7146_read(dev, PSR) & SPCI_DEBI_S))			break;		saa7146_read(dev, MC2);		if (time_after(jiffies, start + HZ/4)) {			DEB_S(("timed out while waiting for transfer completion\n"));			return -ETIMEDOUT;		}	}	return 0;}/**************************************************************************** * general helper functions ****************************************************************************//* this is videobuf_vmalloc_to_sg() from video-buf.c    make sure virt has been allocated with vmalloc_32(), otherwise the BUG()   may be triggered on highmem machines */static struct scatterlist* 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;}/********************************************************************************//* common page table functions */#define SAA7146_PGTABLE_SIZE 4096char *saa7146_vmalloc_build_pgtable(struct pci_dev *pci, long length, struct saa7146_pgtable *pt){	int pages = (length+PAGE_SIZE-1)/PAGE_SIZE;	char *mem = vmalloc_32(length);	int slen = 0;	if (NULL == mem) {		return NULL;	}	if (!(pt->slist = vmalloc_to_sg(mem, pages))) {		vfree(mem);		return NULL;	}	if (saa7146_pgtable_alloc(pci, pt)) {		kfree(pt->slist);		pt->slist = NULL;		vfree(mem);		return NULL;	}		slen = pci_map_sg(pci,pt->slist,pages,PCI_DMA_FROMDEVICE);	if (0 != saa7146_pgtable_build_single(pci, pt, pt->slist, slen)) {		return NULL;	}	return mem;}void saa7146_pgtable_free(struct pci_dev *pci, struct saa7146_pgtable *pt){	if (NULL == pt->cpu)		return;	pci_free_consistent(pci, pt->size, pt->cpu, pt->dma);	pt->cpu = NULL;	if (NULL != pt->slist) {		kfree(pt->slist);		pt->slist = NULL;	}}int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt){        u32          *cpu;        dma_addr_t   dma_addr;	cpu = pci_alloc_consistent(pci, SAA7146_PGTABLE_SIZE, &dma_addr);	if (NULL == cpu) {		return -ENOMEM;	}	pt->size = SAA7146_PGTABLE_SIZE;	pt->cpu  = cpu;	pt->dma  = dma_addr;	return 0;}int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt,	struct scatterlist *list, int sglen  ){	u32 *ptr, fill;	int nr_pages = 0;	int i,p;	BUG_ON( 0 == sglen);		if (list->offset > PAGE_SIZE) {		DEB_D(("offset > PAGE_SIZE. this should not happen."));		return -EINVAL;	}		/* if we have a user buffer, the first page may not be	   aligned to a page boundary. */	pt->offset = list->offset;	ptr = pt->cpu;	for (i = 0; i < sglen; i++, list++) {/*		printk("i:%d, adr:0x%08x, len:%d, offset:%d\n", i,sg_dma_address(list), sg_dma_len(list), list->offset);*/		for (p = 0; p * 4096 < list->length; p++, ptr++) {			*ptr = sg_dma_address(list) + p * 4096;			nr_pages++;		}	}	/* safety; fill the page table up with the last valid page */	fill = *(ptr-1);	for(i=nr_pages;i<1024;i++) {		*ptr++ = fill;	}/*	ptr = pt->cpu;	printk("offset: %d\n",pt->offset);	for(i=0;i<5;i++) {		printk("ptr1 %d: 0x%08x\n",i,ptr[i]);	}*/	return 0;}/********************************************************************************//* gpio functions */void saa7146_setgpio(struct saa7146_dev *dev, int port, u32 data){	u32 val = 0;        val=saa7146_read(dev,GPIO_CTRL);        val&=~(0xff << (8*(port)));        val|=(data)<<(8*(port));        saa7146_write(dev, GPIO_CTRL, val);}/********************************************************************************//* interrupt handler */static irqreturn_t interrupt_hw(int irq, void *dev_id, struct pt_regs *regs){	struct saa7146_dev *dev = (struct saa7146_dev*)dev_id;	u32 isr = 0;	/* read out the interrupt status register */	isr = saa7146_read(dev, ISR);	/* is this our interrupt? */	if ( 0 == isr ) {		/* nope, some other device */		return IRQ_NONE;	}	saa7146_write(dev, ISR, isr);	if( 0 != (dev->ext)) {		if( 0 != (dev->ext->irq_mask & isr )) {			if( 0 != dev->ext->irq_func ) {				dev->ext->irq_func(dev, &isr);			}			isr &= ~dev->ext->irq_mask;		}	}	if (0 != (isr & (MASK_27))) {		DEB_INT(("irq: RPS0 (0x%08x).\n",isr));		if( 0 != dev->vv_data && 0 != dev->vv_callback) {			dev->vv_callback(dev,isr);		}		isr &= ~MASK_27;	}	if (0 != (isr & (MASK_28))) {		if( 0 != dev->vv_data && 0 != dev->vv_callback) {			dev->vv_callback(dev,isr);		}		isr &= ~MASK_28;

⌨️ 快捷键说明

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