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