6936a9c874e2c9bffb4d995e8ab4d8e870c8fda6
[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
44 static void NorError(void)
45 {
46   printf("Nor error\n");
47   while(1){}
48 }
49
50 static void ynorsim_SaveImage(void)
51 {
52   int h = open(YNORSIM_FNAME, O_RDWR | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE);
53   write(h,word,sizeof(word));
54   close(h);
55 }
56
57 static void ynorsim_RestoreImage(void)
58 {
59   int h = open(YNORSIM_FNAME, O_RDONLY, S_IREAD | S_IWRITE);
60   memset(word,0xFF,sizeof(word));
61   read(h,word,sizeof(word));
62   close(h);
63 }
64
65
66 static void ynorsim_PowerFail(void)
67 {
68   ynorsim_SaveImage();
69   exit(1);
70 }
71
72 static int initialised = 0;
73 static int remaining_ops;
74 static int nops_so_far;
75
76 static void ynorsim_MaybePowerFail(void)
77 {
78
79    nops_so_far++;
80    
81    
82    remaining_ops--;
83    if(remaining_ops < 1){
84        printf("Simulated power failure after %d operations\n",nops_so_far);
85         ynorsim_PowerFail();
86   }
87 }
88
89 static void ynorsim_Ready(void)
90 {
91   if(initialised) 
92     return;
93   srand(random_seed);
94   remaining_ops = 1000000000;
95   remaining_ops = (rand() % 10000) * 3000 * YNORSIM_BIT_CHANGES;
96   ynorsim_RestoreImage();
97 }
98
99 void ynorsim_Read32(__u32 *addr,__u32 *buf, int nwords)
100
101    while(nwords > 0){
102      *buf = *addr;
103      buf++;
104      addr++;
105      nwords--;
106    }
107 }
108
109 void ynorsim_WriteOneWord32(__u32 *addr,__u32 val)
110 {
111   __u32 tmp;
112   __u32 m;
113   int i;
114
115   tmp = *addr;
116   if(val & ~tmp){
117     // Fail due to trying to change a zero into a 1
118     printf("attempt to set a zero to one (%x)->(%x)\n",tmp,val);
119     NorError();
120   }
121   
122   for(i = 0; i < YNORSIM_BIT_CHANGES; i++){
123     m = 1 << (rand() & 31);
124     if(!(m & val)){
125       tmp &= ~m;
126       *addr = tmp;
127       ynorsim_MaybePowerFail();
128     }
129        
130   }
131   
132   *addr = tmp & val;
133   ynorsim_MaybePowerFail();
134 }
135
136 void ynorsim_Write32(__u32 *addr, __u32 *buf, int nwords)
137 {
138   while(nwords >0){
139     ynorsim_WriteOneWord32(addr,*buf);
140     addr++;
141     buf++;
142     nwords--;
143   }
144 }
145
146 void ynorsim_EraseBlock(__u32 *addr)
147 {
148   /* Todo... bit flipping */
149   memset(addr,0xFF,YNORSIM_BLOCK_SIZE_U32 * 4);
150 }
151
152 void ynorsim_Initialise(void)
153 {
154   ynorsim_Ready();
155 }
156
157 void ynorsim_Shutdown(void)
158 {
159   ynorsim_SaveImage();
160   initialised=0;
161 }
162
163 __u32 *ynorsim_GetBase(void)
164 {
165   return word;
166 }