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

📄 ms.c

📁 <B>SMSC USB2.0 Flash硬盘驱动源码</B>
💻 C
📖 第 1 页 / 共 5 页
字号:
/*============================================================================
  ____________________________________________________________________________
                                ______________________________________________
   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.
  ____________________________________________________________________________
  ____________________________________________________________________________
  sm.c - memory stick mass storage class implementation file
  ____________________________________________________________________________
  comments tbd
  ____________________________________________________________________________
  Revision History
  Date      Who  Comment
  ________  ___  _____________________________________________________________
  11/##/01  tbh  initial version
  02/26/02  tbh  changed strcpy to strncpy for safety
  04/01/02  tbh  read_boot now finds 2 boot blocks on cards that have them
  04/02/02  tbh  added ms_copy_page
  04/17/02  tbh  override dfa_lun_mode_sense
  04/18/02  tbh  removed that override.  superclass method handles it now.
  05/07/02  cds  added a rw_intra_burst callback to actually perform the blk_xfer inner loop
                 to get around xdata-access bug in the chip
  05/09/02  cds  added call to _dev_soft_reset() when a usbreset occurs during rw_intra_bursts
  06/03/02  cds  updated ms_write_end_xfer() to turn off auto-xfer so that
                 the sector copy can use the fmdu.
  06/19/02  tbh  converted to read boot into xdata buf instead of packet buf
                 since bot layer is can now run concurrently with discovery
  06/20/02  tbh  tweaked the intra-burst callback to stop clearing the isr bit
                 to be compatible with the perf opto done in fmc_transfer
  06/26/02  tbh  added nops in ms_wait_msc_stat_sif_with_timeout.
                 two back to back reads of the alt_stat register causes failure.
                 there is some latency issue causing intermittant failure...
                 inserting nops fixes it.
  07/01/02  tbh  write-protect check is now performed in the lun layer
  07/09/02  cds  renamed WorkBuf to g_sector_buffer
  07/12/02  tbh  lun string name change caused by mandate from on high
  07/17/02  tbh  ms_write_end_xfer sets g_fmc_rslt if map_write_flush returns an error
                 because fmc_transfer doesn't check the return code of the callback.
                 I feared breaking all of the other luns by changing fmc...
  07/18/02  tbh  fixed long standing (but until recently dormant) bug in
                 ms_rw_intra_burst_callback where && was erroneously used
                 in place of &.
  07/23/02  tbh  the ms_wait_msc_stat_sif_with_timeout nop injection was insufficient,
                 it seems.  i increased the number of ops and moved them into the do
                 loop to delay betwean -every- read of the ms_alt_stat register.
                 this appears to resolve the issue of the cards formatted by DoTop
                 becoming unreadable in the 210.
  07/31/02  cds  called media_set_active(...) instead of setting g_active_media
                 to select a new media object.
  08/06/02  tbh  added _force_one_burst_per_split to solve the SanDisk 64MB cards
                 w/ date codes < J [bug report br308]
  08/13/02  tbh  added status check after read error in read-begin-burst to
                 distinguish uncorrectabel error from correctable error on last block.
  08/28/02  tbh  added extra get-int after block-end command for read and write
                 to ensure that no error happened issuing that command (shawn's suggestions).
                 also 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)
                                                  => _media_data(segments_per_page)
  09/12/02  tbh  replaced strncpy() with memcpy() to save data space.
  09/18/02  cds  initialized _media_data(options) field to kbm_media_data_opts_none
  10/17/02  cds  updated for new lun vtbl and lun_data macros
  11/01/02  tbh  made xbuf_rd() visible so ms_media.c can call it.
                 ms_read_boot_block was using the wrong boot block when more than one
                 exists.  changed to use the lowest-numbered one, per the spec.
                 move write-protection test to occur before map_build_sector_map
                 to avoid erroneous block erase on write protected disks.
  11/02/02  tbh  added ms_is_this_blk_in_bad_blk_tbl().
                 added ms_find_map_block() to see if any exists, and compare contents.
  11/03/02  cds  - updated ms_is_this_blk_in_bad_blk_tbl() to include info block
                 - added new global g_ms_user_area_start_blk to help mapper know which blocks
                   are to be used for mapping
                 - updated bad-block table code to read data in big endian format
============================================================================*/
#define __ms_dot_c__
#include "project.h"
#include "dev.h"

code _vtbl_defn(ms);

void fmc_dbg_dump_sector(uint8* sector) reentrant;

//#define k_memory_stick_eraser

//------------------------------------------------------------------------------
// module globals

// status
xdata uint8 _factor;
xdata uint8 _status0;
xdata uint8 _status1;

// extra data registers buffer
xdata uint8 g_ms_extra[4];

// shadow registers
xdata uint8 g_ms_blk_addr_msb;
xdata uint8 g_ms_blk_addr_mid;
xdata uint8 g_ms_blk_addr_lsb;
xdata uint8 g_ms_page;

// logical to physical sector mapping table
//xdata uint16 _ms_map_table[512];
#define k_map_boot_blk    0x8000
#define k_map_initial_err 0xfffd
#define k_map_fatal_err   0xfffe

// total number of blocks on the card
xdata t_uw16 _ms_block_per_card;

// block size - 8k or 16k bytes
xdata t_uw16 _ms_byte_per_block;

// segment size - number of card blocks in a card segment
#define k_phy_block_per_segment      512L
#define k_log_block_per_segment      496L
#define k_log_block_per_boot_segment 494L

// pages per block - a page is analogous to a mass storage class logical block, or disk sector
xdata uint16 _ms_page_per_block;

// tables used by the mapper/pager
#define k_ms_max_zones_per_table 2
xdata uint16 _ms_log2phy[k_ms_max_zones_per_table][k_phy_block_per_segment];
xdata uint8  _ms_assign_map[k_ms_max_zones_per_table][k_phy_block_per_segment/8];

xdata uint16 _ms_bad_blk_tbl[256];

xdata uint16 g_ms_user_area_start_blk;



// br308
// set to false when the boot blocks are read.
// set to true if a block write fails with breq after block-end (i.e., exibits the bug).
// provides the solution for the SanDisk 64MB cards w/ date codes < J
static bit _force_one_burst_per_split;

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
t_bool ms_is_this_blk_in_bad_blk_tbl(uint16 blk) reentrant
{
  uint8 i;
  for (i=0; i<255; i++)
  {
    // the zeroth entry in this table is the "information block"
    // any non-FFFF blocks in the table that are off the end of the card
    // are to be ignored.
    if (_ms_bad_blk_tbl[i] == 0xFFFF)
      return k_no;
    if (_ms_bad_blk_tbl[i] == blk)
    {
      // this physical block appears in the bad block list
      trace1(0, ms_media, 110, "alert: block:%d is in the bad block table!", _ms_bad_blk_tbl[i]);
      if (!i)
      {
        trace0(0, ms_media, 110, "       and its the information block!");
      }
      return k_yes;
    }
  }
  return k_no;
}

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
t_bool ms_is_this_blk_the_information_block(uint16 blk) reentrant
{
  // the zeroth entry in this table is the "information block"
  if (_ms_bad_blk_tbl[0] == blk)
  {
    // this physical block appears in the bad block list
    trace1(0, ms_media, 110, "alert: block:%d is in the information block!", blk);
    return k_yes;
  }
  return k_no;
}

//+-----------------------------------------------------------------------------
// Name:
//   ms_wait_msc_stat_rdy_with_timeout
//
// Declaration:
//   t_result ms_wait_msc_stat_rdy_with_timeout(uint8 ticks);
//
// Purpose:
//   Wait for the ready bit in the msc status register to go hi indicating that
//   the MS card can accept a TPC.
//
// Arguments:
//   ticks - a uint8 representing the timeout period in milliseconds.
//
// Return:
//   A t_result indicating:
//     k_success - the bit was set, and this routine has cleared it.
//     k_usbrst  - usb reset signalling was detected while waiting.
//     k_aborted - traffic occurred on the control pipe while waiting (probably a mass storage reset).
//     k_timeout - timeout limit exceeded.
//
// Notes:
//   This is a FUNCTION, not a DFA.
//   Clears the ready bit after seeing it get set (to rearm for the next one).
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
xdata uint8 status;  //!!! NEED PROPER NAMES IF STICK TO THIS SCHEME (AVOID STKOVF)
xdata t_sync sync;
t_result ms_wait_msc_stat_rdy_with_timeout(uint8 ticks) reentrant;
t_result ms_wait_msc_stat_rdy_with_timeout(uint8 ticks) reentrant
{
  //uint8 status;
  //t_sync sync;

  trace1(0, ms, 1, "ms_wait_msc_stat_rdy_with_timeout(ticks:%d)", ticks);
  //_stack_dump();
  //_stack_check();
  thread_set_timer(ticks+1);
  do
  {
    // clear the interrupt generator in the sony block
    //status = _ms_register_rd(ms_alt_stat);
    status = _mcu_register_rd(x_msc_stat);
    sync = thread_got_sync(kbm_sync_usbrst |kbm_sync_abort |kbm_sync_timer);
    _thread_clr_sync(sync);
    if (sync & kbm_sync_abort)
    {
      trace0(0, err, 110, "ms_wait_msc_stat_rdy_with_timeout() - error: kbm_sync_abort");
      return k_aborted;
    }
    if (sync & kbm_sync_usbrst)
    {
      trace0(0, err, 110, "ms_wait_msc_stat_rdy_with_timeout() - error: kbm_sync_usbrst");
      return k_usbreset;
    }
    if (sync & kbm_sync_timer)
    {
      trace0(0, err, 110, "ms_wait_msc_stat_rdy_with_timeout() - error: kbm_sync_timer");
      return k_timeout;
    }
  } while ((status & kbm_msc_stat_rdy) != kbm_msc_stat_rdy);
  _mcu_register_wr(x_msc_stat, kbm_msc_stat_rdy);
  return k_success;
}

