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

📄 sm_media.c

📁 <B>SMSC USB2.0 Flash硬盘驱动源码</B>
💻 C
📖 第 1 页 / 共 3 页
字号:
    x_imr0 &= ~kbm_isr0_fmc_irq ;
    // set direction - in
    _mcu_register_set_bits( x_ep2_ctl, kbm_ep2_ctl_dir) ;

    // enable buffer a (wrtog_valid=1, ramwr_tog=0) ;
    // _mcu_register_set_bits( x_ep2_ctl, kbm_ep2_ctl_wrtog_valid) ;
    _mcu_register_wr(x_ep2_ctl, kbm_ep2_ctl_wrtog_valid|(_mcu_register_rd(x_ep2_ctl) & ~kbm_ep2_ctl_ramrd_tog));
    
    // set fmc ctl reg - 1 sector
    _mcu_register_wr(x_fmc_cnt3, 0x00) ;
    _mcu_register_wr(x_fmc_cnt2, 0x00) ;
    _mcu_register_wr(x_fmc_cnt1, 0x02) ;
    _mcu_register_wr(x_fmc_cnt0, 0x00) ;


    thread_set_timer(1000) ;
    if (k_success != sm_wait_rdy_with_timeout(k_sm_busy_read_timeout))
    {
      nand_cmd_reset_device();
      return k_error ;
    }

    // enable blk xfer
    _mcu_register_wr(x_fmc_ctl, (kbm_fmc_ctl_512_byte_pkt|kbm_fmc_ctl_blk_xfer_en)) ;

    nand_wr_va2pa() ;

    // bad bad bad form.... do a while loop
    while(_mcu_register_rd( x_fmc_ctl)&kbm_fmc_ctl_blk_xfer_en)
    {
      if(thread_got_sync(kbm_sync_timer) )
      {
        trace0(0, sm_media, 0, "copy: timeout trying to read sector.  aborting") ;
        return k_error ;
      }
    }
    err_byte = _mcu_register_rd(x_smc_stat);
    trace1(0, sm, 0, "copy smc_stat:%02x", (_mcu_register_rd(x_smc_stat))) ;
    if (err_byte&(kbm_smc_stat_ecc_err_d_a|kbm_smc_stat_ecc_err_d_b|kbm_smc_stat_ecc_err_c_a|kbm_smc_stat_ecc_err_c_b))
    {
      if(err_byte&(kbm_smc_stat_ecc_err_d_a|kbm_smc_stat_ecc_err_d_b))
      {
        if(retry)
        {
          trace0(0, sm, 0, "copy: double-bit error: retry failed.  block has gone bad.") ;
          result=k_media_copy_error_src;
          data_status=0x00;
          break;
        }
        else
        {
          trace0(0, sm, 0, "copy: double-bit error: retrying read...") ;
          result=k_media_copy_error_src;
          data_status=0x00;
          retry=k_true;
          // reverse data flow direction to prevent host data from sneaking through
          _mcu_register_clr_bits( x_ep2_ctl, kbm_ep2_ctl_dir) ;
        }
      }
      else
      {
        retry=k_false;
      }
      
      if(err_byte&kbm_smc_stat_ecc_err_c_a)
      {
        trace2(0, sm, 0, "copy: correctable 1-bit error addr:%d.%d", ecc_a_add_h, (ecc_a_add_l&0x07)) ;
        sm_correct_sram_bit(4, ecc_a_add_h, (ecc_a_add_l&0x07));
        _mcu_register_wr(x_smc_stat,kbm_smc_stat_ecc_err_c_a);
      }
      if(err_byte&kbm_smc_stat_ecc_err_c_b)
      {
        trace2(0, sm, 0, "copy: correctable 1-bit error addr:%d.%d", (((uint16)ecc_b_add_h)+0x100), (ecc_b_add_l&0x07)) ;
        sm_correct_sram_bit(4, (ecc_b_add_h+0x100), (ecc_b_add_l&0x07)) ;
        _mcu_register_wr(x_smc_stat,kbm_smc_stat_ecc_err_c_b);
      }
    }
    else
    {
      retry=k_false;
    }

  }while(retry);


  if(map_log_blk_has_bad_data())
  {
    trace0(0, sm, 0, "block has bad data somewhere. read src extra data to correctly copy over 'data status' flag");
    data_status= (sm_check_data_status(g_addr_page, 1)?0x00:data_status);
    // reset chip to get back to read/
    nand_cmd_reset_device();
  }
  // bind current logical block to new physical block
  sm_media_bind_log2phy() ; 
  
  // set the data status (0x00=> data bad, 0xff=>no errors or 1-bit error corrected
  XBYTE[0x3664]=x_sm_redt_data[k_ix_redt_data_status]=data_status;

  trace1(0, sm, 0, "copy:  page data status:%02x", data_status);

  // reverse data flow direction
  _mcu_register_clr_bits( x_ep2_ctl, kbm_ep2_ctl_dir) ;

  x_smc_stat = kbm_smc_stat_rdy ;
  _sm_set_wr_cmd(k_sm_write_data);
  _media_set_write_addr() ; 
  sm_mode_ctl |= kbm_sm_mode_ecc_blk_xfer_en;
  _sm_hw_ecc_wr_start() ;
  trace0(0, sm, 0, "ecc_en on") ;
  
  // set fmc ctl reg - 1 sector
  _mcu_register_wr(x_fmc_cnt3, 0x00) ;
  _mcu_register_wr(x_fmc_cnt2, 0x00) ;
  _mcu_register_wr(x_fmc_cnt1, 0x02) ;
  _mcu_register_wr(x_fmc_cnt0, 0x00) ;
  
  // enable blk xfer
  _mcu_register_wr(x_fmc_ctl, (kbm_fmc_ctl_512_byte_pkt|kbm_fmc_ctl_blk_xfer_en)) ;

  // point the rd toggle & count to buffer a (rd toggles point the dest (SIE or DBUF) where to read)
  _mcu_register_wr( x_ramrdbc_a1, 0x02) ;
  _mcu_register_wr( x_ramrdbc_a2, 0x00) ;
  

  // aim fmc at buffer a
  // _mcu_register_set_bits( x_ep2_ctl, kbm_ep2_ctl_rdtog_valid) ;
  _mcu_register_wr(x_ep2_ctl, kbm_ep2_ctl_rdtog_valid |(_mcu_register_rd(x_ep2_ctl) & ~kbm_ep2_ctl_ramrd_tog));

  // bad bad bad form.... do a while loop
  while(_mcu_register_rd( x_fmc_ctl)&kbm_fmc_ctl_blk_xfer_en)
  {
    if(thread_got_sync(kbm_sync_timer) )
    {
      trace0(0, sm_media, 0, "timeout trying to write sector.  aborting") ;
      return k_media_copy_error_dst ;
    }
  }
  
  _sm_hw_ecc_wr_stop() ;
  sm_mode_ctl &= ~kbm_sm_mode_ecc_blk_xfer_en;
  trace0(0, sm, 0, "ecc_en off") ;
  
  // send the write command to program the data to the card
  trace0(0, sm, 0, "cmd:  write") ;
  _sm_set_wr_cmd(k_sm_write);

  if (k_success != sm_wait_rdy_with_timeout(k_sm_busy_programming_timeout))
  {
    nand_cmd_reset_device();
    trace0(0, sm, 0, "error writing sector for copy") ;
    return k_media_copy_error_dst ;
  }
  
  if (k_success != nand_cmd_check_status())
  {
    trace0(0, sm, 0, "sm_write_end_split - write fault") ;
    return k_media_copy_error_dst ;
  }
  
  _sm_hw_set_wr_standby();
  _sm_hw_set_rd_standby();

  return result; 
}


