1 // NAND Simulator for testing YAFFS
7 #include "yaffs_nandif.h"
10 #define DATA_SIZE 2048
12 #define PAGE_SIZE (DATA_SIZE + SPARE_SIZE)
13 #define PAGES_PER_BLOCK 64
17 unsigned char page[PAGES_PER_BLOCK][PAGE_SIZE];
27 SimData *simDevs[N_RAM_SIM_DEVS];
29 static SimData *DevToSim(yaffs_dev_t *dev)
31 ynandif_Geometry *geom = (ynandif_Geometry *)(dev->driver_context);
32 SimData * sim = (SimData*)(geom->privateData);
37 static void CheckInitialised(void)
42 static int yramsim_erase_internal(SimData *sim, unsigned blockId,int force)
44 if(blockId < 0 || blockId >= sim->nBlocks){
48 if(!sim->blockList[blockId]){
52 if(!force && !sim->blockList[blockId]->blockOk){
56 memset(sim->blockList[blockId],0xff,sizeof(Block));
57 sim->blockList[blockId]->blockOk = 1;
65 static int yramsim_initialise(yaffs_dev_t *dev)
67 SimData *sim = DevToSim(dev);
68 Block **blockList = sim->blockList;
69 return blockList != NULL;
73 static int yramsim_deinitialise(yaffs_dev_t *dev)
78 static int yramsim_rd_chunk (yaffs_dev_t *dev, unsigned pageId,
79 unsigned char *data, unsigned dataLength,
80 unsigned char *spare, unsigned spareLength,
83 SimData *sim = DevToSim(dev);
84 Block **blockList = sim->blockList;
86 unsigned blockId = pageId / PAGES_PER_BLOCK;
87 unsigned pageOffset = pageId % PAGES_PER_BLOCK;
90 if(blockId >= sim->nBlocks ||
91 pageOffset >= PAGES_PER_BLOCK ||
92 dataLength >DATA_SIZE ||
93 spareLength > SPARE_SIZE ||
95 !blockList[blockId]->blockOk){
99 d = blockList[blockId]->page[pageOffset];
103 memcpy(data,d,dataLength);
106 memcpy(spare,s,spareLength);
108 *eccStatus = 0; // 0 = no error, -1 = unfixable error, 1 = fixable
113 static int yramsim_wr_chunk (yaffs_dev_t *dev,unsigned pageId,
114 const unsigned char *data, unsigned dataLength,
115 const unsigned char *spare, unsigned spareLength)
117 SimData *sim = DevToSim(dev);
118 Block **blockList = sim->blockList;
120 unsigned blockId = pageId / PAGES_PER_BLOCK;
121 unsigned pageOffset = pageId % PAGES_PER_BLOCK;
124 if(blockId >= sim->nBlocks ||
125 pageOffset >= PAGES_PER_BLOCK ||
126 dataLength >DATA_SIZE ||
127 spareLength > SPARE_SIZE ||
128 !blockList[blockId]->blockOk){
132 d = blockList[blockId]->page[pageOffset];
136 memcpy(d,data,dataLength);
139 memcpy(s,spare,spareLength);
145 static int yramsim_erase(yaffs_dev_t *dev,unsigned blockId)
147 SimData *sim = DevToSim(dev);
150 return yramsim_erase_internal(sim,blockId,0);
153 static int yramsim_check_block_ok(yaffs_dev_t *dev,unsigned blockId)
155 SimData *sim = DevToSim(dev);
156 Block **blockList = sim->blockList;
157 if(blockId >= sim->nBlocks){
161 return blockList[blockId]->blockOk ? 1 : 0;
164 static int yramsim_mark_block_bad(yaffs_dev_t *dev,unsigned blockId)
166 SimData *sim = DevToSim(dev);
167 Block **blockList = sim->blockList;
168 if(blockId >= sim->nBlocks){
172 blockList[blockId]->blockOk = 0;
178 static SimData *yramsim_alloc_sim_data(__u32 devId, __u32 nBlocks)
187 if(devId >= N_RAM_SIM_DEVS)
190 sim = simDevs[devId];
195 sim = malloc(sizeof (SimData));
199 simDevs[devId] = sim;
201 blockList = malloc(nBlocks * sizeof(Block *));
203 sim->blockList = blockList;
204 sim->nBlocks = nBlocks;
210 for(i = 0; i < nBlocks; i++)
213 for(i = 0; i < nBlocks && ok; i++){
214 b= malloc(sizeof(Block));
217 yramsim_erase_internal(sim,i,1);
224 for(i = 0; i < nBlocks; i++)
239 struct yaffs_dev_s *yramsim_CreateRamSim(const YCHAR *name,
240 __u32 devId, __u32 nBlocks,
241 __u32 start_block, __u32 end_block)
246 sim = yramsim_alloc_sim_data(devId, nBlocks);
248 g = YMALLOC(sizeof(ynandif_Geometry));
256 if(start_block >= sim->nBlocks)
258 if(end_block == 0 || end_block >= sim->nBlocks)
259 end_block = sim->nBlocks - 1;
261 memset(g,0,sizeof(ynandif_Geometry));
262 g->start_block = start_block;
263 g->end_block = end_block;
264 g->dataSize = DATA_SIZE;
265 g->spareSize= SPARE_SIZE;
266 g->pagesPerBlock = PAGES_PER_BLOCK;
270 g->initialise = yramsim_initialise;
271 g->deinitialise = yramsim_deinitialise;
272 g->readChunk = yramsim_rd_chunk,
273 g->writeChunk = yramsim_wr_chunk,
274 g->eraseBlock = yramsim_erase,
275 g->checkBlockOk = yramsim_check_block_ok,
276 g->markBlockBad = yramsim_mark_block_bad,
277 g->privateData = (void *)sim;
279 return yaffs_add_dev_from_geometry(name,g);