mac_drv.c
来自「芯片为 arm s3c2410」· C语言 代码 · 共 373 行
C
373 行
/*****************************************************************
* 文件名 : mac_drv.c
*
* 创建人 : HuaiWei Bai
*
* 日期 :2007
* 版本号 : 1.0
*
*文件描述 :把修改网络MAC地址的数据保存到NAND FLASH 中,内核通过调用在
*启动时使用这个MAC地址,这样就保证了每个ARM板的MAC不一样。
*
*****************************************************************/
#define MODULE
#define __KERNEL__
#ifdef MODULE
#include <linux/module.h>
#include <linux/version.h>
#include <linux/devfs_fs_kernel.h>
#endif
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/poll.h>
#include <linux/ioport.h>
#include <asm/io.h>
#include <linux/delay.h>
#include <asm/s3c2410.h>
#include <asm/arch/S3C2410.h>
#include <linux/fcntl.h>
#define DRIVER_AUTHOR "白怀伟 <bhw1996@163.com>"
#define DRIVER_DESC "mac driver"
/* Module information */
MODULE_AUTHOR( DRIVER_AUTHOR );
MODULE_DESCRIPTION( DRIVER_DESC );
MODULE_LICENSE("GPL");
#define DRIVER_MAJOR 247
#define DRIVER_MINOR 2
static int major=DRIVER_MAJOR;
static int minor=DRIVER_MINOR;
char mac_drv_name[]="mac_drv";
static int mac_drv_open(struct inode *inode, struct file *file);
static int mac_drv_release(struct inode *inode, struct file *filp);
static int mac_drv_read(struct file*, char *,size_t,loff_t *);
static int mac_drv_write(struct file *,char *,int,loff_t *);
static int mac_drv_ioctl(struct inode *s_node,struct file *s_file,unsigned int cmd,unsigned int arg);
static unsigned char mac_data[6];
static struct file_operations mac_drv_fops=
{
open: mac_drv_open,
release: mac_drv_release,
read: mac_drv_read,
write: (void(*))mac_drv_write,
ioctl: (void(*))mac_drv_ioctl,
};
#ifdef CONFIG_DEVFS_FS
static devfs_handle_t devfs_io_dir, devfs_ioraw;
#endif
static int __init mac_drv_init_module(void)
{
#ifdef CONFIG_DEVFS_FS
devfs_io_dir = devfs_mk_dir(NULL, mac_drv_name, NULL);
devfs_ioraw = devfs_register(devfs_io_dir, "0", DEVFS_FL_DEFAULT,
major, minor, S_IFCHR | S_IRUSR | S_IWUSR,
&mac_drv_fops, NULL);
#else
int retv;
SET_MODULE_OWNER(&mac_drv_fops);
//未使用devfs,系统增加一个驱动程序分配一个主设备号。注册字符设备驱动程序。
retv=register_chrdev(major,mac_drv_name,&mac_drv_fops); //<linux/fs.h>
if(retv<0)
{
printk("<1>register fail!\n");
return retv;
}
//为0 表示动态分配设备号。
if(major==0)
{
major=retv;
printk("major=%d\n",major);
}
#endif
printk("<1>hello mac_drvdrv!!\n");
return 0;
}
static void __exit mac_drv_cleanup_module(void)
{
#ifdef CONFIG_DEVFS_FS
devfs_unregister(devfs_ioraw);
devfs_unregister(devfs_io_dir);
#else
int retv;
//在卸载时注销驱动程序。
retv=unregister_chrdev(major,mac_drv_name);
if(retv<0)
{
printk("<1>unreginster fail!\n");
}
#endif
printk("<1>mac_drvdrv:good_bye!\n");
}
static int mac_drv_open(struct inode *inode, struct file *file)
{
int i=0;
MOD_INC_USE_COUNT;
for(i=0;i<6;i++)
mac_data[i]=i;
return 0;
}
static int mac_drv_release(struct inode *inode, struct file *filp)
{
MOD_DEC_USE_COUNT;
return 0;
}
static void WriteCmd(u_char val) {
NFCMD = (u_char) val;
}
static void WriteAddr(u_char val) {
NFADDR = (u_char) val;
}
static u_char ReadData(void) {
return (u_char) NFDATA;
}
static void WriteData(u_char val) {
NFDATA = (u_char) val;
}
static void WaitForReady(void) {
while (!(NFSTAT & NFSTAT_RnB)) {
/* Busy */
udelay(10);
}
}
void EslfDelay( void )
{
unsigned int temp;
for (temp=0; temp<3000;temp++) ;
}
#define BLOCK 4085
static unsigned int mac_flash_addr;
void EraseBlock(void)
{
unsigned int blockPage;
mac_flash_addr=BLOCK;
blockPage=(mac_flash_addr<<5);
WriteCmd(0x60);
WriteAddr(blockPage&0xff);
WriteAddr((blockPage>>8)&0xff);
WriteAddr((blockPage>>16)&0xff);
WriteCmd(0xd0);
EslfDelay();
WaitForReady();
}
void PageWriteFlash( void )
{
int i=0;
unsigned char data_temp[512];
unsigned int blockPage;
mac_flash_addr=BLOCK;
blockPage=(mac_flash_addr<<5);
NF_nFCE_L();
//read
WaitForReady();
WriteCmd(0x00);
WriteAddr(0);
WriteAddr(blockPage&0xff);
WriteAddr((blockPage>>8)&0xff);
WriteAddr((blockPage>>16)&0xff);
EslfDelay();
WaitForReady();
for(i=0;i<512;i++)
{
data_temp[i]=ReadData();
}
WaitForReady();
//Block Erase
EraseBlock();
//write
WriteCmd(0x80);
WriteAddr(0);
WriteAddr(blockPage&0xff);
WriteAddr((blockPage>>8)&0xff);
WriteAddr((blockPage>>16)&0xff);
for(i=0;i<6;i++)
{
data_temp[i]=mac_data[i];
}
i=0;
for(i=0;i<512;i++)
{
WriteData(data_temp[i]);
}
WriteCmd(0x10);
EslfDelay();
WaitForReady();
NF_nFCE_H();
}
void ReadFlash( void )
{
int i=0;
unsigned char data_temp[512];
unsigned int blockPage;
mac_flash_addr=BLOCK;
blockPage=(mac_flash_addr<<5);
NF_nFCE_L();
WaitForReady();
WriteCmd(0x00);
WriteAddr(0);
WriteAddr(blockPage&0xff);
WriteAddr((blockPage>>8)&0xff);
WriteAddr((blockPage>>16)&0xff);
EslfDelay();
WaitForReady();
for(i=0;i<512;i++)
{
data_temp[i]=ReadData();
}
i=0;
for( i=0;i<6;i++)
{
mac_data[i]=data_temp[i];
}
NF_nFCE_H();
}
//Nand flash 以页为单位读写数据,而以块为单位擦除数据。按照这样的组织方式可以形成所谓的三类地址:
// --Block Address -- Page Address --Column Address
static int mac_drv_write(struct file *keybaord_file,char *buf,int len,loff_t *loff)
{
int retv;
unsigned int nfconf_temp;
unsigned int nfcmd_temp;
unsigned int nfaddr_temp;
unsigned int nfdata_temp;
unsigned int nfstat_temp;
unsigned int nfecc_temp;
nfconf_temp=NFCONF;
nfcmd_temp=NFCMD;
nfaddr_temp=NFADDR;
nfdata_temp=NF_RDDATA();
nfstat_temp=NFSTAT;
nfecc_temp=NFECC;
__asm__ __volatile__(
"\n\t"
);
retv=copy_from_user((char *)&mac_data,(char *)buf,(sizeof(unsigned char)*6));
if(retv<0)
{
return -1;
}
PageWriteFlash();
nfconf_temp=NFCONF;
NF_CMD(nfcmd_temp);
NF_ADDR(nfaddr_temp);
NF_WRDATA(nfdata_temp);
NFSTAT=nfstat_temp;
NFECC=nfecc_temp;
return 0;
}
static int mac_drv_read(struct file *file, char *buf,size_t count,loff_t *loff)
{
int retv;
unsigned int nfconf_temp;
unsigned int nfcmd_temp;
unsigned int nfaddr_temp;
unsigned int nfdata_temp;
unsigned int nfstat_temp;
unsigned int nfecc_temp;
nfconf_temp=NFCONF;
nfcmd_temp=NFCMD;
nfaddr_temp=NFADDR;
nfdata_temp=NF_RDDATA();
nfstat_temp=NFSTAT;
nfecc_temp=NFECC;
ReadFlash();
//WriteCmd(0x90);
//WriteAddr(0x00);
//mac_data[0]=ReadData();
//mac_data[1]=ReadData();
//EslfDelay();
//WaitForReady();
retv=copy_to_user((char *)buf,(char *)&mac_data,(sizeof(unsigned char)*6));
if(retv<0)
return -1;
nfconf_temp=NFCONF;
NF_CMD(nfcmd_temp);
NF_ADDR(nfaddr_temp);
NF_WRDATA(nfdata_temp);
NFSTAT=nfstat_temp;
NFECC=nfecc_temp;
return 0;
}
static int mac_drv_ioctl(struct inode *s_node,struct file *s_file,unsigned int cmd,unsigned int arg)
{
return 0;
}
module_init(mac_drv_init_module);
module_exit(mac_drv_cleanup_module);
//lhtMODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?