yaffs: Add python test for O_EXCL
[yaffs2.git] / direct / yaffs_nandif.c
1 /*\r
2  * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.\r
3  *\r
4  * Copyright (C) 2002-2010 Aleph One Ltd.\r
5  *   for Toby Churchill Ltd and Brightstar Engineering\r
6  *\r
7  * Created by Charles Manning <charles@aleph1.co.uk>\r
8  *\r
9  * This program is free software; you can redistribute it and/or modify\r
10  * it under the terms of the GNU General Public License version 2 as\r
11  * published by the Free Software Foundation.\r
12  */\r
13 \r
14 \r
15 \r
16 \r
17 #include "yportenv.h"\r
18 #include "yaffs_guts.h"\r
19 #include "devextras.h"\r
20 \r
21 \r
22 #include "yaffs_nandif.h"\r
23 #include "yaffs_packedtags2.h"\r
24 \r
25 \r
26 #if 0\r
27 \r
28 \r
29 static unsigned char *DevBufferIn(yaffs_Device *dev)\r
30 {\r
31         yfsd_WinCEDevice *cedev = (yfsd_WinCEDevice *)(dev->genericDevice);\r
32         return cedev->bufferIn;\r
33 }\r
34 static unsigned char *DevBufferOut(yaffs_Device *dev)\r
35 {\r
36         yfsd_WinCEDevice *cedev = (yfsd_WinCEDevice *)(dev->genericDevice);\r
37         return cedev->bufferOut;\r
38 }\r
39 \r
40 static unsigned DevBufferSize(yaffs_Device *dev)\r
41 {\r
42         yfsd_WinCEDevice *cedev = (yfsd_WinCEDevice *)(dev->genericDevice);\r
43         return cedev->bufferSize;\r
44 }\r
45 \r
46 #endif\r
47 \r
48 /* NB For use with inband tags....\r
49  * We assume that the data buffer is of size totalBytersPerChunk so that we can also\r
50  * use it to load the tags.\r
51  */\r
52 int ynandif_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND,\r
53                                       const __u8 * data,\r
54                                       const yaffs_ExtendedTags * tags)\r
55 {\r
56 \r
57         int retval = 0;\r
58         yaffs_PackedTags2 pt;\r
59         void *spare;\r
60         unsigned spareSize = 0;\r
61 \r
62         unsigned char *bufferIn   = DevBufferIn(dev);\r
63         unsigned char *bufferOut  = DevBufferOut(dev);\r
64         unsigned       bufferSize = DevBufferSize(dev);\r
65 \r
66         T(YAFFS_TRACE_MTD,\r
67           (TSTR\r
68            ("nandmtd2_WriteChunkWithTagsToNAND chunk %d data %p tags %p"\r
69             TENDSTR), chunkInNAND, data, tags));\r
70             \r
71 \r
72         /* For yaffs2 writing there must be both data and tags.\r
73          * If we're using inband tags, then the tags are stuffed into\r
74          * the end of the data buffer.\r
75          */\r
76 \r
77         if(dev->inbandTags){\r
78                 yaffs_PackedTags2TagsPart *pt2tp;\r
79                 pt2tp = (yaffs_PackedTags2TagsPart *)(data + dev->nDataBytesPerChunk);\r
80                 yaffs_PackTags2TagsPart(pt2tp,tags);\r
81                 spare = NULL;\r
82                 spareSize = 0;\r
83         }\r
84         else{\r
85                 yaffs_PackTags2(&pt, tags);\r
86                 spare = &pt;\r
87                 spareSize = sizeof(yaffs_PackedTags2);\r
88         }\r
89         \r
90         yramsim_WritePage(chunkInNAND,\r
91                                           data, dev->totalBytesPerChunk, spare, spareSize);\r
92 \r
93         return YAFFS_OK;\r
94 }\r
95 \r
96 int ynandif_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,\r
97                                        __u8 * data, yaffs_ExtendedTags * tags)\r
98 {\r
99         yaffs_PackedTags2 pt;\r
100         int localData = 0;\r
101         void *spare = NULL;\r
102         unsigned spareSize;\r
103         int eccStatus; //0 = ok, 1 = fixed, -1 = unfixed\r
104 \r
105         unsigned char *bufferIn   = DevBufferIn(dev);\r
106         unsigned char *bufferOut  = DevBufferOut(dev);\r
107         unsigned       bufferSize = DevBufferSize(dev);\r
108 \r
109         T(YAFFS_TRACE_MTD,\r
110           (TSTR\r
111            ("nandmtd2_ReadChunkWithTagsFromNAND chunk %d data %p tags %p"\r
112             TENDSTR), chunkInNAND, data, tags));\r
113             \r
114         if(!tags){\r
115                 spare = NULL;\r
116                 spareSize = 0;\r
117         }else if(dev->inbandTags){\r
118                 \r
119                 if(!data) {\r
120                         localData = 1;\r
121                         data = yaffs_GetTempBuffer(dev,__LINE__);\r
122                 }\r
123                 spare = NULL;\r
124                 spareSize = 0;\r
125         }\r
126         else {\r
127                 spare = &pt;\r
128                 spareSize = sizeof(yaffs_PackedTags2);\r
129         }\r
130 \r
131         yramsim_ReadPage(chunkInNAND,\r
132                                          data,data ? dev->totalBytesPerChunk : 0,\r
133                                          spare,spareSize,\r
134                                          &eccStatus);\r
135 \r
136 \r
137 \r
138         if(dev->inbandTags){\r
139                 if(tags){\r
140                         yaffs_PackedTags2TagsPart * pt2tp;\r
141                         pt2tp = (yaffs_PackedTags2TagsPart *)&data[dev->nDataBytesPerChunk];    \r
142                         yaffs_UnpackTags2TagsPart(tags,pt2tp);\r
143                 }\r
144         }\r
145         else {\r
146                 if (tags){\r
147                         yaffs_UnpackTags2(tags, &pt);\r
148                 }\r
149         }\r
150 \r
151         if(tags && tags->chunkUsed){\r
152                 if(eccStatus == 0)\r
153                         tags->eccResult = YAFFS_ECC_RESULT_NO_ERROR;\r
154                 else if(eccStatus < 0)\r
155                         tags->eccResult = YAFFS_ECC_RESULT_UNFIXED;\r
156                 else\r
157                         tags->eccResult = YAFFS_ECC_RESULT_FIXED;\r
158         }\r
159 \r
160         if(localData)\r
161                 yaffs_ReleaseTempBuffer(dev,data,__LINE__);\r
162         \r
163         return YAFFS_OK;\r
164 }\r
165 \r
166 int ynandif_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockId)\r
167 {\r
168 \r
169         yramsim_MarkBlockBad(blockId);\r
170 \r
171         return YAFFS_OK;\r
172 }\r
173 \r
174 int ynandif_EraseBlockInNAND(struct yaffs_DeviceStruct *dev, int blockId)\r
175 {\r
176 \r
177         yramsim_EraseBlock(blockId);\r
178 \r
179         return YAFFS_OK;\r
180 }\r
181 \r
182 \r
183 static int ynandif_IsBlockOk(struct yaffs_DeviceStruct *dev, int blockId)\r
184 {\r
185         return yramsim_CheckBlockOk(blockId);\r
186 }\r
187 \r
188 int ynandif_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockId, yaffs_BlockState *state, __u32 *sequenceNumber)\r
189 {\r
190         unsigned chunkNo;\r
191         yaffs_ExtendedTags tags;\r
192 \r
193         *sequenceNumber = 0;\r
194         \r
195         chunkNo = blockId * dev->nChunksPerBlock;\r
196         \r
197         if(!ynandif_IsBlockOk(dev,blockId)){\r
198                 *state = YAFFS_BLOCK_STATE_DEAD;\r
199         } \r
200         else \r
201         {\r
202                 ynandif_ReadChunkWithTagsFromNAND(dev,chunkNo,NULL,&tags);\r
203 \r
204                 if(!tags.chunkUsed)\r
205                 {\r
206                         *state = YAFFS_BLOCK_STATE_EMPTY;\r
207                 }\r
208                 else \r
209                 {\r
210                         *state = YAFFS_BLOCK_STATE_NEEDS_SCANNING;\r
211                         *sequenceNumber = tags.sequenceNumber;\r
212                 }\r
213         }\r
214 \r
215         return YAFFS_OK;\r
216 }\r
217 \r
218 \r
219 int ynandif_GetGeometry(yaffs_Device *dev, ynandif_Geometry *geometry)\r
220 {\r
221 \r
222         yramsim_Geometry g;\r
223 \r
224         yramsim_GetGeometry(&g);\r
225         geometry->startBlock = g.startBlock;\r
226         geometry->endBlock = g.endBlock;\r
227         geometry->dataSize = g.dataSize;\r
228         geometry->spareSize = g.spareSize;\r
229         geometry->pagesPerBlock = g.pagesPerBlock;\r
230         geometry->hasECC = g.hasECC;\r
231         geometry->inbandTags = g.inbandTags;\r
232         geometry->useYaffs2 = g.useYaffs2;\r
233 \r
234         return YAFFS_OK;\r
235 \r
236 }\r
237 \r
238 int ynandif_InitialiseNAND(yaffs_Device *dev)\r
239 {\r
240 \r
241         yramsim_Initialise();\r
242 \r
243         return YAFFS_OK;\r
244 }\r