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

📄 cfi_cmdset_0001.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
		}				/* Latency issues. Drop the lock, wait a while and retry */		spin_unlock_bh(chip->mutex);				z++;		if ( 0 && !(z % 100 )) 		  printk("chip not ready yet after write. looping\n");				udelay(1);				spin_lock_bh(chip->mutex);		continue;	}	if (!z) {		chip->word_write_time--;		if (!chip->word_write_time)			chip->word_write_time++;	}	if (z > 1) 		chip->word_write_time++;	/* Done and happy. */	chip->state = FL_STATUS;	wake_up(&chip->wq);	spin_unlock_bh(chip->mutex);	//	printk("write ret OK at %lx\n", adr);	return 0;}/* This version only uses the 'word write' instruction. We should update it * to write using 'buffer write' if it's available  */static int cfi_intelext_write_1_by_16 (struct mtd_info *mtd, loff_t to , size_t len, size_t *retlen, const u_char *buf){	struct map_info *map = mtd->priv;	struct cfi_private *cfi = map->fldrv_priv;	int ret = 0;	int chipnum;	unsigned long ofs;	*retlen = 0;	chipnum = to >> cfi->chipshift;	ofs = to  - (chipnum << cfi->chipshift);	/* If it's not word-aligned, do the first byte write */	if (ofs & 1) {#if defined(__LITTLE_ENDIAN)		ret = do_write_1_by_16_oneword(map, &cfi->chips[chipnum],					       ofs, 0xFF | (*buf << 8));#elif defined(__BIG_ENDIAN) 		ret = do_write_1_by_16_oneword(map, &cfi->chips[chipnum],					       ofs, 0xFF00 | (*buf));#else#error define a sensible endianness#endif		if (ret) 			return ret;				ofs++;		buf++;		(*retlen)++;		len--;		if (ofs >> cfi->chipshift) {			chipnum ++; 			ofs = 0;			if (chipnum == cfi->numchips)				return 0;		}	}		while(len > 1) {		ret = do_write_1_by_16_oneword(map, &cfi->chips[chipnum],					       ofs, *(__u16 *)buf);		if (ret)			return ret;		ofs += 2;		buf += 2;		(*retlen) += 2;		len -= 2;		if (ofs >> cfi->chipshift) {			chipnum ++; 			ofs = 0;			if (chipnum == cfi->numchips)				return 0;		}	}	if (len) {		/* Final byte to write */#if defined(__LITTLE_ENDIAN)		ret = do_write_1_by_16_oneword(map, &cfi->chips[chipnum],					       ofs, 0xFF00 | (*buf));#elif defined(__BIG_ENDIAN) 		ret = do_write_1_by_16_oneword(map, &cfi->chips[chipnum],					       ofs, 0xFF | (*buf << 8));#else#error define a sensible endianness#endif		if (ret) 			return ret;				(*retlen)++;	}	return 0;}static inline int do_erase_1_by_16_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr){	__u16 status;	unsigned long timeo = jiffies + HZ;	DECLARE_WAITQUEUE(wait, current);	adr += chip->start; retry:	spin_lock_bh(chip->mutex);	/* Check that the chip's ready to talk to us. */	switch (chip->state) {	case FL_CFI_QUERY:	case FL_JEDEC_QUERY:	case FL_READY:		map->write16(map, cpu_to_le16(0x0070), adr);		chip->state = FL_STATUS;		timeo = jiffies + HZ;	case FL_STATUS:		status = le16_to_cpu(map->read16(map, adr));		if (!(status & (1<<7))) {			static int z=0;			/* Urgh. Chip not yet ready to talk to us. */			if (time_after(jiffies, timeo)) {				spin_unlock_bh(chip->mutex);				printk("waiting for chip to be ready timed out in erase");				return -EIO;			}			/* Latency issues. Drop the lock, wait a while and retry */			spin_unlock_bh(chip->mutex);			z++;			if ( 0 && !(z % 100 )) 				printk("chip not ready yet before erase. looping\n");			udelay(1);			goto retry;		}		break;	default:		printk("Waiting for chip, status = %d\n", chip->state);		/* Stick ourselves on a wait queue to be woken when		   someone changes the status */		set_current_state(TASK_INTERRUPTIBLE);		add_wait_queue(&chip->wq, &wait);				spin_unlock_bh(chip->mutex);		schedule();		remove_wait_queue(&chip->wq, &wait);		if(signal_pending(current))			return -EINTR;		timeo = jiffies + HZ;		goto retry;	}		map->write16(map, cpu_to_le16(0x0020), adr);	map->write16(map, cpu_to_le16(0x00D0), adr);	chip->state = FL_ERASING;		timeo = jiffies + (HZ*2);	spin_unlock_bh(chip->mutex);	schedule_timeout(HZ);	spin_lock_bh(chip->mutex);	/* FIXME. Use a timer to check this, and return immediately. */	/* Once the state machine's known to be working I'll do that */	while ( !( (status = le16_to_cpu(map->read16(map, adr)))  & 0x80 ) ) {		static int z=0;		if (chip->state != FL_ERASING) {			/* Someone's suspended the erase. Sleep */			set_current_state(TASK_INTERRUPTIBLE);			add_wait_queue(&chip->wq, &wait);						spin_unlock_bh(chip->mutex);			printk("erase suspended. Sleeping\n");						schedule();			remove_wait_queue(&chip->wq, &wait);						if (signal_pending(current))				return -EINTR;						timeo = jiffies + (HZ*2); /* FIXME */			spin_lock_bh(chip->mutex);			continue;		}		/* OK Still waiting */		if (time_after(jiffies, timeo)) {			chip->state = FL_STATUS;			spin_unlock_bh(chip->mutex);			printk("waiting for erase to complete timed out.");			return -EIO;		}				/* Latency issues. Drop the lock, wait a while and retry */		spin_unlock_bh(chip->mutex);		z++;		if ( 0 && !(z % 100 )) 			printk("chip not ready yet after erase. looping\n");		udelay(1);				spin_lock_bh(chip->mutex);		continue;	}		/* Done and happy. */	chip->state = FL_STATUS;	wake_up(&chip->wq);	spin_unlock_bh(chip->mutex);	//printk("erase ret OK\n");	return 0;}static int cfi_intelext_erase_1_by_16 (struct mtd_info *mtd, struct erase_info *instr){	struct map_info *map = mtd->priv;	struct cfi_private *cfi = map->fldrv_priv;	unsigned long adr, len;	int chipnum, ret = 0;	if (instr->addr & (mtd->erasesize - 1))		return -EINVAL;	if (instr->len & (mtd->erasesize -1))		return -EINVAL;	if ((instr->len + instr->addr) > mtd->size)		return -EINVAL;	chipnum = instr->addr >> cfi->chipshift;	adr = instr->addr - (chipnum << cfi->chipshift);	len = instr->len;	while(len) {		ret = do_erase_1_by_16_oneblock(map, &cfi->chips[chipnum], adr);				if (ret)			return ret;		adr += mtd->erasesize;		len -= mtd->erasesize;		if (adr >> cfi->chipshift) {			adr = 0;			chipnum++;						if (chipnum >= cfi->numchips)			break;		}	}			if (instr->callback)		instr->callback(instr);		return 0;}static void cfi_intelext_sync (struct mtd_info *mtd){	struct map_info *map = mtd->priv;	struct cfi_private *cfi = map->fldrv_priv;	int i;	struct flchip *chip;	int ret = 0;	DECLARE_WAITQUEUE(wait, current);	for (i=0; !ret && i<cfi->numchips; i++) {		chip = &cfi->chips[i];	retry:		spin_lock_bh(chip->mutex);		switch(chip->state) {		case FL_READY:		case FL_STATUS:		case FL_CFI_QUERY:		case FL_JEDEC_QUERY:			chip->oldstate = chip->state;			chip->state = FL_SYNCING;			/* No need to wake_up() on this state change - 			 * as the whole point is that nobody can do anything			 * with the chip now anyway.			 */			spin_unlock_bh(chip->mutex);			break;		default:			/* Not an idle state */			add_wait_queue(&chip->wq, &wait);						spin_unlock_bh(chip->mutex);			schedule();						remove_wait_queue(&chip->wq, &wait);			goto retry;		}	}	/* Unlock the chips again */	for (i--; i >=0; i--) {		chip = &cfi->chips[i];		spin_lock_bh(chip->mutex);				if (chip->state == FL_SYNCING) {			chip->state = chip->oldstate;			wake_up(&chip->wq);		}		spin_unlock_bh(chip->mutex);	}}static int cfi_intelext_suspend(struct mtd_info *mtd){	struct map_info *map = mtd->priv;	struct cfi_private *cfi = map->fldrv_priv;	int i;	struct flchip *chip;	int ret = 0;	for (i=0; !ret && i<cfi->numchips; i++) {		chip = &cfi->chips[i];		spin_lock_bh(chip->mutex);		switch(chip->state) {		case FL_READY:		case FL_STATUS:		case FL_CFI_QUERY:		case FL_JEDEC_QUERY:			chip->oldstate = chip->state;			chip->state = FL_PM_SUSPENDED;			/* No need to wake_up() on this state change - 			 * as the whole point is that nobody can do anything			 * with the chip now anyway.			 */			spin_unlock_bh(chip->mutex);			break;		default:			ret = -EAGAIN;			break;		}	}	/* Unlock the chips again */	for (i--; i >=0; i--) {		chip = &cfi->chips[i];		spin_lock_bh(chip->mutex);				if (chip->state == FL_PM_SUSPENDED) {			chip->state = chip->oldstate;			wake_up(&chip->wq);		}		spin_unlock_bh(chip->mutex);	}		return ret;}static void cfi_intelext_resume(struct mtd_info *mtd){	struct map_info *map = mtd->priv;	struct cfi_private *cfi = map->fldrv_priv;	int i;	struct flchip *chip;	for (i=0; i<cfi->numchips; i++) {			chip = &cfi->chips[i];		spin_lock_bh(chip->mutex);				if (chip->state == FL_PM_SUSPENDED) {			chip->state = chip->oldstate;			wake_up(&chip->wq);		}		else			printk("Argh. Chip not in PM_SUSPENDED state upon resume()\n");		spin_unlock_bh(chip->mutex);	}}static void cfi_intelext_destroy(struct mtd_info *mtd){	struct map_info *map = mtd->priv;	struct cfi_private *cfi = map->fldrv_priv;	kfree(cfi->cmdset_priv);	inter_module_put(cfi->im_name);	kfree(cfi);}static int __init cfi_intelext_init(void){	inter_module_register(im_name, THIS_MODULE, &cfi_cmdset_0001);	return 0;}static void __exit cfi_intelext_exit(void){	inter_module_unregister(im_name);}module_init(cfi_intelext_init);module_exit(cfi_intelext_exit);

⌨️ 快捷键说明

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