//------------------------------------------------------------------------------
//+-----------------------------------------------------------------------------
// Name:
//   sm_media_phy2log()
//
// Declaration:
//   t_result sm_get_lba(void) reentrant
//
// Purpose:
//   TBD
//
// Arguments:
//   TBD
//
// Return:
//   TBD
//
// Notes:
//   TBD
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
t_result  sm_media_phy2log(void) reentrant
{
  uint16 addr1;
  uint16 addr2;

  trace0(0, sm_media, 0, "sm_media_phy2log()") ;

  addr1=_uint16( x_sm_redt_data[k_ix_redt_lba1_hi],x_sm_redt_data[k_ix_redt_lba1_lo]) ;
  addr2=_uint16( x_sm_redt_data[k_ix_redt_lba2_hi],x_sm_redt_data[k_ix_redt_lba2_lo]) ;


  if (addr1==addr2)
  {
    // addresses are equal
    if ((addr1 &0xF000)==0x1000)
    {
      g_addr_log_blk=(addr1 &0x0FFF)/2;
      trace2(0, sm_media, 0, "RD_PHY:%d => log_blk:%d", g_addr_rd_phy_blk, g_addr_log_blk) ;
      return k_success;
    }
  }

  if (bit_count16(addr1^addr2)!=0x01)
  {
    // more than 1 bit error
    trace2(0, sm_media, 0, "inconsistant log_blk binding:  addr1:%04x addr2:%04x", addr1, addr2) ;
    return k_error ;
  }

  // only 1 bit error
  if ((addr1 &0xF000)==0x1000)
  {
    if (0 == (bit_count16(addr1) &0x01))
    {
      g_addr_log_blk=(addr1 &0x0FFF)/2;
      trace2(0, sm_media, 0, "RD_PHY:%d => log_blk:%d", g_addr_rd_phy_blk, g_addr_log_blk) ;
      return k_success;
    }
  }
  if ((addr2 &0xF000)==0x1000)
  {
    if (0 == (bit_count16(addr2) &0x01))
    {
      g_addr_log_blk=(addr2 &0x0FFF)/2;
      trace2(0, sm_media, 0, "phyblock:%d => log_blk:%d", g_addr_rd_phy_blk, g_addr_log_blk) ;
      return k_success;
    }
  }
  trace2(0, sm_media, 0, "inconsistant log_blk binding:  addr1:%04x addr2:%04x", addr1, addr2) ;
  return k_error ;
}

