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

📄 mscbot.c

📁 <B>SMSC USB2.0 Flash硬盘驱动源码</B>
💻 C
📖 第 1 页 / 共 3 页
字号:
      // what direction is the data supposed to flow?
      g_bot_xfer_dir = g_bot_cbw.bCBWFlags & kbm_cbw_dir_d2h ? k_dir_read : k_dir_write;
      // reverse pipe for reads
      if (g_bot_xfer_dir == k_dir_read)
      {
        if (_tx_missed_ack)
          ndp2_tx_enable_ex();
        else
        {
          _endpoint_tx_enable(k_tx_pipe);
        }
      }
      // convert the logical lun (from the cbw) into a physical lun (index into lun tables)
      _active_lun = _lun_log2phy(g_bot_cbw.bCBWlun);
      #ifdef k_pfm_demo

      // there are 5 phy luns, but only 4 leds.  assumes sd and mmc "share" an led.
      _mcu_register_clr_bits(x_gpiob_out, 0x10 << _min(3, _active_lun));
      #endif


      // the mux is no longer enabled here because this is an isr.
      // the mux is enabled in the dev thread when it wakes on sync-cbw.
      // _lun_enable_mux(_active_lun)();
      // data access led on during read/write
      switch (g_bot_cbw.cdb[0])
      {
        case k_protocol_read_10:
        case k_protocol_read_12:
        case k_protocol_write_10:
        case k_protocol_write_12:
        case k_protocol_verify_10:
          if (g_post_access_blink_secs)  //Are we blinking still?
          {
            irq_control(k_irq_cpu_t1,  kbm_irqctl_mask);  //then stop the timer
            g_post_access_blink_secs = 0x00;
            trace0(0, dev, 0, "next data access blinker off");
          }
          if (g_blink_interval)  //Are we supposed to blink?
          {
            irq_control(k_irq_cpu_t1,  kbm_irqctl_unmask);  //then start the timer
            _data_access = k_true;
          }
          //rcc code to turn OFF leds during access to respective luns LEDs are ON when card inserted
          // they go off when card is out or blink off when accessed.
          #ifdef k_pfm_led
          // there are 5 phy luns, but only 4 leds.  assumes sd and mmc "share" an led.
          //_mcu_register_clr_bits(x_gpiob_out, 0x10 << _min(3, _active_lun));
          if (_lun_is_media_present(_active_lun))
          {
            switch (_active_lun)
            {
              case k_lun_cf:
                trace0(0, dev, 66, "CF LED OFF!");
                _mcu_register_clr_bits(x_gpiob_out,  kbm_gpio13);
                break;
              case k_lun_ms:
                trace0(0, dev, 66, "MS LED OFF!");
                _mcu_register_clr_bits(x_gpiob_out,  kbm_gpio12);
                break;
              case k_lun_sm:
                trace0(0, dev, 66, "SM LED OFF!");
                _mcu_register_clr_bits(x_gpiob_out,  kbm_gpio14);
                break;
              case k_lun_sd:
                trace0(0, dev, 66, "SD LED OFF!");
                _mcu_register_clr_bits(x_gpiob_out,  kbm_gpio15);
                break;
              case k_lun_mmc:
                trace0(0, dev, 66, "MMC LED OFF!");
                _mcu_register_clr_bits(x_gpiob_out,  kbm_gpio15);
                break;
            }
          }
          #endif
          break;
      }
      // break the interrupt chain until the foreground is done and restarts the chain
      _hpbot_thread_entry = NULL;
      // tell the fgnd to run the command
      //thread_set_sync(g_ix_dev_thread, kbm_sync_cbw);
      g_thread[g_ix_dev_thread].bits_got |= kbm_sync_cbw;
      //_profile_off(5);
      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);
  }
}

