mscbot.c

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

C
1,068
字号
   rqstp = (t_usb_rqst *)message_rd_arg(msgp);
   switch (message_rd_id(msgp))
   {
      // standard requests
      case k_dsi_usb_get_status:
         trace0(0, nil, 0, "RQ_GET_STATUS: interface");
         // interface status is always 0 per usb spec
         g_wtmp = 0;
         // tell the data pump where to find it and how much there is
         _payload_source(&g_wtmp, 2);
         return(k_success);

      case k_hsi_usb_clr_feature:
         trace0(0, nil, 0, "RQ_CLEAR_FEATURE: interface?");
         // this is always an error per the usb spec
         return(k_error);

      case k_hsi_usb_set_feature:
         trace0(0, nil, 0, "RQ_SET_FEATURE: interface?");
         // this is always an error per the usb spec
         return(k_error);

      case k_dsi_usb_get_interface:
         trace0(0, nil, 0, "RQ_GET_INTERFACE");
         // this interface has no alternate settings
         g_tmp = 0;
         // tell the data pump where to find it and how much there is
         _payload_source(&g_tmp, 1);
         return(k_success);

      case k_hsi_usb_set_interface:
         trace0(0, bot, 0, "RQ_SET_INTERFACE");
         // this interface has no alternate settings, only 0 as a selection
         if (rqstp->wValueLo)
            return(k_error);
         return(k_success);

         // class specific requests
      case k_hci_mscbot_reset:
         // perform the class specific soft reset
         trace0(0, bot, 0, "RQ k_hci_mscbot_reset");
         //According to the spec the Bulk pipe must be set ready for the next OUT token.
         //So,all pending buffers that are queued to be transmitted should be cleared. 
          //dev_thread_wait_create();
        // fgnd_hpbot_wait_create();
         return(k_success);

      case k_hci_mscbot_getmaxlun:
         trace0(0, bot, 0, "RQ k_hci_mscbot_getmaxlun");
         g_tmp = g_max_dyn_lun-1;
         trace1(0, bot, 0, "  maxlun:%d)", g_tmp);
         // tell the data pump where to find it and how much there is
         _payload_source(&g_tmp, 1);
         return(k_success);

#ifdef k_opt_dfu


         // dfu class specific message - must be intercepted here has a hack
         // since the chip only has one physical interface so there cannot be
         // a dangling dfu interface
      case k_hci_dfu_detach:
         trace0(0, dfu, 0, "mscbot_cpex intercepting: k_hci_dfu_detach");
         return(dfu_cpex(msgp));
#endif

#ifdef k_opt_dfu
      case k_msg_transaction_done:
         trace0(0, dfu, 0, "mscbot_cpex routing k_msg_transaction_done to dfu_cpex");
         return(dfu_cpex(msgp));
#endif



         // os messages
      case k_msg_source_payload:
         // load some application specific data into a packet buffer
         // return k_in_progress if app expects to supply at least one more packet's worth of data
         // return k_finished otherwise
         pnr = *(uint8 *)message_rd_arg(msgp);
         pktsz = _min(g_data_len, k_maxpktsz);
         g_data_len -= pktsz;
         mmu_wr_pkt(0, pnr, g_source_addr, pktsz);
         g_source_addr += pktsz;
         return(g_data_len ? k_in_progress : k_finished);

      case k_msg_sink_payload:
         // unload data from a packet buffer and do something application specific with it
         // return k_in_progress if app can process this request
         // return k_finished otherwise
         pnr = *(uint8 *)message_rd_arg(msgp);
         pktsz = _min(g_data_len, k_maxpktsz);
         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_(); }


//------------------------------------------------------------------------------
// 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();

⌨️ 快捷键说明

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