summaryrefslogtreecommitdiff
path: root/ANDROID_3.4.5/fs/yaffs2/yaffs_mtdif1.c
diff options
context:
space:
mode:
authorKevin2014-11-15 10:00:36 +0800
committerKevin2014-11-15 10:00:36 +0800
commit9d40ac5867b9aefe0722bc1f110b965ff294d30d (patch)
treede942df665fac4bac0d9cb7ae86910fe937b0c1a /ANDROID_3.4.5/fs/yaffs2/yaffs_mtdif1.c
parent392e8802486cb573b916e746010e141a75f507e6 (diff)
downloadFOSSEE-netbook-kernel-source-9d40ac5867b9aefe0722bc1f110b965ff294d30d.tar.gz
FOSSEE-netbook-kernel-source-9d40ac5867b9aefe0722bc1f110b965ff294d30d.tar.bz2
FOSSEE-netbook-kernel-source-9d40ac5867b9aefe0722bc1f110b965ff294d30d.zip
add via modify part source code for wm8880 4.4 kitkat
Diffstat (limited to 'ANDROID_3.4.5/fs/yaffs2/yaffs_mtdif1.c')
-rw-r--r--ANDROID_3.4.5/fs/yaffs2/yaffs_mtdif1.c144
1 files changed, 89 insertions, 55 deletions
diff --git a/ANDROID_3.4.5/fs/yaffs2/yaffs_mtdif1.c b/ANDROID_3.4.5/fs/yaffs2/yaffs_mtdif1.c
index 51083695..54d0d2c8 100644
--- a/ANDROID_3.4.5/fs/yaffs2/yaffs_mtdif1.c
+++ b/ANDROID_3.4.5/fs/yaffs2/yaffs_mtdif1.c
@@ -1,7 +1,7 @@
/*
* YAFFS: Yet another FFS. A NAND-flash specific file system.
*
- * Copyright (C) 2002-2010 Aleph One Ltd.
+ * Copyright (C) 2002-2011 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
@@ -36,10 +36,36 @@
#include "linux/types.h"
#include "linux/mtd/mtd.h"
-#ifndef CONFIG_YAFFS_9BYTE_TAGS
-# define YTAG1_SIZE 8
-#else
-# define YTAG1_SIZE 9
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0))
+#define MTD_OPS_AUTO_OOB MTD_OOB_AUTO
+#endif
+
+
+/* Don't compile this module if we don't have MTD's mtd_oob_ops interface */
+#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17))
+
+
+#if 0
+/* Use the following nand_ecclayout with MTD when using
+ * 9 byte tags and the older on-NAND tags layout.
+ * If you have existing Yaffs images and the byte order differs from this,
+ * adjust 'oobfree' to match your existing Yaffs data.
+ *
+ * This nand_ecclayout scatters/gathers to/from the old-yaffs layout with the
+ * page_status byte (at NAND spare offset 4) scattered/gathered from/to
+ * the 9th byte.
+ *
+ * Old-style on-NAND format: T0,T1,T2,T3,P,B,T4,T5,E0,E1,E2,T6,T7,E3,E4,E5
+ * We have/need packed_tags1 plus page_status: T0,T1,T2,T3,T4,T5,T6,T7,P
+ * where Tn are the tag bytes, En are MTD's ECC bytes, P is the page_status
+ * byte and B is the small-page bad-block indicator byte.
+ */
+static struct nand_ecclayout nand_oob_16 = {
+ .eccbytes = 6,
+ .eccpos = {8, 9, 10, 13, 14, 15},
+ .oobavail = 9,
+ .oobfree = {{0, 4}, {6, 2}, {11, 2}, {4, 1} }
+};
#endif
/* Write a chunk (page) of data to NAND.
@@ -64,7 +90,7 @@
* Returns YAFFS_OK or YAFFS_FAIL.
*/
int nandmtd1_write_chunk_tags(struct yaffs_dev *dev,
- int nand_chunk, const u8 * data,
+ int nand_chunk, const u8 *data,
const struct yaffs_ext_tags *etags)
{
struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
@@ -87,29 +113,29 @@ int nandmtd1_write_chunk_tags(struct yaffs_dev *dev,
* that only zeroed-bits stick and set tag bytes to all-ones and
* zero just the (not) deleted bit.
*/
-#ifndef CONFIG_YAFFS_9BYTE_TAGS
- if (etags->is_deleted) {
- memset(&pt1, 0xff, 8);
- /* clear delete status bit to indicate deleted */
- pt1.deleted = 0;
- }
-#else
- ((u8 *) & pt1)[8] = 0xff;
- if (etags->is_deleted) {
- memset(&pt1, 0xff, 8);
- /* zero page_status byte to indicate deleted */
- ((u8 *) & pt1)[8] = 0;
+ if(dev->param.tags_9bytes) {
+ ((u8 *) &pt1)[8] = 0xff;
+ if (etags->is_deleted) {
+ memset(&pt1, 0xff, 8);
+ /* zero page_status byte to indicate deleted */
+ ((u8 *) &pt1)[8] = 0;
+ }
+ } else {
+ if (etags->is_deleted) {
+ memset(&pt1, 0xff, 8);
+ /* clear delete status bit to indicate deleted */
+ pt1.deleted = 0;
+ }
}
-#endif
memset(&ops, 0, sizeof(ops));
- ops.mode = MTD_OOB_AUTO;
+ ops.mode = MTD_OPS_AUTO_OOB;
ops.len = (data) ? chunk_bytes : 0;
- ops.ooblen = YTAG1_SIZE;
+ ops.ooblen = dev->param.tags_9bytes ? 9 : 8;
ops.datbuf = (u8 *) data;
- ops.oobbuf = (u8 *) & pt1;
+ ops.oobbuf = (u8 *) &pt1;
- retval = mtd->write_oob(mtd, addr, &ops);
+ retval = mtd->_write_oob(mtd, addr, &ops);
if (retval) {
yaffs_trace(YAFFS_TRACE_MTD,
"write_oob failed, chunk %d, mtd error %d",
@@ -143,7 +169,7 @@ static int rettags(struct yaffs_ext_tags *etags, int ecc_result, int retval)
* Returns YAFFS_OK or YAFFS_FAIL.
*/
int nandmtd1_read_chunk_tags(struct yaffs_dev *dev,
- int nand_chunk, u8 * data,
+ int nand_chunk, u8 *data,
struct yaffs_ext_tags *etags)
{
struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
@@ -156,21 +182,26 @@ int nandmtd1_read_chunk_tags(struct yaffs_dev *dev,
int deleted;
memset(&ops, 0, sizeof(ops));
- ops.mode = MTD_OOB_AUTO;
+ ops.mode = MTD_OPS_AUTO_OOB;
ops.len = (data) ? chunk_bytes : 0;
- ops.ooblen = YTAG1_SIZE;
+ ops.ooblen = dev->param.tags_9bytes ? 9 : 8;
ops.datbuf = data;
- ops.oobbuf = (u8 *) & pt1;
+ ops.oobbuf = (u8 *) &pt1;
+#if (MTD_VERSION_CODE < MTD_VERSION(2, 6, 20))
+ /* In MTD 2.6.18 to 2.6.19 nand_base.c:nand_do_read_oob() has a bug;
+ * help it out with ops.len = ops.ooblen when ops.datbuf == NULL.
+ */
+ ops.len = (ops.datbuf) ? ops.len : ops.ooblen;
+#endif
/* Read page and oob using MTD.
* Check status and determine ECC result.
*/
- retval = mtd->read_oob(mtd, addr, &ops);
- if (retval) {
+ retval = mtd->_read_oob(mtd, addr, &ops);
+ if (retval)
yaffs_trace(YAFFS_TRACE_MTD,
"read_oob failed, chunk %d, mtd error %d",
nand_chunk, retval);
- }
switch (retval) {
case 0:
@@ -189,26 +220,27 @@ int nandmtd1_read_chunk_tags(struct yaffs_dev *dev,
/* fall into... */
default:
rettags(etags, YAFFS_ECC_RESULT_UNFIXED, 0);
- etags->block_bad = (mtd->block_isbad) (mtd, addr);
+ etags->block_bad = (mtd->_block_isbad) (mtd, addr);
return YAFFS_FAIL;
}
/* Check for a blank/erased chunk.
*/
- if (yaffs_check_ff((u8 *) & pt1, 8)) {
+ if (yaffs_check_ff((u8 *) &pt1, 8)) {
/* when blank, upper layers want ecc_result to be <= NO_ERROR */
return rettags(etags, YAFFS_ECC_RESULT_NO_ERROR, YAFFS_OK);
}
-#ifndef CONFIG_YAFFS_9BYTE_TAGS
- /* Read deleted status (bit) then return it to it's non-deleted
- * state before performing tags mini-ECC check. pt1.deleted is
- * inverted.
- */
- deleted = !pt1.deleted;
- pt1.deleted = 1;
-#else
- deleted = (yaffs_count_bits(((u8 *) & pt1)[8]) < 7);
-#endif
+
+ if(dev->param.tags_9bytes) {
+ deleted = (hweight8(((u8 *) &pt1)[8]) < 7);
+ } else {
+ /* Read deleted status (bit) then return it to it's non-deleted
+ * state before performing tags mini-ECC check. pt1.deleted is
+ * inverted.
+ */
+ deleted = !pt1.deleted;
+ pt1.deleted = 1;
+ }
/* Check the packed tags mini-ECC and correct if necessary/possible.
*/
@@ -232,7 +264,7 @@ int nandmtd1_read_chunk_tags(struct yaffs_dev *dev,
/* Unpack the tags to extended form and set ECC result.
* [set should_be_ff just to keep yaffs_unpack_tags1 happy]
*/
- pt1.should_be_ff = 0xFFFFFFFF;
+ pt1.should_be_ff = 0xffffffff;
yaffs_unpack_tags1(etags, &pt1);
etags->ecc_result = eccres;
@@ -254,10 +286,9 @@ int nandmtd1_mark_block_bad(struct yaffs_dev *dev, int block_no)
int blocksize = dev->param.chunks_per_block * dev->data_bytes_per_chunk;
int retval;
- yaffs_trace(YAFFS_TRACE_BAD_BLOCKS,
- "marking block %d bad", block_no);
+ yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, "marking block %d bad", block_no);
- retval = mtd->block_markbad(mtd, (loff_t) blocksize * block_no);
+ retval = mtd->_block_markbad(mtd, (loff_t) blocksize * block_no);
return (retval) ? YAFFS_FAIL : YAFFS_OK;
}
@@ -265,16 +296,16 @@ int nandmtd1_mark_block_bad(struct yaffs_dev *dev, int block_no)
*
* Returns YAFFS_OK or YAFFS_FAIL.
*/
-static int nandmtd1_test_prerequists(struct mtd_info *mtd)
+static int nandmtd1_test_prerequists(struct yaffs_dev *dev, struct mtd_info *mtd)
{
/* 2.6.18 has mtd->ecclayout->oobavail */
/* 2.6.21 has mtd->ecclayout->oobavail and mtd->oobavail */
int oobavail = mtd->ecclayout->oobavail;
- if (oobavail < YTAG1_SIZE) {
+ if (oobavail < (dev->param.tags_9bytes ? 9 : 8)) {
yaffs_trace(YAFFS_TRACE_ERROR,
"mtd device has only %d bytes for tags, need %d",
- oobavail, YTAG1_SIZE);
+ oobavail, dev->param.tags_9bytes ? 9 : 8);
return YAFFS_FAIL;
}
return YAFFS_OK;
@@ -284,7 +315,7 @@ static int nandmtd1_test_prerequists(struct mtd_info *mtd)
*
* Examine the tags of the first chunk of the block and return the state:
* - YAFFS_BLOCK_STATE_DEAD, the block is marked bad
- * - YAFFS_BLOCK_STATE_NEEDS_SCANNING, the block is in use
+ * - YAFFS_BLOCK_STATE_NEEDS_SCAN, the block is in use
* - YAFFS_BLOCK_STATE_EMPTY, the block is clean
*
* Always returns YAFFS_OK.
@@ -303,20 +334,21 @@ int nandmtd1_query_block(struct yaffs_dev *dev, int block_no,
/* We don't yet have a good place to test for MTD config prerequists.
* Do it here as we are called during the initial scan.
*/
- if (nandmtd1_test_prerequists(mtd) != YAFFS_OK)
+ if (nandmtd1_test_prerequists(dev, mtd) != YAFFS_OK)
return YAFFS_FAIL;
retval = nandmtd1_read_chunk_tags(dev, chunk_num, NULL, &etags);
- etags.block_bad = (mtd->block_isbad) (mtd, addr);
+ etags.block_bad = (mtd->_block_isbad) (mtd, addr);
if (etags.block_bad) {
yaffs_trace(YAFFS_TRACE_BAD_BLOCKS,
- "block %d is marked bad", block_no);
+ "block %d is marked bad",
+ block_no);
state = YAFFS_BLOCK_STATE_DEAD;
} else if (etags.ecc_result != YAFFS_ECC_RESULT_NO_ERROR) {
/* bad tags, need to look more closely */
- state = YAFFS_BLOCK_STATE_NEEDS_SCANNING;
+ state = YAFFS_BLOCK_STATE_NEEDS_SCAN;
} else if (etags.chunk_used) {
- state = YAFFS_BLOCK_STATE_NEEDS_SCANNING;
+ state = YAFFS_BLOCK_STATE_NEEDS_SCAN;
seqnum = etags.seq_number;
} else {
state = YAFFS_BLOCK_STATE_EMPTY;
@@ -328,3 +360,5 @@ int nandmtd1_query_block(struct yaffs_dev *dev, int block_no,
/* query always succeeds */
return YAFFS_OK;
}
+
+#endif /*MTD_VERSION */