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

📄 linuxdsp.c

📁 采用TMS320C6205的PCI设备驱动程序源代码 for Linux
💻 C
字号:
#ifndef __KERNEL__#  define __KERNEL__#endif#ifndef MODULE#  define MODULE#endif#include <asm/io.h>#include <asm/uaccess.h>#include <linux/init.h>#include <linux/module.h>#include <linux/fs.h>#include <linux/sched.h>#include <linux/errno.h>#include <linux/pci.h>//#include <linux/malloc.h>#include <linux/ioport.h>#include <linux/timer.h>#include <linux/proc_fs.h>#include <linux/interrupt.h>#include <linux/tqueue.h>#include "sysdep.h"#define	DSPIRQ#define	LINUX_VERSION		0x2020C#define LINUX_MAGIC			'Q'#define	PCI_VENDOR 			0x104c#define	PCI_DEVICE 			0xa106#define	DSP6205_MAJOR  		80#define	MY_MAJOR			0#define	IO_SPACE_SIZE 		0x10#define	MEM_SPACE_SIZE 		0x400000#define	MAX_DMA_LENGTH 		0x8000#define	DMA_BUF_ORDER 		1#define	DMA_BUF_SIZE 		(PAGE_SIZE<<DMA_BUF_ORDER)#define	SEND_DMA_SIZE  		0x2000#define	READ_DMA_SIZE  		0x2000#define	DSP_MEM_OFFSET		0x0#define	DSP_OPERA_OFFST		0x8000#define	DSP_DATA_OFFST		0x8004#define	DSPMA_REG_OFFST		0x240010#define	PCIMA_REG_OFFST		0x240014#define	DMA_REG_OFFSET 		0x240018#define	DSP_ADDRESS			0x80008004#define	DSP_IRQ_MASK  		0xfffffffb#define	DSP_RESET_FLAG  	0x1#define	SUCESS_FLAG  		0xa5a5a5a5#define	DSP_FLAG  			0x5a5a5a5a#define	HOST_FLAG  			0xaaaa5555#define	HSR				  	0x0#define	HDCR			  	0x4#define	DSPP			  	0x8#define	FLASH_ADR_SLECT	  	0x5
#define	DMA_ADR_SLECT	  	0x6#define	DSP_ADR_SLECT	  	0x200#define	DMA_READ		  	0x1#define	DMA_WRITE		  	0x2#define	DSP_RESET			0x1struct	DBIO{		//dma,irq数据块	char *wbuf;	char *rbuf;	int	 off;	int	 count;};
struct  RWFLASH{
	char buf;
	int	 off;
	int	 flag;
};
//Ioctl指令:start#define LINUX_DSPRESET	_IOW(LINUX_MAGIC,1,0)#define LINUX_DMARANDW	_IOWR(LINUX_MAGIC,2,sizeof(struct DBIO))#define LINUX_QUERYRAW	_IOWR(LINUX_MAGIC,3,sizeof(struct DBIO))#define LINUX_INTQRYRAW	_IOWR(LINUX_MAGIC,4,sizeof(struct DBIO))#define LINUX_INTDMARAW	_IOWR(LINUX_MAGIC,5,sizeof(struct DBIO))#define LINUX_FLASHRAW	_IOWR(LINUX_MAGIC,6,sizeof(struct DBIO))#define LINUX_UNLOCKROM	_IOR(LINUX_MAGIC,7,0)#define LINUX_LOCKROM	_IOR(LINUX_MAGIC,8,0)//Ioctl指令:endenum pci_chipsets{	DSP6205 = 0,};//static 	struct pci_device_id Dsp6205_pci_tbl[] __devinitdata ={//			{PCI_VENDOR,PCI_DEVICE,PCI_ANY_ID,PCI_ANY_ID,0,0,DSP6205},//			{0,}};//MODULE_DEVICE_TABLE(pci, Dsp6205_pci_tbl);struct TDspDev{	int 			bPresent;		//准备好	volatile int 	bUsed;			//使用与否	enum {		IDLE,WAITING,TIME_OUT,		DSP_DONE,DMA_WAITING,		DMA_DONE	} status;	unsigned int 	IoMem;			//IO寄存器地址	unsigned int	PhyMem;			//DSP物理地址	unsigned int 	virtualMem;		//DSP虚拟地址	unsigned int  	Dma_buf;		//DMA缓冲区	int 			Irq;        	//中断	char 			*rbuffer;		//接收缓冲区	int 			rsize;			//接收数量	int 			finish;			//完成情况	};static struct TDspDev *dev6205;struct pci_dev		*dev = NULL;struct timer_list	wait_timer;unsigned int 	IO,PHY;unsigned int 	MEM;unsigned int  	Irq;unsigned long	Dma_Buf;struct wait_queue *wait;//wait_queue_head_t wait;struct semaphore  dsp6205_sem;static void DMA_Transfer(unsigned int count,int bRead);static void Reset(void);static int Dsp6205_open(struct inode *inode,struct file *file);static int Dsp6205_release(struct inode * inode, struct file * filp);static int Dsp6205_read(struct file *filp, char *buf,size_t count, loff_t *ppos);static int Dsp6205_write(struct file *filp, const char *buf,size_t count, loff_t *ppos);static int Dsp6205_ioctl(struct inode *inode, struct file *filp,unsigned int cmd, unsigned long arg);static int Dma_readwrite(unsigned long timeout,unsigned long arg);static int Irq_readwrite(unsigned long timeout,unsigned long arg);static int DMA_Send(const char *buf,int offset,int size);
static int DMA_receive(char *buf,int offset,int size);static int receive(char *buf,int offset,int size);
static int send(char *buf,int offset,int size);
static int Flash_readwrite(unsigned long arg);
static int Detect_Dsp6205();static int wait_flags(void);static int wait_flags(void){	unsigned int	data;	outl(DSP_ADR_SLECT,IO+DSPP);	data=readl(MEM+DSP_OPERA_OFFST);	while(data!=0x5a5a5a5a){		data=readl(MEM+DSP_OPERA_OFFST);	}	return 0;}static void Int_handler(int irq,void * dev_id,struct pt_regs * regs){//	struct TDspDev 	*tDev;	unsigned int	data;//	tDev=(struct TDspDev *) dev_id;	outl(DSP_ADR_SLECT,IO+DSPP);	data=readl(MEM+DSP_OPERA_OFFST);	if(!(data&DSP_FLAG))	{//		printk("Not DSP's IRQ  occured!\n");		return;	}	writel(HOST_FLAG,MEM+DSP_OPERA_OFFST);//	printk("write Flag!\n");	wake_up_interruptible(&wait); //唤醒读进程	//	printk("DSP's IRQ received!\n");	return ;}static void Reset(void){	unsigned long flag;//	printk("Dsp6205_Reset\n");	flag=inl(IO+DSPP);	flag|=DSP_RESET;	outl(flag,IO+HDCR);//	printk("Dsp6205 Reset Sucess!\n");}static void DMA_Transfer(unsigned int count,int bRead){	unsigned int 	size;	unsigned int 	data;		printk("DMA_Transfer open\n");	outl(DMA_ADR_SLECT,IO+DSPP);
//	printk("count = %d\n",count);//	writel(DSP_ADDRESS,MEM+DSPMA_REG_OFFST);//	printk("MEM+DSP_DATA_OFFST = 0x%x\n",MEM+DSP_DATA_OFFST);	//	writel(virt_to_bus((void*)Dma_Buf),MEM+PCIMA_REG_OFFST);		if(!bRead)		size=(count<<16)|DMA_WRITE;	else		size=(count<<16)|DMA_READ;	printk("DMA_Transfer 1\n");	writel(size,MEM+DMA_REG_OFFSET);		data = readl(MEM+DMA_REG_OFFSET);//	printk("data =0x%x\n",data);	while((data&0x3)!=0){		data = readl(MEM+DMA_REG_OFFSET);		printk("data =0x%x\n",data);	}//	printk("DMA_Transfer 2\n");	if(!bRead){		outl(DSP_ADR_SLECT,IO+DSPP);		writel(SUCESS_FLAG,MEM+DSP_OPERA_OFFST);		printk("Write Dma flag!\n");	}	printk("DMA_Transfer finished!\n");}static int DMA_receive(char *buf,int offset,int size){//	printk("Dsp6205 DMA_receive Open\n");	DMA_Transfer(size,1);//	printk("Dsp6205 DMA_receive 1\n");	memcpy(buf,(void*)Dma_Buf,size);//	printk("Dsp6205 DMA_receive finished!\n");	return 0;}static int  DMA_Send(const char *buf,int offset,int size){//	printk("Dsp6205 DMA_Send open!\n");	memcpy((void*)Dma_Buf,buf,size);//	printk("Dsp6205 DMA_Send 1\n");	DMA_Transfer(size,0);//	printk("Dsp6205 DMA_Send finished!\n");	return 0;}static int send(char *buf,int offset,int size){//	printk("Dsp6205_send Happen0!\n");	outl(DSP_ADR_SLECT,IO+DSPP);//	printk("Dsp6205_send Happen1!\n");	memcpy((void*)MEM+DSP_DATA_OFFST,(void*)buf,size);//	wmb();//	printk("Dsp6205_send Happen2!\n");	writel(SUCESS_FLAG,MEM+DSP_OPERA_OFFST);//	printk("Dsp6205_send finished!\n");	return 0;}static int receive(char *buf,int offset,int size){//	printk("Dsp6205_receive Happen0!\n");	outl(DSP_ADR_SLECT,IO+DSPP);	memcpy(buf,(char *)MEM+DSP_DATA_OFFST,size);//	printk("Dsp6205_receive Sucess!\n");	return size;}static int Dma_readwrite(unsigned long timeout,unsigned long arg){	struct DBIO buf,*pbuf=&buf;	unsigned long time;	down(&dsp6205_sem);	//	printk("DSP6205 DMA READ WRITE!\n");	copy_from_user(pbuf,(char*)arg,sizeof(struct DBIO));	DMA_Send(pbuf->wbuf,0,pbuf->count);				time=interruptible_sleep_on_timeout(&wait,timeout);	if(!time){		up(&dsp6205_sem);		return 1;	}//	printk("DSP6205 interrupt Pass! \n");	DMA_receive(pbuf->rbuf,0,pbuf->count);//	printk("DSP6205 DMA Read finished!\n");	copy_to_user((char*)arg,pbuf,sizeof(struct DBIO));	//	printk("DSP6205 DMA Read Sucess!\n");	up(&dsp6205_sem);	return 0;}static int Irq_readwrite(unsigned long timeout,unsigned long arg){	struct DBIO buf,*pbuf=&buf;	unsigned long time;	down(&dsp6205_sem);	//	printk("DSP6205 Query READ WRITE!\n");	copy_from_user(pbuf,(char*)arg,sizeof(struct DBIO));//	printk("DSP6205 Query WRITE Sucess!\n");	send(pbuf->wbuf,0,pbuf->count);//	printk("DSP6205 Query Write 1! \n");	time=interruptible_sleep_on_timeout(&wait,timeout);	if(!time){		up(&dsp6205_sem);		return 1;	}//	printk("DSP6205 interrupt Pass! \n");				receive(pbuf->rbuf,0,pbuf->count);//	printk("DSP6205 Query Read finished!\n");	copy_to_user((char*)arg,pbuf,sizeof(struct DBIO));//	printk("DSP6205 Query Read Sucess!\n");	up(&dsp6205_sem);	return 0;}static int Flash_readwrite(unsigned long arg){	struct RWFLASH buf,*pbuf=&buf;	int	   flag;		int	   offset;		copy_from_user(pbuf,(char*)arg,sizeof(struct RWFLASH));//	printk("DSP6205 Flash Read Write start!\n");	flag = pbuf->flag;	offset = pbuf->off;	if(offset>0x20000) return 1;	outl(FLASH_ADR_SLECT,IO+DSPP);//	printk("buf is %d!\n",pbuf->buf);		if(flag) //write
		writeb(pbuf->buf,MEM+pbuf->off);	else		pbuf->buf = readb(MEM+pbuf->off);//	printk("data is %d!\n",pbuf->buf);	copy_to_user((char*)arg,pbuf,sizeof(struct RWFLASH));//	printk("DSP6205 Flash Read Write Sucess!\n");		return 0;}static struct file_operations Dsp6205_fops = {//	owner:		THIS_MODULE,	read:		Dsp6205_read,	write:		Dsp6205_write,	ioctl:		Dsp6205_ioctl,	open:		Dsp6205_open,	release:	Dsp6205_release,};static int Dsp6205_ioctl(struct inode *inode, struct file *filp,unsigned int cmd, unsigned long arg){	struct DBIO buf,*pbuf=&buf;
	unsigned long	data;	switch(cmd){		case LINUX_DSPRESET://			printk("DSP6205 Reset!\n");//			if (! capable (CAP_SYS_ADMIN))//            	return -EPERM;			Reset();			break;		case LINUX_DMARANDW://			if (! capable (CAP_SYS_ADMIN)) //           	return -EPERM;//			printk("DSP6205 DMA READ WRITE!\n");			copy_from_user(pbuf,(char*)arg,sizeof(struct DBIO));			DMA_Send(pbuf->wbuf,0,pbuf->count);			wait_flags();			DMA_receive(pbuf->rbuf,0,pbuf->count);			copy_to_user((char*)arg,pbuf,sizeof(struct DBIO));				break;		case LINUX_QUERYRAW://			if (! capable (CAP_SYS_ADMIN))//            	return -EPERM;//			printk("DSP6205 Query READ WRITE!\n");			copy_from_user(pbuf,(char*)arg,sizeof(struct DBIO));//			printk("DSP6205 Query WRITE Sucess!\n");			send(pbuf->wbuf,0,pbuf->count);//			printk("DSP6205 Query READ 1! \n");			wait_flags();			receive(pbuf->rbuf,0,pbuf->count);//			printk("DSP6205 Read finished!\n");			copy_to_user((char*)arg,pbuf,sizeof(struct DBIO));//			printk("DSP6205 Query READ Sucess!\n");			break;		case LINUX_INTQRYRAW://			if (! capable (CAP_SYS_ADMIN))//            	return -EPERM;			if(Irq_readwrite(2000,arg))            	return -ETIMEDOUT;			break;		case LINUX_INTDMARAW://			if (! capable (CAP_SYS_ADMIN))//	          	return -EPERM;			if(Dma_readwrite(2000,arg))            	return -ETIMEDOUT;			break;		case LINUX_FLASHRAW://			printk("DSP6205 Flash READ WRITE!\n");			if(Flash_readwrite(arg))				return -EOVERFLOW;			break;		case LINUX_UNLOCKROM:			outl(FLASH_ADR_SLECT,IO+DSPP);			printk("DSP6205 UNLOCK ROM!\n");			data = readl(MEM+0x608c);			data = readl(MEM+0x6080);			data = readl(MEM+0x6088);			data = readl(MEM+0x1060);			data = readl(MEM+0x106c);			data = readl(MEM+0x1064);			data = readl(MEM+0x1068);			printk("DSP6205 UNLOCK ROM! SUCESS!\n");			break;		case LINUX_LOCKROM:			outl(FLASH_ADR_SLECT,IO+DSPP);			printk("DSP6205 LOCK ROM!\n");			data = readl(MEM+0x608c);			data = readl(MEM+0x6080);			data = readl(MEM+0x6088);			data = readl(MEM+0x1060);			data = readl(MEM+0x106c);			data = readl(MEM+0x1064);			data = readl(MEM+0x1028);			printk("DSP6205 LOCK ROM! SUCESS!\n");			break;		default:			break;	}	return 0;}static int Dsp6205_open(struct inode *inode, struct file *file){//	unsigned int 	data;//	printk("Dsp6205_open0\n");	MOD_INC_USE_COUNT;//	printk("Dsp6205_open\n");	return 0;}static int Detect_Dsp6205(){	unsigned int 	data;	pci_read_config_dword(dev,0x10,&data);	data&=PCI_BASE_ADDRESS_MEM_MASK;	PHY=data;//	printk("PHY %x!\n",PHY);	pci_read_config_dword(dev,0x18,&data);	data&=PCI_BASE_ADDRESS_IO_MASK;	IO=data;//	printk("IO %x!\n",IO);	pci_read_config_dword(dev,0x3c,&data);	data&=0xff;	Irq=data;//	printk("Irq %x!\n",Irq);	if(check_region(IO,IO_SPACE_SIZE)<0)   {//		printk("Driver has been loaded,can't request IO!\n");		return 1;	}//	printk("check io region sucess!\n");	request_region(IO,IO_SPACE_SIZE,"DSPDev");//	printk("request io region sucess!\n");	if(!(MEM=(unsigned long) ioremap_nocache(PHY,MEM_SPACE_SIZE))){//		printk("Can't map the physical memory!\n");		goto err;	}//	printk("ioremap mem sucess!\n");//	printk("MEM sucess 0x%x\n",MEM);	if(request_irq(Irq,Int_handler,SA_SHIRQ,"DSPDev",&dev6205)<0){//		printk("Can't request IRQ!\n");		goto err1;	}//	printk("request irq  sucess!\n");	data=inl(IO+HSR)&0xfffffffbL;	outl(data,IO+HSR);	if(register_chrdev(DSP6205_MAJOR,"DSPDev",&Dsp6205_fops)<0) {//		printk("Can't register DSP device driver!\n");		return -ENODEV;	}	Dma_Buf=__get_free_pages(GFP_DMA,DMA_BUF_ORDER);	printk("Dma buf sucess!\n");	if(!Dma_Buf) {		printk("Can't alloc DMA buffer!\n");		goto err2;	}	printk("Dma buf sucess!\n");	outl(DMA_ADR_SLECT,IO+DSPP);//	printk("write  sucess0!\n");	writel(DSP_ADDRESS,MEM+DSPMA_REG_OFFST);//	printk("MEM+DSP_DATA_OFFST = 0x%x\n",MEM+DSP_DATA_OFFST);//	data=readl(MEM+DSPMA_REG_OFFST);//	printk("write  sucess1! data=0x%x\n",data);	writel(virt_to_bus((void*)Dma_Buf),MEM+PCIMA_REG_OFFST);//	printk("Dma_Buf = 0x%x\n",Dma_Buf);	init_waitqueue(&wait);	//	init_waitqueue_head (&wait);//	printk("init_waitqueue_head sucess!\n");	sema_init(&dsp6205_sem, 1);//	printk("sema_init sucess!\n");	return 0;	err2:		free_irq(Irq,&dev6205);//		printk("fail 0!\n");	err1:		iounmap((void*)MEM);//		printk("fail 1!\n");	err://		release_mem_region(PHY,MEM_SPACE_SIZE);		release_region(IO,IO_SPACE_SIZE);//		printk("fail 2!\n");	return 1;}static int Dsp6205_release(struct inode * inode, struct file * filp){//	printk("Dsp6205_release0\n");	MOD_DEC_USE_COUNT;//	printk("Dsp6205_release\n");	return 0;}static int Dsp6205_read(struct file *filp, char *buf,size_t count, loff_t *ppos){//	printk("Dsp6205_read0\ncount = %d\n",count);	outl(DSP_ADR_SLECT,IO+DSPP);	copy_to_user((char*)buf,(char*)MEM+DSP_DATA_OFFST,count);//问题//	memcpy((char*)buf,(char*)MEM+DSP_DATA_OFFST,count);//	printk("Dsp6205_read1\ncount = %d\n",count);	return count;}static int Dsp6205_write(struct file *filp, const char *buf,size_t count, loff_t *ppos){	int	len;//	printk("Dsp6205_write0\n");	outl(DSP_ADR_SLECT,IO+DSPP);	len = strlen(buf);//	printk("len = %d\n",len);	copy_from_user((void*)MEM+DSP_DATA_OFFST,(void*)buf,len);	writel(SUCESS_FLAG,MEM+DSP_OPERA_OFFST);//	printk("Dsp6205_write1\n");	return count;}int init_module(void)//static int  __init	Dsp6205_init_module(void){ 	memset(&dev6205,0,sizeof(struct TDspDev));	if (!pci_present()){	       	printk("No PCI bios present\n");		return -ENODEV;	}	dev=pci_find_device(PCI_VENDOR,PCI_DEVICE,dev);	if (!dev) {	        printk("No find PCI device\n");		return -ENODEV;	}	Detect_Dsp6205();	printk("Sucess! DSP6205\n");	return 0;}void cleanup_module(void) //static void __exit	Dsp6205_cleanup_module(void){//	printk("Dsp6205 cleanup module\n");	unregister_chrdev(DSP6205_MAJOR,"DSPDev");	free_irq(Irq,&dev6205);//	release_mem_region(PHY,MEM_SPACE_SIZE);	release_region(IO,IO_SPACE_SIZE);	iounmap((void *) MEM);   	free_pages(Dma_Buf,DMA_BUF_ORDER);	printk("Goodbye DSP6205\n");}//module_init(Dsp6205_init_module);//module_exit(Dsp6205_cleanup_module);

⌨️ 快捷键说明

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