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

📄 sm.c

📁 <B>SMSC USB2.0 Flash硬盘驱动源码</B>
💻 C
📖 第 1 页 / 共 5 页
字号:
  _media_data(assign_zone)=0;
  g_addr_zone=0;

  if ( k_success != map_build_sector_map())
    return (k_error );

  // sm_dump_log_blk(0) ;

  trace0(0, sm, 0, "media identified") ;

  //  hmmmm... this may be redundant... done in identify-media...
  _lun_data(media) &= ~kbm_lun_media_unknown ;
  return (k_success);
}

//+-----------------------------------------------------------------------------
// Name:
//   dfa_sm_read
//
// Declaration:
//   void dfa_sm_read(void) reentrant
//
// Purpose:
//   Read data from sm media
//
// Arguments:
//   None.
//   Uses _lun_data and g_bot_cbw to get its parameters.
//
// Return:
//   No return value.
//   However, on exit the DFA's argument pointer is written with a t_csw_status indicating:
//     k_command_passed - command completed.
//     k_command_failed - an error occurred.
//
// Notes:
//   This is the start STATE of the dfa_ata_read DFA.
//   It overrides dfa_lun_read.
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
t_result sm_read_begin_xfer() reentrant
{
  trace4(0, sm, 10, "sm_read_begin_xfer() - start:0x%04X%04X count:0x%04X%04X" , _hw(_fmc_get_start_lb_32()), _lw(_fmc_get_start_lb_32()), _hw(_fmc_get_lb_count_32()), _lw(_fmc_get_lb_count_32()));
  _lun_data(sensep) = &sense_read_error;

  if (k_success != map_lba2addr_rd( _fmc_get_start_lb_32() ) )
  {
    _lun_data(sensep)=&sense_illegal_address ;
    trace0(0, sm, 0, "error in lba2addr") ;
    return (k_error );
  }

  if (!g_addr_page)
  {
    _lun_data(max_lb_per_split) = _min( _media_data(pages_per_block), _fmc_get_lb_count_32());
    trace5(0, sm, 10, "-----read begin xfer - zone:%02d phy:0x%04X log:0x%04X page:%02d count:%02d - first in block", g_addr_zone, g_addr_rd_phy_blk, g_addr_log_blk, g_addr_page, _lun_data(max_lb_per_split) );
  }
  else
  {
    _lun_data(max_lb_per_split) = _min( _media_data(pages_per_block) - g_addr_page, _fmc_get_lb_count_32());
    trace5(0, sm, 10, "-----read begin xfer - zone:%02d phy:0x%04X log:0x%04X page:%02d count:%02d", g_addr_zone, g_addr_rd_phy_blk, g_addr_log_blk, g_addr_page, _lun_data(max_lb_per_split));
  }
  _lun_data(max_lb_per_burst) = _lun_data(max_lb_per_split) ;
  return (k_success );
}


//+-----------------------------------------------------------------------------
// Name:
//   sm_read_end_xfer
//
// Declaration:
//   t_result sm_read_end_xfer(void);
//
// Purpose:
//   Issue the read command to the smart media device.
//
// Arguments:
//   None.
//
// Return:
//   A t_result indicating:
//     k_success - command completed.
//
// Notes:
//   This is a FUNCTION, not a DFA.
//   Do not yeild, or run a DFA, from within this callback.
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
t_result sm_read_end_xfer(void) reentrant
{
  trace0(0, sm, 1, "sm_read_end_xfer()") ;

  _sm_hw_set_rd_standby() ;

  if (k_success != _fmc_get_result())
    return (k_error);
  _lun_data(sensep) = &sense_none;
  return (k_success );
}



