00001
00007 #include "uffs/uffs_fs.h"
00008 #include "uffs/uffs_config.h"
00009 #include <string.h>
00010
00011 #define PFX "ecc:"
00012
00013
00014 static const unsigned char column_parity_table[] = {
00015 0x00, 0x55, 0x59, 0x0c, 0x65, 0x30, 0x3c, 0x69, 0x69, 0x3c, 0x30, 0x65, 0x0c, 0x59, 0x55, 0x00,
00016 0x95, 0xc0, 0xcc, 0x99, 0xf0, 0xa5, 0xa9, 0xfc, 0xfc, 0xa9, 0xa5, 0xf0, 0x99, 0xcc, 0xc0, 0x95,
00017 0x99, 0xcc, 0xc0, 0x95, 0xfc, 0xa9, 0xa5, 0xf0, 0xf0, 0xa5, 0xa9, 0xfc, 0x95, 0xc0, 0xcc, 0x99,
00018 0x0c, 0x59, 0x55, 0x00, 0x69, 0x3c, 0x30, 0x65, 0x65, 0x30, 0x3c, 0x69, 0x00, 0x55, 0x59, 0x0c,
00019 0xa5, 0xf0, 0xfc, 0xa9, 0xc0, 0x95, 0x99, 0xcc, 0xcc, 0x99, 0x95, 0xc0, 0xa9, 0xfc, 0xf0, 0xa5,
00020 0x30, 0x65, 0x69, 0x3c, 0x55, 0x00, 0x0c, 0x59, 0x59, 0x0c, 0x00, 0x55, 0x3c, 0x69, 0x65, 0x30,
00021 0x3c, 0x69, 0x65, 0x30, 0x59, 0x0c, 0x00, 0x55, 0x55, 0x00, 0x0c, 0x59, 0x30, 0x65, 0x69, 0x3c,
00022 0xa9, 0xfc, 0xf0, 0xa5, 0xcc, 0x99, 0x95, 0xc0, 0xc0, 0x95, 0x99, 0xcc, 0xa5, 0xf0, 0xfc, 0xa9,
00023 0xa9, 0xfc, 0xf0, 0xa5, 0xcc, 0x99, 0x95, 0xc0, 0xc0, 0x95, 0x99, 0xcc, 0xa5, 0xf0, 0xfc, 0xa9,
00024 0x3c, 0x69, 0x65, 0x30, 0x59, 0x0c, 0x00, 0x55, 0x55, 0x00, 0x0c, 0x59, 0x30, 0x65, 0x69, 0x3c,
00025 0x30, 0x65, 0x69, 0x3c, 0x55, 0x00, 0x0c, 0x59, 0x59, 0x0c, 0x00, 0x55, 0x3c, 0x69, 0x65, 0x30,
00026 0xa5, 0xf0, 0xfc, 0xa9, 0xc0, 0x95, 0x99, 0xcc, 0xcc, 0x99, 0x95, 0xc0, 0xa9, 0xfc, 0xf0, 0xa5,
00027 0x0c, 0x59, 0x55, 0x00, 0x69, 0x3c, 0x30, 0x65, 0x65, 0x30, 0x3c, 0x69, 0x00, 0x55, 0x59, 0x0c,
00028 0x99, 0xcc, 0xc0, 0x95, 0xfc, 0xa9, 0xa5, 0xf0, 0xf0, 0xa5, 0xa9, 0xfc, 0x95, 0xc0, 0xcc, 0x99,
00029 0x95, 0xc0, 0xcc, 0x99, 0xf0, 0xa5, 0xa9, 0xfc, 0xfc, 0xa9, 0xa5, 0xf0, 0x99, 0xcc, 0xc0, 0x95,
00030 0x00, 0x55, 0x59, 0x0c, 0x65, 0x30, 0x3c, 0x69, 0x69, 0x3c, 0x30, 0x65, 0x0c, 0x59, 0x55, 0x00,
00031 };
00032
00033
00034 static int uffs_CountBits(unsigned char x)
00035 {
00036 int r = 0;
00037
00038 while(x)
00039 {
00040 if(x & 1) r++;
00041 x >>= 1;
00042 }
00043 return r;
00044 }
00045
00046 int uffs_GetEccSize512(uffs_Device *dev)
00047 {
00048 return 6;
00049 }
00050
00051 void uffs_MakeEcc512(uffs_Device *dev, void *data, void *ecc)
00052 {
00053 unsigned char *pecc = (unsigned char *)ecc;
00054 unsigned int i;
00055 unsigned char *p = (unsigned char *)data;
00056 unsigned char col_parity = 0;
00057 unsigned char line_parity = 0;
00058 unsigned char line_parity_prime = 0;
00059 unsigned char t;
00060 unsigned char b;
00061
00062
00063 for(i = 0; i < 256; i++)
00064 {
00065 b = column_parity_table[*p++];
00066 col_parity ^= b;
00067
00068 if(b & 0x01)
00069 {
00070 line_parity ^= i;
00071 line_parity_prime ^= ~i;
00072 }
00073
00074 }
00075
00076 pecc[2] = (~col_parity) | 0x03;
00077
00078 t = 0;
00079 if(line_parity & 0x80) t |= 0x80;
00080 if(line_parity_prime & 0x80) t |= 0x40;
00081 if(line_parity & 0x40) t |= 0x20;
00082 if(line_parity_prime & 0x40) t |= 0x10;
00083 if(line_parity & 0x20) t |= 0x08;
00084 if(line_parity_prime & 0x20) t |= 0x04;
00085 if(line_parity & 0x10) t |= 0x02;
00086 if(line_parity_prime & 0x10) t |= 0x01;
00087 pecc[1] = ~t;
00088
00089 t = 0;
00090 if(line_parity & 0x08) t |= 0x80;
00091 if(line_parity_prime & 0x08) t |= 0x40;
00092 if(line_parity & 0x04) t |= 0x20;
00093 if(line_parity_prime & 0x04) t |= 0x10;
00094 if(line_parity & 0x02) t |= 0x08;
00095 if(line_parity_prime & 0x02) t |= 0x04;
00096 if(line_parity & 0x01) t |= 0x02;
00097 if(line_parity_prime & 0x01) t |= 0x01;
00098 pecc[0] = ~t;
00099
00100
00101
00102 col_parity = 0;
00103 line_parity = 0;
00104 line_parity_prime = 0;
00105
00106 for(i = 0; i < 253; i++)
00107 {
00108 b = column_parity_table[*p++];
00109 col_parity ^= b;
00110
00111 if(b & 0x01)
00112 {
00113 line_parity ^= i;
00114 line_parity_prime ^= ~i;
00115 }
00116
00117 }
00118
00119 for(i = 0; i < 6; i++)
00120 {
00121 b = column_parity_table[0];
00122 col_parity ^= b;
00123
00124 if(b & 0x01)
00125 {
00126 line_parity ^= i;
00127 line_parity_prime ^= ~i;
00128 }
00129
00130 }
00131 pecc[5] = (~col_parity) | 0x03;
00132
00133 t = 0;
00134 if(line_parity & 0x80) t |= 0x80;
00135 if(line_parity_prime & 0x80) t |= 0x40;
00136 if(line_parity & 0x40) t |= 0x20;
00137 if(line_parity_prime & 0x40) t |= 0x10;
00138 if(line_parity & 0x20) t |= 0x08;
00139 if(line_parity_prime & 0x20) t |= 0x04;
00140 if(line_parity & 0x10) t |= 0x02;
00141 if(line_parity_prime & 0x10) t |= 0x01;
00142 pecc[4] = ~t;
00143
00144 t = 0;
00145 if(line_parity & 0x08) t |= 0x80;
00146 if(line_parity_prime & 0x08) t |= 0x40;
00147 if(line_parity & 0x04) t |= 0x20;
00148 if(line_parity_prime & 0x04) t |= 0x10;
00149 if(line_parity & 0x02) t |= 0x08;
00150 if(line_parity_prime & 0x02) t |= 0x04;
00151 if(line_parity & 0x01) t |= 0x02;
00152 if(line_parity_prime & 0x01) t |= 0x01;
00153 pecc[3] = ~t;
00154
00155 }
00156
00157 int uffs_EccCorrect512(uffs_Device *dev, void *data, void *read_ecc, const void *test_ecc)
00158 {
00159 unsigned char d0, d1, d2;
00160 unsigned char *p = (unsigned char *)data;
00161 unsigned char *pread_ecc = (unsigned char *)read_ecc, *ptest_ecc = (unsigned char *)test_ecc;
00162
00163 int ret1, ret2;
00164
00165 d0 = pread_ecc[0] ^ ptest_ecc[0];
00166 d1 = pread_ecc[1] ^ ptest_ecc[1];
00167 d2 = pread_ecc[2] ^ ptest_ecc[2];
00168
00169 if((d0 | d1 | d2) == 0)
00170 {
00171 ret1 = 0;
00172 goto second_stage;
00173 }
00174
00175 if( ((d0 ^ (d0 >> 1)) & 0x55) == 0x55 &&
00176 ((d1 ^ (d1 >> 1)) & 0x55) == 0x55 &&
00177 ((d2 ^ (d2 >> 1)) & 0x54) == 0x54)
00178 {
00179
00180
00181 unsigned byte;
00182 unsigned bit;
00183
00184 bit = byte = 0;
00185
00186
00187 if(d1 & 0x80) byte |= 0x80;
00188 if(d1 & 0x20) byte |= 0x40;
00189 if(d1 & 0x08) byte |= 0x20;
00190 if(d1 & 0x02) byte |= 0x10;
00191 if(d0 & 0x80) byte |= 0x08;
00192 if(d0 & 0x20) byte |= 0x04;
00193 if(d0 & 0x08) byte |= 0x02;
00194 if(d0 & 0x02) byte |= 0x01;
00195
00196 if(d2 & 0x80) bit |= 0x04;
00197 if(d2 & 0x20) bit |= 0x02;
00198 if(d2 & 0x08) bit |= 0x01;
00199
00200 p[byte] ^= (1 << bit);
00201
00202 ret1 = 1;
00203 goto second_stage;
00204 }
00205
00206 if((uffs_CountBits(d0)+uffs_CountBits(d1)+uffs_CountBits(d2)) == 1)
00207 {
00208
00209
00210 pread_ecc[0] = ptest_ecc[0];
00211 pread_ecc[1] = ptest_ecc[1];
00212 pread_ecc[2] = ptest_ecc[2];
00213
00214 ret1 = 1;
00215 goto second_stage;
00216 }
00217
00218
00219
00220 return -1;
00221
00222 second_stage:
00223 p += 256;
00224
00225 d0 = pread_ecc[3] ^ ptest_ecc[3];
00226 d1 = pread_ecc[4] ^ ptest_ecc[4];
00227 d2 = pread_ecc[5] ^ ptest_ecc[5];
00228
00229 if((d0 | d1 | d2) == 0)
00230 {
00231 ret2 = 0;
00232 goto end;
00233 }
00234
00235 if( ((d0 ^ (d0 >> 1)) & 0x55) == 0x55 &&
00236 ((d1 ^ (d1 >> 1)) & 0x55) == 0x55 &&
00237 ((d2 ^ (d2 >> 1)) & 0x54) == 0x54)
00238 {
00239
00240
00241 unsigned byte;
00242 unsigned bit;
00243
00244 bit = byte = 0;
00245
00246
00247 if(d1 & 0x80) byte |= 0x80;
00248 if(d1 & 0x20) byte |= 0x40;
00249 if(d1 & 0x08) byte |= 0x20;
00250 if(d1 & 0x02) byte |= 0x10;
00251 if(d0 & 0x80) byte |= 0x08;
00252 if(d0 & 0x20) byte |= 0x04;
00253 if(d0 & 0x08) byte |= 0x02;
00254 if(d0 & 0x02) byte |= 0x01;
00255
00256 if(d2 & 0x80) bit |= 0x04;
00257 if(d2 & 0x20) bit |= 0x02;
00258 if(d2 & 0x08) bit |= 0x01;
00259
00260 if(byte > 250) return -1;
00261
00262 p[byte] ^= (1 << bit);
00263
00264 ret2 = 1;
00265 goto end;
00266 }
00267
00268 if((uffs_CountBits(d0)+uffs_CountBits(d1)+uffs_CountBits(d2)) == 1)
00269 {
00270
00271
00272 pread_ecc[3] = ptest_ecc[3];
00273 pread_ecc[4] = ptest_ecc[4];
00274 pread_ecc[5] = ptest_ecc[5];
00275
00276 ret2 = 1;
00277 goto end;
00278 }
00279
00280
00281 return -1;
00282
00283 end:
00284 if(ret1 == 0 && ret2 == 0) return 0;
00285 return 1;
00286 }
00287
00288