1 // NAND Simulator for testing YAFFS
\r
7 #include "yaffs_nandif.h"
\r
10 #define DATA_SIZE 2048
\r
11 #define SPARE_SIZE 64
\r
12 #define PAGE_SIZE (DATA_SIZE + SPARE_SIZE)
\r
13 #define PAGES_PER_BLOCK 64
\r
17 unsigned char page[PAGES_PER_BLOCK][PAGE_SIZE];
\r
27 static SymData *DevToSym(yaffs_Device *dev)
\r
29 ynandif_Geometry *geom = (ynandif_Geometry *)(dev->driverContext);
\r
30 SymData * sym = (SymData*)(geom->privateData);
\r
35 static void CheckInitialised(void)
\r
40 static int yramsim_EraseBlockInternal(SymData *sym, unsigned blockId,int force)
\r
42 if(blockId < 0 || blockId >= sym->nBlocks){
\r
46 if(!sym->blockList[blockId]){
\r
50 if(!force && !sym->blockList[blockId]->blockOk){
\r
54 memset(sym->blockList[blockId],0xff,sizeof(Block));
\r
55 sym->blockList[blockId]->blockOk = 1;
\r
63 static int yramsim_Initialise(yaffs_Device *dev)
\r
65 SymData *sym = DevToSym(dev);
\r
66 Block **blockList = sym->blockList;
\r
67 return blockList != NULL;
\r
71 static int yramsim_Deinitialise(yaffs_Device *dev)
\r
76 static int yramsim_ReadChunk (yaffs_Device *dev, unsigned pageId,
\r
77 unsigned char *data, unsigned dataLength,
\r
78 unsigned char *spare, unsigned spareLength,
\r
81 SymData *sym = DevToSym(dev);
\r
82 Block **blockList = sym->blockList;
\r
84 unsigned blockId = pageId / PAGES_PER_BLOCK;
\r
85 unsigned pageOffset = pageId % PAGES_PER_BLOCK;
\r
88 if(blockId >= sym->nBlocks ||
\r
89 pageOffset >= PAGES_PER_BLOCK ||
\r
90 dataLength >DATA_SIZE ||
\r
91 spareLength > SPARE_SIZE ||
\r
93 !blockList[blockId]->blockOk){
\r
97 d = blockList[blockId]->page[pageOffset];
\r
101 memcpy(data,d,dataLength);
\r
104 memcpy(spare,s,spareLength);
\r
106 *eccStatus = 0; // 0 = no error, -1 = unfixable error, 1 = fixable
\r
112 static int yramsim_WriteChunk (yaffs_Device *dev,unsigned pageId,
\r
113 const unsigned char *data, unsigned dataLength,
\r
114 const unsigned char *spare, unsigned spareLength)
\r
116 SymData *sym = DevToSym(dev);
\r
117 Block **blockList = sym->blockList;
\r
119 unsigned blockId = pageId / PAGES_PER_BLOCK;
\r
120 unsigned pageOffset = pageId % PAGES_PER_BLOCK;
\r
123 if(blockId >= sym->nBlocks ||
\r
124 pageOffset >= PAGES_PER_BLOCK ||
\r
125 dataLength >DATA_SIZE ||
\r
126 spareLength > SPARE_SIZE ||
\r
127 !blockList[blockId]->blockOk){
\r
131 d = blockList[blockId]->page[pageOffset];
\r
135 memcpy(d,data,dataLength);
\r
138 memcpy(s,spare,spareLength);
\r
145 static int yramsim_EraseBlock(yaffs_Device *dev,unsigned blockId)
\r
147 SymData *sym = DevToSym(dev);
\r
149 CheckInitialised();
\r
150 return yramsim_EraseBlockInternal(sym,blockId,0);
\r
153 static int yramsim_CheckBlockOk(yaffs_Device *dev,unsigned blockId)
\r
155 SymData *sym = DevToSym(dev);
\r
156 Block **blockList = sym->blockList;
\r
157 if(blockId >= sym->nBlocks){
\r
161 return blockList[blockId]->blockOk ? 1 : 0;
\r
164 static int yramsim_MarkBlockBad(yaffs_Device *dev,unsigned blockId)
\r
166 SymData *sym = DevToSym(dev);
\r
167 Block **blockList = sym->blockList;
\r
168 if(blockId >= sym->nBlocks){
\r
172 blockList[blockId]->blockOk = 0;
\r
178 static SymData *yramsim_AllocSymData(int nBlocks)
\r
187 sym = malloc(sizeof (SymData));
\r
191 blockList = malloc(nBlocks * sizeof(Block *));
\r
193 sym->blockList = blockList;
\r
194 sym->nBlocks = nBlocks;
\r
200 for(i = 0; i < nBlocks; i++)
\r
201 blockList[i] = NULL;
\r
203 for(i = 0; i < nBlocks && ok; i++){
\r
204 b= malloc(sizeof(Block));
\r
207 yramsim_EraseBlockInternal(sym,i,1);
\r
214 for(i = 0; i < nBlocks; i++)
\r
216 free(blockList[i]);
\r
217 blockList[i] = NULL;
\r
229 struct yaffs_DeviceStruct *yramsim_CreateSim(const YCHAR *name,int nBlocks)
\r
231 void *sym = (void *)yramsim_AllocSymData(nBlocks);
\r
232 ynandif_Geometry *g;
\r
234 g = YMALLOC(sizeof(ynandif_Geometry));
\r
244 memset(g,0,sizeof(ynandif_Geometry));
\r
246 g->endBlock = nBlocks - 1;
\r
247 g->dataSize = DATA_SIZE;
\r
248 g->spareSize= SPARE_SIZE;
\r
249 g->pagesPerBlock = PAGES_PER_BLOCK;
\r
253 g->initialise = yramsim_Initialise;
\r
254 g->deinitialise = yramsim_Deinitialise;
\r
255 g->readChunk = yramsim_ReadChunk,
\r
256 g->writeChunk = yramsim_WriteChunk,
\r
257 g->eraseBlock = yramsim_EraseBlock,
\r
258 g->checkBlockOk = yramsim_CheckBlockOk,
\r
259 g->markBlockBad = yramsim_MarkBlockBad,
\r
260 g->privateData = sym;
\r
262 return yaffs_AddDeviceFromGeometry(name,g);
\r