Commit 3e3d5815cbc1fdbf33adbe55f63ede3acead886f

Authored by balrog
1 parent 18c9b560

NAND Flash memory emulation and ECC calculation helpers for use by NAND controllers.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2753 c046a42c-6fe2-441c-8c8c-71466251a162
ecc.h 0 → 100644
  1 +/*
  2 + * Calculate Error-correcting Codes. Used by NAND Flash controllers
  3 + * (not by NAND chips).
  4 + *
  5 + * Copyright (c) 2006 Openedhand Ltd.
  6 + * Written by Andrzej Zaborowski <balrog@zabor.org>
  7 + *
  8 + * This code is licensed under the GNU GPL v2.
  9 + */
  10 +
  11 +struct ecc_state_s {
  12 + uint8_t cp; /* Column parity */
  13 + uint16_t lp[2]; /* Line parity */
  14 + uint16_t count;
  15 +};
  16 +
  17 +/*
  18 + * Pre-calculated 256-way 1 byte column parity. Table borrowed from Linux.
  19 + */
  20 +static const uint8_t nand_ecc_precalc_table[] = {
  21 + 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a,
  22 + 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
  23 + 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f,
  24 + 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
  25 + 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c,
  26 + 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
  27 + 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59,
  28 + 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
  29 + 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33,
  30 + 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
  31 + 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56,
  32 + 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
  33 + 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55,
  34 + 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
  35 + 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30,
  36 + 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
  37 + 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30,
  38 + 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
  39 + 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55,
  40 + 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
  41 + 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56,
  42 + 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
  43 + 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33,
  44 + 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
  45 + 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59,
  46 + 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
  47 + 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c,
  48 + 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
  49 + 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f,
  50 + 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
  51 + 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a,
  52 + 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
  53 +};
  54 +
  55 +/* Update ECC parity count. */
  56 +static inline uint8_t ecc_digest(struct ecc_state_s *s, uint8_t sample)
  57 +{
  58 + uint8_t idx = nand_ecc_precalc_table[sample];
  59 +
  60 + s->cp ^= idx & 0x3f;
  61 + if (idx & 0x40) {
  62 + s->lp[0] ^= ~s->count;
  63 + s->lp[1] ^= s->count;
  64 + }
  65 + s->count ++;
  66 +
  67 + return sample;
  68 +}
  69 +
  70 +/* Reinitialise the counters. */
  71 +static inline void ecc_reset(struct ecc_state_s *s)
  72 +{
  73 + s->lp[0] = 0x0000;
  74 + s->lp[1] = 0x0000;
  75 + s->cp = 0x00;
  76 + s->count = 0;
  77 +}
