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

📄 dpram.c

📁 linux下双口RAM idt7026驱动源码
💻 C
字号:
/*******************************************************************************************
文件名	: 1MW风力发电CPU模块_双口RAM驱动程序DPRAM.c
作者 	: 王坚,刘志亮
日期	: 2008.10.25
备注	: 双口ram :IDT70261S驱动程序,处理器:at91rm9200,OS:zimagev2
********************************************************************************************/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/string.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/mach/map.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/cdev.h>

#include "DPRAM.h"

#define DEBUG 1
#define DEBUG_MSG 1
char part;	//分区号
// 在调试模式如果发生的错误,则显示错误信息并挂起程序,否则程序继续
#ifdef DEBUG
	inline void handle_error(char *s)
	{
		printk("Error:%s\n",s);
		while(1);
	}
	#define ASSERT(k,s) { (!k) ? 0 : handle_error(s);}
#else
	#define ASSERT(k,s)
#endif

//显示调试信息
#ifdef DEBUG_MSG
	#define	PDEBUG(s) printk("DEBUG:%s\n",(s))
#else
	#define	PDEBUG(s)
#endif

#define	out_w(v, a)	    (*(volatile char *)(a) = (v))
#define in_w(a)         (*(volatile int *)(a))

unsigned char get_semaphorer(unsigned char partition)
{
	unsigned int a=0,i;
	char *semaphorer = (char *)semaphorer_logic_address;
	partition*=2;//wj
	semaphorer += partition;
	out_w(0x00,semaphorer);	

	while((*semaphorer)!=0)
		{
			a++;
	//		usleep(200);
			if(a>10000)
			{
	//			printk("dpram busy\n");		
				out_w(0x01,semaphorer);
//				a = 0;
				return 1;
	//			break;
			}
	//	  for(a=0;a<5000;a++)
		}		  
		
//	}
	return 0;
#if 0
	if(a >= 5000)
	{
	 	 a = 0;
	  	return 1;
   	 }	
	else
	{
		  return 0;	
	}
#endif
}

/*
 * 释放相应分区的信号量
 */
static void put_semaphorer(unsigned char partition)
{
	char *semaphorer = (char *)semaphorer_logic_address;
	partition*=2;
	semaphorer += partition;
	out_w(0x01,semaphorer);
}

/********************************************************************************************
名称 :	ioctl
功能 :	选择双口ram分区
输入 :	inod:未使用;f:双口ram的文件描述符;arg1:分区号;arg2:未使用
输出 : 返回值0;
备注 :
**********************************************************************************************/
int dualram_ioctl(struct inode *inod,struct file *f,unsigned int arg1,unsigned char arg2)
{ 
	switch (arg1)
	{
       		case 1  :  	part = 0;
                		break;
           	case 2  :  	part = 1;
                		break;
           	case 3  :  	part = 2;
                		break;
           	case 4  :	part = 3;
				break;
           	default :  	printk("wrong part\n");
				break;
	}
 	return 0;
}

/*********************************************************************************************
名称 : dualram_read(struct file *file, char __user *buf,ssize_t count, loff_t* ppos)
功能 : 读双口ram
输入 : file:双口ram的文件描述符;buf:读缓冲区;	count:读字节数;ppos:分区偏移量
输出 : 返回值实际读字节数;
备注 :
*********************************************************************************************/
static long dualram_read(struct file *file, char __user *buf,ssize_t count, loff_t* ppos)
{	
	ssize_t num;
	unsigned long offset=*ppos;

//	printk("sem logic addr=%x\n",semaphorer_logic_address);
//	printk("mem addr=%x\n",memory_logic_address);
	if(1==get_semaphorer(part))
		{
			printk("dpram read busy,part=%x\n",part+1);	//wj
//			put_semaphorer(part);
			return 0;
		}
//	printk("read got\n");
	num=copy_to_user(buf,(unsigned char *)( partition_data_start(part)+offset),count);
	put_semaphorer(part);//wj
//	printk("read put\n");
	return num;
}

/********************************************************************************************
名称 : dualram_write(struct file *file,  char __user *buf,size_t count, loff_t *ppos)
功能 : 读双口ram
输入 : file:双口ram的文件描述符;buf:写缓冲区;	count:写字节数;ppos:分区偏移量
输出 : 返回值实际读字节数;
备注 :
**********************************************************************************************/
static  long dualram_write(struct file *file,  char __user *buf,size_t count, loff_t *ppos)
{	
	ssize_t num;
	unsigned long offset=*ppos;
	if(1==get_semaphorer(part))
		{
			printk("dpram write busy\n");	//wj
//			put_semaphorer(part);
			return 0;
		}//wj
	num=copy_from_user((unsigned char *)(partition_data_start(part)+offset), buf, count);
	put_semaphorer(part);//wj
	return num;
}

