summaryrefslogtreecommitdiff
path: root/nandtest.c
diff options
context:
space:
mode:
authorDongsheng Yang <yangds.fnst@cn.fujitsu.com>2015-10-31 11:12:01 +0800
committerBrian Norris <computersforpeace@gmail.com>2015-11-11 14:38:40 -0800
commit7d81790ced345585b1e647ca9d0f6678e7062fa4 (patch)
tree02f61270c7a0fff7bb6b2e28f247a3d2fd6ff490 /nandtest.c
parent344753f2aacb94d98ce238f81fc4a4b6ef6adea9 (diff)
mtd-utils: Restructure the mtd-utils source.
* There is no code modification in this commit, only moving * the files to proper place. The user tools looks a little messy as we place almost the all tools in the root directory of mtd-utils. To make it more clear, I propose to introduce the following structure for our source code. mtd-utils/ |-- lib |-- include |-- misc-utils |-- jffsX-utils |-- nand-utils |-- nor-utils |-- ubi-utils |-- ubifs-utils `-- tests Signed-off-by: Dongsheng Yang <yangds.fnst@cn.fujitsu.com> Signed-off-by: Brian Norris <computersforpeace@gmail.com>
Diffstat (limited to 'nandtest.c')
-rw-r--r--nandtest.c317
1 files changed, 0 insertions, 317 deletions
diff --git a/nandtest.c b/nandtest.c
deleted file mode 100644
index 2ef7cc8..0000000
--- a/nandtest.c
+++ /dev/null
@@ -1,317 +0,0 @@
-#define PROGRAM_NAME "nandtest"
-
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <unistd.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <getopt.h>
-
-#include <asm/types.h>
-#include "mtd/mtd-user.h"
-#include "common.h"
-
-void usage(int status)
-{
- fprintf(status ? stderr : stdout,
- "usage: %s [OPTIONS] <device>\n\n"
- " -h, --help Display this help output\n"
- " -m, --markbad Mark blocks bad if they appear so\n"
- " -s, --seed Supply random seed\n"
- " -p, --passes Number of passes\n"
- " -r <n>, --reads=<n> Read & check <n> times per pass\n"
- " -o, --offset Start offset on flash\n"
- " -l, --length Length of flash to test\n"
- " -k, --keep Restore existing contents after test\n",
- PROGRAM_NAME);
- exit(status);
-}
-
-struct mtd_info_user meminfo;
-struct mtd_ecc_stats oldstats, newstats;
-int fd;
-int markbad=0;
-int seed;
-
-int read_and_compare(loff_t ofs, unsigned char *data, unsigned char *rbuf)
-{
- ssize_t len;
- int i;
-
- len = pread(fd, rbuf, meminfo.erasesize, ofs);
- if (len < meminfo.erasesize) {
- printf("\n");
- if (len)
- fprintf(stderr, "Short read (%zd bytes)\n", len);
- else
- perror("read");
- exit(1);
- }
-
- if (ioctl(fd, ECCGETSTATS, &newstats)) {
- printf("\n");
- perror("ECCGETSTATS");
- close(fd);
- exit(1);
- }
-
- if (newstats.corrected > oldstats.corrected) {
- printf("\n %d bit(s) ECC corrected at %08x\n",
- newstats.corrected - oldstats.corrected,
- (unsigned) ofs);
- oldstats.corrected = newstats.corrected;
- }
- if (newstats.failed > oldstats.failed) {
- printf("\nECC failed at %08x\n", (unsigned) ofs);
- oldstats.failed = newstats.failed;
- }
-
- printf("\r%08x: checking...", (unsigned)ofs);
- fflush(stdout);
-
- if (memcmp(data, rbuf, meminfo.erasesize)) {
- printf("\n");
- fprintf(stderr, "compare failed. seed %d\n", seed);
- for (i=0; i<meminfo.erasesize; i++) {
- if (data[i] != rbuf[i])
- printf("Byte 0x%x is %02x should be %02x\n",
- i, rbuf[i], data[i]);
- }
- return 1;
- }
- return 0;
-}
-
-int erase_and_write(loff_t ofs, unsigned char *data, unsigned char *rbuf, int nr_reads)
-{
- struct erase_info_user er;
- ssize_t len;
- int i, read_errs = 0;
-
- printf("\r%08x: erasing... ", (unsigned)ofs);
- fflush(stdout);
-
- er.start = ofs;
- er.length = meminfo.erasesize;
-
- if (ioctl(fd, MEMERASE, &er)) {
- perror("MEMERASE");
- if (markbad) {
- printf("Mark block bad at %08lx\n", (long)ofs);
- ioctl(fd, MEMSETBADBLOCK, &ofs);
- }
- return 1;
- }
-
- printf("\r%08x: writing...", (unsigned)ofs);
- fflush(stdout);
-
- len = pwrite(fd, data, meminfo.erasesize, ofs);
- if (len < 0) {
- printf("\n");
- perror("write");
- if (markbad) {
- printf("Mark block bad at %08lx\n", (long)ofs);
- ioctl(fd, MEMSETBADBLOCK, &ofs);
- }
- return 1;
- }
- if (len < meminfo.erasesize) {
- printf("\n");
- fprintf(stderr, "Short write (%zd bytes)\n", len);
- exit(1);
- }
-
- for (i=1; i<=nr_reads; i++) {
- printf("\r%08x: reading (%d of %d)...", (unsigned)ofs, i, nr_reads);
- fflush(stdout);
- if (read_and_compare(ofs, data, rbuf))
- read_errs++;
- }
- if (read_errs) {
- fprintf(stderr, "read/check %d of %d failed. seed %d\n", read_errs, nr_reads, seed);
- return 1;
- }
- return 0;
-}
-
-
-/*
- * Main program
- */
-int main(int argc, char **argv)
-{
- int i;
- unsigned char *wbuf, *rbuf, *kbuf;
- int pass;
- int nr_passes = 1;
- int nr_reads = 4;
- int keep_contents = 0;
- uint32_t offset = 0;
- uint32_t length = -1;
- int error = 0;
-
- seed = time(NULL);
-
- for (;;) {
- static const char short_options[] = "hkl:mo:p:r:s:";
- static const struct option long_options[] = {
- { "help", no_argument, 0, 'h' },
- { "markbad", no_argument, 0, 'm' },
- { "seed", required_argument, 0, 's' },
- { "passes", required_argument, 0, 'p' },
- { "offset", required_argument, 0, 'o' },
- { "length", required_argument, 0, 'l' },
- { "reads", required_argument, 0, 'r' },
- { "keep", no_argument, 0, 'k' },
- {0, 0, 0, 0},
- };
- int option_index = 0;
- int c = getopt_long(argc, argv, short_options, long_options, &option_index);
- if (c == EOF)
- break;
-
- switch (c) {
- case 'h':
- usage(0);
- break;
-
- case '?':
- usage(1);
- break;
-
- case 'm':
- markbad = 1;
- break;
-
- case 'k':
- keep_contents = 1;
- break;
-
- case 's':
- seed = atol(optarg);
- break;
-
- case 'p':
- nr_passes = atol(optarg);
- break;
-
- case 'r':
- nr_reads = atol(optarg);
- break;
-
- case 'o':
- offset = simple_strtoul(optarg, &error);
- break;
-
- case 'l':
- length = simple_strtoul(optarg, &error);
- break;
-
- }
- }
- if (argc - optind != 1)
- usage(1);
- if (error)
- errmsg_die("Try --help for more information");
-
- fd = open(argv[optind], O_RDWR);
- if (fd < 0) {
- perror("open");
- exit(1);
- }
-
- if (ioctl(fd, MEMGETINFO, &meminfo)) {
- perror("MEMGETINFO");
- close(fd);
- exit(1);
- }
-
- if (length == -1)
- length = meminfo.size;
-
- if (offset % meminfo.erasesize) {
- fprintf(stderr, "Offset %x not multiple of erase size %x\n",
- offset, meminfo.erasesize);
- exit(1);
- }
- if (length % meminfo.erasesize) {
- fprintf(stderr, "Length %x not multiple of erase size %x\n",
- length, meminfo.erasesize);
- exit(1);
- }
- if (length + offset > meminfo.size) {
- fprintf(stderr, "Length %x + offset %x exceeds device size %x\n",
- length, offset, meminfo.size);
- exit(1);
- }
-
- wbuf = malloc(meminfo.erasesize * 3);
- if (!wbuf) {
- fprintf(stderr, "Could not allocate %d bytes for buffer\n",
- meminfo.erasesize * 2);
- exit(1);
- }
- rbuf = wbuf + meminfo.erasesize;
- kbuf = rbuf + meminfo.erasesize;
-
- if (ioctl(fd, ECCGETSTATS, &oldstats)) {
- perror("ECCGETSTATS");
- close(fd);
- exit(1);
- }
-
- printf("ECC corrections: %d\n", oldstats.corrected);
- printf("ECC failures : %d\n", oldstats.failed);
- printf("Bad blocks : %d\n", oldstats.badblocks);
- printf("BBT blocks : %d\n", oldstats.bbtblocks);
-
- srand(seed);
-
- for (pass = 0; pass < nr_passes; pass++) {
- loff_t test_ofs;
-
- for (test_ofs = offset; test_ofs < offset+length; test_ofs += meminfo.erasesize) {
- ssize_t len;
-
- seed = rand();
- srand(seed);
-
- if (ioctl(fd, MEMGETBADBLOCK, &test_ofs)) {
- printf("\rBad block at 0x%08x\n", (unsigned)test_ofs);
- continue;
- }
-
- for (i=0; i<meminfo.erasesize; i++)
- wbuf[i] = rand();
-
- if (keep_contents) {
- printf("\r%08x: reading... ", (unsigned)test_ofs);
- fflush(stdout);
-
- len = pread(fd, kbuf, meminfo.erasesize, test_ofs);
- if (len < meminfo.erasesize) {
- printf("\n");
- if (len)
- fprintf(stderr, "Short read (%zd bytes)\n", len);
- else
- perror("read");
- exit(1);
- }
- }
- if (erase_and_write(test_ofs, wbuf, rbuf, nr_reads))
- continue;
- if (keep_contents)
- erase_and_write(test_ofs, kbuf, rbuf, 1);
- }
- printf("\nFinished pass %d successfully\n", pass+1);
- }
- /* Return happy */
- return 0;
-}