yaffs Add error retrieval function for yaffs direct testing
[yaffs2.git] / yaffs_nand.c
1 /*
2  * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
3  *
4  * Copyright (C) 2002-2010 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 #include "yaffs_nand.h"
15 #include "yaffs_tagscompat.h"
16 #include "yaffs_tagsvalidity.h"
17
18 #include "yaffs_getblockinfo.h"
19
20 int yaffs_ReadChunkWithTagsFromNAND(yaffs_Device *dev, int chunkInNAND,
21                                            __u8 *buffer,
22                                            yaffs_ExtendedTags *tags)
23 {
24         int result;
25         yaffs_ExtendedTags localTags;
26
27         int realignedChunkInNAND = chunkInNAND - dev->chunkOffset;
28
29         dev->nPageReads++;
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->param.readChunkWithTagsFromNAND)
36                 result = dev->param.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;
47                 bi = yaffs_GetBlockInfo(dev, chunkInNAND/dev->param.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
60         dev->nPageWrites++;
61
62         chunkInNAND -= dev->chunkOffset;
63
64
65         if (tags) {
66                 tags->sequenceNumber = dev->sequenceNumber;
67                 tags->chunkUsed = 1;
68                 if (!yaffs_ValidateTags(tags)) {
69                         T(YAFFS_TRACE_ERROR,
70                           (TSTR("Writing uninitialised tags" TENDSTR)));
71                         YBUG();
72                 }
73                 T(YAFFS_TRACE_WRITE,
74                   (TSTR("Writing chunk %d tags %d %d" TENDSTR), chunkInNAND,
75                    tags->objectId, tags->chunkId));
76         } else {
77                 T(YAFFS_TRACE_ERROR, (TSTR("Writing with no tags" TENDSTR)));
78                 YBUG();
79         }
80
81         if (dev->param.writeChunkWithTagsToNAND)
82                 return dev->param.writeChunkWithTagsToNAND(dev, chunkInNAND, buffer,
83                                                      tags);
84         else
85                 return yaffs_TagsCompatabilityWriteChunkWithTagsToNAND(dev,
86                                                                        chunkInNAND,
87                                                                        buffer,
88                                                                        tags);
89 }
90
91 int yaffs_MarkBlockBad(yaffs_Device *dev, int blockNo)
92 {
93         blockNo -= dev->blockOffset;
94
95
96         if (dev->param.markNANDBlockBad)
97                 return dev->param.markNANDBlockBad(dev, blockNo);
98         else
99                 return yaffs_TagsCompatabilityMarkNANDBlockBad(dev, blockNo);
100 }
101
102 int yaffs_QueryInitialBlockState(yaffs_Device *dev,
103                                                  int blockNo,
104                                                  yaffs_BlockState *state,
105                                                  __u32 *sequenceNumber)
106 {
107         blockNo -= dev->blockOffset;
108
109         if (dev->param.queryNANDBlock)
110                 return dev->param.queryNANDBlock(dev, blockNo, state, sequenceNumber);
111         else
112                 return yaffs_TagsCompatabilityQueryNANDBlock(dev, blockNo,
113                                                              state,
114                                                              sequenceNumber);
115 }
116
117
118 int yaffs_EraseBlockInNAND(struct yaffs_DeviceStruct *dev,
119                                   int blockInNAND)
120 {
121         int result;
122
123         blockInNAND -= dev->blockOffset;
124
125         dev->nBlockErasures++;
126
127         result = dev->param.eraseBlockInNAND(dev, blockInNAND);
128
129         return result;
130 }
131
132 int yaffs_InitialiseNAND(struct yaffs_DeviceStruct *dev)
133 {
134         if(dev->param.initialiseNAND)
135                 return dev->param.initialiseNAND(dev);
136         return YAFFS_OK;
137 }
138
139
140