X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs2.git;a=blobdiff_plain;f=yaffs_mtdif2.c;h=2c4795112621538728f30b387726e38fe03c81dd;hp=c1554333d89f1016bb116bca5676af06943c4b47;hb=378bbdf4d64b8b26db55a495ab6ae520ff62e471;hpb=92058df84b3bcea504a31463e9c6930dce4a7ae0 diff --git a/yaffs_mtdif2.c b/yaffs_mtdif2.c index c155433..2c47951 100644 --- a/yaffs_mtdif2.c +++ b/yaffs_mtdif2.c @@ -13,14 +13,14 @@ * */ -// mtd interface for YAFFS2 +/* mtd interface for YAFFS2 */ -const char *yaffs_mtdif2_c_version = "$Id: yaffs_mtdif2.c,v 1.3 2005-07-20 18:57:05 charles Exp $"; +const char *yaffs_mtdif2_c_version = + "$Id: yaffs_mtdif2.c,v 1.14 2006-10-03 10:13:03 charles Exp $"; -#ifdef CONFIG_YAFFS_MTD_ENABLED - #include "yportenv.h" + #include "yaffs_mtdif2.h" #include "linux/mtd/mtd.h" @@ -29,156 +29,206 @@ const char *yaffs_mtdif2_c_version = "$Id: yaffs_mtdif2.c,v 1.3 2005-07-20 18:57 #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->nBytesPerChunk; + 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); } -#ifndef CONFIG_YAFFS_USE_OLD_MTD - 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 - { -#endif - if(data) - retval = mtd->write(mtd,addr,dev->nBytesPerChunk,&dummy,data); - if(tags) - retval = mtd->write_oob(mtd,addr,mtd->oobsize,&dummy,(__u8 *)&pt); - -#ifndef CONFIG_YAFFS_USE_OLD_MTD + 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; -#ifndef CONFIG_YAFFS_USE_OLD_MTD - 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->nBytesPerChunk, + &dummy, data); + else if (tags) { + ops.mode = MTD_OOB_AUTO; + ops.ooblen = sizeof(pt); + ops.len = data ? dev->nBytesPerChunk : sizeof(pt); + ops.ooboffs = 0; + ops.datbuf = data; + ops.oobbuf = dev->spareBuffer; + retval = mtd->read_oob(mtd, addr, &ops); } - else - { -#endif - if(data) - retval = mtd->read(mtd,addr,dev->nBytesPerChunk,&dummy,data); - if(tags) - retval = mtd->read_oob(mtd,addr,mtd->oobsize,&dummy,dev->spareBuffer); -#ifndef CONFIG_YAFFS_USE_OLD_MTD +#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 - - -