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

📄 flash.c

📁 如何制作JFFS文件系统
💻 C
📖 第 1 页 / 共 3 页
字号:
		if(!chip) {			printk("Flash: illegal ptr 0x%p in flash_write.\n", ptr);			return -EINVAL;		}		flashStart = (flashptr)chip->start;		programAddress = (flashptr)ptr;		/* if the block doesn't fit in this flash chip, clamp the size */		fsize = (ptr + size) > (chip->start + chip->size) ?			(chip->start + chip->size - ptr) : size;		ptr += fsize;		size -= fsize;		odd_size = fsize & 1;		fsize >>= 1; /* We write one word at a time.  */		FDEBUG(printk("flash_write (flash start 0x%p) %d words to 0x%p\n",			      flashStart, fsize, programAddress));		for (i = 0; i < fsize; i++) {			int retries = 0;			do {				int timeout;				/* Start programming sequence.				 */#ifdef IRQ_LOCKS				unsigned long flags;				save_flags(flags);				cli();#endif				flashStart[unlockAddress1] = unlockData1;				flashStart[unlockAddress2] = unlockData2;				flashStart[unlockAddress1] = programUnlockData;				*programAddress = *theData;				/* give the busy signal time to activate (tBusy, 90 ns) */				nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop();				/* Wait for programming to finish.  */				timeout = 500000;				while(timeout-- &&				      (*programAddress & D8_MASK)				      != (*theData & D8_MASK)) {				    if (*programAddress & D5_MASK)						break;				}				/* nothing */;#ifdef IRQ_LOCKS				restore_flags(flags);#endif				if(timeout <= 0)					printk("flash: write timeout 0x%p\n",					       programAddress);				if (*programAddress == *theData)					break;				printk("Flash: verify error 0x%p. "				       "(flash_write() 1)\n",				       programAddress);				printk("*programAddress = 0x%04x, "				       "*theData = 0x%04x\n",				       *programAddress, *theData);			} while(++retries < 5);			if(retries >= 5) {				printk("FATAL FLASH ERROR (1)\n");				return -EIO; /* we failed... */			}			programAddress++;			theData++;		}		/* We should write one extra byte to the flash.  */		if (odd_size) {			unsigned char last_byte[2];			int retries = 0;			last_byte[0] = *(unsigned char *)theData;			last_byte[1] = ((unsigned char *)programAddress)[1];			do {				int timeout = 500000;#ifdef IRQ_LOCKS				unsigned long flags;				save_flags(flags);				cli();#endif				flashStart[unlockAddress1] = unlockData1;				flashStart[unlockAddress2] = unlockData2;				flashStart[unlockAddress1] = programUnlockData;				*programAddress = *(flashptr) last_byte;				/* give the busy signal time enough to activate (tBusy, 90 ns) */				nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop();				/* Wait for programming to finish */				while(timeout-- &&				      (*programAddress & D8_MASK)				      != ((* (flashptr) last_byte) & D8_MASK)) {				    if (*programAddress & D5_MASK)						break;				}#ifdef IRQ_LOCKS				restore_flags(flags);#endif				if(timeout <= 0)					printk("flash: write timeout 0x%p\n",					       programAddress);				if (*programAddress == * (flashptr) last_byte)					break;				printk("Flash: verify error 0x%p. "				       "(flash_write() 2)\n",				       programAddress);			} while(++retries < 5);			if(retries >= 5) {				printk("FATAL FLASH ERROR (2)\n");				return -EIO; /* we failed... */			}		}	}#else	/* in the simulator we simulate flash as ram, so we can use a simple memcpy */	printk("flash write, source %p dest %p size %d\n", source, ptr, size);	memcpy(ptr, source, size);#endif	return 0;}/* "Memset" a chunk of memory on the flash. * do this by flash_write()'ing a pattern chunk. */intflash_memset(unsigned char *ptr, const __u8 c, unsigned long size){#ifndef CONFIG_SVINTO_SIM	static unsigned char pattern[16];	int i;	/* fill up pattern */	for(i = 0; i < 16; i++)		pattern[i] = c;	/* write as many 16-byte chunks as we can */	while(size >= 16) {		flash_write(ptr, pattern, 16);		size -= 16;		ptr += 16;	}	/* and the rest */	if(size)		flash_write(ptr, pattern, size);#else	/* In the simulator, we simulate flash as ram, so we can use a	   simple memset.  */	printk("flash memset, byte 0x%x dest %p size %d\n", c, ptr, size);	memset(ptr, c, size);#endif	return 0;}#ifdef CONFIG_BLK_DEV_FLASH/* the operations supported by the block device */static struct file_operations flash_block_fops ={	NULL,                   /* lseek - default */	block_read,             /* read - general block-dev read */	block_write,            /* write - general block-dev write */	NULL,                   /* readdir - bad */	NULL,                   /* poll */	flash_ioctl,            /* ioctl */	NULL,                   /* mmap */	flash_open,             /* open */	flash_release,          /* release */	block_fsync,            /* fsync */	NULL,			/* fasync */	NULL,			/* check media change */	NULL			/* revalidate */};#endif#ifdef CONFIG_CHR_DEV_FLASH/* the operations supported by the char device */static struct file_operations flash_char_fops ={	NULL,                   /* lseek - default */	flash_char_read,        /* read */	flash_char_write,       /* write */	NULL,                   /* readdir - bad */	NULL,                   /* poll */	flash_ioctl,            /* ioctl */	NULL,                   /* mmap */	flash_open,             /* open */	flash_release,          /* release */	NULL,                   /* fsync */	NULL,			/* fasync */	NULL,			/* check media change */	NULL			/* revalidate */};#endif/* Initialize the flash_partitions array, by reading the partition information from the * partition table (if there is any). Otherwise use a default partition set. * * The first partition is always sector 0 on the first chip, so start by initializing that. * TODO: partitions only reside on chip[0] now. check that. */static voidflash_init_partitions(){	struct partitiontable_head *ptable_head;	struct partitiontable_entry *ptable;	int use_default_ptable = 1; /* Until proven otherwise */	int pidx = 0;	int pidx_before_probe = 0;	const char *pmsg = "  /dev/flash%d at 0x%x, size 0x%x\n";	/* if there is no chip 0, there is no bootblock => no partitions at all */		if (chips[0].isValid) {		printk("Checking flash partitions:\n");		/* First sector in the flash is partition 0,		   regardless of if it's a real flash "bootblock" or not.  */		partitions[0].chip = &chips[0];		partitions[0].start = chips[0].start;		partitions[0].size = chips[0].sectorsize;		partitions[0].flags = 0;  /* FIXME */		flash_sizes[FLASH_MINOR] =			partitions[0].size >> BLOCK_SIZE_BITS;		FDEBUG(printk(pmsg, 0, partitions[0].start, partitions[0].size));		pidx++;		ptable_head = (struct partitiontable_head *)		  (partitions[0].start + partitions[0].size		   + PARTITION_TABLE_OFFSET);#ifdef CONFIG_SVINTO_SIM                /* If running in the simulator, do not scan nonexistent		   memory.  Behave as when the bootblock is "broken".                   ??? FIXME: Maybe there's something better to do. */		partitions[pidx].chip = &chips[0];		partitions[pidx].start = chips[0].start;		partitions[pidx].size = chips[0].size;		partitions[pidx].flags = 0; /* FIXME */		flash_sizes[FLASH_MINOR + pidx] =			partitions[pidx].size >> BLOCK_SIZE_BITS;		printk(pmsg, pidx, partitions[pidx].start, partitions[pidx].size);		pidx++;#else  /* ! defined CONFIG_SVINTO_SIM */		pidx_before_probe = pidx;		/* TODO: until we've defined a better partition table,		 * always do the default flash1 and flash2 partitions.		 */		if ((ptable_head->magic ==  PARTITION_TABLE_MAGIC)		    && (ptable_head->size			< (MAX_PARTITIONS			   * sizeof(struct partitiontable_entry) + 4))		    && (*(unsigned long*)			((void*)ptable_head			 + sizeof(*ptable_head)			 + ptable_head->size - 4)			==  PARTITIONTABLE_END_MARKER)) {			/* Looks like a start, sane length and end of a			 * partition table, lets check csum etc.			 */			int ptable_ok = 0;			struct partitiontable_entry *max_addr =			  (struct partitiontable_entry *)			  ((unsigned long)ptable_head + sizeof(*ptable_head) +				ptable_head->size);			unsigned long offset = chips[0].sectorsize;			unsigned char *p;			unsigned long csum = 0;			ptable = (struct partitiontable_entry *)			  ((unsigned long)ptable_head + sizeof(*ptable_head));			/* Lets be PARANOID, and check the checksum. */			p = (unsigned char*) ptable;			while (p <= (unsigned char*)max_addr) {				csum += *p++;				csum += *p++;				csum += *p++;				csum += *p++;			}			printk("  total csum: 0x%08X 0x%08X\n",			   csum, ptable_head->checksum);			ptable_ok = (csum == ptable_head->checksum);			/* Read the entries and use/show the info.  */			ptable = (struct partitiontable_entry *)			  ((unsigned long)ptable_head + sizeof(*ptable_head));			printk(" Found %s partition table at 0x%08lX-0x%08lX.\n",			       (ptable_ok ? "valid" : "invalid"),			       (unsigned long)ptable_head,			       (unsigned long)max_addr);			/* We have found a working bootblock.  Now read the			   partition table.  Scan the table.  It ends when			   there is 0xffffffff, that is, empty flash.  */			while (ptable_ok			       && ptable->offset != 0xffffffff			       && ptable < max_addr			       && pidx < MAX_PARTITIONS) {				partitions[pidx].chip = &chips[0];				if ((offset + ptable->offset) >= chips[0].size) {					partitions[pidx].start					  = offset + chips[1].start					    + ptable->offset - chips[0].size;				}				else {					partitions[pidx].start					  = offset + chips[0].start					    + ptable->offset;				}				partitions[pidx].size = ptable->size;				partitions[pidx].flags = ptable->flags;				partitions[pidx].type = ptable->type;				flash_sizes[FLASH_MINOR + pidx] =					partitions[pidx].size >> BLOCK_SIZE_BITS;				printk(pmsg, pidx, partitions[pidx].start,				       partitions[pidx].size);				pidx++;				ptable++;			}#ifdef CONFIG_USE_FLASH_PARTITION_TABLE			use_default_ptable = !ptable_ok;#endif		}printk("Checking flash partitions:\n");		if (use_default_ptable) {			/* the flash is split into flash1, flash2 and bootblock			 * (flash0)			 */			pidx = pidx_before_probe;			FDEBUG(printk(" Using default flash1 and flash2.\n"));			printk(" Using default flash1:.\n");			/* flash1 starts after the first sector */			partitions[pidx].chip = &chips[0];			partitions[pidx].start = chips[0].start + chips[0].sectorsize;			partitions[pidx].size = chips[0].size - (DEF_FLASH2_SIZE +				partitions[0].size);			partitions[pidx].flags = 0; /* FIXME */			flash_sizes[FLASH_MINOR + pidx] =				partitions[pidx].size >> BLOCK_SIZE_BITS;			printk(pmsg, pidx, partitions[pidx].start,			       partitions[pidx].size);			pidx++;			/* flash2 starts after flash1. */			partitions[pidx].chip = &chips[0];			partitions[pidx].start = partitions[pidx - 1].start +				partitions[pidx - 1].size;			partitions[pidx].size = DEF_FLASH2_SIZE;			partitions[pidx].flags = 0; /* FIXME */			flash_sizes[FLASH_MINOR + pidx] =				partitions[pidx].size >> BLOCK_SIZE_BITS;			FDEBUG(printk(pmsg, pidx, partitions[pidx].start,			       partitions[pidx].size));			pidx++;		}#endif /* ! defined CONFIG_SVINTO_SIM */	}	/* fill in the rest of the table as well */	while (pidx < MAX_PARTITIONS) {		partitions[pidx].start = 0;		partitions[pidx].size = 0;		partitions[pidx].chip = 0;		pidx++;	}	/*flash_blk_sizes[FLASH_MINOR + i] = 1024; TODO this should be 512.. */}#ifdef LISAHACKstatic voidmove_around_bootparams(){	unsigned long *newp = (unsigned long *)0x8000c000;  /* new bootsector */	unsigned long *oldp = (unsigned long *)0x801fc000;  /* old bootsector */	unsigned long *buf;	unsigned long magic = 0xbeefcace;	printk("Checking if we need to move bootparams...");	/* First check if they are already moved.  */	if(*newp == magic) {		printk(" no\n");		return;	}	printk(" yes. Moving...");	buf = (unsigned long *)kmalloc(0x4000, GFP_KERNEL);	memcpy(buf, oldp, 0x4000);	flash_write((unsigned char *)newp, (unsigned char *)&magic, 4);	flash_write((unsigned char *)(newp + 1), (unsigned char *)buf, 0x4000 - 4);	/* Erase old boot block, so JFFS can expand into it.  */	flash_init_erase((unsigned char *)0x801f0000, chips[0].sectorsize);	flash_busy_wait_erase(chips[0].start);	printk(" done.\n");	kfree(buf);}#endif/* register the device into the kernel - called at boot */intflash_init(){#ifdef CONFIG_BLK_DEV_FLASH	/* register the block device major */	if(register_blkdev(MAJOR_NR, DEVICE_NAME, &flash_block_fops )) {		printk(KERN_ERR DEVICE_NAME ": Unable to get major %d\n",		       MAJOR_NR);		return -EBUSY;	}	/* register the actual block I/O function - do_flash_request - and the	 * tables containing the device sizes (in 1kb units) and block sizes	 */	blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;	blk_size[MAJOR_NR] = flash_sizes;	blksize_size[MAJOR_NR] = flash_blk_sizes;	read_ahead[MAJOR_NR] = 1; /* fast device, so small read ahead */	printk("Flash/ROM block device v2.1, (c) 1999 Axis Communications AB\n");	printk("Driver for SST39VF160 Flash block device v1.0, (c) 2001 Zhihui Li,Wanhe Corp.,Ltd.\n");#endif#ifdef CONFIG_CHR_DEV_FLASH	/* register the char device major */	if(register_chrdev(MAJOR_NR, DEVICE_NAME, &flash_char_fops )) {		printk(KERN_ERR DEVICE_NAME ": Unable to get major %d\n",		       MAJOR_NR);		return -EBUSY;	}	printk("Flash/ROM char device v2.1, (c) 1999 Axis Communications AB\n");#endif	/* initialize partition table */	flash_init_partitions();#ifdef LISAHACK	/* nasty hack to "upgrade" older beta units of Lisa into newer by	 * moving the boot block parameters. will go away as soon as this	 * build is done.	 */	move_around_bootparams();#endif	return 0;}/* check if it's possible to erase the wanted range, and if not, return * the range that IS erasable, or a negative error code. */longflash_erasable_size(void *_part, __u32 offset, __u32 size){	struct flashpartition *part = (struct flashpartition *)_part;	int ssize;	if (!part->start) {		return -EINVAL;	}	/* assume that sector size for a partition is constant even	 * if it spans more than one chip (you usually put the same	 * type of chips in a system)	 */	ssize = part->chip->sectorsize;	if (offset % ssize) {		/* The offset is not sector size aligned.  */		return -1;	}	else if (offset > part->size) {		return -2;	}	else if (offset + size > part->size) {		return -3;	}	return (size / ssize) * ssize;}

⌨️ 快捷键说明

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