uffs_ecc.c

Go to the documentation of this file.
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 //first 256 bytes   
00063     for(i = 0; i < 256; i++)
00064     {
00065         b = column_parity_table[*p++];
00066         col_parity ^= b;
00067 
00068         if(b & 0x01) // odd number of bits in the byte
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 //second 250 bytes  
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) // odd number of bits in the byte
00112         {
00113             line_parity ^= i;
00114             line_parity_prime ^= ~i;
00115         }
00116         
00117     }
00118 //left 6 bytes, filled with 0
00119     for(i = 0; i < 6; i++)
00120     {
00121         b = column_parity_table[0];
00122         col_parity ^= b;
00123 
00124         if(b & 0x01) // odd number of bits in the byte
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; // deltas 
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         // Single bit (recoverable) error in data
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         // Reccoverable error in ecc
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     // Unrecoverable error
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         // Single bit (recoverable) error in data
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         // Reccoverable error in ecc
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     // Unrecoverable error
00281     return -1;
00282 
00283 end:
00284     if(ret1 == 0 && ret2 == 0) return 0;
00285     return 1;
00286 }
00287 
00288 

Generated on Sat Mar 17 15:45:45 2007 for uffs-doc by  doxygen 1.5.0