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

📄 ms_media.c

📁 <B>SMSC USB2.0 Flash硬盘驱动源码</B>
💻 C
📖 第 1 页 / 共 2 页
字号:
/*============================================================================
  ____________________________________________________________________________
                                ______________________________________________
   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.
  ____________________________________________________________________________
  ____________________________________________________________________________
  media.c - common media sector-mapping, sector copying code, used as a base
            class for sm_media & ms_media specific classes
  ____________________________________________________________________________
  comments tbd
  ____________________________________________________________________________
  Revision History
  Date      Who  Comment
  ________  ___  _____________________________________________________________
  03/01/02  cds  initial version
  03/13/02  tbh  started filling in the stubs
  04/01/02  tbh  ms_media_erase_block protects boot blocks now
  04/02/02  tbh  added ms_media_copy_sector
  04/19/02  tbh  added ms_media_resolve_conflict
  06/03/02  cds  implemented ms_media_copy_sector
  08/06/02  tbh  modified ms_media_copy_sector to use single-page copy commands
                 to work around the SanDisk 64MB issue with cards whose date
                 codes are < J (they assert breq after block-end on writes) [br308]
  08/13/02  tbh  additional comments, minor tweaks to ms_media_copy_sector()
  08/28/02  tbh  changed interpretation of uncorrectable error bits from
                 "all relevant bits set -> uncorrectable error" to
                 "any relevant bit set -> uncorrectable error" to resolve the
                 data corruption issue on sony cards (sorry, no bug reporter number
                 was entered yet)
  09/04/02  cds  address name & usage change-over
                  g_addr_sector => g_addr_page,
                  g_addr_page   => g_addr_segment,
                  _media_data(sectors_per_block)  => _media_data(pages_per_block)
                  _media_data(cis_phy_block)      => _media_data(boot_block)
                  _media_data(cis_sector)         => _media_data(boot_sector)
                  (new item)                      => _media_data(segments_per_page)
  11/01/02  tbh  ms_media_is_phyblock_ok() now references the bad block table
                 from the boot sector of the ms card.
                 do not erase any blocks in ms_media_erase_block() if write protected.
                 added ms_media_is_phyblock_wp(), but didn't use it.  instead
                 ms_media_erase_block performs the test (for the information block).
  11/03/02  cds  added new function to report boot area blocks as "reserved" so that they
                 can neither be read nor written.  
                 
                                  
============================================================================*/
#define __ms_media_dot_c__
#include "project.h"

// provide vtable definition
code _vtbl_defn(ms_media);

// some shared code between this and ms.c files
extern t_result ms_write_parm_reg(uint8 sys_parm, uint8 cmd_parm) reentrant;
extern t_result ms_set_cmd(uint8 cmd) reentrant;
extern t_result ms_get_int(uint8 ticks) reentrant;
extern t_result ms_read_extra_data_reg(void) reentrant;
extern t_result ms_set_tpc(uint8 tpc, uint8 count) reentrant;
extern t_result ms_wait_fifo_with_timeout(uint8 msk, uint8 val, uint8 ticks) reentrant;
extern t_result ms_write_all_reg(uint8 sys_parm, uint8 cmd_parm) reentrant;

// hacks into ms.c to enable ms_media_copy_sector to access relevant data.
// perhaps would be better to move that function in to ms.c?
extern xdata uint8 _factor;   // interrupt factor from get_int()
extern xdata uint8 _status1;  // hack to get SanDisk64MB working

