/*
* 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
+ * Copyright (C) 2002-2018 Aleph One Ltd.
*
* Created by Charles Manning <charles@aleph1.co.uk>
*
#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;
}