⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ecc.c

📁 <B>SMSC USB2.0 Flash硬盘驱动源码</B>
💻 C
字号:
/*============================================================================
  ____________________________________________________________________________
                                ______________________________________________
   SSSS  M   M          CCCC          Standard Microsystems Corporation
  S      MM MM   SSSS  C                    Austin Design Center
   SSS   M M M  S      C                 11000 N. Mopac Expressway
      S  M   M   SSS   C                Stonelake Bldg. 6, Suite 500
  SSSS   M   M      S   CCCC                Austin, Texas 78759
                SSSS            ______________________________________________
  ____________________________________________________________________________
  Copyright(C) 1999, Standard Microsystems Corporation
  All Rights Reserved.
  This program code listing is proprietary to SMSC and may not be copied,
  distributed, or used without a license to do so.  Such license may have
  Limited or Restricted Rights. Please refer to the license for further
  clarification.
  ____________________________________________________________________________
  Notice: The program contained in this listing is a proprietary trade
  secret of SMSC, Hauppauge, New York, and is copyrighted
  under the United States Copyright Act of 1976 as an unpublished work,
  pursuant to Section 104 and Section 408 of Title XVII of the United
  States code. Unauthorized copying, adaption, distribution, use, or
  display is prohibited by this law.
  ____________________________________________________________________________
  Use, duplication, or disclosure by the Government is subject to
  restrictions as set forth in subparagraph(c)(1)(ii) of the Rights
  in Technical Data and Computer Software clause at DFARS 52.227-7013.
  Contractor/Manufacturer is Standard Microsystems Corporation,
  80 Arkay Drive, Hauppauge, New York, 1178-8847.
  ____________________________________________________________________________
  ____________________________________________________________________________
  ecc.c - smart media mass storage class implementation file
  ____________________________________________________________________________
  comments tbd
  ____________________________________________________________________________
  Revision History
  Date      Who  Comment
  ________  ___  _____________________________________________________________
  11/##/01  cds  initial version
============================================================================*/
#include "project.h"

static code uint8 ecctable[256] = {
  0x00,0x55,0x56,0x03,0x59,0x0C,0x0F,0x5A,0x5A,0x0F,0x0C,0x59,0x03,0x56,0x55,0x00,
  0x65,0x30,0x33,0x66,0x3C,0x69,0x6A,0x3F,0x3F,0x6A,0x69,0x3C,0x66,0x33,0x30,0x65,
  0x66,0x33,0x30,0x65,0x3F,0x6A,0x69,0x3C,0x3C,0x69,0x6A,0x3F,0x65,0x30,0x33,0x66,
  0x03,0x56,0x55,0x00,0x5A,0x0F,0x0C,0x59,0x59,0x0C,0x0F,0x5A,0x00,0x55,0x56,0x03,
  0x69,0x3C,0x3F,0x6A,0x30,0x65,0x66,0x33,0x33,0x66,0x65,0x30,0x6A,0x3F,0x3C,0x69,
  0x0C,0x59,0x5A,0x0F,0x55,0x00,0x03,0x56,0x56,0x03,0x00,0x55,0x0F,0x5A,0x59,0x0C,
  0x0F,0x5A,0x59,0x0C,0x56,0x03,0x00,0x55,0x55,0x00,0x03,0x56,0x0C,0x59,0x5A,0x0F,
  0x6A,0x3F,0x3C,0x69,0x33,0x66,0x65,0x30,0x30,0x65,0x66,0x33,0x69,0x3C,0x3F,0x6A,
  0x6A,0x3F,0x3C,0x69,0x33,0x66,0x65,0x30,0x30,0x65,0x66,0x33,0x69,0x3C,0x3F,0x6A,
  0x0F,0x5A,0x59,0x0C,0x56,0x03,0x00,0x55,0x55,0x00,0x03,0x56,0x0C,0x59,0x5A,0x0F,
  0x0C,0x59,0x5A,0x0F,0x55,0x00,0x03,0x56,0x56,0x03,0x00,0x55,0x0F,0x5A,0x59,0x0C,
  0x69,0x3C,0x3F,0x6A,0x30,0x65,0x66,0x33,0x33,0x66,0x65,0x30,0x6A,0x3F,0x3C,0x69,
  0x03,0x56,0x55,0x00,0x5A,0x0F,0x0C,0x59,0x59,0x0C,0x0F,0x5A,0x00,0x55,0x56,0x03,
  0x66,0x33,0x30,0x65,0x3F,0x6A,0x69,0x3C,0x3C,0x69,0x6A,0x3F,0x65,0x30,0x33,0x66,
  0x65,0x30,0x33,0x66,0x3C,0x69,0x6A,0x3F,0x3F,0x6A,0x69,0x3C,0x66,0x33,0x30,0x65,
  0x00,0x55,0x56,0x03,0x59,0x0C,0x0F,0x5A,0x5A,0x0F,0x0C,0x59,0x03,0x56,0x55,0x00
};

