3 * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
\r
5 * Copyright (C) 2002-2007 Aleph One Ltd.
\r
6 * for Toby Churchill Ltd and Brightstar Engineering
\r
8 * Created by Charles Manning <charles@aleph1.co.uk>
\r
10 * This program is free software; you can redistribute it and/or modify
\r
11 * it under the terms of the GNU General Public License version 2 as
\r
12 * published by the Free Software Foundation.
\r
18 #include "yportenv.h"
\r
19 #include "yaffs_guts.h"
\r
20 #include "devextras.h"
\r
23 #include "yaffs_nandif.h"
\r
24 #include "yaffs_packedtags2.h"
\r
30 static unsigned char *DevBufferIn(yaffs_Device *dev)
\r
32 yfsd_WinCEDevice *cedev = (yfsd_WinCEDevice *)(dev->genericDevice);
\r
33 return cedev->bufferIn;
\r
35 static unsigned char *DevBufferOut(yaffs_Device *dev)
\r
37 yfsd_WinCEDevice *cedev = (yfsd_WinCEDevice *)(dev->genericDevice);
\r
38 return cedev->bufferOut;
\r
41 static unsigned DevBufferSize(yaffs_Device *dev)
\r
43 yfsd_WinCEDevice *cedev = (yfsd_WinCEDevice *)(dev->genericDevice);
\r
44 return cedev->bufferSize;
\r
49 /* NB For use with inband tags....
\r
50 * We assume that the data buffer is of size totalBytersPerChunk so that we can also
\r
51 * use it to load the tags.
\r
53 int ynandif_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND,
\r
55 const yaffs_ExtendedTags * tags)
\r
59 yaffs_PackedTags2 pt;
\r
61 unsigned spareSize = 0;
\r
63 unsigned char *bufferIn = DevBufferIn(dev);
\r
64 unsigned char *bufferOut = DevBufferOut(dev);
\r
65 unsigned bufferSize = DevBufferSize(dev);
\r
69 ("nandmtd2_WriteChunkWithTagsToNAND chunk %d data %p tags %p"
\r
70 TENDSTR), chunkInNAND, data, tags));
\r
73 /* For yaffs2 writing there must be both data and tags.
\r
74 * If we're using inband tags, then the tags are stuffed into
\r
75 * the end of the data buffer.
\r
78 if(dev->inbandTags){
\r
79 yaffs_PackedTags2TagsPart *pt2tp;
\r
80 pt2tp = (yaffs_PackedTags2TagsPart *)(data + dev->nDataBytesPerChunk);
\r
81 yaffs_PackTags2TagsPart(pt2tp,tags);
\r
86 yaffs_PackTags2(&pt, tags);
\r
88 spareSize = sizeof(yaffs_PackedTags2);
\r
91 yramsim_WritePage(chunkInNAND,
\r
92 data, dev->totalBytesPerChunk, spare, spareSize);
\r
97 int ynandif_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,
\r
98 __u8 * data, yaffs_ExtendedTags * tags)
\r
100 yaffs_PackedTags2 pt;
\r
102 void *spare = NULL;
\r
103 unsigned spareSize;
\r
104 int eccStatus; //0 = ok, 1 = fixed, -1 = unfixed
\r
106 unsigned char *bufferIn = DevBufferIn(dev);
\r
107 unsigned char *bufferOut = DevBufferOut(dev);
\r
108 unsigned bufferSize = DevBufferSize(dev);
\r
112 ("nandmtd2_ReadChunkWithTagsFromNAND chunk %d data %p tags %p"
\r
113 TENDSTR), chunkInNAND, data, tags));
\r
118 }else if(dev->inbandTags){
\r
122 data = yaffs_GetTempBuffer(dev,__LINE__);
\r
129 spareSize = sizeof(yaffs_PackedTags2);
\r
132 yramsim_ReadPage(chunkInNAND,
\r
133 data,data ? dev->totalBytesPerChunk : 0,
\r
139 if(dev->inbandTags){
\r
141 yaffs_PackedTags2TagsPart * pt2tp;
\r
142 pt2tp = (yaffs_PackedTags2TagsPart *)&data[dev->nDataBytesPerChunk];
\r
143 yaffs_UnpackTags2TagsPart(tags,pt2tp);
\r
148 yaffs_UnpackTags2(tags, &pt);
\r
152 if(tags && tags->chunkUsed){
\r
154 tags->eccResult = YAFFS_ECC_RESULT_NO_ERROR;
\r
155 else if(eccStatus < 0)
\r
156 tags->eccResult = YAFFS_ECC_RESULT_UNFIXED;
\r
158 tags->eccResult = YAFFS_ECC_RESULT_FIXED;
\r
162 yaffs_ReleaseTempBuffer(dev,data,__LINE__);
\r
167 int ynandif_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockId)
\r
170 yramsim_MarkBlockBad(blockId);
\r
175 int ynandif_EraseBlockInNAND(struct yaffs_DeviceStruct *dev, int blockId)
\r
178 yramsim_EraseBlock(blockId);
\r
184 static int ynandif_IsBlockOk(struct yaffs_DeviceStruct *dev, int blockId)
\r
186 return yramsim_CheckBlockOk(blockId);
\r
189 int ynandif_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockId, yaffs_BlockState *state, __u32 *sequenceNumber)
\r
192 yaffs_ExtendedTags tags;
\r
194 *sequenceNumber = 0;
\r
196 chunkNo = blockId * dev->nChunksPerBlock;
\r
198 if(!ynandif_IsBlockOk(dev,blockId)){
\r
199 *state = YAFFS_BLOCK_STATE_DEAD;
\r
203 ynandif_ReadChunkWithTagsFromNAND(dev,chunkNo,NULL,&tags);
\r
205 if(!tags.chunkUsed)
\r
207 *state = YAFFS_BLOCK_STATE_EMPTY;
\r
211 *state = YAFFS_BLOCK_STATE_NEEDS_SCANNING;
\r
212 *sequenceNumber = tags.sequenceNumber;
\r
220 int ynandif_GetGeometry(yaffs_Device *dev, ynandif_Geometry *geometry)
\r
223 yramsim_Geometry g;
\r
225 yramsim_GetGeometry(&g);
\r
226 geometry->startBlock = g.startBlock;
\r
227 geometry->endBlock = g.endBlock;
\r
228 geometry->dataSize = g.dataSize;
\r
229 geometry->spareSize = g.spareSize;
\r
230 geometry->pagesPerBlock = g.pagesPerBlock;
\r
231 geometry->hasECC = g.hasECC;
\r
232 geometry->inbandTags = g.inbandTags;
\r
233 geometry->useYaffs2 = g.useYaffs2;
\r
239 int ynandif_InitialiseNAND(yaffs_Device *dev)
\r
242 yramsim_Initialise();
\r