//+-----------------------------------------------------------------------------
// Name:
//   sm_read_begin_next_split
//
// Declaration:
//   t_result sm_read_begin_next_split(void);
//
// Purpose:
//   Issue the read command to subsequent splits after the first.
//
// Arguments:
//   None.
//
// Return:
//   A t_result indicating:
//     k_success - command completed.
//
// Notes:
//   This is a FUNCTION, not a DFA.
//   Do not yeild, or run a DFA, from within this callback.
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
t_result sm_read_begin_split(void) reentrant
{
  trace0(0, sm, 1, "sm_read_begin_split()") ;

  if (k_success != map_lba2addr_rd( _fmc_get_start_lb_32() ) )
  {
    _lun_data(sensep)=&sense_illegal_address ;
    return (k_error );
  }

  if (map_log_blk_has_bad_data())
  {
    if (sm_check_data_status(g_addr_page, (uint8) _fmc_get_lb_count_32()))
    {
      trace0(0, sm, 0, "read error detected in lba range") ;
      nand_cmd_reset_device();
      return (k_error);
    }
    nand_cmd_reset_device();
    trace0(0, sm, 0, "read in log blk that has bad data is OK");
  }
  trace4(0, sm, 0, "beginning split - zone:%d phy:%d log:%d page:%d", g_addr_zone, g_addr_rd_phy_blk, g_addr_log_blk, g_addr_page) ;

  // convert virtual zone/block/sector into page/offset address
  nand_rd_va2pa() ;
  _sm_rd_cmd_begin(k_sm_read) ;
  _media_set_read_addr() ;
  if (k_success != sm_wait_rdy_with_timeout(k_sm_busy_read_timeout))
  {
    trace0(0, sm, 0, "ssfdc_readsect timeout on busy") ;
    nand_cmd_reset_device();
    return (k_error );
  }

  // must set these after the wait rdy otherwise, the rdy low->high will force the fmc-high and mask the interrupt
  // clear ecc bits
  _mcu_register_wr(x_smc_stat, (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));
  // unmask the ecc err bits
  _mcu_register_clr_bits(x_smc_stat_msk, (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));
  // mask in fmc irqs
  _mcu_register_clr_bits(x_imr0, kbm_isr0_fmc_irq);
  // enable blk_xfer_ecc
  _mcu_register_set_bits(sm_mode_ctl, kbm_sm_mode_ecc_blk_xfer_en) ;
  trace0(0, sm, 0, "ecc on") ;

  // enable ecc error detection
#if 0
  
/*
  mcu_begin_critical_section();
  trace1(0, sm, 0, "    smc_stat: %02x", x_smc_stat) ;
  trace1(0, sm, 0, "smc_stat_msk: %02x", x_smc_stat_msk) ;
  trace1(0, sm, 0, " sm_mode_ctl: %02x", sm_mode_ctl) ;
  trace1(0, sm, 0, "        isr0: %02x", x_isr0);
  trace1(0, sm, 0, "        imr0: %02x", x_imr0);
  mcu_end_critical_section();
*/
#endif
  return (k_success);
}

//+-----------------------------------------------------------------------------
// Name:
//   sm_read_end_split
//
// Declaration:
//   t_result sm_read_end_split(void);
//
// Purpose:
//   nothing to do at the beginning of a split
//
// Arguments:
//   None.
//
// Return:
//   A t_result indicating:
//     k_success - command completed.
//
// Notes:
//   This is a FUNCTION, not a DFA.
//   Do not yeild, or run a DFA, from within this callback.
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
t_result sm_read_end_first_split(void) reentrant
{
  trace0(0, sm, 0, "sm_read_end_first_split()") ;

  // go into overdrive
  trace2(0, sm, 0, "adjusting split/burst size.  before: max_lb_per_split:%d  max_lb_per_burst: %d", _lun_data(max_lb_per_split), _lun_data(max_lb_per_burst)) ;

  _lun_data(max_lb_per_split) = _min(_media_data(pages_per_block), g_n_lb_this_xfer.u32);
  _lun_data(max_lb_per_burst) = _lun_data(max_lb_per_split) ;

  trace2(0, sm, 0, "adjusting split/burst size.  after:  max_lb_per_split:%d  max_lb_per_burst: %d", _lun_data(max_lb_per_split), _lun_data(max_lb_per_burst)) ;

  // no need to callback here any more
  _fmc_set_callback(sm_read_begin_xfer, sm_read_end_xfer,
                    sm_read_begin_split, sm_read_end_split,
                    fmc_dflt_callback, fmc_dflt_callback, sm_read_end_burst);
  return (sm_read_end_split() );
}


//+-----------------------------------------------------------------------------
// Name:
//   sm_read_end_split
//
// Declaration:
//   t_result sm_read_end_split(void);
//
// Purpose:
//   nothing to do at the beginning of a split
//
// Arguments:
//   None.
//
// Return:
//   A t_result indicating:
//     k_success - command completed.
//
// Notes:
//   This is a FUNCTION, not a DFA.
//   Do not yeild, or run a DFA, from within this callback.
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
t_result sm_read_end_split(void) reentrant
{
  trace0(0, sm, 0, "sm_read_end_split()") ;
//  sm_mode_ctl &= ~kbm_sm_mode_ecc_blk_xfer_en;
//  TRACE0(247, sm, 0, "ecc_blk_xfer_en off") ;
  _sm_hw_set_rd_standby() ;
  return (k_success );
}

