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