2 * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
4 * Copyright (C) 2002-2018 Aleph One Ltd.
6 * Created by Charles Manning <charles@aleph1.co.uk>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
14 * NAND Simulator for testing YAFFS
20 #include "yaffs_guts.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 return (SimData*)(dev->driver_context);
50 static void CheckInitialised(void)
55 static int yramsim_erase_internal(SimData *sim, unsigned blockId,int force)
57 if(blockId < 0 || blockId >= sim->nBlocks){
61 if(!sim->blockList[blockId]){
65 if(!force && !sim->blockList[blockId]->blockOk){
69 memset(sim->blockList[blockId],0xff,sizeof(Block));
70 sim->blockList[blockId]->blockOk = 1;
78 static int yramsim_initialise(struct yaffs_dev *dev)
80 SimData *sim = DevToSim(dev);
81 Block **blockList = sim->blockList;
82 return blockList != NULL;
86 static int yramsim_deinitialise(struct yaffs_dev *dev)
91 static int yramsim_rd_chunk (struct yaffs_dev *dev, int pageId,
92 u8 *data, int dataLength,
93 u8 *spare, int spareLength,
94 enum yaffs_ecc_result *ecc_result)
96 SimData *sim = DevToSim(dev);
97 Block **blockList = sim->blockList;
99 unsigned blockId = pageId / PAGES_PER_BLOCK;
100 unsigned pageOffset = pageId % PAGES_PER_BLOCK;
103 if(blockId >= sim->nBlocks ||
104 pageOffset >= PAGES_PER_BLOCK ||
105 dataLength >DATA_SIZE ||
106 spareLength > SPARE_SIZE ||
107 !blockList[blockId]->blockOk){
111 d = blockList[blockId]->page[pageOffset];
115 memcpy(data,d,dataLength);
118 memcpy(spare,s,spareLength);
121 *ecc_result = YAFFS_ECC_RESULT_NO_ERROR;
126 static int yramsim_wr_chunk (struct yaffs_dev *dev, int pageId,
127 const u8 *data, int dataLength,
128 const u8 *spare, int spareLength)
130 SimData *sim = DevToSim(dev);
131 Block **blockList = sim->blockList;
133 unsigned blockId = pageId / PAGES_PER_BLOCK;
134 unsigned pageOffset = pageId % PAGES_PER_BLOCK;
137 if(blockId >= sim->nBlocks ||
138 pageOffset >= PAGES_PER_BLOCK ||
139 dataLength >DATA_SIZE ||
140 spareLength > SPARE_SIZE ||
141 !blockList[blockId]->blockOk){
145 d = blockList[blockId]->page[pageOffset];
149 memcpy(d,data,dataLength);
152 memcpy(s,spare,spareLength);
158 static int yramsim_erase(struct yaffs_dev *dev, int blockId)
160 SimData *sim = DevToSim(dev);
163 return yramsim_erase_internal(sim,blockId,0);
166 static int yramsim_check_block_bad(struct yaffs_dev *dev, int blockId)
168 SimData *sim = DevToSim(dev);
169 Block **blockList = sim->blockList;
170 if(blockId >= sim->nBlocks){
174 return blockList[blockId]->blockOk ? YAFFS_OK : YAFFS_FAIL;
177 static int yramsim_mark_block_bad(struct yaffs_dev *dev, int blockId)
179 SimData *sim = DevToSim(dev);
180 Block **blockList = sim->blockList;
181 if(blockId >= sim->nBlocks){
185 blockList[blockId]->blockOk = 0;
191 static SimData *yramsim_alloc_sim_data(u32 devId, u32 nBlocks)
200 if(devId >= N_RAM_SIM_DEVS)
203 sim = simDevs[devId];
208 sim = malloc(sizeof (SimData));
212 simDevs[devId] = sim;
214 blockList = malloc(nBlocks * sizeof(Block *));
216 sim->blockList = blockList;
217 sim->nBlocks = nBlocks;
223 for(i = 0; i < nBlocks; i++)
226 for(i = 0; i < nBlocks && ok; i++){
227 b= malloc(sizeof(Block));
230 yramsim_erase_internal(sim,i,1);
237 for(i = 0; i < nBlocks; i++)
252 struct yaffs_dev *yramsim_CreateRamSim(const YCHAR *name,
253 u32 devId, u32 nBlocks,
254 u32 start_block, u32 end_block)
257 struct yaffs_dev *dev;
258 struct yaffs_param *p;
259 struct yaffs_driver *d;
261 sim = yramsim_alloc_sim_data(devId, nBlocks);
263 dev = malloc(sizeof(*dev));
271 memset(dev, 0, sizeof(*dev));
273 if(start_block >= sim->nBlocks)
275 if(end_block == 0 || end_block >= sim->nBlocks)
276 end_block = sim->nBlocks - 1;
279 p->name = strdup(name);
280 p->start_block = start_block;
281 p->end_block = end_block;
282 p->total_bytes_per_chunk = DATA_SIZE;
283 p->spare_bytes_per_chunk= SPARE_SIZE;
284 p->chunks_per_block = PAGES_PER_BLOCK;
285 p->n_reserved_blocks = 2;
291 d->drv_initialise_fn = yramsim_initialise;
292 d->drv_deinitialise_fn = yramsim_deinitialise;
293 d->drv_read_chunk_fn = yramsim_rd_chunk;
294 d->drv_write_chunk_fn = yramsim_wr_chunk;
295 d->drv_erase_fn = yramsim_erase;
296 d->drv_check_bad_fn = yramsim_check_block_bad;
297 d->drv_mark_bad_fn = yramsim_mark_block_bad;
299 dev->driver_context= (void *)sim;