X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs2.git;a=blobdiff_plain;f=yaffs_mtdif2.c;h=d927c76737ebc796c0bdaf2f50efa5515010bc54;hp=0dfb942e39100698f5f510d85dadf1c7476931c2;hb=e1ac494e05a5dc7ab61d799af815d103a11d318c;hpb=9f361d87ca8c3d331ed1a4ffea53dd9a8d55ee88 diff --git a/yaffs_mtdif2.c b/yaffs_mtdif2.c index 0dfb942..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,17 +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 */ const char *yaffs_mtdif2_c_version = - "$Id: yaffs_mtdif2.c,v 1.7 2005-08-11 01:07:43 marty Exp $"; + "$Id: yaffs_mtdif2.c,v 1.17 2007-02-14 01:09:06 wookey Exp $"; #include "yportenv.h" -#ifdef CONFIG_YAFFS_YAFFS1 #include "yaffs_mtdif2.h" @@ -35,10 +32,14 @@ int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND, 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; @@ -47,6 +48,23 @@ int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND, ("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); } @@ -54,16 +72,16 @@ int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND, if (data && tags) { if (dev->useNANDECC) retval = - mtd->write_ecc(mtd, addr, dev->nBytesPerChunk, + mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk, &dummy, data, (__u8 *) & pt, NULL); else retval = - mtd->write_ecc(mtd, addr, dev->nBytesPerChunk, + mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk, &dummy, data, (__u8 *) & pt, NULL); } else { if (data) retval = - mtd->write(mtd, addr, dev->nBytesPerChunk, &dummy, + mtd->write(mtd, addr, dev->nDataBytesPerChunk, &dummy, data); if (tags) retval = @@ -71,6 +89,7 @@ int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND, (__u8 *) & pt); } +#endif if (retval == 0) return YAFFS_OK; @@ -82,45 +101,66 @@ 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; - 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_ReadChunkWithTagsToNAND chunk %d data %p tags %p" + ("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 && tags) { if (dev->useNANDECC) { retval = - mtd->read_ecc(mtd, addr, dev->nBytesPerChunk, + mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk, &dummy, data, dev->spareBuffer, NULL); } else { retval = - mtd->read_ecc(mtd, addr, dev->nBytesPerChunk, + mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk, &dummy, data, dev->spareBuffer, NULL); } } else { if (data) retval = - mtd->read(mtd, addr, dev->nBytesPerChunk, &dummy, + 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(tags && retval == -EBADMSG && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR) + tags->eccResult = YAFFS_ECC_RESULT_UNFIXED; if (retval == 0) return YAFFS_OK; @@ -138,7 +178,7 @@ int nandmtd2_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo) retval = mtd->block_markbad(mtd, blockNo * dev->nChunksPerBlock * - dev->nBytesPerChunk); + dev->nDataBytesPerChunk); if (retval == 0) return YAFFS_OK; @@ -158,7 +198,7 @@ int nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, retval = mtd->block_isbad(mtd, blockNo * dev->nChunksPerBlock * - dev->nBytesPerChunk); + dev->nDataBytesPerChunk); if (retval) { T(YAFFS_TRACE_MTD, (TSTR("block is bad" TENDSTR))); @@ -190,4 +230,3 @@ int nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, return YAFFS_FAIL; } -#endif