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

📄 nandsim.c

📁 老版本的mtd-snap
💻 C
📖 第 1 页 / 共 4 页
字号:
			if (ns->regs.row + 1 < ns->geom.pgnum)				ns->regs.row += 1;			NS_DBG("read_byte: switch to the next page (%#x)\n", ns->regs.row);			do_state_action(ns, ACTION_CPY);		}		else if (NS_STATE(ns->nxstate) == STATE_READY)			switch_state(ns);			}		return outb;}static voidns_nand_write_byte(struct mtd_info *mtd, u_char byte){        struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv;		/* Sanity and correctness checks */	if (!ns->lines.ce) {		NS_ERR("write_byte: chip is disabled, ignore write\n");		return;	}	if (ns->lines.ale && ns->lines.cle) {		NS_ERR("write_byte: ALE and CLE pins are high simultaneously, ignore write\n");		return;	}				if (ns->lines.cle == 1) {		/*		 * The byte written is a command.		 */		if (byte == NAND_CMD_RESET) {			NS_LOG("reset chip\n");			switch_to_ready_state(ns, NS_STATUS_OK(ns));			return;		}		/* 		 * Chip might still be in STATE_DATAOUT		 * (if OPT_AUTOINCR feature is supported), STATE_DATAOUT_STATUS or		 * STATE_DATAOUT_STATUS_M state. If so, switch state.		 */		if (NS_STATE(ns->state) == STATE_DATAOUT_STATUS			|| NS_STATE(ns->state) == STATE_DATAOUT_STATUS_M			|| ((ns->options & OPT_AUTOINCR) && NS_STATE(ns->state) == STATE_DATAOUT))			switch_state(ns);		/* Check if chip is expecting command */		if (NS_STATE(ns->nxstate) != STATE_UNKNOWN && !(ns->nxstate & STATE_CMD_MASK)) {			/*			 * We are in situation when something else (not command)			 * was expected but command was input. In this case ignore			 * previous command(s)/state(s) and accept the last one.			 */			NS_WARN("write_byte: command (%#x) wasn't expected, expected state is %s, "				"ignore previous states\n", (uint)byte, get_state_name(ns->nxstate));			switch_to_ready_state(ns, NS_STATUS_FAILED(ns));		}				/* Check that the command byte is correct */		if (check_command(byte)) {			NS_ERR("write_byte: unknown command %#x\n", (uint)byte);			return;		}				NS_DBG("command byte corresponding to %s state accepted\n",			get_state_name(get_state_by_command(byte)));		ns->regs.command = byte;		switch_state(ns);	} else if (ns->lines.ale == 1) {		/*		 * The byte written is an address.		 */		if (NS_STATE(ns->nxstate) == STATE_UNKNOWN) {			NS_DBG("write_byte: operation isn't known yet, identify it\n");			if (find_operation(ns, 1) < 0)				return;						if ((ns->state & ACTION_MASK) && do_state_action(ns, ns->state) < 0) {				switch_to_ready_state(ns, NS_STATUS_FAILED(ns));				return;			}							ns->regs.count = 0;			switch (NS_STATE(ns->nxstate)) {				case STATE_ADDR_PAGE:					ns->regs.num = ns->geom.pgaddrbytes;					break;				case STATE_ADDR_SEC:					ns->regs.num = ns->geom.secaddrbytes;					break;				case STATE_ADDR_ZERO:					ns->regs.num = 1;					break;				default:					BUG();			}		}		/* Check that chip is expecting address */		if (!(ns->nxstate & STATE_ADDR_MASK)) {			NS_ERR("write_byte: address (%#x) isn't expected, expected state is %s, "				"switch to STATE_READY\n", (uint)byte, get_state_name(ns->nxstate));			switch_to_ready_state(ns, NS_STATUS_FAILED(ns));			return;		}				/* Check if this is expected byte */		if (ns->regs.count == ns->regs.num) {			NS_ERR("write_byte: no more address bytes expected\n");			switch_to_ready_state(ns, NS_STATUS_FAILED(ns));			return;		}		accept_addr_byte(ns, byte);		ns->regs.count += 1;		NS_DBG("write_byte: address byte %#x was accepted (%d bytes input, %d expected)\n",				(uint)byte, ns->regs.count, ns->regs.num);		if (ns->regs.count == ns->regs.num) {			NS_DBG("address (%#x, %#x) is accepted\n", ns->regs.row, ns->regs.column);			switch_state(ns);		}			} else {		/*		 * The byte written is an input data.		 */				/* Check that chip is expecting data input */		if (!(ns->state & STATE_DATAIN_MASK)) {			NS_ERR("write_byte: data input (%#x) isn't expected, state is %s, "				"switch to %s\n", (uint)byte,				get_state_name(ns->state), get_state_name(STATE_READY));			switch_to_ready_state(ns, NS_STATUS_FAILED(ns));			return;		}		/* Check if this is expected byte */		if (ns->regs.count == ns->regs.num) {			NS_WARN("write_byte: %u input bytes has already been accepted, ignore write\n",					ns->regs.num);			return;		}		if (ns->busw == 8) {			ns->buf.byte[ns->regs.count] = byte;			ns->regs.count += 1;		} else {			ns->buf.word[ns->regs.count >> 1] = cpu_to_le16((uint16_t)byte);			ns->regs.count += 2;		}	}	return;}static intns_device_ready(struct mtd_info *mtd){	NS_DBG("device_ready\n");	return 1;}static uint16_tns_nand_read_word(struct mtd_info *mtd){	struct nand_chip *chip = (struct nand_chip *)mtd->priv;	NS_DBG("read_word\n");		return chip->read_byte(mtd) | (chip->read_byte(mtd) << 8);}static voidns_nand_write_word(struct mtd_info *mtd, uint16_t word){	struct nand_chip *chip = (struct nand_chip *)mtd->priv;		NS_DBG("write_word\n");		chip->write_byte(mtd, word & 0xFF);	chip->write_byte(mtd, word >> 8);}static void ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len){        struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv;	/* Check that chip is expecting data input */	if (!(ns->state & STATE_DATAIN_MASK)) {		NS_ERR("write_buf: data input isn't expected, state is %s, "			"switch to STATE_READY\n", get_state_name(ns->state));		switch_to_ready_state(ns, NS_STATUS_FAILED(ns));		return;	}	/* Check if these are expected bytes */	if (ns->regs.count + len > ns->regs.num) {		NS_ERR("write_buf: too many input bytes\n");		switch_to_ready_state(ns, NS_STATUS_FAILED(ns));		return;	}	memcpy(ns->buf.byte + ns->regs.count, buf, len);	ns->regs.count += len;		if (ns->regs.count == ns->regs.num) {		NS_DBG("write_buf: %d bytes were written\n", ns->regs.count);	}}static void ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len){        struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv;	/* Sanity and correctness checks */	if (!ns->lines.ce) {		NS_ERR("read_buf: chip is disabled\n");		return;	}	if (ns->lines.ale || ns->lines.cle) {		NS_ERR("read_buf: ALE or CLE pin is high\n");		return;	}	if (!(ns->state & STATE_DATAOUT_MASK)) {		NS_WARN("read_buf: unexpected data output cycle, current state is %s\n",			get_state_name(ns->state));		return;	}	if (NS_STATE(ns->state) != STATE_DATAOUT) {		int i;		for (i = 0; i < len; i++)			buf[i] = ((struct nand_chip *)mtd->priv)->read_byte(mtd);		return;	}	/* Check if these are expected bytes */	if (ns->regs.count + len > ns->regs.num) {		NS_ERR("read_buf: too many bytes to read\n");		switch_to_ready_state(ns, NS_STATUS_FAILED(ns));		return;	}	memcpy(buf, ns->buf.byte + ns->regs.count, len);	ns->regs.count += len;		if (ns->regs.count == ns->regs.num) {		if ((ns->options & OPT_AUTOINCR) && NS_STATE(ns->state) == STATE_DATAOUT) {			ns->regs.count = 0;			if (ns->regs.row + 1 < ns->geom.pgnum)				ns->regs.row += 1;			NS_DBG("read_buf: switch to the next page (%#x)\n", ns->regs.row);			do_state_action(ns, ACTION_CPY);		}		else if (NS_STATE(ns->nxstate) == STATE_READY)			switch_state(ns);	}		return;}static int ns_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len){	ns_nand_read_buf(mtd, (u_char *)&ns_verify_buf[0], len);	if (!memcmp(buf, &ns_verify_buf[0], len)) {		NS_DBG("verify_buf: the buffer is OK\n");		return 0;	} else {		NS_DBG("verify_buf: the buffer is wrong\n");		return -EFAULT;	}}/* * Module initialization function */int __init ns_init_module(void){	struct nand_chip *chip;	struct nandsim *nand;	int retval = -ENOMEM;	if (bus_width != 8 && bus_width != 16) {		NS_ERR("wrong bus width (%d), use only 8 or 16\n", bus_width);		return -EINVAL;	}		/* Allocate and initialize mtd_info, nand_chip and nandsim structures */	nsmtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip)				+ sizeof(struct nandsim), GFP_KERNEL);	if (!nsmtd) {		NS_ERR("unable to allocate core structures.\n");		return -ENOMEM;	}	memset(nsmtd, 0, sizeof(struct mtd_info) + sizeof(struct nand_chip) +			sizeof(struct nandsim));	chip        = (struct nand_chip *)(nsmtd + 1);        nsmtd->priv = (void *)chip;	nand        = (struct nandsim *)(chip + 1);	chip->priv  = (void *)nand;		/*	 * Register simulator's callbacks.	 */	chip->hwcontrol  = ns_hwcontrol;	chip->read_byte  = ns_nand_read_byte;	chip->dev_ready  = ns_device_ready;	chip->write_byte = ns_nand_write_byte;	chip->write_buf  = ns_nand_write_buf;	chip->read_buf   = ns_nand_read_buf;	chip->verify_buf = ns_nand_verify_buf;	chip->write_word = ns_nand_write_word;	chip->read_word  = ns_nand_read_word;	chip->eccmode    = NAND_ECC_SOFT;	chip->options   |= NAND_SKIP_BBTSCAN;	/* 	 * Perform minimum nandsim structure initialization to handle	 * the initial ID read command correctly 	 */	if (third_id_byte != 0xFF || fourth_id_byte != 0xFF)		nand->geom.idbytes = 4;	else		nand->geom.idbytes = 2;	nand->regs.status = NS_STATUS_OK(nand);	nand->nxstate = STATE_UNKNOWN;	nand->options |= OPT_PAGE256; /* temporary value */	nand->ids[0] = first_id_byte;	nand->ids[1] = second_id_byte;	nand->ids[2] = third_id_byte;	nand->ids[3] = fourth_id_byte;	if (bus_width == 16) {		nand->busw = 16;		chip->options |= NAND_BUSWIDTH_16;	}	if ((retval = nand_scan(nsmtd, 1)) != 0) {		NS_ERR("can't register NAND Simulator\n");		if (retval > 0)			retval = -ENXIO;		goto error;	}	if ((retval = init_nandsim(nsmtd)) != 0) {		NS_ERR("scan_bbt: can't initialize the nandsim structure\n");		goto error;	}		if ((retval = nand_default_bbt(nsmtd)) != 0) {		free_nandsim(nand);		goto error;	}	/* Register NAND as one big partition */	add_mtd_partitions(nsmtd, &nand->part, 1);        return 0;error:	kfree(nsmtd);	return retval;}module_init(ns_init_module);/* * Module clean-up function */static void __exit ns_cleanup_module(void){	struct nandsim *ns = (struct nandsim *)(((struct nand_chip *)nsmtd->priv)->priv);	free_nandsim(ns);    /* Free nandsim private resources */	nand_release(nsmtd); /* Unregisterd drived */	kfree(nsmtd);        /* Free other structures */}module_exit(ns_cleanup_module);MODULE_LICENSE ("GPL");MODULE_AUTHOR ("Artem B. Bityuckiy");MODULE_DESCRIPTION ("The NAND flash simulator");

⌨️ 快捷键说明

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