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