//+-----------------------------------------------------------------------------
// Name:
//   sm_correct_sram_bit
//
// Declaration:
//   t_result sm_correct_sram_bit(void);
//
// Purpose:
//   TBD
//
// Arguments:
//   None.
//
// Return:
//   A t_result indicating:
//     k_success - command completed.
//
// Notes:
//   This is a FUNCTION, not a DFA.
//   Do not yeild, or run a DFA, from within this callback.
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
void sm_correct_sram_bit(uint8 buffer, uint16 offset, uint8 ix_bit) reentrant
{
  t_uw16 addr ;
  uint8  err_byte;

  trace3(0, sm, 0, "sm_correct_sram_bit():  buffer:%c, offset.bit:%d.%d", ((buffer==4)?'a':'b'), offset, ix_bit) ;

  addr.u8.hi = k_pkt_addrhi[buffer] ;
  addr.u8.lo = k_pkt_addrlo[buffer] ;
  addr.u16 += offset ;

  trace1(0, sm, 0, "sram byte addr: %04x", addr.u16) ;
  _mcu_register_wr(x_sram_addr_lo, addr.u8.lo);
  _mcu_register_wr(x_sram_addr_hi, addr.u8.hi);
  _hdw_clk_domain_bug_workaround();
  err_byte = _mcu_register_rd(x_sram_data) ;
  err_byte ^= (1 << ix_bit) ;
  _mcu_register_wr(x_sram_addr_lo, addr.u8.lo);
  _mcu_register_wr(x_sram_addr_hi, addr.u8.hi);
  _hdw_clk_domain_bug_workaround();
  _mcu_register_wr(x_sram_data, err_byte) ;
}


//+-----------------------------------------------------------------------------
// Name:
//   sm_read_end_burst
//
// Declaration:
//   t_result sm_read_end_burst(void);
//
// Purpose:
//   TBD
//
// Arguments:
//   None.
//
// Return:
//   A t_result indicating:
//     k_success - command completed.
//
// Notes:
//   This is a FUNCTION, not a DFA.
//   Do not yeild, or run a DFA, from within this callback.
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
t_result sm_read_end_burst(void) reentrant
{
  t_result result ;
  uint8    buffer ;
  uint8    err_byte;
//  uint8    isr ;

  trace0(0, sm, 0, "sm_read_end_burst()") ;

  result = k_success ;
  buffer = 0 ;

  // check blk_err bit to see if there was a correctable error.
  err_byte = _mcu_register_rd(x_smc_stat) ;
  trace1(0, sm, 0, "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))
  {
    trace0(0, sm, 0, "smc_stat_ecc_err_d_a/b -> uncorrectable ecc error (2+bits)") ;
//    sm_media_set_phyblock_failed();//DDD
    nand_cmd_reset_device();
    return (k_error );
  }
  if (err_byte& (kbm_smc_stat_ecc_err_c_a|kbm_smc_stat_ecc_err_c_b))
  {
    trace0(0, sm, 0, "single-bit ecc error detected!") ;

    if (!sie_is_high_speed())
    {
      trace0(0, sm, 0, "cannot correct single-bit errors at full speed.  reporting read error");
      nand_cmd_reset_device();
      return (k_error);
    }

    // this needs to be checked before turning auto-xfer off as per e-mail from Ben
    buffer = (_mcu_register_rd(x_ep2_ctl)&kbm_ep2_ctl_ramwr_tog)?5:4;
    trace1(0, sm, 0, "ramwr_toggle reports error in buffer %c", (buffer==4?'a':'b')) ;

    // stop xfer and correct the error
    _mcu_register_clr_bits(x_fmc_ctl, (kbm_fmc_ctl_auto_trans|kbm_fmc_ctl_auto_tog));
    trace0(0, sm, 0, "auto transfer OFF") ;

    if (x_smc_stat&kbm_smc_stat_ecc_err_c_a)
    {
      trace2(0, sm, 0, "blk xfer interrupted -> correctable 1-bit error addr:%d.%d", ecc_a_add_h, (ecc_a_add_l&0x07)) ;
      sm_correct_sram_bit(buffer, ecc_a_add_h, (ecc_a_add_l&0x07));
      _mcu_register_wr(x_smc_stat,kbm_smc_stat_ecc_err_c_a);
    }
    if (x_smc_stat&kbm_smc_stat_ecc_err_c_b)
    {
      trace2(0, sm, 0, "blk xfer interrupted -> correctable 1-bit error addr:%d.%d", (((uint16)ecc_b_add_h)+0x100), (ecc_b_add_l&0x07)) ;
      sm_correct_sram_bit(buffer, (ecc_b_add_h+0x100), (ecc_b_add_l&0x07)) ;
      _mcu_register_wr(x_smc_stat,kbm_smc_stat_ecc_err_c_b);
    }
    // toggle the buffer to be tx'd
    if (buffer == 4)
    {
      _mcu_register_wr(x_ramrdbc_a1, 0x02) ;
      _mcu_register_wr(x_ramrdbc_a2, 0x00) ;
      _mcu_register_wr(x_ep2_ctl, kbm_ep2_ctl_rdtog_valid |(_mcu_register_rd(x_ep2_ctl) & ~kbm_ep2_ctl_ramrd_tog));
      _hdw_clk_domain_bug_workaround();
      while ( !(x_isr0&kbm_isr0_ramrd_a))
      {

⌨️ 快捷键说明

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