static void   _ecc_trans_result(uint8,uint8,uint8 *,uint8 *) reentrant ;
static uint8  _ecc_correct_data(uint8*, uint8* )reentrant ;

#define kbm_bit7        0x80
#define kbm_bit6        0x40
#define kbm_bit5        0x20
#define kbm_bit4        0x10
#define kbm_bit3        0x08
#define kbm_bit2        0x04
#define kbm_bit1        0x02
#define kbm_bit0        0x01
#define kbm_bit10       0x03
#define kbm_bit23       0x00800000L
#define kbm_cps         0x3f
#define kbm_correctable 0x00555554L

//------------------------------------------------------------------------------
// Transpose (de-interleave) result
// LP14,12,10,... & LP15,13,11,... -> LP15,14,13,... & LP7,6,5,..
//------------------------------------------------------------------------------
static void _ecc_trans_result(
  uint8 reg2,    /* LP14,LP12,LP10,... */
  uint8 reg3,    /* LP15,LP13,LP11,... */
  uint8 *ecc1,   /* LP15,LP14,LP13,... */
  uint8 *ecc2) reentrant   /* LP07,LP06,LP05,... */
{
  uint8 a;     /* Working for reg2,reg3 */
  uint8 b;     /* Working for ecc1,ecc2 */
  uint8 i;     /* For counting */
  a=kbm_bit7; b=kbm_bit7;      /* 80h=10000000b */
  *ecc1=*ecc2=0;       /* Clear ecc1,ecc2 */
  for (i=0; i<4; ++i)
  {
    if ((reg3&a)!=0) *ecc1|=b;  /* LP15,13,11,9 -> ecc1 */
    b=b>>1;            /* Right shift */
    if ((reg2&a)!=0) *ecc1|=b;  /* LP14,12,10,8 -> ecc1 */
    b=b>>1;            /* Right shift */
    a=a>>1;            /* Right shift */
  }
  b=kbm_bit7;              /* 80h=10000000b */
  for (i=0; i<4; ++i)
  {
    if ((reg3&a)!=0) *ecc2|=b;  /* LP7,5,3,1 -> ecc2 */
    b=b>>1;            /* Right shift */
    if ((reg2&a)!=0) *ecc2|=b;  /* LP6,4,2,0 -> ecc2 */
    b=b>>1;            /* Right shift */
    a=a>>1;            /* Right shift */
  }
}

xdata uint8 x_eccbuf[6];
xdata uint8 buf_ecc_lp_hi ; /* lp 15-8 */
xdata uint8 buf_ecc_lp_lo ; /* lp 7-0 */
xdata uint8 buf_ecc_cp ;    /* cp 5-0, 1, 1 */

xdata uint8 ecc_lp_hi ;     /* LP 15-8 */
xdata uint8 ecc_lp_lo ;     /* LP 7-0  */
xdata uint8 ecc_cp ;     /* CP 5-0,"1","1" */ 