//+-----------------------------------------------------------------------------
// Name:
//   sm_media_bind_log2phy()
//
// Declaration:
//   t_result  sm_media_bind_log2phy(void) reentrant
//
// Purpose:
//   TBD
//
// Arguments:
//   TBD
//
// Return:
//   TBD
//
// Notes:
//   TBD
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
t_result  sm_media_bind_log2phy(void) reentrant
{
  uint16  addr;
  trace1(0, sm_media, 0, "+sm_media_bind_log2phy(log_blk:%d)", g_addr_log_blk) ;
  x_sm_redt_data[k_ix_redt_block_status]=0xFF;
  x_sm_redt_data[k_ix_redt_data_status] =0xFF;
  addr=g_addr_log_blk*2+0x1000;
  if ((bit_count16(addr)%2)) addr++;
  x_sm_redt_data[k_ix_redt_lba1_hi]=x_sm_redt_data[k_ix_redt_lba2_hi]= _h(addr) ;
  x_sm_redt_data[k_ix_redt_lba1_lo]=x_sm_redt_data[k_ix_redt_lba2_lo]= _l(addr) ;

  // bind the smc buffer too... just to keep 'em all the same
  sm_synch_hw_buff_to_redt_buf() ;

  // note.. this binding is not set until the data is written!  it's only in the
  // redundant (extra) data section
  return k_success ;
}

//+-----------------------------------------------------------------------------
// Name:
//   sm_map_set_phyblock_failed()
//
// Declaration:
//   t_result sm_map_set_phyblock_failed(void) reentrant
//
// Purpose:
//
// Arguments:
//
// Return:
//
// Notes:
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
t_result sm_media_set_phyblock_failed(void) reentrant
{
  uint8 page;
  uint8 i ;

  page=g_addr_page ;
  trace0(0, sm_media, 0, "sm_media_set_phyblock_failed()...") ;

  // mark the block bad in the x_sm_redt_data data buffer
  for (i=0; i<k_sm_redt_buffer_sz; i++)
    x_sm_redt_data[i]=(uint8)((i==k_ix_redt_block_status)?0xF0:0xFF);
  // write the x_sm_redt_data data buffer to all sectors in the block
  for (g_addr_page=0; 
       g_addr_page<_media_data(pages_per_block) ; 
       g_addr_page++)
  {
    sm_media_write_extra_data();
  }
  g_addr_page=page;
  trace2(0, sm_media, 0, "phy block %d:%d marked bad", g_addr_zone, g_addr_wr_phy_blk);
  return k_success ;
}

