Add yaffs driver for regular NOR on simulator
authorCharles Manning <cdhmanning@gmail.com>
Fri, 12 Oct 2012 02:23:30 +0000 (15:23 +1300)
committerCharles Manning <cdhmanning@gmail.com>
Fri, 12 Oct 2012 02:23:30 +0000 (15:23 +1300)
Signed-off-by: Charles Manning <cdhmanning@gmail.com>
direct/test-framework/FrameworkRules.mk
direct/test-framework/tests/init_fw_update_test_nor.sh
direct/test-framework/tests/nor_stress.c
direct/test-framework/tests/run_fw_update_test_nor.sh
direct/test-framework/yaffs_m18_drv.c
direct/test-framework/yaffs_nor_drv.c [new file with mode: 0644]
direct/test-framework/yaffs_nor_drv.h [new file with mode: 0644]
direct/test-framework/yaffscfg2k.c
direct/test-framework/ynorsim.c
direct/test-framework/ynorsim.h

index da47e49..52cd4da 100644 (file)
@@ -36,7 +36,7 @@ COMMONTESTOBJS = yaffscfg2k.o yaffs_osglue.o yaffs_hweight.o\
                 yaffs_packedtags2.o yaffs_nand.o \
                 yaffs_checkptrw.o  yaffs_qsort.o\
                 yaffs_nameval.o yaffs_attribs.o \
-                yaffs_m18_drv.o  ynorsim.o \
+                yaffs_m18_drv.o  yaffs_nor_drv.o ynorsim.o \
                 yaffs_allocator.o \
                 yaffs_bitmap.o \
                 yaffs_yaffs1.o \
@@ -76,6 +76,7 @@ YAFFSDIRECTSYMLINKS =  \
 FRAMEWORKEXTRASYMLINKS = \
                yaffscfg2k.c yaffs_fileem2k.c yaffs_fileem2k.h\
                yaffs_fileem.c yaffs_m18_drv.c yaffs_m18_drv.h \
+               yaffs_nor_drv.c yaffs_nor_drv.h \
                yaffs_ramdisk.c yaffs_ramdisk.h yaffs_ramem2k.c \
                ynorsim.h ynorsim.c yaffs_osglue.c
 
index 8a0cb1a..963f081 100755 (executable)
@@ -2,4 +2,4 @@
 # Run this to initialise the file system for the test runs.
 rm seed-nor-*
 rm emfile-nor*
-./yaffs_test  -u -i M18-1
+./yaffs_test  -u -i nor
index 3905771..adf1b29 100644 (file)
@@ -51,7 +51,7 @@ static unsigned cycleEnds;
 static int interleave_fsx;
 
 static int no_verification;
+
 char fullPathName[100];
 char fullPowerUpName[100];
 char fullStartName[100];
@@ -96,7 +96,7 @@ static void FatalError(int line_no)
 
   if(ext_fatal)
        ext_fatal();
-       
+
   while(1){
    sleep(1);
   }
@@ -113,11 +113,11 @@ static void UpdateCounter(const char *name, unsigned *val,  int initialise)
   unsigned x[2];
   int nread = 0;
   int nwritten = 0;
-  
+
   x[0] = x[1] = 0;
-  
+
   if(initialise){
-    x[0] = 0; 
+    x[0] = 0;
     x[1] = 1;
   } else {
     inh = yaffs_open(name,O_RDONLY, S_IREAD | S_IWRITE);
@@ -132,18 +132,18 @@ static void UpdateCounter(const char *name, unsigned *val,  int initialise)
       printf("Error reading counter %s handle %d, x[0] %u x[1] %u last error %d\n",
               name, inh, x[0], x[1],yaffsfs_GetLastError());
       FatalError(__LINE__);
-              
+
     }
     x[0]++;
     x[1]++;
   }
-  
+
   FSX();
   outh = yaffs_open(fullTempCounterName, O_RDWR | O_TRUNC | O_CREAT, S_IREAD | S_IWRITE);
-  
+
   if(outh >= 0){
    struct yaffs_stat tmpstat, oldstat, tmpfstat;
-   FSX(); 
+   FSX();
     yaffs_fstat(outh,&tmpfstat);
     printf("\n\n\n*** Writing file %s inode %d\n",fullTempCounterName,tmpfstat.st_ino);
     nwritten = yaffs_write(outh,x,sizeof(x));
@@ -160,15 +160,15 @@ static void UpdateCounter(const char *name, unsigned *val,  int initialise)
     yaffs_rename(fullTempCounterName,name);
     FSX();
   }
-  
+
   if(nwritten != sizeof(x)){
       printf("Error writing counter %s handle %d, x[0] %u x[1] %u\n",
               name, inh, x[0], x[1]);
       FatalError(__LINE__);
   }
