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