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

📄 mscbot.c

📁 <B>SMSC USB2.0 Flash硬盘驱动源码</B>
💻 C
📖 第 1 页 / 共 3 页
字号:
      g_data_len -= pktsz;
      mmu_rd_pkt(pnr, pktsz, g_sink_addr);
      g_sink_addr += pktsz;
      return (g_data_len ? k_in_progress : k_finished);

    default:
      trace0(0, bot, 0, "intr ignored");
      return (k_error);
  }
  return (k_error);
}

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
#define _hdw_clk_domain_bug_workaround() { _nop_(); _nop_(); }

t_isr_fragment _hpbot_thread_entry;
static t_result hpbot_wait_create(void) reentrant;
static t_result hpbot_wait_pipe_ready_for_rx(uint8) reentrant;
static t_result hpbot_wait_cbw(uint8) reentrant;
static t_result hpbot_wait_status_start(uint8) reentrant;
static t_result hpbot_wait_status_end(uint8) reentrant;

//------------------------------------------------------------------------------
// Declaration:
//  static void ndp2_tx_enable_ex(void);
//
// Purpose:
//  Error recovery - retransmit csw after a dropped ack from the host error on the csw.
//
// Arguments:
//  None.
//
// Return:
//  None.
//
// Note:
//  Only call from interrupt level.
//
// Since:
//   atapi-2.0
//------------------------------------------------------------------------------
static xdata t_csw _x_csw;
static void ndp2_tx_enable_ex(void) reentrant;
static void ndp2_tx_enable_ex() reentrant using 1
{
  _endpoint_tx_enable(k_tx_pipe);
  //
  if (!_tx_missed_ack)
    return;
  // off the thin diagonal - missed the ack of previous csw transmission.
  // must retransmit to get toggles resequenced.
  trace0(0, bot, 0, "warning - missed ack on prev csw xmit.  retransmit archival copy.");
  // dont need to copy if reuse same buf, but speed not important for this case
  mmu_wr_pkt(2, 5, (t_memory_ref)&_x_csw, sizeof(t_csw));
  txfifo_wr(2, 5);
  // enter a timer-protected synchronous loop.
  thread_set_timer(50);
  // if it doesn't go out in 50msec then its already too late - device is "dead" to the host
  while (!thread_got_sync(kbm_sync_usbtx))
  {
    if (thread_got_sync(kbm_sync_timer))
    {
      trace0(0, bot, 0, "error - timeout waiting for transmit");
      return;
    }
  }
  _tx_missed_ack = k_no;
}

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
static t_result hpbot_send_status(uint8 status) reentrant using 1
{
  trace0(0, bot, 0, "hpbot_send_status()");
  // ready for transmit, make sure toggles are sequenced.
  if (_tx_missed_ack)
    ndp2_tx_enable_ex();
  else
  {
    _endpoint_tx_enable(k_tx_pipe);
  }
  // fill in the archival csw to use for retransmit in case of rare dropped ack bus error
  _x_csw.dwCSWSignatureLo = 0x55;
  _x_csw.dwCSWSignatureHl = 0x53;
  _x_csw.dwCSWSignatureLh = 0x42;
  _x_csw.dwCSWSignatureHi = 0x53;
  _x_csw.dwCSWtagLo = g_bot_cbw.dwCBWtagLo;
  _x_csw.dwCSWtagHl = g_bot_cbw.dwCBWtagHl;
  _x_csw.dwCSWtagLh = g_bot_cbw.dwCBWtagLh;
  _x_csw.dwCSWtagHi = g_bot_cbw.dwCBWtagHi;
  _x_csw.dwCSWResidueLo = g_bot_data_len.u8.lo;
  _x_csw.dwCSWResidueHl = g_bot_data_len.u8.hl;
  _x_csw.dwCSWResidueLh = g_bot_data_len.u8.lh;
  _x_csw.dwCSWResidueHi = g_bot_data_len.u8.hi;
  _x_csw.bCSWStatus = status;
  trace1(0, bot, 0, "hpbot_send_status(%02X)", status);
  trace1(0, bot, 0, " csw.dwCSWResidueLo %02X (lsw lsb)", _x_csw.dwCSWResidueLo);
  trace1(0, bot, 0, " csw.dwCSWResidueHl %02X (lsw lsb)", _x_csw.dwCSWResidueHl);
  trace1(0, bot, 0, " csw.dwCSWResidueLh %02X (lsw lsb)", _x_csw.dwCSWResidueLh);
  trace1(0, bot, 0, " csw.dwCSWResidueHi %02X (lsw lsb)", _x_csw.dwCSWResidueHi);

  // still on the thin diagonal
  trace0(0, bot, 5, "ready to transmit status on the thin diagonal");
  trace0(0, bot, 6, "direction ==> transmit");
  _mcu_register_set_bits(x_ep2_ctl, kbm_ep2_ctl_dir);
  _hdw_clk_domain_bug_workaround();
  _mcu_register_wr(x_sram_addr_lo, k_pkt_addrlo[4]);
  _mcu_register_wr(x_sram_addr_hi, k_pkt_addrhi[4]);
  _hdw_clk_domain_bug_workaround();
  _mcu_register_wr(x_sram_data, 0x55);
  _mcu_register_wr(x_sram_data, 0x53);
  _mcu_register_wr(x_sram_data, 0x42);
  _mcu_register_wr(x_sram_data, 0x53);
  _mcu_register_wr(x_sram_data, g_bot_cbw.dwCBWtagLo);
  _mcu_register_wr(x_sram_data, g_bot_cbw.dwCBWtagHl);
  _mcu_register_wr(x_sram_data, g_bot_cbw.dwCBWtagLh);
  _mcu_register_wr(x_sram_data, g_bot_cbw.dwCBWtagHi);
  _mcu_register_wr(x_sram_data, g_bot_data_len.u8.lo);
  _mcu_register_wr(x_sram_data, g_bot_data_len.u8.hl);
  _mcu_register_wr(x_sram_data, g_bot_data_len.u8.lh);
  _mcu_register_wr(x_sram_data, g_bot_data_len.u8.hi);
  _mcu_register_wr(x_sram_data, status);
  _mcu_register_wr(x_ramrdbc_a2, 13);
  _mcu_register_wr(x_ramrdbc_a1, 0);
  // determine if the pipe needs to be stalled
  if (g_bot_xfer_dir == k_dir_read)
  {
    // reads:  stall if error OR residue
    if (status || g_bot_data_len.u32)
    {
      trace0(0, bot, 0, "stalling the tx pipe");
      endpoint_tx_stall(k_tx_pipe);
    }
  }
  else                  // g_bot_xfer_dir == k_dir_write
  {
    // writes: stall if error AND residue (another out token is expected to see the stall)
    //if (status && (g_bot_data_len.u32 > 512L))
    if (status && _stall_ndp2_rx)
    {
      // only stall the out-pipe if there is residue, otherwise the host
      // won't see the stall until it tries to send the CBW.  That violates the
      // protocol and the host resets us.
      trace0(0, bot, 99, "alert - stalling the rx pipe");
      _ndp2_rx_stalled = k_yes;
      endpoint_rx_stall(k_rx_pipe);
    }
  }
  _stall_ndp2_rx = k_no;
  // if you hafta stall, do it before que-ing the packet...
  // txfifo_wr - transmit - tx from buffer 'a'
  trace0(0, bot, 7, "hit the transmit bit - ramrd_a ==> enabled, masked in (because the csw must be sent)");
  _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();
  _mcu_register_clr_bits(x_imr0, kbm_isr0_ramrd_a);
  //thread_set_timer(255);  $$$
  _endpoint_unmask_outnak(k_rx_pipe);
  _hpbot_thread_entry = hpbot_wait_status_end;
  #ifdef k_pfm_demo

  // turn off the debug lights of science
  _mcu_register_set_bits(x_gpiob_out, kbm_gpio12 |kbm_gpio13 |kbm_gpio14 |kbm_gpio15);
  #endif
  return (k_success);
}

//------------------------------------------------------------------------------
// this is only called from the foreground.
// it is called only once at por.
// it allows the fgnd to start the high priority thread's interrupt chain
//------------------------------------------------------------------------------
void fgnd_hpbot_wait_create() reentrant
{
  trace0(0, bot, 0, "fgnd_hpbot_wait_create()");
  _mcu_begin_critical_section();
  _endpoint_unmask_outnak(k_rx_pipe);
  _hpbot_thread_entry = hpbot_wait_pipe_ready_for_rx;
  _tx_missed_ack = k_no;
  _mcu_end_critical_section();
}

//------------------------------------------------------------------------------
// this is only called form the isrs
//------------------------------------------------------------------------------
static t_result hpbot_wait_create() reentrant using 1
{
  trace0(0, bot, 0, "hpbot_wait_create()");
  _tx_missed_ack = k_no;
  _thread_clr_sync(kbm_sync_outnak);
  _endpoint_unmask_outnak(k_rx_pipe);
  dev_turn_off_activity_indicator();
  #ifdef k_pfm_demo

  // turn off the debug lights of science
  _mcu_register_set_bits(x_gpiob_out, kbm_gpio12 |kbm_gpio13 |kbm_gpio14 |kbm_gpio15);
  #endif
  #ifdef k_pfm_led

  // turn off the activity LEDs
  _mcu_register_clr_bits(x_gpiob_out, kbm_gpio12 |kbm_gpio13 |kbm_gpio14 |kbm_gpio15);
  #endif
  _hpbot_thread_entry = hpbot_wait_pipe_ready_for_rx;
  return (k_success);
}

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
static t_result hpbot_wait_pipe_ready_for_rx(uint8 intr) reentrant using 1
{
  trace1(0, bot, 0, "hpbot_wait_pipe_ready_for_rx(%d)", intr);
  switch (intr)
  {
    // outnak
    case k_irq_nak2rx:
      if (!dev_rd_most_recent_config())
      {
        // do nothing but rearm for outnaks until the set-config has been processed.
        // this avoids a race condition where the hardware processes the set-config(1)
        // then the first cbw arrives and is delivered to the drive -before- the drive
        // is powered on because the fgnd has not yet processed the set-config()
        // and powered up the drive.  (the fw does not process the control pipe for set-config...
        // the hardware does, and then gives an interrupt letting the fw see the config value...
        // so, leave the pipe in the "por nakking" state, or, after suspend, the "tx"
        // state so the cbw will be nakked, not received, until the drive gets powered
        // on and initialized.  (note this requires that the suspend handler put the
        // pipe into the "tx" state so any cbw will be nakked in the case where the
        // resume interrupt occurs, then a usbreset, then a set-config, and a quickly
        // following inquiry on the bulk pipe.
        _endpoint_unmask_outnak(k_rx_pipe);
        return (k_success);
      }
      // the outnak signals that the host is trying to send us a cbw
      trace0(0, bot, 0, "got the nak, enabling rx endpoint");
      _endpoint_rx_enable(k_rx_pipe);
      _buffer_rx_enable(4);
      _hpbot_thread_entry = hpbot_wait_cbw;
      return (k_success);

      // usbrst
    case k_irq_usb_stat_reset:
    case k_irq_usb_reset:
      _thread_clr_sync(kbm_sync_all);
      hpbot_wait_create();
      // let the default interrupt handler see this also
      return (k_ignored);

      // let the default inrt handler handle everything else
    default:
      trace0(0, bot, 0, "intr ignored");
      return (k_ignored);
  }
}

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
static t_result hpbot_wait_cbw(uint8 intr) reentrant using 1
{
  // t_data_ref bufp;
  t_xdata_ref bufp;

  trace1(0, bot, 0, "hpbot_wait_cbw(%d)", intr);
  switch (intr)
  {
    // usbrx:  profiling shows this case takes about 58usec
    case k_irq_ramwr_a:
      //_profile_on(5);
      //mmu_rd_pkt(pnr, sizeof(t_cbw), (t_memory_ref)&g_bot_cbw);
      // bufp = (t_data_ref)&g_bot_cbw;
      bufp=(t_xdata_ref)&g_bot_cbw;
      _mcu_register_wr(x_sram_addr_lo, k_pkt_addrlo[4]);
      _mcu_register_wr(x_sram_addr_hi, k_pkt_addrhi[4]);
      _hdw_clk_domain_bug_workaround();
      // unrolled loop, 31 bytes of cbw
      *bufp++=_mcu_register_rd(x_sram_data);
      *bufp++=_mcu_register_rd(x_sram_data);
      *bufp++=_mcu_register_rd(x_sram_data);
      *bufp++=_mcu_register_rd(x_sram_data);
      *bufp++=_mcu_register_rd(x_sram_data);
      *bufp++=_mcu_register_rd(x_sram_data);
      *bufp++=_mcu_register_rd(x_sram_data);
      *bufp++=_mcu_register_rd(x_sram_data);
      *bufp++=_mcu_register_rd(x_sram_data);
      *bufp++=_mcu_register_rd(x_sram_data);
      *bufp++=_mcu_register_rd(x_sram_data);
      *bufp++=_mcu_register_rd(x_sram_data);
      *bufp++=_mcu_register_rd(x_sram_data);
      *bufp++=_mcu_register_rd(x_sram_data);
      *bufp++=_mcu_register_rd(x_sram_data);
      *bufp++=_mcu_register_rd(x_sram_data);
      *bufp++=_mcu_register_rd(x_sram_data);
      *bufp++=_mcu_register_rd(x_sram_data);
      *bufp++=_mcu_register_rd(x_sram_data);
      *bufp++=_mcu_register_rd(x_sram_data);
      *bufp++=_mcu_register_rd(x_sram_data);
      *bufp++=_mcu_register_rd(x_sram_data);
      *bufp++=_mcu_register_rd(x_sram_data);
      *bufp++=_mcu_register_rd(x_sram_data);
      *bufp++=_mcu_register_rd(x_sram_data);
      *bufp++=_mcu_register_rd(x_sram_data);
      *bufp++=_mcu_register_rd(x_sram_data);
      *bufp++=_mcu_register_rd(x_sram_data);
      *bufp++=_mcu_register_rd(x_sram_data);
      *bufp++=_mcu_register_rd(x_sram_data);
      *bufp++=_mcu_register_rd(x_sram_data);
      //mmu_deallocate(4);
      _mcu_register_wr(x_isr0, kbm_isr0_ramwr_a);
      _mcu_register_clr_bits(x_imr0, kbm_isr0_ramwr_a);
      // dump its contents
      trace1(0, bot, 0, "dwCBWSignature: %02X (lsw lsb)", g_bot_cbw.dwCBWSignatureLo);
      trace1(0, bot, 0, "dwCBWSignature: %02X (lsw msb)", g_bot_cbw.dwCBWSignatureHl);
      trace1(0, bot, 0, "dwCBWSignature: %02X (msw lsb)", g_bot_cbw.dwCBWSignatureLh);
      trace1(0, bot, 0, "dwCBWSignature: %02X (msw msb)", g_bot_cbw.dwCBWSignatureHi);
      trace1(0, bot, 0, "      dwCBWTag: %02X (lsw lsb)", g_bot_cbw.dwCBWtagLo);
      trace1(0, bot, 0, "      dwCBWTag: %02X (lsw msb)", g_bot_cbw.dwCBWtagHl);
      trace1(0, bot, 0, "      dwCBWTag: %02X (msw lsb)", g_bot_cbw.dwCBWtagLh);
      trace1(0, bot, 0, "      dwCBWTag: %02X (msw msb)", g_bot_cbw.dwCBWtagHi);
      trace1(0, bot, 0, "  dwXferLength: %02X (lsw lsb)", g_bot_cbw.dwCBWXferLengthLo);
      trace1(0, bot, 0, "  dwXferLength: %02X (lsw msb)", g_bot_cbw.dwCBWXferLengthHl);
      trace1(0, bot, 0, "  dwXferLength: %02X (msw lsb)", g_bot_cbw.dwCBWXferLengthLh);
      trace1(0, bot, 0, "  dwXferLength: %02X (msw msb)", g_bot_cbw.dwCBWXferLengthHi);
      trace1(0, bot, 0, "       bCBWlun: %02X",           g_bot_cbw.bCBWlun);
      trace1(0, bot, 0, "    bmCBWFlags: %02X",           g_bot_cbw.bCBWFlags);
      trace1(0, bot, 0, "  bCBWCBLength: %02X",           g_bot_cbw.bCBWCBLength);
      // verify the signature
      if ((0x55 != g_bot_cbw.dwCBWSignatureLo) ||
          (0x53 != g_bot_cbw.dwCBWSignatureHl) ||
          (0x42 != g_bot_cbw.dwCBWSignatureLh) ||
          (0x43 != g_bot_cbw.dwCBWSignatureHi))
      {
        trace0(0, bot, 0, "error - bad signature");
        return (hpbot_send_status(k_command_failed));
      }
      // verify the cdb length
      if (0x10 < g_bot_cbw.bCBWCBLength)
      {
        trace0(0, bot, 0, "error - bad cdb length");
        return (hpbot_send_status(k_command_failed));
      }
      // initialize everything we might need to use
      // extract the parameters from the command
      g_bot_data_len.u8.lo = g_bot_cbw.dwCBWXferLengthLo;
      g_bot_data_len.u8.hl = g_bot_cbw.dwCBWXferLengthHl;
      g_bot_data_len.u8.lh = g_bot_cbw.dwCBWXferLengthLh;
      g_bot_data_len.u8.hi = g_bot_cbw.dwCBWXferLengthHi;

⌨️ 快捷键说明

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