/********************************************************************************************
名称 :	dualram_open(struct inode *inode, struct file *file)
功能 :	打开双口ram时由系统调用
输入 :	
输出 :
备注 : 保留
**********************************************************************************************/
static int dualram_open(struct inode *inode, struct file *file)
{
	//PDEBUG("dualram open");
	return 0;
}

/********************************************************************************************
名称 :	dualram_release(struct inode *inode, struct file *file)
功能 :	关闭双口ram时由系统调用
输入 :	
输出 :
备注 : 保留
**********************************************************************************************/
static int dualram_release(struct inode *inode, struct file *file)
{
	PDEBUG("dualram close");
	return 0;
}
//注册驱动函数
static struct file_operations dualram_fops = 
{
	.owner	 =	THIS_MODULE,
	.open	 =	dualram_open,
	.ioctl	 =	dualram_ioctl,
	.release =	dualram_release,
	.read	 =	dualram_read,
	.write	 =	dualram_write,
};

/********************************************************************************************
名称 : dual_mem_bank_init(void)
功能 : 初始化双口ram,配置处理器寄存器
输入 :	
输出 :
备注 :
**********************************************************************************************/
static int __init dual_mem_bank_init(void)
{
	long *ncs,*ncs5,*ebi_csa,*ebi_cfgr;
    	void *config_addr = ioremap_nocache(0xfffff000, 0xfff);

	ncs  = (long *)(config_addr + 0xf80);
    	ncs5 = (long *)(config_addr + 0xf84);
    	ebi_csa = (long *)(config_addr + 0xf60);
    	ebi_cfgr = (long *)(config_addr + 0xf64);
    	*ebi_csa &= 0x0000000f;
    	*ebi_cfgr = 0x00000000;
    	*ncs = 0x00003284;
    	*ncs5 = 0x00003284;
    	return 0;
}

/********************************************************************************************
名称:	dualram_map_to_kernel(void)
功能:	将双口中RAM的地址映射到内核空间,双口RAM的物理地址分别分0x5000 0000,要映射成无缓存的
输入:	
输出:
备注:
**********************************************************************************************/
static int __init dualram_map_to_kernel(void)
{
	/* 映射双口RAM内存到内核空间 */
	memory_logic_address = (unsigned long) ioremap(DUAL_MEM_PHYS, DUAL_RAM_SIZE);
	if(!memory_logic_address)
	{
		printk(KERN_ERR"Can't remap dual ram memory");
		return -1;
	}
	/* 映射双口RAM信号量到内核空间 */
	semaphorer_logic_address = (unsigned long) ioremap_nocache(DUAL_SEMAPHORER_PHYS, DUAL_SEMAPHORER_SIZE);//物理地址为偶数,可能有问题
	if(!semaphorer_logic_address)
	{
		iounmap((void *)memory_logic_address);
		printk(KERN_ERR"Can't remap dual semaphorer memory");
		return -1;
	}
	return 0;
}

#define MAJOR_NUMBER	253

static int major_nr=MAJOR_NUMBER,minor_nr=0;//主设备号,次设备号,根据实际情况改动
const char device_name[] = "dualram";
struct cdev *dualram_cdev = NULL;
dev_t dualram_dev = 0;

/********************************************************************************************
名称:	dualram_init(void)
功能:	初始化,将双口RAM的内在映射到内核空间
输入:	
输出:
备注:加载模块时,系统调用
**********************************************************************************************/

int __init dualram_init(void)
{
	int err ;
	if((err = dual_mem_bank_init()))//硬件配置
	{
		printk(KERN_ERR"dual memory bank initial error");
		return err;
	}

	if(dualram_map_to_kernel())//将双口RAM映射到内核空间
		return -1;
  
	err = register_chrdev(major_nr,"dualram",&dualram_fops);//设备注册到内核
	if(err<0)
	{
		printk(KERN_DEBUG"register char device error\n");
		iounmap((void *)memory_logic_address);
		iounmap((void *)semaphorer_logic_address);
	}
	return 0;
}
/********************************************************************************************
名称:	dualram_cleanup(void)
功能:	释放申请的资源
输入:	
输出:
备注:卸载模块时,系统调用
**********************************************************************************************/
static void __exit dualram_cleanup(void)
{
	int err=0;
	err=unregister_chrdev(253,"dualram");
	if(err<0)
  	{
    		printk("<1>UnRegister Fail!\n");
  		return;
  	}
	iounmap((void *)memory_logic_address);
	iounmap((void *)semaphorer_logic_address);
  	PDEBUG("GOOD-bye!\n");
}

module_init(dualram_init);
module_exit(dualram_cleanup);

MODULE_AUTHOR("UESTC");
MODULE_DESCRIPTION("Dual port ram used in at91rm9200");
MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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