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

📄 nandsim.c

📁 老版本的mtd-snap
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * NAND flash simulator. * * Author: Artem B. Bityuckiy <dedekind@oktetlabs.ru>, <dedekind@infradead.org> * * Copyright (C) 2004 Nokia Corporation  * * Note: NS means "NAND Simulator". * Note: Input means input TO flash chip, output means output FROM chip. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2, or (at your option) any later * version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA * * $Id: nandsim.c,v 1.11 2005/05/23 12:51:04 dedekind Exp $ */#include <linux/config.h>#include <linux/init.h>#include <linux/types.h>#include <linux/module.h>#include <linux/moduleparam.h>#include <linux/vmalloc.h>#include <linux/slab.h>#include <linux/errno.h>#include <linux/string.h>#include <linux/mtd/mtd.h>#include <linux/mtd/nand.h>#include <linux/mtd/partitions.h>#include <linux/delay.h>#ifdef CONFIG_NS_ABS_POS#include <asm/io.h>#endif#define CONFIG_NANDSIM_FIRST_ID_BYTE        CONFIG_MTD_NAND_NANDSIM_FIRST_ID#define CONFIG_NANDSIM_SECOND_ID_BYTE       CONFIG_MTD_NAND_NANDSIM_SECOND_ID#define CONFIG_NANDSIM_THIRD_ID_BYTE        CONFIG_MTD_NAND_NANDSIM_THIRD_ID#define CONFIG_NANDSIM_FOURTH_ID_BYTE       CONFIG_MTD_NAND_NANDSIM_FOURTH_ID#ifndef CONFIG_MTD_NAND_NANDSIM_ACCESS_DELAY#  define CONFIG_MTD_NAND_NANDSIM_ACCESS_DELAY   25#endif#ifndef CONFIG_MTD_NAND_NANDSIM_PROGRAM_DELAY#  define CONFIG_MTD_NAND_NANDSIM_PROGRAM_DELAY  200#endif#ifndef CONFIG_MTD_NAND_NANDSIM_ERASE_DELAY#  define CONFIG_MTD_NAND_NANDSIM_ERASE_DELAY    2#endif#ifndef CONFIG_MTD_NAND_NANDSIM_OUTPUT_CYCLE#  define CONFIG_MTD_NAND_NANDSIM_OUTPUT_CYCLE   40#endif#ifndef CONFIG_MTD_NAND_NANDSIM_INPUT_CYCLE#  define CONFIG_MTD_NAND_NANDSIM_INPUT_CYCLE    50#endif#ifdef CONFIG_MTD_NAND_NANDSIM_16BIT_BUS#  define CONFIG_NANDSIM_BUS_WIDTH      16#else#  define CONFIG_NANDSIM_BUS_WIDTH      8#endif#ifndef CONFIG_MTD_NAND_NANDSIM_DELAY#  define CONFIG_MTD_NAND_NANDSIM_DELAY 0#else#  undef CONFIG_MTD_NAND_NANDSIM_DELAY#  define CONFIG_MTD_NAND_NANDSIM_DELAY 1#endif#ifndef CONFIG_MTD_NAND_NANDSIM_LOG#  define CONFIG_MTD_NAND_NANDSIM_LOG   0#else#  undef CONFIG_MTD_NAND_NANDSIM_LOG#  define CONFIG_MTD_NAND_NANDSIM_LOG   1#endif#ifndef CONFIG_MTD_NAND_NANDSIM_DEBUG#  define CONFIG_MTD_NAND_NANDSIM_DEBUG 0#else#  undef CONFIG_MTD_NAND_NANDSIM_DEBUG#  define CONFIG_MTD_NAND_NANDSIM_DEBUG 1#endifstatic uint first_id_byte  = CONFIG_NANDSIM_FIRST_ID_BYTE;static uint second_id_byte = CONFIG_NANDSIM_SECOND_ID_BYTE;static uint third_id_byte  = CONFIG_NANDSIM_THIRD_ID_BYTE;static uint fourth_id_byte = CONFIG_NANDSIM_FOURTH_ID_BYTE;static uint access_delay   = CONFIG_MTD_NAND_NANDSIM_ACCESS_DELAY;static uint programm_delay = CONFIG_MTD_NAND_NANDSIM_PROGRAM_DELAY;static uint erase_delay    = CONFIG_MTD_NAND_NANDSIM_ERASE_DELAY;static uint output_cycle   = CONFIG_MTD_NAND_NANDSIM_OUTPUT_CYCLE;static uint input_cycle    = CONFIG_MTD_NAND_NANDSIM_INPUT_CYCLE;static uint bus_width      = CONFIG_NANDSIM_BUS_WIDTH;static uint do_delays      = CONFIG_MTD_NAND_NANDSIM_DELAY;static uint log            = CONFIG_MTD_NAND_NANDSIM_LOG;static uint dbg            = CONFIG_MTD_NAND_NANDSIM_DEBUG;module_param(first_id_byte,  uint, 0400);module_param(second_id_byte, uint, 0400);module_param(third_id_byte,  uint, 0400);module_param(fourth_id_byte, uint, 0400);module_param(access_delay,   uint, 0400);module_param(programm_delay, uint, 0400);module_param(erase_delay,    uint, 0400);module_param(output_cycle,   uint, 0400);module_param(input_cycle,    uint, 0400);module_param(bus_width,      uint, 0400);module_param(do_delays,      uint, 0400);module_param(log,            uint, 0400);module_param(dbg,            uint, 0400);MODULE_PARM_DESC(first_id_byte,  "The fist byte returned by NAND Flash 'read ID' command (manufaturer ID)");MODULE_PARM_DESC(second_id_byte, "The second byte returned by NAND Flash 'read ID' command (chip ID)");MODULE_PARM_DESC(third_id_byte,  "The third byte returned by NAND Flash 'read ID' command");MODULE_PARM_DESC(fourth_id_byte, "The fourth byte returned by NAND Flash 'read ID' command");MODULE_PARM_DESC(access_delay,   "Initial page access delay (microiseconds)");MODULE_PARM_DESC(programm_delay, "Page programm delay (microseconds");MODULE_PARM_DESC(erase_delay,    "Sector erase delay (milliseconds)");MODULE_PARM_DESC(output_cycle,   "Word output (from flash) time (nanoseconds)");MODULE_PARM_DESC(input_cycle,    "Word input (to flash) time (nanoseconds)");MODULE_PARM_DESC(bus_width,      "Chip's bus width (8- or 16-bit)");MODULE_PARM_DESC(do_delays,      "Simulate NAND delays using busy-waits if not zero");MODULE_PARM_DESC(log,            "Perform logging if not zero");MODULE_PARM_DESC(dbg,            "Output debug information if not zero");/* The largest possible page size */#define NS_LARGEST_PAGE_SIZE	2048	/* The prefix for simulator output */#define NS_OUTPUT_PREFIX "[nandsim]"/* Simulator's output macros (logging, debugging, warning, error) */#define NS_LOG(args...) \	do { if (log) printk(KERN_DEBUG NS_OUTPUT_PREFIX " log: " args); } while(0)#define NS_DBG(args...) \	do { if (dbg) printk(KERN_DEBUG NS_OUTPUT_PREFIX " debug: " args); } while(0)#define NS_WARN(args...) \	do { printk(KERN_WARNING NS_OUTPUT_PREFIX " warnig: " args); } while(0)#define NS_ERR(args...) \	do { printk(KERN_ERR NS_OUTPUT_PREFIX " errorr: " args); } while(0)/* Busy-wait delay macros (microseconds, milliseconds) */#define NS_UDELAY(us) \        do { if (do_delays) udelay(us); } while(0)#define NS_MDELAY(us) \        do { if (do_delays) mdelay(us); } while(0)	/* Is the nandsim structure initialized ? */#define NS_IS_INITIALIZED(ns) ((ns)->geom.totsz != 0)/* Good operation completion status */#define NS_STATUS_OK(ns) (NAND_STATUS_READY | (NAND_STATUS_WP * ((ns)->lines.wp == 0)))/* Operation failed completion status */#define NS_STATUS_FAILED(ns) (NAND_STATUS_FAIL | NS_STATUS_OK(ns)) /* Calculate the page offset in flash RAM image by (row, column) address */#define NS_RAW_OFFSET(ns) \	(((ns)->regs.row << (ns)->geom.pgshift) + ((ns)->regs.row * (ns)->geom.oobsz) + (ns)->regs.column)	/* Calculate the OOB offset in flash RAM image by (row, column) address */#define NS_RAW_OFFSET_OOB(ns) (NS_RAW_OFFSET(ns) + ns->geom.pgsz)/* After a command is input, the simulator goes to one of the following states */#define STATE_CMD_READ0        0x00000001 /* read data from the beginning of page */#define STATE_CMD_READ1        0x00000002 /* read data from the second half of page */#define STATE_CMD_READSTART    0x00000003 /* read data second command (large page devices) */#define STATE_CMD_PAGEPROG     0x00000004 /* start page programm */#define STATE_CMD_READOOB      0x00000005 /* read OOB area */#define STATE_CMD_ERASE1       0x00000006 /* sector erase first command */#define STATE_CMD_STATUS       0x00000007 /* read status */#define STATE_CMD_STATUS_M     0x00000008 /* read multi-plane status (isn't implemented) */#define STATE_CMD_SEQIN        0x00000009 /* sequential data imput */#define STATE_CMD_READID       0x0000000A /* read ID */#define STATE_CMD_ERASE2       0x0000000B /* sector erase second command */#define STATE_CMD_RESET        0x0000000C /* reset */#define STATE_CMD_MASK         0x0000000F /* command states mask *//* After an addres is input, the simulator goes to one of these states */#define STATE_ADDR_PAGE        0x00000010 /* full (row, column) address is accepted */#define STATE_ADDR_SEC         0x00000020 /* sector address was accepted */#define STATE_ADDR_ZERO        0x00000030 /* one byte zero address was accepted */#define STATE_ADDR_MASK        0x00000030 /* address states mask *//* Durind data input/output the simulator is in these states */#define STATE_DATAIN           0x00000100 /* waiting for data input */#define STATE_DATAIN_MASK      0x00000100 /* data input states mask */#define STATE_DATAOUT          0x00001000 /* waiting for page data output */#define STATE_DATAOUT_ID       0x00002000 /* waiting for ID bytes output */#define STATE_DATAOUT_STATUS   0x00003000 /* waiting for status output */#define STATE_DATAOUT_STATUS_M 0x00004000 /* waiting for multi-plane status output */#define STATE_DATAOUT_MASK     0x00007000 /* data output states mask *//* Previous operation is done, ready to accept new requests */#define STATE_READY            0x00000000/* This state is used to mark that the next state isn't known yet */#define STATE_UNKNOWN          0x10000000/* Simulator's actions bit masks */#define ACTION_CPY       0x00100000 /* copy page/OOB to the internal buffer */#define ACTION_PRGPAGE   0x00200000 /* programm the internal buffer to flash */#define ACTION_SECERASE  0x00300000 /* erase sector */#define ACTION_ZEROOFF   0x00400000 /* don't add any offset to address */#define ACTION_HALFOFF   0x00500000 /* add to address half of page */#define ACTION_OOBOFF    0x00600000 /* add to address OOB offset */#define ACTION_MASK      0x00700000 /* action mask */#define NS_OPER_NUM      12 /* Number of operations supported by the simulator */#define NS_OPER_STATES   6  /* Maximum number of states in operation */#define OPT_ANY          0xFFFFFFFF /* any chip supports this operation */#define OPT_PAGE256      0x00000001 /* 256-byte  page chips */#define OPT_PAGE512      0x00000002 /* 512-byte  page chips */#define OPT_PAGE2048     0x00000008 /* 2048-byte page chips */#define OPT_SMARTMEDIA   0x00000010 /* SmartMedia technology chips */#define OPT_AUTOINCR     0x00000020 /* page number auto inctimentation is possible */#define OPT_PAGE512_8BIT 0x00000040 /* 512-byte page chips with 8-bit bus width */#define OPT_LARGEPAGE    (OPT_PAGE2048) /* 2048-byte page chips */#define OPT_SMALLPAGE    (OPT_PAGE256  | OPT_PAGE512)  /* 256 and 512-byte page chips *//* Remove action bits ftom state */#define NS_STATE(x) ((x) & ~ACTION_MASK)	/*  * Maximum previous states which need to be saved. Currently saving is * only needed for page programm operation with preceeded read command * (which is only valid for 512-byte pages). */#define NS_MAX_PREVSTATES 1/*  * The structure which describes all the internal simulator data. */struct nandsim {	struct mtd_partition part;	uint busw;              /* flash chip bus width (8 or 16) */	u_char ids[4];          /* chip's ID bytes */	uint32_t options;       /* chip's characteristic bits */	uint32_t state;         /* current chip state */	uint32_t nxstate;       /* next expected state */		uint32_t *op;           /* current operation, NULL operations isn't known yet  */	uint32_t pstates[NS_MAX_PREVSTATES]; /* previous states */	uint16_t npstates;      /* number of previous states saved */	uint16_t stateidx;      /* current state index */	/* The simulated NAND flash image */	union flash_media {		u_char *byte;		uint16_t    *word;	} mem;	/* Internal buffer of page + OOB size bytes */	union internal_buffer {		u_char *byte;    /* for byte access */		uint16_t *word;  /* for 16-bit word access */	} buf;	/* NAND flash "geometry" */	struct nandsin_geometry {		uint32_t totsz;     /* total flash size, bytes */		uint32_t secsz;     /* flash sector (erase block) size, bytes */		uint pgsz;          /* NAND flash page size, bytes */		uint oobsz;         /* page OOB area size, bytes */		uint32_t totszoob;  /* total flash size including OOB, bytes */		uint pgszoob;       /* page size including OOB , bytes*/		uint secszoob;      /* sector size including OOB, bytes */		uint pgnum;         /* total number of pages */		uint pgsec;         /* number of pages per sector */		uint secshift;      /* bits number in sector size */		uint pgshift;       /* bits number in page size */		uint oobshift;      /* bits number in OOB size */		uint pgaddrbytes;   /* bytes per page address */		uint secaddrbytes;  /* bytes per sector address */		uint idbytes;       /* the number ID bytes that this chip outputs */	} geom;	/* NAND flash internal registers */	struct nandsim_regs {		unsigned command; /* the command register */		u_char   status;  /* the status register */		uint     row;     /* the page number */		uint     column;  /* the offset within page */		uint     count;   /* internal counter */		uint     num;     /* number of bytes which must be processed */		uint     off;     /* fixed page offset */	} regs;	/* NAND flash lines state */        struct ns_lines_status {                int ce;  /* chip Enable */                int cle; /* command Latch Enable */                int ale; /* address Latch Enable */                int wp;  /* write Protect */        } lines;};/* * Operations array. To perform any operation the simulator must pass * through the correspondent states chain. */static struct nandsim_operations {	uint32_t reqopts;  /* options which are required to perform the operation */	uint32_t states[NS_OPER_STATES]; /* operation's states */} ops[NS_OPER_NUM] = {	/* Read page + OOB from the beginning */	{OPT_SMALLPAGE, {STATE_CMD_READ0 | ACTION_ZEROOFF, STATE_ADDR_PAGE | ACTION_CPY,			STATE_DATAOUT, STATE_READY}},	/* Read page + OOB from the second half */	{OPT_PAGE512_8BIT, {STATE_CMD_READ1 | ACTION_HALFOFF, STATE_ADDR_PAGE | ACTION_CPY,			STATE_DATAOUT, STATE_READY}},	/* Read OOB */	{OPT_SMALLPAGE, {STATE_CMD_READOOB | ACTION_OOBOFF, STATE_ADDR_PAGE | ACTION_CPY,			STATE_DATAOUT, STATE_READY}},	/* Programm page starting from the beginning */	{OPT_ANY, {STATE_CMD_SEQIN, STATE_ADDR_PAGE, STATE_DATAIN,			STATE_CMD_PAGEPROG | ACTION_PRGPAGE, STATE_READY}},	/* Programm page starting from the beginning */	{OPT_SMALLPAGE, {STATE_CMD_READ0, STATE_CMD_SEQIN | ACTION_ZEROOFF, STATE_ADDR_PAGE,			      STATE_DATAIN, STATE_CMD_PAGEPROG | ACTION_PRGPAGE, STATE_READY}},	/* Programm page starting from the second half */	{OPT_PAGE512, {STATE_CMD_READ1, STATE_CMD_SEQIN | ACTION_HALFOFF, STATE_ADDR_PAGE,			      STATE_DATAIN, STATE_CMD_PAGEPROG | ACTION_PRGPAGE, STATE_READY}},	/* Programm OOB */	{OPT_SMALLPAGE, {STATE_CMD_READOOB, STATE_CMD_SEQIN | ACTION_OOBOFF, STATE_ADDR_PAGE,			      STATE_DATAIN, STATE_CMD_PAGEPROG | ACTION_PRGPAGE, STATE_READY}},	/* Erase sector */	{OPT_ANY, {STATE_CMD_ERASE1, STATE_ADDR_SEC, STATE_CMD_ERASE2 | ACTION_SECERASE, STATE_READY}},	/* Read status */	{OPT_ANY, {STATE_CMD_STATUS, STATE_DATAOUT_STATUS, STATE_READY}},	/* Read multi-plane status */	{OPT_SMARTMEDIA, {STATE_CMD_STATUS_M, STATE_DATAOUT_STATUS_M, STATE_READY}},	/* Read ID */	{OPT_ANY, {STATE_CMD_READID, STATE_ADDR_ZERO, STATE_DATAOUT_ID, STATE_READY}},	/* Large page devices read page */	{OPT_LARGEPAGE, {STATE_CMD_READ0, STATE_ADDR_PAGE, STATE_CMD_READSTART | ACTION_CPY,			       STATE_DATAOUT, STATE_READY}}};/* MTD structure for NAND controller */static struct mtd_info *nsmtd;static u_char ns_verify_buf[NS_LARGEST_PAGE_SIZE];/* * Initialize the nandsim structure. * * RETURNS: 0 if success, -ERRNO if failure. */static intinit_nandsim(struct mtd_info *mtd){	struct nand_chip *chip = (struct nand_chip *)mtd->priv;	struct nandsim   *ns   = (struct nandsim *)(chip->priv);	int i;	if (NS_IS_INITIALIZED(ns)) {		NS_ERR("init_nandsim: nandsim is already initialized\n");		return -EIO;	}	/* Force mtd to not do delays */	chip->chip_delay = 0;	/* Initialize the NAND flash parameters */	ns->busw = chip->options & NAND_BUSWIDTH_16 ? 16 : 8;	ns->geom.totsz    = mtd->size;	ns->geom.pgsz     = mtd->oobblock;	ns->geom.oobsz    = mtd->oobsize;	ns->geom.secsz    = mtd->erasesize;	ns->geom.pgszoob  = ns->geom.pgsz + ns->geom.oobsz;	ns->geom.pgnum    = ns->geom.totsz / ns->geom.pgsz;	ns->geom.totszoob = ns->geom.totsz + ns->geom.pgnum * ns->geom.oobsz;	ns->geom.secshift = ffs(ns->geom.secsz) - 1;	ns->geom.pgshift  = chip->page_shift;	ns->geom.oobshift = ffs(ns->geom.oobsz) - 1;	ns->geom.pgsec    = ns->geom.secsz / ns->geom.pgsz;	ns->geom.secszoob = ns->geom.secsz + ns->geom.oobsz * ns->geom.pgsec;	ns->options = 0;	if (ns->geom.pgsz == 256) {		ns->options |= OPT_PAGE256;	}	else if (ns->geom.pgsz == 512) {		ns->options |= (OPT_PAGE512 | OPT_AUTOINCR);		if (ns->busw == 8)

⌨️ 快捷键说明

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