YAFFS2 import
[platform/kernel/u-boot.git] / fs / yaffs2 / yaffs_nand.c
1 /*
2  * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
3  *
4  * Copyright (C) 2002-2007 Aleph One Ltd.
5  *   for Toby Churchill Ltd and Brightstar Engineering
6  *
7  * Created by Charles Manning <charles@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 const char *yaffs_nand_c_version =
15     "$Id: yaffs_nand.c,v 1.7 2007/02/14 01:09:06 wookey Exp $";
16
17 #include "yaffs_nand.h"
18 #include "yaffs_tagscompat.h"
19 #include "yaffs_tagsvalidity.h"
20
21
22 int yaffs_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,
23                                            __u8 * buffer,
24                                            yaffs_ExtendedTags * tags)
25 {
26         int result;
27         yaffs_ExtendedTags localTags;
28         
29         int realignedChunkInNAND = chunkInNAND - dev->chunkOffset;
30         
31         /* If there are no tags provided, use local tags to get prioritised gc working */
32         if(!tags)
33                 tags = &localTags;
34
35         if (dev->readChunkWithTagsFromNAND)
36                 result = dev->readChunkWithTagsFromNAND(dev, realignedChunkInNAND, buffer,
37                                                       tags);
38         else
39                 result = yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(dev,
40                                                                         realignedChunkInNAND,
41                                                                         buffer,
42                                                                         tags);  
43         if(tags && 
44            tags->eccResult > YAFFS_ECC_RESULT_NO_ERROR){
45         
46                 yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, chunkInNAND/dev->nChunksPerBlock);
47                 yaffs_HandleChunkError(dev,bi);
48         }
49                                                                 
50         return result;
51 }
52
53 int yaffs_WriteChunkWithTagsToNAND(yaffs_Device * dev,
54                                                    int chunkInNAND,
55                                                    const __u8 * buffer,
56                                                    yaffs_ExtendedTags * tags)
57 {
58         chunkInNAND -= dev->chunkOffset;
59
60         
61         if (tags) {
62                 tags->sequenceNumber = dev->sequenceNumber;
63                 tags->chunkUsed = 1;
64                 if (!yaffs_ValidateTags(tags)) {
65                         T(YAFFS_TRACE_ERROR,
66                           (TSTR("Writing uninitialised tags" TENDSTR)));
67                         YBUG();
68                 }
69                 T(YAFFS_TRACE_WRITE,
70                   (TSTR("Writing chunk %d tags %d %d" TENDSTR), chunkInNAND,
71                    tags->objectId, tags->chunkId));
72         } else {
73                 T(YAFFS_TRACE_ERROR, (TSTR("Writing with no tags" TENDSTR)));
74                 YBUG();
75         }
76
77         if (dev->writeChunkWithTagsToNAND)
78                 return dev->writeChunkWithTagsToNAND(dev, chunkInNAND, buffer,
79                                                      tags);
80         else
81                 return yaffs_TagsCompatabilityWriteChunkWithTagsToNAND(dev,
82                                                                        chunkInNAND,
83                                                                        buffer,
84                                                                        tags);
85 }
86
87 int yaffs_MarkBlockBad(yaffs_Device * dev, int blockNo)
88 {
89         blockNo -= dev->blockOffset;
90
91 ;
92         if (dev->markNANDBlockBad)
93                 return dev->markNANDBlockBad(dev, blockNo);
94         else
95                 return yaffs_TagsCompatabilityMarkNANDBlockBad(dev, blockNo);
96 }
97
98 int yaffs_QueryInitialBlockState(yaffs_Device * dev,
99                                                  int blockNo,
100                                                  yaffs_BlockState * state,
101                                                  unsigned *sequenceNumber)
102 {
103         blockNo -= dev->blockOffset;
104
105         if (dev->queryNANDBlock)
106                 return dev->queryNANDBlock(dev, blockNo, state, sequenceNumber);
107         else
108                 return yaffs_TagsCompatabilityQueryNANDBlock(dev, blockNo,
109                                                              state,
110                                                              sequenceNumber);
111 }
112
113
114 int yaffs_EraseBlockInNAND(struct yaffs_DeviceStruct *dev,
115                                   int blockInNAND)
116 {
117         int result;
118
119         blockInNAND -= dev->blockOffset;
120
121
122         dev->nBlockErasures++;
123         result = dev->eraseBlockInNAND(dev, blockInNAND);
124
125         return result;
126 }
127
128 int yaffs_InitialiseNAND(struct yaffs_DeviceStruct *dev)
129 {
130         return dev->initialiseNAND(dev);
131 }
132
133
134