... ...
hw/nand.c 0 → 100644
  1 +/*
  2 + * Flash NAND memory emulation. Based on "16M x 8 Bit NAND Flash
  3 + * Memory" datasheet for the KM29U128AT / K9F2808U0A chips from
  4 + * Samsung Electronic.
  5 + *
  6 + * Copyright (c) 2006 Openedhand Ltd.
  7 + * Written by Andrzej Zaborowski <balrog@zabor.org>
  8 + *
  9 + * This code is licensed under the GNU GPL v2.
  10 + */
  11 +
  12 +#ifndef NAND_IO
  13 +
  14 +# include "vl.h"
  15 +
  16 +# define NAND_CMD_READ0 0x00
  17 +# define NAND_CMD_READ1 0x01
  18 +# define NAND_CMD_READ2 0x50
  19 +# define NAND_CMD_LPREAD2 0x30
  20 +# define NAND_CMD_NOSERIALREAD2 0x35
  21 +# define NAND_CMD_RANDOMREAD1 0x05
  22 +# define NAND_CMD_RANDOMREAD2 0xe0
  23 +# define NAND_CMD_READID 0x90
  24 +# define NAND_CMD_RESET 0xff
  25 +# define NAND_CMD_PAGEPROGRAM1 0x80
  26 +# define NAND_CMD_PAGEPROGRAM2 0x10
  27 +# define NAND_CMD_CACHEPROGRAM2 0x15
  28 +# define NAND_CMD_BLOCKERASE1 0x60
  29 +# define NAND_CMD_BLOCKERASE2 0xd0
  30 +# define NAND_CMD_READSTATUS 0x70
  31 +# define NAND_CMD_COPYBACKPRG1 0x85
  32 +
  33 +# define NAND_IOSTATUS_ERROR (1 << 0)
  34 +# define NAND_IOSTATUS_PLANE0 (1 << 1)
  35 +# define NAND_IOSTATUS_PLANE1 (1 << 2)
  36 +# define NAND_IOSTATUS_PLANE2 (1 << 3)
  37 +# define NAND_IOSTATUS_PLANE3 (1 << 4)
  38 +# define NAND_IOSTATUS_BUSY (1 << 6)
  39 +# define NAND_IOSTATUS_UNPROTCT (1 << 7)
  40 +
  41 +# define MAX_PAGE 0x800
  42 +# define MAX_OOB 0x40
  43 +
  44 +struct nand_flash_s {
  45 + uint8_t manf_id, chip_id;
  46 + int size, pages;
  47 + int page_shift, oob_shift, erase_shift, addr_shift;
  48 + uint8_t *storage;
  49 + BlockDriverState *bdrv;
  50 + int mem_oob;
  51 +
  52 + int cle, ale, ce, wp, gnd;
  53 +
  54 + uint8_t io[MAX_PAGE + MAX_OOB + 0x400];
  55 + uint8_t *ioaddr;
  56 + int iolen;
  57 +
  58 + uint32_t cmd, addr;
  59 + int addrlen;
  60 + int status;
  61 + int offset;
  62 +
  63 + void (*blk_write)(struct nand_flash_s *s);
  64 + void (*blk_erase)(struct nand_flash_s *s);
  65 + void (*blk_load)(struct nand_flash_s *s, uint32_t addr, int offset);
  66 +};
  67 +
  68 +# define NAND_NO_AUTOINCR 0x00000001
  69 +# define NAND_BUSWIDTH_16 0x00000002
  70 +# define NAND_NO_PADDING 0x00000004
  71 +# define NAND_CACHEPRG 0x00000008
  72 +# define NAND_COPYBACK 0x00000010
  73 +# define NAND_IS_AND 0x00000020
  74 +# define NAND_4PAGE_ARRAY 0x00000040
  75 +# define NAND_NO_READRDY 0x00000100
  76 +# define NAND_SAMSUNG_LP (NAND_NO_PADDING | NAND_COPYBACK)
  77 +
  78 +# define NAND_IO
  79 +
  80 +# define PAGE(addr) ((addr) >> ADDR_SHIFT)
  81 +# define PAGE_START(page) (PAGE(page) * (PAGE_SIZE + OOB_SIZE))
  82 +# define PAGE_MASK ((1 << ADDR_SHIFT) - 1)
  83 +# define OOB_SHIFT (PAGE_SHIFT - 5)
  84 +# define OOB_SIZE (1 << OOB_SHIFT)
  85 +# define SECTOR(addr) ((addr) >> (9 + ADDR_SHIFT - PAGE_SHIFT))
  86 +# define SECTOR_OFFSET(addr) ((addr) & ((511 >> PAGE_SHIFT) << 8))
  87 +
  88 +# define PAGE_SIZE 256
  89 +# define PAGE_SHIFT 8
  90 +# define PAGE_SECTORS 1
  91 +# define ADDR_SHIFT 8
  92 +# include "nand.c"
  93 +# define PAGE_SIZE 512
  94 +# define PAGE_SHIFT 9
  95 +# define PAGE_SECTORS 1
  96 +# define ADDR_SHIFT 8
  97 +# include "nand.c"
  98 +# define PAGE_SIZE 2048
  99 +# define PAGE_SHIFT 11
  100 +# define PAGE_SECTORS 4
  101 +# define ADDR_SHIFT 16
  102 +# include "nand.c"
  103 +
  104 +/* Information based on Linux drivers/mtd/nand/nand_ids.c */
  105 +struct nand_info_s {
  106 + int size;
  107 + int width;
  108 + int page_shift;
  109 + int erase_shift;
  110 + uint32_t options;
  111 +} nand_flash_ids[0x100] = {
  112 + [0 ... 0xff] = { 0 },
  113 +
  114 + [0x6e] = { 1, 8, 8, 4, 0 },
  115 + [0x64] = { 2, 8, 8, 4, 0 },
  116 + [0x6b] = { 4, 8, 9, 4, 0 },
  117 + [0xe8] = { 1, 8, 8, 4, 0 },
  118 + [0xec] = { 1, 8, 8, 4, 0 },
  119 + [0xea] = { 2, 8, 8, 4, 0 },
  120 + [0xd5] = { 4, 8, 9, 4, 0 },
  121 + [0xe3] = { 4, 8, 9, 4, 0 },
  122 + [0xe5] = { 4, 8, 9, 4, 0 },
  123 + [0xd6] = { 8, 8, 9, 4, 0 },
  124 +
  125 + [0x39] = { 8, 8, 9, 4, 0 },
  126 + [0xe6] = { 8, 8, 9, 4, 0 },
  127 + [0x49] = { 8, 16, 9, 4, NAND_BUSWIDTH_16 },
  128 + [0x59] = { 8, 16, 9, 4, NAND_BUSWIDTH_16 },
  129 +
  130 + [0x33] = { 16, 8, 9, 5, 0 },
  131 + [0x73] = { 16, 8, 9, 5, 0 },
  132 + [0x43] = { 16, 16, 9, 5, NAND_BUSWIDTH_16 },
  133 + [0x53] = { 16, 16, 9, 5, NAND_BUSWIDTH_16 },
  134 +
  135 + [0x35] = { 32, 8, 9, 5, 0 },
  136 + [0x75] = { 32, 8, 9, 5, 0 },
  137 + [0x45] = { 32, 16, 9, 5, NAND_BUSWIDTH_16 },
  138 + [0x55] = { 32, 16, 9, 5, NAND_BUSWIDTH_16 },
  139 +
  140 + [0x36] = { 64, 8, 9, 5, 0 },
  141 + [0x76] = { 64, 8, 9, 5, 0 },
  142 + [0x46] = { 64, 16, 9, 5, NAND_BUSWIDTH_16 },
  143 + [0x56] = { 64, 16, 9, 5, NAND_BUSWIDTH_16 },
  144 +
  145 + [0x78] = { 128, 8, 9, 5, 0 },
  146 + [0x39] = { 128, 8, 9, 5, 0 },
  147 + [0x79] = { 128, 8, 9, 5, 0 },
  148 + [0x72] = { 128, 16, 9, 5, NAND_BUSWIDTH_16 },
  149 + [0x49] = { 128, 16, 9, 5, NAND_BUSWIDTH_16 },
  150 + [0x74] = { 128, 16, 9, 5, NAND_BUSWIDTH_16 },
  151 + [0x59] = { 128, 16, 9, 5, NAND_BUSWIDTH_16 },
  152 +
  153 + [0x71] = { 256, 8, 9, 5, 0 },
  154 +
  155 + /*
  156 + * These are the new chips with large page size. The pagesize and the
  157 + * erasesize is determined from the extended id bytes
  158 + */
  159 +# define LP_OPTIONS (NAND_SAMSUNG_LP | NAND_NO_READRDY | NAND_NO_AUTOINCR)
  160 +# define LP_OPTIONS16 (LP_OPTIONS | NAND_BUSWIDTH_16)
  161 +
  162 + /* 512 Megabit */
  163 + [0xa2] = { 64, 8, 0, 0, LP_OPTIONS },
  164 + [0xf2] = { 64, 8, 0, 0, LP_OPTIONS },
  165 + [0xb2] = { 64, 16, 0, 0, LP_OPTIONS16 },
  166 + [0xc2] = { 64, 16, 0, 0, LP_OPTIONS16 },
  167 +
  168 + /* 1 Gigabit */
  169 + [0xa1] = { 128, 8, 0, 0, LP_OPTIONS },
  170 + [0xf1] = { 128, 8, 0, 0, LP_OPTIONS },
  171 + [0xb1] = { 128, 16, 0, 0, LP_OPTIONS16 },
  172 + [0xc1] = { 128, 16, 0, 0, LP_OPTIONS16 },
  173 +
  174 + /* 2 Gigabit */
  175 + [0xaa] = { 256, 8, 0, 0, LP_OPTIONS },
  176 + [0xda] = { 256, 8, 0, 0, LP_OPTIONS },
  177 + [0xba] = { 256, 16, 0, 0, LP_OPTIONS16 },
  178 + [0xca] = { 256, 16, 0, 0, LP_OPTIONS16 },
  179 +
  180 + /* 4 Gigabit */
  181 + [0xac] = { 512, 8, 0, 0, LP_OPTIONS },
  182 + [0xdc] = { 512, 8, 0, 0, LP_OPTIONS },
  183 + [0xbc] = { 512, 16, 0, 0, LP_OPTIONS16 },
  184 + [0xcc] = { 512, 16, 0, 0, LP_OPTIONS16 },
  185 +
  186 + /* 8 Gigabit */
  187 + [0xa3] = { 1024, 8, 0, 0, LP_OPTIONS },
  188 + [0xd3] = { 1024, 8, 0, 0, LP_OPTIONS },
  189 + [0xb3] = { 1024, 16, 0, 0, LP_OPTIONS16 },
  190 + [0xc3] = { 1024, 16, 0, 0, LP_OPTIONS16 },
  191 +
  192 + /* 16 Gigabit */
  193 + [0xa5] = { 2048, 8, 0, 0, LP_OPTIONS },
  194 + [0xd5] = { 2048, 8, 0, 0, LP_OPTIONS },
  195 + [0xb5] = { 2048, 16, 0, 0, LP_OPTIONS16 },
  196 + [0xc5] = { 2048, 16, 0, 0, LP_OPTIONS16 },
  197 +};
  198 +
  199 +static void nand_reset(struct nand_flash_s *s)
  200 +{
  201 + s->cmd = NAND_CMD_READ0;
  202 + s->addr = 0;
  203 + s->addrlen = 0;
  204 + s->iolen = 0;
  205 + s->offset = 0;
  206 + s->status &= NAND_IOSTATUS_UNPROTCT;
  207 +}
  208 +
  209 +static void nand_command(struct nand_flash_s *s)
  210 +{
  211 + switch (s->cmd) {
  212 + case NAND_CMD_READ0:
  213 + s->iolen = 0;
  214 + break;
  215 +
  216 + case NAND_CMD_READID:
  217 + s->io[0] = s->manf_id;
  218 + s->io[1] = s->chip_id;
  219 + s->io[2] = 'Q'; /* Don't-care byte (often 0xa5) */
  220 + if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP)
  221 + s->io[3] = 0x15; /* Page Size, Block Size, Spare Size.. */
  222 + else
  223 + s->io[3] = 0xc0; /* Multi-plane */
  224 + s->ioaddr = s->io;
  225 + s->iolen = 4;
  226 + break;
  227 +
  228 + case NAND_CMD_RANDOMREAD2:
  229 + case NAND_CMD_NOSERIALREAD2:
  230 + if (!(nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP))
  231 + break;
  232 +
  233 + s->blk_load(s, s->addr, s->addr & ((1 << s->addr_shift) - 1));
  234 + break;
  235 +
  236 + case NAND_CMD_RESET:
  237 + nand_reset(s);
  238 + break;
  239 +
  240 + case NAND_CMD_PAGEPROGRAM1:
  241 + s->ioaddr = s->io;
  242 + s->iolen = 0;
  243 + break;
  244 +
  245 + case NAND_CMD_PAGEPROGRAM2:
  246 + if (s->wp) {
  247 + s->blk_write(s);
  248 + }
  249 + break;
  250 +
  251 + case NAND_CMD_BLOCKERASE1:
  252 + break;
  253 +
  254 + case NAND_CMD_BLOCKERASE2:
  255 + if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP)
  256 + s->addr <<= 16;
  257 + else
  258 + s->addr <<= 8;
  259 +
  260 + if (s->wp) {
  261 + s->blk_erase(s);
  262 + }
  263 + break;
  264 +
  265 + case NAND_CMD_READSTATUS:
  266 + s->io[0] = s->status;
  267 + s->ioaddr = s->io;
  268 + s->iolen = 1;
  269 + break;
  270 +
  271 + default:
  272 + printf("%s: Unknown NAND command 0x%02x\n", __FUNCTION__, s->cmd);
  273 + }
  274 +}
  275 +
  276 +/*
  277 + * Chip inputs are CLE, ALE, CE, WP, GND and eight I/O pins. Chip
  278 + * outputs are R/B and eight I/O pins.
  279 + *
  280 + * CE, WP and R/B are active low.
  281 + */
  282 +void nand_setpins(struct nand_flash_s *s,
  283 + int cle, int ale, int ce, int wp, int gnd)
  284 +{
  285 + s->cle = cle;
  286 + s->ale = ale;
  287 + s->ce = ce;
  288 + s->wp = wp;
  289 + s->gnd = gnd;
  290 + if (wp)
  291 + s->status |= NAND_IOSTATUS_UNPROTCT;
  292 + else
  293 + s->status &= ~NAND_IOSTATUS_UNPROTCT;
  294 +}
  295 +
  296 +void nand_getpins(struct nand_flash_s *s, int *rb)
  297 +{
  298 + *rb = 1;
  299 +}
  300 +
  301 +void nand_setio(struct nand_flash_s *s, uint8_t value)
  302 +{
  303 + if (!s->ce && s->cle) {
  304 + if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) {
  305 + if (s->cmd == NAND_CMD_READ0 && value == NAND_CMD_LPREAD2)
  306 + return;
  307 + if (value == NAND_CMD_RANDOMREAD1) {
  308 + s->addr &= ~((1 << s->addr_shift) - 1);
  309 + s->addrlen = 0;
  310 + return;
  311 + }
  312 + }
  313 + if (value == NAND_CMD_READ0)
  314 + s->offset = 0;
  315 + else if (value == NAND_CMD_READ1) {
  316 + s->offset = 0x100;
  317 + value = NAND_CMD_READ0;
  318 + }
  319 + else if (value == NAND_CMD_READ2) {
  320 + s->offset = 1 << s->page_shift;
  321 + value = NAND_CMD_READ0;
  322 + }
  323 +
  324 + s->cmd = value;
  325 +
  326 + if (s->cmd == NAND_CMD_READSTATUS ||
  327 + s->cmd == NAND_CMD_PAGEPROGRAM2 ||
  328 + s->cmd == NAND_CMD_BLOCKERASE1 ||
  329 + s->cmd == NAND_CMD_BLOCKERASE2 ||
  330 + s->cmd == NAND_CMD_NOSERIALREAD2 ||
  331 + s->cmd == NAND_CMD_RANDOMREAD2 ||
  332 + s->cmd == NAND_CMD_RESET)
  333 + nand_command(s);
  334 +
  335 + if (s->cmd != NAND_CMD_RANDOMREAD2) {
  336 + s->addrlen = 0;
  337 + s->addr = 0;
  338 + }
  339 + }
  340 +
  341 + if (s->ale) {
  342 + s->addr |= value << (s->addrlen * 8);
  343 + s->addrlen ++;
  344 +
  345 + if (s->addrlen == 1 && s->cmd == NAND_CMD_READID)
  346 + nand_command(s);
  347 +
  348 + if (!(nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) &&
  349 + s->addrlen == 3 && (
  350 + s->cmd == NAND_CMD_READ0 ||
  351 + s->cmd == NAND_CMD_PAGEPROGRAM1))
  352 + nand_command(s);
  353 + if ((nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) &&
  354 + s->addrlen == 4 && (
  355 + s->cmd == NAND_CMD_READ0 ||
  356 + s->cmd == NAND_CMD_PAGEPROGRAM1))
  357 + nand_command(s);
  358 + }
  359 +
  360 + if (!s->cle && !s->ale && s->cmd == NAND_CMD_PAGEPROGRAM1) {
  361 + if (s->iolen < (1 << s->page_shift) + (1 << s->oob_shift))
  362 + s->io[s->iolen ++] = value;
  363 + } else if (!s->cle && !s->ale && s->cmd == NAND_CMD_COPYBACKPRG1) {
  364 + if ((s->addr & ((1 << s->addr_shift) - 1)) <
  365 + (1 << s->page_shift) + (1 << s->oob_shift)) {
  366 + s->io[s->iolen + (s->addr & ((1 << s->addr_shift) - 1))] = value;
  367 + s->addr ++;
  368 + }
  369 + }
  370 +}
  371 +
  372 +uint8_t nand_getio(struct nand_flash_s *s)
  373 +{
  374 + int offset;
  375 +
  376 + /* Allow sequential reading */
  377 + if (!s->iolen && s->cmd == NAND_CMD_READ0) {
  378 + offset = (s->addr & ((1 << s->addr_shift) - 1)) + s->offset;
  379 + s->offset = 0;
  380 +
  381 + s->blk_load(s, s->addr, offset);
  382 + if (s->gnd)
  383 + s->iolen = (1 << s->page_shift) - offset;
  384 + else
  385 + s->iolen = (1 << s->page_shift) + (1 << s->oob_shift) - offset;
  386 + }
  387 +
  388 + if (s->ce || s->iolen <= 0)
  389 + return 0;
  390 +
  391 + s->iolen --;
  392 + return *(s->ioaddr ++);
  393 +}
  394 +
  395 +struct nand_flash_s *nand_init(int manf_id, int chip_id)
  396 +{
  397 + int pagesize;
  398 + struct nand_flash_s *s;
  399 +
  400 + if (nand_flash_ids[chip_id].size == 0) {
  401 + cpu_abort(cpu_single_env, "%s: Unsupported NAND chip ID.\n",
  402 + __FUNCTION__);
  403 + }
  404 +
  405 + s = (struct nand_flash_s *) qemu_mallocz(sizeof(struct nand_flash_s));
  406 + s->bdrv = mtd_bdrv;
  407 + s->manf_id = manf_id;
  408 + s->chip_id = chip_id;
  409 + s->size = nand_flash_ids[s->chip_id].size << 20;
  410 + if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) {
  411 + s->page_shift = 11;
  412 + s->erase_shift = 6;
  413 + } else {
  414 + s->page_shift = nand_flash_ids[s->chip_id].page_shift;
  415 + s->erase_shift = nand_flash_ids[s->chip_id].erase_shift;
  416 + }
  417 +
  418 + switch (1 << s->page_shift) {
  419 + case 256:
  420 + nand_init_256(s);
  421 + break;
  422 + case 512:
  423 + nand_init_512(s);
  424 + break;
  425 + case 2048:
  426 + nand_init_2048(s);
  427 + break;
  428 + default:
  429 + cpu_abort(cpu_single_env, "%s: Unsupported NAND block size.\n",
  430 + __FUNCTION__);
  431 + }
  432 +
  433 + pagesize = 1 << s->oob_shift;
  434 + s->mem_oob = 1;
  435 + if (s->bdrv && bdrv_getlength(s->bdrv) >=
  436 + (s->pages << s->page_shift) + (s->pages << s->oob_shift)) {
  437 + pagesize = 0;
  438 + s->mem_oob = 0;
  439 + }
  440 +
  441 + if (!s->bdrv)
  442 + pagesize += 1 << s->page_shift;
  443 + if (pagesize)
  444 + s->storage = (uint8_t *) memset(qemu_malloc(s->pages * pagesize),
  445 + 0xff, s->pages * pagesize);
  446 + return s;
  447 +}
  448 +
  449 +void nand_done(struct nand_flash_s *s)
  450 +{
  451 + if (s->bdrv) {
  452 + bdrv_close(s->bdrv);
  453 + bdrv_delete(s->bdrv);
  454 + }
  455 +
  456 + if (!s->bdrv || s->mem_oob)
  457 + free(s->storage);
  458 +
  459 + free(s);
  460 +}
  461 +
  462 +#else
  463 +
  464 +/* Program a single page */
  465 +static void glue(nand_blk_write_, PAGE_SIZE)(struct nand_flash_s *s)
  466 +{
  467 + uint32_t off, page, sector, soff;
  468 + uint8_t iobuf[(PAGE_SECTORS + 2) * 0x200];
  469 + if (PAGE(s->addr) >= s->pages)
  470 + return;
  471 +
  472 + if (!s->bdrv) {
  473 + memcpy(s->storage + PAGE_START(s->addr) + (s->addr & PAGE_MASK) +
  474 + s->offset, s->io, s->iolen);
  475 + } else if (s->mem_oob) {
  476 + sector = SECTOR(s->addr);
  477 + off = (s->addr & PAGE_MASK) + s->offset;
  478 + soff = SECTOR_OFFSET(s->addr);
  479 + if (bdrv_read(s->bdrv, sector, iobuf, PAGE_SECTORS) == -1) {
  480 + printf("%s: read error in sector %i\n", __FUNCTION__, sector);
  481 + return;
  482 + }
  483 +
  484 + memcpy(iobuf + (soff | off), s->io, MIN(s->iolen, PAGE_SIZE - off));
  485 + if (off + s->iolen > PAGE_SIZE) {
  486 + page = PAGE(s->addr);
  487 + memcpy(s->storage + (page << OOB_SHIFT), s->io + PAGE_SIZE - off,
  488 + MIN(OOB_SIZE, off + s->iolen - PAGE_SIZE));
  489 + }
  490 +
  491 + if (bdrv_write(s->bdrv, sector, iobuf, PAGE_SECTORS) == -1)
  492 + printf("%s: write error in sector %i\n", __FUNCTION__, sector);
  493 + } else {
  494 + off = PAGE_START(s->addr) + (s->addr & PAGE_MASK) + s->offset;
  495 + sector = off >> 9;
  496 + soff = off & 0x1ff;
  497 + if (bdrv_read(s->bdrv, sector, iobuf, PAGE_SECTORS + 2) == -1) {
  498 + printf("%s: read error in sector %i\n", __FUNCTION__, sector);
  499 + return;
  500 + }
  501 +
  502 + memcpy(iobuf + soff, s->io, s->iolen);
  503 +
  504 + if (bdrv_write(s->bdrv, sector, iobuf, PAGE_SECTORS + 2) == -1)
  505 + printf("%s: write error in sector %i\n", __FUNCTION__, sector);
  506 + }
  507 + s->offset = 0;
  508 +}
  509 +
  510 +/* Erase a single block */
  511 +static void glue(nand_blk_erase_, PAGE_SIZE)(struct nand_flash_s *s)
  512 +{
  513 + uint32_t i, page, addr;
  514 + uint8_t iobuf[0x200] = { [0 ... 0x1ff] = 0xff, };
  515 + addr = s->addr & ~((1 << (ADDR_SHIFT + s->erase_shift)) - 1);
  516 +
  517 + if (PAGE(addr) >= s->pages)
  518 + return;
  519 +
  520 + if (!s->bdrv) {
  521 + memset(s->storage + PAGE_START(addr),
  522 + 0xff, (PAGE_SIZE + OOB_SIZE) << s->erase_shift);
  523 + } else if (s->mem_oob) {
  524 + memset(s->storage + (PAGE(addr) << OOB_SHIFT),
  525 + 0xff, OOB_SIZE << s->erase_shift);
  526 + i = SECTOR(addr);
  527 + page = SECTOR(addr + (ADDR_SHIFT + s->erase_shift));
  528 + for (; i < page; i ++)
  529 + if (bdrv_write(s->bdrv, i, iobuf, 1) == -1)
  530 + printf("%s: write error in sector %i\n", __FUNCTION__, i);
  531 + } else {
  532 + addr = PAGE_START(addr);
  533 + page = addr >> 9;
  534 + if (bdrv_read(s->bdrv, page, iobuf, 1) == -1)
  535 + printf("%s: read error in sector %i\n", __FUNCTION__, page);
  536 + memset(iobuf + (addr & 0x1ff), 0xff, (~addr & 0x1ff) + 1);
  537 + if (bdrv_write(s->bdrv, page, iobuf, 1) == -1)
  538 + printf("%s: write error in sector %i\n", __FUNCTION__, page);
  539 +
  540 + memset(iobuf, 0xff, 0x200);
  541 + i = (addr & ~0x1ff) + 0x200;
  542 + for (addr += ((PAGE_SIZE + OOB_SIZE) << s->erase_shift) - 0x200;
  543 + i < addr; i += 0x200)
  544 + if (bdrv_write(s->bdrv, i >> 9, iobuf, 1) == -1)
  545 + printf("%s: write error in sector %i\n", __FUNCTION__, i >> 9);
  546 +
  547 + page = i >> 9;
  548 + if (bdrv_read(s->bdrv, page, iobuf, 1) == -1)
  549 + printf("%s: read error in sector %i\n", __FUNCTION__, page);
  550 + memset(iobuf, 0xff, addr & 0x1ff);
  551 + if (bdrv_write(s->bdrv, page, iobuf, 1) == -1)
  552 + printf("%s: write error in sector %i\n", __FUNCTION__, page);
  553 + }
  554 +}
  555 +
  556 +static void glue(nand_blk_load_, PAGE_SIZE)(struct nand_flash_s *s,
  557 + uint32_t addr, int offset)
  558 +{
  559 + if (PAGE(addr) >= s->pages)
  560 + return;
  561 +
  562 + if (s->bdrv) {
  563 + if (s->mem_oob) {
  564 + if (bdrv_read(s->bdrv, SECTOR(addr), s->io, PAGE_SECTORS) == -1)
  565 + printf("%s: read error in sector %i\n",
  566 + __FUNCTION__, SECTOR(addr));
  567 + memcpy(s->io + SECTOR_OFFSET(s->addr) + PAGE_SIZE,
  568 + s->storage + (PAGE(s->addr) << OOB_SHIFT),
  569 + OOB_SIZE);
  570 + s->ioaddr = s->io + SECTOR_OFFSET(s->addr) + offset;
  571 + } else {
  572 + if (bdrv_read(s->bdrv, PAGE_START(addr) >> 9,
  573 + s->io, (PAGE_SECTORS + 2)) == -1)
  574 + printf("%s: read error in sector %i\n",
  575 + __FUNCTION__, PAGE_START(addr) >> 9);
  576 + s->ioaddr = s->io + (PAGE_START(addr) & 0x1ff) + offset;
  577 + }
  578 + } else {
  579 + memcpy(s->io, s->storage + PAGE_START(s->addr) +
  580 + offset, PAGE_SIZE + OOB_SIZE - offset);
  581 + s->ioaddr = s->io;
  582 + }
  583 +
  584 + s->addr &= PAGE_SIZE - 1;
  585 + s->addr += PAGE_SIZE;
  586 +}
  587 +
  588 +static void glue(nand_init_, PAGE_SIZE)(struct nand_flash_s *s)
  589 +{
  590 + s->oob_shift = PAGE_SHIFT - 5;
  591 + s->pages = s->size >> PAGE_SHIFT;
  592 + s->addr_shift = ADDR_SHIFT;
  593 +
  594 + s->blk_erase = glue(nand_blk_erase_, PAGE_SIZE);
  595 + s->blk_write = glue(nand_blk_write_, PAGE_SIZE);
  596 + s->blk_load = glue(nand_blk_load_, PAGE_SIZE);
  597 +}
  598 +
  599 +# undef PAGE_SIZE
  600 +# undef PAGE_SHIFT
  601 +# undef PAGE_SECTORS
  602 +# undef ADDR_SHIFT
  603 +#endif /* NAND_IO */