//------------------------------------------------------------------------------
// this is only called from the foreground.
// it is called immediately after processing a msc command.
// it allows the fgnd to restart the high priority thread's
// interrupt chain after the data phase of a transfer
//------------------------------------------------------------------------------
void fgnd_hpbot_wait_status_start(uint8 rslt) reentrant
{
  // wait to hear the innak before sending the status
  trace1(0, bot, 0, "fgnd_hpbot_wait_status_start(%d)", rslt);
  _mcu_begin_critical_section();
  _endpoint_unmask_innak(k_rx_pipe);
  _endpoint_unmask_outnak(k_rx_pipe);
  _hpbot_thread_entry = hpbot_wait_status_start;
  _status = rslt;
  _mcu_end_critical_section();
}

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
static t_result hpbot_wait_status_start(uint8 intr) reentrant using 1
{
  trace1(0, bot, 0, "hpbot_wait_status_start(%d)", intr);
  switch (intr)
  {
    // innak
    case k_irq_nak2tx:
      trace0(0, bot, 99, "innak");
      // the status stage cannot start on a read until the final data packet has been transmitted
      // to the host, and ack'd.  this can be detected by checking to see that both ramrd a and b
      // are set (ie, not in use, and/or waiting to be transmitted).  this helps avoids mistaking
      // an innak for the data as the innak for the status.  in theory the status stage shouldn't
      // even be run intil after all the data has been sent and ack'd by the host.  but, since we
      // are going for minimum csw turnaround time, we want to send the status asap. the tricky
      // thing here is knowing that the data stage has ended.  this code may not be perfected
      // handle all error conditions yet... caveat implementor...
      if (g_bot_xfer_dir == k_dir_read)
        if ((_mcu_register_rd(x_isr0) & (kbm_isr0_ramrd_a |kbm_isr0_ramrd_b)) != (kbm_isr0_ramrd_a |kbm_isr0_ramrd_b))
        {
          // a transmittable buffer is still in play... not time to send the csw yet...
          _endpoint_unmask_innak(k_tx_pipe);
          return (k_ignored);
        }
        // it is not safe to turn off autoxfer until after innak is heard.
        // otherwise you could lose possible retransmit of the final data packet.
        // it does not hurt to turn it off if it was already off though...
      trace0(0, bot, 0, "AUTOXFER ==> OFF");
      _mcu_register_clr_bits(x_fmc_ctl, kbm_fmc_ctl_auto_trans);
      _stall_ndp2_rx = k_no;
      return (hpbot_send_status(_status));

      // outnak
    case k_irq_nak2rx:
      trace0(0, bot, 99, "outnak");
      // it is not safe to turn off autoxfer until after innak is heard.
      // otherwise you could lose possible retransmit of the final data packet.
      // it does not hurt to turn it off if it was already off though...
      trace0(0, bot, 0, "AUTOXFER ==> OFF");
      _mcu_register_clr_bits(x_fmc_ctl, kbm_fmc_ctl_auto_trans);
      _stall_ndp2_rx = k_yes;
      return (hpbot_send_status(_status));

      // 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 intr handler handle everything else
    default:
      trace0(0, bot, 0, "intr ignored");
      return (k_ignored);
  }
}

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
static uint8 _nakkount = 0;
static t_result hpbot_wait_status_end(uint8 intr) reentrant using 1
{
  trace1(0, bot, 0, "hpbot_wait_status_end(%d)", intr);
  if (_data_access)     // Is this a data access cmd?
  {
    if (g_blink_interval)  //Were we blinking?
    {
      //do we need to continue blinking?
      //we could do a direct read from nvstore but I believe that is a waste of time on this fast code
      g_post_access_blink_secs = g_nvstore_post_access_blink_secs;
      if (!g_post_access_blink_secs)  //No need to blink
      {
        irq_control(k_irq_cpu_t1,  kbm_irqctl_mask);  //then stop the timer
      }
      else
      {
        trace0(0, dev, 0, "blinker on");
      }
    }
    _data_access = k_false;
  }
  dev_turn_off_activity_indicator();

#ifdef k_pfm_led
  if (_lun_is_media_present(_active_lun))
  {
    switch (_active_lun)
    {
      case k_lun_cf:
        trace0(0, dev, 66, "CF LED ON!");
        _mcu_register_set_bits(x_gpiob_out,  kbm_gpio13);
        break;
      case k_lun_ms:
        trace0(0, dev, 66, "MS LED ON!");
        _mcu_register_set_bits(x_gpiob_out,  kbm_gpio12);
        break;
      case k_lun_sm:
        trace0(0, dev, 66, "SM LED ON!");
        _mcu_register_set_bits(x_gpiob_out,  kbm_gpio14);
        break;
      case k_lun_sd:
        if (_lun_is_media_known(_active_lun))
        {
          trace0(0, dev, 66, "SD LED ON!");
          _mcu_register_set_bits(x_gpiob_out,  kbm_gpio15);
        }
        break;
      case k_lun_mmc:
        if (_lun_is_media_known(_active_lun))
        {
          trace0(0, dev, 66, "MMC LED ON!");
          _mcu_register_set_bits(x_gpiob_out,  kbm_gpio15);
        }
        break;
    }
  }
#endif

  switch (intr)
  {
    // usbtx:
    case k_irq_ramrd_a:
      trace0(0, bot, 10, "got the kbm_sync_usbtx");
      _nakkount = 0;
      _endpoint_rx_enable(k_rx_pipe);
      _buffer_rx_enable(4);
      _hpbot_thread_entry = hpbot_wait_cbw;
      return (k_success);

      // outnak
    case k_irq_nak2rx:
      if (_nakkount++ < 200)
      {
        trace0(0, bot, 11, "alert - got the kbm_sync_outnak - *before* the tx - dropped ack?");
        _endpoint_unmask_outnak(k_rx_pipe);
        return (k_success);
      }
      // detecting outnak before tx means dropped ack, unless pipe is stalled.
      _nakkount = 0;
      trace0(0, bot, 11, "got the kbm_sync_outnak - dropped ack?");
      if (_ndp2_rx_stalled)
      {
        _ndp2_rx_stalled = k_no;
        trace0(0, bot, 12, "...while stall in progress...");
        return (k_success);
      }
      _tx_missed_ack = k_yes;
      trace0(0, bot, 11, "dropped ack");
      _endpoint_unmask_outnak(k_rx_pipe);
      _hpbot_thread_entry = hpbot_wait_pipe_ready_for_rx;
      return (k_success);

      // usbrst
    case k_irq_usb_stat_reset:
    case k_irq_usb_reset:
      //case k_irq_timer1: - this case is kind of a hold over from the first seat 'o the pants
      // debug session in the pre-comdex'00 days.  if the outnaks don't start coming (the only
      // reason for a timeout to occur) then the device is dead.  the host ain't pinging.
      // so you are eventually gonna either get a usbreset, or the host will drop you like
      // a cold turd.  in either case, you have already lost.
      _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);
  }
}

