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_ramem.c  NAND emulation on top of a chunk of RAM
440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *
540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * Copyright (C) 2002 Aleph One Ltd.
640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *   for Toby Churchill Ltd and Brightstar Engineering
740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *
840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * Created by Charles Manning <charles@aleph1.co.uk>
940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *
1040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * This program is free software; you can redistribute it and/or modify
1140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * it under the terms of the GNU General Public License version 2 as
1240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * published by the Free Software Foundation.
1340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *
1440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
1540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project //yaffs_ramem2k.c: RAM emulation in-kernel for 2K pages (YAFFS2)
1640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
1740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
1840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectconst char *yaffs_ramem2k_c_version = "$Id: yaffs_ramem2k.c,v 1.1 2005/08/09 01:00:37 charles Exp $";
1940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
2040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifndef __KERNEL__
2140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#define CONFIG_YAFFS_RAM_ENABLED
2240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#else
2340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include <linux/config.h>
2440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
2540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
2640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef CONFIG_YAFFS_RAM_ENABLED
2740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
2840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include "yportenv.h"
2940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
3040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include "yaffs_nandemul2k.h"
3140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include "yaffs_guts.h"
3240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include "yaffsinterface.h"
3340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include "devextras.h"
3440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include "yaffs_packedtags2.h"
3540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
3640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
3740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
3840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#define EM_SIZE_IN_MEG (32)
3940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#define PAGE_DATA_SIZE  (2048)
4040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#define PAGE_SPARE_SIZE (64)
4140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#define PAGES_PER_BLOCK (64)
4240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
4340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
4440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
4540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#define EM_SIZE_IN_BYTES (EM_SIZE_IN_MEG * (1<<20))
4640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
4740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#define PAGE_TOTAL_SIZE (PAGE_DATA_SIZE+PAGE_SPARE_SIZE)
4840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
4940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#define BLOCK_TOTAL_SIZE (PAGES_PER_BLOCK * PAGE_TOTAL_SIZE)
5040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
5140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#define BLOCKS_PER_MEG ((1<<20)/(PAGES_PER_BLOCK * PAGE_DATA_SIZE))
5240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
5340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
5440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projecttypedef struct
5540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
5640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	__u8 data[PAGE_TOTAL_SIZE]; // Data + spare
5740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int empty;      // is this empty?
5840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project} nandemul_Page;
5940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
6040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
6140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projecttypedef struct
6240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
6340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	nandemul_Page *page[PAGES_PER_BLOCK];
6440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int damaged;
6540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project} nandemul_Block;
6640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
6740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
6840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
6940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projecttypedef struct
7040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
7140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	nandemul_Block**block;
7240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int nBlocks;
7340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project} nandemul_Device;
7440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
7540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic nandemul_Device ned;
7640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
7740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int sizeInMB = EM_SIZE_IN_MEG;
7840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
7940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
8040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void nandemul_yield(int n)
8140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
8240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef __KERNEL__
8340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(n > 0) schedule_timeout(n);
8440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
8540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
8640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
8740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
8840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
8940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void nandemul_ReallyEraseBlock(int blockNumber)
9040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
9140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int i;
9240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
9340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	nandemul_Block *blk;
9440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
9540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(blockNumber < 0 || blockNumber >= ned.nBlocks)
9640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	{
9740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return;
9840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
9940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
10040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	blk = ned.block[blockNumber];
10140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
10240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	for(i = 0; i < PAGES_PER_BLOCK; i++)
10340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	{
10440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		memset(blk->page[i],0xff,sizeof(nandemul_Page));
10540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		blk->page[i]->empty = 1;
10640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
10740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	nandemul_yield(2);
10840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
10940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
11040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
11140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int nandemul2k_CalcNBlocks(void)
11240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
11340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return EM_SIZE_IN_MEG * BLOCKS_PER_MEG;
11440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
11540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
11640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
11740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
11840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int  CheckInit(void)
11940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
12040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	static int initialised = 0;
12140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
12240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int i,j;
12340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
12440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int fail = 0;
12540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int nBlocks;
12640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
12740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int nAllocated = 0;
12840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
12940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(initialised)
13040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	{
13140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return YAFFS_OK;
13240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
13340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
13440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
13540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	ned.nBlocks = nBlocks = nandemul2k_CalcNBlocks();
13640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
13740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
13840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	ned.block = YMALLOC(sizeof(nandemul_Block*) * nBlocks );
13940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
14040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(!ned.block) return YAFFS_FAIL;
14140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
14240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
14340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
14440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
14540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
14640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	for(i=fail=0; i <nBlocks; i++)
14740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	{
14840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
14940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		nandemul_Block *blk;
15040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
15140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if(!(blk = ned.block[i] = YMALLOC(sizeof(nandemul_Block))))
15240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		{
15340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 fail = 1;
15440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
15540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		else
15640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		{
15740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			for(j = 0; j < PAGES_PER_BLOCK; j++)
15840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			{
15940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				if((blk->page[j] = YMALLOC(sizeof(nandemul_Page))) == 0)
16040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				{
16140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					fail = 1;
16240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				}
16340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
16440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			nandemul_ReallyEraseBlock(i);
16540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			ned.block[i]->damaged = 0;
16640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			nAllocated++;
16740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
16840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
16940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
17040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(fail)
17140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	{
17240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		//Todo thump pages
17340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
17440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		for(i = 0; i < nAllocated; i++)
17540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		{
17640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			YFREE(ned.block[i]);
17740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
17840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		YFREE(ned.block);
17940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
18040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(YAFFS_TRACE_ALWAYS,("Allocation failed, could only allocate %dMB of %dMB requested.\n",
18140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		   nAllocated/64,sizeInMB));
18240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return 0;
18340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
18440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
18540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	ned.nBlocks = nBlocks;
18640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
18740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	initialised = 1;
18840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
18940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return 1;
19040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
19140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
19240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint nandemul2k_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, yaffs_ExtendedTags *tags)
19340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
19440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int blk;
19540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int pg;
19640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int i;
19740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
19840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	__u8 *x;
19940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
20040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
20140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	blk = chunkInNAND/PAGES_PER_BLOCK;
20240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	pg = chunkInNAND%PAGES_PER_BLOCK;
20340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
20440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
20540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(data)
20640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	{
20740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		x = ned.block[blk]->page[pg]->data;
20840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
20940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		for(i = 0; i < PAGE_DATA_SIZE; i++)
21040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		{
21140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			x[i] &=data[i];
21240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
21340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
21440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		ned.block[blk]->page[pg]->empty = 0;
21540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
21640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
21740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
21840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(tags)
21940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	{
22040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		x = &ned.block[blk]->page[pg]->data[PAGE_DATA_SIZE];
22140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
22240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_PackTags2((yaffs_PackedTags2 *)x,tags);
22340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
22440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
22540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
22640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(tags || data)
22740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	{
22840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		nandemul_yield(1);
22940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
23040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
23140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return YAFFS_OK;
23240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
23340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
23440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
23540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint nandemul2k_ReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_ExtendedTags *tags)
23640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
23740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int blk;
23840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int pg;
23940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
24040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	__u8 *x;
24140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
24240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
24340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
24440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	blk = chunkInNAND/PAGES_PER_BLOCK;
24540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	pg = chunkInNAND%PAGES_PER_BLOCK;
24640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
24740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
24840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(data)
24940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	{
25040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		memcpy(data,ned.block[blk]->page[pg]->data,PAGE_DATA_SIZE);
25140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
25240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
25340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
25440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(tags)
25540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	{
25640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		x = &ned.block[blk]->page[pg]->data[PAGE_DATA_SIZE];
25740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
25840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		yaffs_UnpackTags2(tags,(yaffs_PackedTags2 *)x);
25940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
26040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
26140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return YAFFS_OK;
26240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
26340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
26440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
26540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int nandemul2k_CheckChunkErased(yaffs_Device *dev,int chunkInNAND)
26640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
26740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int blk;
26840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int pg;
26940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int i;
27040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
27140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
27240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
27340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	blk = chunkInNAND/PAGES_PER_BLOCK;
27440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	pg = chunkInNAND%PAGES_PER_BLOCK;
27540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
27640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
27740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	for(i = 0; i < PAGE_TOTAL_SIZE; i++)
27840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	{
27940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if(ned.block[blk]->page[pg]->data[i] != 0xFF)
28040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		{
28140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			return YAFFS_FAIL;
28240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
28340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
28440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
28540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return YAFFS_OK;
28640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
28740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
28840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
28940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint nandemul2k_EraseBlockInNAND(yaffs_Device *dev, int blockNumber)
29040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
29140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
29240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
29340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(blockNumber < 0 || blockNumber >= ned.nBlocks)
29440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	{
29540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(YAFFS_TRACE_ALWAYS,("Attempt to erase non-existant block %d\n",blockNumber));
29640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
29740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	else if(ned.block[blockNumber]->damaged)
29840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	{
29940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(YAFFS_TRACE_ALWAYS,("Attempt to erase damaged block %d\n",blockNumber));
30040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
30140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	else
30240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	{
30340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		nandemul_ReallyEraseBlock(blockNumber);
30440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
30540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
30640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return YAFFS_OK;
30740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
30840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
30940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint nandemul2k_InitialiseNAND(yaffs_Device *dev)
31040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
31140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	CheckInit();
31240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return YAFFS_OK;
31340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
31440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
31540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint nandemul2k_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo)
31640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
31740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
31840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	__u8 *x;
31940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
32040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	x = &ned.block[blockNo]->page[0]->data[PAGE_DATA_SIZE];
32140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
32240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	memset(x,0,sizeof(yaffs_PackedTags2));
32340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
32440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
32540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return YAFFS_OK;
32640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
32740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
32840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
32940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint nandemul2k_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, yaffs_BlockState *state, int *sequenceNumber)
33040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
33140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	yaffs_ExtendedTags tags;
33240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int chunkNo;
33340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
33440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	*sequenceNumber = 0;
33540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
33640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	chunkNo = blockNo * dev->nChunksPerBlock;
33740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
33840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	nandemul2k_ReadChunkWithTagsFromNAND(dev,chunkNo,NULL,&tags);
33940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(tags.blockBad)
34040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	{
34140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		*state = YAFFS_BLOCK_STATE_DEAD;
34240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
34340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	else if(!tags.chunkUsed)
34440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	{
34540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		*state = YAFFS_BLOCK_STATE_EMPTY;
34640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
34740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	else if(tags.chunkUsed)
34840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	{
34940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		*state = YAFFS_BLOCK_STATE_NEEDS_SCANNING;
35040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		*sequenceNumber = tags.sequenceNumber;
35140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
35240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return YAFFS_OK;
35340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
35440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
35540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint nandemul2k_GetBytesPerChunk(void) { return PAGE_DATA_SIZE;}
35640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
35740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint nandemul2k_GetChunksPerBlock(void) { return PAGES_PER_BLOCK; }
35840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint nandemul2k_GetNumberOfBlocks(void) {return nandemul2k_CalcNBlocks();}
35940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
36040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
36140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif //YAFFS_RAM_ENABLED
36240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
363