1/*
2 * YAFFS: Yet another FFS. A NAND-flash specific file system.
3 *
4 * Copyright (C) 2002 Aleph One Ltd.
5 *   for Toby Churchill Ltd and Brightstar Engineering
6 *
7 * Created by Charles Manning <charles@aleph1.co.uk>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 *
13 */
14
15const char *yaffs_nand_c_version =
16    "$Id: yaffs_nand.c,v 1.4 2006/10/13 08:52:49 charles Exp $";
17
18#include "yaffs_nand.h"
19#include "yaffs_tagscompat.h"
20#include "yaffs_tagsvalidity.h"
21
22
23int yaffs_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,
24					   __u8 * buffer,
25					   yaffs_ExtendedTags * tags)
26{
27	int result;
28	yaffs_ExtendedTags localTags;
29
30	int realignedChunkInNAND = chunkInNAND - dev->chunkOffset;
31
32	/* If there are no tags provided, use local tags to get prioritised gc working */
33	if(!tags)
34		tags = &localTags;
35
36	if (dev->readChunkWithTagsFromNAND)
37		result = dev->readChunkWithTagsFromNAND(dev, realignedChunkInNAND, buffer,
38						      tags);
39	else
40		result = yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(dev,
41									realignedChunkInNAND,
42									buffer,
43									tags);
44	if(tags &&
45	   tags->eccResult > YAFFS_ECC_RESULT_NO_ERROR){
46
47		yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, chunkInNAND/dev->nChunksPerBlock);
48                yaffs_HandleChunkError(dev,bi);
49	}
50
51	return result;
52}
53
54int yaffs_WriteChunkWithTagsToNAND(yaffs_Device * dev,
55						   int chunkInNAND,
56						   const __u8 * buffer,
57						   yaffs_ExtendedTags * tags)
58{
59	chunkInNAND -= dev->chunkOffset;
60
61
62	if (tags) {
63		tags->sequenceNumber = dev->sequenceNumber;
64		tags->chunkUsed = 1;
65		if (!yaffs_ValidateTags(tags)) {
66			T(YAFFS_TRACE_ERROR,
67			  (TSTR("Writing uninitialised tags" TENDSTR)));
68			YBUG();
69		}
70		T(YAFFS_TRACE_WRITE,
71		  (TSTR("Writing chunk %d tags %d %d" TENDSTR), chunkInNAND,
72		   tags->objectId, tags->chunkId));
73	} else {
74		T(YAFFS_TRACE_ERROR, (TSTR("Writing with no tags" TENDSTR)));
75		YBUG();
76	}
77
78	if (dev->writeChunkWithTagsToNAND)
79		return dev->writeChunkWithTagsToNAND(dev, chunkInNAND, buffer,
80						     tags);
81	else
82		return yaffs_TagsCompatabilityWriteChunkWithTagsToNAND(dev,
83								       chunkInNAND,
84								       buffer,
85								       tags);
86}
87
88int yaffs_MarkBlockBad(yaffs_Device * dev, int blockNo)
89{
90	blockNo -= dev->blockOffset;
91
92;
93	if (dev->markNANDBlockBad)
94		return dev->markNANDBlockBad(dev, blockNo);
95	else
96		return yaffs_TagsCompatabilityMarkNANDBlockBad(dev, blockNo);
97}
98
99int yaffs_QueryInitialBlockState(yaffs_Device * dev,
100						 int blockNo,
101						 yaffs_BlockState * state,
102						 unsigned *sequenceNumber)
103{
104	blockNo -= dev->blockOffset;
105
106	if (dev->queryNANDBlock)
107		return dev->queryNANDBlock(dev, blockNo, state, sequenceNumber);
108	else
109		return yaffs_TagsCompatabilityQueryNANDBlock(dev, blockNo,
110							     state,
111							     sequenceNumber);
112}
113
114
115int yaffs_EraseBlockInNAND(struct yaffs_DeviceStruct *dev,
116				  int blockInNAND)
117{
118	int result;
119
120	blockInNAND -= dev->blockOffset;
121
122
123	dev->nBlockErasures++;
124	result = dev->eraseBlockInNAND(dev, blockInNAND);
125
126	/* If at first we don't succeed, try again *once*.*/
127	if (!result)
128		result = dev->eraseBlockInNAND(dev, blockInNAND);
129	return result;
130}
131
132int yaffs_InitialiseNAND(struct yaffs_DeviceStruct *dev)
133{
134	return dev->initialiseNAND(dev);
135}
136
137
138
139