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