Add nand driver that works with a nand simulator
[yaffs2.git] / direct / test-framework / ynorsim.c
index 36bfa625ca346b91e29d186aebc736ae2e527470..38a4632e800f4f69386d77a9e4d30a7b01945e23 100644 (file)
@@ -13,8 +13,6 @@
 
 #include "ynorsim.h"
 
 
 #include "ynorsim.h"
 
-
-
 #include <stdio.h>
 #include <fcntl.h>
 #include <sys/stat.h>
 #include <stdio.h>
 #include <fcntl.h>
 #include <sys/stat.h>
 
 #define YNORSIM_FNAME "emfile-nor"
 
 
 #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
  * 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_BIT_CHANGES 15
 #define YNORSIM_BIT_CHANGES 2
 
 #define YNORSIM_DEV_SIZE_U32   (8*1024 * 1024/4)
 #endif
 
 #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;
 
 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;
 }
 }