1 // NAND Simulator for testing YAFFS
\r
7 #include "yaffs_nandif.h"
\r
11 #include <windows.h>
\r
13 #define DebugBreak() do { } while(0)
\r
17 #define DATA_SIZE 2048
\r
18 #define SPARE_SIZE 64
\r
19 #define PAGE_SIZE (DATA_SIZE + SPARE_SIZE)
\r
20 #define PAGES_PER_BLOCK 64
\r
24 unsigned char page[PAGES_PER_BLOCK][PAGE_SIZE];
\r
34 static SymData *DevToSym(yaffs_Device *dev)
\r
36 ynandif_Geometry *geom = (ynandif_Geometry *)(dev->driverContext);
\r
37 SymData * sym = (SymData*)(geom->privateData);
\r
42 static void CheckInitialised(void)
\r
47 static int yramsim_EraseBlockInternal(SymData *sym, unsigned blockId,int force)
\r
49 if(blockId < 0 || blockId >= sym->nBlocks){
\r
54 if(!sym->blockList[blockId]){
\r
59 if(!force && !sym->blockList[blockId]->blockOk){
\r
64 memset(sym->blockList[blockId],0xff,sizeof(Block));
\r
65 sym->blockList[blockId]->blockOk = 1;
\r
73 static int yramsim_Initialise(yaffs_Device *dev)
\r
75 SymData *sym = DevToSym(dev);
\r
76 Block **blockList = sym->blockList;
\r
77 return blockList != NULL;
\r
81 static int yramsim_Deinitialise(yaffs_Device *dev)
\r
86 static int yramsim_ReadChunk (yaffs_Device *dev, unsigned pageId,
\r
87 unsigned char *data, unsigned dataLength,
\r
88 unsigned char *spare, unsigned spareLength,
\r
91 SymData *sym = DevToSym(dev);
\r
92 Block **blockList = sym->blockList;
\r
94 unsigned blockId = pageId / PAGES_PER_BLOCK;
\r
95 unsigned pageOffset = pageId % PAGES_PER_BLOCK;
\r
98 if(blockId >= sym->nBlocks ||
\r
99 pageOffset >= PAGES_PER_BLOCK ||
\r
100 dataLength >DATA_SIZE ||
\r
101 spareLength > SPARE_SIZE ||
\r
103 !blockList[blockId]->blockOk){
\r
108 d = blockList[blockId]->page[pageOffset];
\r
112 memcpy(data,d,dataLength);
\r
115 memcpy(spare,s,spareLength);
\r
117 *eccStatus = 0; // 0 = no error, -1 = unfixable error, 1 = fixable
\r
123 static int yramsim_WriteChunk (yaffs_Device *dev,unsigned pageId,
\r
124 const unsigned char *data, unsigned dataLength,
\r
125 const unsigned char *spare, unsigned spareLength)
\r
127 SymData *sym = DevToSym(dev);
\r
128 Block **blockList = sym->blockList;
\r
130 unsigned blockId = pageId / PAGES_PER_BLOCK;
\r
131 unsigned pageOffset = pageId % PAGES_PER_BLOCK;
\r
134 if(blockId >= sym->nBlocks ||
\r
135 pageOffset >= PAGES_PER_BLOCK ||
\r
136 dataLength >DATA_SIZE ||
\r
137 spareLength > SPARE_SIZE ||
\r
138 !blockList[blockId]->blockOk){
\r
143 d = blockList[blockId]->page[pageOffset];
\r
147 memcpy(d,data,dataLength);
\r
150 memcpy(s,spare,spareLength);
\r
157 static int yramsim_EraseBlock(yaffs_Device *dev,unsigned blockId)
\r
159 SymData *sym = DevToSym(dev);
\r
161 CheckInitialised();
\r
162 return yramsim_EraseBlockInternal(sym,blockId,0);
\r
165 static int yramsim_CheckBlockOk(yaffs_Device *dev,unsigned blockId)
\r
167 SymData *sym = DevToSym(dev);
\r
168 Block **blockList = sym->blockList;
\r
169 if(blockId >= sym->nBlocks){
\r
174 return blockList[blockId]->blockOk ? 1 : 0;
\r
177 static int yramsim_MarkBlockBad(yaffs_Device *dev,unsigned blockId)
\r
179 SymData *sym = DevToSym(dev);
\r
180 Block **blockList = sym->blockList;
\r
181 if(blockId >= sym->nBlocks){
\r
186 blockList[blockId]->blockOk = 0;
\r
192 static SymData *yramsim_AllocSymData(int nBlocks)
\r
201 sym = malloc(sizeof (SymData));
\r
205 blockList = malloc(nBlocks * sizeof(Block *));
\r
207 sym->blockList = blockList;
\r
208 sym->nBlocks = nBlocks;
\r
214 for(i = 0; i < nBlocks; i++)
\r
215 blockList[i] = NULL;
\r
217 for(i = 0; i < nBlocks && ok; i++){
\r
218 b= malloc(sizeof(Block));
\r
221 yramsim_EraseBlockInternal(sym,i,1);
\r
228 for(i = 0; i < nBlocks; i++)
\r
230 free(blockList[i]);
\r
231 blockList[i] = NULL;
\r
243 struct yaffs_DeviceStruct *yramsim_CreateSim(const YCHAR *name,int nBlocks)
\r
245 void *sym = (void *)yramsim_AllocSymData(nBlocks);
\r
246 ynandif_Geometry *g;
\r
248 g = YMALLOC(sizeof(ynandif_Geometry));
\r
258 memset(g,0,sizeof(ynandif_Geometry));
\r
260 g->endBlock = nBlocks - 1;
\r
261 g->dataSize = DATA_SIZE;
\r
262 g->spareSize= SPARE_SIZE;
\r
263 g->pagesPerBlock = PAGES_PER_BLOCK;
\r
267 g->initialise = yramsim_Initialise;
\r
268 g->deinitialise = yramsim_Deinitialise;
\r
269 g->readChunk = yramsim_ReadChunk,
\r
270 g->writeChunk = yramsim_WriteChunk,
\r
271 g->eraseBlock = yramsim_EraseBlock,
\r
272 g->checkBlockOk = yramsim_CheckBlockOk,
\r
273 g->markBlockBad = yramsim_MarkBlockBad,
\r
274 g->privateData = sym;
\r
276 return yaffs_AddDeviceFromGeometry(name,g);
\r