smc_ecc.c
上传用户:yj_qqy
上传日期:2017-01-28
资源大小:2911k
文件大小:13k
源码类别:

uCOS

开发平台:

C/C++

  1. /*
  2. **********************************************************************
  3. *                          Micrium, Inc.
  4. *                      949 Crestview Circle
  5. *                     Weston,  FL 33327-1848
  6. *
  7. *                            uC/FS
  8. *
  9. *             (c) Copyright 2001 - 2003, Micrium, Inc.
  10. *                      All rights reserved.
  11. *
  12. ***********************************************************************
  13. ----------------------------------------------------------------------
  14. File        : smc_ecc.c
  15. Purpose     : ECC functions for SMC driver
  16. ----------------------------------------------------------------------
  17. Known problems or limitations with current version
  18. ----------------------------------------------------------------------
  19. None.
  20. ---------------------------END-OF-HEADER------------------------------
  21. */
  22. /*********************************************************************
  23. *
  24. *             #include Section
  25. *
  26. **********************************************************************
  27. */
  28. #include "fs_port.h"
  29. #ifndef FS_FARCHARPTR
  30. #define FS_FARCHARPTR char *
  31. #endif
  32. #include "fs_dev.h"
  33. #include "fs_conf.h"
  34. #if FS_USE_SMC_DRIVER
  35. #include "smc.h"
  36. /*********************************************************************
  37. *
  38. *             #define constants
  39. *
  40. **********************************************************************
  41. */
  42. #define SUCCESS          0          /* SUCCESS     */
  43. #define ERROR           -1          /* ERROR       */
  44. #define CORRECT          1          /* CORRECTABLE */
  45. #define    BIT7    0x80
  46. #define    BIT6    0x40
  47. #define    BIT5    0x20
  48. #define    BIT4    0x10
  49. #define    BIT3    0x08
  50. #define    BIT2    0x04
  51. #define    BIT1    0x02
  52. #define    BIT0    0x01
  53. #define    BIT1BIT0    0x03
  54. #define    BIT23       0x00800000L
  55. #define    MASK_CPS    0x3f
  56. #define    CORRECTABLE 0x00555554L
  57. /*********************************************************************
  58. *
  59. *             Local Variables        
  60. *
  61. **********************************************************************
  62. */
  63. static const unsigned char _FS_SMC_ecctable[256] = {
  64.     0x00,0x55,0x56,0x03,0x59,0x0C,0x0F,0x5A,0x5A,0x0F,0x0C,0x59,0x03,0x56,0x55,0x00,
  65.     0x65,0x30,0x33,0x66,0x3C,0x69,0x6A,0x3F,0x3F,0x6A,0x69,0x3C,0x66,0x33,0x30,0x65,
  66.     0x66,0x33,0x30,0x65,0x3F,0x6A,0x69,0x3C,0x3C,0x69,0x6A,0x3F,0x65,0x30,0x33,0x66,
  67.     0x03,0x56,0x55,0x00,0x5A,0x0F,0x0C,0x59,0x59,0x0C,0x0F,0x5A,0x00,0x55,0x56,0x03,
  68.     0x69,0x3C,0x3F,0x6A,0x30,0x65,0x66,0x33,0x33,0x66,0x65,0x30,0x6A,0x3F,0x3C,0x69,
  69.     0x0C,0x59,0x5A,0x0F,0x55,0x00,0x03,0x56,0x56,0x03,0x00,0x55,0x0F,0x5A,0x59,0x0C,
  70.     0x0F,0x5A,0x59,0x0C,0x56,0x03,0x00,0x55,0x55,0x00,0x03,0x56,0x0C,0x59,0x5A,0x0F,
  71.     0x6A,0x3F,0x3C,0x69,0x33,0x66,0x65,0x30,0x30,0x65,0x66,0x33,0x69,0x3C,0x3F,0x6A,
  72.     0x6A,0x3F,0x3C,0x69,0x33,0x66,0x65,0x30,0x30,0x65,0x66,0x33,0x69,0x3C,0x3F,0x6A,
  73.     0x0F,0x5A,0x59,0x0C,0x56,0x03,0x00,0x55,0x55,0x00,0x03,0x56,0x0C,0x59,0x5A,0x0F,
  74.     0x0C,0x59,0x5A,0x0F,0x55,0x00,0x03,0x56,0x56,0x03,0x00,0x55,0x0F,0x5A,0x59,0x0C,
  75.     0x69,0x3C,0x3F,0x6A,0x30,0x65,0x66,0x33,0x33,0x66,0x65,0x30,0x6A,0x3F,0x3C,0x69,
  76.     0x03,0x56,0x55,0x00,0x5A,0x0F,0x0C,0x59,0x59,0x0C,0x0F,0x5A,0x00,0x55,0x56,0x03,
  77.     0x66,0x33,0x30,0x65,0x3F,0x6A,0x69,0x3C,0x3C,0x69,0x6A,0x3F,0x65,0x30,0x33,0x66,
  78.     0x65,0x30,0x33,0x66,0x3C,0x69,0x6A,0x3F,0x3F,0x6A,0x69,0x3C,0x66,0x33,0x30,0x65,
  79.     0x00,0x55,0x56,0x03,0x59,0x0C,0x0F,0x5A,0x5A,0x0F,0x0C,0x59,0x03,0x56,0x55,0x00
  80. };
  81. static const unsigned char _FS_SMC_cis[]={ 0x01,0x03,0xD9,0x01,0xFF,0x18,0x02,0xDF,0x01,0x20 };
  82. /*********************************************************************
  83. *
  84. *             Local functions
  85. *
  86. **********************************************************************
  87. */
  88. /*********************************************************************
  89. *
  90. *             _FS_SMC_StringCmp
  91. */
  92. static int _FS_SMC_StringCmp(FS_FARCHARPTR stringA, FS_FARCHARPTR stringB, int count)
  93. {
  94.     int i;
  95.     for (i=0;i<count;i++)
  96.         if (*stringA++ != *stringB++)   return(ERROR);
  97.     return(SUCCESS);
  98. }
  99. /*********************************************************************
  100. *
  101. *             _FS_SMC_trans_result
  102. *
  103.     Transfer result
  104.     LP14,12,10,... & LP15,13,11,... -> LP15,14,13,... & LP7,6,5,..
  105. */
  106. static void _FS_SMC_trans_result(unsigned char reg2,unsigned char reg3,
  107.                                   unsigned char *ecc1,unsigned char *ecc2)
  108. {
  109.     unsigned char a;                          /* Working for reg2,reg3        */
  110.     unsigned char b;                          /* Working for ecc1,ecc2        */
  111.     unsigned char i;                          /* For counting                 */
  112.     a=BIT7; b=BIT7;                           /* 80h=10000000b                */
  113.     *ecc1=*ecc2=0;                            /* Clear ecc1,ecc2              */
  114.     for(i=0; i<4; ++i) {
  115.         if ((reg3&a)!=0) *ecc1|=b;            /* LP15,13,11,9 -> ecc1         */
  116.         b=b>>1;                               /* Right shift                  */
  117.         if ((reg2&a)!=0) *ecc1|=b;            /* LP14,12,10,8 -> ecc1         */
  118.         b=b>>1;                               /* Right shift                  */
  119.         a=a>>1;                               /* Right shift                  */
  120.     }
  121.     b=BIT7;                                   /* 80h=10000000b                */
  122.     for(i=0; i<4; ++i) {
  123.         if ((reg3&a)!=0) *ecc2|=b;            /* LP7,5,3,1 -> ecc2            */
  124.         b=b>>1;                               /* Right shift                  */
  125.         if ((reg2&a)!=0) *ecc2|=b;            /* LP6,4,2,0 -> ecc2            */
  126.         b=b>>1;                               /* Right shift                  */
  127.         a=a>>1;                               /* Right shift                  */
  128.     }
  129. }
  130. /*********************************************************************
  131. *
  132. *             _FS_SMC_calculate_ecc
  133. *
  134.     Calculating ECC
  135.     data[0-255] -> ecc1,ecc2,ecc3 using CP0-CP5 code table[0-255]
  136. */
  137. static void _FS_SMC_calculate_ecc(const unsigned char *table,unsigned char *data,
  138.                                     unsigned char *ecc1,unsigned char *ecc2,
  139.                                     unsigned char *ecc3)
  140. {
  141.     unsigned int i;                           /* For counting                 */
  142.     unsigned char a;                          /* Working for table            */
  143.     unsigned char reg1;                       /* D-all,CP5,CP4,CP3,...        */
  144.     unsigned char reg2;                       /* LP14,LP12,L10,...            */
  145.     unsigned char reg3;                       /* LP15,LP13,L11,...            */
  146.     reg1=reg2=reg3=0;                         /* Clear parameter              */
  147.     for(i=0; i<256; ++i) {
  148.         a=table[data[i]];                     /* Get CP0-CP5 code from table  */
  149.         reg1^=(a&MASK_CPS);                   /* XOR with a                   */
  150.         if ((a&BIT6)!=0) {                    /* If D_all(all bit XOR) = 1    */
  151.             reg3^=(unsigned char)i;           /* XOR with counter             */
  152.             reg2^=~((unsigned char)i);        /* XOR with inv. of counter     */
  153.         }
  154.     }
  155.     /* Trans LP14,12,10,... & LP15,13,11,... -> LP15,14,13,... & LP7,6,5,..   */
  156.     _FS_SMC_trans_result(reg2,reg3,ecc1,ecc2);
  157.     *ecc1=~(*ecc1); *ecc2=~(*ecc2);           /* Inv. ecc2 & ecc3             */
  158.     *ecc3=((~reg1)<<2)|BIT1BIT0;              /* Make TEL format              */
  159. }
  160. /*********************************************************************
  161. *
  162. *             _FS_SMC_correct_data
  163. */
  164.                              
  165. static unsigned char _FS_SMC_correct_data(unsigned char *data,unsigned char *eccdata,
  166.                                             unsigned char ecc1,unsigned char ecc2,
  167.                                             unsigned char ecc3)
  168. {
  169.     unsigned long l;                          /* Working to check d           */
  170.     unsigned long d;                          /* Result of comparison         */
  171.     unsigned int i;                           /* For counting                 */
  172.     unsigned char d1,d2,d3;                   /* Result of comparison         */
  173.     unsigned char a;                          /* Working for add              */
  174.     unsigned char add;                        /* Byte address of cor. DATA    */
  175.     unsigned char b;                          /* Working for bit              */
  176.     unsigned char bit;                        /* Bit address of cor. DATA     */
  177.     d1=ecc1^eccdata[1]; d2=ecc2^eccdata[0];   /* Compare LP's                 */
  178.     d3=ecc3^eccdata[2];                       /* Comapre CP's                 */
  179.     d=((unsigned long)d1<<16)                 /* Result of comparison         */
  180.         +((unsigned long)d2<<8)
  181.         +(unsigned long)d3;
  182.     if (d==0) return(0);                      /* If No error, return          */
  183.     if (((d^(d>>1))&CORRECTABLE)==CORRECTABLE) {    /* If correctable         */
  184.         l=BIT23;
  185.         add=0;                                /* Clear parameter              */
  186.         a=BIT7;
  187.         for(i=0; i<8; ++i) {                  /* Checking 8 bit               */
  188.             if ((d&l)!=0) add|=a;             /* Make byte address from LP's  */
  189.             l>>=2; a>>=1;                     /* Right Shift                  */
  190.         }
  191.         bit=0;                                /* Clear parameter              */
  192.         b=BIT2;
  193.         for(i=0; i<3; ++i) {                  /* Checking 3 bit               */
  194.             if ((d&l)!=0) bit|=b;             /* Make bit address from CP's   */
  195.             l>>=2; b>>=1;                     /* Right shift                  */
  196.         }
  197.         b=BIT0;
  198.         data[add]^=(b<<bit);                  /* Put corrected data           */
  199.         return(1);
  200.     }
  201.     i=0;                                      /* Clear count                  */
  202.     d&=0x00ffffffL;                           /* Masking                      */
  203.     while(d) {                                /* If d=0 finish counting       */
  204.         if (d&BIT0) ++i;                      /* Count number of 1 bit        */
  205.         d>>=1;                                /* Right shift                  */
  206.     }
  207.     if (i==1) {                               /* If ECC error                 */
  208.         eccdata[1]=ecc1; eccdata[0]=ecc2;    /* Put right ECC code           */
  209.         eccdata[2]=ecc3;
  210.         return(2);
  211.     }
  212.     return(3);                                /* Uncorrectable error          */
  213. }
  214. /*********************************************************************
  215. *
  216. *             Global functions
  217. *
  218. **********************************************************************
  219. */
  220. /*********************************************************************
  221. *
  222. *             FS__SMC_ECC_Chk_CISdata
  223. */
  224. int FS__SMC_ECC_Chk_CISdata(unsigned char *buf, unsigned char *redundant)
  225. {
  226.     unsigned char ecc1,ecc2,ecc3;
  227.     unsigned int err;
  228.     _FS_SMC_calculate_ecc(_FS_SMC_ecctable,buf,&ecc1,&ecc2,&ecc3);
  229.     err=_FS_SMC_correct_data(buf,redundant+0x0D,ecc1,ecc2,ecc3);
  230.     if(err==0 || err==1 || err==2)
  231.         return(_FS_SMC_StringCmp((FS_FARCHARPTR)buf,(FS_FARCHARPTR)_FS_SMC_cis,10));
  232.     buf+=0x100;
  233.     _FS_SMC_calculate_ecc(_FS_SMC_ecctable,buf,&ecc1,&ecc2,&ecc3);
  234.     err=_FS_SMC_correct_data(buf,redundant+0x08,ecc1,ecc2,ecc3);
  235.     if(err==0 || err==1 || err==2)
  236.         return(_FS_SMC_StringCmp((FS_FARCHARPTR)buf,(FS_FARCHARPTR)_FS_SMC_cis,10));
  237.     return(ERROR);
  238. }
  239. /*********************************************************************
  240. *
  241. *             FS__SMC_ECC_Chk_ECCdata
  242. */
  243. int FS__SMC_ECC_Chk_ECCdata(unsigned char *buf, unsigned char *redundant)
  244. {
  245.     unsigned char ecc1,ecc2,ecc3;
  246.     unsigned int err, corr=SUCCESS;
  247.     _FS_SMC_calculate_ecc(_FS_SMC_ecctable,buf,&ecc1,&ecc2,&ecc3);
  248.     err=_FS_SMC_correct_data(buf,redundant+0x0D,ecc1,ecc2,ecc3);
  249.     if(err==1 || err==2)    corr=CORRECT;
  250.     else if(err)            return(ERROR);
  251.     buf+=0x100;
  252.     _FS_SMC_calculate_ecc(_FS_SMC_ecctable,buf,&ecc1,&ecc2,&ecc3);
  253.     err=_FS_SMC_correct_data(buf,redundant+0x08,ecc1,ecc2,ecc3);
  254.     if(err==1 || err==2)    corr=CORRECT;
  255.     else if(err)            return(ERROR);
  256.     return(corr);
  257. }
  258. /*********************************************************************
  259. *
  260. *             FS__SMC_ECC_Set_ECCdata
  261. */
  262. void FS__SMC_ECC_Set_ECCdata(unsigned char *buf, unsigned char *redundant)
  263. {
  264.     _FS_SMC_calculate_ecc(_FS_SMC_ecctable,buf,redundant+0x0E,redundant+0x0D,redundant+0x0F);
  265.     buf+=0x100;
  266.     _FS_SMC_calculate_ecc(_FS_SMC_ecctable,buf,redundant+0x09,redundant+0x08,redundant+0x0A);
  267. }
  268. #endif /* FS_USE_SMC_DRIVER */