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

📄 nand.c

📁 <B>SMSC USB2.0 Flash硬盘驱动源码</B>
💻 C
📖 第 1 页 / 共 5 页
字号:
//
// 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
//------------------------------------------------------------------------------
void nand_dfa_read(void) reentrant
{
  TRACE0(396, nand, 0, "nand_dfa_read()");
  _fmc_set_options(0);
  _fmc_set_timeout(10000);
  if ( g_ix_media_nand == k_ix_media_nand_int)
  {
    _fmc_set_callback(nand_read_begin_xfer, sm_read_end_xfer,
                      nand_read_begin_split, nand_read_end_first_split,
                      fmc_dflt_callback, fmc_dflt_callback, nand_int_read_end_burst);
  }
  else
  {
    _fmc_set_callback(nand_read_begin_xfer, sm_read_end_xfer,
                      nand_read_begin_split, nand_read_end_first_split,
                      fmc_dflt_callback, fmc_dflt_callback, sm_read_end_burst);
  }
#ifdef k_enable_write_caching
  // flush write cache
  if (_media_data(options)&kbm_media_data_opt_write_cache)
    map_write_cache_flush_all() ;
#endif

  dfa_lun_read();
}

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------


//+-----------------------------------------------------------------------------
// Name:
//   nand_write_begin_first_split
//
// Declaration:
//   t_result nand_write_begin_first_split(void);
//
// Purpose:
//   Issue the write 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 nand_write_begin_first_split() reentrant
{
  TRACE0(397, nand, 1, "nand_write_begin_first_split()");
  // compute phy addresses in case this is the first sector
  if (k_ix_media_nand_int != g_active_media)
    nand_select_card() ;
  nand_wr_va2pa() ;
  nand_rd_va2pa() ;

  if (k_ix_media_nand==g_active_media)
  {
    g_fmc_begin_split_callback = (t_fmc_callback) sm_write_begin_split;
    _sm_rd_cmd_begin(k_sm_reset_chip); 
    sm_wait_rdy_with_timeout(k_sm_busy_reset_timeout);
  }
  else if (k_ix_media_nand_int == g_active_media)
  {

    g_fmc_begin_split_callback = (t_fmc_callback) nand_int_write_begin_quick_split;
    nand_int_select_chip(_media_data(segments_per_page)-1);
    _sm_rd_cmd_begin(k_sm_reset_chip);
    sm_wait_rdy_with_timeout(k_sm_busy_reset_timeout);
    return(nand_int_write_begin_quick_split());
    trace2(0, nand_int, 0, "beginning split at page:%d segment:%d", g_addr_page, g_addr_segment) ;
  }
  else
  {
    g_fmc_begin_split_callback = (t_fmc_callback) n2k_write_begin_split;

    trace2(0, n2k, 0, "beginning split at page:%d segment:%d", g_addr_page, g_addr_segment) ;
    // check to see if we are starting in middle of a page
    if (g_addr_segment)
    {
      // pre-read the old page into chip cache
      n2k_page_read_for_copy() ;
      // write the full destination address
      nand_cmd_page_write_cache_data() ;
      n2k_page_set_wr_offset( _n2k_data_offset( g_addr_segment ) ) ;
    }

    return(k_success);
  }
  return(k_success);
}


