X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs2.git;a=blobdiff_plain;f=yaffs_mtdif2.c;h=d927c76737ebc796c0bdaf2f50efa5515010bc54;hp=9cf9828ed749e8d30dc6b039c226f6e33f5f020e;hb=e1ac494e05a5dc7ab61d799af815d103a11d318c;hpb=e528916d3c9c87aa1547b1cc2536389ef5efbcb3 diff --git a/yaffs_mtdif2.c b/yaffs_mtdif2.c index 9cf9828..d927c76 100644 --- a/yaffs_mtdif2.c +++ b/yaffs_mtdif2.c @@ -1,8 +1,7 @@ /* - * YAFFS: Yet another FFS. A NAND-flash specific file system. - * yaffs_mtdif.c NAND mtd wrapper functions. + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. * - * Copyright (C) 2002 Aleph One Ltd. + * Copyright (C) 2002-2007 Aleph One Ltd. * for Toby Churchill Ltd and Brightstar Engineering * * Created by Charles Manning @@ -10,16 +9,15 @@ * 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. - * */ -// mtd interface for YAFFS2 +/* mtd interface for YAFFS2 */ + +const char *yaffs_mtdif2_c_version = + "$Id: yaffs_mtdif2.c,v 1.17 2007-02-14 01:09:06 wookey Exp $"; -const char *yaffs_mtdif2_c_version = "$Id: yaffs_mtdif2.c,v 1.6 2005-08-01 20:52:35 luc Exp $"; - #include "yportenv.h" -#ifdef CONFIG_YAFFS_YAFFS1 #include "yaffs_mtdif2.h" @@ -29,148 +27,206 @@ const char *yaffs_mtdif2_c_version = "$Id: yaffs_mtdif2.c,v 1.6 2005-08-01 20:52 #include "yaffs_packedtags2.h" - - - -int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_ExtendedTags *tags) +int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND, + const __u8 * data, + const yaffs_ExtendedTags * tags) { struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) + struct mtd_oob_ops ops; +#else size_t dummy; +#endif int retval = 0; - - loff_t addr = ((loff_t)chunkInNAND) * dev->nBytesPerChunk; + loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk; yaffs_PackedTags2 pt; - - T(YAFFS_TRACE_MTD,(TSTR("nandmtd2_WriteChunkWithTagsToNAND chunk %d data %p tags %p" TENDSTR),chunkInNAND,data,tags)); - if(tags) - { - yaffs_PackTags2(&pt,tags); + T(YAFFS_TRACE_MTD, + (TSTR + ("nandmtd2_WriteChunkWithTagsToNAND chunk %d data %p tags %p" + TENDSTR), chunkInNAND, data, tags)); + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) + if (tags) + yaffs_PackTags2(&pt, tags); + else + BUG(); /* both tags and data should always be present */ + + if (data) { + ops.mode = MTD_OOB_AUTO; + ops.ooblen = sizeof(pt); + ops.len = dev->nDataBytesPerChunk; + ops.ooboffs = 0; + ops.datbuf = (__u8 *)data; + ops.oobbuf = (void *)&pt; + retval = mtd->write_oob(mtd, addr, &ops); + } else + BUG(); /* both tags and data should always be present */ +#else + if (tags) { + yaffs_PackTags2(&pt, tags); } - if(data && tags) - { - if(dev->useNANDECC) - retval = mtd->write_ecc(mtd,addr,dev->nBytesPerChunk,&dummy,data,(__u8 *)&pt,NULL); + if (data && tags) { + if (dev->useNANDECC) + retval = + mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk, + &dummy, data, (__u8 *) & pt, NULL); else - retval = mtd->write_ecc(mtd,addr,dev->nBytesPerChunk,&dummy,data,(__u8 *)&pt,NULL); - } - else - { - if(data) - retval = mtd->write(mtd,addr,dev->nBytesPerChunk,&dummy,data); - if(tags) - retval = mtd->write_oob(mtd,addr,mtd->oobsize,&dummy,(__u8 *)&pt); - + retval = + mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk, + &dummy, data, (__u8 *) & pt, NULL); + } else { + if (data) + retval = + mtd->write(mtd, addr, dev->nDataBytesPerChunk, &dummy, + data); + if (tags) + retval = + mtd->write_oob(mtd, addr, mtd->oobsize, &dummy, + (__u8 *) & pt); + } +#endif - if (retval == 0) - return YAFFS_OK; - else - return YAFFS_FAIL; + if (retval == 0) + return YAFFS_OK; + else + return YAFFS_FAIL; } -int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_ExtendedTags *tags) +int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND, + __u8 * data, yaffs_ExtendedTags * tags) { struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) + struct mtd_oob_ops ops; +#endif size_t dummy; - int retval = 0; - + int retval = 0; - loff_t addr = ((loff_t)chunkInNAND) * dev->nBytesPerChunk; - - yaffs_PackedTags2 pt; + loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk; - T(YAFFS_TRACE_MTD,(TSTR("nandmtd2_ReadChunkWithTagsToNAND chunk %d data %p tags %p" TENDSTR),chunkInNAND,data,tags)); + yaffs_PackedTags2 pt; - if(data && tags) - { - if(dev->useNANDECC) - { - retval = mtd->read_ecc(mtd,addr,dev->nBytesPerChunk,&dummy,data,dev->spareBuffer,NULL); - } - else - { - retval = mtd->read_ecc(mtd,addr,dev->nBytesPerChunk,&dummy,data,dev->spareBuffer,NULL); - } + T(YAFFS_TRACE_MTD, + (TSTR + ("nandmtd2_ReadChunkWithTagsFromNAND chunk %d data %p tags %p" + TENDSTR), chunkInNAND, data, tags)); + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) + if (data && !tags) + retval = mtd->read(mtd, addr, dev->nDataBytesPerChunk, + &dummy, data); + else if (tags) { + ops.mode = MTD_OOB_AUTO; + ops.ooblen = sizeof(pt); + ops.len = data ? dev->nDataBytesPerChunk : sizeof(pt); + ops.ooboffs = 0; + ops.datbuf = data; + ops.oobbuf = dev->spareBuffer; + retval = mtd->read_oob(mtd, addr, &ops); } - else - { - if(data) - retval = mtd->read(mtd,addr,dev->nBytesPerChunk,&dummy,data); - if(tags) - retval = mtd->read_oob(mtd,addr,mtd->oobsize,&dummy,dev->spareBuffer); +#else + if (data && tags) { + if (dev->useNANDECC) { + retval = + mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk, + &dummy, data, dev->spareBuffer, + NULL); + } else { + retval = + mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk, + &dummy, data, dev->spareBuffer, + NULL); + } + } else { + if (data) + retval = + mtd->read(mtd, addr, dev->nDataBytesPerChunk, &dummy, + data); + if (tags) + retval = + mtd->read_oob(mtd, addr, mtd->oobsize, &dummy, + dev->spareBuffer); } +#endif - memcpy(&pt,dev->spareBuffer,sizeof(pt)); - - if(tags) - yaffs_UnpackTags2(tags,&pt); - - if (retval == 0) - return YAFFS_OK; - else - return YAFFS_FAIL; + memcpy(&pt, dev->spareBuffer, sizeof(pt)); + + if (tags) + yaffs_UnpackTags2(tags, &pt); + + if(tags && retval == -EBADMSG && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR) + tags->eccResult = YAFFS_ECC_RESULT_UNFIXED; + + if (retval == 0) + return YAFFS_OK; + else + return YAFFS_FAIL; } int nandmtd2_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo) { struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); int retval; - T(YAFFS_TRACE_MTD,(TSTR("nandmtd2_MarkNANDBlockBad %d" TENDSTR),blockNo)); - - - retval = mtd->block_markbad(mtd,blockNo * dev->nChunksPerBlock * dev->nBytesPerChunk); + T(YAFFS_TRACE_MTD, + (TSTR("nandmtd2_MarkNANDBlockBad %d" TENDSTR), blockNo)); + + retval = + mtd->block_markbad(mtd, + blockNo * dev->nChunksPerBlock * + dev->nDataBytesPerChunk); - if (retval == 0) - return YAFFS_OK; - else - return YAFFS_FAIL; + if (retval == 0) + return YAFFS_OK; + else + return YAFFS_FAIL; } -int nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, yaffs_BlockState *state, int *sequenceNumber) +int nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, + yaffs_BlockState * state, int *sequenceNumber) { struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); int retval; - - T(YAFFS_TRACE_MTD,(TSTR("nandmtd2_QueryNANDBlock %d" TENDSTR),blockNo)); - retval = mtd->block_isbad(mtd,blockNo* dev->nChunksPerBlock * dev->nBytesPerChunk); - - if(retval) - { - T(YAFFS_TRACE_MTD,(TSTR("block is bad" TENDSTR))); - + + T(YAFFS_TRACE_MTD, + (TSTR("nandmtd2_QueryNANDBlock %d" TENDSTR), blockNo)); + retval = + mtd->block_isbad(mtd, + blockNo * dev->nChunksPerBlock * + dev->nDataBytesPerChunk); + + if (retval) { + T(YAFFS_TRACE_MTD, (TSTR("block is bad" TENDSTR))); + *state = YAFFS_BLOCK_STATE_DEAD; *sequenceNumber = 0; - } - else - { + } else { yaffs_ExtendedTags t; - nandmtd2_ReadChunkWithTagsFromNAND(dev,blockNo * dev->nChunksPerBlock,NULL, &t); - - if(t.chunkUsed) - { - *sequenceNumber = t.sequenceNumber; - *state = YAFFS_BLOCK_STATE_NEEDS_SCANNING; - } - else - { - *sequenceNumber = 0; - *state = YAFFS_BLOCK_STATE_EMPTY; + nandmtd2_ReadChunkWithTagsFromNAND(dev, + blockNo * + dev->nChunksPerBlock, NULL, + &t); + + if (t.chunkUsed) { + *sequenceNumber = t.sequenceNumber; + *state = YAFFS_BLOCK_STATE_NEEDS_SCANNING; + } else { + *sequenceNumber = 0; + *state = YAFFS_BLOCK_STATE_EMPTY; } } - T(YAFFS_TRACE_MTD,(TSTR("block is bad seq %d state %d" TENDSTR), *sequenceNumber,*state)); + T(YAFFS_TRACE_MTD, + (TSTR("block is bad seq %d state %d" TENDSTR), *sequenceNumber, + *state)); - if (retval == 0) - return YAFFS_OK; - else - return YAFFS_FAIL; + if (retval == 0) + return YAFFS_OK; + else + return YAFFS_FAIL; } -#endif - - -