Add experimental yaffs_nandif.[ch]
authorcharles <charles>
Mon, 9 Feb 2009 03:20:33 +0000 (03:20 +0000)
committercharles <charles>
Mon, 9 Feb 2009 03:20:33 +0000 (03:20 +0000)
direct/yaffs_nandif.c [new file with mode: 0644]
direct/yaffs_nandif.h [new file with mode: 0644]

diff --git a/direct/yaffs_nandif.c b/direct/yaffs_nandif.c
new file mode 100644 (file)
index 0000000..6216b86
--- /dev/null
@@ -0,0 +1,245 @@
+\r
+/*\r
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.\r
+ *\r
+ * Copyright (C) 2002-2007 Aleph One Ltd.\r
+ *   for Toby Churchill Ltd and Brightstar Engineering\r
+ *\r
+ * Created by Charles Manning <charles@aleph1.co.uk>\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License version 2 as\r
+ * published by the Free Software Foundation.\r
+ */\r
+\r
+\r
+\r
+\r
+#include "yportenv.h"\r
+#include "yaffs_guts.h"\r
+#include "devextras.h"\r
+\r
+\r
+#include "yaffs_nandif.h"\r
+#include "yaffs_packedtags2.h"\r
+\r
+\r
+#if 0\r
+\r
+\r
+static unsigned char *DevBufferIn(yaffs_Device *dev)\r
+{\r
+       yfsd_WinCEDevice *cedev = (yfsd_WinCEDevice *)(dev->genericDevice);\r
+       return cedev->bufferIn;\r
+}\r
+static unsigned char *DevBufferOut(yaffs_Device *dev)\r
+{\r
+       yfsd_WinCEDevice *cedev = (yfsd_WinCEDevice *)(dev->genericDevice);\r
+       return cedev->bufferOut;\r
+}\r
+\r
+static unsigned DevBufferSize(yaffs_Device *dev)\r
+{\r
+       yfsd_WinCEDevice *cedev = (yfsd_WinCEDevice *)(dev->genericDevice);\r
+       return cedev->bufferSize;\r
+}\r
+\r
+#endif\r
+\r
+/* NB For use with inband tags....\r
+ * We assume that the data buffer is of size totalBytersPerChunk so that we can also\r
+ * use it to load the tags.\r
+ */\r
+int ynandif_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND,\r
+                                     const __u8 * data,\r
+                                     const yaffs_ExtendedTags * tags)\r
+{\r
+\r
+       int retval = 0;\r
+       yaffs_PackedTags2 pt;\r
+       void *spare;\r
+       unsigned spareSize = 0;\r
+\r
+       unsigned char *bufferIn   = DevBufferIn(dev);\r
+       unsigned char *bufferOut  = DevBufferOut(dev);\r
+       unsigned       bufferSize = DevBufferSize(dev);\r
+\r
+       T(YAFFS_TRACE_MTD,\r
+         (TSTR\r
+          ("nandmtd2_WriteChunkWithTagsToNAND chunk %d data %p tags %p"\r
+           TENDSTR), chunkInNAND, data, tags));\r
+           \r
+\r
+       /* For yaffs2 writing there must be both data and tags.\r
+        * If we're using inband tags, then the tags are stuffed into\r
+        * the end of the data buffer.\r
+        */\r
+\r
+       if(dev->inbandTags){\r
+               yaffs_PackedTags2TagsPart *pt2tp;\r
+               pt2tp = (yaffs_PackedTags2TagsPart *)(data + dev->nDataBytesPerChunk);\r
+               yaffs_PackTags2TagsPart(pt2tp,tags);\r
+               spare = NULL;\r
+               spareSize = 0;\r
+       }\r
+       else{\r
+               yaffs_PackTags2(&pt, tags);\r
+               spare = &pt;\r
+               spareSize = sizeof(yaffs_PackedTags2);\r
+       }\r
+       \r
+       yramsim_WritePage(chunkInNAND,\r
+                                         data, dev->totalBytesPerChunk, spare, spareSize);\r
+\r
+       return YAFFS_OK;\r
+}\r
+\r
+int ynandif_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,\r
+                                      __u8 * data, yaffs_ExtendedTags * tags)\r
+{\r
+       yaffs_PackedTags2 pt;\r
+       int localData = 0;\r
+       void *spare = NULL;\r
+       unsigned spareSize;\r
+       int eccStatus; //0 = ok, 1 = fixed, -1 = unfixed\r
+\r
+       unsigned char *bufferIn   = DevBufferIn(dev);\r
+       unsigned char *bufferOut  = DevBufferOut(dev);\r
+       unsigned       bufferSize = DevBufferSize(dev);\r
+\r
+       T(YAFFS_TRACE_MTD,\r
+         (TSTR\r
+          ("nandmtd2_ReadChunkWithTagsFromNAND chunk %d data %p tags %p"\r
+           TENDSTR), chunkInNAND, data, tags));\r
+           \r
+       if(!tags){\r
+               spare = NULL;\r
+               spareSize = 0;\r
+       }else if(dev->inbandTags){\r
+               \r
+               if(!data) {\r
+                       localData = 1;\r
+                       data = yaffs_GetTempBuffer(dev,__LINE__);\r
+               }\r
+               spare = NULL;\r
+               spareSize = 0;\r
+       }\r
+       else {\r
+               spare = &pt;\r
+               spareSize = sizeof(yaffs_PackedTags2);\r
+       }\r
+\r
+       yramsim_ReadPage(chunkInNAND,\r
+                                        data,data ? dev->totalBytesPerChunk : 0,\r
+                                        spare,spareSize,\r
+                                        &eccStatus);\r
+\r
+\r
+\r
+       if(dev->inbandTags){\r
+               if(tags){\r
+                       yaffs_PackedTags2TagsPart * pt2tp;\r
+                       pt2tp = (yaffs_PackedTags2TagsPart *)&data[dev->nDataBytesPerChunk];    \r
+                       yaffs_UnpackTags2TagsPart(tags,pt2tp);\r
+               }\r
+       }\r
+       else {\r
+               if (tags){\r
+                       yaffs_UnpackTags2(tags, &pt);\r
+               }\r
+       }\r
+\r
+       if(tags && tags->chunkUsed){\r
+               if(eccStatus == 0)\r
+                       tags->eccResult = YAFFS_ECC_RESULT_NO_ERROR;\r
+               else if(eccStatus < 0)\r
+                       tags->eccResult = YAFFS_ECC_RESULT_UNFIXED;\r
+               else\r
+                       tags->eccResult = YAFFS_ECC_RESULT_FIXED;\r
+       }\r
+\r
+       if(localData)\r
+               yaffs_ReleaseTempBuffer(dev,data,__LINE__);\r
+       \r
+       return YAFFS_OK;\r
+}\r
+\r
+int ynandif_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockId)\r
+{\r
+\r
+       yramsim_MarkBlockBad(blockId);\r
+\r
+       return YAFFS_OK;\r
+}\r
+\r
+int ynandif_EraseBlockInNAND(struct yaffs_DeviceStruct *dev, int blockId)\r
+{\r
+\r
+       yramsim_EraseBlock(blockId);\r
+\r
+       return YAFFS_OK;\r
+}\r
+\r
+\r
+static int ynandif_IsBlockOk(struct yaffs_DeviceStruct *dev, int blockId)\r
+{\r
+       return yramsim_CheckBlockOk(blockId);\r
+}\r
+\r
+int ynandif_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockId, yaffs_BlockState *state, __u32 *sequenceNumber)\r
+{\r
+       unsigned chunkNo;\r
+       yaffs_ExtendedTags tags;\r
+\r
+       *sequenceNumber = 0;\r
+       \r
+       chunkNo = blockId * dev->nChunksPerBlock;\r
+       \r
+       if(!ynandif_IsBlockOk(dev,blockId)){\r
+               *state = YAFFS_BLOCK_STATE_DEAD;\r
+       } \r
+       else \r
+       {\r
+               ynandif_ReadChunkWithTagsFromNAND(dev,chunkNo,NULL,&tags);\r
+\r
+               if(!tags.chunkUsed)\r
+               {\r
+                       *state = YAFFS_BLOCK_STATE_EMPTY;\r
+               }\r
+               else \r
+               {\r
+                       *state = YAFFS_BLOCK_STATE_NEEDS_SCANNING;\r
+                       *sequenceNumber = tags.sequenceNumber;\r
+               }\r
+       }\r
+\r
+       return YAFFS_OK;\r
+}\r
+\r
+\r
+int ynandif_GetGeometry(yaffs_Device *dev, ynandif_Geometry *geometry)\r
+{\r
+\r
+       yramsim_Geometry g;\r
+\r
+       yramsim_GetGeometry(&g);\r
+       geometry->startBlock = g.startBlock;\r
+       geometry->endBlock = g.endBlock;\r
+       geometry->dataSize = g.dataSize;\r
+       geometry->spareSize = g.spareSize;\r
+       geometry->pagesPerBlock = g.pagesPerBlock;\r
+       geometry->hasECC = g.hasECC;\r
+       geometry->inbandTags = g.inbandTags;\r
+       geometry->useYaffs2 = g.useYaffs2;\r
+\r
+       return YAFFS_OK;\r
+\r
+}\r
+\r
+int ynandif_InitialiseNAND(yaffs_Device *dev)\r
+{\r
+\r
+       yramsim_Initialise();\r
+\r
+       return YAFFS_OK;\r
+}\r
diff --git a/direct/yaffs_nandif.h b/direct/yaffs_nandif.h
new file mode 100644 (file)
index 0000000..1a17262
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. 
+ *
+ * Copyright (C) 2002-2007 Aleph One Ltd.
+ *   for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+
+#ifndef __YNANDIF_H__
+#define __YNANDIF_H__
+
+#include "yaffs_guts.h"
+
+typedef struct {
+               unsigned startBlock;
+               unsigned endBlock;
+               unsigned dataSize;              // Number of data bytes per page
+               unsigned spareSize;             // Number of spare bytes per chunk
+               unsigned pagesPerBlock;
+               unsigned hasECC;
+               unsigned inbandTags;    // Use inband tags on this device
+               unsigned useYaffs2;
+} ynandif_Geometry;
+
+int ynandif_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_ExtendedTags *tags);
+int ynandif_ReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_ExtendedTags *tags);
+int ynandif_EraseBlockInNAND(yaffs_Device *dev, int blockNumber);
+int ynandif_InitialiseNAND(yaffs_Device *dev);
+int ynandif_MarkNANDBlockBad(yaffs_Device *dev,int blockNumber);
+int ynandif_QueryNANDBlock(yaffs_Device *dev, int blockNo, yaffs_BlockState *state, __u32 *sequenceNumber);
+int ynandif_GetGeometry(yaffs_Device *dev, ynandif_Geometry *geometry);
+#endif