140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/* 240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * YAFFS: Yet another FFS. A NAND-flash specific file system. 340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * yaffs_ramdisk.c: yaffs ram disk component 440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * 540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * Copyright (C) 2002 Aleph One Ltd. 640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * 740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * Created by Charles Manning <charles@aleph1.co.uk> 840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * 940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * This program is free software; you can redistribute it and/or modify 1040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * it under the terms of the GNU General Public License version 2 as 1140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * published by the Free Software Foundation. 1240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * 1340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */ 1440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 1540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project// This provides a rma disk under yaffs. 1640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project// NB this is not intended for NAND emulation. 1740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project// Use this with dev->useNANDECC enabled, then ECC overheads are not required. 1840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 1940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectconst char *yaffs_ramdisk_c_version = "$Id: yaffs_ramdisk.c,v 1.2 2004/11/22 03:22:25 charles Exp $"; 2040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 2140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 2240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include "yportenv.h" 2340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 2440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include "yaffs_ramdisk.h" 2540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include "yaffs_guts.h" 2640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include "devextras.h" 2740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include "yaffs_packedtags1.h" 2840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 2940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 3040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 3140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#define SIZE_IN_MB 2 3240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 3340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#define BLOCK_SIZE (32 * 528) 3440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#define BLOCKS_PER_MEG ((1024*1024)/(32 * 512)) 3540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 3640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 3740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 3840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 3940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 4040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projecttypedef struct 4140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{ 4240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project __u8 data[528]; // Data + spare 4340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project} yramdisk_Page; 4440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 4540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projecttypedef struct 4640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{ 4740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project yramdisk_Page page[32]; // The pages in the block 4840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 4940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project} yramdisk_Block; 5040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 5140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 5240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 5340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projecttypedef struct 5440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{ 5540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project yramdisk_Block **block; 5640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project int nBlocks; 5740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project} yramdisk_Device; 5840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 5940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic yramdisk_Device ramdisk; 6040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 6140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int CheckInit(yaffs_Device *dev) 6240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{ 6340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project static int initialised = 0; 6440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 6540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project int i; 6640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project int fail = 0; 6740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project //int nBlocks; 6840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project int nAllocated = 0; 6940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 7040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(initialised) 7140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project { 7240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return YAFFS_OK; 7340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 7440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 7540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project initialised = 1; 7640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 7740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 7840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project ramdisk.nBlocks = (SIZE_IN_MB * 1024 * 1024)/(16 * 1024); 7940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 8040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project ramdisk.block = YMALLOC(sizeof(yramdisk_Block *) * ramdisk.nBlocks); 8140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 8240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(!ramdisk.block) return 0; 8340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 8440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project for(i=0; i <ramdisk.nBlocks; i++) 8540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project { 8640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project ramdisk.block[i] = NULL; 8740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 8840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 8940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project for(i=0; i <ramdisk.nBlocks && !fail; i++) 9040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project { 9140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if((ramdisk.block[i] = YMALLOC(sizeof(yramdisk_Block))) == 0) 9240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project { 9340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project fail = 1; 9440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 9540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project else 9640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project { 9740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project yramdisk_EraseBlockInNAND(dev,i); 9840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project nAllocated++; 9940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 10040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 10140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 10240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(fail) 10340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project { 10440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project for(i = 0; i < nAllocated; i++) 10540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project { 10640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project YFREE(ramdisk.block[i]); 10740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 10840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project YFREE(ramdisk.block); 10940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 11040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project T(YAFFS_TRACE_ALWAYS,("Allocation failed, could only allocate %dMB of %dMB requested.\n", 11140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project nAllocated/64,ramdisk.nBlocks * 528)); 11240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return 0; 11340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 11440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 11540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 11640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return 1; 11740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project} 11840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 11940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yramdisk_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, yaffs_ExtendedTags *tags) 12040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{ 12140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project int blk; 12240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project int pg; 12340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 12440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 12540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project CheckInit(dev); 12640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 12740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project blk = chunkInNAND/32; 12840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project pg = chunkInNAND%32; 12940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 13040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 13140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(data) 13240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project { 13340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project memcpy(ramdisk.block[blk]->page[pg].data,data,512); 13440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 13540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 13640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 13740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(tags) 13840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project { 13940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project yaffs_PackedTags1 pt; 14040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 14140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project yaffs_PackTags1(&pt,tags); 14240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project memcpy(&ramdisk.block[blk]->page[pg].data[512],&pt,sizeof(pt)); 14340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 14440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 14540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return YAFFS_OK; 14640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 14740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project} 14840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 14940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 15040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yramdisk_ReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_ExtendedTags *tags) 15140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{ 15240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project int blk; 15340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project int pg; 15440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 15540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 15640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project CheckInit(dev); 15740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 15840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project blk = chunkInNAND/32; 15940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project pg = chunkInNAND%32; 16040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 16140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 16240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(data) 16340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project { 16440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project memcpy(data,ramdisk.block[blk]->page[pg].data,512); 16540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 16640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 16740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 16840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(tags) 16940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project { 17040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project yaffs_PackedTags1 pt; 17140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 17240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project memcpy(&pt,&ramdisk.block[blk]->page[pg].data[512],sizeof(pt)); 17340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project yaffs_UnpackTags1(tags,&pt); 17440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 17540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 17640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 17740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return YAFFS_OK; 17840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project} 17940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 18040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 18140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yramdisk_CheckChunkErased(yaffs_Device *dev,int chunkInNAND) 18240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{ 18340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project int blk; 18440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project int pg; 18540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project int i; 18640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 18740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 18840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project CheckInit(dev); 18940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 19040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project blk = chunkInNAND/32; 19140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project pg = chunkInNAND%32; 19240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 19340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 19440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project for(i = 0; i < 528; i++) 19540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project { 19640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(ramdisk.block[blk]->page[pg].data[i] != 0xFF) 19740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project { 19840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return YAFFS_FAIL; 19940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 20040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 20140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 20240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return YAFFS_OK; 20340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 20440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project} 20540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 20640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yramdisk_EraseBlockInNAND(yaffs_Device *dev, int blockNumber) 20740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{ 20840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 20940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project CheckInit(dev); 21040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 21140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(blockNumber < 0 || blockNumber >= ramdisk.nBlocks) 21240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project { 21340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project T(YAFFS_TRACE_ALWAYS,("Attempt to erase non-existant block %d\n",blockNumber)); 21440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return YAFFS_FAIL; 21540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 21640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project else 21740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project { 21840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project memset(ramdisk.block[blockNumber],0xFF,sizeof(yramdisk_Block)); 21940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return YAFFS_OK; 22040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 22140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 22240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project} 22340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 22440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yramdisk_InitialiseNAND(yaffs_Device *dev) 22540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{ 22640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project //dev->useNANDECC = 1; // force on useNANDECC which gets faked. 22740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project // This saves us doing ECC checks. 22840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 22940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return YAFFS_OK; 23040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project} 23140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 23240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 233