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

📄 device.c

📁 linux下 双口ram驱动程序 2.4.18
💻 C
字号:
#include <linux/types.h>#include <linux/module.h>#include <linux/init.h>#include <linux/string.h>#include <linux/kernel.h>#include <linux/ioport.h>#include <linux/mm.h>#include <linux/vmalloc.h>#include <asm/errno.h>#include <asm/signal.h>#ifdef ARM2410#include <asm/irq.h>#else#include <linux/irq.h>#include <linux/tqueue.h>#include <linux/wrapper.h>#endif#include <linux/interrupt.h>//#include <linux/kallsyms.h>#include <linux/keyboard.h>#include <asm/bitops.h>#include <asm/io.h>#include <linux/sched.h>#include <linux/fs.h>#include <linux/version.h>#include <asm/uaccess.h>#include <asm/delay.h>#include "sh_global.h"#include "sh_tools.h"#include "sh_device.h"MODULE_AUTHOR ("");MODULE_DESCRIPTION ("");MODULE_LICENSE("GPL");static int device_open(struct inode *inode,struct file *file){	printk("device %d.%d open\n",			inode->i_rdev >> 8,			inode->i_rdev & 0xff);	if(0 != device_busy)	{		return -EBUSY;	}	device_busy ++;//	MOD_INC_USE_COUNT;	return SUCCESS;}static int device_release(struct inode *inode,struct file *file){	clientdestroy();	device_busy --;//	MOD_DEC_USE_COUNT;	printk("device %d.%d close\n",			inode->i_rdev >> 8,			inode->i_rdev & 0xff);	return 	SUCCESS;}static ssize_t device_read(struct file *file,char *buff,size_t length,loff_t *offset){	int bytes_read = 0;#ifdef _DEBUG	struct timeval tv1;	struct timeval tv2;	int sec;	int usec;	do_gettimeofday(&tv1);#endif	if(length%2 == 0)	{		bytes_read = RW_TOUSER(*offset,buff,length);	}	else	{		bytes_read = RB_TOUSER(*offset,buff,length);	}#ifdef _DEBUG	do_gettimeofday(&tv2);	sec=tv2.tv_sec - tv1.tv_sec;	usec=tv2.tv_usec - tv1.tv_usec;	if(usec < 0)	{		usec += 1000000;		sec --;	}	rwtimes=sec * 1000 + usec/1000;//	printk("device_read length=%d,offset=0x%x,ret=%d\n",//			length,*((unsigned int *)offset),bytes_read);#endif	if(bytes_read >=0)	{		*offset = *offset + bytes_read;		return bytes_read;	}	return bytes_read;}static ssize_t device_write(struct file *file,const char *buff,size_t length,loff_t *offset){	int bytes_write = 0;	if(length%2 == 0)	{		bytes_write = WW_FROMUSER(*offset,(char *)buff,length);	}	else	{		bytes_write = WB_FROMUSER(*offset,(char *)buff,length);	}//	printk("device_write length=%d,offset=0x%x:%u,ret=%d\n",//			length,*((unsigned int *)offset),*((unsigned int *)offset),bytes_write);	if(bytes_write >=0)	{		*offset = *offset + bytes_write;		return bytes_write;	}	else	{		return -EPERM;	}}static int device_mmap(struct file * file, struct vm_area_struct * vma){	int ret;	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;//	printk("start %x,end %x,pgoff %x,offset %x\n",vma->vm_start,vma->vm_end,//		vma->vm_pgoff,offset);	/*	 * Accessing memory above the top the kernel knows about or	 * through a file pointer that was marked O_SYNC will be	 * done non-cached.	 *///	if (noncached_address(offset) || (file->f_flags & O_SYNC))//		vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);	/* Don't try to swap out physical pages.. */	vma->vm_flags |= VM_RESERVED;	/*	 * Don't dump addresses that are not real memory to a core file.	 */	if (offset >= __pa(high_memory) || (file->f_flags & O_SYNC))		vma->vm_flags |= VM_IO;#ifdef VER2_6	ret=remap_pfn_range(vma,			    vma->vm_start,			    vma->vm_pgoff,			    vma->vm_end-vma->vm_start,			    vma->vm_page_prot);#else	ret=remap_page_range(vma->vm_start, offset, vma->vm_end-vma->vm_start,			     vma->vm_page_prot);#endif	if(ret)		return -EAGAIN;	return 0;}static int device_ioctl(struct inode *inode, struct file *file,unsigned int cmd, unsigned long arg){	switch(cmd)	{	case ICW_INIT:		return clientinit(arg);	case ICW_REIRQENABLE:		enableirq(DISABLE_IRQ);		enableirq(devpriv.curirqenable);		return 0;	case ICW_RESETBOARD:		return resetboard(arg);	case ICW_SETINT_COMMAND_DOWN:		return 			(arg,DNINT_COMMAND_DOWN);	case ICW_SETINT_DATA_OK:		return setdspdownint(arg,DNINT_DATA_OK);		case ICW_SETINT_DOWN_RES1:		return setdspdownint(arg,DNINT_RES1);	case ICW_SETINT_DOWN_RES2:		return setdspdownint(arg,DNINT_RES2);	case ICW_CLEARINT_DATA_READ:		return cleardspupint(arg,UPINT_DATA_READ);	case ICW_APPREADFAULTEND:		cleardspupint(arg,UPINT_DATA_READ);		//下发中断		setdspdownint(arg,DNINT_DATA_OK);		return 0;//清除山川中断	//DSP板回复通知MONITOR命令返回中断位	case ICW_CLEARINT_COMMAND_RETURN:		return cleardspupint(arg,UPINT_COMMAND_RETURN);	//DSP板通知MONITOR复位结束中断位	case ICW_CLEARINT_RESET:		return cleardspupint(arg,UPINT_RESET);	//DSP板告警中断位	case ICW_CLEARINT_ERROR:		return cleardspupint(arg,UPINT_ERROR);//设置旗语	case ICW_SETDSPFLAG0:		return setdspflag(arg,DSPFLAG_0);	case ICW_SETDSPFLAG1:		return setdspflag(arg,DSPFLAG_1);	case ICW_SETDSPFLAG2:		return setdspflag(arg,DSPFLAG_2);	case ICW_SETDSPFLAG3:		return setdspflag(arg,DSPFLAG_3);	case ICW_SETDSPFLAG4:		return setdspflag(arg,DSPFLAG_4);	case ICW_SETDSPFLAG5:		return setdspflag(arg,DSPFLAG_5);	case ICW_SETDSPFLAG6:		return setdspflag(arg,DSPFLAG_6);	case ICW_SETDSPFLAG7:		return setdspflag(arg,DSPFLAG_7);//放弃旗语	case ICW_CLEARDSPFLAG0:		return cleardspflag(arg,DSPFLAG_0);	case ICW_CLEARDSPFLAG1:		return cleardspflag(arg,DSPFLAG_1);	case ICW_CLEARDSPFLAG2:		return cleardspflag(arg,DSPFLAG_2);	case ICW_CLEARDSPFLAG3:		return cleardspflag(arg,DSPFLAG_3);	case ICW_CLEARDSPFLAG4:		return cleardspflag(arg,DSPFLAG_4);	case ICW_CLEARDSPFLAG5:		return cleardspflag(arg,DSPFLAG_5);	case ICW_CLEARDSPFLAG6:		return cleardspflag(arg,DSPFLAG_6);	case ICW_CLEARDSPFLAG7:		return cleardspflag(arg,DSPFLAG_7);	//设置输出量	case ICW_SETOUT:		return setout(arg);	//清除输出量	case ICW_CLEAROUT:		return clearout(arg);	//开灯	case ICW_SETLED:		return setled(arg);	//关灯	case ICW_CLEARLED:		return clearled(arg);	//允许中断	case ICW_SETENABLEIRQ:		return setenableirq(arg);	//禁止中断	case ICW_CLEARENABLEIRQ:		return clearenableirq(arg);//设置同步信号	case ICW_SETSYN_AB_INT:		return setsyn_ab_int();	case ICW_SETSYN_QD_INT:		return setsyn_qd_int();	case ICW_SETSYN_SYN_WK1:		return setsyn_syn_wk1();	case ICW_SETSYN_SYN_WK2:		return setsyn_syn_wk2();//清除同步信号	case ICW_CLEARSYN_QD_INT:		return clearsyn_qd_int();	case ICW_CLEARSYN_AB_INT:		return clearsyn_ab_int();	case ICW_CLEARSYN_SYN_WK1:		return clearsyn_syn_wk1();	case ICW_CLEARSYN_SYN_WK2:		return clearsyn_syn_wk2();	//设定定时时间	case ICW_ADDTIMEEVENT:		{		stimeevent timeevent;		if( 0 != copy_from_user(&timeevent,(char *)arg,sizeof(stimeevent)))		{			printk("copy stimeevent struct error\n");			return -1;		}		return addtimeevent(&timeevent);		}	//清除定时时间	case ICW_DELTIMEEVENT:		return deltimeevent(arg);	//清除中断信号源	case ICW_CLEARIRQFLAG:		return clearirqflag(arg);	//给DSP板发送命令	case ICW_SENDCMD:		{		sdspcmd dspcmd;		if( 0 != copy_from_user(&dspcmd,(char *)arg,sizeof(sdspcmd)))		{			printk("copy sdspcmd struct error\n");			return -1;		}		return senddspcmdfromuser(dspcmd.boardno,dspcmd.cmd,dspcmd.cmdlen);		}	//允许硬件中断	case ICW_HWIRQENALBE:		return hwirqenable();	//禁止硬件中断	case ICW_HWIRQDISABLE:		return hwirqdisable();	case ICW_KERTIMER:		return kertimer();	//清除下发中断	case ICW_CLEARINT_DATA_OK:		return	cleardspdownint(arg,DNINT_DATA_OK);	case ICW_CLEARINT_COMMAND_DOWN:		return	cleardspdownint(arg,DNINT_COMMAND_DOWN);	case ICW_CLEARINT_RES1:		return	cleardspdownint(arg,DNINT_RES1);	case ICW_CLEARINT_RES2:		return	cleardspdownint(arg,DNINT_RES2);	//设置gps下传中断	case ICW_SETGPS_DOWN_INT:		return	setgpsdownint();	//清除gps下传中断	case ICW_CLEARGPS_DOWN_INT:		return cleargpsdownint();	//清除gps上传中断	case ICW_CLEARGPS_UP_INT:		return cleargpsupint();	case ICW_CLEARREADANDSETOK:		return clearreadandsetok(arg);	//给gps发送命令	case ICW_GPS_SENDCMD:		{		sdatastr *pdatastr;//		cleargpsdownint();		if(TRUE == getgpsdownint())		{			return -1;		}		pdatastr=(sdatastr *)arg;		if(NULL == pdatastr)		{			return -EINVAL;		}		if(pdatastr->datalen != setgpsdowndata_fromuser(pdatastr->data,pdatastr->datalen))		{			return -EINVAL;		}		return setgpsdownint();		}	//读取gps命令响应	case ICW_GPS_GETDNDATA:		{		sdatastr *pdatastr;		if(TRUE == getgpsdownint())		{			return -1;		}		pdatastr=(sdatastr *)arg;		if(NULL == pdatastr)		{			return -2;		}		if(pdatastr->datalen != getgpsdowndata_fromuser(pdatastr->data,pdatastr->datalen))		{			return -3;		}		return 0;		}	//读取gps上传区内容	case ICW_GPS_GETUPDATA:		{		sdatastr *pdatastr;		pdatastr=(sdatastr *)arg;		if(NULL == pdatastr)		{			return -EINVAL;		}		if(pdatastr->datalen != getgpsupdata_fromuser(pdatastr->data,pdatastr->datalen))		{			return -EINVAL;		}		return 0;		}//gps上传命令响应	case ICW_GPS_RESPUPDATA:		{		sdatastr *pdatastr;//		cleargpsdownint();		pdatastr=(sdatastr *)arg;		if(NULL == pdatastr)		{			return -EINVAL;		}		if(pdatastr->datalen != setgpsupdata_fromuser(pdatastr->data,pdatastr->datalen))		{			return -EINVAL;		}		return cleargpsupint();		}	//写看门狗告警单元	case ICW_DOG_WARNING:		{			unsigned char flag=arg;			if(sizeof(flag) != WB(DEVADDR_DOG_WARNING,&flag,sizeof(flag)))			{				printk("write DOG WARNING fail \n");				return -1;			}			else			{				return 0;			}		}	case ICR_MONIRQSTATE:		{		int state;		//读中断状态		state=getmonirqstate();		if(state <0 )		{			//读错误			return -1;		}		if( 0 != copy_to_user((char *)arg,&state,sizeof(state)))		{			printk("copy monirqstate error\n");			return -EINVAL;		}		return 0;		}	case ICR_GETIN:		{		unsigned char instate;		int ret;				ret=getin();		if(ret < 0)		{			return -EINVAL;		}		instate=(unsigned char)ret;		if( 0 != copy_to_user((char *)arg,&instate,sizeof(instate)))		{			printk("copy in state error\n");			return -EINVAL;		}		}		return 0;	case ICR_DEVIRQSTATE:		if( 0 == arg)		{			return -EINVAL;		}		if( 0 == getdevirqstate(&(devpriv.devirqstate)))		{			if( 0 != copy_to_user((char *)arg,&(devpriv.devirqstate),sizeof(sdevirqstate)))			{				printk("copy devirqstate error\n");				return -EINVAL;			}			return 0;		}		return -EINVAL;	case ICR_GETFAULTDATA:		{		unsigned char boardno;#ifdef _DEBUG		struct timeval tv1;		struct timeval tv2;		int sec;		int usec;		int ret;#endif		if( 0 != copy_from_user(&boardno,(char *)arg,sizeof(boardno)))		{			printk("copy from user boardno error\n");			return -1;		}#ifdef _DEBUG		do_gettimeofday(&tv1);		ret=getfaultdata(boardno,(unsigned char *)arg);		do_gettimeofday(&tv2);		sec=tv2.tv_sec - tv1.tv_sec;		usec=tv2.tv_usec - tv1.tv_usec;		if(usec < 0)		{			usec += 1000000;			sec --;		}		rwtimes=sec * 1000 + usec/1000;		return ret;#else		return getfaultdata(boardno,(unsigned char *)arg);#endif		}	case ICR_GETDNINT_DATA_OK:		return getdspdownint(arg,DNINT_DATA_OK);	//读取gps下传中断	case ICR_GETGPS_DOWN_INT:		{		unsigned char flag;		flag=(unsigned char)getgpsdownint();		if( 0 != copy_to_user((char *)arg,&flag,sizeof(flag)))		{			printk("copy gps down int flag error\n");			return -EINVAL;		}		}		return 0;		//读取gps上传中断	case ICR_GETGPS_UP_INT:		{		unsigned char flag;		flag=(unsigned char)getgpsupint();		if( 0 != copy_to_user((char *)arg,&flag,sizeof(flag)))		{			printk("copy gps up int flag error\n");			return -EINVAL;		}		}		return 0;	case ICR_RWTIMES:		if(0 == arg)		{			return -EINVAL;		}		if(0 != put_user(rwtimes,(int *)arg))		{			return -EINVAL;		}		return 0;	case ICR_TEST:		test_setdspdataok(arg);		return 0;	default:		return -EINVAL;	}}#ifdef VER2_6irqreturn_t myirq_handle(int irq,void *dev_id,struct pt_regs *regs)#elsevoid myirq_handle(int irq,void *dev_id,struct pt_regs *regs)#endif{	static stv_and_devirqstate tvdev;	static unsigned int count;	tvdev.irqtimes = ++count;	hwirqdisable();//	if(TRUE == clientisvalid())	{		do_gettimeofday(&(tvdev.tv));//		getdevirqstate(&(tvdev.devirqstate));//		printk("kern catch sig times %d\n",count);		//设备是独占中断,所以不判断		//直接发送信号到应用程序		sendsig(SIGRTMIN,&(tvdev),sizeof(stv_and_devirqstate),devpriv.pid);	}#ifdef VER2_6	return 0;#endif}static struct file_operations fops= {	.read		=device_read,	.write		=device_write,	.ioctl		=device_ioctl,	.open		=device_open,	.release	=device_release,	.mmap		=device_mmap,};#ifdef VER2_6#define check_region check_mem_region#define request_region	request_mem_region#define release_region release_mem_region#endifstatic int __init shdev_init_module(void){	int ret;	printk("init\n");	if(0 == check_region(IOPORT_START,IOPORT_NUM))	{		request_region(IOPORT_START,IOPORT_NUM,DEVICE_NAME);		printk("request ipport from 0x%x num %d good\n",IOPORT_START,IOPORT_NUM);	}	else	{		printk("ipport from 0x%x num %d busy\n",IOPORT_START,IOPORT_NUM);		return -1;	}	ret = register_chrdev(DEVICE_MARJOR,DEVICE_NAME,&fops);	if(ret == 0)	{	}	else	{		release_region(IOPORT_START,IOPORT_NUM);		printk("register chr dev fail %d\n",ret);		return -1;	}	return 0;}static void __exit shdev_cleanup_module(void){	int ret;	printk("clearup\n");	//防止客户应用死机	clientdestroy();	release_region(IOPORT_START,IOPORT_NUM);	ret=unregister_chrdev(DEVICE_MARJOR,DEVICE_NAME);	if(ret<0)	{		printk("unregister char dev error %d\n",ret);	}}module_init(shdev_init_module);module_exit(shdev_cleanup_module);/*//中断下半部处理程序void myirq_bhhandle(void){	static int count=0;	printk("bh count %d\n",++count);//	sendsig(SIGRTMIN);int ret;	struct timespec t;	unsigned long expire;	t.tv_nsec=0;	t.tv_sec = 5;	expire = timespec_to_jiffies(&t) + (t.tv_sec || t.tv_nsec);	ret=interruptible_sleep_on_timeout(&sh_wait, expire);	if(ret == 0)	{		//timeout		printk("irq bh timeout \n");	}	else	{		printk("irq bh wait end \n");	}}*/	/*读端口*//*	sig=testirq();	if(sig > 0)	{		//关中段		enableirq(DISABLE_IRQ);		printk("irq %d catach times %d sendsig %d\n",irq,++count,sig);		sendsig(sig);	}*/	/*给应用程序发送信号usr1*///	if(pid>0 && sendsig==1)/*	if(1 == clientisvalid())	{		queue_task(&task, &tq_immediate);		mark_bh(IMMEDIATE_BH);	}*//*	//读中断状态	state=getmonirqstate();	if(state <0 )	{		//读错误		return;	}	//有中断	if(TRUE == havmonirqstate(IRQSTATE_ALL,state))	{		//处理中断		//irqevent();		if( 0 == getdevirqstate(&(devpriv.devirqstate)))		{			sendsig(SIGRTMIN,&(devpriv.devirqstate),sizeof(sdevirqstate));		}	}*/

⌨️ 快捷键说明

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