// length must be less than 64 bytes, and must contain the
// entire data portion of the transfer.  this code takes up
// a lot of instructions and is used for sending small bot
// data payloads for non-media data commands like mode sense
// inquiry, etc.
void mscbot_tx_data_buffer(uint8* buffer, uint8 length) reentrant
{
  uint8 pnr;

  trace1(0, bot, 0, "mscbot_tx_data_buffer() - quick sending a %d byte data response", length) ;

  pnr = mmu_allocate();
  _thread_clr_sync(kbm_sync_usbtx);
  length = _min( (uint32) length, _mscbot_residue_32());  // alloc length
  mmu_wr_pkt(k_tx_pipe, pnr, buffer, length);
  txfifo_wr(k_tx_pipe, pnr);
  _mscbot_decr_residue(length);

}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------

// length must be less than 64 bytes, and must contain the
// entire data portion of the transfer.  this code takes up
// a lot of instructions and is used for receiving small bot
// data payloads for non-media data commands like mode sense
// inquiry, etc.
//WARNING!! This fn assumes that this packet arrives at buffer B. This will work because we 
//receive our cbw only on buffer A
uint8 mscbot_rx_data_buffer(uint8* buffer, uint8 length) reentrant
{
  trace1(0, bot, 0, "mscbot_rx_data_buffer() - quick receiving a %d byte data", length) ;
  thread_clr_sync(kbm_sync_usbrx);
  _endpoint_rx_enable(k_rx_pipe);
  _buffer_rx_enable(5);
  thread_set_timer(200);
  while (!thread_got_sync(kbm_sync_usbrx))
  {
    if (thread_got_sync(kbm_sync_timer))
    {
      return (k_timeout);
    }
  }
  thread_clr_sync(kbm_sync_usbrx);
  mmu_rd_pkt(5, length, buffer);
  return (k_success);
}


//---eof------------------------------------------------------------------------

⌨️ 快捷键说明

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