Tweaks to retirement handling
[yaffs2.git] / direct / yaffs_fileem2k.c
index 786094b349a307c5ab28ba41feb05f068086e1b4..59d0c8efa12e3d51b1faf283bb6cdb8dcbec6ca2 100644 (file)
@@ -15,7 +15,7 @@
 // This provides a YAFFS nand emulation on a file for emulating 2kB pages.
 // THis is only intended as test code to test persistence etc.
 
-const char *yaffs_flashif_c_version = "$Id: yaffs_fileem2k.c,v 1.3 2005-07-03 05:48:11 charles Exp $";
+const char *yaffs_flashif_c_version = "$Id: yaffs_fileem2k.c,v 1.7 2006-10-13 08:52:49 charles Exp $";
 
 
 #include "yportenv.h"
@@ -47,23 +47,65 @@ typedef struct
 
 
 
+#define MAX_HANDLES 20
+#define BLOCKS_PER_HANDLE 8000
+
 typedef struct
 {
-       int handle;
+       int handle[MAX_HANDLES];
        int nBlocks;
 } yflash_Device;
 
 static yflash_Device filedisk;
 
-static int  CheckInit(yaffs_Device *dev)
+int yaffs_testPartialWrite = 0;
+
+
+static char *NToName(char *buf,int n)
 {
-       static int initialised = 0;
+       sprintf(buf,"emfile%d",n);
+       return buf;
+}
+
+static char dummyBuffer[BLOCK_SIZE];
+
+static int GetBlockFileHandle(int n)
+{
+       int h;
+       int requiredSize;
        
+       char name[40];
+       NToName(name,n);
+       int fSize;
+       int i;
+       
+       h =  open(name, O_RDWR | O_CREAT, S_IREAD | S_IWRITE);
+       if(h >= 0){
+               fSize = lseek(h,0,SEEK_END);
+               requiredSize = BLOCKS_PER_HANDLE * BLOCK_SIZE;
+               if(fSize < requiredSize){
+                  for(i = 0; i < BLOCKS_PER_HANDLE; i++)
+                       if(write(h,dummyBuffer,BLOCK_SIZE) != BLOCK_SIZE)
+                               return -1;
+                       
+               }
+       }
+       
+       return h;
+
+}
+
+static int  CheckInit(void)
+{
+       static int initialised = 0;
+       int h;
        int i;
 
        
-       int fSize;
+       off_t fSize;
+       off_t requiredSize;
        int written;
+       int blk;
        
        yflash_Page p;
        
@@ -74,69 +116,65 @@ static int  CheckInit(yaffs_Device *dev)
 
        initialised = 1;
        
+       memset(dummyBuffer,0xff,sizeof(dummyBuffer));
        
-       filedisk.nBlocks = SIZE_IN_MB * BLOCKS_PER_MB;
-       
-       filedisk.handle = open("yaffsemfile2k", O_RDWR | O_CREAT, S_IREAD | S_IWRITE);
-       
-       if(filedisk.handle < 0)
-       {
-               perror("Failed to open yaffs emulation file");
-               return YAFFS_FAIL;
-       }
        
+       filedisk.nBlocks = SIZE_IN_MB * BLOCKS_PER_MB;
+
+       for(i = 0; i <  MAX_HANDLES; i++)
+               filedisk.handle[i] = -1;
        
-       fSize = lseek(filedisk.handle,0,SEEK_END);
+       for(i = 0,blk = 0; blk < filedisk.nBlocks; blk+=BLOCKS_PER_HANDLE,i++)
+               filedisk.handle[i] = GetBlockFileHandle(i);
        
-       if(fSize < filedisk.nBlocks * BLOCK_SIZE)
-       {
-               printf("Creating yaffs emulation file\n");
-               
-               lseek(filedisk.handle,0,SEEK_SET);
-               
-               memset(&p,0xff,sizeof(yflash_Page));
-               
-               for(i = 0; i <  filedisk.nBlocks * BLOCK_SIZE; i+= PAGE_SIZE)
-               {
-                       written = write(filedisk.handle,&p,sizeof(yflash_Page));
-                       
-                       if(written != sizeof(yflash_Page))
-                       {
-                               printf("Write failed\n");
-                               return YAFFS_FAIL;
-                       }
-               }               
-       }
        
        return 1;
 }
 
