📄 mscbot.c
字号:
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 + -