mscbot.c

来自「U盘控制器USB97C223的固件代码,对2kPAGE NAND FLASH 有」· C语言 代码 · 共 1,068 行 · 第 1/4 页

C
1,068
字号
         // 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))
            {
               trace1(0, bot, 0, "enter:sfr[D9]:%02x (x_imr_nak)", x_imr_nak);
               trace1(0, bot, 0, "sfr[80]:%02x (x_isr0)", x_isr0) ;
               // 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
         dev_turn_off_activity_indicator();
      }
      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);
			dev_common_media_led_on();
            break;
         case k_lun_ms:
            trace0(0, dev, 66, "MS LED ON!");
            _mcu_register_set_bits(x_gpiob_out,  kbm_gpio12);
			dev_common_media_led_on();
            break;
         case k_lun_sm:
            trace0(0, dev, 66, "SM LED ON!");
            _mcu_register_set_bits(x_gpiob_out,  kbm_gpio14);
			dev_common_media_led_on();
            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);
			dev_common_media_led_on();
            }
            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);
			dev_common_media_led_on();
            }
            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 + =
减小字号Ctrl + -
显示快捷键?