//------------------------------------------------------------------------------
static xdata t_udw32 _phyblk;

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void set_rd_phyblk()
{
  _phyblk.u32 = g_addr_zone * _media_data(physical_blocks_per_zone) + g_addr_rd_phy_blk;
  g_ms_blk_addr_msb = _phyblk.u8.lh;
  g_ms_blk_addr_mid = _phyblk.u8.hl;
  g_ms_blk_addr_lsb = _phyblk.u8.lo;
  // g_ms_page = g_addr_sector;
  g_ms_page = g_addr_page;
  //TRACE3(286, ms, 0, " addr:0x00%02X%02X%02X", g_ms_blk_addr_msb, g_ms_blk_addr_mid, g_ms_blk_addr_lsb);
  //TRACE1(287, ms, 0, " page:0x%02X", g_ms_page);
}

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void set_wr_phyblk()
{
  _phyblk.u32 = g_addr_zone * _media_data(physical_blocks_per_zone) + g_addr_wr_phy_blk;
  g_ms_blk_addr_msb = _phyblk.u8.lh;
  g_ms_blk_addr_mid = _phyblk.u8.hl;
  g_ms_blk_addr_lsb = _phyblk.u8.lo;
  // g_ms_page = g_addr_sector;
  g_ms_page = g_addr_page;
  //TRACE3(286, ms, 0, " addr:0x00%02X%02X%02X", g_ms_blk_addr_msb, g_ms_blk_addr_mid, g_ms_blk_addr_lsb);
  //TRACE1(287, ms, 0, " page:0x%02X", g_ms_page);
}

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
t_result ms_media_erase_block() reentrant
{
  uint16 old_page;

  trace2(0, ms_media, 110, "ms_media_erase_block() - zone:%d blk:%d", g_addr_zone, g_addr_wr_phy_blk);
  old_page = g_addr_page;
  g_addr_page = 0;
  set_wr_phyblk();
  g_addr_page = old_page;
  // don't erase the boot blocks
  if (_phyblk.u32 <= _media_data(boot_block))
  {
    trace0(0, err, 0, "error: attempt to erase a boot block");
    return k_error;
  }
  if (_lun_data(media) & kbm_lun_media_wrprot)
  {
    trace0(0, err, 0, "error: the disk is write protected");
    return k_media_error_wp;
  }
  if (ms_is_this_blk_the_information_block(g_addr_zone * _media_data(physical_blocks_per_zone) + g_addr_wr_phy_blk))
  {
    trace0(0, err, 0, "error: attempt to erase information block");
    return k_media_error_wp;
  }
  return ms_erase_block();
}

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//t_result ms_media_read_sector() reentrant
//{
//  trace0(0, ms_media, 0, "ms_media_read_sector()");
//  set_rd_phyblk();
//  return ms_pio_read_page(k_max_pnr);
//}

#if 0
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
t_result ms_media_copy_sector() reentrant
{
  trace0(0, ms_media, 0, "ms_media_copy_sector()");
  set_rd_phyblk();
  return ms_copy_page();
}
#else
//+-----------------------------------------------------------------------------
// Name:
//   ms_media_copy_sector()
//
// Declaration:
// t_result ms_media_copy_sector(void);
//
// Purpose:
//   Copy a single 512 byte sector/page from one block to another block.
//   Used during copy-head/copy-tail operations.
//
// Arguments:
//   None.
//
// Return:
//
// Notes:
//   This implements pattern-2 for writes.
//   Could probably be a little faster changing to implement patters-1 for writes,
//   avoiding an extra get_int call.
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
t_result ms_media_copy_sector() reentrant
{

  trace4(0, ms_media, 0, "+ms_media_copy_sector() zone:%d SRC_BLK:%d DEST_BLK:%d page:%d", g_addr_zone, g_addr_rd_phy_blk, g_addr_wr_phy_blk, g_addr_page) ;
  if( (g_addr_wr_phy_blk == k_block_free) )
  {
    trace0(0, ms_media, 0, "  error. invalid wr_phy_block: 0xffff") ;
    return k_media_err_illegal_lba ;
  }
  if( (g_addr_zone==0) && (g_addr_wr_phy_blk<=_media_data(boot_block)))
  {
    trace1(0, ms_media, 0, "  error. wr_phy_block has lower address than cis_phy_block.  Invalid address: 0x%04X", g_addr_wr_phy_blk) ;
    return k_media_err_illegal_lba ;
  }
  // set direction - device->sram
  _mcu_register_set_bits( x_ep2_ctl, kbm_ep2_ctl_dir) ;
  // enable buffer a to receive (wrtog_valid=1, ramwr_tog=0) ;
  _mcu_register_set_bits( x_ep2_ctl, kbm_ep2_ctl_wrtog_valid) ;
  // issue command to read sector at g_addr_rd_phy_blk
  set_rd_phyblk();
  if (k_success != ms_write_parm_reg(0x80, 0x20))
    return k_error;
  if (k_success != ms_set_cmd(k_ms_block_read))
    return k_error;
  // wait for memory stick to be ready
  if (k_success != ms_get_int(10))
    return k_error;
  if (_factor & kbm_ms_reg_int_cmdnk)
  {
    trace0(0, ms, 10, "error: cmdnk");
    return k_error;
  }
  if (!(_factor & kbm_ms_reg_int_ced))
  {
    trace0(0, ms, 10, "error: ced not set");
    return k_error;
  }
  trace0(0, ms, 0, "ced");
  if (!(_factor & kbm_ms_reg_int_breq))
  {
    trace0(0, ms, 0, "error: breq not set");
    return k_error;
  }
  trace0(0, ms, 0, "breq");
  if (_factor & kbm_ms_reg_int_err)
  {
    trace0(0, ms, 0, "error: err");
    if (k_success != ms_read_status())
      return k_error;
//    if (_status1 & (kbm_ms_reg_status1_ucdt |kbm_ms_reg_status1_ucex |kbm_ms_reg_status1_ucfg) ==
//        (kbm_ms_reg_status1_ucdt |kbm_ms_reg_status1_ucex |kbm_ms_reg_status1_ucfg))
    if (_status1 & (kbm_ms_reg_status1_ucdt |kbm_ms_reg_status1_ucex |kbm_ms_reg_status1_ucfg))
    {
      trace0(0, ms, 0, "error: ucdt&ucex&ucfg - uncorrectable flash read error");
      ms_media_set_phyblock_failed();
      return k_error;
    }
  }

  // daken must be set during dma transfers.
  // only wr-page-data and rd-page-data can be issued with daken set.
  _ms_register_set_bits(ms_mode_ctl, kbm_ms_mode_ctl_daken);
  if (k_success != ms_set_tpc(k_ms_tpc_rd_page_data |0x02, 0))
  {
    _ms_register_clr_bits(ms_mode_ctl, kbm_ms_mode_ctl_daken);
    return k_error;
  }
  // $$$ IMPORTANT!  This begin_critical_section() is ended in the 'end_burst' function
  // $$$ to prevent xdata access while blk_xfer bit is enabled
  _mcu_begin_critical_section();
  // 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, use 512 bytes per burst
  _mcu_register_wr(x_fmc_ctl, (kbm_fmc_ctl_512_byte_pkt|kbm_fmc_ctl_blk_xfer_en)) ;
  _mcu_register_wr(x_isr0, kbm_isr0_blk_xfer_complete);
  _mcu_register_clr_bits(x_imr0, kbm_isr0_blk_xfer_complete);
  // $$$$$$ warning!
  // $$ must do a while loop because we cannot yield
  // also, cannot have a timer, because of the memory stick bug... the timer
  // is in XDATA space, and touching it during ms fmdu xfers ist verboten
  while( !(_mcu_register_rd(x_isr0)&kbm_isr0_blk_xfer_complete)) ;
  _mcu_end_critical_section() ;
  if (!_ms_rx_data_fifo_is_empty())
  {
    trace0(0, ms, 10, "alert - entered read_end_burst before rx fifo emptied - wait before stopping dma");
    if (k_success != ms_wait_fifo_with_timeout(ms_fifo_stat_r_buf_e, ms_fifo_stat_r_buf_e, 3))  //rcc test for MS bug tbh!!!
      return k_error;
  }
  // clear daken before issuing command other than wr-page-data and rd-page-data
  _ms_register_clr_bits(ms_mode_ctl, kbm_ms_mode_ctl_daken);
  trace0(0, ms_media, 0, "ms_copy_sector() read complete") ;
  // bind current logical block to new physical block
  ms_media_bind_log2phy() ;
  // reverse data flow direction: sram->device
  _mcu_register_clr_bits( x_ep2_ctl, kbm_ep2_ctl_dir) ;
  // program the card to write 1 sector at g_addr_wr_phy_blk
  set_wr_phyblk();
  //return ms_write_issue_command();
  if (k_success != ms_write_all_reg(0x80, 0x20))
    return k_error;
  if (k_success != ms_set_cmd(k_ms_block_write))
    return k_error;
  if (k_success != ms_get_int(10))
    return k_error;
  if (_factor & kbm_ms_reg_int_cmdnk)
  {
    trace0(0, ms, 10, "error: cmdnk");
    return k_error;
  }
  if (!(_factor & kbm_ms_reg_int_breq))
  {
    trace0(0, ms, 10, "error: breq not set");
    return k_error;
  }
  // daken must be set during dma transfers.
  // only wr-page-data and rd-page-data can be issued with daken set.
  _ms_register_set_bits(ms_mode_ctl, kbm_ms_mode_ctl_daken);
  if (k_success != ms_set_tpc(k_ms_tpc_wr_page_data |0x02, 0))
  {
    _ms_register_clr_bits(ms_mode_ctl, kbm_ms_mode_ctl_daken);
    return k_error;
  }
  // IMPORTANT!  This begin_critical_section() is ended in the 'rw_intra_burst' function
  // to prevent xdata access while blk_xfer bit is enabled
  _mcu_begin_critical_section();
  // 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, use 512 bytes per burst
  _mcu_register_wr(x_isr0, kbm_isr0_blk_xfer_complete);
  _mcu_register_clr_bits(x_imr0, kbm_isr0_blk_xfer_complete);
  _mcu_register_wr(x_fmc_ctl, (kbm_fmc_ctl_512_byte_pkt|kbm_fmc_ctl_blk_xfer_en)) ;
  // point the byte count & source buffer for fmdu to buffer a
  _mcu_register_wr( x_ramrdbc_a1, 0x02) ;
  _mcu_register_wr( x_ramrdbc_a2, 0x00) ;
  // (rdtog_valid:1 ramrd_tog:0)
  _mcu_register_set_bits( x_ep2_ctl, kbm_ep2_ctl_rdtog_valid) ;
  // warning!
  // must do a while loop because we cannot yield
  // also, cannot have a timer, because of the memory stick bug... the timer
  // is in XDATA space, and touching it during ms fmdu xfers ist verboten
  while( !(_mcu_register_rd( x_isr0)&kbm_isr0_blk_xfer_complete)) ;
  _mcu_end_critical_section() ;
  if (!_ms_tx_data_fifo_is_empty())
  {
    trace0(0, ms, 10, "alert - entered write_end_burst before tx fifo emptied - wait before stopping dma");
    if (k_success != ms_wait_fifo_with_timeout(ms_fifo_stat_t_buf_e, ms_fifo_stat_t_buf_e, 3))  //rcc test for MS bug tbh!!!
      return k_error;
  }
  // clear daken before issuing command other than wr-page-data and rd-page-data
  _ms_register_clr_bits(ms_mode_ctl, kbm_ms_mode_ctl_daken);
  // get status
  if (k_success != ms_get_int(10))
    return k_error;
  if (_factor & kbm_ms_reg_int_cmdnk)
  {
    trace0(0, ms, 10, "error: cmdnk");
    return k_error;
  }
  if (_factor & kbm_ms_reg_int_breq)
  {
    trace0(0, ms, 0, "error: breq set after block-end (presumably) delivered");
    return k_error;
    //TRACE0(448, ms, 0, "alert: breq set");
  }
  if (!(_factor & kbm_ms_reg_int_ced))
  {
    trace0(0, ms, 0, "error: ced not set");
    return k_error;
  }

⌨️ 快捷键说明

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