140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/*
240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * YAFFS: Yet another FFS. A NAND-flash specific file system.
340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * yaffs_tagscompat.h: Tags compatability layer to use YAFFS1 formatted NAND.
440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *
540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * Copyright (C) 2002 Aleph One Ltd.
640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *
740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * Created by Charles Manning <charles@aleph1.co.uk>
840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *
940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * This program is free software; you can redistribute it and/or modify
1040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * it under the terms of the GNU General Public License version 2 as
1140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * published by the Free Software Foundation.
1240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *
1340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * $Id: yaffs_tagscompat.c,v 1.8 2005/11/29 20:54:32 marty Exp $
1440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
1540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
1640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include "yaffs_guts.h"
1740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include "yaffs_tagscompat.h"
1840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include "yaffs_ecc.h"
1940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
2040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_HandleReadDataError(yaffs_Device * dev, int chunkInNAND);
2140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef NOTYET
2240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_CheckWrittenBlock(yaffs_Device * dev, int chunkInNAND);
2340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_HandleWriteChunkOk(yaffs_Device * dev, int chunkInNAND,
2440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				     const __u8 * data,
2540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				     const yaffs_Spare * spare);
2640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_HandleUpdateChunk(yaffs_Device * dev, int chunkInNAND,
2740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    const yaffs_Spare * spare);
2840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_HandleWriteChunkError(yaffs_Device * dev, int chunkInNAND);
2940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
3040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
3140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic const char yaffs_countBitsTable[256] = {
3240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
3340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
3440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
3540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
3740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
4040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
4140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
4240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
4340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
4440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
4540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
4640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
4740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
4840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project};
4940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
5040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_CountBits(__u8 x)
5140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
5240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int retVal;
5340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	retVal = yaffs_countBitsTable[x];
5440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return retVal;
5540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
5640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
5740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/********** Tags ECC calculations  *********/
5840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
5940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectvoid yaffs_CalcECC(const __u8 * data, yaffs_Spare * spare)
6040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
6140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_ECCCalculate(data, spare->ecc1);
6240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_ECCCalculate(&data[256], spare->ecc2);
6340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
6440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
6540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectvoid yaffs_CalcTagsECC(yaffs_Tags * tags)
6640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
6740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Calculate an ecc */
6840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
6940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	unsigned char *b = ((yaffs_TagsUnion *) tags)->asBytes;
7040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	unsigned i, j;
7140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	unsigned ecc = 0;
7240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	unsigned bit = 0;
7340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
7440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	tags->ecc = 0;
7540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
7640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	for (i = 0; i < 8; i++) {
7740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		for (j = 1; j & 0xff; j <<= 1) {
7840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			bit++;
7940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (b[i] & j) {
8040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				ecc ^= bit;
8140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
8240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
8340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
8440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
8540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	tags->ecc = ecc;
8640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
8740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
8840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
8940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yaffs_CheckECCOnTags(yaffs_Tags * tags)
9040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
9140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	unsigned ecc = tags->ecc;
9240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
9340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_CalcTagsECC(tags);
9440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
9540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	ecc ^= tags->ecc;
9640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
9740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (ecc && ecc <= 64) {
9840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* TODO: Handle the failure better. Retire? */
9940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		unsigned char *b = ((yaffs_TagsUnion *) tags)->asBytes;
10040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
10140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		ecc--;
10240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
10340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		b[ecc / 8] ^= (1 << (ecc & 7));
10440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
10540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* Now recvalc the ecc */
10640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_CalcTagsECC(tags);
10740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
10840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return 1;	/* recovered error */
10940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	} else if (ecc) {
11040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* Wierd ecc failure value */
11140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* TODO Need to do somethiong here */
11240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return -1;	/* unrecovered error */
11340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
11440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
11540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return 0;
11640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
11740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
11840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/********** Tags **********/
11940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
12040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_LoadTagsIntoSpare(yaffs_Spare * sparePtr,
12140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    yaffs_Tags * tagsPtr)
12240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
12340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_TagsUnion *tu = (yaffs_TagsUnion *) tagsPtr;
12440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
12540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_CalcTagsECC(tagsPtr);
12640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
12740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	sparePtr->tagByte0 = tu->asBytes[0];
12840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	sparePtr->tagByte1 = tu->asBytes[1];
12940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	sparePtr->tagByte2 = tu->asBytes[2];
13040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	sparePtr->tagByte3 = tu->asBytes[3];
13140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	sparePtr->tagByte4 = tu->asBytes[4];
13240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	sparePtr->tagByte5 = tu->asBytes[5];
13340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	sparePtr->tagByte6 = tu->asBytes[6];
13440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	sparePtr->tagByte7 = tu->asBytes[7];
13540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
13640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
13740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_GetTagsFromSpare(yaffs_Device * dev, yaffs_Spare * sparePtr,
13840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				   yaffs_Tags * tagsPtr)
13940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
14040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_TagsUnion *tu = (yaffs_TagsUnion *) tagsPtr;
14140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int result;
14240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
14340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	tu->asBytes[0] = sparePtr->tagByte0;
14440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	tu->asBytes[1] = sparePtr->tagByte1;
14540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	tu->asBytes[2] = sparePtr->tagByte2;
14640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	tu->asBytes[3] = sparePtr->tagByte3;
14740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	tu->asBytes[4] = sparePtr->tagByte4;
14840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	tu->asBytes[5] = sparePtr->tagByte5;
14940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	tu->asBytes[6] = sparePtr->tagByte6;
15040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	tu->asBytes[7] = sparePtr->tagByte7;
15140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
15240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	result = yaffs_CheckECCOnTags(tagsPtr);
15340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (result > 0) {
15440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->tagsEccFixed++;
15540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	} else if (result < 0) {
15640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->tagsEccUnfixed++;
15740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
15840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
15940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
16040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_SpareInitialise(yaffs_Spare * spare)
16140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
16240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	memset(spare, 0xFF, sizeof(yaffs_Spare));
16340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
16440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
16540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_WriteChunkToNAND(struct yaffs_DeviceStruct *dev,
16640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				  int chunkInNAND, const __u8 * data,
16740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				  yaffs_Spare * spare)
16840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
16940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (chunkInNAND < dev->startBlock * dev->nChunksPerBlock) {
17040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(YAFFS_TRACE_ERROR,
17140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		  (TSTR("**>> yaffs chunk %d is not valid" TENDSTR),
17240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		   chunkInNAND));
17340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return YAFFS_FAIL;
17440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
17540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
17640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->nPageWrites++;
17740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return dev->writeChunkToNAND(dev, chunkInNAND, data, spare);
17840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
17940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
18040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_ReadChunkFromNAND(struct yaffs_DeviceStruct *dev,
18140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				   int chunkInNAND,
18240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				   __u8 * data,
18340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				   yaffs_Spare * spare,
18440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				   yaffs_ECCResult * eccResult,
18540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				   int doErrorCorrection)
18640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
18740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int retVal;
18840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Spare localSpare;
18940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
19040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->nPageReads++;
19140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
19240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (!spare && data) {
19340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* If we don't have a real spare, then we use a local one. */
19440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* Need this for the calculation of the ecc */
19540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		spare = &localSpare;
19640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
19740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
19840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (!dev->useNANDECC) {
19940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		retVal = dev->readChunkFromNAND(dev, chunkInNAND, data, spare);
20040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (data && doErrorCorrection) {
20140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* Do ECC correction */
20240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* Todo handle any errors */
20340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			int eccResult1, eccResult2;
20440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			__u8 calcEcc[3];
20540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
20640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			yaffs_ECCCalculate(data, calcEcc);
20740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			eccResult1 =
20840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			    yaffs_ECCCorrect(data, spare->ecc1, calcEcc);
20940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			yaffs_ECCCalculate(&data[256], calcEcc);
21040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			eccResult2 =
21140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			    yaffs_ECCCorrect(&data[256], spare->ecc2, calcEcc);
21240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
21340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (eccResult1 > 0) {
21440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				T(YAFFS_TRACE_ERROR,
21540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				  (TSTR
21640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				   ("**>>yaffs ecc error fix performed on chunk %d:0"
21740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    TENDSTR), chunkInNAND));
21840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				dev->eccFixed++;
21940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			} else if (eccResult1 < 0) {
22040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				T(YAFFS_TRACE_ERROR,
22140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				  (TSTR
22240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				   ("**>>yaffs ecc error unfixed on chunk %d:0"
22340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    TENDSTR), chunkInNAND));
22440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				dev->eccUnfixed++;
22540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
22640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
22740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (eccResult2 > 0) {
22840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				T(YAFFS_TRACE_ERROR,
22940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				  (TSTR
23040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				   ("**>>yaffs ecc error fix performed on chunk %d:1"
23140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    TENDSTR), chunkInNAND));
23240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				dev->eccFixed++;
23340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			} else if (eccResult2 < 0) {
23440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				T(YAFFS_TRACE_ERROR,
23540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				  (TSTR
23640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				   ("**>>yaffs ecc error unfixed on chunk %d:1"
23740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    TENDSTR), chunkInNAND));
23840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				dev->eccUnfixed++;
23940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
24040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
24140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (eccResult1 || eccResult2) {
24240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				/* We had a data problem on this page */
24340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				yaffs_HandleReadDataError(dev, chunkInNAND);
24440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
24540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
24640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (eccResult1 < 0 || eccResult2 < 0)
24740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				*eccResult = YAFFS_ECC_RESULT_UNFIXED;
24840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			else if (eccResult1 > 0 || eccResult2 > 0)
24940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				*eccResult = YAFFS_ECC_RESULT_FIXED;
25040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			else
25140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				*eccResult = YAFFS_ECC_RESULT_NO_ERROR;
25240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
25340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	} else {
25440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* Must allocate enough memory for spare+2*sizeof(int) */
25540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* for ecc results from device. */
25640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		struct yaffs_NANDSpare nspare;
25740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		retVal =
25840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		    dev->readChunkFromNAND(dev, chunkInNAND, data,
25940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					   (yaffs_Spare *) & nspare);
26040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		memcpy(spare, &nspare, sizeof(yaffs_Spare));
26140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (data && doErrorCorrection) {
26240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (nspare.eccres1 > 0) {
26340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				T(YAFFS_TRACE_ERROR,
26440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				  (TSTR
26540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				   ("**>>mtd ecc error fix performed on chunk %d:0"
26640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    TENDSTR), chunkInNAND));
26740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			} else if (nspare.eccres1 < 0) {
26840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				T(YAFFS_TRACE_ERROR,
26940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				  (TSTR
27040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				   ("**>>mtd ecc error unfixed on chunk %d:0"
27140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    TENDSTR), chunkInNAND));
27240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
27340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
27440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (nspare.eccres2 > 0) {
27540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				T(YAFFS_TRACE_ERROR,
27640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				  (TSTR
27740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				   ("**>>mtd ecc error fix performed on chunk %d:1"
27840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    TENDSTR), chunkInNAND));
27940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			} else if (nspare.eccres2 < 0) {
28040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				T(YAFFS_TRACE_ERROR,
28140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				  (TSTR
28240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				   ("**>>mtd ecc error unfixed on chunk %d:1"
28340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    TENDSTR), chunkInNAND));
28440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
28540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
28640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (nspare.eccres1 || nspare.eccres2) {
28740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				/* We had a data problem on this page */
28840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				yaffs_HandleReadDataError(dev, chunkInNAND);
28940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
29040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
29140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (nspare.eccres1 < 0 || nspare.eccres2 < 0)
29240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				*eccResult = YAFFS_ECC_RESULT_UNFIXED;
29340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			else if (nspare.eccres1 > 0 || nspare.eccres2 > 0)
29440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				*eccResult = YAFFS_ECC_RESULT_FIXED;
29540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			else
29640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				*eccResult = YAFFS_ECC_RESULT_NO_ERROR;
29740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
29840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
29940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
30040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return retVal;
30140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
30240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
30340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef NOTYET
30440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev,
30540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				  int chunkInNAND)
30640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
30740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
30840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	static int init = 0;
30940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	static __u8 cmpbuf[YAFFS_BYTES_PER_CHUNK];
31040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	static __u8 data[YAFFS_BYTES_PER_CHUNK];
31140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Might as well always allocate the larger size for */
31240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* dev->useNANDECC == true; */
31340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	static __u8 spare[sizeof(struct yaffs_NANDSpare)];
31440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
31540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	dev->readChunkFromNAND(dev, chunkInNAND, data, (yaffs_Spare *) spare);
31640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
31740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (!init) {
31840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		memset(cmpbuf, 0xff, YAFFS_BYTES_PER_CHUNK);
31940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		init = 1;
32040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
32140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
32240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (memcmp(cmpbuf, data, YAFFS_BYTES_PER_CHUNK))
32340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return YAFFS_FAIL;
32440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (memcmp(cmpbuf, spare, 16))
32540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return YAFFS_FAIL;
32640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
32740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return YAFFS_OK;
32840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
32940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
33040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
33140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
33240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/*
33340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * Functions for robustisizing
33440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
33540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
33640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_HandleReadDataError(yaffs_Device * dev, int chunkInNAND)
33740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
33840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int blockInNAND = chunkInNAND / dev->nChunksPerBlock;
33940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
34040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Mark the block for retirement */
34140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_GetBlockInfo(dev, blockInNAND)->needsRetiring = 1;
34240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,
34340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	  (TSTR("**>>Block %d marked for retirement" TENDSTR), blockInNAND));
34440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
34540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* TODO:
34640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 * Just do a garbage collection on the affected block
34740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 * then retire the block
34840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 * NB recursion
34940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	 */
35040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
35140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
35240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef NOTYET
35340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_CheckWrittenBlock(yaffs_Device * dev, int chunkInNAND)
35440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
35540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
35640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
35740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_HandleWriteChunkOk(yaffs_Device * dev, int chunkInNAND,
35840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				     const __u8 * data,
35940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				     const yaffs_Spare * spare)
36040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
36140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
36240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
36340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_HandleUpdateChunk(yaffs_Device * dev, int chunkInNAND,
36440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				    const yaffs_Spare * spare)
36540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
36640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
36740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
36840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_HandleWriteChunkError(yaffs_Device * dev, int chunkInNAND)
36940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
37040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int blockInNAND = chunkInNAND / dev->nChunksPerBlock;
37140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
37240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Mark the block for retirement */
37340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_GetBlockInfo(dev, blockInNAND)->needsRetiring = 1;
37440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Delete the chunk */
37540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_DeleteChunk(dev, chunkInNAND, 1, __LINE__);
37640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
37740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
37840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_VerifyCompare(const __u8 * d0, const __u8 * d1,
37940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			       const yaffs_Spare * s0, const yaffs_Spare * s1)
38040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
38140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
38240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (memcmp(d0, d1, YAFFS_BYTES_PER_CHUNK) != 0 ||
38340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    s0->tagByte0 != s1->tagByte0 ||
38440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    s0->tagByte1 != s1->tagByte1 ||
38540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    s0->tagByte2 != s1->tagByte2 ||
38640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    s0->tagByte3 != s1->tagByte3 ||
38740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    s0->tagByte4 != s1->tagByte4 ||
38840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    s0->tagByte5 != s1->tagByte5 ||
38940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    s0->tagByte6 != s1->tagByte6 ||
39040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    s0->tagByte7 != s1->tagByte7 ||
39140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    s0->ecc1[0] != s1->ecc1[0] ||
39240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    s0->ecc1[1] != s1->ecc1[1] ||
39340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    s0->ecc1[2] != s1->ecc1[2] ||
39440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    s0->ecc2[0] != s1->ecc2[0] ||
39540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    s0->ecc2[1] != s1->ecc2[1] || s0->ecc2[2] != s1->ecc2[2]) {
39640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return 0;
39740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
39840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
39940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return 1;
40040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
40140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif				/* NOTYET */
40240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
40340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yaffs_TagsCompatabilityWriteChunkWithTagsToNAND(yaffs_Device * dev,
40440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    int chunkInNAND,
40540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    const __u8 * data,
40640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    const yaffs_ExtendedTags *
40740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						    eTags)
40840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
40940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Spare spare;
41040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Tags tags;
41140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
41240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_SpareInitialise(&spare);
41340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
41440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (eTags->chunkDeleted) {
41540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		spare.pageStatus = 0;
41640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	} else {
41740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		tags.objectId = eTags->objectId;
41840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		tags.chunkId = eTags->chunkId;
41940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		tags.byteCount = eTags->byteCount;
42040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		tags.serialNumber = eTags->serialNumber;
42140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
42240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (!dev->useNANDECC && data) {
42340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			yaffs_CalcECC(data, &spare);
42440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
42540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_LoadTagsIntoSpare(&spare, &tags);
42640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
42740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
42840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
42940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return yaffs_WriteChunkToNAND(dev, chunkInNAND, data, &spare);
43040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
43140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
43240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(yaffs_Device * dev,
43340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						     int chunkInNAND,
43440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						     __u8 * data,
43540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						     yaffs_ExtendedTags * eTags)
43640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
43740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
43840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Spare spare;
43940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Tags tags;
44040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_ECCResult eccResult;
44140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
44240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	static yaffs_Spare spareFF;
44340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	static int init;
44440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
44540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (!init) {
44640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		memset(&spareFF, 0xFF, sizeof(spareFF));
44740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		init = 1;
44840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
44940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
45040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (yaffs_ReadChunkFromNAND
45140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    (dev, chunkInNAND, data, &spare, &eccResult, 1)) {
45240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* eTags may be NULL */
45340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (eTags) {
45440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
45540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			int deleted =
45640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			    (yaffs_CountBits(spare.pageStatus) < 7) ? 1 : 0;
45740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
45840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			eTags->chunkDeleted = deleted;
45940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			eTags->eccResult = eccResult;
46040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			eTags->blockBad = 0;	/* We're reading it */
46140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			/* therefore it is not a bad block */
46240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			eTags->chunkUsed =
46340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			    (memcmp(&spareFF, &spare, sizeof(spareFF)) !=
46440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			     0) ? 1 : 0;
46540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
46640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (eTags->chunkUsed) {
46740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				yaffs_GetTagsFromSpare(dev, &spare, &tags);
46840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
46940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				eTags->objectId = tags.objectId;
47040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				eTags->chunkId = tags.chunkId;
47140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				eTags->byteCount = tags.byteCount;
47240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				eTags->serialNumber = tags.serialNumber;
47340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
47440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
47540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
47640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return YAFFS_OK;
47740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	} else {
47840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return YAFFS_FAIL;
47940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
48040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
48140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
48240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yaffs_TagsCompatabilityMarkNANDBlockBad(struct yaffs_DeviceStruct *dev,
48340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					    int blockInNAND)
48440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
48540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
48640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Spare spare;
48740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
48840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	memset(&spare, 0xff, sizeof(yaffs_Spare));
48940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
49040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	spare.blockStatus = 'Y';
49140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
49240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_WriteChunkToNAND(dev, blockInNAND * dev->nChunksPerBlock, NULL,
49340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			       &spare);
49440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_WriteChunkToNAND(dev, blockInNAND * dev->nChunksPerBlock + 1,
49540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			       NULL, &spare);
49640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
49740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return YAFFS_OK;
49840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
49940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
50040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
50140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yaffs_TagsCompatabilityQueryNANDBlock(struct yaffs_DeviceStruct *dev,
50240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					  int blockNo, yaffs_BlockState *
50340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					  state,
50440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					  int *sequenceNumber)
50540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
50640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
50740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_Spare spare0, spare1;
50840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	static yaffs_Spare spareFF;
50940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	static int init;
51040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_ECCResult dummy;
51140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
51240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (!init) {
51340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		memset(&spareFF, 0xFF, sizeof(spareFF));
51440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		init = 1;
51540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
51640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
51740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	*sequenceNumber = 0;
51840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
51940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_ReadChunkFromNAND(dev, blockNo * dev->nChunksPerBlock, NULL,
52040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				&spare0, &dummy, 1);
52140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_ReadChunkFromNAND(dev, blockNo * dev->nChunksPerBlock + 1, NULL,
52240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				&spare1, &dummy, 1);
52340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
52440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (yaffs_CountBits(spare0.blockStatus & spare1.blockStatus) < 7)
52540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		*state = YAFFS_BLOCK_STATE_DEAD;
52640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	else if (memcmp(&spareFF, &spare0, sizeof(spareFF)) == 0)
52740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		*state = YAFFS_BLOCK_STATE_EMPTY;
52840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	else
52940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		*state = YAFFS_BLOCK_STATE_NEEDS_SCANNING;
53040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
53140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return YAFFS_OK;
53240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
533