aboutsummaryrefslogtreecommitdiff
path: root/usr.sbin/nandsim/nandsim_cfgparse.c
diff options
context:
space:
mode:
authorWarner Losh <imp@FreeBSD.org>2019-06-25 04:50:09 +0000
committerWarner Losh <imp@FreeBSD.org>2019-06-25 04:50:09 +0000
commitf5a95d9a07941650493461c255408f5727d0638b (patch)
treeec681c8739341d8c1e8ff3b891e07a31c0fb3ace /usr.sbin/nandsim/nandsim_cfgparse.c
parente861dab451869582008237a8c11e97348d2440ce (diff)
downloadsrc-f5a95d9a0794.tar.gz
src-f5a95d9a0794.zip
Remove NAND and NANDFS support
NANDFS has been broken for years. Remove it. The NAND drivers that remain are for ancient parts that are no longer relevant. They are polled, have terrible performance and just for ancient arm hardware. NAND parts have evolved significantly from this early work and little to none of it would be relevant should someone need to update to support raw nand. This code has been off by default for years and has violated the vnode protocol leading to panics since it was committed. Numerous posts to arch@ and other locations have found no actual users for this software. Relnotes: Yes No Objection From: arch@ Differential Revision: https://reviews.freebsd.org/D20745
Notes
Notes: svn path=/head/; revision=349352
Diffstat (limited to 'usr.sbin/nandsim/nandsim_cfgparse.c')
-rw-r--r--usr.sbin/nandsim/nandsim_cfgparse.c961
1 files changed, 0 insertions, 961 deletions
diff --git a/usr.sbin/nandsim/nandsim_cfgparse.c b/usr.sbin/nandsim/nandsim_cfgparse.c
deleted file mode 100644
index 4a310fb58a0f..000000000000
--- a/usr.sbin/nandsim/nandsim_cfgparse.c
+++ /dev/null
@@ -1,961 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * 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.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/errno.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-
-#include <dev/nand/nandsim.h>
-
-#include <ctype.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <sysexits.h>
-#include <unistd.h>
-
-#include "nandsim_cfgparse.h"
-
-#define warn(fmt, args...) do { \
- printf("WARNING: " fmt "\n", ##args); } while (0)
-
-#define error(fmt, args...) do { \
- printf("ERROR: " fmt "\n", ##args); } while (0)
-
-#define MSG_MANDATORYKEYMISSING "mandatory key \"%s\" value belonging to " \
- "section \"%s\" is missing!\n"
-
-#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 STRBUFSIZ 2000
-
-/* Macros extracts type and type size */
-#define TYPE(x) ((x) & 0xf8)
-#define SIZE(x) (((x) & 0x07))
-
-/* Erase/Prog/Read time max and min values */
-#define DELAYTIME_MIN 10000
-#define DELAYTIME_MAX 10000000
-
-/* Structure holding configuration for controller. */
-static struct sim_ctrl ctrl_conf;
-/* Structure holding configuration for chip. */
-static struct sim_chip chip_conf;
-
-static struct nandsim_key nandsim_ctrl_keys[] = {
- {"num_cs", 1, VALUE_UINT | SIZE_8, (void *)&ctrl_conf.num_cs, 0},
- {"ctrl_num", 1, VALUE_UINT | SIZE_8, (void *)&ctrl_conf.num, 0},
-
- {"ecc_layout", 1, VALUE_UINTARRAY | SIZE_16,
- (void *)&ctrl_conf.ecc_layout, MAX_ECC_BYTES},
-
- {"filename", 0, VALUE_STRING,
- (void *)&ctrl_conf.filename, FILENAME_SIZE},
-
- {"ecc", 0, VALUE_BOOL, (void *)&ctrl_conf.ecc, 0},
- {NULL, 0, 0, NULL, 0},
-};
-
-static struct nandsim_key nandsim_chip_keys[] = {
- {"chip_cs", 1, VALUE_UINT | SIZE_8, (void *)&chip_conf.num, 0},
- {"chip_ctrl", 1, VALUE_UINT | SIZE_8, (void *)&chip_conf.ctrl_num,
- 0},
- {"device_id", 1, VALUE_UINT | SIZE_8, (void *)&chip_conf.device_id,
- 0},
- {"manufacturer_id", 1, VALUE_UINT | SIZE_8,
- (void *)&chip_conf.manufact_id, 0},
- {"model", 0, VALUE_STRING, (void *)&chip_conf.device_model,
- DEV_MODEL_STR_SIZE},
- {"manufacturer", 0, VALUE_STRING, (void *)&chip_conf.manufacturer,
- MAN_STR_SIZE},
- {"page_size", 1, VALUE_UINT | SIZE_32, (void *)&chip_conf.page_size,
- 0},
- {"oob_size", 1, VALUE_UINT | SIZE_32, (void *)&chip_conf.oob_size,
- 0},
- {"pages_per_block", 1, VALUE_UINT | SIZE_32,
- (void *)&chip_conf.pgs_per_blk, 0},
- {"blocks_per_lun", 1, VALUE_UINT | SIZE_32,
- (void *)&chip_conf.blks_per_lun, 0},
- {"luns", 1, VALUE_UINT | SIZE_32, (void *)&chip_conf.luns, 0},
- {"column_addr_cycle", 1,VALUE_UINT | SIZE_8,
- (void *)&chip_conf.col_addr_cycles, 0},
- {"row_addr_cycle", 1, VALUE_UINT | SIZE_8,
- (void *)&chip_conf.row_addr_cycles, 0},
- {"program_time", 0, VALUE_UINT | SIZE_32,
- (void *)&chip_conf.prog_time, 0},
- {"erase_time", 0, VALUE_UINT | SIZE_32,
- (void *)&chip_conf.erase_time, 0},
- {"read_time", 0, VALUE_UINT | SIZE_32,
- (void *)&chip_conf.read_time, 0},
- {"width", 1, VALUE_UINT | SIZE_8, (void *)&chip_conf.width, 0},
- {"wear_out", 1, VALUE_UINT | SIZE_32, (void *)&chip_conf.wear_level,
- 0},
- {"bad_block_map", 0, VALUE_UINTARRAY | SIZE_32,
- (void *)&chip_conf.bad_block_map, MAX_BAD_BLOCKS},
- {NULL, 0, 0, NULL, 0},
-};
-
-static struct nandsim_section sections[] = {
- {"ctrl", (struct nandsim_key *)&nandsim_ctrl_keys},
- {"chip", (struct nandsim_key *)&nandsim_chip_keys},
- {NULL, NULL},
-};
-
-static uint8_t logoutputtoint(char *, int *);
-static uint8_t validate_chips(struct sim_chip *, int, struct sim_ctrl *, int);
-static uint8_t validate_ctrls(struct sim_ctrl *, int);
-static int configure_sim(const char *, struct rcfile *);
-static int create_ctrls(struct rcfile *, struct sim_ctrl **, int *);
-static int create_chips(struct rcfile *, struct sim_chip **, int *);
-static void destroy_ctrls(struct sim_ctrl *);
-static void destroy_chips(struct sim_chip *);
-static int validate_section_config(struct rcfile *, const char *, int);
-
-int
-convert_argint(char *arg, int *value)
-{
-
- if (arg == NULL || value == NULL)
- return (EINVAL);
-
- errno = 0;
- *value = (int)strtol(arg, NULL, 0);
- if (*value == 0 && errno != 0) {
- error("Cannot convert to number argument \'%s\'", arg);
- return (EINVAL);
- }
- return (0);
-}
-
-int
-convert_arguint(char *arg, unsigned int *value)
-{
-
- if (arg == NULL || value == NULL)
- return (EINVAL);
-
- errno = 0;
- *value = (unsigned int)strtol(arg, NULL, 0);
- if (*value == 0 && errno != 0) {
- error("Cannot convert to number argument \'%s\'", arg);
- return (EINVAL);
- }
- return (0);
-}
-
-/* Parse given ',' separated list of bytes into buffer. */
-int
-parse_intarray(char *array, int **buffer)
-{
- char *tmp, *tmpstr, *origstr;
- unsigned int currbufp = 0, i;
- unsigned int count = 0, from = 0, to = 0;
-
- /* Remove square braces */
- if (array[0] == '[')
- array ++;
- if (array[strlen(array)-1] == ']')
- array[strlen(array)-1] = ',';
-
- from = strlen(array);
- origstr = (char *)malloc(sizeof(char) * from);
- strcpy(origstr, array);
-
- tmpstr = (char *)strtok(array, ",");
- /* First loop checks for how big int array we need to allocate */
- while (tmpstr != NULL) {
- errno = 0;
- if ((tmp = strchr(tmpstr, '-')) != NULL) {
- *tmp = ' ';
- if (convert_arguint(tmpstr, &from) ||
- convert_arguint(tmp, &to)) {
- free(origstr);
- return (EINVAL);
- }
-
- count += to - from + 1;
- } else {
- if (convert_arguint(tmpstr, &from)) {
- free(origstr);
- return (EINVAL);
- }
- count++;
- }
- tmpstr = (char *)strtok(NULL, ",");
- }
-
- if (count == 0)
- goto out;
-
- /* Allocate buffer of ints */
- tmpstr = (char *)strtok(origstr, ",");
- *buffer = malloc(count * sizeof(int));
-
- /* Second loop is just inserting converted values into int array */
- while (tmpstr != NULL) {
- errno = 0;
- if ((tmp = strchr(tmpstr, '-')) != NULL) {
- *tmp = ' ';
- from = strtol(tmpstr, NULL, 0);
- to = strtol(tmp, NULL, 0);
- tmpstr = strtok(NULL, ",");
- for (i = from; i <= to; i ++)
- (*buffer)[currbufp++] = i;
- continue;
- }
- errno = 0;
- from = (int)strtol(tmpstr, NULL, 0);
- (*buffer)[currbufp++] = from;
- tmpstr = (char *)strtok(NULL, ",");
- }
-out:
- free(origstr);
- return (count);
-}
-
-/* Convert logoutput strings literals into appropriate ints. */
-static uint8_t
-logoutputtoint(char *logoutput, int *output)
-{
- int out;
-
- if (strcmp(logoutput, "file") == 0)
- out = NANDSIM_OUTPUT_FILE;
-
- else if (strcmp(logoutput, "console") == 0)
- out = NANDSIM_OUTPUT_CONSOLE;
-
- else if (strcmp(logoutput, "ram") == 0)
- out = NANDSIM_OUTPUT_RAM;
-
- else if (strcmp(logoutput, "none") == 0)
- out = NANDSIM_OUTPUT_NONE;
- else
- out = -1;
-
- *output = out;
-
- if (out == -1)
- return (EINVAL);
- else
- return (0);
-}
-
-static int
-configure_sim(const char *devfname, struct rcfile *f)
-{
- struct sim_param sim_conf;
- char buf[255];
- int err, tmpv, fd;
-
- err = rc_getint(f, "sim", 0, "log_level", &tmpv);
-
- if (tmpv < 0 || tmpv > 255 || err) {
- error("Bad log level specified (%d)\n", tmpv);
- return (ENOTSUP);
- } else
- sim_conf.log_level = tmpv;
-
- rc_getstring(f, "sim", 0, "log_output", 255, (char *)&buf);
-
- tmpv = -1;
- err = logoutputtoint((char *)&buf, &tmpv);
- if (err) {
- error("Log output specified in config file does not seem to "
- "be valid (%s)!", (char *)&buf);
- return (ENOTSUP);
- }
-
- sim_conf.log_output = tmpv;
-
- fd = open(devfname, O_RDWR);
- if (fd == -1) {
- error("could not open simulator device file (%s)!",
- devfname);
- return (EX_OSFILE);
- }
-
- err = ioctl(fd, NANDSIM_SIM_PARAM, &sim_conf);
- if (err) {
- error("simulator parameters could not be modified: %s",
- strerror(errno));
- close(fd);
- return (ENXIO);
- }
-
- close(fd);
- return (EX_OK);
-}
-
-static int
-create_ctrls(struct rcfile *f, struct sim_ctrl **ctrls, int *cnt)
-{
- int count, i;
- struct sim_ctrl *ctrlsptr;
-
- count = rc_getsectionscount(f, "ctrl");
- if (count > MAX_SIM_DEV) {
- error("Too many CTRL sections specified(%d)", count);
- return (ENOTSUP);
- } else if (count == 0) {
- error("No ctrl sections specified");
- return (ENOENT);
- }
-
- ctrlsptr = (struct sim_ctrl *)malloc(sizeof(struct sim_ctrl) * count);
- if (ctrlsptr == NULL) {
- error("Could not allocate memory for ctrl configuration");
- return (ENOMEM);
- }
-
- for (i = 0; i < count; i++) {
- bzero((void *)&ctrl_conf, sizeof(ctrl_conf));
-
- /*
- * ECC layout have to end up with 0xffff, so
- * we're filling buffer with 0xff. If ecc_layout is
- * defined in config file, values will be overridden.
- */
- memset((void *)&ctrl_conf.ecc_layout, 0xff,
- sizeof(ctrl_conf.ecc_layout));
-
- if (validate_section_config(f, "ctrl", i) != 0) {
- free(ctrlsptr);
- return (EINVAL);
- }
-
- if (parse_section(f, "ctrl", i) != 0) {
- free(ctrlsptr);
- return (EINVAL);
- }
-
- memcpy(&ctrlsptr[i], &ctrl_conf, sizeof(ctrl_conf));
- /* Try to create ctrl with config parsed */
- debug("NUM=%d\nNUM_CS=%d\nECC=%d\nFILENAME=%s\nECC_LAYOUT[0]"
- "=%d\nECC_LAYOUT[1]=%d\n\n",
- ctrlsptr[i].num, ctrlsptr[i].num_cs, ctrlsptr[i].ecc,
- ctrlsptr[i].filename, ctrlsptr[i].ecc_layout[0],
- ctrlsptr[i].ecc_layout[1]);
- }
- *cnt = count;
- *ctrls = ctrlsptr;
- return (0);
-}
-
-static void
-destroy_ctrls(struct sim_ctrl *ctrls)
-{
-
- free(ctrls);
-}
-
-static int
-create_chips(struct rcfile *f, struct sim_chip **chips, int *cnt)
-{
- struct sim_chip *chipsptr;
- int count, i;
-
- count = rc_getsectionscount(f, "chip");
- if (count > (MAX_CTRL_CS * MAX_SIM_DEV)) {
- error("Too many chip sections specified(%d)", count);
- return (ENOTSUP);
- } else if (count == 0) {
- error("No chip sections specified");
- return (ENOENT);
- }
-
- chipsptr = (struct sim_chip *)malloc(sizeof(struct sim_chip) * count);
- if (chipsptr == NULL) {
- error("Could not allocate memory for chip configuration");
- return (ENOMEM);
- }
-
- for (i = 0; i < count; i++) {
- bzero((void *)&chip_conf, sizeof(chip_conf));
-
- /*
- * Bad block map have to end up with 0xffff, so
- * we're filling array with 0xff. If bad block map is
- * defined in config file, values will be overridden.
- */
- memset((void *)&chip_conf.bad_block_map, 0xff,
- sizeof(chip_conf.bad_block_map));
-
- if (validate_section_config(f, "chip", i) != 0) {
- free(chipsptr);
- return (EINVAL);
- }
-
- if (parse_section(f, "chip", i) != 0) {
- free(chipsptr);
- return (EINVAL);
- }
-
- memcpy(&chipsptr[i], &chip_conf, sizeof(chip_conf));
-
- /* Try to create chip with config parsed */
- debug("CHIP:\nNUM=%d\nCTRL_NUM=%d\nDEVID=%d\nMANID=%d\n"
- "PAGE_SZ=%d\nOOBSZ=%d\nREAD_T=%d\nDEVMODEL=%s\n"
- "MAN=%s\nCOLADDRCYCLES=%d\nROWADDRCYCLES=%d\nCHWIDTH=%d\n"
- "PGS/BLK=%d\nBLK/LUN=%d\nLUNS=%d\nERR_RATIO=%d\n"
- "WEARLEVEL=%d\nISWP=%d\n\n\n\n",
- chipsptr[i].num, chipsptr[i].ctrl_num,
- chipsptr[i].device_id, chipsptr[i].manufact_id,
- chipsptr[i].page_size, chipsptr[i].oob_size,
- chipsptr[i].read_time, chipsptr[i].device_model,
- chipsptr[i].manufacturer, chipsptr[i].col_addr_cycles,
- chipsptr[i].row_addr_cycles, chipsptr[i].width,
- chipsptr[i].pgs_per_blk, chipsptr[i].blks_per_lun,
- chipsptr[i].luns, chipsptr[i].error_ratio,
- chipsptr[i].wear_level, chipsptr[i].is_wp);
- }
- *cnt = count;
- *chips = chipsptr;
- return (0);
-}
-
-static void
-destroy_chips(struct sim_chip *chips)
-{
-
- free(chips);
-}
-
-int
-parse_config(char *cfgfname, const char *devfname)
-{
- int err = 0, fd;
- unsigned int chipsectionscnt, ctrlsectionscnt, i;
- struct rcfile *f;
- struct sim_chip *chips;
- struct sim_ctrl *ctrls;
-
- err = rc_open(cfgfname, "r", &f);
- if (err) {
- error("could not open configuration file (%s)", cfgfname);
- return (EX_NOINPUT);
- }
-
- /* First, try to configure simulator itself. */
- if (configure_sim(devfname, f) != EX_OK) {
- rc_close(f);
- return (EINVAL);
- }
-
- debug("SIM CONFIGURED!\n");
- /* Then create controllers' configs */
- if (create_ctrls(f, &ctrls, &ctrlsectionscnt) != 0) {
- rc_close(f);
- return (ENXIO);
- }
- debug("CTRLS CONFIG READ!\n");
-
- /* Then create chips' configs */
- if (create_chips(f, &chips, &chipsectionscnt) != 0) {
- destroy_ctrls(ctrls);
- rc_close(f);
- return (ENXIO);
- }
- debug("CHIPS CONFIG READ!\n");
-
- if (validate_ctrls(ctrls, ctrlsectionscnt) != 0) {
- destroy_ctrls(ctrls);
- destroy_chips(chips);
- rc_close(f);
- return (EX_SOFTWARE);
- }
- if (validate_chips(chips, chipsectionscnt, ctrls,
- ctrlsectionscnt) != 0) {
- destroy_ctrls(ctrls);
- destroy_chips(chips);
- rc_close(f);
- return (EX_SOFTWARE);
- }
-
- /* Open device */
- fd = open(devfname, O_RDWR);
- if (fd == -1) {
- error("could not open simulator device file (%s)!",
- devfname);
- rc_close(f);
- destroy_chips(chips);
- destroy_ctrls(ctrls);
- return (EX_OSFILE);
- }
-
- debug("SIM CONFIG STARTED!\n");
-
- /* At this stage, both ctrls' and chips' configs should be valid */
- for (i = 0; i < ctrlsectionscnt; i++) {
- err = ioctl(fd, NANDSIM_CREATE_CTRL, &ctrls[i]);
- if (err) {
- if (err == EEXIST)
- error("Controller#%d already created\n",
- ctrls[i].num);
- else if (err == EINVAL)
- error("Incorrect controller number (%d)\n",
- ctrls[i].num);
- else
- error("Could not created controller#%d\n",
- ctrls[i].num);
- /* Errors during controller creation stops parsing */
- close(fd);
- rc_close(f);
- destroy_ctrls(ctrls);
- destroy_chips(chips);
- return (ENXIO);
- }
- debug("CTRL#%d CONFIG STARTED!\n", i);
- }
-
- for (i = 0; i < chipsectionscnt; i++) {
- err = ioctl(fd, NANDSIM_CREATE_CHIP, &chips[i]);
- if (err) {
- if (err == EEXIST)
- error("Chip#%d for controller#%d already "
- "created\n", chips[i].num,
- chips[i].ctrl_num);
- else if (err == EINVAL)
- error("Incorrect chip number (%d:%d)\n",
- chips[i].num, chips[i].ctrl_num);
- else
- error("Could not create chip (%d:%d)\n",
- chips[i].num, chips[i].ctrl_num);
- error("Could not start chip#%d\n", i);
- destroy_chips(chips);
- destroy_ctrls(ctrls);
- close(fd);
- rc_close(f);
- return (ENXIO);
- }
- }
- debug("CHIPS CONFIG STARTED!\n");
-
- close(fd);
- rc_close(f);
- destroy_chips(chips);
- destroy_ctrls(ctrls);
- return (0);
-}
-
-/*
- * Function tries to get appropriate value for given key, convert it to
- * array of ints (of given size), and perform all the necessary checks and
- * conversions.
- */
-static int
-get_argument_intarray(const char *sect_name, int sectno,
- struct nandsim_key *key, struct rcfile *f)
-{
- char strbuf[STRBUFSIZ];
- int *intbuf;
- int getres;
- uint32_t cnt, i = 0;
-
- getres = rc_getstring(f, sect_name, sectno, key->keyname, STRBUFSIZ,
- (char *)&strbuf);
-
- if (getres != 0) {
- if (key->mandatory != 0) {
- error(MSG_MANDATORYKEYMISSING, key->keyname,
- sect_name);
- return (EINVAL);
- } else
- /* Non-mandatory key, not present -- skip */
- return (0);
- }
- cnt = parse_intarray((char *)&strbuf, &intbuf);
- cnt = (cnt <= key->maxlength) ? cnt : key->maxlength;
-
- for (i = 0; i < cnt; i++) {
- if (SIZE(key->valuetype) == SIZE_8)
- *((uint8_t *)(key->field) + i) =
- (uint8_t)intbuf[i];
- else if (SIZE(key->valuetype) == SIZE_16)
- *((uint16_t *)(key->field) + i) =
- (uint16_t)intbuf[i];
- else
- *((uint32_t *)(key->field) + i) =
- (uint32_t)intbuf[i];
- }
- free(intbuf);
- return (0);
-}
-
-/*
- * Function tries to get appropriate value for given key, convert it to
- * int of certain length.
- */
-static int
-get_argument_int(const char *sect_name, int sectno, struct nandsim_key *key,
- struct rcfile *f)
-{
- int getres;
- uint32_t val;
-
- getres = rc_getint(f, sect_name, sectno, key->keyname, &val);
- if (getres != 0) {
-
- if (key->mandatory != 0) {
- error(MSG_MANDATORYKEYMISSING, key->keyname,
- sect_name);
-
- return (EINVAL);
- } else
- /* Non-mandatory key, not present -- skip */
- return (0);
- }
- if (SIZE(key->valuetype) == SIZE_8)
- *(uint8_t *)(key->field) = (uint8_t)val;
- else if (SIZE(key->valuetype) == SIZE_16)
- *(uint16_t *)(key->field) = (uint16_t)val;
- else
- *(uint32_t *)(key->field) = (uint32_t)val;
- return (0);
-}
-
-/* Function tries to get string value for given key */
-static int
-get_argument_string(const char *sect_name, int sectno,
- struct nandsim_key *key, struct rcfile *f)
-{
- char strbuf[STRBUFSIZ];
- int getres;
-
- getres = rc_getstring(f, sect_name, sectno, key->keyname, STRBUFSIZ,
- strbuf);
-
- if (getres != 0) {
- if (key->mandatory != 0) {
- error(MSG_MANDATORYKEYMISSING, key->keyname,
- sect_name);
- return (1);
- } else
- /* Non-mandatory key, not present -- skip */
- return (0);
- }
- strncpy(key->field, (char *)&strbuf, (size_t)(key->maxlength - 1));
- return (0);
-}
-
-/* Function tries to get on/off value for given key */
-static int
-get_argument_bool(const char *sect_name, int sectno, struct nandsim_key *key,
- struct rcfile *f)
-{
- int getres, val;
-
- getres = rc_getbool(f, sect_name, sectno, key->keyname, &val);
- if (getres != 0) {
- if (key->mandatory != 0) {
- error(MSG_MANDATORYKEYMISSING, key->keyname,
- sect_name);
- return (1);
- } else
- /* Non-mandatory key, not present -- skip */
- return (0);
- }
- *(uint8_t *)key->field = (uint8_t)val;
- return (0);
-}
-
-int
-parse_section(struct rcfile *f, const char *sect_name, int sectno)
-{
- struct nandsim_key *key;
- struct nandsim_section *sect = (struct nandsim_section *)&sections;
- int getres = 0;
-
- while (1) {
- if (sect == NULL)
- return (EINVAL);
-
- if (strcmp(sect->name, sect_name) == 0)
- break;
- else
- sect++;
- }
- key = sect->keys;
- do {
- debug("->Section: %s, Key: %s, type: %d, size: %d",
- sect_name, key->keyname, TYPE(key->valuetype),
- SIZE(key->valuetype)/2);
-
- switch (TYPE(key->valuetype)) {
- case VALUE_UINT:
- /* Single int value */
- getres = get_argument_int(sect_name, sectno, key, f);
-
- if (getres != 0)
- return (getres);
-
- break;
- case VALUE_UINTARRAY:
- /* Array of ints */
- getres = get_argument_intarray(sect_name,
- sectno, key, f);
-
- if (getres != 0)
- return (getres);
-
- break;
- case VALUE_STRING:
- /* Array of chars */
- getres = get_argument_string(sect_name, sectno, key,
- f);
-
- if (getres != 0)
- return (getres);
-
- break;
- case VALUE_BOOL:
- /* Boolean value (true/false/on/off/yes/no) */
- getres = get_argument_bool(sect_name, sectno, key,
- f);
-
- if (getres != 0)
- return (getres);
-
- break;
- }
- } while ((++key)->keyname != NULL);
-
- return (0);
-}
-
-static uint8_t
-validate_chips(struct sim_chip *chips, int chipcnt,
- struct sim_ctrl *ctrls, int ctrlcnt)
-{
- int cchipcnt, i, width, j, id, max;
-
- cchipcnt = chipcnt;
- for (chipcnt -= 1; chipcnt >= 0; chipcnt--) {
- if (chips[chipcnt].num >= MAX_CTRL_CS) {
- error("chip no. too high (%d)!!\n",
- chips[chipcnt].num);
- return (EINVAL);
- }
-
- if (chips[chipcnt].ctrl_num >= MAX_SIM_DEV) {
- error("controller no. too high (%d)!!\n",
- chips[chipcnt].ctrl_num);
- return (EINVAL);
- }
-
- if (chips[chipcnt].width != 8 &&
- chips[chipcnt].width != 16) {
- error("invalid width:%d for chip#%d",
- chips[chipcnt].width, chips[chipcnt].num);
- return (EINVAL);
- }
-
- /* Check if page size is > 512 and if its power of 2 */
- if (chips[chipcnt].page_size < 512 ||
- (chips[chipcnt].page_size &
- (chips[chipcnt].page_size - 1)) != 0) {
- error("invalid page size:%d for chip#%d at ctrl#%d!!"
- "\n", chips[chipcnt].page_size,
- chips[chipcnt].num,
- chips[chipcnt].ctrl_num);
- return (EINVAL);
- }
-
- /* Check if controller no. ctrl_num is configured */
- for (i = 0, id = -1; i < ctrlcnt && id == -1; i++)
- if (ctrls[i].num == chips[chipcnt].ctrl_num)
- id = i;
-
- if (i == ctrlcnt && id == -1) {
- error("Missing configuration for controller %d"
- " (at least one chip is connected to it)",
- chips[chipcnt].ctrl_num);
- return (EINVAL);
- } else {
- /*
- * Controller is configured -> check oob_size
- * validity
- */
- i = 0;
- max = ctrls[id].ecc_layout[0];
- while (i < MAX_ECC_BYTES &&
- ctrls[id].ecc_layout[i] != 0xffff) {
-
- if (ctrls[id].ecc_layout[i] > max)
- max = ctrls[id].ecc_layout[i];
- i++;
- }
-
- if (chips[chipcnt].oob_size < (unsigned)i) {
- error("OOB size for chip#%d at ctrl#%d is "
- "smaller than ecc layout length!",
- chips[chipcnt].num,
- chips[chipcnt].ctrl_num);
- exit(EINVAL);
- }
-
- if (chips[chipcnt].oob_size < (unsigned)max) {
- error("OOB size for chip#%d at ctrl#%d is "
- "smaller than maximal ecc position in "
- "defined layout!", chips[chipcnt].num,
- chips[chipcnt].ctrl_num);
- exit(EINVAL);
- }
-
-
- }
-
- if ((chips[chipcnt].erase_time < DELAYTIME_MIN ||
- chips[chipcnt].erase_time > DELAYTIME_MAX) &&
- chips[chipcnt].erase_time != 0) {
- error("Invalid erase time value for chip#%d at "
- "ctrl#%d",
- chips[chipcnt].num,
- chips[chipcnt].ctrl_num);
- return (EINVAL);
- }
-
- if ((chips[chipcnt].prog_time < DELAYTIME_MIN ||
- chips[chipcnt].prog_time > DELAYTIME_MAX) &&
- chips[chipcnt].prog_time != 0) {
- error("Invalid prog time value for chip#%d at "
- "ctr#%d!",
- chips[chipcnt].num,
- chips[chipcnt].ctrl_num);
- return (EINVAL);
- }
-
- if ((chips[chipcnt].read_time < DELAYTIME_MIN ||
- chips[chipcnt].read_time > DELAYTIME_MAX) &&
- chips[chipcnt].read_time != 0) {
- error("Invalid read time value for chip#%d at "
- "ctrl#%d!",
- chips[chipcnt].num,
- chips[chipcnt].ctrl_num);
- return (EINVAL);
- }
- }
- /* Check if chips attached to the same controller, have same width */
- for (i = 0; i < ctrlcnt; i++) {
- width = -1;
- for (j = 0; j < cchipcnt; j++) {
- if (chips[j].ctrl_num == i) {
- if (width == -1) {
- width = chips[j].width;
- } else {
- if (width != chips[j].width) {
- error("Chips attached to "
- "ctrl#%d have different "
- "widths!\n", i);
- return (EINVAL);
- }
- }
- }
- }
- }
-
- return (0);
-}
-
-static uint8_t
-validate_ctrls(struct sim_ctrl *ctrl, int ctrlcnt)
-{
- for (ctrlcnt -= 1; ctrlcnt >= 0; ctrlcnt--) {
- if (ctrl[ctrlcnt].num > MAX_SIM_DEV) {
- error("Controller no. too high (%d)!!\n",
- ctrl[ctrlcnt].num);
- return (EINVAL);
- }
- if (ctrl[ctrlcnt].num_cs > MAX_CTRL_CS) {
- error("Too many CS (%d)!!\n", ctrl[ctrlcnt].num_cs);
- return (EINVAL);
- }
- if (ctrl[ctrlcnt].ecc != 0 && ctrl[ctrlcnt].ecc != 1) {
- error("ECC is set to neither 0 nor 1 !\n");
- return (EINVAL);
- }
- }
-
- return (0);
-}
-
-static int validate_section_config(struct rcfile *f, const char *sect_name,
- int sectno)
-{
- struct nandsim_key *key;
- struct nandsim_section *sect;
- char **keys_tbl;
- int i, match;
-
- for (match = 0, sect = (struct nandsim_section *)&sections;
- sect != NULL; sect++) {
- if (strcmp(sect->name, sect_name) == 0) {
- match = 1;
- break;
- }
- }
-
- if (match == 0)
- return (EINVAL);
-
- keys_tbl = rc_getkeys(f, sect_name, sectno);
- if (keys_tbl == NULL)
- return (ENOMEM);
-
- for (i = 0; keys_tbl[i] != NULL; i++) {
- key = sect->keys;
- match = 0;
- do {
- if (strcmp(keys_tbl[i], key->keyname) == 0) {
- match = 1;
- break;
- }
- } while ((++key)->keyname != NULL);
-
- if (match == 0) {
- error("Invalid key in config file: %s\n", keys_tbl[i]);
- free(keys_tbl);
- return (EINVAL);
- }
- }
-
- free(keys_tbl);
- return (0);
-}