📄 yaffs_ramem2k.c
字号:
/* * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. * * Copyright (C) 2002-2007 Aleph One Ltd. * for Toby Churchill Ltd and Brightstar Engineering * * Created by Charles Manning <charles@aleph1.co.uk> * * 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. *//* * yaffs_ramem2k.c: RAM emulation in-kernel for 2K pages (YAFFS2) */const char *yaffs_ramem2k_c_version = "$Id: yaffs_ramem2k.c,v 1.4 2008/05/05 07:58:58 charles Exp $";#ifndef __KERNEL__#define CONFIG_YAFFS_RAM_ENABLED#else#include <linux/config.h>#endif#ifdef CONFIG_YAFFS_RAM_ENABLED#include "yportenv.h"#include "yaffs_nandemul2k.h"#include "yaffs_guts.h"#include "yaffsinterface.h"#include "devextras.h"#include "yaffs_packedtags2.h"#define EM_SIZE_IN_MEG (32)#define PAGE_DATA_SIZE (2048)#define PAGE_SPARE_SIZE (64)#define PAGES_PER_BLOCK (64)#define EM_SIZE_IN_BYTES (EM_SIZE_IN_MEG * (1<<20))#define PAGE_TOTAL_SIZE (PAGE_DATA_SIZE+PAGE_SPARE_SIZE)#define BLOCK_TOTAL_SIZE (PAGES_PER_BLOCK * PAGE_TOTAL_SIZE)#define BLOCKS_PER_MEG ((1<<20)/(PAGES_PER_BLOCK * PAGE_DATA_SIZE))typedef struct { __u8 data[PAGE_TOTAL_SIZE]; // Data + spare int empty; // is this empty?} nandemul_Page;typedef struct{ nandemul_Page *page[PAGES_PER_BLOCK]; int damaged; } nandemul_Block;typedef struct{ nandemul_Block**block; int nBlocks;} nandemul_Device;static nandemul_Device ned;static int sizeInMB = EM_SIZE_IN_MEG;static void nandemul_yield(int n){#ifdef __KERNEL__ if(n > 0) schedule_timeout(n);#endif}static void nandemul_ReallyEraseBlock(int blockNumber){ int i; nandemul_Block *blk; if(blockNumber < 0 || blockNumber >= ned.nBlocks) { return; } blk = ned.block[blockNumber]; for(i = 0; i < PAGES_PER_BLOCK; i++) { memset(blk->page[i],0xff,sizeof(nandemul_Page)); blk->page[i]->empty = 1; } nandemul_yield(2);}static int nandemul2k_CalcNBlocks(void){ return EM_SIZE_IN_MEG * BLOCKS_PER_MEG;}static int CheckInit(void){ static int initialised = 0; int i,j; int fail = 0; int nBlocks; int nAllocated = 0; if(initialised) { return YAFFS_OK; } ned.nBlocks = nBlocks = nandemul2k_CalcNBlocks(); ned.block = YMALLOC(sizeof(nandemul_Block*) * nBlocks ); if(!ned.block) return YAFFS_FAIL; for(i=fail=0; i <nBlocks; i++) { nandemul_Block *blk; if(!(blk = ned.block[i] = YMALLOC(sizeof(nandemul_Block)))) { fail = 1; } else { for(j = 0; j < PAGES_PER_BLOCK; j++) { if((blk->page[j] = YMALLOC(sizeof(nandemul_Page))) == 0) { fail = 1; } } nandemul_ReallyEraseBlock(i); ned.block[i]->damaged = 0; nAllocated++; } } if(fail) { //Todo thump pages for(i = 0; i < nAllocated; i++) { YFREE(ned.block[i]); } YFREE(ned.block); T(YAFFS_TRACE_ALWAYS,("Allocation failed, could only allocate %dMB of %dMB requested.\n", nAllocated/64,sizeInMB)); return 0; } ned.nBlocks = nBlocks; initialised = 1; return 1;}int nandemul2k_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_ExtendedTags *tags){ int blk; int pg; int i; __u8 *x; blk = chunkInNAND/PAGES_PER_BLOCK; pg = chunkInNAND%PAGES_PER_BLOCK; if(data) { x = ned.block[blk]->page[pg]->data; for(i = 0; i < PAGE_DATA_SIZE; i++) { x[i] &=data[i]; } ned.block[blk]->page[pg]->empty = 0; } if(tags) { x = &ned.block[blk]->page[pg]->data[PAGE_DATA_SIZE]; yaffs_PackTags2((yaffs_PackedTags2 *)x,tags); } if(tags || data) { nandemul_yield(1); } return YAFFS_OK;}int nandemul2k_ReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_ExtendedTags *tags){ int blk; int pg; __u8 *x; blk = chunkInNAND/PAGES_PER_BLOCK; pg = chunkInNAND%PAGES_PER_BLOCK; if(data) { memcpy(data,ned.block[blk]->page[pg]->data,PAGE_DATA_SIZE); } if(tags) { x = &ned.block[blk]->page[pg]->data[PAGE_DATA_SIZE]; yaffs_UnpackTags2(tags,(yaffs_PackedTags2 *)x); } return YAFFS_OK;}static int nandemul2k_CheckChunkErased(yaffs_Device *dev,int chunkInNAND){ int blk; int pg; int i; blk = chunkInNAND/PAGES_PER_BLOCK; pg = chunkInNAND%PAGES_PER_BLOCK; for(i = 0; i < PAGE_TOTAL_SIZE; i++) { if(ned.block[blk]->page[pg]->data[i] != 0xFF) { return YAFFS_FAIL; } } return YAFFS_OK;}int nandemul2k_EraseBlockInNAND(yaffs_Device *dev, int blockNumber){ if(blockNumber < 0 || blockNumber >= ned.nBlocks) { T(YAFFS_TRACE_ALWAYS,("Attempt to erase non-existant block %d\n",blockNumber)); } else if(ned.block[blockNumber]->damaged) { T(YAFFS_TRACE_ALWAYS,("Attempt to erase damaged block %d\n",blockNumber)); } else { nandemul_ReallyEraseBlock(blockNumber); } return YAFFS_OK;}int nandemul2k_InitialiseNAND(yaffs_Device *dev){ CheckInit(); return YAFFS_OK;} int nandemul2k_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo){ __u8 *x; x = &ned.block[blockNo]->page[0]->data[PAGE_DATA_SIZE]; memset(x,0,sizeof(yaffs_PackedTags2)); return YAFFS_OK; }int nandemul2k_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, yaffs_BlockState *state, __u32 *sequenceNumber){ yaffs_ExtendedTags tags; int chunkNo; *sequenceNumber = 0; chunkNo = blockNo * dev->nChunksPerBlock; nandemul2k_ReadChunkWithTagsFromNAND(dev,chunkNo,NULL,&tags); if(tags.blockBad) { *state = YAFFS_BLOCK_STATE_DEAD; } else if(!tags.chunkUsed) { *state = YAFFS_BLOCK_STATE_EMPTY; } else if(tags.chunkUsed) { *state = YAFFS_BLOCK_STATE_NEEDS_SCANNING; *sequenceNumber = tags.sequenceNumber; } return YAFFS_OK;}int nandemul2k_GetBytesPerChunk(void) { return PAGE_DATA_SIZE;}int nandemul2k_GetChunksPerBlock(void) { return PAGES_PER_BLOCK; }int nandemul2k_GetNumberOfBlocks(void) {return nandemul2k_CalcNBlocks();}#endif //YAFFS_RAM_ENABLED
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -