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
21 #include "yaffs_guts.h"
26 #define DATA_SIZE 2048
28 #define PAGE_SIZE (DATA_SIZE + SPARE_SIZE)
29 #define PAGES_PER_BLOCK 64
33 unsigned char page[PAGES_PER_BLOCK][PAGE_SIZE];
43 SimData *simDevs[N_RAM_SIM_DEVS];
45 static SimData *DevToSim(struct yaffs_dev *dev)
47 return (SimData*)(dev->driver_context);
51 static void CheckInitialised(void)
56 static int yramsim_erase_internal(SimData *sim, unsigned blockId,int force)
58 if(blockId < 0 || blockId >= sim->nBlocks){
62 if(!sim->blockList[blockId]){
66 if(!force && !sim->blockList[blockId]->blockOk){
70 memset(sim->blockList[blockId],0xff,sizeof(Block));
71 sim->blockList[blockId]->blockOk = 1;
79 static int yramsim_initialise(struct yaffs_dev *dev)
81 SimData *sim = DevToSim(dev);
82 Block **blockList = sim->blockList;
83 return blockList != NULL;
87 static int yramsim_deinitialise(struct yaffs_dev *dev)
92 static int yramsim_rd_chunk (struct yaffs_dev *dev, int pageId,
93 u8 *data, int dataLength,
94 u8 *spare, int spareLength,
95 enum yaffs_ecc_result *ecc_result)
97 SimData *sim = DevToSim(dev);
98 Block **blockList = sim->blockList;
100 unsigned blockId = pageId / PAGES_PER_BLOCK;
101 unsigned pageOffset = pageId % PAGES_PER_BLOCK;
104 if(blockId >= sim->nBlocks ||
105 pageOffset >= PAGES_PER_BLOCK ||
106 dataLength >DATA_SIZE ||
107 spareLength > SPARE_SIZE ||
108 !blockList[blockId]->blockOk){
112 d = blockList[blockId]->page[pageOffset];
116 memcpy(data,d,dataLength);
119 memcpy(spare,s,spareLength);
122 *ecc_result = YAFFS_ECC_RESULT_NO_ERROR;
127 static int yramsim_wr_chunk (struct yaffs_dev *dev, int pageId,
128 const u8 *data, int dataLength,
129 const u8 *spare, int spareLength)
131 SimData *sim = DevToSim(dev);
132 Block **blockList = sim->blockList;
134 unsigned blockId = pageId / PAGES_PER_BLOCK;
135 unsigned pageOffset = pageId % PAGES_PER_BLOCK;
138 if(blockId >= sim->nBlocks ||
139 pageOffset >= PAGES_PER_BLOCK ||
140 dataLength >DATA_SIZE ||
141 spareLength > SPARE_SIZE ||
142 !blockList[blockId]->blockOk){
146 d = blockList[blockId]->page[pageOffset];
150 memcpy(d,data,dataLength);
153 memcpy(s,spare,spareLength);
159 static int yramsim_erase(struct yaffs_dev *dev, int blockId)
161 SimData *sim = DevToSim(dev);
164 return yramsim_erase_internal(sim,blockId,0);
167 static int yramsim_check_block_bad(struct yaffs_dev *dev, int blockId)
169 SimData *sim = DevToSim(dev);
170 Block **blockList = sim->blockList;
171 if(blockId >= sim->nBlocks){
175 return blockList[blockId]->blockOk ? YAFFS_OK : YAFFS_FAIL;
178 static int yramsim_mark_block_bad(struct yaffs_dev *dev, int blockId)
180 SimData *sim = DevToSim(dev);
181 Block **blockList = sim->blockList;
182 if(blockId >= sim->nBlocks){
186 blockList[blockId]->blockOk = 0;
192 static SimData *yramsim_alloc_sim_data(u32 devId, u32 nBlocks)
201 if(devId >= N_RAM_SIM_DEVS)
204 sim = simDevs[devId];
209 sim = malloc(sizeof (SimData));
213 simDevs[devId] = sim;
215 blockList = malloc(nBlocks * sizeof(Block *));
217 sim->blockList = blockList;
218 sim->nBlocks = nBlocks;
224 for(i = 0; i < nBlocks; i++)
227 for(i = 0; i < nBlocks && ok; i++){
228 b= malloc(sizeof(Block));
231 yramsim_erase_internal(sim,i,1);
238 for(i = 0; i < nBlocks; i++)
253 struct yaffs_dev *yramsim_CreateRamSim(const YCHAR *name,
254 u32 devId, u32 nBlocks,
255 u32 start_block, u32 end_block)
258 struct yaffs_dev *dev;
259 struct yaffs_param *p;
260 struct yaffs_driver *d;
262 sim = yramsim_alloc_sim_data(devId, nBlocks);
264 dev = malloc(sizeof(*dev));
272 memset(dev, 0, sizeof(*dev));
274 if(start_block >= sim->nBlocks)
276 if(end_block == 0 || end_block >= sim->nBlocks)
277 end_block = sim->nBlocks - 1;
280 p->name = strdup(name);
281 p->start_block = start_block;
282 p->end_block = end_block;
283 p->total_bytes_per_chunk = DATA_SIZE;
284 p->spare_bytes_per_chunk= SPARE_SIZE;
285 p->chunks_per_block = PAGES_PER_BLOCK;
286 p->n_reserved_blocks = 2;
292 d->drv_initialise_fn = yramsim_initialise;
293 d->drv_deinitialise_fn = yramsim_deinitialise;
294 d->drv_read_chunk_fn = yramsim_rd_chunk;
295 d->drv_write_chunk_fn = yramsim_wr_chunk;
296 d->drv_erase_fn = yramsim_erase;
297 d->drv_check_bad_fn = yramsim_check_block_bad;
298 d->drv_mark_bad_fn = yramsim_mark_block_bad;
300 dev->driver_context= (void *)sim;