2 * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
4 * Copyright (C) 2002-2010 Aleph One Ltd.
5 * for Toby Churchill Ltd and Brightstar Engineering
7 * Created by Charles Manning <charles@aleph1.co.uk>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
15 * NAND Simulator for testing YAFFS
22 #include "yaffs_nandif.h"
25 #define DATA_SIZE 2048
27 #define PAGE_SIZE (DATA_SIZE + SPARE_SIZE)
28 #define PAGES_PER_BLOCK 64
32 unsigned char page[PAGES_PER_BLOCK][PAGE_SIZE];
42 SimData *simDevs[N_RAM_SIM_DEVS];
44 static SimData *DevToSim(yaffs_Device *dev)
46 ynandif_Geometry *geom = (ynandif_Geometry *)(dev->driverContext);
47 SimData * sim = (SimData*)(geom->privateData);
52 static void CheckInitialised(void)
57 static int yramsim_EraseBlockInternal(SimData *sim, unsigned blockId,int force)
59 if(blockId < 0 || blockId >= sim->nBlocks){
63 if(!sim->blockList[blockId]){
67 if(!force && !sim->blockList[blockId]->blockOk){
71 memset(sim->blockList[blockId],0xff,sizeof(Block));
72 sim->blockList[blockId]->blockOk = 1;
80 static int yramsim_Initialise(yaffs_Device *dev)
82 SimData *sim = DevToSim(dev);
83 Block **blockList = sim->blockList;
84 return blockList != NULL;
88 static int yramsim_Deinitialise(yaffs_Device *dev)
93 static int yramsim_ReadChunk (yaffs_Device *dev, unsigned pageId,
94 unsigned char *data, unsigned dataLength,
95 unsigned char *spare, unsigned spareLength,
98 SimData *sim = DevToSim(dev);
99 Block **blockList = sim->blockList;
101 unsigned blockId = pageId / PAGES_PER_BLOCK;
102 unsigned pageOffset = pageId % PAGES_PER_BLOCK;
105 if(blockId >= sim->nBlocks ||
106 pageOffset >= PAGES_PER_BLOCK ||
107 dataLength >DATA_SIZE ||
108 spareLength > SPARE_SIZE ||
110 !blockList[blockId]->blockOk){
114 d = blockList[blockId]->page[pageOffset];
118 memcpy(data,d,dataLength);
121 memcpy(spare,s,spareLength);
123 *eccStatus = 0; // 0 = no error, -1 = unfixable error, 1 = fixable
128 static int yramsim_WriteChunk (yaffs_Device *dev,unsigned pageId,
129 const unsigned char *data, unsigned dataLength,
130 const unsigned char *spare, unsigned spareLength)
132 SimData *sim = DevToSim(dev);
133 Block **blockList = sim->blockList;
135 unsigned blockId = pageId / PAGES_PER_BLOCK;
136 unsigned pageOffset = pageId % PAGES_PER_BLOCK;
139 if(blockId >= sim->nBlocks ||
140 pageOffset >= PAGES_PER_BLOCK ||
141 dataLength >DATA_SIZE ||
142 spareLength > SPARE_SIZE ||
143 !blockList[blockId]->blockOk){
147 d = blockList[blockId]->page[pageOffset];
151 memcpy(d,data,dataLength);
154 memcpy(s,spare,spareLength);
160 static int yramsim_EraseBlock(yaffs_Device *dev,unsigned blockId)
162 SimData *sim = DevToSim(dev);
165 return yramsim_EraseBlockInternal(sim,blockId,0);
168 static int yramsim_CheckBlockOk(yaffs_Device *dev,unsigned blockId)
170 SimData *sim = DevToSim(dev);
171 Block **blockList = sim->blockList;
172 if(blockId >= sim->nBlocks){
176 return blockList[blockId]->blockOk ? 1 : 0;
179 static int yramsim_MarkBlockBad(yaffs_Device *dev,unsigned blockId)
181 SimData *sim = DevToSim(dev);
182 Block **blockList = sim->blockList;
183 if(blockId >= sim->nBlocks){
187 blockList[blockId]->blockOk = 0;
193 static SimData *yramsim_AllocSimData(__u32 devId, __u32 nBlocks)
202 if(devId >= N_RAM_SIM_DEVS)
205 sim = simDevs[devId];
210 sim = malloc(sizeof (SimData));
214 simDevs[devId] = sim;
216 blockList = malloc(nBlocks * sizeof(Block *));
218 sim->blockList = blockList;
219 sim->nBlocks = nBlocks;
225 for(i = 0; i < nBlocks; i++)
228 for(i = 0; i < nBlocks && ok; i++){
229 b= malloc(sizeof(Block));
232 yramsim_EraseBlockInternal(sim,i,1);
239 for(i = 0; i < nBlocks; i++)
254 struct yaffs_DeviceStruct *yramsim_CreateRamSim(const YCHAR *name,
255 __u32 devId, __u32 nBlocks,
256 __u32 startBlock, __u32 endBlock)
261 sim = yramsim_AllocSimData(devId, nBlocks);
263 g = YMALLOC(sizeof(ynandif_Geometry));
271 if(startBlock >= sim->nBlocks)
273 if(endBlock == 0 || endBlock >= sim->nBlocks)
274 endBlock = sim->nBlocks - 1;
276 memset(g,0,sizeof(ynandif_Geometry));
277 g->startBlock = startBlock;
278 g->endBlock = endBlock;
279 g->dataSize = DATA_SIZE;
280 g->spareSize= SPARE_SIZE;
281 g->pagesPerBlock = PAGES_PER_BLOCK;
285 g->initialise = yramsim_Initialise;
286 g->deinitialise = yramsim_Deinitialise;
287 g->readChunk = yramsim_ReadChunk,
288 g->writeChunk = yramsim_WriteChunk,
289 g->eraseBlock = yramsim_EraseBlock,
290 g->checkBlockOk = yramsim_CheckBlockOk,
291 g->markBlockBad = yramsim_MarkBlockBad,
292 g->privateData = (void *)sim;
294 return yaffs_AddDeviceFromGeometry(name,g);