yaffs u-boot: Fix erase for inband tags.
[yaffs2.git] / direct / basic-test / ynorsim.c
1 /*
2  * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
3  *
4  * Copyright (C) 2002-2011 Aleph One Ltd.
5  *   for Toby Churchill Ltd and Brightstar Engineering
6  *
7  * Created by Charles Manning <charles@aleph1.co.uk>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License version 2 as
11  * published by the Free Software Foundation.
12  */
13
14 #include "ynorsim.h"
15
16
17
18 #include <stdio.h>
19 #include <fcntl.h>
20 #include <sys/stat.h>
21 #include <unistd.h>
22 #include <time.h>
23
24 #define YNORSIM_FNAME "emfile-nor"
25
26 /* Set YNORSIM_BIT_CHANGES to a a value from 1..30 to 
27  *simulate bit flipping as the programming happens. 
28  * A low value results in faster simulation with less chance of encountering a partially programmed
29  * word. 
30  */
31    
32 //#define YNORSIM_BIT_CHANGES 15
33 #define YNORSIM_BIT_CHANGES 2
34
35 #if 0
36 /* Simulate 32MB of flash in 256k byte blocks.
37  * This stuff is x32.
38  */
39
40 #define YNORSIM_BLOCK_SIZE_U32  (256*1024/4)
41 #define YNORSIM_DEV_SIZE_U32    (32*1024 * 1024/4)
42 #else
43 /* Simulate 8MB of flash in 256k byte blocks.
44  * This stuff is x32.
45  */
46
47 #define YNORSIM_BLOCK_SIZE_U32  (256*1024/4)
48 #define YNORSIM_DEV_SIZE_U32    (8*1024 * 1024/4)
49 #endif
50
51 static u32 word[YNORSIM_DEV_SIZE_U32];
52
53 extern int random_seed;
54 extern int simulate_power_failure;
55
56 static void NorError(void)
57 {
58   printf("Nor error\n");
59   while(1){}
60 }
61
62 static void ynorsim_save_image(void)
63 {
64   int h = open(YNORSIM_FNAME, O_RDWR | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE);
65   write(h,word,sizeof(word));
66   close(h);
67 }
68
69 static void ynorsim_restore_image(void)
70 {
71   int h = open(YNORSIM_FNAME, O_RDONLY, S_IREAD | S_IWRITE);
72   memset(word,0xFF,sizeof(word));
73   read(h,word,sizeof(word));
74   close(h);
75 }
76
77
78 static void ynorsim_power_fail(void)
79 {
80   ynorsim_save_image();
81   exit(1);
82 }
83
84 static int initialised = 0;
85 static int remaining_ops;
86 static int nops_so_far;
87
88 int ops_multiplier = 500;
89
90 static void ynorsim_maybe_power_fail(void)
91 {
92
93    nops_so_far++;
94    
95    
96    remaining_ops--;
97    if(simulate_power_failure &&
98       remaining_ops < 1){
99        printf("Simulated power failure after %d operations\n",nops_so_far);
100         ynorsim_power_fail();
101   }
102 }
103
104 static void ynorsim_ready(void)
105 {
106   if(initialised) 
107     return;
108   srand(random_seed);
109   remaining_ops = 1000000000;
110   remaining_ops = (rand() % 10000) * ops_multiplier * YNORSIM_BIT_CHANGES;
111   ynorsim_restore_image();
112 }
113
114 void ynorsim_rd32(u32 *addr,u32 *buf, int nwords)
115
116    while(nwords > 0){
117      *buf = *addr;
118      buf++;
119      addr++;
120      nwords--;
121    }
122 }
123
124 void ynorsim_wr_one_word32(u32 *addr,u32 val)
125 {
126   u32 tmp;
127   u32 m;
128   int i;
129
130   tmp = *addr;
131   if(val & ~tmp){
132     // Fail due to trying to change a zero into a 1
133     printf("attempt to set a zero to one (%x)->(%x)\n",tmp,val);
134     NorError();
135   }
136   
137   for(i = 0; i < YNORSIM_BIT_CHANGES; i++){
138     m = 1 << (rand() & 31);
139     if(!(m & val)){
140       tmp &= ~m;
141       *addr = tmp;
142       ynorsim_maybe_power_fail();
143     }
144        
145   }
146   
147   *addr = tmp & val;
148   ynorsim_maybe_power_fail();
149 }
150
151 void ynorsim_wr32(u32 *addr, u32 *buf, int nwords)
152 {
153   while(nwords >0){
154     ynorsim_wr_one_word32(addr,*buf);
155     addr++;
156     buf++;
157     nwords--;
158   }
159 }
160
161 void ynorsim_erase(u32 *addr)
162 {
163   /* Todo... bit flipping */
164   memset(addr,0xFF,YNORSIM_BLOCK_SIZE_U32 * 4);
165 }
166
167 void ynorsim_initialise(void)
168 {
169   ynorsim_ready();
170 }
171
172 void ynorsim_shutdown(void)
173 {
174   ynorsim_save_image();
175   initialised=0;
176 }
177
178 u32 *ynorsim_get_base(void)
179 {
180   return word;
181 }