Compilation clean up
[yaffs2.git] / direct / test-framework / yaffs_fileem2k.c
1 /*
2  * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
3  *
4  * Copyright (C) 2002-2011 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 /*
15  * This provides a YAFFS nand emulation on a file for emulating 2kB pages.
16  * This is only intended as test code to test persistence etc.
17  */
18
19 #include "yportenv.h"
20 #include "yaffs_trace.h"
21
22 #include "yaffs_flashif2.h"
23 #include "yaffs_guts.h"
24 #include "yaffs_fileem2k.h"
25 #include "yaffs_packedtags2.h"
26
27
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <fcntl.h>
31 #include <unistd.h>
32
33 #if 1
34
35 #define SIZE_IN_MB 32
36 /* #define SIZE_IN_MB 128 */
37
38 #define PAGE_DATA_SIZE (2048)
39 #define PAGE_SPARE_SIZE  (64)
40 #define PAGE_SIZE  (PAGE_DATA_SIZE + PAGE_SPARE_SIZE)
41 #define PAGES_PER_BLOCK (64)
42 #define BLOCK_DATA_SIZE (PAGE_DATA_SIZE * PAGES_PER_BLOCK)
43 #define BLOCK_SIZE (PAGES_PER_BLOCK * (PAGE_SIZE))
44 #define BLOCKS_PER_MB ((1024*1024)/BLOCK_DATA_SIZE)
45 #define SIZE_IN_BLOCKS (BLOCKS_PER_MB * SIZE_IN_MB)
46
47 #else
48
49 #define SIZE_IN_MB 128
50 #define PAGE_DATA_SIZE (512)
51 #define SPARE_SIZE  (16)
52 #define PAGE_SIZE  (PAGE_DATA_SIZE + SPARE_SIZE)
53 #define PAGES_PER_BLOCK (32)
54 #define BLOCK_DATA_SIZE (PAGE_SIZE * PAGES_PER_BLOCK)
55 #define BLOCK_SIZE (PAGES_PER_BLOCK * (PAGE_SIZE))
56 #define BLOCKS_PER_MB ((1024*1024)/BLOCK_DATA_SIZE)
57 #define SIZE_IN_BLOCKS (BLOCKS_PER_MB * SIZE_IN_MB)
58
59 #endif
60
61 #define REPORT_ERROR 0
62
63 typedef struct
64 {
65         u8 data[PAGE_SIZE]; // Data + spare
66 } yflash_Page;
67
68 typedef struct
69 {
70         yflash_Page page[PAGES_PER_BLOCK]; // The pages in the block
71
72 } yflash_Block;
73
74
75
76 #define MAX_HANDLES 20
77 #define BLOCKS_PER_HANDLE (32*8)
78
79 typedef struct
80 {
81         int handle[MAX_HANDLES];
82         int nBlocks;
83 } yflash_Device;
84
85 static yflash_Device filedisk;
86
87 int yaffs_test_partial_write = 0;
88
89 extern int random_seed;
90 extern int simulate_power_failure;
91 static int remaining_ops;
92 static int nops_so_far;
93
94 int ops_multiplier;
95
96 static void yflash2_MaybePowerFail(unsigned int nand_chunk, int failPoint)
97 {
98
99    nops_so_far++;
100
101
102    remaining_ops--;
103    if(simulate_power_failure &&
104       remaining_ops < 1){
105        printf("Simulated power failure after %d operations\n",nops_so_far);
106        printf("  power failed on nand_chunk %d, at fail point %d\n",
107                         nand_chunk, failPoint);
108         exit(0);
109   }
110 }
111
112 static char *NToName(char *buf,int n)
113 {
114         sprintf(buf,"emfile-2k-%d",n);
115         return buf;
116 }
117
118 static char dummyBuffer[BLOCK_SIZE];
119
120 static int GetBlockFileHandle(int n)
121 {
122         int h;
123         int requiredSize;
124
125         char name[40];
126         NToName(name,n);
127         int fSize;
128         int i;
129
130         h =  open(name, O_RDWR | O_CREAT, S_IREAD | S_IWRITE);
131         if(h >= 0){
132                 fSize = lseek(h,0,SEEK_END);
133                 requiredSize = BLOCKS_PER_HANDLE * BLOCK_SIZE;
134                 if(fSize < requiredSize){
135                    for(i = 0; i < BLOCKS_PER_HANDLE; i++)
136                         if(write(h,dummyBuffer,BLOCK_SIZE) != BLOCK_SIZE)
137                                 return -1;
138
139                 }
140         }
141
142         return h;
143
144 }
145
146 static int  CheckInit(void)
147 {
148         static int initialised = 0;
149         int i;
150
151         int blk;
152
153
154         if(initialised)
155         {
156                 return YAFFS_OK;
157         }
158
159         initialised = 1;
160
161
162         srand(random_seed);
163         remaining_ops = (rand() % 1000) * 5;
164         memset(dummyBuffer,0xff,sizeof(dummyBuffer));
165
166
167
168         filedisk.nBlocks = SIZE_IN_MB * BLOCKS_PER_MB;
169
170         for(i = 0; i <  MAX_HANDLES; i++)
171                 filedisk.handle[i] = -1;
172
173         for(i = 0,blk = 0; blk < filedisk.nBlocks; blk+=BLOCKS_PER_HANDLE,i++)
174                 filedisk.handle[i] = GetBlockFileHandle(i);
175
176
177         return 1;
178 }
179
180
181 int yflash2_GetNumberOfBlocks(void)
182 {
183         CheckInit();
184
185         return filedisk.nBlocks;
186 }
187
188
189 int yaffs_check_all_ff(const u8 *ptr, int n)
190 {
191         while(n)
192         {
193                 n--;
194                 if(*ptr!=0xFF) return 0;
195                 ptr++;
196         }
197         return 1;
198 }
199
200
201 static int yflash2_WriteChunk(struct yaffs_dev *dev, int nand_chunk,
202                                    const u8 *data, int data_len,
203                                    const u8 *oob, int oob_len)
204 {
205         int retval = YAFFS_OK;
206         int pos;
207         int h;
208         int nwritten;
209
210         (void) dev;
211
212         if (data && data_len) {
213                 pos = (nand_chunk % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE;
214                 h = filedisk.handle[(nand_chunk / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))];
215                 lseek(h,pos,SEEK_SET);
216                 nwritten = write(h,data,data_len);
217                 if(nwritten != data_len)
218                         retval = YAFFS_FAIL;
219         }
220
221         if (oob && oob_len) {
222                 pos = (nand_chunk % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE + PAGE_DATA_SIZE;
223                 h = filedisk.handle[(nand_chunk / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))];
224                 lseek(h,pos,SEEK_SET);
225                 nwritten = write(h,oob,oob_len);
226                 if(nwritten != oob_len)
227                         retval = YAFFS_FAIL;
228         }
229
230         yflash2_MaybePowerFail(nand_chunk,3);
231
232         return retval;
233 }
234
235 static int yflash2_ReadChunk(struct yaffs_dev *dev, int nand_chunk,
236                                    u8 *data, int data_len,
237                                    u8 *oob, int oob_len,
238                                    enum yaffs_ecc_result *ecc_result)
239 {
240         int retval = YAFFS_OK;
241         int pos;
242         int h;
243         int nread;
244
245         (void) dev;
246
247         if (data && data_len) {
248                 pos = (nand_chunk % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE;
249                 h = filedisk.handle[(nand_chunk / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))];
250                 lseek(h,pos,SEEK_SET);
251                 nread = read(h,data,data_len);
252                 if(nread != data_len)
253                         retval = YAFFS_FAIL;
254         }
255
256         if (oob && oob_len) {
257                 pos = (nand_chunk % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE + PAGE_DATA_SIZE;
258                 h = filedisk.handle[(nand_chunk / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))];
259                 lseek(h,pos,SEEK_SET);
260                 nread = read(h,oob,oob_len);
261                 if(nread != oob_len)
262                         retval = YAFFS_FAIL;
263         }
264
265         if (ecc_result)
266                 *ecc_result = YAFFS_ECC_RESULT_NO_ERROR;
267
268         return retval;
269 }
270
271 static int yflash2_EraseBlock(struct yaffs_dev *dev, int block_no)
272 {
273         u32 i;
274         int h;
275
276         CheckInit();
277
278         if(block_no < 0 || block_no >= filedisk.nBlocks)
279         {
280                 yaffs_trace(YAFFS_TRACE_ALWAYS,"Attempt to erase non-existant block %d",block_no);
281                 return YAFFS_FAIL;
282         }
283         else
284         {
285
286                 u8 pg[PAGE_SIZE];
287                 int syz = PAGE_SIZE;
288
289                 memset(pg,0xff,syz);
290
291
292                 h = filedisk.handle[(block_no / ( BLOCKS_PER_HANDLE))];
293                 lseek(h,((block_no % BLOCKS_PER_HANDLE) * dev->param.chunks_per_block) * PAGE_SIZE,SEEK_SET);
294                 for(i = 0; i < dev->param.chunks_per_block; i++)
295                 {
296                         write(h,pg,PAGE_SIZE);
297                 }
298
299                 return YAFFS_OK;
300         }
301 }
302
303 static int yflash2_MarkBad(struct yaffs_dev *dev, int block_no)
304 {
305         int written;
306         int h;
307
308         struct yaffs_packed_tags2 pt;
309
310         CheckInit();
311
312         memset(&pt,0,sizeof(pt));
313         h = filedisk.handle[(block_no / ( BLOCKS_PER_HANDLE))];
314         lseek(h,((block_no % BLOCKS_PER_HANDLE) * dev->param.chunks_per_block) * PAGE_SIZE + PAGE_DATA_SIZE,SEEK_SET);
315         written = write(h,&pt,sizeof(pt));
316
317         if(written != sizeof(pt))
318                 return YAFFS_FAIL;
319
320         return YAFFS_OK;
321
322 }
323
324 static int yflash2_CheckBad(struct yaffs_dev *dev, int block_no)
325 {
326         (void) dev;
327         (void) block_no;
328
329         return YAFFS_OK;
330 }
331
332 static int yflash2_Initialise(struct yaffs_dev *dev)
333 {
334         (void) dev;
335
336         CheckInit();
337
338         return YAFFS_OK;
339 }
340
341 struct yaffs_dev *yflash2_install_drv(const char *name)
342 {
343         struct yaffs_dev *dev = NULL;
344         struct yaffs_param *param;
345         struct yaffs_driver *drv;
346
347         dev = malloc(sizeof(*dev));
348
349         if(!dev)
350                 return NULL;
351
352         memset(dev, 0, sizeof(*dev));
353
354         dev->param.name = strdup(name);
355
356         if(!dev->param.name) {
357                 free(dev);
358                 return NULL;
359         }
360
361         drv = &dev->drv;
362
363         drv->drv_write_chunk_fn = yflash2_WriteChunk;
364         drv->drv_read_chunk_fn = yflash2_ReadChunk;
365         drv->drv_erase_fn = yflash2_EraseBlock;
366         drv->drv_mark_bad_fn = yflash2_MarkBad;
367         drv->drv_check_bad_fn = yflash2_CheckBad;
368         drv->drv_initialise_fn = yflash2_Initialise;
369
370         param = &dev->param;
371
372         param->total_bytes_per_chunk = 2048;
373         param->chunks_per_block = 64;
374         param->start_block = 0;
375         param->end_block = yflash2_GetNumberOfBlocks()-1;
376         param->is_yaffs2 = 1;
377         param->use_nand_ecc=1;
378
379         param->n_reserved_blocks = 5;
380         param->wide_tnodes_disabled=0;
381         param->refresh_period = 1000;
382         param->n_caches = 10; // Use caches
383
384         param->enable_xattr = 1;
385
386         /* dev->driver_context is not used by this simulator */
387
388         yaffs_add_device(dev);
389
390         return dev;
391 }