+
+int yflash_GetNumberOfBlocks(void)
+{
+       CheckInit();
+       
+       return filedisk.nBlocks;
+}
+
 int yflash_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, yaffs_ExtendedTags *tags)
 {
        int written;
        int pos;
-
-       CheckInit(dev);
+       int h;
+       
+       CheckInit();
        
        
        
        if(data)
        {
-               pos = chunkInNAND * PAGE_SIZE;
-               lseek(filedisk.handle,pos,SEEK_SET);
-               written = write(filedisk.handle,data,dev->nBytesPerChunk);
+               pos = (chunkInNAND % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE;
+               h = filedisk.handle[(chunkInNAND / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))];
+               
+               lseek(h,pos,SEEK_SET);
+               written = write(h,data,dev->nDataBytesPerChunk);
                
-               if(written != dev->nBytesPerChunk) return YAFFS_FAIL;
+               if(yaffs_testPartialWrite){
+                       close(h);
+                       exit(1);
+               }
+               
+               if(written != dev->nDataBytesPerChunk) return YAFFS_FAIL;
        }
        
        if(tags)
        {
-               pos = chunkInNAND * PAGE_SIZE + PAGE_DATA_SIZE;
-               lseek(filedisk.handle,pos,SEEK_SET);
+               pos = (chunkInNAND % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE + PAGE_DATA_SIZE ;
+               h = filedisk.handle[(chunkInNAND / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))];
+               
+               lseek(h,pos,SEEK_SET);
                if( 0 && dev->isYaffs2)
                {
                        
-                       written = write(filedisk.handle,tags,sizeof(yaffs_ExtendedTags));
+                       written = write(h,tags,sizeof(yaffs_ExtendedTags));
                        if(written != sizeof(yaffs_ExtendedTags)) return YAFFS_FAIL;
                }
                else
@@ -144,7 +182,7 @@ int yflash_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8
                        yaffs_PackedTags2 pt;
                        yaffs_PackTags2(&pt,tags);
 
-                       written = write(filedisk.handle,&pt,sizeof(pt));
+                       written = write(h,&pt,sizeof(pt));
                        if(written != sizeof(pt)) return YAFFS_FAIL;
                }
        }
@@ -154,25 +192,6 @@ int yflash_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8
 
 }
 
-int yflash_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo)
-{
-       int written;
-       
-       yaffs_PackedTags2 pt;
-
-       CheckInit(dev);
-       
-       memset(&pt,0,sizeof(pt));
-       lseek(filedisk.handle,(blockNo * dev->nChunksPerBlock) * PAGE_SIZE + PAGE_DATA_SIZE,SEEK_SET);
-       written = write(filedisk.handle,&pt,sizeof(pt));
-               
-       if(written != sizeof(pt)) return YAFFS_FAIL;
-       
-       
-       return YAFFS_OK;
-       
-}
-
 int yaffs_CheckAllFF(const __u8 *ptr, int n)
 {
        while(n)
@@ -185,31 +204,39 @@ int yaffs_CheckAllFF(const __u8 *ptr, int n)
 }
 
 
