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

📄 flash.c

📁 如何制作JFFS文件系统
💻 C
📖 第 1 页 / 共 3 页
字号:
	wlen = flash_safe_write(part,				(unsigned char *)part->start + filp->f_pos,				(unsigned char *)buf, count);	/* advance file position pointer */	if(wlen >= 0)		filp->f_pos += wlen;	return wlen;}#endif /* CONFIG_CHR_DEV_FLASH */static intflash_ioctl(struct inode *inode, struct file *file,	    unsigned int cmd, unsigned long arg){	int minor;	struct flashpartition *part;	struct flashchipinfo *finfo;	if (!inode || !inode->i_rdev)		return -EINVAL;	minor = MINOR(inode->i_rdev);	if(minor < FLASH_MINOR)		return -EINVAL; /* only ioctl's for flash devices */	part = &partitions[minor - FLASH_MINOR];	switch(cmd) {	case FLASHIO_CHIPINFO:		if(!suser())			return -EACCES;		if(arg == 0)			return -EINVAL;		finfo = (struct flashchipinfo *)arg;		/* TODO: verify arg */		finfo->isValid = chips[0].isValid;		finfo->manufacturer_id = chips[0].manufacturer_id;		finfo->device_id = chips[0].device_id;		finfo->size = chips[0].size;		finfo->sectorsize = chips[0].sectorsize;		return 0;	case FLASHIO_ERASEALL:		if(!part->start)			return -EINVAL;		if(!suser())			return -EACCES;		/* Invalidate all pages and buffers */		invalidate_inodes(inode->i_rdev);		invalidate_buffers(inode->i_rdev);		/*		 * Start the erasure, then sleep and wake up now and		 * then to see if it's done. We use the waitqueue to		 * make sure we don't start erasing in the middle of		 * a write, or that nobody start using the flash while		 * we're erasing.		 *		 * TODO: break up partition erases that spans more than one		 *       chip.		 */		flash_safe_acquire(part);		flash_init_erase(part->start, part->size);		while (flash_is_busy(part->start)		       || !flash_pos_is_clean(part->start)) {			current->state = TASK_INTERRUPTIBLE;			current->timeout = jiffies + HZ / 2;			schedule();		}		flash_safe_release(part);		return 0;	default:		return -EPERM;	}	return -EPERM;}/* probe for Flash RAM's - this isn't in the init function, because this needs * to be done really early in the boot, so we can use the device to burn an * image before the system is running. */voidflash_probe(){	int i;	/* start adresses for the Flash chips - these should really	 * be settable in some other way.	 */#ifdef FLASH_VERBOSE	safe_printk("Probing flash...\n");#endif#ifdef CONFIG_COLDFIRE	chips[0].start = (unsigned char *)(0xf0110000);#else	chips[0].start = (unsigned char *)(MEM_CSE0_START | MEM_NON_CACHEABLE);	chips[1].start = (unsigned char *)(MEM_CSE1_START | MEM_NON_CACHEABLE);#endif	for(i = 0; i < MAX_CHIPS; i++) {		struct flashchip *chip = chips + i;		flashptr flashStart = (flashptr)chip->start;		unsigned short manu;#ifdef FLASH_VERBOSE		FDEBUG(safe_printk("Probing flash #%d at 0x%x\n", i, flashStart));#endif#ifdef CONFIG_SVINTO_SIM		/* in the simulator, dont trash the flash ram by writing unlocks */		chip->isValid = 1;		chip->device_id = AM29LV160BT;#else		/* reset */		flashStart[unlockAddress1] = unlockData1;		flashStart[unlockAddress2] = unlockData2;		flashStart[unlockAddress1] = resetData;		/* read manufacturer */		flashStart[unlockAddress1] = unlockData1;		flashStart[unlockAddress2] = unlockData2;		flashStart[unlockAddress1] = manufacturerUnlockData;		flashStart[unlockAddress1] = 0x9898;		manu = flashStart[manufacturerAddress];		chip->isValid = (manu == ManufacturerAMD ||				 manu == ManufacturerToshiba ||				 manu == ManufacturerST ||				 manu == ManufacturerSST);		chip->manufacturer_id = manu;		/* reset */		flashStart[unlockAddress1] = unlockData1;		flashStart[unlockAddress2] = unlockData2;		flashStart[unlockAddress1] = resetData;		/* read device id */		flashStart[unlockAddress1] = unlockData1;		flashStart[unlockAddress2] = unlockData2;		flashStart[unlockAddress1] = manufacturerUnlockData;		chip->device_id = flashStart[deviceIdAddress];		/* reset */		flashStart[unlockAddress1] = unlockData1;		flashStart[unlockAddress2] = unlockData2;		flashStart[unlockAddress1] = resetData;#endif		/* check device type and fill in correct sizes etc */		switch(chip->device_id) {		case AM29LV160BT:		case TC58FVT160:#ifdef FLASH_VERBOSE			safe_printk("Flash: 16Mb TB\n");#endif			chip->size = 0x00200000;			chip->sectorsize = 0x10000;			chip->bootsector = chip->start + chip->size					   - chip->sectorsize;			chip->bootsectorsize[0] = 0x8000;			chip->bootsectorsize[1] = 0x2000;			chip->bootsectorsize[2] = 0x2000;			chip->bootsectorsize[3] = 0x4000;			break;		//case AM29LV160BB:		case TC58FVB160:#ifdef FLASH_VERBOSE			safe_printk("Flash: 16Mb BB\n");#endif			chip->size = 0x00200000;			chip->sectorsize = 0x10000;			chip->bootsector = chip->start;			chip->bootsectorsize[0] = 0x4000;			chip->bootsectorsize[1] = 0x2000;			chip->bootsectorsize[2] = 0x2000;			chip->bootsectorsize[3] = 0x8000;			break;		case AM29LV800BB:		case AM29F800BB:#ifdef FLASH_VERBOSE			safe_printk("Flash: 8Mb BB\n");#endif			chip->size = 0x00100000;			chip->sectorsize = 0x10000;			chip->bootsector = chip->start;			chip->bootsectorsize[0] = 0x4000;			chip->bootsectorsize[1] = 0x2000;			chip->bootsectorsize[2] = 0x2000;			chip->bootsectorsize[3] = 0x8000;			break;		case M29W800T:		case AM29LV800BT:		case AM29F800BT:#ifdef FLASH_VERBOSE			safe_printk("Flash: 8Mb TB\n");#endif			chip->size = 0x00100000;			chip->sectorsize = 0x10000;			chip->bootsector = chip->start + chip->size					   - chip->sectorsize;			chip->bootsectorsize[0] = 0x8000;			chip->bootsectorsize[1] = 0x2000;			chip->bootsectorsize[2] = 0x2000;			chip->bootsectorsize[3] = 0x4000;			break;			//     case AM29LV800BB:			/* the following supports smaller sector erases (like 2 Kword)			 * so they dont use bootblocks. until we've implemented real			 * support for the smaller erases, we just treat them as if they			 * dont have bootblocks at all.			 */		case SST39LF800:#ifdef FLASH_VERBOSE			safe_printk("Flash: 8Mb No B\n");#endif			chip->size = 0x00010000;			chip->sectorsize = 0x1000;			chip->bootsector = (unsigned char *)MEM_DRAM_START; /* never a flash address (see above) */			break;		case SST39VF160:#ifdef FLASH_VERBOSE			safe_printk("Flash: SST39VF160 16Mb No B");#endif			chip->size = 0x00100000;			chip->sectorsize = 0x0100;			chip->bootsector = (unsigned char *)MEM_DRAM_START; /* never a flash address */			break;		default:#ifdef FLASH_VERBOSE			safe_printk("Flash: Unknown device\n");#endif			chip->isValid = 1;			chip->size = 0x00100000;		    chip->sectorsize = 0x1000;			chip->bootsector = (unsigned char *)MEM_DRAM_START;			break;		}		chip->busy = 0;		init_waitqueue(&chip->wqueue);	}}/* locate the flashchip structure associated with the given adress */static struct flashchip *getchip(unsigned char *ptr){	int i;	for (i = 0; i < MAX_CHIPS; i++) {		FDEBUG(printk("flash: chips[i].start: 0x%x,chips[i].size=0x%x!\n", chips[i].start,chips[i].size));		if (ptr >= chips[i].start		    && ptr < (chips[i].start + chips[i].size)) {			return &chips[i];		}	}	printk("flash: Illegal address: getchip(0x%p)!\n", ptr);	return (void *)0;}void *flash_getpart(kdev_t dev){	struct flashpartition *part;	if (MINOR(dev) < FLASH_MINOR) {		return 0;	}	part = &partitions[MINOR(dev) - FLASH_MINOR];	if (!part->start) {		return 0;	}	return (void *)part;}unsigned char *flash_get_direct_pointer(kdev_t dev, __u32 offset){	struct flashpartition *part;	if (MINOR(dev) < FLASH_MINOR) {		return 0;	}	part = &partitions[MINOR(dev) - FLASH_MINOR];	if (!part->start) {		return 0;	}	return (unsigned char *) ((__u32) part->start + offset);}/* start erasing flash-memory at ptr of a certain size * this does not wait until the erasing is done */voidflash_init_erase(unsigned char *ptr, unsigned int size){	struct flashchip *chip;	int bootSectorCounter = 0;	unsigned int erasedSize = 0;	flashptr flashStart;	unsigned long  i;    unsigned short status;#ifdef IRQ_LOCKS	unsigned long flags;#endif	ptr = (unsigned char *)((unsigned long)ptr | MEM_NON_CACHEABLE);	chip = getchip(ptr);	flashStart = (flashptr)chip->start;	FDEBUG(safe_printk("Flash: erasing memory at 0x%p, size 0x%x.\n", ptr, size));	/* need to disable interrupts, to avoid possible delays between the	 * unlocking and erase-init	 */#ifdef IRQ_LOCKS	save_flags(flags);	cli();#endif	/* Init erasing of the number of sectors needed */        printk("Erase flash device now,please wait...\n");	while (erasedSize < size) {		flashStart[unlockAddress1] = unlockData1;		flashStart[unlockAddress2] = unlockData2;		flashStart[unlockAddress1] = sectorEraseUnlockData;		flashStart[unlockAddress1] = unlockData1;		flashStart[unlockAddress2] = unlockData2;		*(flashptr)ptr = sectorEraseUnlockData2;		/* make sure we erase the individual bootsectors if in that area */		/* TODO this BREAKS if we start erasing in the middle of the bootblock! */		if (ptr < chip->bootsector || ptr >= (chip->bootsector +						      chip->sectorsize)) {			erasedSize += chip->sectorsize;			ptr += chip->sectorsize;		}		else {			erasedSize += chip->bootsectorsize[bootSectorCounter];			ptr += chip->bootsectorsize[bootSectorCounter++];		}		for(i=0;i<0x30000;i++){                        status=*(flashptr)ptr;                        if(status&0x0080){                                FDEBUG(printk("Erase address 0x%x OK! i=%d\n",ptr,i));                                break;                        }                }        }        printk("Erased OK! You can mount jffs now!\n");#ifdef IRQ_LOCKS	restore_flags(flags);#endif	/* give the busy signal time enough to activate (tBusy, 90 ns) */	nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop();}intflash_erase_region(kdev_t dev, __u32 offset, __u32 size){	int minor;	struct flashpartition *part;	unsigned char *erase_start;	short retries = 5;	short success;        minor = MINOR(dev);	if (minor < FLASH_MINOR) {		return -EINVAL;	}	part = &partitions[minor - FLASH_MINOR];	if (!part->start) {		return -EINVAL;	}	/* Start the erasure, then sleep and wake up now and then to see	 * if it's done.	 */	erase_start = part->start + offset;	flash_safe_acquire(part);	do {		flash_init_erase(erase_start, size);		while (flash_is_busy(erase_start)) {			current->state = TASK_INTERRUPTIBLE;			current->timeout = jiffies + HZ / 2;			schedule();		}        		success = ((flashptr)erase_start)[0] == 0xffff	        		  && ((flashptr)erase_start)[1] == 0xffff		        	  && ((flashptr)erase_start)[2] == 0xffff			          && ((flashptr)erase_start)[3] == 0xffff;		if (!success) {			printk(KERN_NOTICE "flash: erase of region "			       "[0x%p, 0x%p] failed once\n",			       erase_start, erase_start + size);		}	} while (retries-- && !success);	flash_safe_release(part);	if (retries == 0 && !success) {		printk(KERN_WARNING "flash: erase of region "			       "[0x%p, 0x%p] totally failed\n",			       erase_start, erase_start + size);		return -1;	}	return 0;}/* wait until the erase operation is finished, in a CPU hogging manner */voidflash_busy_wait_erase(unsigned char *ptr){	flashptr flashStart;	ptr = (unsigned char *)((unsigned long)ptr | MEM_NON_CACHEABLE);	flashStart = (flashptr)getchip(ptr)->start;	/* busy-wait for flash completion - when D6 stops toggling between	 * reads.	 */	while (flash_is_busy(flashStart))		/* nothing */;}/* erase all flashchips and wait until operation is completed */voidflash_erase_all(){	/* TODO: we should loop over chips, not just try the first two! */	if(chips[0].isValid)		flash_init_erase(chips[0].start, chips[0].size);	if(chips[1].isValid)		flash_init_erase(chips[1].start, chips[0].size);	if(chips[0].isValid)		flash_busy_wait_erase(chips[0].start);	if(chips[1].isValid)		flash_busy_wait_erase(chips[1].start);#ifdef FLASH_VERBOSE	safe_printk("Flash: full erasure completed.\n");#endif}/* Write a block of Flash. The destination Flash sectors need to be erased * first. If the size is larger than the Flash chip the block starts in, the * function will continue flashing in the next chip if it exists. * Returns 0 on success, -1 on error. */intflash_write(unsigned char *ptr, const unsigned char *source, unsigned int size){#ifndef CONFIG_SVINTO_SIM	struct flashchip *chip;	flashptr theData = (flashptr)source;	flashptr flashStart;	flashptr programAddress;	int i, fsize;	int odd_size;	ptr = (unsigned char *)((unsigned long)ptr | MEM_NON_CACHEABLE);	while(size > 0) {		chip = getchip(ptr);

⌨️ 快捷键说明

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