applied patch 11-sparse-fix--use-C99-struct-initializer.diff
[yaffs2.git] / yaffs_ramem.c
1 /*
2  * YAFFS: Yet another FFS. A NAND-flash specific file system. 
3  * yaffs_ramem.c  NAND emulation on top of a chunk of RAM
4  *
5  * Copyright (C) 2002 Aleph One Ltd.
6  *   for Toby Churchill Ltd and Brightstar Engineering
7  *
8  * Created by Charles Manning <charles@aleph1.co.uk>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2 as
12  * published by the Free Software Foundation.
13  *
14  */
15  //yaffs_ramem.c
16  // Since this creates the RAM block at start up it is pretty useless for testing the scanner.
17
18 const char *yaffs_ramem_c_version = "$Id: yaffs_ramem.c,v 1.3 2005-07-29 19:57:38 luc Exp $";
19
20 #ifndef __KERNEL__
21 #define CONFIG_YAFFS_RAM_ENABLED
22 #else
23 #include <linux/config.h>
24 #endif
25
26 #ifdef CONFIG_YAFFS_RAM_ENABLED
27
28 #include "yportenv.h"
29
30 #include "yaffs_nandemul.h"
31 #include "yaffs_guts.h"
32 #include "yaffsinterface.h"
33 #include "devextras.h"
34
35
36 #define EM_SIZE_IN_MEG 2
37
38 #define YAFFS_BLOCK_SIZE (32 * 528)
39 #define BLOCKS_PER_MEG ((1024*1024)/(32 * 512))
40 #define FILE_SIZE_IN_BLOCKS (FILE_SIZE_IN_MEG * BLOCKS_PER_MEG)
41 #define FILE_SIZE_IN_BYTES (FILE_SIZE_IN_BLOCKS * YAFFS_BLOCK_SIZE)
42
43
44
45 #define DEFAULT_SIZE_IN_MB 2
46
47 typedef struct 
48 {
49         __u8 data[528]; // Data + spare
50         int count[3];   // The programming count for each area of
51                         // the page (0..255,256..511,512..527
52         int empty;      // is this empty?
53 } nandemul_Page;
54
55 typedef struct
56 {
57         nandemul_Page page[32]; // The pages in the block
58         __u8 damaged;           // Is the block damaged?
59         
60 } nandemul_Block;
61
62
63
64 typedef struct
65 {
66         nandemul_Block **block;
67         int nBlocks;
68 } nandemul_Device;
69
70 static nandemul_Device ned;
71
72 static int sizeInMB = DEFAULT_SIZE_IN_MB;
73
74
75 static void nandemul_yield(int n)
76 {
77 #ifdef __KERNEL__
78         if(n > 0) schedule_timeout(n);
79 #endif
80
81 }
82
83
84 static void nandemul_ReallyEraseBlock(int blockNumber)
85 {
86         int i;
87         
88         nandemul_Block *theBlock = ned.block[blockNumber];
89         
90         for(i = 0; i < 32; i++)
91         {
92                 memset(theBlock->page[i].data,0xff,528);
93                 theBlock->page[i].count[0] = 0;
94                 theBlock->page[i].count[1] = 0;
95                 theBlock->page[i].count[2] = 0;
96                 theBlock->page[i].empty = 1;
97                 nandemul_yield(2);
98         }
99
100 }
101
102
103 int nandemul_CalcNBlocks(void)
104 {
105         switch(sizeInMB)
106         {
107                 case 8:
108                 case 16:
109                 case 32:
110                 case 64:
111                 case 128:
112                 case 256:
113                 case 512:
114                         break;
115                 default:
116                         sizeInMB = DEFAULT_SIZE_IN_MB;
117         }
118         return sizeInMB * 64;
119 }
120
121
122
123 static int  CheckInit(void)
124 {
125         static int initialised = 0;
126         
127         int i;
128         int fail = 0;
129         int nBlocks; 
130         int nAllocated = 0;
131         
132         if(initialised) 
133         {
134                 return YAFFS_OK;
135         }
136         
137         
138         nBlocks = nandemul_CalcNBlocks();
139         
140         ned.block = YMALLOC(sizeof(nandemul_Block *) * nBlocks);
141         
142         if(!ned.block) return 0;
143         
144         for(i=0; i <nBlocks; i++)
145         {
146                 ned.block[i] = NULL;
147         }
148         
149         for(i=0; i <nBlocks && !fail; i++)
150         {
151                 if((ned.block[i] = YMALLOC(sizeof(nandemul_Block))) == 0)
152                 {
153                         fail = 1;
154                 }
155                 else
156                 {
157                         nandemul_ReallyEraseBlock(i);
158                         ned.block[i]->damaged = 0;
159                         nAllocated++;
160                 }
161         }
162         
163         if(fail)
164         {
165                 for(i = 0; i < nAllocated; i++)
166                 {
167                         YFREE(ned.block[i]);
168                 }
169                 YFREE(ned.block);
170                 
171                 T(YAFFS_TRACE_ALWAYS,("Allocation failed, could only allocate %dMB of %dMB requested.\n",
172                    nAllocated/64,sizeInMB));
173                 return 0;
174         }
175         
176         ned.nBlocks = nBlocks;
177         
178         initialised = 1;
179         
180         return 1;
181 }
182
183 int nandemul_WriteChunkToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_Spare *spare)
184 {
185         int blk;
186         int pg;
187         int i;
188         
189         __u8 *x;
190         
191         __u8 *spareAsBytes = (__u8 *)spare;
192
193         
194         CheckInit();
195         
196         blk = chunkInNAND/32;
197         pg = chunkInNAND%32;
198         
199         
200         if(data)
201         {
202                 x = ned.block[blk]->page[pg].data;
203                 
204                 for(i = 0; i < 512; i++)
205                 {
206                         x[i] &=data[i];
207                 }
208                 
209                 ned.block[blk]->page[pg].count[0]++;
210                 ned.block[blk]->page[pg].count[1]++;
211                 ned.block[blk]->page[pg].empty = 0;
212         }
213         
214         
215         if(spare)
216         {
217                 x = &ned.block[blk]->page[pg].data[512];
218                         
219                 for(i = 0; i < 16; i++)
220                 {
221                         x[i] &=spareAsBytes[i];
222                 }
223                 ned.block[blk]->page[pg].count[2]++;
224         }
225         
226         if(spare || data)
227         {
228                 nandemul_yield(1);
229         }
230
231         return YAFFS_OK;
232 }
233
234
235 int nandemul_ReadChunkFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_Spare *spare)
236 {
237         int blk;
238         int pg;
239
240         
241         CheckInit();
242         
243         blk = chunkInNAND/32;
244         pg = chunkInNAND%32;
245         
246         
247         if(data)
248         {
249                 memcpy(data,ned.block[blk]->page[pg].data,512);
250         }
251         
252         
253         if(spare)
254         {
255                 memcpy(spare,&ned.block[blk]->page[pg].data[512],16);
256         }
257
258         return YAFFS_OK;
259 }
260
261
262 int nandemul_CheckChunkErased(yaffs_Device *dev,int chunkInNAND)
263 {
264         int blk;
265         int pg;
266         int i;
267
268         
269         CheckInit();
270         
271         blk = chunkInNAND/32;
272         pg = chunkInNAND%32;
273         
274         
275         for(i = 0; i < 528; i++)
276         {
277                 if(ned.block[blk]->page[pg].data[i] != 0xFF)
278                 {
279                         return YAFFS_FAIL;
280                 }
281         }
282
283         return YAFFS_OK;
284
285 }
286
287 int nandemul_EraseBlockInNAND(yaffs_Device *dev, int blockNumber)
288 {
289         
290         CheckInit();
291         
292         if(blockNumber < 0 || blockNumber >= ned.nBlocks)
293         {
294                 T(YAFFS_TRACE_ALWAYS,("Attempt to erase non-existant block %d\n",blockNumber));
295         }
296         else if(ned.block[blockNumber]->damaged)
297         {
298                 T(YAFFS_TRACE_ALWAYS,("Attempt to erase damaged block %d\n",blockNumber));
299         }
300         else
301         {
302                 nandemul_ReallyEraseBlock(blockNumber);
303         }
304         
305         return YAFFS_OK;
306 }
307
308 int nandemul_InitialiseNAND(yaffs_Device *dev)
309 {
310         return YAFFS_OK;
311 }
312
313 #endif //YAFFS_RAM_ENABLED
314