//+----------------------------------------------------------------------
// Calculating ECC
// data[0-255] -> ecc1,ecc2,ecc3 using CP0-CP5 code table[0-255]
//-----------------------------------------------------------------------
void ecc_sw_calculate(uint8 *buf) reentrant
{
  unsigned int i;      /* For counting */
  uint8 a;     /* Working for table */
  uint8 reg1;  /* D-all,CP5,CP4,CP3,... */
  uint8 reg2;  /* LP14,LP12,L10,... */
  uint8 reg3;  /* LP15,LP13,L11,... */
  reg1=reg2=reg3=0;    /* Clear parameter */
  for (i=0; i<256; ++i)
  {
    a=ecctable[buf[i]];  // lookup column parity code (CP0-CP5) from table */
    reg1^=(a&kbm_cps);   // XOR with a */
    if ((a&kbm_bit6)!=0)
    {                  /* If D_all(all bit XOR) = 1 */
      reg3^=(uint8)i;  /* XOR with counter */
      reg2^=~((uint8)i);  /* XOR with inv. of counter */
    }
  }
  
  // transpose LP14,12,10,... & LP15,13,11,... -> LP15,14,13,... & LP7,6,5,..
  _ecc_trans_result(reg2,reg3,&ecc_lp_hi,&ecc_lp_lo);

  // invert & store ecc calculation in global ecc registers
  ecc_lp_hi=~(ecc_lp_hi); 
  ecc_lp_lo=~(ecc_lp_lo);  /* Inv. lp */
  ecc_cp=((~reg1)<<2)|kbm_bit10;  /* Make TEL format */
}


//+----------------------------------------------------------------------
// "ecccor.c" _ecc_correct_data() modified
// data[256-258] --> eccdata[0-2]
//-----------------------------------------------------------------------
static xdata unsigned long _ecc_l;     /* Working to check d */
static xdata unsigned long _ecc_d;     /* Result of comparison */
static uint8 ecc_correct_data( uint8 *buf ) reentrant    
{
  unsigned int i;      /* For counting */
  uint8 d1,d2,d3;  /* Result of comparison */
  uint8 a;     /* Working for add */
  uint8 add;   /* Byte address of cor. DATA */
  uint8 b;     /* Working for bit */
  uint8 bitaddr;   /* Bit address of cor. DATA */

  /* Compare line parity  */
  d1=ecc_lp_hi^buf_ecc_lp_hi ;
  d2=ecc_lp_lo^buf_ecc_lp_lo ;  
   /* Compare column parity's */
  d3=ecc_cp^buf_ecc_cp;                      

 /* Result of comparison */
  _ecc_d=((unsigned long)d1<<16)+((unsigned long)d2<<8) +(unsigned long)d3;
  
  if (_ecc_d==0) 
    return k_success ; /* If No error, return */


  /* If correctable */
  if (((_ecc_d^(_ecc_d>>1))&kbm_correctable)==kbm_correctable)
  {                    
    _ecc_l=kbm_bit23;
    add=0;             /* Clear parameter */

    a=kbm_bit7;
    for (i=0; i<8; ++i)
    { 
      /* Checking 8 bit */
      if ((_ecc_d&_ecc_l)!=0) 
        add|=a;  /* Make byte address from LP's */
      
      _ecc_l>>=2;
      a>>=1;          /* Right Shift */
    }

    bitaddr=0;             /* Clear parameter */
    b=kbm_bit2;
    for (i=0; i<3; ++i)
    {                  /* Checking 3 bit */
      if ((_ecc_d&_ecc_l)!=0) 
        bitaddr|=b;  /* Make bit address from CP's */
      
      _ecc_l>>=2; 
      b>>=1;    /* Right shift */
    }
    b=kbm_bit0;
//    TRACE2(191, ecc, 0, "single error bit in buffer.  address byte.bit:%d.%d", add, bitaddr) ;
    buf[add]^=(b<<bitaddr);  /* Put corrected data */

    return k_ecc_corrected_buf_err;
  }

  i=0;                 
  _ecc_d&=0x00ffffffL;      
  while (_ecc_d)
  {                    /* If d=0 finish counting */
    if (_ecc_d&kbm_bit0) ++i;   /* Count number of 1 bit */
    _ecc_d>>=1;             /* Right shift */
  }
  if (i==1)
  {
    /* Put in correct ecc data */
    buf_ecc_lp_hi=ecc_lp_hi; 
    buf_ecc_lp_lo=ecc_lp_lo;  
    buf_ecc_cp=ecc_cp;
    return k_ecc_corrected_ecc_code_err ;
  }
//  TRACE0(214, ecc, 0, "uncorrectable error detected.") ;
  return k_ecc_uncorrectable_err ;           /* Uncorrectable error */
}

//-----------------------------------------------------------------------
// ##### End of 'ecctable.c' and 'ecccor.c' ###################################
//-----------------------------------------------------------------------



