?? mtdcore.c
字號:
/* * vivi/drivers/mtd/mtdcore.c: MTD率 包訪等 巴甸 * * Copyright (C) 2001 MIZI Research, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * Author: Janghoon Lyu <nandy@mizi.com> * Date : $Date: 2002/12/10 06:59:07 $ * * $Revision: 1.16 $ * $Id: mtdcore.c,v 1.16 2002/12/10 06:59:07 tolkien Exp $ * * * TODO: * - In a do_format_jffs2(): after erase all blocks, * we need write 'cleanmarke' to every blocks if needed. * * History * * 2001-12-23: Janghoon Lyu <nandy@mizi.com> * - Initial code * * 2002-02-23: Janghoon Lyu <nandy@mizi.com> * - Add flash commands */#include "config.h"#include "machine.h"#include <priv_data.h>#include "mtd/mtd.h"#include "mtd/cfi.h"#include "mtd/bonfs.h"#include "command.h"#include "printk.h"#include "memory.h"#include "serial.h"#include "vivi_string.h"#include <types.h>#include <errno.h>/* temporary debugging macros */#undef DEBUG_MTDCORE#ifdef DEBUG_MTDCORE#define DPRINTK(args...) printk(##args)#else#define DPRINTK(args...)#endiftypedef enum { WS_LOCKING, WS_UNLOCKING, WS_FM_JFFS2, WS_ERASING, WS_WRITING, WS_VERIFYING, WS_ERROR, WS_DONE} ws_state_t;//struct mtd_info *mymtd = NULL;#define MAXFLASH 4struct mtd_info *mtd_tbl[MAXFLASH];static int mtdnum;static u_int32_t mtd_baseaddr;int mtd_add(struct mtd_info *mtd){ if (mtdnum < MAXFLASH) { mtd->baseaddr = mtd_baseaddr; mtd_baseaddr += mtd->size; mtd_tbl[mtdnum++] = mtd; return 0; } return -1;}struct mtd_info *mtd_get(loff_t ofs, size_t len){ int i; struct mtd_info *mtd; loff_t end = ofs+len; for (i=0;i<mtdnum;i++) { mtd = mtd_tbl[i]; if (mtd && (ofs >= mtd->baseaddr) && (end <= (mtd->baseaddr+mtd->size))) { //printk("i:%d, offset: 0x%08lx, size: 0x%08lx\n", i, (u32)ofs,(u32)len); //printk("flash: %d(name:%s)\n", i, mtd->name); return mtd; } } return NULL;}struct mtd_info *mtd_nget(int nmtd){ return mtd_tbl[nmtd];}size_t find_erase_size(struct mtd_info *mtd, loff_t ofs, size_t len){ struct mtd_erase_region_info *regions = mtd->eraseregions; size_t erasesize, retlen; int i, j, first, last; switch (mtd->type) { case MTD_NORFLASH: i = 0; while ((i < mtd->numeraseregions) && (ofs >= regions[i].offset)) { i++; } i--; first = i; i = first; //printk("first = %d\n", first); while ((i < mtd->numeraseregions) && ((ofs +len) >= regions[i].offset)) { i++; } i--; last = i; //printk("first = %d, last = %d\n", first, last); retlen = 0; for (i = first; i <= last; i++) { for (j = 0; j < regions[i].numblocks; j++) { if (len > regions[i].erasesize) { retlen += regions[i].erasesize; len -= regions[i].erasesize; //printk("retlen = 0x%x\n", retlen); } else { retlen += regions[i].erasesize; //printk("Oh..! retlen = 0x%x\n", retlen); return retlen; } } } break; case MTD_NANDFLASH: erasesize = mtd->erasesize; if (len & (erasesize - 1)) { /* not aligned */ return ((len & ~(erasesize - 1)) + erasesize); } else { /* ok. aligned */ return (len); } break; default: printk("Something wrong\n"); return 0; } return 0;}static intdo_format_jffs2(struct mtd_info *mtd, loff_t ofs, size_t len){ int ret; mtd_partition_t *usr; struct erase_info erase; usr = find_mtd_partition((ulong)ofs); if (usr == NULL) { printk("Can no find information of mtd partition\n"); return -1; } erase.addr = usr->offset; erase.len = usr->size; printk("Formating... "); ret = mtd->erase(mtd, &erase); if (ret) { printk(" ... failed\n"); return ret; } printk(" ... done\n"); return 0;}static intnor_unlock(struct mtd_info *mtd, loff_t ofs, size_t len){ int ret; printk("Unlocking... "); ret = mtd->unlock(mtd, ofs, len); if (ret) { printk(" ... failed\n"); return -1; } printk(" ... done\n"); return 0;}static intnor_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(" ... failed\n"); return ret; } printk(" ... done\n"); return 0;}static intnor_erase(struct mtd_info *mtd, loff_t ofs, size_t len){ int ret; struct erase_info erase; erase.addr = ofs; erase.len = len; printk("Erasing... "); ret = mtd->erase(mtd, &erase); if (ret) { printk(" ... failed\n"); return ret; } printk(" ... done\n"); return 0;}static intnor_write(struct mtd_info *mtd, loff_t ofs, size_t len, const u_char * buf){ int ret; __u32 retlen = 0; printk("Writing... "); retlen = 0; ret = mtd->write(mtd, ofs, len, &retlen, buf); if ((ret < 0) || (retlen != len)) { printk(" ... failed\n\tretlen = %d, ret = %d\n", retlen, ret); return ret; } printk(" ... done\n"); return 0;}static intnor_verify(const u_char *buf, loff_t ofs, size_t len){ int ret; printk("Verifying... ");#ifdef CONFIG_MSG_PROGRESS ret = mem_compare(buf, (u_char*)(ulong)(ofs + FLASH_UNCACHED_BASE), len, 1);#else ret = mem_compare(buf, (u_char*)(ulong)(ofs + FLASH_UNCACHED_BASE), len, 0);#endif if (ret != len) { printk(" ... failed\n\tnot mached. offset = 0x%08lx, ", ret); printk("\tsrc = 0x%08lx, dst = 0x%08lx\n", *(ulong *)((ulong)(buf + ret)), *(ulong *)((ulong)(ofs + ret))); return -1; } printk(" ... done\n"); return 0;}static inline int make_steps(ws_state_t *steps, int flag){ int i, temp, num_step; steps[0] = WS_ERASING; steps[1] = WS_WRITING; steps[2] = WS_VERIFYING; num_step = 3; if (flag & MF_JFFS2) { steps[0] = WS_FM_JFFS2; } if (flag & MF_LOCKED) { temp = num_step; for (i = 0; i < num_step; i++) { steps[temp] = steps[temp-1]; temp--; } steps[0] = WS_UNLOCKING; num_step++; steps[num_step++] = WS_LOCKING; } steps[num_step++] = WS_DONE; DPRINTK("number of steps = %d\n", num_step); return num_step;}static int write_to_nor(struct mtd_info *mtd, loff_t ofs, size_t len, const u_char *buf, int flag){ int ret = 0; ws_state_t steps[10]; int num_step = 0, i; size_t blk_size = find_erase_size(mtd, ofs, len); DPRINTK("Found block size = 0x%08lx\n", blk_size); num_step = make_steps(steps, flag); for (i = 0; i <= num_step; i++) { switch(steps[i]) { case WS_LOCKING: ret = nor_lock(mtd, ofs, blk_size); if (ret) steps[i+1] = WS_ERROR; break; case WS_UNLOCKING: ret = nor_unlock(mtd, ofs, blk_size); if (ret) steps[i+1] = WS_ERROR; break; case WS_FM_JFFS2: ret = do_format_jffs2(mtd, ofs, len); if (ret) steps[i+1] = WS_ERROR; break; case WS_ERASING: ret = nor_erase(mtd, ofs, blk_size); if (ret) steps[i+1] = WS_ERROR; break; case WS_WRITING: ret = nor_write(mtd, ofs, len, buf); if (ret) steps[i+1] = WS_ERROR; break; case WS_VERIFYING: ret = nor_verify(buf, ofs, len); if (ret) steps[i+1] = WS_ERROR; break; case WS_ERROR: printk("Error\n"); return -1; case WS_DONE: printk("Nor Written %d bytes\n", len); return 0; default: printk("Error while writing a image.\n"); return -1; } } return 0;}static int write_yaffs_image(struct mtd_info *mtd, loff_t to, char *src, size_t len){ char *dataptr;
ulong offs; int ret = 0; __u32 retlen = 0; char oobbuff[16]; mtd_partition_t *part; loff_t end; if(len % (mtd->oobblock+mtd->oobsize)){ printk("Image not a multiple of %d bytes\n",mtd->oobblock+mtd->oobsize); return -1; }
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -