yaffs Clean up WinCE compilation issues
[yaffs2.git] / direct / basic-test / yramsim.c
1 // NAND Simulator for testing YAFFS\r
2 \r
3 #include <string.h>\r
4 \r
5 #include "yramsim.h"\r
6 \r
7 #include "yaffs_nandif.h"\r
8 \r
9 \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
14 \r
15 \r
16 typedef struct {\r
17         unsigned char page[PAGES_PER_BLOCK][PAGE_SIZE];\r
18         unsigned blockOk;\r
19 } Block;\r
20 \r
21 typedef struct {\r
22         Block **blockList;\r
23         int nBlocks;\r
24 } SymData;\r
25 \r
26 \r
27 static SymData *DevToSym(yaffs_Device *dev)\r
28 {\r
29         ynandif_Geometry *geom = (ynandif_Geometry *)(dev->driverContext);\r
30         SymData * sym = (SymData*)(geom->privateData);\r
31         return sym;\r
32\r
33 \r
34 \r
35 static void CheckInitialised(void)\r
36 {\r
37 \r
38 }\r
39 \r
40 static int yramsim_EraseBlockInternal(SymData *sym, unsigned blockId,int force)\r
41 {\r
42         if(blockId < 0 || blockId >= sym->nBlocks){\r
43                 return 0;\r
44         }\r
45 \r
46         if(!sym->blockList[blockId]){\r
47                 return 0;\r
48         }\r
49 \r
50         if(!force && !sym->blockList[blockId]->blockOk){\r
51                 return 0;\r
52         }\r
53 \r
54         memset(sym->blockList[blockId],0xff,sizeof(Block));\r
55         sym->blockList[blockId]->blockOk = 1;\r
56 \r
57         return 1;\r
58 }\r
59 \r
60 \r
61 \r
62 \r
63 static int yramsim_Initialise(yaffs_Device *dev)\r
64 {\r
65         SymData *sym = DevToSym(dev);\r
66         Block **blockList = sym->blockList;\r
67         return blockList != NULL;\r
68 }\r
69 \r
70 \r
71 static int yramsim_Deinitialise(yaffs_Device *dev)\r
72 {\r
73         return 1;\r
74 }\r
75 \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
79                                           int *eccStatus)\r
80 {\r
81         SymData *sym = DevToSym(dev);\r
82         Block **blockList = sym->blockList;\r
83 \r
84         unsigned blockId = pageId / PAGES_PER_BLOCK;\r
85         unsigned pageOffset = pageId % PAGES_PER_BLOCK;\r
86         unsigned char * d;\r
87         unsigned char *s;\r
88         if(blockId >= sym->nBlocks ||\r
89            pageOffset >= PAGES_PER_BLOCK ||\r
90            dataLength >DATA_SIZE ||\r
91            spareLength > SPARE_SIZE ||\r
92            !eccStatus ||\r
93            !blockList[blockId]->blockOk){\r
94                    return 0;\r
95         }\r
96 \r
97         d = blockList[blockId]->page[pageOffset];\r
98         s = d + DATA_SIZE;\r
99 \r
100         if(data)\r
101                 memcpy(data,d,dataLength);\r
102 \r
103         if(spare)\r
104                 memcpy(spare,s,spareLength);\r
105 \r
106         *eccStatus = 0; // 0 = no error, -1 = unfixable error, 1 = fixable\r
107 \r
108         return 1;\r
109         \r
110 }\r
111 \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
115 {\r
116         SymData *sym = DevToSym(dev);\r
117         Block **blockList = sym->blockList;\r
118 \r
119         unsigned blockId = pageId / PAGES_PER_BLOCK;\r
120         unsigned pageOffset = pageId % PAGES_PER_BLOCK;\r
121         unsigned char * d;\r
122         unsigned char *s;\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
128                    return 0;\r
129         }\r
130 \r
131         d = blockList[blockId]->page[pageOffset];\r
132         s = d + DATA_SIZE;\r
133 \r
134         if(data)\r
135                 memcpy(d,data,dataLength);\r
136 \r
137         if(spare)\r
138                 memcpy(s,spare,spareLength);\r
139 \r
140         return 1;\r
141         \r
142 }\r
143 \r
144 \r
145 static int yramsim_EraseBlock(yaffs_Device *dev,unsigned blockId)\r
146 {\r
147         SymData *sym = DevToSym(dev);\r
148 \r
149         CheckInitialised();\r
150         return yramsim_EraseBlockInternal(sym,blockId,0);\r
151 }\r
152 \r
153 static int yramsim_CheckBlockOk(yaffs_Device *dev,unsigned blockId)\r
154 {\r
155         SymData *sym = DevToSym(dev);\r
156         Block **blockList = sym->blockList;\r
157         if(blockId >= sym->nBlocks){\r
158                 return 0;\r
159         }\r
160 \r
161         return blockList[blockId]->blockOk ? 1 : 0;\r
162 }\r
163 \r
164 static int yramsim_MarkBlockBad(yaffs_Device *dev,unsigned blockId)\r
165 {\r
166         SymData *sym = DevToSym(dev);\r
167         Block **blockList = sym->blockList;\r
168         if(blockId >= sym->nBlocks){\r
169                 return 0;\r
170         }\r
171 \r
172         blockList[blockId]->blockOk = 0;\r
173 \r
174         return 1;\r
175 }\r
176 \r
177 \r
178 static SymData *yramsim_AllocSymData(int nBlocks)\r
179 {\r
180         int ok = 1;\r
181 \r
182         Block **blockList;\r
183         SymData *sym;\r
184         Block *b;\r
185         int i;\r
186 \r
187         sym = malloc(sizeof (SymData));\r
188         if(!sym)\r
189                 return NULL;\r
190 \r
191         blockList = malloc(nBlocks * sizeof(Block *));\r
192         \r
193         sym->blockList = blockList;\r
194         sym->nBlocks = nBlocks;\r
195         if(!blockList){\r
196                 free(sym);\r
197                 return NULL;\r
198         }\r
199 \r
200         for(i = 0; i < nBlocks; i++)\r
201                 blockList[i] = NULL;\r
202 \r
203         for(i = 0; i < nBlocks && ok; i++){\r
204                 b=  malloc(sizeof(Block));\r
205                 if(b){\r
206                         blockList[i] = b;\r
207                         yramsim_EraseBlockInternal(sym,i,1);\r
208                 }\r
209                 else\r
210                         ok = 0;\r
211         }\r
212 \r
213         if(!ok){\r
214                 for(i = 0; i < nBlocks; i++)\r
215                         if(blockList[i]){\r
216                                 free(blockList[i]);\r
217                                 blockList[i] = NULL;\r
218                         }\r
219                 free(blockList);\r
220                 blockList = NULL;\r
221                 free(sym);\r
222                 sym = NULL;\r
223         }\r
224 \r
225         return sym;\r
226 }\r
227 \r
228 \r
229 struct yaffs_DeviceStruct *yramsim_CreateSim(const YCHAR *name,int nBlocks)\r
230 {\r
231         void *sym = (void *)yramsim_AllocSymData(nBlocks);\r
232         ynandif_Geometry *g;\r
233 \r
234         g = YMALLOC(sizeof(ynandif_Geometry));\r
235         \r
236         if(!sym || !g){\r
237                 if(sym)\r
238                         YFREE(sym);\r
239                 if(g)\r
240                         YFREE(g);\r
241                 return NULL;\r
242         }\r
243 \r
244         memset(g,0,sizeof(ynandif_Geometry));\r
245         g->startBlock = 0;\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
250         g->hasECC = 1;\r
251         g->inbandTags = 0;\r
252         g->useYaffs2 = 1;\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
261 \r
262         return yaffs_AddDeviceFromGeometry(name,g);\r
263 }