X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs2.git;a=blobdiff_plain;f=direct%2Fbasic-test%2Fyramsim.c;h=9b50a39a76d517bff8c8414274453a8ddcde7f8f;hp=a791791bb49bfdd221069c31ba6bc179eb6e23b5;hb=5092cb42f05f875154d89639dbd5d6cea573da5f;hpb=4a700fe570d217c2c5df87070db7c2652bc0eaaf diff --git a/direct/basic-test/yramsim.c b/direct/basic-test/yramsim.c index a791791..9b50a39 100644 --- a/direct/basic-test/yramsim.c +++ b/direct/basic-test/yramsim.c @@ -1,277 +1,295 @@ -// NAND Simulator for testing YAFFS - -#include - -#include "yramsim.h" - -#include "yaffs_nandif.h" - - -#ifdef __WINCE__ -#include -#else -#define DebugBreak() do { } while(0) -#endif - - -#define DATA_SIZE 2048 -#define SPARE_SIZE 64 -#define PAGE_SIZE (DATA_SIZE + SPARE_SIZE) -#define PAGES_PER_BLOCK 64 - - -typedef struct { - unsigned char page[PAGES_PER_BLOCK][PAGE_SIZE]; - unsigned blockOk; -} Block; - -typedef struct { - Block **blockList; - int nBlocks; -} SymData; - - -static SymData *DevToSym(yaffs_Device *dev) -{ - ynandif_Geometry *geom = (ynandif_Geometry *)(dev->driverContext); - SymData * sym = (SymData*)(geom->privateData); - return sym; -} - - -static void CheckInitialised(void) -{ - -} - -static int yramsim_EraseBlockInternal(SymData *sym, unsigned blockId,int force) -{ - if(blockId < 0 || blockId >= sym->nBlocks){ - DebugBreak(); - return 0; - } - - if(!sym->blockList[blockId]){ - DebugBreak(); - return 0; - } - - if(!force && !sym->blockList[blockId]->blockOk){ - DebugBreak(); - return 0; - } - - memset(sym->blockList[blockId],0xff,sizeof(Block)); - sym->blockList[blockId]->blockOk = 1; - - return 1; -} - - - - -static int yramsim_Initialise(yaffs_Device *dev) -{ - SymData *sym = DevToSym(dev); - Block **blockList = sym->blockList; - return blockList != NULL; -} - - -static int yramsim_Deinitialise(yaffs_Device *dev) -{ - return 1; -} - -static int yramsim_ReadChunk (yaffs_Device *dev, unsigned pageId, - unsigned char *data, unsigned dataLength, - unsigned char *spare, unsigned spareLength, - int *eccStatus) -{ - SymData *sym = DevToSym(dev); - Block **blockList = sym->blockList; - - unsigned blockId = pageId / PAGES_PER_BLOCK; - unsigned pageOffset = pageId % PAGES_PER_BLOCK; - unsigned char * d; - unsigned char *s; - if(blockId >= sym->nBlocks || - pageOffset >= PAGES_PER_BLOCK || - dataLength >DATA_SIZE || - spareLength > SPARE_SIZE || - !eccStatus || - !blockList[blockId]->blockOk){ - DebugBreak(); - return 0; - } - - d = blockList[blockId]->page[pageOffset]; - s = d + DATA_SIZE; - - if(data) - memcpy(data,d,dataLength); - - if(spare) - memcpy(spare,s,spareLength); - - *eccStatus = 0; // 0 = no error, -1 = unfixable error, 1 = fixable - - return 1; - -} - -static int yramsim_WriteChunk (yaffs_Device *dev,unsigned pageId, - const unsigned char *data, unsigned dataLength, - const unsigned char *spare, unsigned spareLength) -{ - SymData *sym = DevToSym(dev); - Block **blockList = sym->blockList; - - unsigned blockId = pageId / PAGES_PER_BLOCK; - unsigned pageOffset = pageId % PAGES_PER_BLOCK; - unsigned char * d; - unsigned char *s; - if(blockId >= sym->nBlocks || - pageOffset >= PAGES_PER_BLOCK || - dataLength >DATA_SIZE || - spareLength > SPARE_SIZE || - !blockList[blockId]->blockOk){ - DebugBreak(); - return 0; - } - - d = blockList[blockId]->page[pageOffset]; - s = d + DATA_SIZE; - - if(data) - memcpy(d,data,dataLength); - - if(spare) - memcpy(s,spare,spareLength); - - return 1; - -} - - -static int yramsim_EraseBlock(yaffs_Device *dev,unsigned blockId) -{ - SymData *sym = DevToSym(dev); - - CheckInitialised(); - return yramsim_EraseBlockInternal(sym,blockId,0); -} - -static int yramsim_CheckBlockOk(yaffs_Device *dev,unsigned blockId) -{ - SymData *sym = DevToSym(dev); - Block **blockList = sym->blockList; - if(blockId >= sym->nBlocks){ - DebugBreak(); - return 0; - } - - return blockList[blockId]->blockOk ? 1 : 0; -} - -static int yramsim_MarkBlockBad(yaffs_Device *dev,unsigned blockId) -{ - SymData *sym = DevToSym(dev); - Block **blockList = sym->blockList; - if(blockId >= sym->nBlocks){ - DebugBreak(); - return 0; - } - - blockList[blockId]->blockOk = 0; - - return 1; -} - - -static SymData *yramsim_AllocSymData(int nBlocks) -{ - int ok = 1; - - Block **blockList; - SymData *sym; - Block *b; - int i; - - sym = malloc(sizeof (SymData)); - if(!sym) - return NULL; - - blockList = malloc(nBlocks * sizeof(Block *)); - - sym->blockList = blockList; - sym->nBlocks = nBlocks; - if(!blockList){ - free(sym); - return NULL; - } - - for(i = 0; i < nBlocks; i++) - blockList[i] = NULL; - - for(i = 0; i < nBlocks && ok; i++){ - b= malloc(sizeof(Block)); - if(b){ - blockList[i] = b; - yramsim_EraseBlockInternal(sym,i,1); - } - else - ok = 0; - } - - if(!ok){ - for(i = 0; i < nBlocks; i++) - if(blockList[i]){ - free(blockList[i]); - blockList[i] = NULL; - } - free(blockList); - blockList = NULL; - free(sym); - sym = NULL; - } - - return sym; -} - - -struct yaffs_DeviceStruct *yramsim_CreateSim(const YCHAR *name,int nBlocks) -{ - void *sym = (void *)yramsim_AllocSymData(nBlocks); - ynandif_Geometry *g; - - g = YMALLOC(sizeof(ynandif_Geometry)); - - if(!sym || !g){ - if(sym) - YFREE(sym); - if(g) - YFREE(g); - return NULL; - } - - memset(g,0,sizeof(ynandif_Geometry)); - g->startBlock = 0; - g->endBlock = nBlocks - 1; - g->dataSize = DATA_SIZE; - g->spareSize= SPARE_SIZE; - g->pagesPerBlock = PAGES_PER_BLOCK; - g->hasECC = 1; - g->inbandTags = 0; - g->useYaffs2 = 1; - g->initialise = yramsim_Initialise; - g->deinitialise = yramsim_Deinitialise; - g->readChunk = yramsim_ReadChunk, - g->writeChunk = yramsim_WriteChunk, - g->eraseBlock = yramsim_EraseBlock, - g->checkBlockOk = yramsim_CheckBlockOk, - g->markBlockBad = yramsim_MarkBlockBad, - g->privateData = sym; - - return yaffs_AddDeviceFromGeometry(name,g); +/* + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. + * + * Copyright (C) 2002-2010 Aleph One Ltd. + * for Toby Churchill Ltd and Brightstar Engineering + * + * Created by Charles Manning + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* + * NAND Simulator for testing YAFFS + */ + +#include + +#include "yramsim.h" + +#include "yaffs_nandif.h" + + +#define DATA_SIZE 2048 +#define SPARE_SIZE 64 +#define PAGE_SIZE (DATA_SIZE + SPARE_SIZE) +#define PAGES_PER_BLOCK 64 + + +typedef struct { + unsigned char page[PAGES_PER_BLOCK][PAGE_SIZE]; + unsigned blockOk; +} Block; + +typedef struct { + Block **blockList; + int nBlocks; +} SimData; + + +SimData *simDevs[N_RAM_SIM_DEVS]; + +static SimData *DevToSim(struct yaffs_dev *dev) +{ + ynandif_Geometry *geom = (ynandif_Geometry *)(dev->driver_context); + SimData * sim = (SimData*)(geom->privateData); + return sim; +} + + +static void CheckInitialised(void) +{ + +} + +static int yramsim_erase_internal(SimData *sim, unsigned blockId,int force) +{ + if(blockId < 0 || blockId >= sim->nBlocks){ + return 0; + } + + if(!sim->blockList[blockId]){ + return 0; + } + + if(!force && !sim->blockList[blockId]->blockOk){ + return 0; + } + + memset(sim->blockList[blockId],0xff,sizeof(Block)); + sim->blockList[blockId]->blockOk = 1; + + return 1; +} + + + + +static int yramsim_initialise(struct yaffs_dev *dev) +{ + SimData *sim = DevToSim(dev); + Block **blockList = sim->blockList; + return blockList != NULL; +} + + +static int yramsim_deinitialise(struct yaffs_dev *dev) +{ + return 1; +} + +static int yramsim_rd_chunk (struct yaffs_dev *dev, unsigned pageId, + unsigned char *data, unsigned dataLength, + unsigned char *spare, unsigned spareLength, + int *eccStatus) +{ + SimData *sim = DevToSim(dev); + Block **blockList = sim->blockList; + + unsigned blockId = pageId / PAGES_PER_BLOCK; + unsigned pageOffset = pageId % PAGES_PER_BLOCK; + unsigned char * d; + unsigned char *s; + if(blockId >= sim->nBlocks || + pageOffset >= PAGES_PER_BLOCK || + dataLength >DATA_SIZE || + spareLength > SPARE_SIZE || + !eccStatus || + !blockList[blockId]->blockOk){ + return 0; + } + + d = blockList[blockId]->page[pageOffset]; + s = d + DATA_SIZE; + + if(data) + memcpy(data,d,dataLength); + + if(spare) + memcpy(spare,s,spareLength); + + *eccStatus = 0; // 0 = no error, -1 = unfixable error, 1 = fixable + + return 1; +} + +static int yramsim_wr_chunk (struct yaffs_dev *dev,unsigned pageId, + const unsigned char *data, unsigned dataLength, + const unsigned char *spare, unsigned spareLength) +{ + SimData *sim = DevToSim(dev); + Block **blockList = sim->blockList; + + unsigned blockId = pageId / PAGES_PER_BLOCK; + unsigned pageOffset = pageId % PAGES_PER_BLOCK; + unsigned char * d; + unsigned char *s; + if(blockId >= sim->nBlocks || + pageOffset >= PAGES_PER_BLOCK || + dataLength >DATA_SIZE || + spareLength > SPARE_SIZE || + !blockList[blockId]->blockOk){ + return 0; + } + + d = blockList[blockId]->page[pageOffset]; + s = d + DATA_SIZE; + + if(data) + memcpy(d,data,dataLength); + + if(spare) + memcpy(s,spare,spareLength); + + return 1; +} + + +static int yramsim_erase(struct yaffs_dev *dev,unsigned blockId) +{ + SimData *sim = DevToSim(dev); + + CheckInitialised(); + return yramsim_erase_internal(sim,blockId,0); +} + +static int yramsim_check_block_ok(struct yaffs_dev *dev,unsigned blockId) +{ + SimData *sim = DevToSim(dev); + Block **blockList = sim->blockList; + if(blockId >= sim->nBlocks){ + return 0; + } + + return blockList[blockId]->blockOk ? 1 : 0; +} + +static int yramsim_mark_block_bad(struct yaffs_dev *dev,unsigned blockId) +{ + SimData *sim = DevToSim(dev); + Block **blockList = sim->blockList; + if(blockId >= sim->nBlocks){ + return 0; + } + + blockList[blockId]->blockOk = 0; + + return 1; +} + + +static SimData *yramsim_alloc_sim_data(u32 devId, u32 nBlocks) +{ + int ok = 1; + + Block **blockList; + SimData *sim; + Block *b; + u32 i; + + if(devId >= N_RAM_SIM_DEVS) + return NULL; + + sim = simDevs[devId]; + + if(sim) + return sim; + + sim = malloc(sizeof (SimData)); + if(!sim) + return NULL; + + simDevs[devId] = sim; + + blockList = malloc(nBlocks * sizeof(Block *)); + + sim->blockList = blockList; + sim->nBlocks = nBlocks; + if(!blockList){ + free(sim); + return NULL; + } + + for(i = 0; i < nBlocks; i++) + blockList[i] = NULL; + + for(i = 0; i < nBlocks && ok; i++){ + b= malloc(sizeof(Block)); + if(b){ + blockList[i] = b; + yramsim_erase_internal(sim,i,1); + } + else + ok = 0; + } + + if(!ok){ + for(i = 0; i < nBlocks; i++) + if(blockList[i]){ + free(blockList[i]); + blockList[i] = NULL; + } + free(blockList); + blockList = NULL; + free(sim); + sim = NULL; + } + + return sim; +} + + +struct yaffs_dev *yramsim_CreateRamSim(const YCHAR *name, + u32 devId, u32 nBlocks, + u32 start_block, u32 end_block) +{ + SimData *sim; + ynandif_Geometry *g; + + sim = yramsim_alloc_sim_data(devId, nBlocks); + + g = YMALLOC(sizeof(ynandif_Geometry)); + + if(!sim || !g){ + if(g) + YFREE(g); + return NULL; + } + + if(start_block >= sim->nBlocks) + start_block = 0; + if(end_block == 0 || end_block >= sim->nBlocks) + end_block = sim->nBlocks - 1; + + memset(g,0,sizeof(ynandif_Geometry)); + g->start_block = start_block; + g->end_block = end_block; + g->dataSize = DATA_SIZE; + g->spareSize= SPARE_SIZE; + g->pagesPerBlock = PAGES_PER_BLOCK; + g->hasECC = 1; + g->inband_tags = 0; + g->useYaffs2 = 1; + g->initialise = yramsim_initialise; + g->deinitialise = yramsim_deinitialise; + g->readChunk = yramsim_rd_chunk, + g->writeChunk = yramsim_wr_chunk, + g->eraseBlock = yramsim_erase, + g->checkBlockOk = yramsim_check_block_ok, + g->markBlockBad = yramsim_mark_block_bad, + g->privateData = (void *)sim; + + return yaffs_add_dev_from_geometry(name,g); }