... ...
... ... @@ -140,6 +140,7 @@ IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS];
140 140 BlockDriverState *bs_table[MAX_DISKS + 1], *fd_table[MAX_FD];
141 141 BlockDriverState *pflash_table[MAX_PFLASH];
142 142 BlockDriverState *sd_bdrv;
  143 +BlockDriverState *mtd_bdrv;
143 144 /* point to the block driver where the snapshots are managed */
144 145 BlockDriverState *bs_snapshots;
145 146 int vga_ram_size;
... ... @@ -6419,6 +6420,7 @@ void help(void)
6419 6420 "-hda/-hdb file use 'file' as IDE hard disk 0/1 image\n"
6420 6421 "-hdc/-hdd file use 'file' as IDE hard disk 2/3 image\n"
6421 6422 "-cdrom file use 'file' as IDE cdrom image (cdrom is ide1 master)\n"
  6423 + "-mtdblock file use 'file' as on-board Flash memory image\n"
6422 6424 "-sd file use 'file' as SecureDigital card image\n"
6423 6425 "-pflash file use 'file' as a parallel flash image\n"
6424 6426 "-boot [a|c|d|n] boot on floppy (a), hard disk (c), CD-ROM (d), or network (n)\n"
... ... @@ -6559,6 +6561,7 @@ enum {
6559 6561 QEMU_OPTION_hdc,
6560 6562 QEMU_OPTION_hdd,
6561 6563 QEMU_OPTION_cdrom,
  6564 + QEMU_OPTION_mtdblock,
6562 6565 QEMU_OPTION_sd,
6563 6566 QEMU_OPTION_pflash,
6564 6567 QEMU_OPTION_boot,
... ... @@ -6640,6 +6643,7 @@ const QEMUOption qemu_options[] = {
6640 6643 { "hdc", HAS_ARG, QEMU_OPTION_hdc },
6641 6644 { "hdd", HAS_ARG, QEMU_OPTION_hdd },
6642 6645 { "cdrom", HAS_ARG, QEMU_OPTION_cdrom },
  6646 + { "mtdblock", HAS_ARG, QEMU_OPTION_mtdblock },
6643 6647 { "sd", HAS_ARG, QEMU_OPTION_sd },
6644 6648 { "pflash", HAS_ARG, QEMU_OPTION_pflash },
6645 6649 { "boot", HAS_ARG, QEMU_OPTION_boot },
... ... @@ -6944,6 +6948,7 @@ int main(int argc, char **argv)
6944 6948 const char *hd_filename[MAX_DISKS], *fd_filename[MAX_FD];
6945 6949 const char *pflash_filename[MAX_PFLASH];
6946 6950 const char *sd_filename;
  6951 + const char *mtd_filename;
6947 6952 const char *kernel_filename, *kernel_cmdline;
6948 6953 DisplayState *ds = &display_state;
6949 6954 int cyls, heads, secs, translation;
... ... @@ -7008,6 +7013,7 @@ int main(int argc, char **argv)
7008 7013 pflash_filename[i] = NULL;
7009 7014 pflash_index = 0;
7010 7015 sd_filename = NULL;
  7016 + mtd_filename = NULL;
7011 7017 ram_size = DEFAULT_RAM_SIZE * 1024 * 1024;
7012 7018 vga_ram_size = VGA_RAM_SIZE;
7013 7019 #ifdef CONFIG_GDBSTUB
... ... @@ -7126,6 +7132,9 @@ int main(int argc, char **argv)
7126 7132 cdrom_index = -1;
7127 7133 }
7128 7134 break;
  7135 + case QEMU_OPTION_mtdblock:
  7136 + mtd_filename = optarg;
  7137 + break;
7129 7138 case QEMU_OPTION_sd:
7130 7139 sd_filename = optarg;
7131 7140 break;
... ... @@ -7678,6 +7687,18 @@ int main(int argc, char **argv)
7678 7687 qemu_key_check(sd_bdrv, sd_filename);
7679 7688 }
7680 7689  
  7690 + if (mtd_filename) {
  7691 + mtd_bdrv = bdrv_new ("mtd");
  7692 + if (bdrv_open(mtd_bdrv, mtd_filename,
  7693 + snapshot ? BDRV_O_SNAPSHOT : 0) < 0 ||
  7694 + qemu_key_check(mtd_bdrv, mtd_filename)) {
  7695 + fprintf(stderr, "qemu: could not open Flash image %s\n",
  7696 + mtd_filename);
  7697 + bdrv_delete(mtd_bdrv);
  7698 + mtd_bdrv = 0;
  7699 + }
  7700 + }
  7701 +
