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_Device *dev)
31 ynandif_Geometry *geom = (ynandif_Geometry *)(dev->driverContext);
32 SimData * sim = (SimData*)(geom->privateData);
37 static void CheckInitialised(void)
42 static int yramsim_EraseBlockInternal(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_Device *dev)
67 SimData *sim = DevToSim(dev);
68 Block **blockList = sim->blockList;
69 return blockList != NULL;
73 static int yramsim_Deinitialise(yaffs_Device *dev)
78 static int yramsim_ReadChunk (yaffs_Device *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_WriteChunk (yaffs_Device *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_EraseBlock(yaffs_Device *dev,unsigned blockId)
147 SimData *sim = DevToSim(dev);
150 return yramsim_EraseBlockInternal(sim,blockId,0);
153 static int yramsim_CheckBlockOk(yaffs_Device *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_MarkBlockBad(yaffs_Device *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_AllocSimData(__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_EraseBlockInternal(sim,i,1);
224 for(i = 0; i < nBlocks; i++)
239 struct yaffs_DeviceStruct *yramsim_CreateRamSim(const YCHAR *name,
240 __u32 devId, __u32 nBlocks,
241 __u32 startBlock, __u32 endBlock)
246 sim = yramsim_AllocSimData(devId, nBlocks);
248 g = YMALLOC(sizeof(ynandif_Geometry));
256 if(startBlock >= sim->nBlocks)
258 if(endBlock == 0 || endBlock >= sim->nBlocks)
259 endBlock = sim->nBlocks - 1;
261 memset(g,0,sizeof(ynandif_Geometry));
262 g->startBlock = startBlock;
263 g->endBlock = endBlock;
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_ReadChunk,
273 g->writeChunk = yramsim_WriteChunk,
274 g->eraseBlock = yramsim_EraseBlock,
275 g->checkBlockOk = yramsim_CheckBlockOk,
276 g->markBlockBad = yramsim_MarkBlockBad,
277 g->privateData = (void *)sim;
279 return yaffs_add_dev_from_geometry(name,g);