723b72b453b30f0c0d39e659782efe579d197b2e
[yaffs2.git] / direct / ynorsim.c
1
2
3 #include "ynorsim.h"
4
5
6
7 #include <stdio.h>
8 #include <fcntl.h>
9 #include <sys/stat.h>
10 #include <unistd.h>
11 #include <time.h>
12
13 #define YNORSIM_FNAME "ynorsimdata"
14
15 /* Set YNORSIM_BIT_CHANGES to a a value from 1..30 to 
16  *simulate bit flipping as the programming happens. 
17  * A low value results in faster simulation with less chance of encountering a partially programmed
18  * word. 
19  */
20    
21 //#define YNORSIM_BIT_CHANGES 15
22 #define YNORSIM_BIT_CHANGES 1
23
24 #if 0
25 /* Simulate 32MB of flash in 256k byte blocks.
26  * This stuff is x32.
27  */
28
29 #define YNORSIM_BLOCK_SIZE_U32  (256*1024/4)
30 #define YNORSIM_DEV_SIZE_U32    (32*1024 * 1024/4)
31 #else
32 /* Simulate 8MB of flash in 256k byte blocks.
33  * This stuff is x32.
34  */
35
36 #define YNORSIM_BLOCK_SIZE_U32  (256*1024/4)
37 #define YNORSIM_DEV_SIZE_U32    (8*1024 * 1024/4)
38 #endif
39
40 static __u32 word[YNORSIM_DEV_SIZE_U32];
41
42 extern int random_seed;
43 extern int simulate_power_failure;
44
45 static void NorError(void)
46 {
47   printf("Nor error\n");
48   while(1){}
49 }
50
51 static void ynorsim_SaveImage(void)
52 {
53   int h = open(YNORSIM_FNAME, O_RDWR | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE);
54   write(h,word,sizeof(word));
55   close(h);
56 }
57
58 static void ynorsim_RestoreImage(void)
59 {
60   int h = open(YNORSIM_FNAME, O_RDONLY, S_IREAD | S_IWRITE);
61   memset(word,0xFF,sizeof(word));
62   read(h,word,sizeof(word));
63   close(h);
64 }
65
66
67 static void ynorsim_PowerFail(void)
68 {
69   ynorsim_SaveImage();
70   exit(1);
71 }
72
73 static int initialised = 0;
74 static int remaining_ops;
75 static int nops_so_far;
76
77 static void ynorsim_MaybePowerFail(void)
78 {
79
80    nops_so_far++;
81    
82    
83    remaining_ops--;
84    if(simulate_power_failure &&
85       remaining_ops < 1){
86        printf("Simulated power failure after %d operations\n",nops_so_far);
87         ynorsim_PowerFail();
88   }
89 }
90
91 static void ynorsim_Ready(void)
92 {
93   if(initialised) 
94     return;
95   srand(random_seed);
96   remaining_ops = 1000000000;
97   remaining_ops = (rand() % 10000) * 300 * YNORSIM_BIT_CHANGES;
98   ynorsim_RestoreImage();
99 }
100
101 void ynorsim_Read32(__u32 *addr,__u32 *buf, int nwords)
102
103    while(nwords > 0){
104      *buf = *addr;
105      buf++;
106      addr++;
107      nwords--;
108    }
109 }
110
111 void ynorsim_WriteOneWord32(__u32 *addr,__u32 val)
112 {
113   __u32 tmp;
114   __u32 m;
115   int i;
116
117   tmp = *addr;
118   if(val & ~tmp){
119     // Fail due to trying to change a zero into a 1
120     printf("attempt to set a zero to one (%x)->(%x)\n",tmp,val);
121     NorError();
122   }
123   
124   for(i = 0; i < YNORSIM_BIT_CHANGES; i++){
125     m = 1 << (rand() & 31);
126     if(!(m & val)){
127       tmp &= ~m;
128       *addr = tmp;
129       ynorsim_MaybePowerFail();
130     }
131        
132   }
133   
134   *addr = tmp & val;
135   ynorsim_MaybePowerFail();
136 }
137
138 void ynorsim_Write32(__u32 *addr, __u32 *buf, int nwords)
139 {
140   while(nwords >0){
141     ynorsim_WriteOneWord32(addr,*buf);
142     addr++;
143     buf++;
144     nwords--;
145   }
146 }
147
148 void ynorsim_EraseBlock(__u32 *addr)
149 {
150   /* Todo... bit flipping */
151   memset(addr,0xFF,YNORSIM_BLOCK_SIZE_U32 * 4);
152 }
153
154 void ynorsim_Initialise(void)
155 {
156   ynorsim_Ready();
157 }
158
159 void ynorsim_Shutdown(void)
160 {
161   ynorsim_SaveImage();
162   initialised=0;
163 }
164
165 __u32 *ynorsim_GetBase(void)
166 {
167   return word;
168 }