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(struct yaffs_dev *dev)
46 ynandif_Geometry *geom = (ynandif_Geometry *)(dev->driver_context);
47 SimData * sim = (SimData*)(geom->privateData);
52 static void CheckInitialised(void)
57 static int yramsim_erase_internal(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(struct yaffs_dev *dev)
82 SimData *sim = DevToSim(dev);
83 Block **blockList = sim->blockList;
84 return blockList != NULL;
88 static int yramsim_deinitialise(struct yaffs_dev *dev)
93 static int yramsim_rd_chunk (struct yaffs_dev *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_wr_chunk (struct yaffs_dev *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_erase(struct yaffs_dev *dev,unsigned blockId)
162 SimData *sim = DevToSim(dev);
165 return yramsim_erase_internal(sim,blockId,0);
168 static int yramsim_check_block_ok(struct yaffs_dev *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_mark_block_bad(struct yaffs_dev *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_alloc_sim_data(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_erase_internal(sim,i,1);
239 for(i = 0; i < nBlocks; i++)
254 struct yaffs_dev *yramsim_CreateRamSim(const YCHAR *name,
255 u32 devId, u32 nBlocks,
256 u32 start_block, u32 end_block)
261 sim = yramsim_alloc_sim_data(devId, nBlocks);
263 g = malloc(sizeof(ynandif_Geometry));
271 if(start_block >= sim->nBlocks)
273 if(end_block == 0 || end_block >= sim->nBlocks)
274 end_block = sim->nBlocks - 1;
276 memset(g,0,sizeof(ynandif_Geometry));
277 g->start_block = start_block;
278 g->end_block = end_block;
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_rd_chunk,
288 g->writeChunk = yramsim_wr_chunk,
289 g->eraseBlock = yramsim_erase,
290 g->checkBlockOk = yramsim_check_block_ok,
291 g->markBlockBad = yramsim_mark_block_bad,
292 g->privateData = (void *)sim;
294 return yaffs_add_dev_from_geometry(name,g);