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

📄 uboot_flash_dev.c

📁 uclinux下 intel mx flash驱动源码!
💻 C
字号:
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/init.h>
#include <asm/uaccess.h>
#include <asm-generic/errno-base.h>
#include <linux/stddef.h>
#include <linux/delay.h>

#include "uboot_common.h"


#define FLASH_MAJOR	  206


static loff_t flash_env_dev_llseek(struct file * file, loff_t offset, int orig)
{
/*
 *  orig 0: position from begning of flash
 *  orig 1: relative from current position
 *  orig 2: position from last flash address
 */
  
  switch (orig)
  {
   case 0:
     file->f_pos = offset;
     break;
   case 1:
     file->f_pos += offset;
     break;
   case 2:
     file->f_pos = CFG_FLASH_SIZE- offset;   // FLASH SIZE  = 0x1000000 = 16M bytes
     break;
   default:
     return -EINVAL;
  }

  /* truncate position */
  if (file->f_pos < 0)
  {
    file->f_pos = 0;    
    return(-EOVERFLOW);
  }
  
  if (file->f_pos >= CFG_FLASH_SIZE)
  {
    file->f_pos = CFG_FLASH_SIZE - 1;
    return(-EOVERFLOW);
  }

  return ( file->f_pos );
}

extern void * memcpy(void * to, const void * from, size_t n);
static ssize_t flash_env_dev_read (struct file *file, char __user *buf, size_t count,
                            loff_t *offset)
{   
	unsigned long temp_size;
    unsigned long p;  
    p = file->f_pos;
    

    while(count)
    {
        temp_size = count > CFG_MAIN_SECT_SIZE ? CFG_MAIN_SECT_SIZE : count;
		memcpy(uboot_env_ptr, (void*)((unsigned long)uboot_flash_addr+p), temp_size);
    	copy_to_user(buf, uboot_env_ptr, temp_size);
    	
    	count -= temp_size;
    	p += temp_size;
        buf += temp_size;
    }
    
	return 0;
}


static ssize_t flash_env_dev_write (struct file *file, const char __user *buf, size_t count,
                             loff_t *offset)
{
    uboot_flash_info_t *info;
    unsigned long p;
    unsigned long temp_size;
    unsigned long flash_sector_offset;
    unsigned long flash_sector_offset_len;
    unsigned long sector_addr;
    unsigned long len;
    unsigned long range, flashsize;
    p = file->f_pos;
    
	info=&uboot_flash_info[0];
	flashsize = info->size;

    while(count)
    {
        if ( p<0x10000 ) //in boot flash range
        {
        	if (info->size == 0x400000)
        	{
		        flash_sector_offset = p & (CFG_BOOT_SECT_SIZE -1); //  flash secotor size = 0x2000; get the offset in one flash sector
			 sector_addr = p & (CFG_FLASH_SIZE - CFG_BOOT_SECT_SIZE);  //sector_addr =p & 0X3FE000
		        
		       // printk("sector_addr = 0x%x!\n",sector_addr);
		        
		        flash_sector_offset_len = CFG_BOOT_SECT_SIZE - flash_sector_offset;
		        
		        temp_size = count > CFG_BOOT_SECT_SIZE ? CFG_BOOT_SECT_SIZE : count;
		        
		        len = temp_size > flash_sector_offset_len ? flash_sector_offset_len : temp_size;
		        
			memcpy(uboot_env_ptr, (void*)((unsigned long)uboot_flash_addr+ sector_addr), CFG_BOOT_SECT_SIZE);	        
        	}
		else if (info->size == 0x200000)//xusha add for 2M flash
		{
			if (p<0x4000)
			{
				range = CFG_BOOT_SECT_SIZE*2;
				flash_sector_offset = p & (range -1);
				sector_addr = p & (flashsize - range);
			       flash_sector_offset_len = range - flash_sector_offset;			        
			       temp_size = count > range ? range : count; 
			       len = temp_size > flash_sector_offset_len ? flash_sector_offset_len : temp_size;
				memcpy(uboot_env_ptr, (void*)((unsigned long)uboot_flash_addr+ sector_addr), range);				
			}
			else if (p>=0x4000&&p<0x8000)
			{
				range = CFG_BOOT_SECT_SIZE;
				flash_sector_offset = p & (range -1);
				sector_addr = p & (flashsize - range);			   			        
			       flash_sector_offset_len = range - flash_sector_offset;			        
			       temp_size = count > range ? range : count; 
			       len = temp_size > flash_sector_offset_len ? flash_sector_offset_len : temp_size;  
				memcpy(uboot_env_ptr, (void*)((unsigned long)uboot_flash_addr+ sector_addr), range);			
			}
			else
			{
				range = CFG_BOOT_SECT_SIZE*4;
				flash_sector_offset = p & (range -1);
				sector_addr = p & (flashsize - range);			   			        
			       flash_sector_offset_len = range - flash_sector_offset;			        
			       temp_size = count > range ? range : count; 
			       len = temp_size > flash_sector_offset_len ? flash_sector_offset_len : temp_size;  
				memcpy(uboot_env_ptr, (void*)((unsigned long)uboot_flash_addr+ sector_addr), range);		
			}
		}
    	}
        else if ( ( p>=0x10000 ) && ( p<CFG_FLASH_SIZE ) ) //in main flash range
        {
 	        flash_sector_offset = p & (CFG_MAIN_SECT_SIZE -1); //  flash main secotor size = 0x10000; get the offset in one flash sector

	        sector_addr = p & (CFG_FLASH_SIZE - CFG_MAIN_SECT_SIZE);  //sector_addr =p & 0X3F0000
	        
	       // printk("sector_addr = 0x%x!\n",sector_addr);
	        
	        flash_sector_offset_len = CFG_MAIN_SECT_SIZE - flash_sector_offset;
	        
	        temp_size = count > CFG_MAIN_SECT_SIZE ? CFG_MAIN_SECT_SIZE : count;
	        
	        len = temp_size > flash_sector_offset_len ? flash_sector_offset_len : temp_size;  

            //printk("len = 0x%x!\n",len);	        
			memcpy(uboot_env_ptr, (void*)((unsigned long)uboot_flash_addr+ sector_addr), CFG_MAIN_SECT_SIZE);	        
        }
            	    
	copy_from_user((uboot_env_ptr+flash_sector_offset), buf, len);

	//printk("uboot_env_ptr is :%s\n", uboot_env_ptr);	    

        //printk("uboot_env_ptr+flash_sector_offset is :%s\n", uboot_env_ptr+flash_sector_offset);	    
    	
	uboot_saveenv(sector_addr);
    	count -= len;
    	p += len;
        buf += len;        
    }

   // printk("write flash done!\n");
	return 0;
}

 
static int flash_env_dev_ioctl (struct inode *inode, struct file *file, unsigned int cmd, 
                  unsigned long arg)
{
	return 0;
}   
  

static int flash_env_dev_open(struct inode *inode, struct file *file)
{
    uboot_env_ptr = (env_t *)kmalloc(CFG_MAIN_SECT_SIZE,GFP_KERNEL); 

    if (uboot_env_ptr == NULL)
    {    
       printk("writing flash but kmalloc failue,return!\n"); 
       return (-ENOMEM);
    }

    uboot_flash_init();

	//printk("start flash_env device success\n");

	return 0;
}

static int flash_env_dev_release(struct inode *inode, struct file *file)
{
    kfree(uboot_env_ptr);
	return 0;
}

static struct file_operations flash_env_dev_fops = {
	.owner		= THIS_MODULE,
	.llseek		= flash_env_dev_llseek,
	.read		= flash_env_dev_read,
	.write		= flash_env_dev_write,
	.ioctl		= flash_env_dev_ioctl,
	.open		= flash_env_dev_open,
	.release	= flash_env_dev_release,
};


static int __init flash_env_dev_init(void)
{ 
	int res;

	//printk("flash_env /dev entries driver\n");	 
 	
	res = register_chrdev(FLASH_MAJOR, "flash_env", &flash_env_dev_fops);
	if(res)
		goto flash_env_out;
	
	init_pf7_interrupt();	

	devfs_mk_dir("flash_env");
 
	return 0;   

flash_env_out_unreg_chrdev:
	unregister_chrdev(FLASH_MAJOR, "flash_env");
flash_env_out:
	printk(KERN_ERR "%s: Driver Initialisation failed", __FILE__);
	
	return res;
}
    
static void __exit flash_env_dev_exit(void)
{	
	devfs_remove("flash_env");
	unregister_chrdev(FLASH_MAJOR,"flash_env");
}

MODULE_AUTHOR("Suntek-Polytek Inc.");
MODULE_DESCRIPTION("flash_env /dev entries driver");
MODULE_LICENSE("Copyright (c) Suntek-Polytek Inc.");

module_init(flash_env_dev_init);
module_exit(flash_env_dev_exit);

⌨️ 快捷键说明

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