1a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org/*
2a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org * YAFFS: Yet another FFS. A NAND-flash specific file system.
3a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org * yaffs_mtdif.c  NAND mtd wrapper functions.
4a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org *
5a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org * Copyright (C) 2002 Aleph One Ltd.
6a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org *   for Toby Churchill Ltd and Brightstar Engineering
7a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org *
8a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org * Created by Charles Manning <charles@aleph1.co.uk>
9a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org *
10a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org * This program is free software; you can redistribute it and/or modify
11a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org * it under the terms of the GNU General Public License version 2 as
12a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org * published by the Free Software Foundation.
13a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org *
14a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org */
157e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org
167e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org/* mtd interface for YAFFS2 */
17a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org
1874257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.orgconst char *yaffs_mtdif2_c_version =
19a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org    "$Id: yaffs_mtdif2.c,v 1.14 2006/10/03 10:13:03 charles Exp $";
207e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org
217e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org#include "yportenv.h"
227e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org
237e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org
247e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org#include "yaffs_mtdif2.h"
257e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org
26a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org#include "linux/mtd/mtd.h"
27a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org#include "linux/types.h"
28a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org#include "linux/time.h"
2901d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org
3001d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org#include "yaffs_packedtags2.h"
317e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org
3201d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org
3374257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.orgvoid nandmtd2_pt2buf(yaffs_Device *dev, yaffs_PackedTags2 *pt, int is_raw)
3474257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org{
3574257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org	struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
36a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org	__u8 *ptab = (__u8 *)pt; /* packed tags as bytes */
37c4af4cf7814bb773d838aefa476c196e5f1bc360asapersson@webrtc.org
3872cc32a68bcb9b2aa32f751dc6d120716d220a10asapersson@webrtc.org	int	i, j = 0, k, n;
3972cc32a68bcb9b2aa32f751dc6d120716d220a10asapersson@webrtc.org#ifdef CONFIG_YAFFS_DOES_ECC
4072cc32a68bcb9b2aa32f751dc6d120716d220a10asapersson@webrtc.org	size_t packed_size = sizeof(yaffs_PackedTags2);
4172cc32a68bcb9b2aa32f751dc6d120716d220a10asapersson@webrtc.org#else
4272cc32a68bcb9b2aa32f751dc6d120716d220a10asapersson@webrtc.org	size_t packed_size = sizeof(yaffs_PackedTags2TagsPart);
4372cc32a68bcb9b2aa32f751dc6d120716d220a10asapersson@webrtc.org#endif
4472cc32a68bcb9b2aa32f751dc6d120716d220a10asapersson@webrtc.org
45c4af4cf7814bb773d838aefa476c196e5f1bc360asapersson@webrtc.org	/* Pack buffer with 0xff */
46c4af4cf7814bb773d838aefa476c196e5f1bc360asapersson@webrtc.org	for (i = 0; i < mtd->oobsize; i++)
47c4af4cf7814bb773d838aefa476c196e5f1bc360asapersson@webrtc.org		dev->spareBuffer[i] = 0xff;
4872cc32a68bcb9b2aa32f751dc6d120716d220a10asapersson@webrtc.org
4972cc32a68bcb9b2aa32f751dc6d120716d220a10asapersson@webrtc.org	if(!is_raw){
5072cc32a68bcb9b2aa32f751dc6d120716d220a10asapersson@webrtc.org		memcpy(dev->spareBuffer,pt,packed_size);
51a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org	} else {
52a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org		j = 0;
53a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org		k = mtd->ecclayout->oobfree[j].offset;
5474257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org		n = mtd->ecclayout->oobfree[j].length;
5574257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org
5674257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org		//printk("nandmtd2_pt2buf: writing %d bytes of extra data into %d\n", packed_size, mtd->oobsize);
5774257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org
5874257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org		if (n == 0) {
5974257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org			T(YAFFS_TRACE_ERROR, (TSTR("No OOB space for tags" TENDSTR)));
60a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org			YBUG();
6101d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org		}
6201d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org
63a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org		for (i = 0; i < packed_size; i++) {
6401d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org			if (n == 0) {
65a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org				j++;
66a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org				k = mtd->ecclayout->oobfree[j].offset;
67a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org				n = mtd->ecclayout->oobfree[j].length;
6874257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org				if (n == 0 || j >= (sizeof(mtd->ecclayout->oobfree) / sizeof(mtd->ecclayout->oobfree[0]))) {
6974257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org					T(YAFFS_TRACE_ERROR, (TSTR("No OOB space for tags" TENDSTR)));
7074257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org					YBUG();
7174257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org				}
7274257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org			}
7374257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org			dev->spareBuffer[k] = ptab[i];
7474257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org			k++;
7574257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org			n--;
7674257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org		}
77a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org	}
78a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org
79a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org}
80a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org
81a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.orgvoid nandmtd2_buf2pt(yaffs_Device *dev, yaffs_PackedTags2 *pt, int is_raw)
8201d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org{
8301d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org	struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
84a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org	int	i, j = 0, k, n;
85a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org	__u8 *ptab = (__u8 *)pt; /* packed tags as bytes */
86a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org	size_t packed_size = dev->useNANDECC ? sizeof(yaffs_PackedTags2TagsPart) : sizeof(yaffs_PackedTags2);
8701d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org
88a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org	if (!is_raw) {
8901d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org
9074257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org		memcpy(pt,dev->spareBuffer,packed_size);
9174257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org	} else {
9201d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org		j = 0;
9301d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org		k = mtd->ecclayout->oobfree[j].offset;
9401d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org		n = mtd->ecclayout->oobfree[j].length;
9501d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org
9601d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org		if (n == 0) {
9701d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org			T(YAFFS_TRACE_ERROR, (TSTR("No space in OOB for tags" TENDSTR)));
9801d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org			YBUG();
9901d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org		}
10001d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org
10101d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org		for (i = 0; i < packed_size; i++) {
10201d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org			if (n == 0) {
10301d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org				j++;
10401d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org				k = mtd->ecclayout->oobfree[j].offset;
10501d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org				n = mtd->ecclayout->oobfree[j].length;
10601d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org				if (n == 0 || j >= (sizeof(mtd->ecclayout->oobfree) / sizeof(mtd->ecclayout->oobfree[0]))) {
10701d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org					T(YAFFS_TRACE_ERROR, (TSTR("No space in OOB for tags" TENDSTR)));
10801d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org					YBUG();
10901d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org				}
1104a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org			}
1114a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org			ptab[i] = dev->spareBuffer[k];
1124a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org			k++;
11301d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org			n--;
11401d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org		}
11501d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org	}
11601d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org
1174a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org}
1184a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org
1194a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.orgint nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND,
1204a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org				      const __u8 * data,
1214a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org				      const yaffs_ExtendedTags * tags)
1224a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org{
1234a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org	struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
1244a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
1254a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org	struct mtd_oob_ops ops;
12674257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org#else
12774257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org	size_t dummy;
12874257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org#endif
12974257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org	int retval = 0;
13074257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org
13174257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org	loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk;
132a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org
133a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org	yaffs_PackedTags2 pt;
134a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org
135a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org	T(YAFFS_TRACE_MTD,
136a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org	  (TSTR
137a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org	   ("nandmtd2_WriteChunkWithTagsToNAND chunk %d data %p tags %p"
138a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org	    TENDSTR), chunkInNAND, data, tags));
13901d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org
14001d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
14101d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org	if (tags)
14201d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org		yaffs_PackTags2(&pt, tags);
14374257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org	else
144903e746cc9a73da17bfa3f6110293582fa6ee3bestefan@webrtc.org		BUG(); /* both tags and data should always be present */
14501d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org
14674257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org	nandmtd2_pt2buf(dev, &pt, 1);
14774257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org	if (data) {
14874257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org		ops.mode = MTD_OOB_AUTO;
14974257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org		ops.ooblen = mtd->oobsize;
15074257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org		ops.len = dev->nDataBytesPerChunk;
15174257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org		ops.ooboffs = 0;
15274257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org		ops.datbuf = (__u8 *)data;
15374257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org		ops.oobbuf = dev->spareBuffer;
15474257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org		retval = mtd->write_oob(mtd, addr, &ops);
15574257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org	} else
15601d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org		BUG(); /* both tags and data should always be present */
15701d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org#else
15874257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org	if (tags) {
159903e746cc9a73da17bfa3f6110293582fa6ee3bestefan@webrtc.org		yaffs_PackTags2(&pt, tags);
16001d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org	}
16101d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org
16201d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org	if (tags) {
16301d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org		nandmtd2_pt2buf(dev, &pt, 1);
164a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org		retval =
165a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org		    mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk,
16601d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org				   &dummy, data, dev->spareBuffer, NULL);
16701d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org	} else if (data) {
16874257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org			retval =
16974257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org			    mtd->write(mtd, addr, dev->nDataBytesPerChunk, &dummy,
17074257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org				       data);
17174257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org	}
17274257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org#endif
17374257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org
17474257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org	if (retval == 0)
17574257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org		return YAFFS_OK;
17674257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org	else
17774257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org		return YAFFS_FAIL;
17874257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org}
17974257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org
18074257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.orgint nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,
18174257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org				       __u8 * data, yaffs_ExtendedTags * tags)
18274257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org{
18374257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org	struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
18474257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
18574257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org	struct mtd_oob_ops ops;
18674257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org#endif
18774257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org	size_t dummy;
18874257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org	int retval = 0;
18974257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org
19074257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org	loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk;
19174257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org
19274257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org	yaffs_PackedTags2 pt;
19374257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org
19474257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org	T(YAFFS_TRACE_MTD,
19574257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org	  (TSTR
19674257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org	   ("nandmtd2_ReadChunkWithTagsFromNAND chunk %d data %p tags %p"
19774257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org	    TENDSTR), chunkInNAND, data, tags));
19874257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org
199a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
200a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org	if (data && !tags)
20174257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org		retval = mtd->read(mtd, addr, dev->nDataBytesPerChunk,
20274257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org				&dummy, data);
20374257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org	else if (tags) {
20474257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org		ops.mode = MTD_OOB_AUTO;
20574257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org		ops.ooblen = mtd->oobsize;
20674257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org		ops.len = data ? dev->nDataBytesPerChunk : mtd->oobsize;
20774257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org		ops.ooboffs = 0;
20874257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org		ops.datbuf = data;
20974257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org		ops.oobbuf = dev->spareBuffer;
21074257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org		retval = mtd->read_oob(mtd, addr, &ops);
21174257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org		nandmtd2_buf2pt(dev, &pt, 1);
21274257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org	}
21374257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org#else
21474257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org	if (data && tags) {
21574257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org			retval =
21674257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org			    mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk,
21774257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org					  &dummy, data, dev->spareBuffer,
21874257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org					  NULL);
21974257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org		} else {
22074257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org			retval =
22174257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org			    mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk,
22274257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org					  &dummy, data, dev->spareBuffer,
22374257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org					  NULL);
22474257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org		}
22574257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org	} else {
22674257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org		if (data)
22774257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org			retval =
22874257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org			    mtd->read(mtd, addr, dev->nDataBytesPerChunk, &dummy,
22974257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org				      data);
23074257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org		if (tags) {
23174257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org			retval =
23274257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org			    mtd->read_oob(mtd, addr, mtd->oobsize, &dummy,
23374257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org					  dev->spareBuffer);
23474257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org			nandmtd2_buf2pt(dev, &pt, 1);
23574257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org		}
23674257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org	}
23774257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org#endif
23874257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org
23974257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org	if (tags)
24074257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org		yaffs_UnpackTags2(tags, &pt);
24174257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org
24274257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org	if(tags && retval == -EBADMSG && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR)
24374257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org		tags->eccResult = YAFFS_ECC_RESULT_UNFIXED;
24474257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org
24574257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org	if (retval == 0)
24674257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org		return YAFFS_OK;
24774257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org	else
24874257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org		return YAFFS_FAIL;
24974257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org}
25074257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org
25174257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.orgint nandmtd2_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo)
25274257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org{
253a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org	struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
254fec6b6e5999edec8c90efae54357f1aae6a4c7ddsolenberg@webrtc.org	int retval;
255a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org	T(YAFFS_TRACE_MTD,
256a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org	  (TSTR("nandmtd2_MarkNANDBlockBad %d" TENDSTR), blockNo));
25701d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org
258a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org	retval =
25901d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org	    mtd->block_markbad(mtd,
260a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org			       blockNo * dev->nChunksPerBlock *
26101d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org			       dev->nDataBytesPerChunk);
26201d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org
263a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org	if (retval == 0)
26401d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org		return YAFFS_OK;
265a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org	else
26601d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org		return YAFFS_FAIL;
267a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org
268a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org}
269a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org
270a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.orgint nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
271a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org			    yaffs_BlockState * state, int *sequenceNumber)
272a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org{
27301d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org	struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
27401d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org	int retval;
27501d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org
27601d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org	T(YAFFS_TRACE_MTD,
27701d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org	  (TSTR("nandmtd2_QueryNANDBlock %d" TENDSTR), blockNo));
27801d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org	retval =
279a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org	    mtd->block_isbad(mtd,
280a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org			     blockNo * dev->nChunksPerBlock *
281a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org			     dev->nDataBytesPerChunk);
28201d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org
2835041831648212bfd5b68e91e1ff39e2b420f679easapersson@webrtc.org	if (retval) {
2845041831648212bfd5b68e91e1ff39e2b420f679easapersson@webrtc.org		T(YAFFS_TRACE_MTD, (TSTR("block is bad" TENDSTR)));
28501d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org
28601d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org		*state = YAFFS_BLOCK_STATE_DEAD;
28701d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org		*sequenceNumber = 0;
28801d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org	} else {
28901d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org		yaffs_ExtendedTags t;
290a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org		nandmtd2_ReadChunkWithTagsFromNAND(dev,
291a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org						   blockNo *
2923dc7ff30185a2d7a597acb69183fca73bd1004d8asapersson@webrtc.org						   dev->nChunksPerBlock, NULL,
29301d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org						   &t);
29401d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org
29501d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org		if (t.chunkUsed) {
2963dc7ff30185a2d7a597acb69183fca73bd1004d8asapersson@webrtc.org			*sequenceNumber = t.sequenceNumber;
2973dc7ff30185a2d7a597acb69183fca73bd1004d8asapersson@webrtc.org			*state = YAFFS_BLOCK_STATE_NEEDS_SCANNING;
29872cc32a68bcb9b2aa32f751dc6d120716d220a10asapersson@webrtc.org		} else {
29901d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org			*sequenceNumber = 0;
30072cc32a68bcb9b2aa32f751dc6d120716d220a10asapersson@webrtc.org			*state = YAFFS_BLOCK_STATE_EMPTY;
30101d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org		}
30201d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org
30372cc32a68bcb9b2aa32f751dc6d120716d220a10asapersson@webrtc.org		T(YAFFS_TRACE_MTD,
30401d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org		  (TSTR("block is OK seq %d state %d" TENDSTR), *sequenceNumber,
30572cc32a68bcb9b2aa32f751dc6d120716d220a10asapersson@webrtc.org		   *state));
30601d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org	}
30772cc32a68bcb9b2aa32f751dc6d120716d220a10asapersson@webrtc.org
30872cc32a68bcb9b2aa32f751dc6d120716d220a10asapersson@webrtc.org	if (retval == 0)
30901d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org		return YAFFS_OK;
31001d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org	else
31101d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org		return YAFFS_FAIL;
31201d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org}
31301d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org
31472cc32a68bcb9b2aa32f751dc6d120716d220a10asapersson@webrtc.org