Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 10 Mar 2012 02:46:55 +0000 (UTC)
From:      Grzegorz Bernacki <gber@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r232760 - projects/nand/usr.sbin/nandsim
Message-ID:  <201203100246.q2A2ktw0036128@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: gber
Date: Sat Mar 10 02:46:55 2012
New Revision: 232760
URL: http://svn.freebsd.org/changeset/base/232760

Log:
  Add NAND simulator.
  
  The NAND simulator is very simple utility which allows to create ONFI
  compliant device based on given configuration file (simple configuration
  file is provided). NAND Framework creates gnand(4) device for this
  virtual chip which allow to access it (read, write, erase, etc..).
  
  Obtained from: Semihalf
  Supported by:  FreeBSD Foundation, Juniper Networks

Added:
  projects/nand/usr.sbin/nandsim/
  projects/nand/usr.sbin/nandsim/Makefile
  projects/nand/usr.sbin/nandsim/nandsim.8
  projects/nand/usr.sbin/nandsim/nandsim.c
  projects/nand/usr.sbin/nandsim/nandsim_cfgparse.c
  projects/nand/usr.sbin/nandsim/nandsim_cfgparse.h
  projects/nand/usr.sbin/nandsim/nandsim_rcfile.c
  projects/nand/usr.sbin/nandsim/nandsim_rcfile.h
  projects/nand/usr.sbin/nandsim/sample.conf

Added: projects/nand/usr.sbin/nandsim/Makefile
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ projects/nand/usr.sbin/nandsim/Makefile	Sat Mar 10 02:46:55 2012	(r232760)
@@ -0,0 +1,8 @@
+PROG=	nandsim
+SRCS=	nandsim.c nandsim_rcfile.c nandsim_cfgparse.c
+BINDIR=	/usr/sbin
+MAN=nandsim.8
+
+WARNS?=	3
+
+.include <bsd.prog.mk>