//+-----------------------------------------------------------------------------
// Name:
//   sm_media_is_phyblock_ok()
//
// Declaration:
//   t_bool sm_media_is_phyblock_ok(void) reentrant
//
// Purpose:
//   TBD
//
// Arguments:
//   TBD
//
// Return:
//   TBD
//
// Notes:
//   TBD
//
// Since:
//   TBD
//------------------------------------------------------------------------------
t_result  sm_media_is_phyblock_ok(void) reentrant
{
  uint8 blk_status = x_sm_redt_data[k_ix_redt_block_status] ;

  trace0(0, sm_media, 0, "sm_media_is_phyblock_ok()") ;

  if (blk_status==0xFF)
  {
    trace0(0, sm_media, 0, "sm_media_is_phyblock_ok() - Y") ;
    return k_true ;
  }
  // sm_dbg_dump_redt_data();
  if (blk_status==0x00)
  {
    trace1(0, sm_media, 0, "sm_media_is_phyblock_ok() - N.  block status: %02x.  block marked 'bad'", blk_status) ;
    return k_false ;
  }

  if (bit_count8(blk_status)<7)
  {
    trace1(0, sm_media, 0, "sm_media_is_phyblock_ok() - N.  block status: %02x.  too many errors.  bit_count8(blk) < 7)  could try to reclaim?", blk_status) ;
    return k_false ;
  }

  // if the status was not 0xff, but has a bit count of 7, then there is a
  // 1-bit error, off from being 0xff, therefor it's considered to be "good"
  trace1(0, sm_media, 0, "sm_media_is_phyblock_ok() - Y.  block status: %02x, bit count of 7", blk_status) ;
  return k_true ;
}

//+-----------------------------------------------------------------------------
// Name:
//   sm_media_is_phyblock_blank()
//
// Declaration:
//   t_bool sm_is_data_blank(void) reentrant
//
// Purpose:
//   TBD
//
// Arguments:
//   TBD
//
// Return:
//   TBD
//
// Notes:
//   TBD
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
t_result sm_media_is_phyblock_blank (void) reentrant
{
  uint8 i;

  for (i=0; i<k_sm_redt_buffer_sz; i++)
    if (x_sm_redt_data[i]!=0xFF)
    {
      trace0(0, sm, 0, "sm_media_is_phyblock_blank(): N") ;
      return k_false ;
    }
    
  trace0(0, sm, 0, "sm_media_is_phyblock_blank(): Y") ;
  return k_true ;

  
}


//+-----------------------------------------------------------------------------
// Name:
//   sm_media_seek_cis()
//
// Declaration:
// t_result sm_media_seek_cis(void) reentrant
//
// Purpose:
//  TBD
//
// Arguments:
//  TBD
//
// Return:
//  TBD
//
// Notes:
//  TBD
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------

t_result sm_media_seek_cis(void) reentrant
{
  g_addr_zone=0;
  g_addr_page=0;

  trace0(0, sm_media, 0, "sm_media_seek_cis()") ;
  for ( g_addr_rd_phy_blk=0;
        g_addr_rd_phy_blk<(_media_data(physical_blocks_per_zone)-_media_data(logical_blocks_per_zone)-1);
        g_addr_rd_phy_blk++)
  {
    if (k_success != sm_media_read_extra_data())
    {
      trace0(0, sm_media, 0, "error - could not read extra data") ;
      sm_soft_reset();
      return( k_error);
    }
    if (sm_media_is_phyblock_ok())
      break;
  }

  if (g_addr_rd_phy_blk==(_media_data(physical_blocks_per_zone)-_media_data(logical_blocks_per_zone)-1))
  {
    trace0(0, sm_media, 0, "error - valid cis block not found.") ;
    sm_soft_reset();
    return k_error ;
  }

  while (g_addr_page<k_sm_max_cis_sect)
  {
    if (g_addr_page)
    {
      if (k_success != sm_media_read_extra_data())
      {
        trace0(0, sm_media, 0, "error - could not read extra data (2)") ;
        sm_soft_reset();
        return k_error ;
      }
    }

    if (sm_redt_is_data_valid())
    {
      // redundant data reports data is good.
      _media_data(sector_buffer) = g_sector_buffer ;
      if ( k_success != sm_media_read_sector())
      {
        trace1(0, sm_media, 0, "page %d read failure.  cis not found.", g_addr_page) ;
        sm_soft_reset();
        return k_error ;
      }

      if ( k_success != sm_media_validate_sector(g_sector_buffer) )
      {
        trace1(0, sm_media, 0, "page %d data invalid", g_addr_page) ;
        sm_soft_reset();
        return k_error ;
      }

      if ( k_success != sm_validate_cis(g_sector_buffer))
      {

⌨️ 快捷键说明

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