//-----------------------------------------------------------------------
// name:
//  t_result ecc_sw_correct()
//
// purpose:
//  correct a 256-byte buffer of data, given read ecc and calculated ecc.
//
// notes:
//  this function assumes that ecc_lp_hi, ecc_lp_lo, and ecc_cp 
//  contain the 'post-read calculated ecc'
//
// source:
//-----------------------------------------------------------------------
// t_result ecc_sw_correct(uint8 *buf, uint8 *buf_ecc, uint8* calc_ecc ) reentrant 

#define _set_buf_ecc(__buffer_ecc_data) \
  { buf_ecc_lp_hi = __buffer_ecc_data[1];buf_ecc_lp_lo=__buffer_ecc_data[0];buf_ecc_cp=__buffer_ecc_data[2]; }

#define _get_buf_ecc(__buffer_ecc_data) \
  { __buffer_ecc_data[1]=buf_ecc_lp_hi; __buffer_ecc_data[0]=buf_ecc_lp_lo ;__buffer_ecc_data[2]=buf_ecc_cp; }

#define _set_ecc(__ecc_data) \
  { ecc_lp_hi = __ecc_data[1]; ecc_lp_lo = __ecc_data[0]; ecc_cp = __ecc_data[2] ; }

#define _get_ecc(__ecc_data) \
  { __ecc_data[1] = ecc_lp_hi; __ecc_data[0] = buf_ecc_lp_lo ; __ecc_data[2] = buf_ecc_cp; }

//+----------------------------------------------------------------------
//-----------------------------------------------------------------------
t_result ecc_sw_correct(uint8 *buf, uint8 *buf_ecc, uint8* calc_ecc ) reentrant 
{
  unsigned int err;

  _set_buf_ecc(buf_ecc) ;
  _set_ecc(calc_ecc) ;
  
/*
  buf_ecc_lp_hi = buf_ecc[1] ;
  buf_ecc_lp_lo = buf_ecc[0] ;
  buf_ecc_cp = buf_ecc[2] ;
*/

// err=_ecc_correct_data(buf,redundant_ecc,*(calculate_ecc+1),*(calculate_ecc),*(calculate_ecc+2));
  err=ecc_correct_data(buf) ; 

/*
  *(calc_ecc+1) = ecc_lp_hi ;
  *(calc_ecc)   = ecc_lp_lo ;
  *(calc_ecc+2) = ecc_cp ;
*/
  _get_ecc(calc_ecc) ;

  if (err==1) 
  {
    _get_buf_ecc(buf_ecc) ;
  }

  if (err==0 || err==1 || err==2) 
    return k_success ;

  return k_error ;
}

//+----------------------------------------------------------------------
//-----------------------------------------------------------------------
t_result ecc_sw_correct_ex(uint8 *buf ) reentrant 
{
  unsigned int err;
  
  err=ecc_correct_data(buf) ; 

  if (err==k_ecc_corrected_buf_err) 
  {
    buf_ecc_lp_hi = ecc_lp_hi ;
    buf_ecc_lp_lo = ecc_lp_lo ;
    buf_ecc_cp    = ecc_cp ;
  }

  return ( k_ecc_uncorrectable_err == err) ? k_error : k_success ;
}

//+----------------------------------------------------------------------
//-----------------------------------------------------------------------
t_result ecc_check_rd_error() reentrant 
{
// return ((buff_ecc_a == ecc_a)&&(buff_ecc_b == ecc_b));
  if (! memcmp((char *)(x_sm_redt_data+0x0D),(char *) x_eccbuf,3))
    if (! memcmp((char *)(x_sm_redt_data+0x08),(char *)(x_eccbuf+0x03),3))
      return k_success;
  return k_error ;
   
}

//+----------------------------------------------------------------------
//-----------------------------------------------------------------------
t_result ecc_check_and_correct(unsigned char *buf) reentrant
{
  // check first 256 bytes against first 3 ecc parameters
  if (memcmp((char *)(x_sm_redt_data+0x0D),(char *)x_eccbuf,3))
    if (ecc_sw_correct(buf,x_sm_redt_data+0x0D,x_eccbuf))
      return k_error ;

  // check second 256 bytes agains second 3 ecc parameters
  buf+=0x100;
  if (memcmp((char *)(x_sm_redt_data+0x08),(char *)(x_eccbuf+0x03),3))
    if (ecc_sw_correct(buf,x_sm_redt_data+0x08,x_eccbuf+0x03))
      return k_error ;

  return k_success;
}



⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -