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_mtdif.c  NAND mtd wrapper functions.
440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *
540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * Copyright (C) 2002 Aleph One Ltd.
640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *   for Toby Churchill Ltd and Brightstar Engineering
740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *
840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * Created by Charles Manning <charles@aleph1.co.uk>
940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *
1040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * This program is free software; you can redistribute it and/or modify
1140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * it under the terms of the GNU General Public License version 2 as
1240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * published by the Free Software Foundation.
1340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *
1440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
1540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
1640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/* mtd interface for YAFFS2 */
1740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
1840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectconst char *yaffs_mtdif2_c_version =
1940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project    "$Id: yaffs_mtdif2.c,v 1.14 2006/10/03 10:13:03 charles Exp $";
2040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
2140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include "yportenv.h"
2240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
2340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
2440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include "yaffs_mtdif2.h"
2540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
2640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include "linux/mtd/mtd.h"
2740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include "linux/types.h"
2840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include "linux/time.h"
2940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
3040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include "yaffs_packedtags2.h"
3140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
3240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
3340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectvoid nandmtd2_pt2buf(yaffs_Device *dev, yaffs_PackedTags2 *pt, int is_raw)
3440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
3540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
3640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	__u8 *ptab = (__u8 *)pt; /* packed tags as bytes */
3740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
3840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int	i, j = 0, k, n;
3940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef CONFIG_YAFFS_DOES_ECC
4040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	size_t packed_size = sizeof(yaffs_PackedTags2);
4140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#else
4240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	size_t packed_size = sizeof(yaffs_PackedTags2TagsPart);
4340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
4440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
4540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Pack buffer with 0xff */
4640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	for (i = 0; i < mtd->oobsize; i++)
4740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		dev->spareBuffer[i] = 0xff;
4840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
4940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(!is_raw){
5040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		memcpy(dev->spareBuffer,pt,packed_size);
5140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	} else {
5240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		j = 0;
5340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		k = mtd->ecclayout->oobfree[j].offset;
5440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		n = mtd->ecclayout->oobfree[j].length;
5540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
5640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		//printk("nandmtd2_pt2buf: writing %d bytes of extra data into %d\n", packed_size, mtd->oobsize);
5740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
5840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (n == 0) {
5940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			T(YAFFS_TRACE_ERROR, (TSTR("No OOB space for tags" TENDSTR)));
6040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			YBUG();
6140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
6240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
6340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		for (i = 0; i < packed_size; i++) {
6440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (n == 0) {
6540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				j++;
6640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				k = mtd->ecclayout->oobfree[j].offset;
6740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				n = mtd->ecclayout->oobfree[j].length;
6840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				if (n == 0 || j >= (sizeof(mtd->ecclayout->oobfree) / sizeof(mtd->ecclayout->oobfree[0]))) {
6940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					T(YAFFS_TRACE_ERROR, (TSTR("No OOB space for tags" TENDSTR)));
7040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					YBUG();
7140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				}
7240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
7340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			dev->spareBuffer[k] = ptab[i];
7440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			k++;
7540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			n--;
7640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
7740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
7840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
7940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
8040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
8140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectvoid nandmtd2_buf2pt(yaffs_Device *dev, yaffs_PackedTags2 *pt, int is_raw)
8240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
8340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
8440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int	i, j = 0, k, n;
8540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	__u8 *ptab = (__u8 *)pt; /* packed tags as bytes */
8640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	size_t packed_size = dev->useNANDECC ? sizeof(yaffs_PackedTags2TagsPart) : sizeof(yaffs_PackedTags2);
8740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
8840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (!is_raw) {
8940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
9040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		memcpy(pt,dev->spareBuffer,packed_size);
9140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	} else {
9240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		j = 0;
9340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		k = mtd->ecclayout->oobfree[j].offset;
9440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		n = mtd->ecclayout->oobfree[j].length;
9540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
9640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (n == 0) {
9740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			T(YAFFS_TRACE_ERROR, (TSTR("No space in OOB for tags" TENDSTR)));
9840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			YBUG();
9940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
10040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
10140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		for (i = 0; i < packed_size; i++) {
10240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			if (n == 0) {
10340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				j++;
10440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				k = mtd->ecclayout->oobfree[j].offset;
10540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				n = mtd->ecclayout->oobfree[j].length;
10640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				if (n == 0 || j >= (sizeof(mtd->ecclayout->oobfree) / sizeof(mtd->ecclayout->oobfree[0]))) {
10740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					T(YAFFS_TRACE_ERROR, (TSTR("No space in OOB for tags" TENDSTR)));
10840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					YBUG();
10940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				}
11040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
11140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			ptab[i] = dev->spareBuffer[k];
11240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			k++;
11340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			n--;
11440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
11540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
11640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
11740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
11840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
11940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND,
12040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				      const __u8 * data,
12140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				      const yaffs_ExtendedTags * tags)
12240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
12340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
12440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
12540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	struct mtd_oob_ops ops;
12640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#else
12740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	size_t dummy;
12840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
12940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int retval = 0;
13040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
13140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk;
13240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
13340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_PackedTags2 pt;
13440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
13540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	T(YAFFS_TRACE_MTD,
13640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	  (TSTR
13740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	   ("nandmtd2_WriteChunkWithTagsToNAND chunk %d data %p tags %p"
13840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    TENDSTR), chunkInNAND, data, tags));
13940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
14040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
14140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (tags)
14240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_PackTags2(&pt, tags);
14340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	else
14440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		BUG(); /* both tags and data should always be present */
14540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
14640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	nandmtd2_pt2buf(dev, &pt, 1);
14740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (data) {
14840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		ops.mode = MTD_OOB_AUTO;
14940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		ops.ooblen = mtd->oobsize;
15040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		ops.len = dev->nDataBytesPerChunk;
15140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		ops.ooboffs = 0;
15240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		ops.datbuf = (__u8 *)data;
15340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		ops.oobbuf = dev->spareBuffer;
15440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		retval = mtd->write_oob(mtd, addr, &ops);
15540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	} else
15640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		BUG(); /* both tags and data should always be present */
15740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#else
15840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (tags) {
15940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_PackTags2(&pt, tags);
16040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
16140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
16240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (tags) {
16340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		nandmtd2_pt2buf(dev, &pt, 1);
16440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		retval =
16540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		    mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk,
16640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				   &dummy, data, dev->spareBuffer, NULL);
16740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	} else if (data) {
16840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			retval =
16940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			    mtd->write(mtd, addr, dev->nDataBytesPerChunk, &dummy,
17040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				       data);
17140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
17240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
17340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
17440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (retval == 0)
17540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return YAFFS_OK;
17640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	else
17740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return YAFFS_FAIL;
17840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
17940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
18040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,
18140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				       __u8 * data, yaffs_ExtendedTags * tags)
18240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
18340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
18440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
18540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	struct mtd_oob_ops ops;
18640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
18740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	size_t dummy;
18840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int retval = 0;
18940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
19040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk;
19140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
19240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_PackedTags2 pt;
19340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
19440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	T(YAFFS_TRACE_MTD,
19540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	  (TSTR
19640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	   ("nandmtd2_ReadChunkWithTagsFromNAND chunk %d data %p tags %p"
19740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    TENDSTR), chunkInNAND, data, tags));
19840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
19940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
20040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (data && !tags)
20140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		retval = mtd->read(mtd, addr, dev->nDataBytesPerChunk,
20240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				&dummy, data);
20340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	else if (tags) {
20440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		ops.mode = MTD_OOB_AUTO;
20540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		ops.ooblen = mtd->oobsize;
20640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		ops.len = data ? dev->nDataBytesPerChunk : mtd->oobsize;
20740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		ops.ooboffs = 0;
20840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		ops.datbuf = data;
20940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		ops.oobbuf = dev->spareBuffer;
21040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		retval = mtd->read_oob(mtd, addr, &ops);
21140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		nandmtd2_buf2pt(dev, &pt, 1);
21240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
21340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#else
21440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (data && tags) {
21540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			retval =
21640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			    mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk,
21740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					  &dummy, data, dev->spareBuffer,
21840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					  NULL);
21940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		} else {
22040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			retval =
22140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			    mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk,
22240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					  &dummy, data, dev->spareBuffer,
22340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					  NULL);
22440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
22540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	} else {
22640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (data)
22740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			retval =
22840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			    mtd->read(mtd, addr, dev->nDataBytesPerChunk, &dummy,
22940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				      data);
23040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (tags) {
23140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			retval =
23240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			    mtd->read_oob(mtd, addr, mtd->oobsize, &dummy,
23340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					  dev->spareBuffer);
23440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			nandmtd2_buf2pt(dev, &pt, 1);
23540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
23640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
23740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
23840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
23940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (tags)
24040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_UnpackTags2(tags, &pt);
24140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
24240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(tags && retval == -EBADMSG && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR)
24340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		tags->eccResult = YAFFS_ECC_RESULT_UNFIXED;
24440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
24540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (retval == 0)
24640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return YAFFS_OK;
24740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	else
24840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return YAFFS_FAIL;
24940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
25040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
25140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint nandmtd2_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo)
25240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
25340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
25440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int retval;
25540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	T(YAFFS_TRACE_MTD,
25640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	  (TSTR("nandmtd2_MarkNANDBlockBad %d" TENDSTR), blockNo));
25740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
25840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	retval =
25940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    mtd->block_markbad(mtd,
26040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			       blockNo * dev->nChunksPerBlock *
26140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			       dev->nDataBytesPerChunk);
26240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
26340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (retval == 0)
26440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return YAFFS_OK;
26540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	else
26640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return YAFFS_FAIL;
26740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
26840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
26940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
27040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
27140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			    yaffs_BlockState * state, int *sequenceNumber)
27240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
27340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
27440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int retval;
27540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
27640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	T(YAFFS_TRACE_MTD,
27740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	  (TSTR("nandmtd2_QueryNANDBlock %d" TENDSTR), blockNo));
27840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	retval =
27940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	    mtd->block_isbad(mtd,
28040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			     blockNo * dev->nChunksPerBlock *
28140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			     dev->nDataBytesPerChunk);
28240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
28340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (retval) {
28440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(YAFFS_TRACE_MTD, (TSTR("block is bad" TENDSTR)));
28540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
28640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		*state = YAFFS_BLOCK_STATE_DEAD;
28740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		*sequenceNumber = 0;
28840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	} else {
28940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_ExtendedTags t;
29040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		nandmtd2_ReadChunkWithTagsFromNAND(dev,
29140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						   blockNo *
29240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						   dev->nChunksPerBlock, NULL,
29340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project						   &t);
29440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
29540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if (t.chunkUsed) {
29640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			*sequenceNumber = t.sequenceNumber;
29740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			*state = YAFFS_BLOCK_STATE_NEEDS_SCANNING;
29840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		} else {
29940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			*sequenceNumber = 0;
30040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			*state = YAFFS_BLOCK_STATE_EMPTY;
30140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
30240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
30340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(YAFFS_TRACE_MTD,
30440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		  (TSTR("block is OK seq %d state %d" TENDSTR), *sequenceNumber,
30540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		   *state));
30640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
30740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
30840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (retval == 0)
30940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return YAFFS_OK;
31040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	else
31140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return YAFFS_FAIL;
31240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
31340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
314