-  
+
   *val = x[0];
-  
+
   printf("##\n"
          "## Set counter %s to %u\n"
          "##\n", name,x[0]);
@@ -183,9 +183,9 @@ static void dump_directory_tree_worker(const char *dname,int recursive)
        char str[1000];
        int error_line = 0;
        int nentries;
-                       
+
        d = yaffs_opendir(dname);
-       
+
        if(!d)
        {
                printf("opendir failed\n");
@@ -199,9 +199,9 @@ static void dump_directory_tree_worker(const char *dname,int recursive)
                        strcat(str,"/");
                        strcat(str,de->d_name);
                        nentries++;
-                       
+
                        yaffs_lstat(str,&s);
-                       
+
                        printf("%s inode %ld %d obj %x length %d mode %X ",str, de->d_ino, s.st_ino,de->d_dont_use,(int)s.st_size,s.st_mode);\
                        if(de->d_ino != s.st_ino){
                                printf(" \n\n!!!! HEY inode mismatch\n\n");
@@ -216,21 +216,21 @@ static void dump_directory_tree_worker(const char *dname,int recursive)
                                                          if(yaffs_readlink(str,str,100) < 0)
                                                                printf("no alias");
                                                          else
-                                                               printf("\"%s\"",str);    
+                                                               printf("\"%s\"",str);
                                                          break;
                                default: printf("unknown"); break;
                        }
-                       
+
                        printf("\n");
 
                        if((s.st_mode & S_IFMT) == S_IFDIR && recursive)
                                dump_directory_tree_worker(str,1);
-                               
+
                         if(s.st_ino > 10000)
                                error_line = __LINE__;
-                                                       
+
                }
-               
+
                if(strstr(dname,"lost+found") && nentries >0){
                        printf("\n\n!!! HEY lost+found not empty, had %d entries\n\n\n",nentries);
                        error_line = __LINE__;
@@ -238,7 +238,7 @@ static void dump_directory_tree_worker(const char *dname,int recursive)
 
                if(error_line && !no_verification)
                        FatalError(error_line);
-               
+
                yaffs_closedir(d);
        }
 
@@ -265,13 +265,13 @@ static int y_wr_file(const char *fname, unsigned sz32)
        int i;
        struct yaffs_stat st;
        unsigned checksum = 0;
-       
+
 
        FSX();
        h = yaffs_open(fname,O_RDWR | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE);
        yaffs_fstat(h,&st);
        printf("\n\n\n**** Open writing file %s inode %d\n",fname, st.st_ino);
-       
+
        FSX();
 
        if(h < 0){
@@ -291,7 +291,7 @@ static int y_wr_file(const char *fname, unsigned sz32)
                  xx[i] = sz32 + i;
                  checksum ^= xx[i];
                 }
-                
+
                 FSX();
                if((r = yaffs_write(h,xx,sizeof(xx))) != sizeof(xx)){
                        goto WRITE_ERROR;
@@ -304,7 +304,7 @@ static int y_wr_file(const char *fname, unsigned sz32)
        if((r = yaffs_write(h,xx,sizeof(unsigned))) != sizeof(unsigned)){
                goto WRITE_ERROR;
        }
-       
+
        FSX();
        yaffs_close(h);
        printf("File closed\n");
@@ -314,7 +314,7 @@ WRITE_ERROR:
        printf("ywrite error at position %d\n",(int)yaffs_lseek(h,0,SEEK_END));
        yaffs_close(h);
        return -1;
-       
+
 }
 
 static int y_verify_file(const char *fName)
@@ -332,7 +332,7 @@ static int y_verify_file(const char *fName)
                return 0;
 
         printf("Verifying file %s\n",fName);
-               
+
        h = yaffs_open(fName, O_RDONLY,S_IREAD | S_IWRITE);
 
        if(h < 0){
@@ -350,7 +350,7 @@ static int y_verify_file(const char *fName)
                yaffs_close(h);
                return -1;
        }
-       
+
        recordedSize = sz32 * sizeof(xx) + 8;
 
        printf("verify %s: file size is %d, recorded size is %d\n", fName, totalSize, recordedSize);
@@ -380,7 +380,7 @@ static int y_verify_file(const char *fName)
                yaffs_close(h);
                return -1;
        }
-       
+
        checksum ^= xx[0];
 
        if(checksum != 0){
@@ -399,12 +399,12 @@ static void DoUpdateMainFile(void)
         int result;
         int sz32;
         sz32 = (myrand() % 1000)   + 20;
-        
+
        result = y_wr_file(fullTempMainName,sz32);
        FSX();
        if(!no_verification && result)
            FatalError(__LINE__);
-       printf("Raname file %s to %s\n",fullTempMainName,fullMainName);
+       printf("Rename file %s to %s\n",fullTempMainName,fullMainName);
        yaffs_rename(fullTempMainName,fullMainName);
        FSX();
 }
