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
This commit is contained in:
balrog
2007-04-30 02:09:25 +00:00
parent 18c9b56060
commit 3e3d5815cb
4 changed files with 723 additions and 0 deletions
+77
View File
@@ -0,0 +1,77 @@
/*
* Calculate Error-correcting Codes. Used by NAND Flash controllers
* (not by NAND chips).
*
* Copyright (c) 2006 Openedhand Ltd.
* Written by Andrzej Zaborowski <balrog@zabor.org>
*
* This code is licensed under the GNU GPL v2.
*/
struct ecc_state_s {
uint8_t cp; /* Column parity */
uint16_t lp[2]; /* Line parity */
uint16_t count;
};
/*
* Pre-calculated 256-way 1 byte column parity. Table borrowed from Linux.
*/
static const uint8_t nand_ecc_precalc_table[] = {
0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a,
0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f,
0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c,
0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59,
0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33,
0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56,
0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55,
0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30,
0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30,
0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55,
0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56,
0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33,
0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59,
0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c,
0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f,
0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a,
0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
};
/* Update ECC parity count. */
static inline uint8_t ecc_digest(struct ecc_state_s *s, uint8_t sample)
{
uint8_t idx = nand_ecc_precalc_table[sample];
s->cp ^= idx & 0x3f;
if (idx & 0x40) {
s->lp[0] ^= ~s->count;
s->lp[1] ^= s->count;
}
s->count ++;
return sample;
}
/* Reinitialise the counters. */
static inline void ecc_reset(struct ecc_state_s *s)
{
s->lp[0] = 0x0000;
s->lp[1] = 0x0000;
s->cp = 0x00;
s->count = 0;
}
+603
View File
File diff suppressed because it is too large Load Diff
+21
View File
@@ -140,6 +140,7 @@ IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS];
BlockDriverState *bs_table[MAX_DISKS + 1], *fd_table[MAX_FD];
BlockDriverState *pflash_table[MAX_PFLASH];
BlockDriverState *sd_bdrv;
BlockDriverState *mtd_bdrv;
/* point to the block driver where the snapshots are managed */
BlockDriverState *bs_snapshots;
int vga_ram_size;
@@ -6419,6 +6420,7 @@ void help(void)
"-hda/-hdb file use 'file' as IDE hard disk 0/1 image\n"
"-hdc/-hdd file use 'file' as IDE hard disk 2/3 image\n"
"-cdrom file use 'file' as IDE cdrom image (cdrom is ide1 master)\n"
"-mtdblock file use 'file' as on-board Flash memory image\n"
"-sd file use 'file' as SecureDigital card image\n"
"-pflash file use 'file' as a parallel flash image\n"
"-boot [a|c|d|n] boot on floppy (a), hard disk (c), CD-ROM (d), or network (n)\n"
@@ -6559,6 +6561,7 @@ enum {
QEMU_OPTION_hdc,
QEMU_OPTION_hdd,
QEMU_OPTION_cdrom,
QEMU_OPTION_mtdblock,
QEMU_OPTION_sd,
QEMU_OPTION_pflash,
QEMU_OPTION_boot,
@@ -6640,6 +6643,7 @@ const QEMUOption qemu_options[] = {
{ "hdc", HAS_ARG, QEMU_OPTION_hdc },
{ "hdd", HAS_ARG, QEMU_OPTION_hdd },
{ "cdrom", HAS_ARG, QEMU_OPTION_cdrom },
{ "mtdblock", HAS_ARG, QEMU_OPTION_mtdblock },
{ "sd", HAS_ARG, QEMU_OPTION_sd },
{ "pflash", HAS_ARG, QEMU_OPTION_pflash },
{ "boot", HAS_ARG, QEMU_OPTION_boot },
@@ -6944,6 +6948,7 @@ int main(int argc, char **argv)
const char *hd_filename[MAX_DISKS], *fd_filename[MAX_FD];
const char *pflash_filename[MAX_PFLASH];
const char *sd_filename;
const char *mtd_filename;
const char *kernel_filename, *kernel_cmdline;
DisplayState *ds = &display_state;
int cyls, heads, secs, translation;
@@ -7008,6 +7013,7 @@ int main(int argc, char **argv)
pflash_filename[i] = NULL;
pflash_index = 0;
sd_filename = NULL;
mtd_filename = NULL;
ram_size = DEFAULT_RAM_SIZE * 1024 * 1024;
vga_ram_size = VGA_RAM_SIZE;
#ifdef CONFIG_GDBSTUB
@@ -7126,6 +7132,9 @@ int main(int argc, char **argv)
cdrom_index = -1;
}
break;
case QEMU_OPTION_mtdblock:
mtd_filename = optarg;
break;
case QEMU_OPTION_sd:
sd_filename = optarg;
break;
@@ -7678,6 +7687,18 @@ int main(int argc, char **argv)
qemu_key_check(sd_bdrv, sd_filename);
}
if (mtd_filename) {
mtd_bdrv = bdrv_new ("mtd");
if (bdrv_open(mtd_bdrv, mtd_filename,
snapshot ? BDRV_O_SNAPSHOT : 0) < 0 ||
qemu_key_check(mtd_bdrv, mtd_filename)) {
fprintf(stderr, "qemu: could not open Flash image %s\n",
mtd_filename);
bdrv_delete(mtd_bdrv);
mtd_bdrv = 0;
}
}
register_savevm("timer", 0, 2, timer_save, timer_load, NULL);
register_savevm("ram", 0, 2, ram_save, ram_load, NULL);
+22
View File
@@ -967,6 +967,7 @@ extern uint8_t _translate_keycode(const int key);
extern BlockDriverState *bs_table[MAX_DISKS + 1];
extern BlockDriverState *sd_bdrv;
extern BlockDriverState *mtd_bdrv;
void isa_ide_init(int iobase, int iobase2, qemu_irq irq,
BlockDriverState *hd0, BlockDriverState *hd1);
@@ -1478,6 +1479,27 @@ pflash_t *pflash_register (target_ulong base, ram_addr_t off,
uint16_t id0, uint16_t id1,
uint16_t id2, uint16_t id3);
/* nand.c */
struct nand_flash_s;
struct nand_flash_s *nand_init(int manf_id, int chip_id);
void nand_done(struct nand_flash_s *s);
void nand_setpins(struct nand_flash_s *s,
int cle, int ale, int ce, int wp, int gnd);
void nand_getpins(struct nand_flash_s *s, int *rb);
void nand_setio(struct nand_flash_s *s, uint8_t value);
uint8_t nand_getio(struct nand_flash_s *s);
#define NAND_MFR_TOSHIBA 0x98
#define NAND_MFR_SAMSUNG 0xec
#define NAND_MFR_FUJITSU 0x04
#define NAND_MFR_NATIONAL 0x8f
#define NAND_MFR_RENESAS 0x07
#define NAND_MFR_STMICRO 0x20
#define NAND_MFR_HYNIX 0xad
#define NAND_MFR_MICRON 0x2c
#include "ecc.h"
/* PCMCIA/Cardbus */
struct pcmcia_socket_s {