2 * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
4 * Copyright (C) 2002-2011 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(struct yaffs_dev *dev)
46 struct ynandif_Geometry *geom =
47 (struct ynandif_Geometry *)(dev->driver_context);
48 SimData * sim = (SimData*)(geom->privateData);
53 static void CheckInitialised(void)
58 static int yramsim_erase_internal(SimData *sim, unsigned blockId,int force)
60 if(blockId < 0 || blockId >= sim->nBlocks){
64 if(!sim->blockList[blockId]){
68 if(!force && !sim->blockList[blockId]->blockOk){
72 memset(sim->blockList[blockId],0xff,sizeof(Block));
73 sim->blockList[blockId]->blockOk = 1;
81 static int yramsim_initialise(struct yaffs_dev *dev)
83 SimData *sim = DevToSim(dev);
84 Block **blockList = sim->blockList;
85 return blockList != NULL;
89 static int yramsim_deinitialise(struct yaffs_dev *dev)
94 static int yramsim_rd_chunk (struct yaffs_dev *dev, unsigned pageId,
95 unsigned char *data, unsigned dataLength,
96 unsigned char *spare, unsigned spareLength,
99 SimData *sim = DevToSim(dev);
100 Block **blockList = sim->blockList;
102 unsigned blockId = pageId / PAGES_PER_BLOCK;
103 unsigned pageOffset = pageId % PAGES_PER_BLOCK;
106 if(blockId >= sim->nBlocks ||
107 pageOffset >= PAGES_PER_BLOCK ||
108 dataLength >DATA_SIZE ||
109 spareLength > SPARE_SIZE ||
111 !blockList[blockId]->blockOk){
115 d = blockList[blockId]->page[pageOffset];
119 memcpy(data,d,dataLength);
122 memcpy(spare,s,spareLength);
124 *eccStatus = 0; // 0 = no error, -1 = unfixable error, 1 = fixable
129 static int yramsim_wr_chunk (struct yaffs_dev *dev,unsigned pageId,
130 const unsigned char *data, unsigned dataLength,
131 const unsigned char *spare, unsigned spareLength)
133 SimData *sim = DevToSim(dev);
134 Block **blockList = sim->blockList;
136 unsigned blockId = pageId / PAGES_PER_BLOCK;
137 unsigned pageOffset = pageId % PAGES_PER_BLOCK;
140 if(blockId >= sim->nBlocks ||
141 pageOffset >= PAGES_PER_BLOCK ||
142 dataLength >DATA_SIZE ||
143 spareLength > SPARE_SIZE ||
144 !blockList[blockId]->blockOk){
148 d = blockList[blockId]->page[pageOffset];
152 memcpy(d,data,dataLength);
155 memcpy(s,spare,spareLength);
161 static int yramsim_erase(struct yaffs_dev *dev,unsigned blockId)
163 SimData *sim = DevToSim(dev);
166 return yramsim_erase_internal(sim,blockId,0);
169 static int yramsim_check_block_ok(struct yaffs_dev *dev,unsigned blockId)
171 SimData *sim = DevToSim(dev);
172 Block **blockList = sim->blockList;
173 if(blockId >= sim->nBlocks){
177 return blockList[blockId]->blockOk ? 1 : 0;
180 static int yramsim_mark_block_bad(struct yaffs_dev *dev,unsigned blockId)
182 SimData *sim = DevToSim(dev);
183 Block **blockList = sim->blockList;
184 if(blockId >= sim->nBlocks){
188 blockList[blockId]->blockOk = 0;
194 static SimData *yramsim_alloc_sim_data(u32 devId, u32 nBlocks)
203 if(devId >= N_RAM_SIM_DEVS)
206 sim = simDevs[devId];
211 sim = malloc(sizeof (SimData));
215 simDevs[devId] = sim;
217 blockList = malloc(nBlocks * sizeof(Block *));
219 sim->blockList = blockList;
220 sim->nBlocks = nBlocks;
226 for(i = 0; i < nBlocks; i++)
229 for(i = 0; i < nBlocks && ok; i++){
230 b= malloc(sizeof(Block));
233 yramsim_erase_internal(sim,i,1);
240 for(i = 0; i < nBlocks; i++)
255 struct yaffs_dev *yramsim_CreateRamSim(const YCHAR *name,
256 u32 devId, u32 nBlocks,
257 u32 start_block, u32 end_block)
260 struct ynandif_Geometry *g;
262 sim = yramsim_alloc_sim_data(devId, nBlocks);
264 g = malloc(sizeof(*g));
272 if(start_block >= sim->nBlocks)
274 if(end_block == 0 || end_block >= sim->nBlocks)
275 end_block = sim->nBlocks - 1;
277 memset(g,0,sizeof(*g));
278 g->start_block = start_block;
279 g->end_block = end_block;
280 g->dataSize = DATA_SIZE;
281 g->spareSize= SPARE_SIZE;
282 g->pagesPerBlock = PAGES_PER_BLOCK;
286 g->initialise = yramsim_initialise;
287 g->deinitialise = yramsim_deinitialise;
288 g->readChunk = yramsim_rd_chunk,
289 g->writeChunk = yramsim_wr_chunk,
290 g->eraseBlock = yramsim_erase,
291 g->checkBlockOk = yramsim_check_block_ok,
292 g->markBlockBad = yramsim_mark_block_bad,
293 g->privateData = (void *)sim;
295 return yaffs_add_dev_from_geometry(name,g);