Fix unmounting flag
[yaffs/.git] / yaffs_fileem.c
1 /*
2  * YAFFS: Yet another FFS. A NAND-flash specific file system. 
3  * yaffs_fileem.c  NAND emulation on top of files
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_fileem.c
16
17 #include "yaffs_fileem.h"
18 #include "yaffs_guts.h"
19 #include "yaffsinterface.h"
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <fcntl.h>
27 #include <string.h>
28
29 #define FILE_SIZE_IN_MEG 2
30
31 // #define YAFFS_ERROR_TESTING 
32
33 #define BLOCK_SIZE (32 * 528)
34 #define BLOCKS_PER_MEG ((1024*1024)/(32 * 512))
35 #define FILE_SIZE_IN_BLOCKS (FILE_SIZE_IN_MEG * BLOCKS_PER_MEG)
36 #define FILE_SIZE_IN_BYTES (FILE_SIZE_IN_BLOCKS * BLOCK_SIZE)
37
38
39 static int h;
40 static __u8 ffChunk[528];
41
42 static int eraseDisplayEnabled;
43
44 static int markedBadBlocks[] = { 1, 4, -1};
45
46 static int IsAMarkedBadBlock(int blk)
47 {
48 #if YAFFS_ERROR_TESTING
49         int *m = markedBadBlocks;
50         
51         while(*m >= 0)
52         {
53                 if(*m == blk) return 1;
54                 m++;
55         }
56 #endif
57         return 0;
58 }
59
60
61 static __u8 yaffs_WriteFailCorruption(int chunkInNAND)
62 {
63 #if YAFFS_ERROR_TESTING
64
65         // Whole blocks that fail
66         switch(chunkInNAND/YAFFS_CHUNKS_PER_BLOCK)
67         {
68                 case 50:
69                 case 52:
70                                         return 7;
71         }
72         
73         // Single blocks that fail
74         switch(chunkInNAND)
75         {
76                 case 2000:
77                 case 2003:
78                 case 3000:
79                 case 3001:
80                                         return 3;// ding two bits
81                 case 2001:
82                 case 3003:
83                 case 3004:
84                 case 3005:
85                 case 3006:
86                 case 3007:  return 1;// ding one bit
87                 
88                 
89         }
90 #endif
91         return 0;
92 }
93
94 static void yaffs_ModifyWriteData(int chunkInNAND,__u8 *data)
95 {
96 #if YAFFS_ERROR_TESTING
97         if(data)
98         {
99                 *data ^= yaffs_WriteFailCorruption(chunkInNAND);        
100         }
101 #endif
102 }
103
104 static __u8 yaffs_ReadFailCorruption(int chunkInNAND)
105 {
106         switch(chunkInNAND)
107         {
108 #if YAFFS_ERROR_TESTING
109                 case 500:
110                                         return 3;// ding two bits
111                 case 700:
112                 case 750:
113                                         return 1;// ding one bit
114                 
115 #endif
116                 default: return 0;
117                 
118         }
119 }
120
121 static void yaffs_ModifyReadData(int chunkInNAND,__u8 *data)
122 {
123 #if YAFFS_ERROR_TESTING
124         if(data)
125         {
126                 *data ^= yaffs_ReadFailCorruption(chunkInNAND); 
127         }
128 #endif
129 }
130
131
132
133
134
135 static void  CheckInit(yaffs_Device *dev)
136 {
137         static int initialised = 0;
138
139         int length;
140         int nWritten;
141
142         
143         if(!initialised)
144         {
145                 memset(ffChunk,0xFF,528);
146                 
147 //#ifdef YAFFS_DUMP
148 //              h = open("yaffs-em-file" , O_RDONLY);
149 //#else
150                 h = open("yaffs-em-file" , O_RDWR | O_CREAT, S_IREAD | S_IWRITE);
151 //#endif
152                 if(h < 0)
153                 {
154                         perror("Fatal error opening yaffs emulation file");
155                         exit(1);
156                 }
157                 initialised = 1;
158                 
159                 length = lseek(h,0,SEEK_END);
160                 nWritten = 528;
161                 while(length <  FILE_SIZE_IN_BYTES && nWritten == 528)
162                 {
163                         write(h,ffChunk,528);
164                         length = lseek(h,0,SEEK_END);           
165                 }
166                 if(nWritten != 528)
167                 {
168                         perror("Fatal error expanding yaffs emulation file");
169                         exit(1);
170
171                 }
172                 
173                 close(h);
174                 
175 #ifdef YAFFS_DUMP
176                 h = open("yaffs-em-file" , O_RDONLY);
177 #else
178                 h = open("yaffs-em-file" , O_RDWR | O_CREAT, S_IREAD | S_IWRITE);
179 #endif
180         }
181 }
182
183 int yaffs_FEWriteChunkToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, yaffs_Spare *spare)
184 {
185         __u8 localData[512];
186         
187         int pos;
188         
189         pos = chunkInNAND * 528;
190         
191         CheckInit(dev);
192         
193         
194         if(data)
195         {
196                 memcpy(localData,data,512);
197                 yaffs_ModifyWriteData(chunkInNAND,localData);
198                 lseek(h,pos,SEEK_SET);
199                 write(h,localData,512);
200         }
201         
202         pos += 512;
203         
204         if(spare)
205         {
206                 lseek(h,pos,SEEK_SET);
207                 write(h,spare,16);      
208         }
209
210         return YAFFS_OK;
211 }
212
213
214 int yaffs_FEReadChunkFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_Spare *spare)
215 {
216         int pos;
217
218         pos = chunkInNAND * 528;
219         
220         
221         CheckInit(dev);
222         
223         if(data)
224         {
225                 lseek(h,pos,SEEK_SET);
226                 read(h,data,512);
227                 yaffs_ModifyReadData(chunkInNAND,data);
228         }
229         
230         pos += 512;
231         
232         if(spare)
233         {
234                 lseek(h,pos,SEEK_SET);
235                 read(h,spare,16);       
236         }
237
238         return YAFFS_OK;
239 }
240
241
242 int yaffs_FEEraseBlockInNAND(yaffs_Device *dev,int blockInNAND)
243 {
244         int i;
245         
246         CheckInit(dev);
247         
248         if(eraseDisplayEnabled)
249         {
250                 printf("Erasing block %d\n",blockInNAND);
251         }
252         
253         lseek(h,blockInNAND * BLOCK_SIZE,SEEK_SET);
254         for(i = 0; i < 32; i++)
255         {
256                 write(h,ffChunk,528);
257         }
258         
259         switch(blockInNAND)
260         {
261                 case 10: 
262                 case 15: return YAFFS_FAIL;
263                 
264         }
265         return YAFFS_OK;
266 }
267
268 int yaffs_FEInitialiseNAND(yaffs_Device *dev)
269 {
270         return YAFFS_OK;
271 }