//+-----------------------------------------------------------------------------
// Name:
//   ms_wait_msc_stat_sif_with_timeout
//
// Declaration:
//   t_result ms_wait_msc_stat_sif_with_timeout(uint8 ticks);
//
// Purpose:
//   Wait for the sif bit in the msc alternate status register to go hi indicating
//   that the getint command can be issued.
//
// Arguments:
//   ticks - a uint8 representing the timeout period in milliseconds.
//
// Return:
//   A t_result indicating:
//     k_success - the bit was set, and this routine has cleared it.
//     k_usbrst  - usb reset signalling was detected while waiting.
//     k_aborted - traffic occurred on the control pipe while waiting (probably a mass storage reset).
//     k_timeout - timeout limit exceeded.
//
// Notes:
//   This is a FUNCTION, not a DFA.
//   Clears the sif bit after seeing it get set (to rearm for the next one)
//   by writing the msc staus register (causing alternate status register to clear also.
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
t_result ms_wait_msc_stat_sif_with_timeout(uint8 ticks) reentrant;
t_result ms_wait_msc_stat_sif_with_timeout(uint8 ticks) reentrant
{
  //uint8 status;
  //t_sync sync;

  trace1(0, ms, 0, "ms_wait_msc_stat_sif_with_timeout(ticks:%d)", ticks);
  //_stack_check();
  thread_set_timer(ticks+1);
  do
  {
    // two back to back reads of the alt_stat register appears to cause failure.
    // apparently there is some latency issue causing intermittant failure...
    // note well that i have not yet invested the time to determine if this
    // is really cause by a synchronization issue or not.  i merely opted
    // for the 'bit ricochet' gambit and inserted a delay between every read of the
    // ms_alt_status register.  emperical evidence suggests that this fixs the problem...
    // but i am not willing to assert that as a proof...
    // the actual cause of death could not be determined from the forensic evidence.
    _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
    _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
    _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
    // clear the interrupt generator in the sony block
    status = _ms_register_rd(ms_alt_stat);
    //status = _mcu_register_rd(x_msc_stat);
    trace1(0, ms, 0, "status:0x%02X", status);
    sync = thread_got_sync(kbm_sync_usbrst |kbm_sync_abort |kbm_sync_timer);
    _thread_clr_sync(sync);
    if (sync & kbm_sync_abort)
    {
      trace0(0, err, 110, "ms_wait_msc_stat_sif_with_timeout() - error: kbm_sync_abort");
      return k_aborted;
    }
    if (sync & kbm_sync_usbrst)
    {
      trace0(0, err, 110, "ms_wait_msc_stat_sif_with_timeout() - error: kbm_sync_usbrst");
      return k_usbreset;
    }
    if (sync & kbm_sync_timer)
    {
      trace0(0, err, 110, "ms_wait_msc_stat_sif_with_timeout() - error: kbm_sync_timer");
      return k_timeout;
    }
  } while ((status & kbm_msc_stat_sif) != kbm_msc_stat_sif);
  _mcu_register_wr(x_msc_stat, kbm_msc_stat_sif);
  return k_success;
}

//+-----------------------------------------------------------------------------
// Name:
//   ms_wait_fifo_with_timeout
//
// Declaration:
//   t_result ms_wait_fifo_with_timeout(uint8 msk, uint8 val, uint8 ticks);
//
// Purpose:
//   Wait for the a bit patern in the msc fifo status register to go hi indicating
//   that the fifo has emptied, filled, etc.  (Waiting for status & mask == value.)
//
// Arguments:
//   msk   - a uint8 bitmask to be logically and-ed with the msc fifo status register.
//   val   - a uint8 indicating the desired bit pattern.
//   ticks - a uint8 representing the timeout period in milliseconds.
//

⌨️ 快捷键说明

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