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