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 * 440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * Copyright (C) 2002 Aleph One Ltd. 540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * for Toby Churchill Ltd and Brightstar Engineering 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 */ 1440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 1540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectconst char *yaffs_nand_c_version = 1640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project "$Id: yaffs_nand.c,v 1.4 2006/10/13 08:52:49 charles Exp $"; 1740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 1840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include "yaffs_nand.h" 1940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include "yaffs_tagscompat.h" 2040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include "yaffs_tagsvalidity.h" 2140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 2240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 2340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yaffs_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND, 2440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project __u8 * buffer, 2540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project yaffs_ExtendedTags * tags) 2640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{ 2740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project int result; 2840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project yaffs_ExtendedTags localTags; 2940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 3040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project int realignedChunkInNAND = chunkInNAND - dev->chunkOffset; 3140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 3240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project /* If there are no tags provided, use local tags to get prioritised gc working */ 3340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(!tags) 3440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project tags = &localTags; 3540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 3640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if (dev->readChunkWithTagsFromNAND) 3740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project result = dev->readChunkWithTagsFromNAND(dev, realignedChunkInNAND, buffer, 3840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project tags); 3940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project else 4040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project result = yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(dev, 4140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project realignedChunkInNAND, 4240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project buffer, 4340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project tags); 4440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(tags && 4540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project tags->eccResult > YAFFS_ECC_RESULT_NO_ERROR){ 4640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 4740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, chunkInNAND/dev->nChunksPerBlock); 4840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project yaffs_HandleChunkError(dev,bi); 4940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 5040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 5140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return result; 5240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project} 5340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 5440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yaffs_WriteChunkWithTagsToNAND(yaffs_Device * dev, 5540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project int chunkInNAND, 5640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project const __u8 * buffer, 5740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project yaffs_ExtendedTags * tags) 5840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{ 5940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project chunkInNAND -= dev->chunkOffset; 6040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 6140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 6240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if (tags) { 6340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project tags->sequenceNumber = dev->sequenceNumber; 6440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project tags->chunkUsed = 1; 6540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if (!yaffs_ValidateTags(tags)) { 6640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project T(YAFFS_TRACE_ERROR, 6740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project (TSTR("Writing uninitialised tags" TENDSTR))); 6840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project YBUG(); 6940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 7040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project T(YAFFS_TRACE_WRITE, 7140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project (TSTR("Writing chunk %d tags %d %d" TENDSTR), chunkInNAND, 7240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project tags->objectId, tags->chunkId)); 7340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } else { 7440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project T(YAFFS_TRACE_ERROR, (TSTR("Writing with no tags" TENDSTR))); 7540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project YBUG(); 7640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 7740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 7840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if (dev->writeChunkWithTagsToNAND) 7940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return dev->writeChunkWithTagsToNAND(dev, chunkInNAND, buffer, 8040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project tags); 8140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project else 8240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return yaffs_TagsCompatabilityWriteChunkWithTagsToNAND(dev, 8340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project chunkInNAND, 8440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project buffer, 8540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project tags); 8640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project} 8740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 8840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yaffs_MarkBlockBad(yaffs_Device * dev, int blockNo) 8940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{ 9040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project blockNo -= dev->blockOffset; 9140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 9240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project; 9340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if (dev->markNANDBlockBad) 9440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return dev->markNANDBlockBad(dev, blockNo); 9540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project else 9640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return yaffs_TagsCompatabilityMarkNANDBlockBad(dev, blockNo); 9740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project} 9840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 9940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yaffs_QueryInitialBlockState(yaffs_Device * dev, 10040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project int blockNo, 10140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project yaffs_BlockState * state, 10240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project unsigned *sequenceNumber) 10340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{ 10440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project blockNo -= dev->blockOffset; 10540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 10640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if (dev->queryNANDBlock) 10740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return dev->queryNANDBlock(dev, blockNo, state, sequenceNumber); 10840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project else 10940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return yaffs_TagsCompatabilityQueryNANDBlock(dev, blockNo, 11040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project state, 11140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project sequenceNumber); 11240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project} 11340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 11440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 11540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yaffs_EraseBlockInNAND(struct yaffs_DeviceStruct *dev, 11640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project int blockInNAND) 11740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{ 11840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project int result; 11940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 12040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project blockInNAND -= dev->blockOffset; 12140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 12240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 12340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->nBlockErasures++; 12440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project result = dev->eraseBlockInNAND(dev, blockInNAND); 12540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 12640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project /* If at first we don't succeed, try again *once*.*/ 12740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if (!result) 12840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project result = dev->eraseBlockInNAND(dev, blockInNAND); 12940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return result; 13040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project} 13140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 13240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yaffs_InitialiseNAND(struct yaffs_DeviceStruct *dev) 13340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{ 13440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return dev->initialiseNAND(dev); 13540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project} 13640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 13740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 13840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 139