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 + -
显示快捷键?