7681 7702 register_savevm("timer", 0, 2, timer_save, timer_load, NULL);
7682 7703 register_savevm("ram", 0, 2, ram_save, ram_load, NULL);
7683 7704  
... ...
... ... @@ -967,6 +967,7 @@ extern uint8_t _translate_keycode(const int key);
967 967  
968 968 extern BlockDriverState *bs_table[MAX_DISKS + 1];
969 969 extern BlockDriverState *sd_bdrv;
  970 +extern BlockDriverState *mtd_bdrv;
970 971  
971 972 void isa_ide_init(int iobase, int iobase2, qemu_irq irq,
972 973 BlockDriverState *hd0, BlockDriverState *hd1);
... ... @@ -1478,6 +1479,27 @@ pflash_t *pflash_register (target_ulong base, ram_addr_t off,
1478 1479 uint16_t id0, uint16_t id1,
1479 1480 uint16_t id2, uint16_t id3);
1480 1481  
  1482 +/* nand.c */
  1483 +struct nand_flash_s;
  1484 +struct nand_flash_s *nand_init(int manf_id, int chip_id);
  1485 +void nand_done(struct nand_flash_s *s);
  1486 +void nand_setpins(struct nand_flash_s *s,
  1487 + int cle, int ale, int ce, int wp, int gnd);
  1488 +void nand_getpins(struct nand_flash_s *s, int *rb);
  1489 +void nand_setio(struct nand_flash_s *s, uint8_t value);
  1490 +uint8_t nand_getio(struct nand_flash_s *s);
  1491 +
  1492 +#define NAND_MFR_TOSHIBA 0x98
  1493 +#define NAND_MFR_SAMSUNG 0xec
  1494 +#define NAND_MFR_FUJITSU 0x04
  1495 +#define NAND_MFR_NATIONAL 0x8f
  1496 +#define NAND_MFR_RENESAS 0x07
  1497 +#define NAND_MFR_STMICRO 0x20
  1498 +#define NAND_MFR_HYNIX 0xad
  1499 +#define NAND_MFR_MICRON 0x2c
  1500 +
  1501 +#include "ecc.h"
  1502 +
1481 1503 /* PCMCIA/Cardbus */
1482 1504  
1483 1505 struct pcmcia_socket_s {
... ...