Added: projects/nand/usr.sbin/nandsim/nandsim.8
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ projects/nand/usr.sbin/nandsim/nandsim.8	Sat Mar 10 02:46:55 2012	(r232760)
@@ -0,0 +1,215 @@
+.\" Copyright (c) 2010 Semihalf
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.Dd August 10, 2010
+.Dt NANDSIM 8
+.Os
+.Sh NAME
+.Nm nandsim
+.Nd NAND simulator
+.Sh SYNOPSIS
+.Nm
+.Ic status
+.Aq ctrl_no | Fl -all  | Fl a
+.Op Fl v
+.Nm
+.Ic conf
+.Aq filename
+.Nm
+.Ic start
+.Aq ctrl_no
+.Nm
+.Ic mod
+.Aq ctrl_no:cs_no | Fl l Aq loglevel
+.Op Fl p Aq prog_time
+.Op Fl e Aq erase_time
+.Op Fl r Aq read_time
+.Op Fl E Aq error_ratio
+.Op Fl h
+.Nm
+.Ic stop
+.Aq ctrl_no
+.Nm
+.Ic error
+.Aq ctrl_no:cs_no
+.Aq page_num
+.Aq column
+.Aq length
+.Aq pattern
+.Nm
+.Ic bb
+.Aq ctrl_no:cs_no
+.Op blk_num,blk_num2,...
+.Op Fl U
+.Op Fl L
+.Nm
+.Ic freeze
+.Op ctrl_no
+.Nm
+.Ic log
+.Aq ctrl_no | Fl -all  | Fl a
+.Nm
+.Ic stats
+.Aq ctrl_no:cs_no
+.Aq page_num
+.Nm
+.Ic dump
+.Aq ctrl_no:cs_no
+.Aq filename
+.Nm
+.Ic restore
+.Aq ctrl_no:chip_no
+.Aq filename
+.Nm
+.Ic destroy
+.Aq ctrl_no[:cs_no] | Fl -all | Fl a
+.Nm
+.Ic help
+.Op Fl v
+.Sh COMMAND DESCRIPTION
+Controllers and chips are arranged into a simple hierarchy. There can be up to
+4 controllers configured, each with 4 chip select (CS) lines. A given chip is
+connected to one of the chip selects.
+.Pp
+Controllers are specified as
+.Aq ctrl_no ;
+chip selects are specified as
+.Aq cs_no .
+.Bl -tag -width periphlist
+.It Ic status
+Gets controller(s) status. If
+.Fl a
+or
+.Fl -all
+flag is specified - command will print status of every controller
+currently available. Optional flag
+.Fl v
+causes printing complete information about the controller, and all
+chips attached to it.
+.It Ic conf
+Reads simulator configuration from a specified file (this includes
+the simulation "layout" i.e. controllers-chips assignments).
+Configuration changes for an already started simulation require a
+full stop-start cycle in order to take effect i.e.:
+.Pp
+.Bl -column
+.It nandsim stop ...
+.It nandsim destroy ...
+.Pp
+.It << edit config file >>
+.Pp
+.It nandsim conf ...
+.It nandsim start ...
+.El
+.It Ic mod
+Alters simulator parameters on-the-fly. If controller number and CS
+pair is not specified, the general simulator parameters (not
+specific to a controller or a chip) will be modified. Changing
+chip's parameters requires specifying both controller number and CS
+to which the given chip is connected. Parameters which can be
+altered:
+.Pp
+General simulator related:
+.Bl -tag -width flag
+.It Fl l Aq log_level
+change logging level to
+.Aq log_level
+.El
+.Pp
+Chip related:
+.Bl -tag -width flag
+.It Fl p Aq prog_time
+change prog time for specified chip to
+.Aq prog_time
+.It Fl e Aq erase_time
+change erase time for specified chip to
+.Aq erase_time
+.It Fl r Aq read_time
+change read time for specified chip to
+.Aq read_time
+.It Fl E Aq error_ratio
+change error ratio for specified chip to
+.Aq error_ratio .
+Error ratio is a number of errors per million read/write bytes.
+.El
+.Pp
+Additionally, flag
+.Fl h
+will list parameters which can be altered.
+.El
+.Bl -tag -width periphlist
+.It Ic bb
+Marks/unmarks a specified block as bad. To mark/unmark the bad
+condition an a block, the following parameters have to be supplied:
+controller number, CS number, and at least one block number.  It is
+possible to specify multiple blocks, by separating blocks numbers
+with a comma. The following options can be used for the 'bb'
+command:
+.Bl -tag -width flag
+.It Fl U
+unmark the bad previously marked block as bad.
+.It Fl L
+list all blocks marked as bad on a given chip.
+.El
+.It Ic log
+Prints activity log of the specified controller to stdout; if
+controller number is not specifed, logs for all available
+controllers are printed.
+.It Ic stats
+Print statistics of the selected controller, chip and page.
+Statistics includes read count, write count, raw read count, raw
+write count, ECC stats (succeeded corrections, failed correction).
+.It Ic dump
+Dumps a snaphot of a single chip (including data and bad blocks
+information, wearout level) into the file.
+.It Ic restore
+Restores chip state from a dump-file snapshot (produced previously
+with the 'dump' command).
+.It Ic start
+Starts a controller i.e. the simulation.
+.It Ic stop
+Stops an already started controller; if the controller number is not
+supplied, attempts to stop all currently working controllers.
+.It Ic destroy
+Removes existing active chip/controller and its configuration from
+memory and releases the resources. Specifying flag
+.Fl a
+or
+.Fl -all
+causes removal of every chip and controller. Controller must be
+stopped in order to be destroyed.
+.It Ic error
+Directly overwrites a certain number of bytes in the specified page
+at a given offset with a supplied pattern (which mimics the
+corruption of flash contents).
+.It Ic help
+Prints synopsis,
+.Fl v
+gives more verbose output.
+.It Ic freeze
+Stops simulation of given controller (simulates power-loss). All
+commands issues to any chip on this controller are ignored.
+.El
+.Sh AUTHORS
+.An Lukasz Wojcik

