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_flashif_c_version = "$Id: yaffs_flashif.c,v 1.1 2004/11/03 08:29:28 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_flashif.h" 2540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include "yaffs_guts.h" 2640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include "devextras.h" 2740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 2840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 2940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#define SIZE_IN_MB 16 3040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 3140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#define BLOCK_SIZE (32 * 528) 3240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#define BLOCKS_PER_MEG ((1024*1024)/(32 * 512)) 3340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 3440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 3540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 3640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projecttypedef struct 3740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{ 3840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project __u8 data[528]; // Data + spare 3940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project} yflash_Page; 4040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 4140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projecttypedef struct 4240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{ 4340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project yflash_Page page[32]; // The pages in the block 4440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 4540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project} yflash_Block; 4640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 4740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 4840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 4940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projecttypedef struct 5040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{ 5140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project yflash_Block **block; 5240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project int nBlocks; 5340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project} yflash_Device; 5440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 5540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic yflash_Device ramdisk; 5640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 5740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int CheckInit(yaffs_Device *dev) 5840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{ 5940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project static int initialised = 0; 6040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 6140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project int i; 6240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project int fail = 0; 6340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project int nAllocated = 0; 6440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 6540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(initialised) 6640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project { 6740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return YAFFS_OK; 6840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 6940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 7040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project initialised = 1; 7140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 7240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 7340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project ramdisk.nBlocks = (SIZE_IN_MB * 1024 * 1024)/(16 * 1024); 7440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 7540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project ramdisk.block = YMALLOC(sizeof(yflash_Block *) * ramdisk.nBlocks); 7640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 7740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(!ramdisk.block) return 0; 7840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 7940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project for(i=0; i <ramdisk.nBlocks; i++) 8040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project { 8140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project ramdisk.block[i] = NULL; 8240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 8340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 8440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project for(i=0; i <ramdisk.nBlocks && !fail; i++) 8540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project { 8640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if((ramdisk.block[i] = YMALLOC(sizeof(yflash_Block))) == 0) 8740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project { 8840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project fail = 1; 8940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 9040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project else 9140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project { 9240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project yflash_EraseBlockInNAND(dev,i); 9340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project nAllocated++; 9440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 9540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 9640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 9740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(fail) 9840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project { 9940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project for(i = 0; i < nAllocated; i++) 10040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project { 10140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project YFREE(ramdisk.block[i]); 10240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 10340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project YFREE(ramdisk.block); 10440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 10540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project T(YAFFS_TRACE_ALWAYS,("Allocation failed, could only allocate %dMB of %dMB requested.\n", 10640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project nAllocated/64,ramdisk.nBlocks * YAFFS_BYTES_PER_BLOCK)); 10740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return 0; 10840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 10940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 11040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 11140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 11240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return 1; 11340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project} 11440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 11540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yflash_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, yaffs_ExtendedTags *tags) 11640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{ 11740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project int blk; 11840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project int pg; 11940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 12040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 12140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project CheckInit(dev); 12240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 12340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project blk = chunkInNAND/32; 12440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project pg = chunkInNAND%32; 12540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 12640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 12740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(data) 12840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project { 12940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project memcpy(ramdisk.block[blk]->page[pg].data,data,512); 13040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 13140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 13240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 13340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(tags) 13440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project { 13540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project yaffs_PackedTags pt; 13640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project yaffs_PackTags(&pt,tags); 13740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project memcpy(&ramdisk.block[blk]->page[pg].data[512],&pt,sizeof(pt)); 13840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 13940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 14040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return YAFFS_OK; 14140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 14240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project} 14340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 14440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 14540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yflash_ReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_Tags *tags) 14640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{ 14740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project int blk; 14840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project int pg; 14940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 15040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 15140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project CheckInit(dev); 15240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 15340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project blk = chunkInNAND/32; 15440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project pg = chunkInNAND%32; 15540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 15640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 15740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(data) 15840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project { 15940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project memcpy(data,ramdisk.block[blk]->page[pg].data,512); 16040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 16140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 16240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 16340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(tags) 16440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project { 16540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project yaffs_PackedTags pt; 16640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project memcpy(&pt,&ramdisk.block[blk]->page[pg].data[512],sizeof(yaffs_PackedTags)); 16740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project yaffs_UnpackTags(tags,&pt); 16840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 16940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 17040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return YAFFS_OK; 17140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project} 17240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 17340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 17440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yflash_CheckChunkErased(yaffs_Device *dev,int chunkInNAND) 17540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{ 17640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project int blk; 17740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project int pg; 17840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project int i; 17940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 18040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 18140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project CheckInit(dev); 18240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 18340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project blk = chunkInNAND/32; 18440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project pg = chunkInNAND%32; 18540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 18640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 18740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project for(i = 0; i < 528; i++) 18840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project { 18940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(ramdisk.block[blk]->page[pg].data[i] != 0xFF) 19040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project { 19140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return YAFFS_FAIL; 19240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 19340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 19440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 19540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return YAFFS_OK; 19640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 19740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project} 19840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 19940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yflash_EraseBlockInNAND(yaffs_Device *dev, int blockNumber) 20040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{ 20140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 20240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project CheckInit(dev); 20340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 20440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(blockNumber < 0 || blockNumber >= ramdisk.nBlocks) 20540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project { 20640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project T(YAFFS_TRACE_ALWAYS,("Attempt to erase non-existant block %d\n",blockNumber)); 20740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return YAFFS_FAIL; 20840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 20940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project else 21040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project { 21140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project memset(ramdisk.block[blockNumber],0xFF,sizeof(yflash_Block)); 21240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return YAFFS_OK; 21340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 21440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 21540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project} 21640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 21740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yflash_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo) 21840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{ 21940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return YAFFS_OK; 22040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 22140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project} 22240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yflash_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, yaffs_BlockState *state, int *sequenceNumber) 22340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{ 22440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *state = YAFFS_BLOCK_STATE_EMPTY; 22540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *sequenceNumber = 0; 22640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project} 22740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 22840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 22940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yflash_InitialiseNAND(yaffs_Device *dev) 23040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{ 23140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return YAFFS_OK; 23240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project} 23340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 234