1 /* 2 * YAFFS: Yet another FFS. A NAND-flash specific file system. 3 * 4 * Copyright (C) 2002 Aleph One Ltd. 5 * for Toby Churchill Ltd and Brightstar Engineering 6 * 7 * Created by Charles Manning <charles (at) aleph1.co.uk> 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License version 2 as 11 * published by the Free Software Foundation. 12 * 13 */ 14 15 const char *yaffs_nand_c_version = 16 "$Id: yaffs_nand.c,v 1.4 2006/10/13 08:52:49 charles Exp $"; 17 18 #include "yaffs_nand.h" 19 #include "yaffs_tagscompat.h" 20 #include "yaffs_tagsvalidity.h" 21 22 23 int yaffs_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND, 24 __u8 * buffer, 25 yaffs_ExtendedTags * tags) 26 { 27 int result; 28 yaffs_ExtendedTags localTags; 29 30 int realignedChunkInNAND = chunkInNAND - dev->chunkOffset; 31 32 /* If there are no tags provided, use local tags to get prioritised gc working */ 33 if(!tags) 34 tags = &localTags; 35 36 if (dev->readChunkWithTagsFromNAND) 37 result = dev->readChunkWithTagsFromNAND(dev, realignedChunkInNAND, buffer, 38 tags); 39 else 40 result = yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(dev, 41 realignedChunkInNAND, 42 buffer, 43 tags); 44 if(tags && 45 tags->eccResult > YAFFS_ECC_RESULT_NO_ERROR){ 46 47 yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, chunkInNAND/dev->nChunksPerBlock); 48 yaffs_HandleChunkError(dev,bi); 49 } 50 51 return result; 52 } 53 54 int yaffs_WriteChunkWithTagsToNAND(yaffs_Device * dev, 55 int chunkInNAND, 56 const __u8 * buffer, 57 yaffs_ExtendedTags * tags) 58 { 59 chunkInNAND -= dev->chunkOffset; 60 61 62 if (tags) { 63 tags->sequenceNumber = dev->sequenceNumber; 64 tags->chunkUsed = 1; 65 if (!yaffs_ValidateTags(tags)) { 66 T(YAFFS_TRACE_ERROR, 67 (TSTR("Writing uninitialised tags" TENDSTR))); 68 YBUG(); 69 } 70 T(YAFFS_TRACE_WRITE, 71 (TSTR("Writing chunk %d tags %d %d" TENDSTR), chunkInNAND, 72 tags->objectId, tags->chunkId)); 73 } else { 74 T(YAFFS_TRACE_ERROR, (TSTR("Writing with no tags" TENDSTR))); 75 YBUG(); 76 } 77 78 if (dev->writeChunkWithTagsToNAND) 79 return dev->writeChunkWithTagsToNAND(dev, chunkInNAND, buffer, 80 tags); 81 else 82 return yaffs_TagsCompatabilityWriteChunkWithTagsToNAND(dev, 83 chunkInNAND, 84 buffer, 85 tags); 86 } 87 88 int yaffs_MarkBlockBad(yaffs_Device * dev, int blockNo) 89 { 90 blockNo -= dev->blockOffset; 91 92 ; 93 if (dev->markNANDBlockBad) 94 return dev->markNANDBlockBad(dev, blockNo); 95 else 96 return yaffs_TagsCompatabilityMarkNANDBlockBad(dev, blockNo); 97 } 98 99 int yaffs_QueryInitialBlockState(yaffs_Device * dev, 100 int blockNo, 101 yaffs_BlockState * state, 102 unsigned *sequenceNumber) 103 { 104 blockNo -= dev->blockOffset; 105 106 if (dev->queryNANDBlock) 107 return dev->queryNANDBlock(dev, blockNo, state, sequenceNumber); 108 else 109 return yaffs_TagsCompatabilityQueryNANDBlock(dev, blockNo, 110 state, 111 sequenceNumber); 112 } 113 114 115 int yaffs_EraseBlockInNAND(struct yaffs_DeviceStruct *dev, 116 int blockInNAND) 117 { 118 int result; 119 120 blockInNAND -= dev->blockOffset; 121 122 123 dev->nBlockErasures++; 124 result = dev->eraseBlockInNAND(dev, blockInNAND); 125 126 /* If at first we don't succeed, try again *once*.*/ 127 if (!result) 128 result = dev->eraseBlockInNAND(dev, blockInNAND); 129 return result; 130 } 131 132 int yaffs_InitialiseNAND(struct yaffs_DeviceStruct *dev) 133 { 134 return dev->initialiseNAND(dev); 135 } 136 137 138 139