@@ -424,7 +424,7 @@ static void DoVerifyMainFile(void)
 void NorStressTestInitialise(const char *prefix)
 {
   MakeFullNames(prefix);
-  
+
   UpdateCounter(fullPowerUpName,&powerUps,1);
   UpdateCounter(fullStartName,&cycleStarts,1);
   UpdateCounter(fullEndName,&cycleEnds,1);
@@ -439,16 +439,16 @@ void NorStressTestRun(const char *prefix, int n_cycles, int do_fsx, int skip_ver
 
   interleave_fsx = do_fsx;
   no_verification = skip_verification;
+
   MakeFullNames(prefix);
   dump_directory_tree(fullPathName);
   FSX_INIT(prefix);
-    
+
   dump_directory_tree(fullPathName);
-  
+
   UpdateCounter(fullPowerUpName,&powerUps,0);
   dump_directory_tree(fullPathName);
-  
+
   while(n_cycles < 0 || n_cycles > 0){
     if(n_cycles > 0)
       n_cycles--;
@@ -457,7 +457,7 @@ void NorStressTestRun(const char *prefix, int n_cycles, int do_fsx, int skip_ver
     DoVerifyMainFile();
     DoUpdateMainFile();
     dump_directory_tree(fullPathName);
-  
+
     UpdateCounter(fullEndName,&cycleEnds,0);
     dump_directory_tree(fullPathName);
   }
index 9265336..82eebb7 100755 (executable)
@@ -33,7 +33,7 @@ do
    echo "#########"
    echo "#########"
    echo "#########"
-   ./yaffs_test -u -f -p -s$seed -t0 M18-1 
+   ./yaffs_test -u -f -p -s$seed -t0 nor
    #>log-nor-$i
 done
 
index 0325968..eca97ec 100644 (file)
 
 /* Compile this for a simulation */
 #include "ynorsim.h"
-#define m18_drv_FlashInit() ynorsim_initialise()
-#define m18_drv_FlashDeinit() ynorsim_shutdown()
-#define m18_drv_FlashWrite32(addr,buf,nwords) ynorsim_wr32(addr,buf,nwords)
-#define m18_drv_FlashRead32(addr,buf,nwords) ynorsim_rd32(addr,buf,nwords)
-#define m18_drv_FlashEraseBlock(addr) ynorsim_erase(addr)
-#define DEVICE_BASE     ynorsim_get_base()
+
+static struct nor_sim *nor_sim;
+
+#define m18_drv_FlashInit() do {nor_sim = ynorsim_initialise("emfile-m18", BLOCKS_IN_DEVICE, BLOCK_SIZE_IN_BYTES); } while(0)
+#define m18_drv_FlashDeinit() ynorsim_shutdown(nor_sim)
+#define m18_drv_FlashWrite32(addr,buf,nwords) ynorsim_wr32(nor_sim,addr,buf,nwords)
+#define m18_drv_FlashRead32(addr,buf,nwords) ynorsim_rd32(nor_sim,addr,buf,nwords)
+#define m18_drv_FlashEraseBlock(addr) ynorsim_erase(nor_sim,addr)
+#define DEVICE_BASE     ynorsim_get_base(nor_sim)
+
 #else
 
 /* Compile this to hook up to read hardware */
@@ -85,6 +89,7 @@
 #define DEVICE_BASE     (32 * 1024 * 1024)
 #endif
 
+
 static u32 *Block2Addr(struct yaffs_dev *dev, int blockNumber)
 {
        u32 addr;
@@ -315,6 +320,7 @@ static int m18_drv_InitialiseNAND(struct yaffs_dev *dev)
 static int m18_drv_Deinitialise_flash_fn(struct yaffs_dev *dev)
 {
        dev=dev;
+
        m18_drv_FlashDeinit();
 
        return YAFFS_OK;
diff --git a/direct/test-framework/yaffs_nor_drv.c b/direct/test-framework/yaffs_nor_drv.c
new file mode 100644 (file)
index 0000000..a510979
--- /dev/null
@@ -0,0 +1,346 @@
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 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 General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * This is an interface module for handling NOR in yaffs1 mode.
+ */
+
+/* This code is intended to be used with "regular" NOR that is bit-modifyable.
+ *
+ * Each "chunk" is a contguous area of 512 + 16 bytes.
+ * This makes 248 such chunks with some space left over where a format markerr
+ * is stored.
+ */
+
+#include "yaffs_nor_drv.h"
+
+#include "yportenv.h"
+#include "yaffs_trace.h"
+
+#include "yaffs_flashif.h"
+#include "yaffs_guts.h"
+
+/* Tunable data */
+#define DATA_BYTES_PER_CHUNK   512
+#define SPARE_BYTES_PER_CHUNK  16
+#define BLOCK_SIZE_IN_BYTES    (128*1024)
+#define BYTES_IN_DEVICE                (4*1024*1024)
+
+#define BYTES_PER_CHUNK                (DATA_BYTES_PER_CHUNK + SPARE_BYTES_PER_CHUNK)
+#define SPARE_AREA_OFFSET      DATA_BYTES_PER_CHUNK
+#define CHUNKS_PER_BLOCK (BLOCK_SIZE_IN_BYTES/BYTES_PER_CHUNK)
+
+#define BLOCKS_IN_DEVICE       (BYTES_IN_DEVICE/BLOCK_SIZE_IN_BYTES)
+
+#define YNOR_PREMARKER          (0xF6)
+#define YNOR_POSTMARKER         (0xF0)
+
+#define FORMAT_OFFSET          (CHUNKS_PER_BLOCK * BYTES_PER_CHUNK)
+#define FORMAT_VALUE           0x1234
+
+#if 1
+
+/* Compile this for a simulation */
+#include "ynorsim.h"
+
+static struct nor_sim *nor_sim;
+
+#define nor_drv_FlashInit() do {nor_sim = ynorsim_initialise("emfile-nor", BLOCKS_IN_DEVICE, BLOCK_SIZE_IN_BYTES); } while(0)
+#define nor_drv_FlashDeinit() ynorsim_shutdown(nor_sim)
+#define nor_drv_FlashWrite32(addr,buf,nwords) ynorsim_wr32(nor_sim,addr,buf,nwords)
+#define nor_drv_FlashRead32(addr,buf,nwords) ynorsim_rd32(nor_sim,addr,buf,nwords)
+#define nor_drv_FlashEraseBlock(addr) ynorsim_erase(nor_sim,addr)
+#define DEVICE_BASE     ynorsim_get_base(nor_sim)
+
+#else
+
+/* Compile this to hook up to read hardware */
+#include "../blob/yflashrw.h"
+#define nor_drv_FlashInit()  do{} while(0)
+#define nor_drv_FlashDeinit() do {} while(0)
+#define nor_drv_FlashWrite32(addr,buf,nwords) Y_FlashWrite(addr,buf,nwords)
+#define nor_drv_FlashRead32(addr,buf,nwords)  Y_FlashRead(addr,buf,nwords)
+#define nor_drv_FlashEraseBlock(addr)         Y_FlashErase(addr,BLOCK_SIZE_IN_BYTES)
+#define DEVICE_BASE     (32 * 1024 * 1024)
+#endif
+
+
+static u32 *Block2Addr(struct yaffs_dev *dev, int blockNumber)
+{
+       u8 *addr;
+
+       dev=dev;
+
+       addr = (u8*)DEVICE_BASE;
+       addr += blockNumber * BLOCK_SIZE_IN_BYTES;
+
+       return (u32 *) addr;
+}
+
+static u32 *Block2FormatAddr(struct yaffs_dev *dev, int blockNumber)
+{
+       u8 *addr;
+
+       addr = (u8*) Block2Addr(dev,blockNumber);
+       addr += FORMAT_OFFSET;
+
+       return (u32 *)addr;
+}
+
+static u32 *Chunk2DataAddr(struct yaffs_dev *dev, int chunk_id)
+{
+       unsigned block;
+       unsigned chunkInBlock;
+       u8 *addr;
+
+       block = chunk_id/dev->param.chunks_per_block;
+       chunkInBlock = chunk_id % dev->param.chunks_per_block;
+
+       addr = (u8*) Block2Addr(dev,block);
+       addr += chunkInBlock * BYTES_PER_CHUNK;
+
+       return (u32 *)addr;
+}
+
+static u32 *Chunk2SpareAddr(struct yaffs_dev *dev, int chunk_id)
+{
+       u8 *addr;
+
+       addr = (u8*) Chunk2DataAddr(dev, chunk_id);
+       addr += SPARE_AREA_OFFSET;
+       return (u32 *)addr;
+}
+
+
+static void nor_drv_AndBytes(u8*target, const u8 *src, int nbytes)
+{
+       while(nbytes > 0){
+               *target &= *src;
+               target++;
+               src++;
+               nbytes--;
+       }
+}
+
+static int nor_drv_WriteChunkToNAND(struct yaffs_dev *dev,int nand_chunk,
+                                   const u8 *data, int data_len,
+                                   const u8 *oob, int oob_len)
+{
+       u32 *dataAddr = Chunk2DataAddr(dev,nand_chunk);
+       u32 *spareAddr = Chunk2SpareAddr(dev,nand_chunk);
+
+       struct yaffs_spare *spare = (struct yaffs_spare *)oob;
+       struct yaffs_spare tmpSpare;
+
+       (void) oob_len;
+
+       /* We should only be getting called for one of 3 reasons:
+         * Writing a chunk: data and spare will not be NULL
+         * Writing a deletion marker: data will be NULL, spare not NULL
+         * Writing a bad block marker: data will be NULL, spare not NULL
+         */
+
+       if(sizeof(struct yaffs_spare) != SPARE_BYTES_PER_CHUNK)
+               BUG();
+
+       if(data && oob) {
+               if(spare->page_status != 0xff)
+                       BUG();
+               /* Write a pre-marker */
+               memset(&tmpSpare,0xff,sizeof(tmpSpare));
+               tmpSpare.page_status = YNOR_PREMARKER;
+               nor_drv_FlashWrite32(spareAddr,(u32 *)&tmpSpare,sizeof(struct yaffs_spare)/sizeof(u32));
+
+               /* Write the data */
+               nor_drv_FlashWrite32(dataAddr,(u32 *)data, data_len/ sizeof(u32));
+
+               memcpy(&tmpSpare,spare,sizeof(struct yaffs_spare));
+
+               /* Write the real tags, but override the premarker*/
+               tmpSpare.page_status = YNOR_PREMARKER;
+               nor_drv_FlashWrite32(spareAddr,(u32 *)&tmpSpare,sizeof(struct yaffs_spare)/sizeof(u32));
+
+               /* Write a post-marker */
+               tmpSpare.page_status = YNOR_POSTMARKER;
+               nor_drv_FlashWrite32(spareAddr,(u32 *)&tmpSpare,sizeof(tmpSpare)/sizeof(u32));
+
+       } else if(spare){
+               /* This has to be a read-modify-write operation to handle NOR-ness */
+
+               nor_drv_FlashRead32(spareAddr,(u32 *)&tmpSpare,sizeof(struct yaffs_spare)/sizeof(u32));
+
+               nor_drv_AndBytes((u8 *)&tmpSpare,(u8 *)spare,sizeof(struct yaffs_spare));
+
+               nor_drv_FlashWrite32(spareAddr,(u32 *)&tmpSpare,sizeof(struct yaffs_spare)/sizeof(u32));
+       } else {
+               BUG();
+       }
+
+       return YAFFS_OK;
+}
+
+static int nor_drv_ReadChunkFromNAND(struct yaffs_dev *dev,int nand_chunk,
+                                       u8 *data, int data_len,
+                                       u8 *oob, int oob_len,
+                                       enum yaffs_ecc_result *ecc_result)
+{
+       struct yaffs_spare *spare = (struct yaffs_spare *)oob;
+
+       u32 *dataAddr = Chunk2DataAddr(dev,nand_chunk);
+       u32 *spareAddr = Chunk2SpareAddr(dev,nand_chunk);
+
+       if (data) {
+               nor_drv_FlashRead32(dataAddr,(u32 *)data,dev->param.total_bytes_per_chunk / sizeof(u32));
+       }
+
+       if (oob) {
+               nor_drv_FlashRead32(spareAddr,(u32 *)spare, oob_len/ sizeof(u32));
+
+               /* If the page status is YNOR_POSTMARKER then it was written properly
+                 * so change that to 0xFF so that the rest of yaffs is happy.
+                 */
+               if(spare->page_status == YNOR_POSTMARKER)
+                       spare->page_status = 0xff;
+               else if(spare->page_status != 0xff &&
+                       (spare->page_status | YNOR_PREMARKER) != 0xff)
+                       spare->page_status = YNOR_PREMARKER;
+       }
+
+       if(ecc_result)
+               *ecc_result = YAFFS_ECC_RESULT_NO_ERROR;
+
+       return YAFFS_OK;
+
+}
+
+
+static int nor_drv_FormatBlock(struct yaffs_dev *dev, int blockNumber)
+{
+       u32 *blockAddr = Block2Addr(dev,blockNumber);
+       u32 *formatAddr = Block2FormatAddr(dev,blockNumber);
+       u32 formatValue = FORMAT_VALUE;
+
+       nor_drv_FlashEraseBlock(blockAddr);
+       nor_drv_FlashWrite32(formatAddr,&formatValue,1);
+
+       return YAFFS_OK;
+}
+
+static int nor_drv_UnformatBlock(struct yaffs_dev *dev, int blockNumber)
+{
+       u32 *formatAddr = Block2FormatAddr(dev,blockNumber);
+       u32 formatValue = 0;
+
+       nor_drv_FlashWrite32(formatAddr,&formatValue,1);
+
+       return YAFFS_OK;
+}
+
+static int nor_drv_IsBlockFormatted(struct yaffs_dev *dev, int blockNumber)
+{
+       u32 *formatAddr = Block2FormatAddr(dev,blockNumber);
+       u32 formatValue;
+
+
+       nor_drv_FlashRead32(formatAddr,&formatValue,1);
+
+       return (formatValue == FORMAT_VALUE);
+}
+
+static int nor_drv_EraseBlockInNAND(struct yaffs_dev *dev, int blockNumber)
+{
+
+       if(blockNumber < 0 || blockNumber >= BLOCKS_IN_DEVICE)
+       {
+               yaffs_trace(YAFFS_TRACE_ALWAYS,
+                       "Attempt to erase non-existant block %d\n",
+                       blockNumber);
+               return YAFFS_FAIL;
+       }
+       else
+       {
+               nor_drv_UnformatBlock(dev,blockNumber);
+               nor_drv_FormatBlock(dev,blockNumber);
+               return YAFFS_OK;
+       }
+
+}
+
+static int nor_drv_InitialiseNAND(struct yaffs_dev *dev)
+{
+       int i;
+
+       nor_drv_FlashInit();
+       /* Go through the blocks formatting them if they are not formatted */
+       for(i = dev->param.start_block; i <= dev->param.end_block; i++){
+               if(!nor_drv_IsBlockFormatted(dev,i)){
+                       nor_drv_FormatBlock(dev,i);
+               }
+       }
+       return YAFFS_OK;
+}
+
+static int nor_drv_Deinitialise_flash_fn(struct yaffs_dev *dev)
+{
+       dev=dev;
+
+       nor_drv_FlashDeinit();
+
+       return YAFFS_OK;
+}
+
+
+struct yaffs_dev *yaffs_nor_install_drv(const char *name)
+{
+
+       struct yaffs_dev *dev = malloc(sizeof(struct yaffs_dev));
+       char *name_copy = strdup(name);
+       struct yaffs_param *param;
+       struct yaffs_driver *drv;
+
+
+       if(!dev || !name_copy) {
+               free(name_copy);
+               free(dev);
+               return NULL;
+       }
+
+       param = &dev->param;
+       drv = &dev->drv;
+
+       memset(dev, 0, sizeof(*dev));
+
+       param->name = name_copy;
+
+       param->total_bytes_per_chunk = DATA_BYTES_PER_CHUNK;
+       param->chunks_per_block = CHUNKS_PER_BLOCK;
+       param->n_reserved_blocks = 2;
+       param->start_block = 0; // Can use block 0
+       param->end_block = BLOCKS_IN_DEVICE - 1; // Last block
+       param->use_nand_ecc = 0; // use YAFFS's ECC
+
+       drv->drv_write_chunk_fn = nor_drv_WriteChunkToNAND;
+       drv->drv_read_chunk_fn = nor_drv_ReadChunkFromNAND;
+       drv->drv_erase_fn = nor_drv_EraseBlockInNAND;
+       drv->drv_initialise_fn = nor_drv_InitialiseNAND;
+       drv->drv_deinitialise_fn = nor_drv_Deinitialise_flash_fn;
+
+       param->n_caches = 10;
+       param->disable_soft_del = 1;
+
+       dev->driver_context = (void *) nor_sim;
+
+       yaffs_add_device(dev);
+
+       return NULL;
+}
diff --git a/direct/test-framework/yaffs_nor_drv.h b/direct/test-framework/yaffs_nor_drv.h
new file mode 100644 (file)
index 0000000..f856223
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 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 __YAFFS_NOR_DRV_H__
+#define __YAFFS_NOR_DRV_H__
+
+struct yaffs_dev;
+struct yaffs_dev *yaffs_nor_install_drv(const char *name);
+
+#endif
+
+
index b9a09a7..9e24866 100644 (file)
@@ -48,6 +48,7 @@ unsigned yaffs_trace_mask =
 
 #include "yaffs_flashif2.h"
 #include "yaffs_m18_drv.h"
+#include "yaffs_nor_drv.h"
 
 int yaffs_start_up(void)
 {
@@ -63,6 +64,7 @@ int yaffs_start_up(void)
 
 
        yaffs_m18_install_drv("M18-1");
+       yaffs_nor_install_drv("nor");
 
        // /yaffs2  yaffs2 file emulation
        yflash2_install_drv("yaffs2");
index 36bfa62..38a4632 100644 (file)
@@ -13,8 +13,6 @@
 
 #include "ynorsim.h"
 
-
-
 #include <stdio.h>
 #include <fcntl.h>
 #include <sys/stat.h>
 
 #define YNORSIM_FNAME "emfile-nor"
 
-/* Set YNORSIM_BIT_CHANGES to a a value from 1..30 to 
- *simulate bit flipping as the programming happens. 
+/* Set YNORSIM_BIT_CHANGES to a a value from 1..30 to
+ *simulate bit flipping as the programming happens.
  * A low value results in faster simulation with less chance of encountering a partially programmed
- * word. 
+ * word.
  */
-   
+
 //#define YNORSIM_BIT_CHANGES 15
 #define YNORSIM_BIT_CHANGES 2
 
 #define YNORSIM_DEV_SIZE_U32   (8*1024 * 1024/4)
 #endif
 
-static u32 word[YNORSIM_DEV_SIZE_U32];
+struct nor_sim {
+       int n_blocks;
+       int block_size_bytes;
+       int file_size;
+       u32 *word;
+       int initialised;
+       char *fname;
+       int remaining_ops;
+       int nops_so_far;
+};
 
+int ops_multiplier = 500;
 extern int random_seed;
 extern int simulate_power_failure;
 
-static void NorError(void)
+static void NorError(struct nor_sim *sim)
 {
-  printf("Nor error\n");
-  while(1){}
+       printf("Nor error on device %s\n", sim->fname);
+       while (1) {
+       }
 }
 
-static void ynorsim_save_image(void)
+static void ynorsim_save_image(struct nor_sim *sim)
 {
-  int h = open(YNORSIM_FNAME, O_RDWR | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE);
-  write(h,word,sizeof(word));
-  close(h);
+       int h;
+
+       h = open(sim->fname, O_RDWR | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE);
+       write(h, sim->word, sim->file_size);
+       close(h);
 }
 
-static void ynorsim_restore_image(void)
+static void ynorsim_restore_image(struct nor_sim *sim)
 {
-  int h = open(YNORSIM_FNAME, O_RDONLY, S_IREAD | S_IWRITE);
-  memset(word,0xFF,sizeof(word));
-  read(h,word,sizeof(word));
-  close(h);
-}
+       int h;
 
+       h = open(sim->fname, O_RDONLY, S_IREAD | S_IWRITE);
+       memset(sim->word, 0xFF, sim->file_size);
+       read(h, sim->word, sim->file_size);
+       close(h);
+}
 
-static void ynorsim_power_fail(void)
+static void ynorsim_power_fail(struct nor_sim *sim)
 {
-  ynorsim_save_image();
-  exit(1);
+       ynorsim_save_image(sim);
+       exit(1);
 }
 
-static int initialised = 0;
-static int remaining_ops;
-static int nops_so_far;
-
-int ops_multiplier = 500;
-
-static void ynorsim_maybe_power_fail(void)
+static void ynorsim_maybe_power_fail(struct nor_sim *sim)
 {
-
-   nops_so_far++;
-   
-   
-   remaining_ops--;
-   if(simulate_power_failure &&
-      remaining_ops < 1){
-       printf("Simulated power failure after %d operations\n",nops_so_far);
-       ynorsim_power_fail();
-  }
+       sim->nops_so_far++;
+       sim->remaining_ops--;
+       if (simulate_power_failure && sim->remaining_ops < 1) {
+               printf("Simulated power failure after %d operations\n",
+                      sim->nops_so_far);
+               ynorsim_power_fail(sim);
+       }
 }
 
-static void ynorsim_ready(void)
+static void ynorsim_ready(struct nor_sim *sim)
 {
-  if(initialised) 
-    return;
-  srand(random_seed);
-  remaining_ops = 1000000000;
-  remaining_ops = (rand() % 10000) * ops_multiplier * YNORSIM_BIT_CHANGES;
-  ynorsim_restore_image();
+       if (sim->initialised)
+               return;
+       srand(random_seed);
+       sim->remaining_ops = 1000000000;
+       sim->remaining_ops =
+           (rand() % 10000) * ops_multiplier * YNORSIM_BIT_CHANGES;
+       ynorsim_restore_image(sim);
+       sim->initialised = 1;
 }
 
-void ynorsim_rd32(u32 *addr,u32 *buf, int nwords)
-{ 
-   while(nwords > 0){
-     *buf = *addr;
-     buf++;
-     addr++;
-     nwords--;
-   }
+/* Public functions. */
+
+void ynorsim_rd32(struct nor_sim *sim, u32 * addr, u32 * buf, int nwords)
+{
+       sim = sim;
+       while (nwords > 0) {
+               *buf = *addr;
+               buf++;
+               addr++;
+               nwords--;
+       }
 }
 
-void ynorsim_wr_one_word32(u32 *addr,u32 val)
+void ynorsim_wr_one_word32(struct nor_sim *sim, u32 * addr, u32 val)
 {
-  u32 tmp;
-  u32 m;
-  int i;
-
-  tmp = *addr;
-  if(val & ~tmp){
-    // Fail due to trying to change a zero into a 1
-    printf("attempt to set a zero to one (%x)->(%x)\n",tmp,val);
-    NorError();
-  }
-  
-  for(i = 0; i < YNORSIM_BIT_CHANGES; i++){
-    m = 1 << (rand() & 31);
-    if(!(m & val)){
-      tmp &= ~m;
-      *addr = tmp;
-      ynorsim_maybe_power_fail();
-    }
-       
-  }
-  
-  *addr = tmp & val;
-  ynorsim_maybe_power_fail();
+       u32 tmp;
+       u32 m;
+       int i;
+
+       tmp = *addr;
+       if (val & ~tmp) {
+               /* Fail due to trying to change a zero into a 1 */
+               printf("attempt to set a zero to one (%x)->(%x)\n", tmp, val);
+               NorError(sim);
+       }
+
+       for (i = 0; i < YNORSIM_BIT_CHANGES; i++) {
+               m = 1 << (rand() & 31);
+               if (!(m & val)) {
+                       tmp &= ~m;
+                       *addr = tmp;
+                       ynorsim_maybe_power_fail(sim);
+               }
+
+       }
+
+       *addr = tmp & val;
+       ynorsim_maybe_power_fail(sim);
 }
 
-void ynorsim_wr32(u32 *addr, u32 *buf, int nwords)
+void ynorsim_wr32(struct nor_sim *sim, u32 * addr, u32 * buf, int nwords)
 {
-  while(nwords >0){
-    ynorsim_wr_one_word32(addr,*buf);
-    addr++;
-    buf++;
-    nwords--;
-  }
+       while (nwords > 0) {
+               ynorsim_wr_one_word32(sim, addr, *buf);
+               addr++;
+               buf++;
+               nwords--;
+       }
 }
 
-void ynorsim_erase(u32 *addr)
+void ynorsim_erase(struct nor_sim *sim, u32 * addr)
 {
-  /* Todo... bit flipping */
-  memset(addr,0xFF,YNORSIM_BLOCK_SIZE_U32 * 4);
+       /* Todo... bit flipping */
+       memset(addr, 0xFF, sim->block_size_bytes);
 }
 
-void ynorsim_initialise(void)
+struct nor_sim *ynorsim_initialise(char *name, int n_blocks,
+                                  int block_size_bytes)
 {
-  ynorsim_ready();
+       struct nor_sim *sim;
+
+       sim = malloc(sizeof(*sim));
+       if (!sim)
+               return NULL;
+
+       memset(sim, 0, sizeof(*sim));
+       sim->n_blocks = n_blocks;
+       sim->block_size_bytes = block_size_bytes;
+       sim->file_size = n_blocks * block_size_bytes;
+       sim->word = malloc(sim->file_size);
+       sim->fname = strdup(name);
+
+       if(!sim->word)
+               return NULL;
+
+       ynorsim_ready(sim);
+       return sim;
 }
 
-void ynorsim_shutdown(void)
+void ynorsim_shutdown(struct nor_sim *sim)
 {
-  ynorsim_save_image();
-  initialised=0;
+       ynorsim_save_image(sim);
+       sim->initialised = 0;
 }
 
-u32 *ynorsim_get_base(void)
+u32 *ynorsim_get_base(struct nor_sim *sim)
 {
-  return word;
+       return sim->word;
 }
index 6b1193f..a51617e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * YAFFS: Yet another Flash File System . A NAND-flash specific file system. 
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
  *
  * Copyright (C) 2002-2011 Aleph One Ltd.
  *   for Toby Churchill Ltd and Brightstar Engineering
 
 #include "yaffs_guts.h"
 
-void ynorsim_rd32(u32 *addr, u32 *data, int nwords);
-void ynorsim_wr32(u32 *addr, u32 *data, int nwords);
-void ynorsim_erase(u32 *addr);
-void ynorsim_shutdown(void);
-void ynorsim_initialise(void);
-u32 * ynorsim_get_base(void);
+struct nor_sim;
+
+void ynorsim_rd32(struct nor_sim *sim, u32 *addr, u32 *data, int nwords);
+void ynorsim_wr32(struct nor_sim *sim, u32 *addr, u32 *data, int nwords);
+void ynorsim_erase(struct nor_sim *sim, u32 *addr);
+void ynorsim_shutdown(struct nor_sim *sim);
+struct nor_sim *ynorsim_initialise(char *name, int n_blocks, int block_size_bytes);
+u32 * ynorsim_get_base(struct nor_sim *sim);
 
 #endif