Added: projects/nand/usr.sbin/nandsim/nandsim.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ projects/nand/usr.sbin/nandsim/nandsim.c	Sat Mar 10 02:46:55 2012	(r232760)
@@ -0,0 +1,1399 @@
+/*-
+ * Copyright (C) 2009-2012 Semihalf
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Control application for the NAND simulator.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/errno.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <dev/nand/nandsim.h>
+#include <dev/nand/nand_cdev.h>
+
+#include <ctype.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <sysexits.h>
+
+#include "nandsim_cfgparse.h"
+
+#define SIMDEVICE	"/dev/nandsim.ioctl"
+
+#define error(fmt, args...) do { \
+    printf("ERROR: " fmt "\n", ##args); } while (0)
+
+#define warn(fmt, args...) do { \
+    printf("WARNING: " fmt "\n", ##args); } while (0)
+
+#define DEBUG
+#undef DEBUG
+
+#ifdef DEBUG
+#define debug(fmt, args...) do { \
+    printf("NANDSIM_CONF:" fmt "\n", ##args); } while (0)
+#else
+#define debug(fmt, args...) do {} while(0)
+#endif
+
+#define NANDSIM_RAM_LOG_SIZE 16384
+
+#define MSG_NOTRUNNING		"Controller#%d is not running.Please start" \
+    " it first."
+#define MSG_RUNNING		"Controller#%d is already running!"
+#define MSG_CTRLCHIPNEEDED	"You have to specify ctrl_no:cs_no pair!"
+#define MSG_STATUSACQCTRLCHIP	"Could not acquire status for ctrl#%d chip#%d"
+#define MSG_STATUSACQCTRL	"Could not acquire status for ctrl#%d"
+#define MSG_NOCHIP		"There is no such chip configured (chip#%d "\
+    "at ctrl#%d)!"
+
+#define MSG_NOCTRL		"Controller#%d is not configured!"
+#define MSG_NOTCONFIGDCTRLCHIP	"Chip connected to ctrl#%d at cs#%d " \
+    "is not configured."
+
+typedef int (commandfunc_t)(int , char **);
+
+static struct nandsim_command *getcommand(char *arg);
+static int parse_devstring(char *str, int *ctrl, int *cs);
+static void printchip(struct sim_chip *chip, uint8_t verbose);
+static void printctrl(struct sim_ctrl *ctrl);
+static int opendev(int *fd);
+static commandfunc_t cmdstatus;
+static commandfunc_t cmdconf;
+static commandfunc_t cmdstart;
+static commandfunc_t cmdstop;
+static commandfunc_t cmdmod;
+static commandfunc_t cmderror;
+static commandfunc_t cmdbb;
+static commandfunc_t cmdfreeze;
+static commandfunc_t cmdlog;
+static commandfunc_t cmdstats;
+static commandfunc_t cmddump;
+static commandfunc_t cmdrestore;
+static commandfunc_t cmddestroy;
+static commandfunc_t cmdhelp;
+static int checkusage(int argc, int argsreqd, char **argv);
+static int is_chip_created(int ctrl_no, int chip_no, int *created);
+static int is_ctrl_created(int ctrl_no, int *created);
+static int is_ctrl_running(int ctrl_no, int *running);
+static int assert_chip_connected(int ctrl_no, int chip_no);
+static int printstats(int ctrlno, int chipno, uint32_t pageno, int cdevd);
+
+struct nandsim_command {
+	const char	*cmd_name;	/* Command name */
+	commandfunc_t	*commandfunc;	/* Ptr to command function */
+	uint8_t		req_argc;	/* Mandatory arguments count */
+	const char	*usagestring;	/* Usage string */
+};
+
+static struct nandsim_command commands[] = {
+	{"status", cmdstatus, 1,
+	    "status <ctl_no|--all|-a> [-v]\n" },
+	{"conf", cmdconf, 1,
+	    "conf <filename>\n" },
+	{"start", cmdstart, 1,
+	    "start <ctrl_no>\n" },
+	{"mod", cmdmod, 2,
+	    "mod [-l <loglevel>] | <ctl_no:cs_no> [-p <prog_time>]\n"
+	    "\t[-e <erase_time>] [-r <read_time>]\n"
+	    "\t[-E <error_ratio>] | [-h]\n" },
+	{"stop", cmdstop, 1,
+	    "stop <ctrl_no>\n" },
+	{"error", cmderror, 5,
+	    "error <ctrl_no:cs_no> <page_num> <column> <length> <pattern>\n" },
+	{"bb", cmdbb, 2,
+	    "bb <ctl_no:cs_no>  [blk_num1,blk_num2,..] [-U] [-L]\n" },
+	{"freeze", cmdfreeze, 1,
+	    "freeze [ctrl_no]\n" },
+	{"log", cmdlog, 1,
+	    "log <ctrl_no|--all|-a>\n" },
+	{"stats", cmdstats, 2,
+	    "stats <ctrl_no:cs_no> <pagenumber>\n" },
+	{"dump", cmddump, 2,
+	    "dump <ctrl_no:cs_no> <filename>\n" },
+	{"restore", cmdrestore, 2,
+	    "restore <ctrl_no:chip_no> <filename>\n" },
+	{"destroy", cmddestroy, 1,
+	    "destroy <ctrl_no[:cs_no]|--all|-a>\n" },
+	{"help", cmdhelp, 0,
+	    "help [-v]" },
+	{NULL, NULL, 0, NULL},
+};
+
+
+/* Parse command name, and start appropriate function */
+static struct nandsim_command*
+getcommand(char *arg)
+{
+	struct nandsim_command *opts;
+
+	for (opts = commands; (opts != NULL) &&
+	    (opts->cmd_name != NULL); opts++) {
+		if (strcmp(opts->cmd_name, arg) == 0)
+			return (opts);
+	}
+	return (NULL);
+}
+
+/*
+ * Parse given string in format <ctrl_no>:<cs_no>, if possible -- set
+ * ctrl and/or cs, and return 0 (success) or 1 (in case of error).
+ *
+ * ctrl == 0xff && chip == 0xff  : '--all' flag specified
+ * ctrl != 0xff && chip != 0xff  : both ctrl & chip were specified
+ * ctrl != 0xff && chip == 0xff  : only ctrl was specified
+ */
+static int
+parse_devstring(char *str, int *ctrl, int *cs)
+{
+	char *tmpstr;
+	unsigned int num = 0;
+
+	/* Ignore white spaces at the beginning */
+	while (isspace(*str) && (*str != '\0'))
+		str++;
+
+	*ctrl = 0xff;
+	*cs = 0xff;
+	if (strcmp(str, "--all") == 0 ||
+	    strcmp(str, "-a") == 0) {
+		/* if --all or -a is specified, ctl==chip==0xff */
+		debug("CTRL=%d CHIP=%d\n", *ctrl, *cs);
+		return (0);
+	}
+	/* Separate token and try to convert it to int */
+	tmpstr = (char *)strtok(str, ":");
+	if ((tmpstr != NULL) && (*tmpstr != '\0')) {
+		if (convert_arguint(tmpstr, &num) != 0)
+			return (1);
+
+		if (num > MAX_SIM_DEV - 1) {
+			error("Invalid ctrl_no supplied: %s. Valid ctrl_no "
+			    "value must lie between 0 and 3!", tmpstr);
+			return (1);
+		}
+
+		*ctrl = num;
+		tmpstr = (char *)strtok(NULL, ":");
+
+		if ((tmpstr != NULL) && (*tmpstr != '\0')) {
+			if (convert_arguint(tmpstr, &num) != 0)
+				return (1);
+
+			/* Check if chip_no is valid */
+			if (num > MAX_CTRL_CS - 1) {
+				error("Invalid chip_no supplied: %s. Valid "
+				    "chip_no value must lie between 0 and 3!",
+				    tmpstr);
+				return (1);
+			}
+			*cs = num;
+		}
+	} else
+		/* Empty devstring supplied */
+		return (1);
+
+	debug("CTRL=%d CHIP=%d\n", *ctrl, *cs);
+	return (0);
+}
+
+static int
+opendev(int *fd)
+{
+
+	/* Open simulator device. */
+	*fd = open(SIMDEVICE, O_RDWR);
+	if (*fd == -1) {
+		error("Could not open simulator device file (%s)!",
+		    SIMDEVICE);
+		return (EX_OSFILE);
+	}
+	return (EX_OK);
+}
+
+static int
+opencdev(int *cdevd, int ctrl, int chip)
+{
+	char fname[255];
+
+	sprintf(fname, "/dev/nandsim%d.%d", ctrl, chip);
+	*cdevd = open(fname, O_RDWR);
+	if (*cdevd == -1)
+		return (EX_NOINPUT);
+
+	return (EX_OK);
+}
+
+/*
+ * Check if given arguments count match requirements. If no, or
+ * --help (-h) flag is specified -- return 1 (print usage)
+ */
+static int
+checkusage(int gargc, int argsreqd, char **gargv)
+{
+
+	if (gargc < argsreqd + 2 || (gargc >= (argsreqd + 2) &&
+	    (strcmp(gargv[1], "--help") == 0 ||
+	    strcmp(gargv[1], "-h") == 0))) {
+		return (1);
+	} else
+		return (0);
+}
+
+static int
+cmdstatus(int gargc, char **gargv)
+{
+	int chip = 0, ctl = 0, err = 0, fd, idx, idx2, start, stop;
+	uint8_t verbose = 0;
+	struct sim_ctrl ctrlconf;
+	struct sim_chip chipconf;
+
+	err = parse_devstring(gargv[2], &ctl, &chip);
+	if (err) {
+		return (EX_USAGE);
+	} else if (ctl == 0xff) {
+		/* Every controller */
+		start = 0;
+		stop = MAX_SIM_DEV-1;
+	} else {
+		/* Specified controller only */
+		start = ctl;
+		stop = ctl;
+	}
+
+	if (opendev(&fd) != EX_OK)
+		return (EX_OSFILE);
+
+	for (idx = 0; idx < gargc; idx ++)
+		if (strcmp(gargv[idx], "-v") == 0 ||
+		    strcmp(gargv[idx], "--verbose") == 0)
+			verbose = 1;
+
+	for (idx = start; idx <= stop; idx++) {
+		ctrlconf.num = idx;
+		err = ioctl(fd, NANDSIM_STATUS_CTRL, &ctrlconf);
+		if (err) {
+			err = EX_SOFTWARE;
+			error(MSG_STATUSACQCTRL, idx);
+			continue;
+		}
+
+		printctrl(&ctrlconf);
+
+		for (idx2 = 0; idx2 < MAX_CTRL_CS; idx2++) {
+			chipconf.num = idx2;
+			chipconf.ctrl_num = idx;
+
+			err = ioctl(fd, NANDSIM_STATUS_CHIP, &chipconf);
+			if (err) {
+				err = EX_SOFTWARE;
+				error(MSG_STATUSACQCTRL, idx);
+				continue;
+			}
+
+			printchip(&chipconf, verbose);
+		}
+	}
+	close(fd);
+	return(EX_OK);
+}
+
+static int
+cmdconf(int gargc, char **gargv)
+{
+	int err;
+
+	err = parse_config(gargv[2], SIMDEVICE);
+	if (err)
+		return (EX_DATAERR);
+
+	return (EX_OK);
+}
+
+static int
+cmdstart(int gargc, char **gargv)
+{
+	int chip = 0, ctl = 0, err = 0, fd, running, state;
+
+	err = parse_devstring(gargv[2], &ctl, &chip);
+	if (err)
+		return (EX_USAGE);
+
+	err = is_ctrl_created(ctl, &state);
+	if (err) {
+		return (EX_SOFTWARE);
+	} else if (state == 0) {
+		error(MSG_NOCTRL, ctl);
+		return (EX_SOFTWARE);
+	}
+
+	err = is_ctrl_running(ctl, &running);
+	if (err)
+		return (EX_SOFTWARE);
+
+	if (running) {
+		warn(MSG_RUNNING, ctl);
+	} else {
+		if (opendev(&fd) != EX_OK)
+			return (EX_OSFILE);
+
+		err = ioctl(fd, NANDSIM_START_CTRL, &ctl);
+		close(fd);
+		if (err) {
+			error("Cannot start controller#%d", ctl);
+			err = EX_SOFTWARE;
+		}
+	}
+	return (err);
+}
+
+static int
+cmdstop(int gargc, char **gargv)
+{
+	int chip = 0, ctl = 0, err = 0, fd, running;
+
+	err = parse_devstring(gargv[2], &ctl, &chip);
+	if (err)
+		return (EX_USAGE);
+
+	err = is_ctrl_running(ctl, &running);
+	if (err)
+		return (EX_SOFTWARE);
+
+	if (!running) {
+		error(MSG_NOTRUNNING, ctl);
+	} else {
+		if (opendev(&fd) != EX_OK)
+			return (EX_OSFILE);
+
+		err = ioctl(fd, NANDSIM_STOP_CTRL, &ctl);
+		close(fd);
+		if (err) {
+			error("Cannot stop controller#%d", ctl);
+			err = EX_SOFTWARE;
+		}
+	}
+
+	return (err);
+}
+
+static int
+cmdmod(int gargc, char **gargv)
+{
+	int chip, ctl, err = 0, fd = -1, i;
+	struct sim_mod mods;
+
+	if (gargc >= 4) {
+		if (strcmp(gargv[2], "--loglevel") == 0 || strcmp(gargv[2],
+		    "-l") == 0) {
+			/* Set loglevel (ctrl:chip pair independant) */
+			mods.field = SIM_MOD_LOG_LEVEL;
+
+			if (convert_arguint(gargv[3], &mods.new_value) != 0)
+				return (EX_SOFTWARE);
+
+			if (opendev(&fd) != EX_OK)
+				return (EX_OSFILE);
+
+			err = ioctl(fd, NANDSIM_MODIFY, &mods);
+			if (err) {
+				error("simulator parameter %s could not be "
+				    "modified !", gargv[i]);
+				close(fd);
+				return (EX_SOFTWARE);
+			}
+
+			debug("request : loglevel = %d\n", mods.new_value);
+			close(fd);
+			return (EX_OK);
+		}
+	}
+
+	err = parse_devstring(gargv[2], &ctl, &chip);
+	if (err)
+		return (EX_USAGE);
+
+	else if (chip == 0xff) {
+		error(MSG_CTRLCHIPNEEDED);
+		return (EX_USAGE);
+	}
+
+	if (!assert_chip_connected(ctl, chip))
+		return (EX_SOFTWARE);
+
+	if (opendev(&fd) != EX_OK)
+		return (EX_OSFILE);
+
+	/* Findout which flags were passed */
+	for (i = 3; i < gargc; i++) {
+
+		if (convert_arguint(gargv[i+1], &mods.new_value) != 0)
+			continue;
+
+		if (strcmp(gargv[i], "--prog-time") == 0 ||
+		    strcmp(gargv[i], "-p") == 0) {
+
+			mods.field = SIM_MOD_PROG_TIME;
+			debug("request : progtime = %d\n", mods.new_value);
+
+		} else if (strcmp(gargv[i], "--erase-time") == 0 ||
+		    strcmp(gargv[i], "-e") == 0) {
+
+			mods.field = SIM_MOD_ERASE_TIME;
+			debug("request : eraseime = %d\n", mods.new_value);
+
+		} else if (strcmp(gargv[i], "--read-time") == 0 ||
+		    strcmp(gargv[i], "-r") == 0) {
+
+			mods.field = SIM_MOD_READ_TIME;
+			debug("request : read_time = %d\n", mods.new_value);
+
+		} else if (strcmp(gargv[i], "--error-ratio") == 0 ||
+		    strcmp(gargv[i], "-E") == 0) {
+
+			mods.field = SIM_MOD_ERROR_RATIO;
+			debug("request : error_ratio = %d\n", mods.new_value);
+
+		} else {
+			/* Flag not recognized, or nothing specified. */
+			error("Unrecognized flag:%s\n", gargv[i]);
+			if (fd >= 0)
+				close(fd);
+			return (EX_USAGE);
+		}
+
+		mods.chip_num = chip;
+		mods.ctrl_num = ctl;
+
+		/* Call appropriate ioctl */
+		err = ioctl(fd, NANDSIM_MODIFY, &mods);
+		if (err) {
+			error("simulator parameter %s could not be modified! ",
+			    gargv[i]);
+			continue;
+		}
+		i++;
+	}
+	close(fd);
+	return (EX_OK);
+}
+
+static int
+cmderror(int gargc, char **gargv)
+{
+	uint32_t page, column, len, pattern;
+	int chip = 0, ctl = 0, err = 0, fd;
+	struct sim_error sim_err;
+
+	err = parse_devstring(gargv[2], &ctl, &chip);
+	if (err)
+		return (EX_USAGE);
+
+	if (chip == 0xff) {
+		error(MSG_CTRLCHIPNEEDED);
+		return (EX_USAGE);
+	}
+
+	if (convert_arguint(gargv[3], &page) ||
+	    convert_arguint(gargv[4], &column) ||
+	    convert_arguint(gargv[5], &len) ||
+	    convert_arguint(gargv[6], &pattern))
+		return (EX_SOFTWARE);
+
+	if(!assert_chip_connected(ctl, chip))
+		return (EX_SOFTWARE);
+
+	sim_err.page_num = page;
+	sim_err.column = column;
+	sim_err.len = len;
+	sim_err.pattern = pattern;
+	sim_err.ctrl_num = ctl;
+	sim_err.chip_num = chip;
+
+	if (opendev(&fd) != EX_OK)
+		return (EX_OSFILE);
+
+	err = ioctl(fd, NANDSIM_INJECT_ERROR, &sim_err);
+
+	close(fd);
+	if (err) {
+		error("Could not inject error !");
+		return (EX_SOFTWARE);
+	}
+	return (EX_OK);
+}
+
+static int
+cmdbb(int gargc, char **gargv)
+{
+	struct sim_block_state bs;
+	struct chip_param_io cparams;
+	uint32_t blkidx;
+	int c, cdevd, chip = 0, ctl = 0, err = 0, fd, idx;
+	uint8_t flagL = 0, flagU = 0;
+	int *badblocks = NULL;
+
+	/* Check for --list/-L or --unmark/-U flags */
+	for (idx = 3; idx < gargc; idx++) {
+		if (strcmp(gargv[idx], "--list") == 0 ||
+		    strcmp(gargv[idx], "-L") == 0)
+			flagL = idx;
+		if (strcmp(gargv[idx], "--unmark") == 0 ||
+		    strcmp(gargv[idx], "-U") == 0)
+			flagU = idx;
+	}
+
+	if (flagL == 2 || flagU == 2 || flagU == 3)
+		return (EX_USAGE);
+
+	err = parse_devstring(gargv[2], &ctl, &chip);
+	if (err) {
+		return (EX_USAGE);
+	}
+	if (chip == 0xff || ctl == 0xff) {
+		error(MSG_CTRLCHIPNEEDED);
+		return (EX_USAGE);
+	}
+
+	bs.ctrl_num = ctl;
+	bs.chip_num = chip;
+
+	if(!assert_chip_connected(ctl, chip))
+		return (EX_SOFTWARE);
+
+	if (opencdev(&cdevd, ctl, chip) != EX_OK)
+		return (EX_OSFILE);
+
+	err = ioctl(cdevd, NAND_IO_GET_CHIP_PARAM, &cparams);
+	if (err)
+		return (EX_SOFTWARE);
+
+	close(cdevd);
+
+	bs.ctrl_num = ctl;
+	bs.chip_num = chip;
+
+	if (opendev(&fd) != EX_OK)
+		return (EX_OSFILE);
+
+	if (flagL != 3) {
+		/*
+		 * Flag -L was specified either after blocklist or was not
+		 * specified at all.
+		 */
+		c = parse_intarray(gargv[3], &badblocks);
+
+		for (idx = 0; idx < c; idx++) {
+			bs.block_num = badblocks[idx];
+			/* Do not change wearout */
+			bs.wearout = -1;
+			bs.state = (flagU == 0) ? NANDSIM_BAD_BLOCK :
+			    NANDSIM_GOOD_BLOCK;
+
+			err = ioctl(fd, NANDSIM_SET_BLOCK_STATE, &bs);
+			if (err) {
+				error("Could not set bad block(%d) for "
+				    "controller (%d)!",
+				    badblocks[idx], ctl);
+				err = EX_SOFTWARE;
+				break;
+			}
+		}
+	}
+	if (flagL != 0) {
+		/* If flag -L was specified (anywhere) */
+		for (blkidx = 0; blkidx < cparams.blocks; blkidx++) {
+			bs.block_num = blkidx;
+			/* Do not change the wearout */
+			bs.wearout = -1;
+			err = ioctl(fd, NANDSIM_GET_BLOCK_STATE, &bs);
+			if (err) {
+				error("Could not acquire block state");
+				continue;
+			}
+			printf("Block#%d: wear count: %d %s\n", blkidx,
+			    bs.wearout,
+			    (bs.state == NANDSIM_BAD_BLOCK) ? "BAD":"GOOD");
+		}
+	}
+	close(fd);
+	return (0);
+}
+
+static int
+cmdfreeze(int gargc, char **gargv)
+{
+	int chip = 0, ctl = 0, err = 0, fd, i, start = 0, state, stop = 0;
+	struct sim_ctrl_chip ctrlchip;
+
+	err = parse_devstring(gargv[2], &ctl, &chip);
+	if (err)
+		return (EX_USAGE);
+
+	if (ctl == 0xff) {
+		error("You have to specify at least controller number");
+		return (EX_USAGE);
+	}
+
+	if (ctl != 0xff && chip == 0xff) {
+		start = 0;
+		stop = MAX_CTRL_CS - 1;
+	} else {
+		start = chip;
+		stop = chip;
+	}
+
+	ctrlchip.ctrl_num = ctl;
+
+	err = is_ctrl_running(ctl, &state);
+	if (err)
+		return (EX_SOFTWARE);
+	if (state == 0) {
+		error(MSG_NOTRUNNING, ctl);
+		return (EX_SOFTWARE);
+	}
+
+	if (opendev(&fd) != EX_OK)
+		return (EX_OSFILE);
+
+	for (i = start; i <= stop; i++) {
+		err = is_chip_created(ctl, i, &state);
+		if (err)
+			return (EX_SOFTWARE);
+		else if (state == 0) {
+			continue;
+		}
+
+		ctrlchip.chip_num = i;
+		err = ioctl(fd, NANDSIM_FREEZE, &ctrlchip);
+		if (err) {
+			error("Could not freeze ctrl#%d chip#%d", ctl, i);
+			close(fd);
+			return (EX_SOFTWARE);
+		}
+	}
+	close(fd);
+	return (EX_OK);
+}
+
+static int
+cmdlog(int gargc, char **gargv)
+{
+	struct sim_log log;
+	int chip = 0, ctl = 0, err = 0, fd, idx, start = 0, stop = 0;
+	char *logbuf;
+
+	err = parse_devstring(gargv[2], &ctl, &chip);
+	if (err)
+		return (EX_USAGE);
+
+	logbuf = (char *)malloc(sizeof(char) * NANDSIM_RAM_LOG_SIZE);
+	if (logbuf == NULL) {
+		error("Not enough memory to create log buffer");
+		return (EX_SOFTWARE);
+	}
+
+	memset(logbuf, 0, NANDSIM_RAM_LOG_SIZE);
+	log.log = logbuf;
+	log.len = NANDSIM_RAM_LOG_SIZE;
+
+	if (ctl == 0xff) {
+		start = 0;
+		stop = MAX_SIM_DEV-1;
+	} else {
+		start = ctl;
+		stop = ctl;
+	}
+
+	if (opendev(&fd) != EX_OK) {
+		free(logbuf);
+		return (EX_OSFILE);
+	}
+
+	/* Print logs for selected controller(s) */
+	for (idx = start; idx <= stop; idx++) {
+		log.ctrl_num = idx;
+
+		err = ioctl(fd, NANDSIM_PRINT_LOG, &log);
+		if (err) {
+			error("Could not get log for controller %d!", idx);
+			continue;
+		}
+
+		printf("Logs for controller#%d:\n%s\n", idx, logbuf);
+	}
+
+	free(logbuf);
+	close(fd);
+	return (EX_OK);
+}
+
+static int
+cmdstats(int gargc, char **gargv)

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201203100246.q2A2ktw0036128>