2 * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
\r
4 * Copyright (C) 2002-2010 Aleph One Ltd.
\r
5 * for Toby Churchill Ltd and Brightstar Engineering
\r
7 * Created by Charles Manning <charles@aleph1.co.uk>
\r
9 * This program is free software; you can redistribute it and/or modify
\r
10 * it under the terms of the GNU General Public License version 2 as
\r
11 * published by the Free Software Foundation.
\r
17 #include "yportenv.h"
\r
18 #include "yaffs_guts.h"
\r
19 #include "devextras.h"
\r
22 #include "yaffs_nandif.h"
\r
23 #include "yaffs_packedtags2.h"
\r
29 static unsigned char *DevBufferIn(yaffs_Device *dev)
\r
31 yfsd_WinCEDevice *cedev = (yfsd_WinCEDevice *)(dev->genericDevice);
\r
32 return cedev->bufferIn;
\r
34 static unsigned char *DevBufferOut(yaffs_Device *dev)
\r
36 yfsd_WinCEDevice *cedev = (yfsd_WinCEDevice *)(dev->genericDevice);
\r
37 return cedev->bufferOut;
\r
40 static unsigned DevBufferSize(yaffs_Device *dev)
\r
42 yfsd_WinCEDevice *cedev = (yfsd_WinCEDevice *)(dev->genericDevice);
\r
43 return cedev->bufferSize;
\r
48 /* NB For use with inband tags....
\r
49 * We assume that the data buffer is of size totalBytersPerChunk so that we can also
\r
50 * use it to load the tags.
\r
52 int ynandif_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND,
\r
54 const yaffs_ExtendedTags * tags)
\r
58 yaffs_PackedTags2 pt;
\r
60 unsigned spareSize = 0;
\r
62 unsigned char *bufferIn = DevBufferIn(dev);
\r
63 unsigned char *bufferOut = DevBufferOut(dev);
\r
64 unsigned bufferSize = DevBufferSize(dev);
\r
68 ("nandmtd2_WriteChunkWithTagsToNAND chunk %d data %p tags %p"
\r
69 TENDSTR), chunkInNAND, data, tags));
\r
72 /* For yaffs2 writing there must be both data and tags.
\r
73 * If we're using inband tags, then the tags are stuffed into
\r
74 * the end of the data buffer.
\r
77 if(dev->inbandTags){
\r
78 yaffs_PackedTags2TagsPart *pt2tp;
\r
79 pt2tp = (yaffs_PackedTags2TagsPart *)(data + dev->nDataBytesPerChunk);
\r
80 yaffs_PackTags2TagsPart(pt2tp,tags);
\r
85 yaffs_PackTags2(&pt, tags);
\r
87 spareSize = sizeof(yaffs_PackedTags2);
\r
90 yramsim_WritePage(chunkInNAND,
\r
91 data, dev->totalBytesPerChunk, spare, spareSize);
\r
96 int ynandif_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,
\r
97 __u8 * data, yaffs_ExtendedTags * tags)
\r
99 yaffs_PackedTags2 pt;
\r
101 void *spare = NULL;
\r
102 unsigned spareSize;
\r
103 int eccStatus; //0 = ok, 1 = fixed, -1 = unfixed
\r
105 unsigned char *bufferIn = DevBufferIn(dev);
\r
106 unsigned char *bufferOut = DevBufferOut(dev);
\r
107 unsigned bufferSize = DevBufferSize(dev);
\r
111 ("nandmtd2_ReadChunkWithTagsFromNAND chunk %d data %p tags %p"
\r
112 TENDSTR), chunkInNAND, data, tags));
\r
117 }else if(dev->inbandTags){
\r
121 data = yaffs_GetTempBuffer(dev,__LINE__);
\r
128 spareSize = sizeof(yaffs_PackedTags2);
\r
131 yramsim_ReadPage(chunkInNAND,
\r
132 data,data ? dev->totalBytesPerChunk : 0,
\r
138 if(dev->inbandTags){
\r
140 yaffs_PackedTags2TagsPart * pt2tp;
\r
141 pt2tp = (yaffs_PackedTags2TagsPart *)&data[dev->nDataBytesPerChunk];
\r
142 yaffs_UnpackTags2TagsPart(tags,pt2tp);
\r
147 yaffs_UnpackTags2(tags, &pt);
\r
151 if(tags && tags->chunkUsed){
\r
153 tags->eccResult = YAFFS_ECC_RESULT_NO_ERROR;
\r
154 else if(eccStatus < 0)
\r
155 tags->eccResult = YAFFS_ECC_RESULT_UNFIXED;
\r
157 tags->eccResult = YAFFS_ECC_RESULT_FIXED;
\r
161 yaffs_ReleaseTempBuffer(dev,data,__LINE__);
\r
166 int ynandif_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockId)
\r
169 yramsim_MarkBlockBad(blockId);
\r
174 int ynandif_EraseBlockInNAND(struct yaffs_DeviceStruct *dev, int blockId)
\r
177 yramsim_EraseBlock(blockId);
\r
183 static int ynandif_IsBlockOk(struct yaffs_DeviceStruct *dev, int blockId)
\r
185 return yramsim_CheckBlockOk(blockId);
\r
188 int ynandif_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockId, yaffs_BlockState *state, __u32 *sequenceNumber)
\r
191 yaffs_ExtendedTags tags;
\r
193 *sequenceNumber = 0;
\r
195 chunkNo = blockId * dev->nChunksPerBlock;
\r
197 if(!ynandif_IsBlockOk(dev,blockId)){
\r
198 *state = YAFFS_BLOCK_STATE_DEAD;
\r
202 ynandif_ReadChunkWithTagsFromNAND(dev,chunkNo,NULL,&tags);
\r
204 if(!tags.chunkUsed)
\r
206 *state = YAFFS_BLOCK_STATE_EMPTY;
\r
210 *state = YAFFS_BLOCK_STATE_NEEDS_SCANNING;
\r
211 *sequenceNumber = tags.sequenceNumber;
\r
219 int ynandif_GetGeometry(yaffs_Device *dev, ynandif_Geometry *geometry)
\r
222 yramsim_Geometry g;
\r
224 yramsim_GetGeometry(&g);
\r
225 geometry->startBlock = g.startBlock;
\r
226 geometry->endBlock = g.endBlock;
\r
227 geometry->dataSize = g.dataSize;
\r
228 geometry->spareSize = g.spareSize;
\r
229 geometry->pagesPerBlock = g.pagesPerBlock;
\r
230 geometry->hasECC = g.hasECC;
\r
231 geometry->inbandTags = g.inbandTags;
\r
232 geometry->useYaffs2 = g.useYaffs2;
\r
238 int ynandif_InitialiseNAND(yaffs_Device *dev)
\r
241 yramsim_Initialise();
\r