b6c83f206e9dfd3b1dcd2c8695e0596a6029730b
[yaffs2.git] / rtems / rtems-y-test / common / yaffs-rtems-flashsim.c
1 /*
2  * Modified verion of yramsim.c.
3  */
4 #include "yaffs-rtems-flashsim.h"
5
6 #include <string.h>
7 #include "../../yaffs_guts.h"
8
9
10
11 #define N_RAM_SIM_DEVS  1
12
13 #define DATA_SIZE       2048
14 #define SPARE_SIZE      64
15 #define PAGE_SIZE       (DATA_SIZE + SPARE_SIZE)
16 #define PAGES_PER_BLOCK 64
17
18
19 #if 0
20 #define dout printf
21 #else
22 #define dout(...) do { } while(0)
23 #endif
24
25 typedef struct {
26         unsigned char page[PAGES_PER_BLOCK][PAGE_SIZE];
27         unsigned blockOk;
28 } Block;
29
30 typedef struct {
31         Block **blockList;
32         int nBlocks;
33 } SimData;
34
35
36 SimData *simDevs[N_RAM_SIM_DEVS];
37
38 static SimData *DevToSim(struct yaffs_dev *dev)
39 {
40         return (SimData*)(dev->driver_context);
41 }
42
43
44 static void CheckInitialised(void)
45 {
46
47 }
48
49 static int yramsim_erase_internal(SimData *sim, unsigned blockId,int force)
50 {
51         if(blockId < 0 || blockId >= sim->nBlocks){
52                 return 0;
53         }
54
55         if(!sim->blockList[blockId]){
56                 return 0;
57         }
58
59         if(!force && !sim->blockList[blockId]->blockOk){
60                 return 0;
61         }
62
63         memset(sim->blockList[blockId],0xff,sizeof(Block));
64         sim->blockList[blockId]->blockOk = 1;
65
66         return 1;
67 }
68
69
70
71
72 static int yramsim_initialise(struct yaffs_dev *dev)
73 {
74         SimData *sim = DevToSim(dev);
75         Block **blockList = sim->blockList;
76         return blockList != NULL;
77 }
78
79
80 static int yramsim_deinitialise(struct yaffs_dev *dev)
81 {
82         return 1;
83 }
84
85 static int yramsim_rd_chunk (struct yaffs_dev *dev, int pageId,
86                                           u8 *data, int dataLength,
87                                           u8 *spare, int spareLength,
88                                           enum yaffs_ecc_result *ecc_result)
89 {
90         SimData *sim = DevToSim(dev);
91         Block **blockList = sim->blockList;
92
93         unsigned blockId = pageId / PAGES_PER_BLOCK;
94         unsigned pageOffset = pageId % PAGES_PER_BLOCK;
95         unsigned char * d;
96         unsigned char *s;
97
98         if(blockId >= sim->nBlocks ||
99            pageOffset >= PAGES_PER_BLOCK ||
100            dataLength >DATA_SIZE ||
101            spareLength > SPARE_SIZE ||
102            !blockList[blockId]->blockOk){
103                    return YAFFS_FAIL;
104         }
105
106         d = blockList[blockId]->page[pageOffset];
107         s = d + DATA_SIZE;
108
109         if(data)
110                 memcpy(data,d,dataLength);
111
112         if(spare)
113                 memcpy(spare,s,spareLength);
114
115         if (ecc_result)
116                 *ecc_result  = YAFFS_ECC_RESULT_NO_ERROR;
117
118         return YAFFS_OK;
119 }
120
121 static int yramsim_wr_chunk (struct yaffs_dev *dev, int pageId,
122                                            const u8 *data, int dataLength,
123                                            const u8 *spare, int spareLength)
124 {
125         SimData *sim = DevToSim(dev);
126         Block **blockList = sim->blockList;
127
128         unsigned blockId = pageId / PAGES_PER_BLOCK;
129         unsigned pageOffset = pageId % PAGES_PER_BLOCK;
130         unsigned char * d;
131         unsigned char *s;
132
133         dout("wr_chunk\n");
134
135         if(blockId >= sim->nBlocks ||
136            pageOffset >= PAGES_PER_BLOCK ||
137            dataLength >DATA_SIZE ||
138            spareLength > SPARE_SIZE ||
139            !blockList[blockId]->blockOk){
140                    return YAFFS_FAIL;
141         }
142
143         d = blockList[blockId]->page[pageOffset];
144         s = d + DATA_SIZE;
145
146         if(data)
147                 memcpy(d,data,dataLength);
148
149         if(spare)
150                 memcpy(s,spare,spareLength);
151
152         return YAFFS_OK;
153 }
154
155
156 static int yramsim_erase(struct yaffs_dev *dev, int blockId)
157 {
158         SimData *sim = DevToSim(dev);
159
160         CheckInitialised();
161         return yramsim_erase_internal(sim,blockId,0);
162 }
163
164 static int yramsim_check_block_bad(struct yaffs_dev *dev, int blockId)
165 {
166         SimData *sim = DevToSim(dev);
167         Block **blockList = sim->blockList;
168         if(blockId >= sim->nBlocks){
169                 return YAFFS_FAIL;
170         }
171
172         return blockList[blockId]->blockOk ? YAFFS_OK : YAFFS_FAIL;
173 }
174
175 static int yramsim_mark_block_bad(struct yaffs_dev *dev, int blockId)
176 {
177         SimData *sim = DevToSim(dev);
178         Block **blockList = sim->blockList;
179         if(blockId >= sim->nBlocks){
180                 return YAFFS_FAIL;
181         }
182
183         blockList[blockId]->blockOk = 0;
184
185         return YAFFS_OK;
186 }
187
188
189 static SimData *yramsim_alloc_sim_data(u32 devId, u32 nBlocks)
190 {
191         int ok = 1;
192
193         Block **blockList;
194         SimData *sim;
195         Block *b;
196         u32 i;
197
198         if(devId >= N_RAM_SIM_DEVS)
199                 return NULL;
200
201         sim = simDevs[devId];
202
203         if(sim)
204                 return sim;
205
206         sim = malloc(sizeof (SimData));
207         if(!sim)
208                 return NULL;
209
210         simDevs[devId] = sim;
211
212         blockList = malloc(nBlocks * sizeof(Block *));
213
214         sim->blockList = blockList;
215         sim->nBlocks = nBlocks;
216         if(!blockList){
217                 free(sim);
218                 return NULL;
219         }
220
221         for(i = 0; i < nBlocks; i++)
222                 blockList[i] = NULL;
223
224         for(i = 0; i < nBlocks && ok; i++){
225                 b=  malloc(sizeof(Block));
226                 if(b){
227                         blockList[i] = b;
228                         yramsim_erase_internal(sim,i,1);
229                 }
230                 else
231                         ok = 0;
232         }
233
234         if(!ok){
235                 for(i = 0; i < nBlocks; i++)
236                         if(blockList[i]){
237                                 free(blockList[i]);
238                                 blockList[i] = NULL;
239                         }
240                 free(blockList);
241                 blockList = NULL;
242                 free(sim);
243                 sim = NULL;
244         }
245
246         return sim;
247 }
248
249
250 struct yaffs_dev *yramsim_CreateRamSim(const YCHAR *name,
251                                 u32 devId, u32 nBlocks,
252                                 u32 start_block, u32 end_block)
253 {
254         SimData *sim;
255         struct yaffs_dev *dev;
256         struct yaffs_param *p;
257         struct yaffs_driver *d;
258
259         sim = yramsim_alloc_sim_data(devId, nBlocks);
260
261         dev = malloc(sizeof(*dev));
262
263         if(!sim || !dev){
264                 free(sim);
265                 free(dev);
266                 printf("Flash Sim creation failed. sim = %p, dev = %p\n",
267                                 sim, dev);
268                 return NULL;
269         }
270
271         memset(dev, 0, sizeof(*dev));
272
273         if(start_block >= sim->nBlocks)
274                 start_block = 0;
275         if(end_block == 0 || end_block >= sim->nBlocks)
276                 end_block = sim->nBlocks - 1;
277
278         p = &dev->param;
279         p->name = strdup(name);
280         p->start_block = start_block;
281         p->end_block = end_block;
282         p->total_bytes_per_chunk = DATA_SIZE;
283         p->spare_bytes_per_chunk= SPARE_SIZE;
284         p->chunks_per_block = PAGES_PER_BLOCK;
285         p->n_reserved_blocks = 2;
286         p->use_nand_ecc = 1;
287         p->inband_tags = 0;
288         p->is_yaffs2 = 1;
289
290         d= &dev->drv;
291         d->drv_initialise_fn = yramsim_initialise;
292         d->drv_deinitialise_fn = yramsim_deinitialise;
293         d->drv_read_chunk_fn = yramsim_rd_chunk;
294         d->drv_write_chunk_fn = yramsim_wr_chunk;
295         d->drv_erase_fn = yramsim_erase;
296         d->drv_check_bad_fn = yramsim_check_block_bad;
297         d->drv_mark_bad_fn = yramsim_mark_block_bad;
298
299         dev->driver_context= (void *)sim;
300
301         printf("Created simulated flash device %p\n", dev);
302         return dev;
303 }
304
305 struct yaffs_dev *yaffs_rtems_flashsim_setup(void)
306 {
307         return yramsim_CreateRamSim("ramsim",
308                                 0, 100,
309                                 0, 99);
310 }
311