📄 mtdcore.c
字号:
/* * vivi/drivers/mtd/mtdcore.c: * core for MTD * * Copyright (c) 2001-2004 MIZI Research, Inc. All rights reserved. * * $Id: mtdcore.c,v 1.33 2004/05/24 06:56:40 nandy Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * * 2001-12-23 Janghoon Lyu * - Initial code. * * 2002-02-23 Janghoon Lyu * - Add flash commands. * * 2004-03-23 Janghoon Lyu * - Update MTDs. */#include <config.h>#include <machine.h>#include <mtd/partitions.h>#include <mtd/mtd.h>#include <command.h>#include <serial.h>#include <vstring.h>#include <types.h>#include <errno.h>#include <progressbar.h>extern int bon_do_read(int npart, char *buf, unsigned long pos, size_t size);extern int bon_do_write(int npart, char *buf, unsigned long pos, size_t size);extern int doc_do_write(mtd_partition_t *part, size_t len, const u_char *buf);extern int doc_do_read(mtd_partition_t *part, u_char *buf);struct mtd_info *mymtd = NULL;int add_mtd_device (struct mtd_info *mtd){ mymtd = mtd; return 0;}int del_mtd_device (struct mtd_info *mtd){ mymtd = NULL; return 0;}int mtd_read_raw(u_char *buf, ulong ofs, size_t count){ int retlen; if (MTD_READ(mymtd, ofs, count, &retlen, buf) < 0) return 1; if (retlen != count) return 1; return 0;}int mtd_write_raw(u_char *buf, ulong ofs, size_t count){ int retlen; ulong len; struct erase_info ei; len = (((count >> 14) + 1) << 14); ei.mtd = mymtd; ei.addr = ofs; ei.len = len; ei.retries = 0; ei.callback = NULL; if (MTD_ERASE(mymtd, &ei) < 0) return 1; len = (((count >> 9) + 1) << 9); if (MTD_WRITE(mymtd, ofs, len, &retlen, buf) < 0) return 1; if (retlen != len) return 1; return 0;}int mtd_read_part(char *name, u_char *buf, size_t count){ mtd_partition_t *part; part = get_mtd_partition(name); if (part == NULL) { printk("Unable to find the '%s' partition\n",name); return 1; } switch (part->flag) { case MF_BON:#ifdef CONFIG_MTD_NAND_BON#if 0 if (!count) count = part->used;#endif /* 亲惑 颇萍记狼 矫累困摹俊辑. */ bon_do_read(*(int *)(part->priv), buf, 0, part->size);#else return 1;#endif /* CONFIG_MTD_NAND_BON */ break; case MF_DOC:#ifdef CONFIG_MTD_MDOCG3 return doc_do_read(part, buf);#else return 1;#endif /* CONFIG_MTD_MDOCG3 */ break; case MF_RAW: return mtd_read_raw(buf, part->offset, part->size); default: return 1; } return 0;}int mtd_write_part(char *name, u_char *buf, size_t count){ mtd_partition_t *part; part = get_mtd_partition(name); if (part == NULL) { printk("Unable to find the '%s' partition\n",name); return 1; } switch (part->flag) { case MF_BON:#ifdef CONFIG_MTD_NAND_BON /* 亲惑 颇萍记狼 矫累困摹俊辑. */ bon_do_write(*(int *)(part->priv), buf, 0, count);#else return 1;#endif /* CONFIG_MTD_NAND_BON */ break; case MF_DOC:#ifdef CONFIG_MTD_MDOCG3 return doc_do_write(part, buf, count);#else return 1;#endif /* CONFIG_MTD_MDOCG3 */ break; case MF_RAW: return mtd_write_raw(buf, part->offset, count); default: return 1; } return 0;}static intdo_unlock(struct mtd_info *mtd, loff_t ofs, size_t len){ int ret; printk("Unlocking... "); ret = mtd->unlock(mtd, ofs, len); if (ret) { printk("fail\n"); return -1; } printk("ok\n"); return 0;}static intdo_lock(struct mtd_info *mtd, loff_t ofs, size_t len){ int ret; printk("Locking... "); ret = mtd->lock(mtd, ofs, len); if (ret < 0) { printk("fail\n"); return ret; } printk("ok\n"); return 0;}static intdo_erase(struct mtd_info *mtd, loff_t ofs, size_t len){ int ret = 0; struct erase_info erase; printk("Erasing 0x%Lx - 0x%Lx... ", ofs, ofs+len); progressbar_set_total(len); while (len > 0) { erase.addr = ofs; erase.len = mtd->erasesize; ret = mtd->erase(mtd, &erase); if (ret) break; len -= mtd->erasesize; ofs += mtd->erasesize; progressbar(len, BAR_DECREASE); } if (ret) printk("FAIL\n"); else printk("OK\n"); return 0;}static void do_dump(struct mtd_info *mtd, loff_t ofs){ unsigned char readbuf[512]; unsigned char oobbuf[16]; int i; int bs = 512; printk("Dump 0x%x:\n", ofs); if (!mtd->read_ecc) { printk("There is no read_ecc()"); return; } mtd->read_ecc(mtd, ofs, bs, NULL, readbuf, NULL, NULL); for (i = 0; i < bs; i+= 16) { printk("0x%08x: %02x %02x %02x %02x %02x %02x %02x %02x " "%02x %02x %02x %02x %02x %02x %02x %02x\n", (unsigned int)(ofs + i), readbuf[i], readbuf[i+1], readbuf[i+2], readbuf[i+3], readbuf[i+4], readbuf[i+5], readbuf[i+6], readbuf[i+7], readbuf[i+8], readbuf[i+9], readbuf[i+10], readbuf[i+11], readbuf[i+12], readbuf[i+13], readbuf[i+14], readbuf[i+15]); } if (!mtd->read_oob) { printk("There is no read_oob()"); return; } mtd->read_oob(mtd, ofs, mtd->oobsize, NULL, oobbuf); if (mtd->oobsize == 16) { printk("OOB Data: %02x %02x %02x %02x %02x %02x %02x %02x " "%02x %02x %02x %02x %02x %02x %02x %02x\n", oobbuf[0], oobbuf[1], oobbuf[2], oobbuf[3], oobbuf[4], oobbuf[5], oobbuf[6], oobbuf[7], oobbuf[8], oobbuf[9], oobbuf[10], oobbuf[11], oobbuf[12], oobbuf[13], oobbuf[14], oobbuf[15]); } else { printk("OOB Data: %02x %02x %02x %02x %02x %02x %02x %02x", oobbuf[0], oobbuf[1], oobbuf[2], oobbuf[3], oobbuf[4], oobbuf[5], oobbuf[6], oobbuf[7]); }}static void usage(void){ printk("\nUsage:\n" " flash erase <offset> <length> - erase blocks\n" " flash erase all - erase all blocks\n" " flash lock <offset> <length> - lock blocks\n" " flash unlock <offset> <length> - unlock blocks\n" " flash dump <offset> - dump 512 bytes\n" " flash ee - erase bad block\n" " flash de - don't erase bad block\n" "\n");}#ifdef CONFIG_MTD_NANDextern void enable_bad_block_erase(void);extern void disable_bad_block_erase(void);#endif /* CONFIG_MTD_NAND */void command_flash(int argc, const char *argv[]){ struct mtd_info *mtd = mymtd; mtd_partition_t *part = NULL; ulong offset = ~0, size = 0; if (mtd == NULL) { printk("Error: Can not find MTD information\n"); return; } switch (argc) { case 2: if (strncmp("help", argv[1], 4) == 0) { usage(); return; }#ifdef CONFIG_MTD_NAND if (strncmp("ee", argv[1], 2) == 0) { enable_bad_block_erase(); return; } if (strncmp("de", argv[1], 2) == 0) { disable_bad_block_erase(); return; }#endif /* CONFIG_MTD_NAND */ break; case 3: if (strncmp("dump", argv[1], 4) == 0) { offset = simple_strtoul(argv[2], NULL, 0); do_dump(mtd, offset); return; } if (strncmp("erase", argv[1], 5) == 0) { offset = 0; size = mtd->size; do_erase(mtd, offset, size); return; } part = get_mtd_partition(argv[2]); offset = part->offset; size = part->size; break; case 4: offset = simple_strtoul(argv[2], NULL, 0); size = simple_strtoul(argv[3], NULL, 0); break; default: usage(); return; } if (strncmp("lock", argv[1], 4) == 0) { do_lock(mtd, offset, size); } else if (strncmp("unlock", argv[1], 6) == 0) { do_unlock(mtd, offset, size); } else if (strncmp("erase", argv[1], 5) == 0) { do_erase(mtd, offset, size); } else { usage(); }}static user_command_t flash_cmd = { "flash", command_flash, NULL};extern int s3c2410_nand_init(void);extern int mp2520f_nand_init(void);extern int bon_init(void);extern int doc_init(void);extern user_command_t nandtst_cmd;extern int s3c24a0_nand_init(void);int mtd_dev_init(void){ int ret = 0;#if defined(CONFIG_MTD_NAND_S3C2410) ret = s3c2410_nand_init();#elif defined(CONFIG_MTD_NAND_MMSP2) ret = mp2520f_nand_init();#elif defined(CONFIG_MTD_NAND_S3C24A0) ret = s3c24a0_nand_init();#elif defined(CONFIG_MTD_MDOCG3) return doc_init();#else ret = 1;#endif if (ret) return 1;#ifdef CONFIG_MTD_NAND_BON ret = bon_init();#endif#ifdef CONFIG_MTD_NAND_TESTCMD add_command(&nandtst_cmd);#endif add_command(&flash_cmd); return ret;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -