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 + -
显示快捷键?