*** empty log message ***
[yaffs2.git] / direct / yaffs_fileem2k.c
1 /*
2  * YAFFS: Yet another FFS. A NAND-flash specific file system. 
3  * yaffs_ramdisk.c: yaffs ram disk component
4  *
5  * Copyright (C) 2002 Aleph One Ltd.
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 const char *yaffs_flashif_c_version = "$Id: yaffs_fileem2k.c,v 1.1 2004-11-03 08:29:28 charles Exp $";
19
20
21 #include "yportenv.h"
22
23 #include "yaffs_flashif.h"
24 #include "yaffs_guts.h"
25 #include "devextras.h"
26
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <fcntl.h>
30 #include <unistd.h> 
31
32 #include "yaffs_fileem2k.h"
33 #include "yaffs_packedtags.h"
34
35
36
37 typedef struct 
38 {
39         __u8 data[PAGE_SIZE]; // Data + spare
40 } yflash_Page;
41
42 typedef struct
43 {
44         yflash_Page page[PAGES_PER_BLOCK]; // The pages in the block
45         
46 } yflash_Block;
47
48
49
50 typedef struct
51 {
52         int handle;
53         int nBlocks;
54 } yflash_Device;
55
56 static yflash_Device filedisk;
57
58 static int  CheckInit(yaffs_Device *dev)
59 {
60         static int initialised = 0;
61         
62         int i;
63
64         
65         int fSize;
66         int written;
67         
68         yflash_Page p;
69         
70         if(initialised) 
71         {
72                 return YAFFS_OK;
73         }
74
75         initialised = 1;
76         
77         
78         filedisk.nBlocks = SIZE_IN_MB * BLOCKS_PER_MB;
79         
80         filedisk.handle = open("yaffsemfile2k", O_RDWR | O_CREAT, S_IREAD | S_IWRITE);
81         
82         if(filedisk.handle < 0)
83         {
84                 perror("Failed to open yaffs emulation file");
85                 return YAFFS_FAIL;
86         }
87         
88         
89         fSize = lseek(filedisk.handle,0,SEEK_END);
90         
91         if(fSize < filedisk.nBlocks * BLOCK_SIZE)
92         {
93                 printf("Creating yaffs emulation file\n");
94                 
95                 lseek(filedisk.handle,0,SEEK_SET);
96                 
97                 memset(&p,0xff,sizeof(yflash_Page));
98                 
99                 for(i = 0; i <  filedisk.nBlocks * BLOCK_SIZE; i+= PAGE_SIZE)
100                 {
101                         written = write(filedisk.handle,&p,sizeof(yflash_Page));
102                         
103                         if(written != sizeof(yflash_Page))
104                         {
105                                 printf("Write failed\n");
106                                 return YAFFS_FAIL;
107                         }
108                 }               
109         }
110         
111         return 1;
112 }
113
114 int yflash_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, yaffs_ExtendedTags *tags)
115 {
116         int written;
117         int pos;
118
119         CheckInit(dev);
120         
121         
122         
123         if(data)
124         {
125                 pos = chunkInNAND * PAGE_SIZE;
126                 lseek(filedisk.handle,pos,SEEK_SET);
127                 written = write(filedisk.handle,data,dev->nBytesPerChunk);
128                 
129                 if(written != dev->nBytesPerChunk) return YAFFS_FAIL;
130         }
131         
132         if(tags)
133         {
134                 pos = chunkInNAND * PAGE_SIZE + PAGE_DATA_SIZE;
135                 lseek(filedisk.handle,pos,SEEK_SET);
136                 if(dev->isYaffs2)
137                 {
138                         
139                         written = write(filedisk.handle,tags,sizeof(yaffs_ExtendedTags));
140                         if(written != sizeof(yaffs_ExtendedTags)) return YAFFS_FAIL;
141                 }
142                 else
143                 {
144                         yaffs_PackedTags pt;
145                         yaffs_PackTags(&pt,tags);
146
147                         written = write(filedisk.handle,&pt,sizeof(pt));
148                         if(written != sizeof(pt)) return YAFFS_FAIL;
149                 }
150         }
151         
152
153         return YAFFS_OK;        
154
155 }
156
157 int yflash_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo)
158 {
159         int written;
160         
161         yaffs_PackedTags pt;
162
163         CheckInit(dev);
164         
165         memset(&pt,0,sizeof(pt));
166         lseek(filedisk.handle,(blockNo * dev->nChunksPerBlock) * PAGE_SIZE + PAGE_DATA_SIZE,SEEK_SET);
167         written = write(filedisk.handle,&pt,sizeof(pt));
168                 
169         if(written != sizeof(pt)) return YAFFS_FAIL;
170         
171         
172         return YAFFS_OK;
173         
174 }
175
176 int yaffs_CheckAllFF(const __u8 *ptr, int n)
177 {
178         while(n)
179         {
180                 n--;
181                 if(*ptr!=0xFF) return 0;
182                 ptr++;
183         }
184         return 1;
185 }
186
187
188 int yflash_ReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_ExtendedTags *tags)
189 {
190         int nread;
191         int pos;
192
193         CheckInit(dev);
194         
195         
196         
197         if(data)
198         {
199                 pos = chunkInNAND * PAGE_SIZE;
200                 lseek(filedisk.handle,pos,SEEK_SET);
201                 nread = read(filedisk.handle,data,dev->nBytesPerChunk);
202                 
203                 if(nread != dev->nBytesPerChunk) return YAFFS_FAIL;
204         }
205         
206         if(tags)
207         {
208                 pos = chunkInNAND * PAGE_SIZE + PAGE_DATA_SIZE;
209                 lseek(filedisk.handle,pos,SEEK_SET);
210                 if(dev->isYaffs2)
211                 {
212                         nread= read(filedisk.handle,tags,sizeof(yaffs_ExtendedTags));
213                         if(nread != sizeof(yaffs_ExtendedTags)) return YAFFS_FAIL;
214                         if(yaffs_CheckAllFF((__u8 *)tags,sizeof(yaffs_ExtendedTags)))
215                         {
216                                 yaffs_InitialiseTags(tags);
217                         }
218                         else
219                         {
220                                 tags->chunkUsed = 1;
221                         }
222                 }
223                 else
224                 {
225                         yaffs_PackedTags pt;
226                         nread= read(filedisk.handle,&pt,sizeof(pt));
227                         yaffs_UnpackTags(tags,&pt);
228                         if(nread != sizeof(pt)) return YAFFS_FAIL;
229                 }
230         }
231         
232
233         return YAFFS_OK;        
234
235 }
236
237
238 int yflash_EraseBlockInNAND(yaffs_Device *dev, int blockNumber)
239 {
240
241         int i;
242                 
243         CheckInit(dev);
244         
245         if(blockNumber < 0 || blockNumber >= filedisk.nBlocks)
246         {
247                 T(YAFFS_TRACE_ALWAYS,("Attempt to erase non-existant block %d\n",blockNumber));
248                 return YAFFS_FAIL;
249         }
250         else
251         {
252         
253                 __u8 pg[PAGE_SIZE];
254                 int syz = PAGE_SIZE;
255                 int pos;
256                 
257                 memset(pg,0xff,syz);
258                 
259                 pos = lseek(filedisk.handle, blockNumber * dev->nChunksPerBlock * PAGE_SIZE, SEEK_SET);
260                 
261                 for(i = 0; i < dev->nChunksPerBlock; i++)
262                 {
263                         write(filedisk.handle,pg,PAGE_SIZE);
264                 }
265                 pos = lseek(filedisk.handle, 0,SEEK_CUR);
266                 
267                 return YAFFS_OK;
268         }
269         
270 }
271
272 int yflash_InitialiseNAND(yaffs_Device *dev)
273 {
274         CheckInit(dev);
275         
276         return YAFFS_OK;
277 }
278
279
280
281
282 int yflash_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, yaffs_BlockState *state, int *sequenceNumber)
283 {
284         yaffs_ExtendedTags tags;
285         int chunkNo;
286
287         *sequenceNumber = 0;
288         
289         chunkNo = blockNo * dev->nChunksPerBlock;
290         
291         yflash_ReadChunkWithTagsFromNAND(dev,chunkNo,NULL,&tags);
292         if(tags.blockBad)
293         {
294                 *state = YAFFS_BLOCK_STATE_DEAD;
295         }
296         else if(!tags.chunkUsed)
297         {
298                 *state = YAFFS_BLOCK_STATE_EMPTY;
299         }
300         else if(tags.chunkUsed)
301         {
302                 *state = YAFFS_BLOCK_STATE_NEEDS_SCANNING;
303                 *sequenceNumber = tags.sequenceNumber;
304         }
305         return YAFFS_OK;
306 }
307