package yaffs2.port.emulation; import yaffs2.port.Guts_H; import yaffs2.port.yaffs_Device; import yaffs2.port.yaffs_ExtendedTags; import yaffs2.port.yaffs_PackedTags1; import yaffs2.port.yaffs_packedtags1_C; import yaffs2.port.ydirectenv; import yaffs2.port.yportenv; import yaffs2.port.yaffs_Device.eraseBlockInNANDInterface; import yaffs2.port.yaffs_Device.initialiseNANDInterface; import yaffs2.port.yaffs_Device.readChunkWithTagsFromNANDInterface; import yaffs2.port.yaffs_Device.writeChunkWithTagsToNANDInterface; import yaffs2.utils.*; import yaffs2.utils.factory.PrimitiveWrapperFactory; public class yaffs_ramdisk_C implements yaffs_Device.writeChunkWithTagsToNANDInterface, yaffs_Device.readChunkWithTagsFromNANDInterface, yaffs_Device.eraseBlockInNANDInterface, yaffs_Device.initialiseNANDInterface { // PORT public static final yaffs_ramdisk_C instance = new yaffs_ramdisk_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_ramdisk.c: yaffs ram disk component // * This provides a ram disk under yaffs. // * NB this is not intended for NAND emulation. // * Use this with dev->useNANDECC enabled, then ECC overheads are not required. // */ // // const char *yaffs_ramdisk_c_version = "$Id: yaffs_ramdisk_C.java,v 1.1 2007/09/24 13:31:33 peter.hilber Exp $"; // // // #include "yportenv.h" // // #include "yaffs_ramdisk.h" // #include "yaffs_guts.h" // #include "devextras.h" // #include "yaffs_packedtags1.h" /*#define*/static final int SIZE_IN_MB = 2; /*#define*/static final int BLOCK_SIZE = (32 * 528); //16896 /*#define*/static final int BLOCKS_PER_MEG = ((1024*1024)/(32 * 512)); //64 static yramdisk_Device ramdisk; static int _STATIC_LOCAL_CheckInit_initialised = 0; static boolean CheckInit(yaffs_Device dev) { // static int initialised = 0; int i; int fail = 0; //int nBlocks; int nAllocated = 0; if(_STATIC_LOCAL_CheckInit_initialised != 0) { return Guts_H.YAFFS_OK; } _STATIC_LOCAL_CheckInit_initialised = 1; ramdisk.set_nBlocks((SIZE_IN_MB * 1024 * 1024)/(16 * 1024)); ramdisk.set_block(); //ramdisk.block = YMALLOC(sizeof(yramdisk_Block *) * ramdisk.nBlocks); yramdisk_BlockPointer blockPointer = new yramdisk_BlockPointer(ramdisk.block[0]); // XXX // ramdisk.block = blockPointer.dereferenced; if(!(ramdisk.block != null)) return false; for(i=0; i <ramdisk.nBlocks; i++) { ramdisk.block[i] = null; } for(i=0; i <ramdisk.nBlocks && !(fail != 0); i++) { if((ramdisk.block[i] = new yramdisk_Block()) == null) { fail = 1; } else { /*yramdisk_*/ instance.eraseBlockInNAND(dev,i); nAllocated++; } } if(fail != 0) { for(i = 0; i < nAllocated; i++) { ydirectenv.YFREE(ramdisk.block[i]); } ydirectenv.YFREE(/*ramdisk.block*/blockPointer.dereferenced); // XXX ??? yportenv.T(yportenv.YAFFS_TRACE_ALWAYS,"Allocation failed, could only allocate %dMB of %dMB requested.\n", PrimitiveWrapperFactory.get(nAllocated/64),PrimitiveWrapperFactory.get(ramdisk.nBlocks * 528)); return false; } return true; } public boolean /*yramdisk_*/ writeChunkWithTagsToNAND(yaffs_Device dev,int chunkInNAND,/*const __u8 **/byte[] data,int dataIndex, yaffs_ExtendedTags tags) { int blk; int pg; CheckInit(dev); blk = chunkInNAND/32; pg = chunkInNAND%32; if(data != null) { Unix.memcpy(ramdisk.block[blk].page[pg].data,0,data,dataIndex,512); } if(tags != null) { yaffs_PackedTags1 pt = new yaffs_PackedTags1(); yaffs_packedtags1_C.yaffs_PackTags1(pt,tags); // made it a static method Unix.memcpy(ramdisk.block[blk].page[pg].data,512,pt.serialized,pt.offset,/*sizeof(*/pt.SERIALIZED_LENGTH/*)*/); } return Guts_H.YAFFS_OK; } public boolean /*yramdisk_*/ readChunkWithTagsFromNAND(yaffs_Device dev,int chunkInNAND, /*__u8 **/byte[] data, int dataIndex, yaffs_ExtendedTags tags) { int blk; int pg; CheckInit(dev); blk = chunkInNAND/32; pg = chunkInNAND%32; if(data != null) { Unix.memcpy(data,dataIndex,ramdisk.block[blk].page[pg].data,0,512); } if(tags != null) { yaffs_PackedTags1 pt = new yaffs_PackedTags1(); Unix.memcpy(pt.serialized,pt.offset,ramdisk.block[blk].page[pg].data,512,/*sizeof(*/pt.SERIALIZED_LENGTH/*)*/); yaffs_packedtags1_C.yaffs_UnpackTags1(tags,pt); } return Guts_H.YAFFS_OK; } static boolean yramdisk_CheckChunkErased(yaffs_Device dev,int chunkInNAND) { int blk; int pg; int i; CheckInit(dev); blk = chunkInNAND/32; pg = chunkInNAND%32; for(i = 0; i < 528; i++) { if(ramdisk.block[blk].page[pg].data[i] != 0xFF) { return Guts_H.YAFFS_FAIL; } } return Guts_H.YAFFS_OK; } public boolean /*yramdisk_*/ eraseBlockInNAND(yaffs_Device dev, int blockNumber) { CheckInit(dev); if(blockNumber < 0 || blockNumber >= ramdisk.nBlocks) { yportenv.T(yportenv.YAFFS_TRACE_ALWAYS,"Attempt to erase non-existant block %d\n",PrimitiveWrapperFactory.get(blockNumber)); return Guts_H.YAFFS_FAIL; } else { yaffs2.utils.emulation.RamEmulationUnix.memset(ramdisk.block[blockNumber],(byte)0xFF/*,sizeof(yramdisk_Block*)*/); return Guts_H.YAFFS_OK; } } public boolean /*yramdisk_*/ initialiseNAND(yaffs_Device dev) { //dev->useNANDECC = 1; // force on useNANDECC which gets faked. // This saves us doing ECC checks. return Guts_H.YAFFS_OK; } }