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

📄 flash.c

📁 如何制作JFFS文件系统
💻 C
📖 第 1 页 / 共 3 页
字号:
/* $Id: flash.c,v 1.2 2000/10/06 08:36:02 davidm Exp $ * * Flash-memory char or block device * * Copyright (c) 1998, 1999, 2000 Axis Communications AB * * Authors:  Bjorn Wesen (bjornw@axis.com) * * This driver implements a read/write /erase interface to the flash chips. * It probes for chips, and tries to read a bootblock with partition info from * the bootblock on the first chip. This bootblock is given the device name * /dev/flash0, and the rest of the partitions are given flash1 and upwards. * If no bootblock is found, the entire first chip (including bootblock) is * set as /dev/flash1. * * TODO: *   implement Unlock Bypass programming, to double the write speed *   fix various loops for partitions than span more than one chip *   take advantage of newer chips with 2 kword sector erase sizes * * $Log: flash.c,v $ * Revision 1.2  2000/10/06 08:36:02  davidm * * Changes to get the flash driver used by jffs working with the toshiba * flash in a NETtel with 4Mb. * * This code based on elinux_20000801.tgz. * * Revision 1.52  2000/07/31 18:32:15  finn * flash_ioctl: Made FLASHIO_ERASEALL work better. * * Revision 1.51  2000/07/25 08:38:13  finn * Uncommented CONFIG_USE_FLASH_PARTITION_TABLE. Some cleanup. * * Revision 1.50  2000/07/25 00:24:37  danielj * Fixed so that a partition that start after the end of chip 0 starts in * chip 1. * * Revision 1.49  2000/07/18 12:21:51  finn * Whitespace police. * * Revision 1.48  2000/07/14 16:26:42  johana * Flash partitiontable in flash seem to works but is not enabled. * Local CONFIG_USE_FLASH_PARTITION_TABLE can be defined to enabe it. * Maybe we should have a better magic (not 0xbeef) and a better checksum? * *//* define to make kernel bigger, but with verbose Flash messages *///#define LISAHACK/* if IRQ_LOCKS is enabled, interrupts are disabled while doing things * with the flash that cant have other accesses to the flash at the same * time. this is normally not needed since we have a wait_queue lock on the * flash chip as a mutex. */#include <linux/config.h>#include <linux/major.h>#include <linux/malloc.h>//#define IRQ_LOCKS#define FLASH_VERBOSE#define FLASH_16BIT/* This should perhaps be in kernal config: ? *//* Define it locally to test it - maybe we need a better checksum? * (it must work both with and without aptable defined and with a * trashed flash) */#define CONFIG_USE_FLASH_PARTITION_TABLE/* ROM and flash devices have major 31 (Documentation/devices.txt) * However, KROM is using that major now, so we use an experimental major = 60. * When this driver works, it will support read-only memory as well and we can * remove KROM. * Our minors start at: 16 = /dev/flash0       First flash memory card (rw) *//*#define MAJOR_NR 31 */#define MAJOR_NR 60#define ROM_MINOR   8   /* ro ROM card */#define FLASH_MINOR 16  /* rw Flash card *//* Don't touch the MAX_CHIPS until the hardcoded chip0 and chip1 are   removed from the code.  */#ifdef CONFIG_COLDFIRE#define MAX_CHIPS 1#else#define MAX_CHIPS 2#endif#define MAX_PARTITIONS 8#define DEF_FLASH2_SIZE 0x0d0000   /* 5 sectors for JFFS partition per default,Now we don't define it*//* all this stuff needs to go in blk.h */#define DEVICE_NAME "Flash/ROM device"#ifdef CONFIG_BLK_DEV_FLASH#define FLASH_SECTSIZE 512 /* arbitrary, but Linux assumes 512 often it seems */#define DEVICE_REQUEST do_flash_request#define DEVICE_NR(device) (MINOR(device))#define DEVICE_ON(device)#define DEVICE_OFF(device)#include <linux/blk.h>/* the device and block sizes for each minor */static int flash_sizes[32];static int flash_blk_sizes[32];#endif#include <asm/system.h>#ifdef CONFIG_SVINTO#include <asm/svinto.h>#endif#include <linux/flash.h>#ifndef MEM_NON_CACHEABLE#define MEM_NON_CACHEABLE 0#endif#ifndef MEM_DRAM_START#define MEM_DRAM_START 0#endif//#define DEBUG#ifdef DEBUG#define FDEBUG(x) x#else#define FDEBUG(x)#endif#if defined(__CRIS__) && !defined(DEBUG)/* breaks badly if we use printk before we flash an image... */extern void console_print_etrax(const char *b, ...);#define safe_printk console_print_etrax#else#define safe_printk printk#endifint flash_write(unsigned char *ptr, const unsigned char *source, unsigned int size);void flash_init_erase(unsigned char *ptr, unsigned int size);static struct flashchip *getchip(unsigned char *ptr);static void flash_init_partitions(void);#ifdef FLASH_16BIT/* 16-bit wide Flash-ROM */enum {  unlockAddress1          = 0x5555,        unlockData1             = 0xAAAA,        unlockAddress2          = 0x2AAA,        unlockData2             = 0x5555,        manufacturerUnlockData  = 0x9090,        manufacturerAddress     = 0x00,        deviceIdAddress         = 0x01,        programUnlockData       = 0xA0A0,        resetData               = 0xF0F0,        sectorEraseUnlockData   = 0x8080,        sectorEraseUnlockData2  = 0x3030 };typedef unsigned volatile short *flashptr;#else/* 32-bit wide Flash-ROM * Since we have two devices in parallell, we need to duplicate * the special _data_ below so it reaches both chips. */enum {  unlockAddress1          = 0x555,        unlockData1             = 0x00AA00AA,        unlockAddress2          = 0x2AA,        unlockData2             = 0x00550055,        manufacturerUnlockData  = 0x00900090,        manufacturerAddress     = 0x00,        deviceIdAddress         = 0x01,        programUnlockData       = 0x00A000A0,        resetData               = 0x00F000F0,        sectorEraseUnlockData   = 0x00800080,        sectorEraseUnlockData2  = 0x00300030 };typedef volatile unsigned long *flashptr;#endifenum {  ManufacturerAMD   = 0x01,	AM29F800BB        = 0x2258,	AM29F800BT        = 0x22D6,	AM29LV800BB       = 0x225B,	AM29LV800BT       = 0x22DA,	AM29LV160BT       = 0x22C4};enum {  ManufacturerToshiba = 0x0098,	TC58FVT160          = 0x00c2,	TC58FVB160          = 0x0043};enum {	/* ST - www.st.com */	ManufacturerST    = 0x0020,	M29W800T          = 0x00D7 /* Used in 5600, similar to AM29LV800,				    * but no unlock bypass */};enum {	/* SST*/	ManufacturerSST   = 0x00BF,	SST39LF800        = 0x2781,	SST39VF160        = 0x2782};enum {	D5_MASK           = 0x2020,	D6_MASK           = 0x4040,	D8_MASK           = 0x8080};enum {  maxNumberOfBootSectors = 8 };/* internal structure for keeping track of flash devices */struct flashchip {	unsigned char *start;	unsigned char *bootsector;	unsigned int bootsectorsize[maxNumberOfBootSectors];	unsigned short manufacturer_id;	unsigned short device_id;	unsigned short isValid;	int size, sectorsize;	/* to block accesses during erase and writing etc */	int busy;	struct wait_queue *wqueue;};/* and partitions */struct flashpartition {	struct flashchip *chip;   /* the chip we reside in */	unsigned char *start;     /* starting flash mem address */	int size;                 /* size of partition in bytes */	unsigned int flags;       /* protection bits etc */	__u16 type;               /* type of partition */};static struct flashchip chips[MAX_CHIPS];static struct flashpartition partitions[MAX_PARTITIONS];/* check if flash is busy */static inline intflash_is_busy(flashptr ptr){	/* this should probably be protected! */	return ((*ptr & D8_MASK) != (0xffffffff & D8_MASK));}static inline intflash_pos_is_clean(unsigned char *ptr){	ptr = (unsigned char *)((unsigned long)ptr | MEM_NON_CACHEABLE);	return (*((__u32 *)ptr) == 0xffffffff);}/* Open the device. We don't need to do anything really.  */static intflash_open(struct inode *inode, struct file *filp){#ifdef CONFIG_CHR_DEV_FLASH	int minor = MINOR(inode->i_rdev);	struct flashpartition *part;	if(minor < FLASH_MINOR)		return -ENODEV;	part = &partitions[minor - FLASH_MINOR];	if(!part->start)		return -ENODEV;	filp->private_data = (void *)part;  /* remember for the future */#endif	return 0; /* everything went ok */}static voidflash_release(struct inode *inode, struct file *filp){#ifdef CONFIG_BLK_DEV_FLASH	sync_dev(inode->i_rdev);#endif	return;}#ifdef CONFIG_BLK_DEV_FLASHstatic voiddo_flash_request(){	while(1) {		int minor, fsize, opsize;		struct flashchip *chip;		struct flashpartition *part;		unsigned char *fptr;		unsigned long flags;		INIT_REQUEST;		minor = DEVICE_NR(CURRENT_DEV);		minor -= FLASH_MINOR;		/* for now, just handle requests to the flash minors */		if(minor < 0 || minor >= MAX_PARTITIONS ||		   !partitions[minor].start) {			printk(KERN_WARNING "flash: bad minor %d.", minor);			end_request(0);			continue;		}		part = partitions + minor;		/* get the actual memory address of the sectors requested */		fptr = part->start + CURRENT->sector * FLASH_SECTSIZE;		fsize = CURRENT->current_nr_sectors * FLASH_SECTSIZE;		/* check so it's not totally out of bounds */		if(fptr + fsize > part->start + part->size) {			printk(KERN_WARNING "flash: request past end "			       "of partition\n");			end_request(0);			continue;		}		/* actually do something, but get a lock on the chip first.		 * since the partition might span several chips, we need to		 * loop and lock each chip in turn		 */		while(fsize > 0) {			chip = getchip(fptr);			/* how much fits in this chip ? */			opsize = (fptr + fsize) > (chip->start + chip->size) ?				 (chip->start + chip->size - fptr) : fsize;			/* lock the chip */			save_flags(flags);			cli();			while(chip->busy)				sleep_on(&chip->wqueue);			chip->busy = 1;			restore_flags(flags);			switch(CURRENT->cmd) {			case READ:				memcpy(CURRENT->buffer, fptr, opsize);				FDEBUG(printk("flash read from %p to %p "					      "size %d\n", fptr,					      CURRENT->buffer, opsize));				break;			case WRITE:				FDEBUG(printk("flash write block at 0x%p\n",					      fptr));				flash_write(fptr,					    (unsigned char *)					    CURRENT->buffer,					    opsize);				break;			default:				/* Shouldn't happen.  */				chip->busy = 0;				wake_up(&chip->wqueue);				end_request(0);				continue;			}			/* release the lock */			chip->busy = 0;			wake_up(&chip->wqueue);			/* see if there is anything left to write in the next chip */			fsize -= opsize;			fptr += opsize;		}		/* We have a liftoff! */		end_request(1);	}}#endif /* CONFIG_BLK_DEV_FLASH */voidflash_safe_acquire(void *part){	struct flashchip *chip = ((struct flashpartition *)part)->chip;	while (chip->busy)		sleep_on(&chip->wqueue);	chip->busy = 1;}voidflash_safe_release(void *part){	struct flashchip *chip = ((struct flashpartition *)part)->chip;	chip->busy = 0;	wake_up(&chip->wqueue);}/* flash_safe_read and flash_safe_write are used by the JFFS flash filesystem */intflash_safe_read(void *_part, unsigned char *fptr,		unsigned char *buf, int count){	struct flashpartition *part = (struct flashpartition *)_part;	/* Check so it's not totally out of bounds.  */	if(fptr + count > part->start + part->size) {		printk(KERN_WARNING "flash: read request past "		       "end of device (address: 0x%p, size: %d)\n",		       fptr, count);		return -EINVAL;	}	FDEBUG(printk("flash_safe_read: %d bytes from 0x%p to 0x%p\n",		      count, fptr, buf));	/* Actually do something, but get a lock on the chip first.  */	flash_safe_acquire(part);	memcpy(buf, fptr, count);	/* Release the lock.  */	flash_safe_release(part);	return count; /* success */}intflash_safe_write(void *_part, unsigned char *fptr,		 const unsigned char *buf, int count){	struct flashpartition *part = (struct flashpartition *)_part;	int err;	/* Check so it's not totally out of bounds.  */	if(fptr + count > part->start + part->size) {		printk(KERN_WARNING "flash: write operation past "		       "end of device (address: 0x%p, size: %d)\n",		       fptr, count);		return -EINVAL;	}	FDEBUG(printk("flash_safe_write: %d bytes from 0x%p to 0x%p\n",		      count, buf, fptr));	/* Actually do something, but get a lock on the chip first.  */	flash_safe_acquire(part);	if ((err = flash_write(fptr, buf, count)) < 0) {		count = err;	}	/* Release the lock.  */	flash_safe_release(part);	return count; /* success */}#ifdef CONFIG_CHR_DEV_FLASHstatic intflash_char_read(struct inode *inode, struct file *filp,		char *buf, int count){	int rlen;	struct flashpartition *part = (struct flashpartition *)filp->private_data;	FDEBUG(printk("flash_char_read\n"));	rlen = flash_safe_read(part,			       (unsigned char *)part->start + filp->f_pos,			       (unsigned char *)buf, count);	/* advance file position pointer */	if(rlen >= 0)		filp->f_pos += rlen;	return rlen;}static intflash_char_write(struct inode *inode, struct file *filp,		 const char *buf, int count){	int wlen;	struct flashpartition *part = (struct flashpartition *)filp->private_data;	FDEBUG(printk("flash_char_write\n"));

⌨️ 快捷键说明

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