Merge branch 'master' of ssh://www.aleph1.co.uk/home/aleph1/git/yaffs2
[yaffs2.git] / direct / yaffs_flashif.c
1 /*
2  * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
3  *
4  * Copyright (C) 2002-2010 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 const char *yaffs_flashif_c_version = "$Id: yaffs_flashif.c,v 1.3 2007-02-14 01:09:06 wookey Exp $";
16
17
18 #include "yportenv.h"
19
20 #include "yaffs_flashif.h"
21 #include "yaffs_guts.h"
22
23
24 #define SIZE_IN_MB 16
25
26 #define BLOCK_SIZE (32 * 528)
27 #define BLOCKS_PER_MEG ((1024*1024)/(32 * 512))
28
29
30
31 typedef struct 
32 {
33         u8 data[528]; // Data + spare
34 } yflash_Page;
35
36 typedef struct
37 {
38         yflash_Page page[32]; // The pages in the block
39         
40 } yflash_Block;
41
42
43
44 typedef struct
45 {
46         yflash_Block **block;
47         int nBlocks;
48 } yflash_Device;
49
50 static yflash_Device ramdisk;
51
52 static int  CheckInit(struct yaffs_dev *dev)
53 {
54         static int initialised = 0;
55         
56         int i;
57         int fail = 0;
58         int nAllocated = 0;
59         
60         if(initialised) 
61         {
62                 return YAFFS_OK;
63         }
64
65         initialised = 1;
66         
67         
68         ramdisk.nBlocks = (SIZE_IN_MB * 1024 * 1024)/(16 * 1024);
69         
70         ramdisk.block = YMALLOC(sizeof(yflash_Block *) * ramdisk.nBlocks);
71         
72         if(!ramdisk.block) return 0;
73         
74         for(i=0; i <ramdisk.nBlocks; i++)
75         {
76                 ramdisk.block[i] = NULL;
77         }
78         
79         for(i=0; i <ramdisk.nBlocks && !fail; i++)
80         {
81                 if((ramdisk.block[i] = YMALLOC(sizeof(yflash_Block))) == 0)
82                 {
83                         fail = 1;
84                 }
85                 else
86                 {
87                         yflash_EraseBlockInNAND(dev,i);
88                         nAllocated++;
89                 }
90         }
91         
92         if(fail)
93         {
94                 for(i = 0; i < nAllocated; i++)
95                 {
96                         YFREE(ramdisk.block[i]);
97                 }
98                 YFREE(ramdisk.block);
99                 
100                 T(YAFFS_TRACE_ALWAYS,("Allocation failed, could only allocate %dMB of %dMB requested.\n",
101                    nAllocated/64,ramdisk.nBlocks * YAFFS_BYTES_PER_BLOCK));
102                 return 0;
103         }
104         
105         
106         
107         return 1;
108 }
109
110 int yflash_WriteChunkWithTagsToNAND(struct yaffs_dev *dev,int nand_chunk,const u8 *data, struct yaffs_ext_tags *tags)
111 {
112         int blk;
113         int pg;
114         
115
116         CheckInit(dev);
117         
118         blk = nand_chunk/32;
119         pg = nand_chunk%32;
120         
121         
122         if(data)
123         {
124                 memcpy(ramdisk.block[blk]->page[pg].data,data,512);
125         }
126         
127         
128         if(tags)
129         {
130                 yaffs_PackedTags pt;
131                 yaffs_PackTags(&pt,tags);
132                 memcpy(&ramdisk.block[blk]->page[pg].data[512],&pt,sizeof(pt));
133         }
134
135         return YAFFS_OK;        
136
137 }
138
139
140 int yflash_ReadChunkWithTagsFromNAND(struct yaffs_dev *dev,int nand_chunk, u8 *data, struct yaffs_tags *tags)
141 {
142         int blk;
143         int pg;
144
145         
146         CheckInit(dev);
147         
148         blk = nand_chunk/32;
149         pg = nand_chunk%32;
150         
151         
152         if(data)
153         {
154                 memcpy(data,ramdisk.block[blk]->page[pg].data,512);
155         }
156         
157         
158         if(tags)
159         {
160                 yaffs_PackedTags pt;
161                 memcpy(&pt,&ramdisk.block[blk]->page[pg].data[512],sizeof(yaffs_PackedTags));
162                 yaffs_unpack_tags(tags,&pt);
163         }
164
165         return YAFFS_OK;
166 }
167
168
169 int yflash_CheckChunkErased(struct yaffs_dev *dev,int nand_chunk)
170 {
171         int blk;
172         int pg;
173         int i;
174
175         
176         CheckInit(dev);
177         
178         blk = nand_chunk/32;
179         pg = nand_chunk%32;
180         
181         
182         for(i = 0; i < 528; i++)
183         {
184                 if(ramdisk.block[blk]->page[pg].data[i] != 0xFF)
185                 {
186                         return YAFFS_FAIL;
187                 }
188         }
189
190         return YAFFS_OK;
191
192 }
193
194 int yflash_EraseBlockInNAND(struct yaffs_dev *dev, int blockNumber)
195 {
196         
197         CheckInit(dev);
198         
199         if(blockNumber < 0 || blockNumber >= ramdisk.nBlocks)
200         {
201                 T(YAFFS_TRACE_ALWAYS,("Attempt to erase non-existant block %d\n",blockNumber));
202                 return YAFFS_FAIL;
203         }
204         else
205         {
206                 memset(ramdisk.block[blockNumber],0xFF,sizeof(yflash_Block));
207                 return YAFFS_OK;
208         }
209         
210 }
211
212 int yflash_MarkNANDBlockBad(struct yaffs_dev *dev, int block_no)
213 {
214         return YAFFS_OK;
215         
216 }
217 int yflash_QueryNANDBlock(struct yaffs_dev *dev, int block_no, enum yaffs_block_state *state, int *seq_number)
218 {
219         *state = YAFFS_BLOCK_STATE_EMPTY;
220         *seq_number = 0;
221 }
222
223
224 int yflash_InitialiseNAND(struct yaffs_dev *dev)
225 {
226         return YAFFS_OK;
227 }
228