📄 dpram.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 + -