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