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

📄 lun.c

📁 <B>SMSC USB2.0 Flash硬盘驱动源码</B>
💻 C
📖 第 1 页 / 共 5 页
字号:
//+-----------------------------------------------------------------------------
// Name:
//   dfa_lun_read_capacity()
//
// Declaration:
//   void dfa_lun_read_capacity(void) reentrant
//
// Purpose:
//
// Arguments:
//
// Return:
//
// Notes:
//   - This is a dfa.
//   - Should not need to be overridden.  This function will automatically use
//     lun instance data to respond to the host.
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
void dfa_lun_read_capacity(void)reentrant
{
  uint8* ptr;
  uint8  i;

  TRACE0(110, lun, 0, "dfa_lun_read_capacity()");
  lun_dump_sense(g_active_lun);
  g_tmp = _lun_data(media);
  // check for no media
  if (!(g_tmp & kbm_lun_media_present))
  {
    TRACE0(111, lun, 0, "no media present... setting command failed") ;
    _lun_data(sensep) = &sense_no_media;
    _thread_return_dfa(k_command_failed);
  }
  // check for media changed
  if (g_tmp & kbm_lun_media_unknown)
  {
    TRACE0(112, lun, 0, "media unknown... setting media change sense") ;
    _lun_data(sensep) = &sense_media_change;
    _thread_return_dfa(k_command_failed);
  }
  // validate command parameters
  //reladr = (g_bot_cbw.cdb[1] & 0x01);
  //lba    = _uint32(g_bot_cbw.cdb[2], g_bot_cbw.cdb[3], g_bot_cbw.cdb[4], g_bot_cbw.cdb[5]);
  //pmi    = (g_bot_cbw.cdb[8] & 0x01);
  //if (!reladr || !pmi || lba)
  //{
  //  _lun_data(g_active_lun, sensep) = &sense_illegal_rqst;
  //}
  // check for any error
  if (_lun_data(sensep) != &sense_none)
  {
    TRACE0(113, lun, 0, "active lun sensep != sense_none.  failing command") ;
    lun_dump_sense(g_active_lun);
    _thread_return_dfa(k_command_failed);
  }
  // report the data to the host
  stream_open(2, k_data_in);
  ptr = (uint8*) &(_lun_data(capacity));
  //lba = _lun_data(g_active_lun, capacity).lba_max.u32 - 1;
  for (i=0; i<8; i++)
  {
    while (!stream_put(2, ptr[i]));
  }
  _mscbot_zero_residue();
  stream_close(2);
  _lun_data(sensep) = &sense_none;
  _thread_return_dfa(k_command_passed);
}

//+-----------------------------------------------------------------------------
// Name:
//   dfa_lun_read
//
// Declaration:
//   void dfa_lun_read(void);
//
// Purpose:
//   Read data from an ata drive.
//
// 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:
//   Should be overridden.  Derived method should set callbacks, then call this.
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
// BBB: the first optimization to this was to call it directly from dfa_lun_process_cb.
// that eliminated a dfa layer (55usec push, 66usec pop) and required no changes here.
// the second optimization was to call it directly from dev_thread_wait_cbw.
// that eliminated another dfa layer cutting out 240 to 270 usec in toto (as measured)
// but required a change here.  all of the _thread_return_dfa() calls had to be replaced
// with __thread_return_dfa() calls to eliminate the final call to thread_end_dfa()
// (because its not run as a dfa any more, it just looks very much like one due to
// mildly clever macroitization) and replace it with a simple return.
// 07/01/02 - tbh - moved to lun.h
//#define __thread_return_dfa(__val) { (*(uint8 *)thread_rd_dfa_argp())=(__val); return; }
void dfa_lun_read(void)reentrant
{
  // profile: ~46..49 usec
#if 0
  TRACE0(114, lun, 0, "dfa_lun_read() - error: pure virtual method must be overridden");
  _lun_data(sensep) = &sense_illegal_opcode;
  __thread_return_dfa(k_command_failed);
#else





  //_profile_on(7);
  TRACE0(115, fmc, 0, "dfa_lun_read()");
  if (_lun_data(sensep) != &sense_none)
  {
    TRACE1(116, fmc, 0, "sensep: %04x", ((uint16) _lun_data(sensep)));  // use lun_dump_sense()
    __thread_return_dfa(k_command_failed);
  }
  _fmc_set_start_lb_8(g_bot_cbw.cdb[2], g_bot_cbw.cdb[3], g_bot_cbw.cdb[4], g_bot_cbw.cdb[5]);
  // do you trust the host enough to sacrifice robustness for speed here?  are you sure?
#ifndef k_optimizeXXX





  // valid lba range - required if host just wants to validate a range of addresses w/o a data xfer
  if (_fmc_get_start_lb_32() > _lun_data(capacity).lba_max.u32)
  {
    TRACE2(117, fmc, 0, "dfa_lun_read() - error bad lba:%04X%04X", (_fmc_get_start_lb_32() >> 16), (_fmc_get_start_lb_32() & 0xffff));
    _lun_data(sensep) = &sense_illegal_address;
    __thread_return_dfa(k_command_failed);
  }
#endif
  if (g_bot_cbw.cdb[0] == k_protocol_read_10)
  {
    TRACE0(118, fmc, 1, "read_10 command");
    _fmc_set_lb_count_8(0, 0, g_bot_cbw.cdb[7], g_bot_cbw.cdb[8]);
  }
  else
  {
    TRACE0(119, fmc, 1, "read 12 command");
    _fmc_set_lb_count_8(g_bot_cbw.cdb[6], g_bot_cbw.cdb[7], g_bot_cbw.cdb[8], g_bot_cbw.cdb[9]);
  }
  TRACE4(120, fmc, 0, "read lba:%04X%04X xfer_length:%04X%04X", _hw(_fmc_get_start_lb_32()), _lw(_fmc_get_start_lb_32()), _hw(g_n_lb_this_xfer.u32), _lw(g_n_lb_this_xfer.u32));
  // do you trust the host enough to sacrifice robustness for speed here?  are you sure?
#ifndef k_optimizeXXX
  if ((_fmc_get_start_lb_32() + _fmc_get_lb_count_32() - 1L) > _lun_data(capacity).lba_max.u32)
  {
    TRACE0(121, fmc, 0, "dfa_lun_read() - lba range invalid\n");
    TRACE2(122, fmc, 0, "dfa_lun_read() - error bad start:%04X%04X", (_fmc_get_start_lb_32() >> 16), (_fmc_get_start_lb_32() & 0xffff));
    TRACE2(123, fmc, 0, "dfa_lun_read() - error bad count:%04X%04X", (_fmc_get_lb_count_32() >> 16), (_fmc_get_lb_count_32() & 0xffff));
    TRACE2(124, fmc, 0, "dfa_lun_read() -        capacity:%04X%04X", (_lun_data(capacity).lba_max.u32 >> 16), (_lun_data(capacity).lba_max.u32 & 0xffff));
    _lun_data(sensep) = &sense_illegal_address;
    __thread_return_dfa(k_command_failed);
  }
#endif
  //_profile_off(7);  //ABOUT 46 usec
  if (k_success != fmc_transfer())
    __thread_return_dfa(k_command_failed);
  if (_lun_data(sensep) != &sense_none)
    __thread_return_dfa(k_command_failed);
  __thread_return_dfa(k_command_passed);
#endif
}

//+-----------------------------------------------------------------------------
// Name:
//   dfa_lun_write
//
// Declaration:
//   void dfa_lun_write(void);
//
// Purpose:
//   Write data.
//
// 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:
//   Should be overridden.  Derived method should set callbacks, then call this.
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
// BBB: the first optimization to this was to cal it directly from dfa_lun_process_cb.
// that eliminated a dfa layer (55usec push, 66usec pop) and required no changes here.
// the second optimization was to call it directly from dev_thread_wait_cbw.
// that eliminated another dfa layer cutting out 240 to 270 usec in toto (as measured)
// but required a change here.  all of the _thread_return_dfa() calls had to be replaced
// with __thread_return_dfa() calls to eliminate the final call to thread_end_dfa()
// (because its not run as a dfa any more, it just looks very much like one due to
// mildly clever macroitization) and replace it with a simple return.
void dfa_lun_write(void)reentrant
{
#if 0
  TRACE0(125, lun, 0, "dfa_lun_write() - error: pure virtual method must be overridden");
  _lun_data(sensep) = &sense_illegal_opcode;
  __thread_return_dfa(k_command_failed);
#else
  TRACE0(126, lun, 0, "dfa_lun_write");
  if (_lun_data(media) & kbm_lun_media_wrprot)
  {
    TRACE0(127, lun, 10, "write protected");
    _lun_data(sensep) = &sense_write_protect;
    __thread_return_dfa(k_command_failed);
  }
  if (_lun_data(sensep) != &sense_none)
  {
    __thread_return_dfa(k_command_failed);
  }
  _fmc_set_start_lb_8(g_bot_cbw.cdb[2], g_bot_cbw.cdb[3], g_bot_cbw.cdb[4], g_bot_cbw.cdb[5]);

  // do you trust the host enough to sacrifice robustness for speed here?  are you sure?
#ifndef k_optimizeXXX
  if (_fmc_get_start_lb_32() > _lun_data(capacity).lba_max.u32)
  {
    TRACE2(128, fmc, 0, "dfa_lun_write() - error bad lba:%04X%04X", (_fmc_get_start_lb_32() >> 16), (_fmc_get_start_lb_32() & 0xffff));
    _lun_data(sensep) = &sense_illegal_address;
    __thread_return_dfa(k_command_failed);
  }
#endif

  if (g_bot_cbw.cdb[0] == k_protocol_write_10)
  {
    TRACE0(129, fmc, 1, "write 10 command");
    _fmc_set_lb_count_8(0, 0, g_bot_cbw.cdb[7], g_bot_cbw.cdb[8]);
  }
  else
  {
    TRACE0(130, fmc, 1, "write 12 command");
    _fmc_set_lb_count_8(g_bot_cbw.cdb[6], g_bot_cbw.cdb[7], g_bot_cbw.cdb[8], g_bot_cbw.cdb[9]);
  }
  TRACE4(131, fmc, 0, "write lba:%04X%04X xfer_length:%04X%04X", _hw(_fmc_get_start_lb_32()), _lw(_fmc_get_start_lb_32()), _hw(g_n_lb_this_xfer.u32), _lw(g_n_lb_this_xfer.u32));

  // do you trust the host enough to sacrifice robustness for speed here?  are you sure?
#ifndef k_optimizeXXX
  if ((_fmc_get_start_lb_32() + _fmc_get_lb_count_32() - 1L) > _lun_data(capacity).lba_max.u32)
  {
    TRACE0(132, fmc, 0, "dfa_lun_write() - lba range invalid\n");
    _lun_data(sensep) = &sense_illegal_address;
    __thread_return_dfa(k_command_failed);
  }
#endif

  if (k_success != fmc_transfer())
    __thread_return_dfa(k_command_failed);
  if (_lun_data(sensep) != &sense_none)
    __thread_return_dfa(k_command_failed);
  __thread_return_dfa(k_command_passed);
#endif
}

//------------------------------------------------------------------------------
// verify options
#define kbm_verify_options_dpo      0x04
#define kbm_verify_options_bytchk   0x02
#define kbm_verify_options_reladr   0x01

//+-----------------------------------------------------------------------------
// Name:
//   dfa_lun_verify
//
// Declaration:
//   void dfa_lun_verify(void);
//
// Purpose:
//   Verify that the data on the drive matches the data sent down.
//
// 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 implementation is incorrect.  It should not write the data to the drive,
//   but should read the drive and compare to the provided data???
//   Should be overridden.  Derived method should set callbacks, then call this.
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
void dfa_lun_verify(void)reentrant
{
#if 0
  TRACE0(133, lun, 0, "dfa_lun_verify() - error: pure virtual method must be overridden");
  _lun_data(sensep) = &sense_illegal_opcode;
  _thread_return_dfa(k_command_failed);
#else
  uint8 vopt;

  TRACE0(134, fmc, 0, "dfa_lun_verify");
  if (_lun_data(sensep) != &sense_none)
  {
    _thread_return_dfa(k_command_failed);
  }
  vopt = g_bot_cbw.cdb[1];
  _fmc_get_start_lb_8(g_bot_cbw.cdb[2], g_bot_cbw.cdb[3], g_bot_cbw.cdb[4], g_bot_cbw.cdb[5]);
  // valid lba range - required if host just wants to validate a range of addresses w/o a data xfer
  if (_fmc_get_start_lb_32() > _lun_data(capacity).lba_max.u32)
  {
    TRACE0(135, fmc, 0, "verify error:  invalid lba");
    _lun_data(sensep) = &sense_illegal_address;
    _thread_return_dfa(k_command_failed);
  }
  _fmc_set_lb_count_8(0, 0, g_bot_cbw.cdb[7], g_bot_cbw.cdb[8]);
  if ((_fmc_get_start_lb_32() + _fmc_get_lb_count_32() - 1L) > _lun_data(capacity).lba_max.u32)
  {
    TRACE0(136, fmc, 0, "verify error:  lba range invalid\n");
    _lun_data(sensep) = &sense_illegal_address;
    _thread_return_dfa(k_command_failed);
  }
  // check to see if there is any data transfer
  if (!(vopt & kbm_verify_options_bytchk))
  {
    // no data comparrison, so just return a-ok.
    TRACE0(137, fmc, 0, "verify: no data comparison... just say ok\n");
    _lun_data(sensep) = &sense_none;
    _thread_return_dfa(k_command_passed);
  }
  TRACE4(138, fmc, 0, "verify lba:%04X%04X xfer_length:%04X%04X", _hw(_fmc_get_start_lb_32()), _lw(_fmc_get_start_lb_32()), _hw(g_n_lb_this_xfer.u32), _lw(g_n_lb_this_xfer.u32));
  TRACE4(139, fmc, 0, "verify - opts:0x%02X vlba:%04X%04X vlen:%04X", vopt, _hw(_fmc_get_start_lb_32()), _lw(_fmc_get_start_lb_32()), g_n_lb_this_xfer.u32);
  if (k_success != fmc_transfer())
    _thread_return_dfa(k_command_failed);
  if (_lun_data(sensep) != &sense_none)
    _thread_return_dfa(k_command_failed);
  _thread_return_dfa(k_command_passed);
#endif
}

//+-----------------------------------------------------------------------------
// Name:
//   dfa_lun_mode_sense()
//
// Declaration:
//   void dfa_lun_mode_sense(void) reentrant ;
//
// Purpose:
//
// Arguments:
//
// Return:
//
// Notes:
//   - This is a dfa.
//   - Should not need to be overridden.  This function will automatically use
//     lun instance data to respond to the host.
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
// spc3r07 8.4 - 4 bytes of header: mode-data-length, medium-type, device-parm, block-len
uint8 code _msense[4]    = { 0x03, 0x00, 0x00, 0x00};
uint8 code _msense_wp[4] = { 0x03, 0x00, 0x80, 0x00};
uint8 code _msense10[8] =  { 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8 code _msense10_wp[8] = { 0x00, 0x06, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00};

void dfa_lun_mode_sense(void) reentrant
{

⌨️ 快捷键说明

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