?? 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 + -