+static int fail300 = 1;
+static int fail320 = 1;
+
 int yflash_ReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_ExtendedTags *tags)
 {
        int nread;
        int pos;
-
-       CheckInit(dev);
+       int h;
+       
+       CheckInit();
        
        
        
        if(data)
        {
-               pos = chunkInNAND * PAGE_SIZE;
-               lseek(filedisk.handle,pos,SEEK_SET);
-               nread = read(filedisk.handle,data,dev->nBytesPerChunk);
+
+               pos = (chunkInNAND % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE;
+               h = filedisk.handle[(chunkInNAND / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))];             
+               lseek(h,pos,SEEK_SET);
+               nread = read(h,data,dev->nDataBytesPerChunk);
                
-               if(nread != dev->nBytesPerChunk) return YAFFS_FAIL;
+               if(nread != dev->nDataBytesPerChunk) return YAFFS_FAIL;
        }
        
        if(tags)
        {
-               pos = chunkInNAND * PAGE_SIZE + PAGE_DATA_SIZE;
-               lseek(filedisk.handle,pos,SEEK_SET);
+               pos = (chunkInNAND % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE + PAGE_DATA_SIZE;
+               h = filedisk.handle[(chunkInNAND / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))];             
+               lseek(h,pos,SEEK_SET);
+
                if(0 && dev->isYaffs2)
                {
-                       nread= read(filedisk.handle,tags,sizeof(yaffs_ExtendedTags));
+                       nread= read(h,tags,sizeof(yaffs_ExtendedTags));
                        if(nread != sizeof(yaffs_ExtendedTags)) return YAFFS_FAIL;
                        if(yaffs_CheckAllFF((__u8 *)tags,sizeof(yaffs_ExtendedTags)))
                        {
@@ -223,8 +250,21 @@ int yflash_ReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *da
                else
                {
                        yaffs_PackedTags2 pt;
-                       nread= read(filedisk.handle,&pt,sizeof(pt));
+                       nread= read(h,&pt,sizeof(pt));
                        yaffs_UnpackTags2(tags,&pt);
+                       if((chunkInNAND >> 6) == 300) {
+                           if(fail300 && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR){
+                              tags->eccResult = YAFFS_ECC_RESULT_FIXED;
+                              fail300 = 0;
+                           }
+                           
+                       }
+                       if((chunkInNAND >> 6) == 320) {
+                           if(fail320 && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR){
+                              tags->eccResult = YAFFS_ECC_RESULT_FIXED;
+                              fail320 = 0;
+                           }
+                       }
                        if(nread != sizeof(pt)) return YAFFS_FAIL;
                }
        }
@@ -235,12 +275,37 @@ int yflash_ReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *da
 }
 
 
+int yflash_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo)
+{
+       int written;
+       int h;
+       
+       yaffs_PackedTags2 pt;
+
+       CheckInit();
+       
+       memset(&pt,0,sizeof(pt));
+       h = filedisk.handle[(blockNo / ( BLOCKS_PER_HANDLE))];
+       lseek(h,((blockNo % BLOCKS_PER_HANDLE) * dev->nChunksPerBlock) * PAGE_SIZE + PAGE_DATA_SIZE,SEEK_SET);
+       written = write(h,&pt,sizeof(pt));
+               
+       if(written != sizeof(pt)) return YAFFS_FAIL;
+       
+       
+       return YAFFS_OK;
+       
+}
+
 int yflash_EraseBlockInNAND(yaffs_Device *dev, int blockNumber)
 {
 
        int i;
+       int h;
                
-       CheckInit(dev);
+       CheckInit();
+       
+       if(blockNumber == 320)
+               fail320 = 1;
        
        if(blockNumber < 0 || blockNumber >= filedisk.nBlocks)
        {
@@ -256,13 +321,14 @@ int yflash_EraseBlockInNAND(yaffs_Device *dev, int blockNumber)
                
                memset(pg,0xff,syz);
                
-               pos = lseek(filedisk.handle, blockNumber * dev->nChunksPerBlock * PAGE_SIZE, SEEK_SET);
-               
+
+               h = filedisk.handle[(blockNumber / ( BLOCKS_PER_HANDLE))];
+               lseek(h,((blockNumber % BLOCKS_PER_HANDLE) * dev->nChunksPerBlock) * PAGE_SIZE,SEEK_SET);               
                for(i = 0; i < dev->nChunksPerBlock; i++)
                {
-                       write(filedisk.handle,pg,PAGE_SIZE);
+                       write(h,pg,PAGE_SIZE);
                }
-               pos = lseek(filedisk.handle, 0,SEEK_CUR);
+               pos = lseek(h, 0,SEEK_CUR);
                
                return YAFFS_OK;
        }
@@ -271,7 +337,7 @@ int yflash_EraseBlockInNAND(yaffs_Device *dev, int blockNumber)
 
 int yflash_InitialiseNAND(yaffs_Device *dev)
 {
-       CheckInit(dev);
+       CheckInit();
        
        return YAFFS_OK;
 }