//+-----------------------------------------------------------------------------
// Name:
//   n2k_write_begin_xfer
//
// Declaration:
//   void n2k_write_begin_xfer(void) reentrant
//
// Purpose:
//
// Arguments:
//
// Return:
//
// Notes:
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
t_result n2k_write_begin_xfer() reentrant
{
  t_result result ;
  uint16   max_split_size ;

  trace4(0, sm, 10, "n2k_write_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_write_error;

  // get virtual addr
  map_lba2addr_rd(_fmc_get_start_lb_32()) ;

  // enable the correct card
  nand_select_card() ;

  // copy head
  result = map_write_begin( _fmc_get_start_lb_32() ) ;

  // make sure we're in the right mode - fixes a bug where
  // the first burst of the first split of the xfer begins
  // on a zone that needed to be paged in...
  sm_set_write_mode_page_data();

  // precompute max split size
  max_split_size = (_media_data(pages_per_block)-g_addr_page)*_media_data(segments_per_page)-g_addr_segment ;

  if (!g_addr_page)
  {
    _lun_data(max_lb_per_split) = _min( max_split_size, _fmc_get_lb_count_32());
    trace5(0, n2k, 10, "-----write begin xfer - zone:%d phy:%d log:%d page:%d count:%d - first in block", g_addr_zone, g_addr_wr_phy_blk, g_addr_log_blk, g_addr_page, _lun_data(max_lb_per_split) );
  }
  else
  {
    _lun_data(max_lb_per_split) = _min( max_split_size, _fmc_get_lb_count_32());
    trace5(0, n2k, 10, "-----write begin xfer - zone:%d phy:%d log:%d page:%d count:%d", g_addr_zone, g_addr_wr_phy_blk, g_addr_log_blk, g_addr_page, _lun_data(max_lb_per_split));
  }

  // burst size needs to be 1, because the sm controller can't
  // handle more than 512 bytes out at a time.
  _lun_data(max_lb_per_burst) = 1;
  return(result );
}


//+-----------------------------------------------------------------------------
// Name:
//   n2k_write_begin_split
//
// Declaration:
//   t_result n2k_write_begin_split(void);
//
// Purpose:
//   Issue the write 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 n2k_write_begin_split() reentrant
{
  uint8 zone_before ;
  trace0(0, n2k, 1, "sm_write_begin_split()");
  trace1(0, n2k, 0, "g_addr_rd_phy_blk: %d", g_addr_rd_phy_blk) ;

  zone_before = g_addr_zone ;

  // if a new physical block, tell the mapper to go git us one.
  if (k_success != map_lba2addr_rd(_fmc_get_start_lb_32()))
    return(k_error);

  if (g_addr_zone != zone_before)
  {
    // we've crossed a boundry on a split, do a reset
    trace0(0, n2k, 0, "zone-change detected.") ;
    nand_select_card() ;
    sm_set_write_mode_page_data() ;
  }

  if (!g_addr_page)
  {
    if (k_success != map_alloc_wr_blk())
      return(k_error);
  }

  // convert virtual address zone/block/sector into page/offsets
  nand_rd_va2pa() ;
  nand_wr_va2pa() ;


  trace0(0, sm, 0, "ready to begin writing sectors") ;
  return(k_success);
}

//+-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
t_result n2k_write_end_split(void) reentrant
{
  trace0(0, n2k, 0, "n2k_write_end_split()") ;

  trace2(0, n2k, 0, "split ended on to page %d segment %d", g_addr_page, g_addr_segment) ;
  if ( g_addr_segment )
  {
    trace0(0, n2k, 0, "last split.  need to flush current page cache") ;
    if ( k_success != nand_cmd_page_program() )
    {
      trace0(0, n2k, 0, "nand_cmd_cache_program failed") ;
      return(k_error );
    }
    g_addr_page++;
    g_addr_segment=0;
    nand_incr_addr() ;
  }
  return(sm_write_end_split() );
}

//+-----------------------------------------------------------------------------
// Name:
//   sm_write_begin_burst
//
// Declaration:
//   t_result sm_write_begin_burst(void);
//
// Purpose:
//   Issue the write 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 n2k_write_begin_burst() reentrant
{
  trace5(0, n2k, 0, "n2k_write_begin_burst() - zone:%d log:%d-phy:%d page:%d seg:%d", g_addr_zone, g_addr_log_blk, g_addr_wr_phy_blk, g_addr_page, g_addr_segment) ;
  trace1(0, n2k, 0, "                        - n_lbs_this_xfer:%d", g_n_lb_this_xfer.u32) ;
  // check to see if we are starting in middle of a page
  if (!g_addr_segment)
  {
    // pre-read the old page into chip cache
    n2k_page_read_for_copy() ;
    // write data into the on-chip cache, starting at the beginning of the page
    nand_cmd_page_write_cache_data() ;
  }

  _mcu_register_set_bits(sm_mode_ctl,kbm_sm_mode_ecc_blk_xfer_en) ;
  _sm_hw_ecc_wr_start() ;
  trace0(0, n2k, 0, "bursting") ;
  return(k_success);
}


//+-----------------------------------------------------------------------------
// Name:
//   sm_write_end_burst
//
// Declaration:
//   t_result sm_write_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 n2k_write_end_burst(void) reentrant
{

  trace0(0, sm, 0, "n2k_write_end_burst()") ;
  _sm_hw_ecc_wr_stop() ;
  sm_mode_ctl &= ~kbm_sm_mode_ecc_blk_xfer_en;
  trace0(0, sm, 0, "ecc_en off") ;

  g_addr_segment++ ;

  if ( g_addr_segment==_media_data(segments_per_page) )
  {
    trace0(0, n2k, 0, "last burst in the page.  program the page cache") ;
    if ( k_success != nand_cmd_page_program() )
    {
      trace0(0, sm, 0, "nand_cmd_cache_program failed") ;
      return(k_error );
    }
    g_addr_page++;
    g_addr_segment=0;
    nand_incr_addr() ;
  }
  return(k_success );
}

//+-----------------------------------------------------------------------------
// Name:
//   dfa_sm_write
//
// Declaration:
//   void dfa_sm_write(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_write DFA.
//   It overrides dfa_lun_write.
//

⌨️ 快捷键说明

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