📄 lun.c
字号:
// uint8 pnr;
uint8 cmd = g_bot_cbw.cdb[0];
TRACE0(140, lun, 0, "dfa_lun_mode_sense()");
if ( cmd == k_protocol_mode_sense_10)
{
if (_lun_data(media)&kbm_lun_media_wrprot)
{
TRACE0(141, lun, 10, "write protected");
mscbot_tx_data_buffer((uint8*) _msense10_wp, sizeof(_msense10_wp));
}
else
{
mscbot_tx_data_buffer((uint8*) _msense10, sizeof(_msense10));
}
}
else
{
if (_lun_data(media) & kbm_lun_media_wrprot)
{
TRACE0(142, lun, 10, "write protected");
mscbot_tx_data_buffer((uint8*) _msense_wp, sizeof(_msense_wp));
}
else
{
mscbot_tx_data_buffer((uint8*) _msense, sizeof(_msense));
}
}
_thread_return_dfa(k_command_passed);
}
//+-----------------------------------------------------------------------------
// Name:
// dfa_lun_mode_select()
//
// Declaration:
// void dfa_lun_mode_select(void) reentrant ;
//
// Purpose:
//
// Arguments:
//
// Return:
//
// Notes:
// - This is a dfa.
// - Should not need to be overridden. This function will automatically use
// lun instance data to respond to the host.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
void dfa_lun_mode_select(void)reentrant
{
uint8 dummy;
TRACE0(143, lun, 0, "dfa_lun_mode_select()");
// must consume all data coming from host... throw away
stream_open(k_rx_pipe, k_data_out);
while (_mscbot_has_residue())
{
_mscbot_decr_residue(stream_get(k_rx_pipe, &dummy));
}
stream_close(k_rx_pipe);
_lun_data(sensep) = &sense_illegal_opcode;
_thread_return_dfa(k_command_failed);
}
//+-----------------------------------------------------------------------------
// Name:
// dfa_lun_read_format_capacity()
//
// Declaration:
// void dfa_lun_read_format_capacity(void) reentrant ;
//
// Purpose:
//
// Arguments:
//
// Return:
//
// Notes:
// - This is a dfa.
// - Should not need to be overridden. This function will automatically use
// lun instance data to respond to the host.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
void dfa_lun_read_format_capacity(void)reentrant
{
t_uw16 alloc_length ;
TRACE0(144, lun, 0, "dfa_lun_read_format_capacity() - virtual method - may be overridden");
alloc_length.u16 = (((t_scsi_cb*) &g_bot_cbw.cdb[0])->param.read_format_capacity.allocation_len) ;
TRACE1(145, lun, 0, "rd_fmt_cap alloc_length = %d bytes", alloc_length.u16) ;
if ( _u16_equ_0(alloc_length) )
{
_lun_data(sensep) = &sense_none ;
_thread_return_dfa(k_command_passed) ;
}
stream_open(2, k_data_in);
if ( alloc_length.u16 >= 0x0004 )
{
// write list header - 8 bytes to follow
stream_put(2, 0);
stream_put(2, 0);
stream_put(2, 0);
stream_put(2, 8);
_mscbot_decr_residue(4);
if ( alloc_length.u16 >= 0x000c )
{
TRACE2(146, lun, 0, "read format capacity max lba:%04X%04X", _hw(_lun_data(capacity.lba_max.u32)), _lw(_lun_data(capacity.lba_max.u32)));
stream_put(2, _lun_data(capacity.lba_max.u8.hi )) ;
stream_put(2, _lun_data(capacity.lba_max.u8.lh )) ;
stream_put(2, _lun_data(capacity.lba_max.u8.hl )) ;
stream_put(2, _lun_data(capacity.lba_max.u8.lo )) ;
TRACE2(147, lun, 0, "read format capacity lba size:%04X%04X", _hw(_lun_data(capacity.lba_sz.u32)), _lw(_lun_data(capacity.lba_sz.u32)));
stream_put(2, _lun_data(capacity.lba_sz.u8.hi)) ;
stream_put(2, _lun_data(capacity.lba_sz.u8.lh)) ;
stream_put(2, _lun_data(capacity.lba_sz.u8.hl)) ;
stream_put(2, _lun_data(capacity.lba_sz.u8.lo)) ;
_mscbot_decr_residue(8) ;
}
}
else
{
stream_flush(2) ;
stream_close(2) ;
_lun_data(sensep) = &sense_illegal_length ;
_thread_return_dfa(k_command_failed) ;
}
if (_mscbot_has_residue())
{
// only flush if we have residue... otherwise, we could accidentally zlp the CSW transaction
stream_flush(2);
}
stream_close(2);
_lun_data(sensep) = &sense_none;
_thread_return_dfa(k_command_passed) ;
}
//+-----------------------------------------------------------------------------
// Name:
// dfa_lun_format_unit()
//
// Declaration:
// void dfa_lun_format_unit(void) reentrant ;
//
// Purpose:
//
// Arguments:
//
// Return:
//
// Notes:
// - This is a dfa.
// - Should not need to be overridden. This function will automatically use
// lun instance data to respond to the host.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
void dfa_lun_format_unit(void)reentrant
{
TRACE0(148, lun, 0, "dfa_lun_format_unit() - error: pure virtual method must be overridden");
_lun_data(sensep) = &sense_illegal_opcode;
_thread_return_dfa(k_command_failed);
}
//+-----------------------------------------------------------------------------
// Name:
// dfa_lun_start_stop_unit()
//
// Declaration:
// void dfa_lun_start_stop_unit(void) reentrant ;
//
// Purpose:
//
// Arguments:
//
// Return:
//
// Notes:
// - This is a dfa.
// - Should not need to be overridden. This function will automatically use
// lun instance data to respond to the host.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
void dfa_lun_start_stop_unit(void)reentrant
{
t_bool immed ;
uint8 action ;
uint8 pc ;
t_result result ;
TRACE0(149, lun, 0, "dfa_lun_start_stop_unit()") ;
immed = (((t_scsi_cb*) &g_bot_cbw.cdb[0])->param.start_stop_unit.opts & kbm_scsi_ssu_msk_immed)?k_true:k_false;
pc = (((t_scsi_cb*) &g_bot_cbw.cdb[0])->param.start_stop_unit.pc_action & kbm_scsi_ssu_msk_pc) ;
action= (((t_scsi_cb*) &g_bot_cbw.cdb[0])->param.start_stop_unit.pc_action & kbm_scsi_ssu_msk_action) ;
_lun_data(sensep) = &sense_illegal_request;
result = k_error ;
TRACE1(150, lun, 0, " start-stop immediate: %d", immed) ;
switch (pc)
{
case k_scsi_ssu_pc_nc :
TRACE0(151, lun, 3, "No change in power control") ;
break;
case k_scsi_ssu_pc_active :
TRACE0(152, lun, 3, "Device -> ACTIVE") ;
break;
case k_scsi_ssu_pc_idle :
TRACE0(153, lun, 3, "Device -> IDLE") ;
break;
case k_scsi_ssu_pc_standby :
TRACE0(154, lun, 3, "Device -> STANDBY") ;
break;
case k_scsi_ssu_pc_sleep :
TRACE0(155, lun, 3, "Device -> SLEEP") ;
break;
case k_scsi_ssu_pc_dev_ctl :
TRACE0(156, lun, 3, "Xfer Power Control to Device") ;
break;
case k_scsi_ssu_pc_idle_cdm_0 :
TRACE0(157, lun, 3, "Force Device IDLE Timer to 0") ;
break ;
case k_scsi_ssu_pc_standby_cdm_0 :
TRACE0(158, lun, 3, "Force Device STANDBY Timer to 0") ;
break;
default:
TRACE1(159, lun, 0, "reserved power control code - %02X", pc) ;
break;
}
TRACE1(160, lun, 0, "action:%02x", action) ;
switch (action)
{
case kbm_scsi_ssu_action_stop:
TRACE0(161, lun, 3, "Stop Device") ;
_lun_data(sensep) = &sense_none;
result = k_command_passed ;
break;
case kbm_scsi_ssu_action_start:
TRACE0(162, lun, 3, "Start Device") ;
if (_lun_is_media_present(g_active_lun))
{
_lun_data(sensep) = &sense_none;
result = k_command_passed ;
}
break;
case kbm_scsi_ssu_action_unload:
if (!(_lun_is_media_removable(g_active_lun)))
break;
TRACE0(163, lun, 3, "Stop & Unload Device") ;
switch (g_active_lun)
{
case k_lun_cf:
trace0(0, dev, 0, "_cf_pwr_off()") ;
_cf_pwr_off();
_ejected(k_lun_cf);
break;
case k_lun_ms:
_ms_pwr_off();
_ejected(k_lun_ms);
break;
case k_lun_sm:
_sm_pwr_off();
_ejected(k_lun_sm);
break;
case k_lun_sd:
case k_lun_mmc:
// it is desireable to power the card off here, but that
// causes an insert/eject interrupt...
irq_control(k_irq_sd_insert_eject, kbm_irqctl_clear |kbm_irqctl_mask);
trace0(0, dev, 0, "turning power off");
_sd_pwr_off();
// this seems like a long time, but its an eject from the host, so
// speed is not critical, and 25msec is long enough to "debounce"
// the power off and avoid the tedious insert/eject interrupt
thread_set_timer(25);
while (!thread_got_sync(kbm_sync_timer));
irq_control(k_irq_sd_insert_eject, kbm_irqctl_clear |kbm_irqctl_unmask);
_lun_map_log2phy(k_log_lun_sd, k_lun_sd);
// the _xx_ejected() macros clear the x_crd_ps kbm_crd_ps_sd/kbm_crd_ps_mmc bits
// which causes the new SD probing code in device.c to activate.
// thus after an eject command from the host the SD prober fires and
// reloads the media on XP and OSX. this should keep it ejected until
// it is physically removed and then re-inserted.
//_sd_ejected();
_lun_data_wr(k_lun_sd, media, _lun_data_rd(k_lun_sd, media)&~(kbm_lun_media_present|kbm_lun_media_unknown|kbm_lun_media_changed));
//_mmc_ejected();
_lun_data_wr(k_lun_mmc, media, _lun_data_rd(k_lun_mmc, media)&~(kbm_lun_media_present|kbm_lun_media_unknown|kbm_lun_media_changed));
break;
}
_lun_data(sensep) = &sense_none;
result = k_command_passed ;
break;
case kbm_scsi_ssu_action_load:
TRACE0(164, lun, 3, "Load & Start Device") ;
if (_lun_is_media_removable(g_active_lun))
break;
if (_lun_is_media_present(g_active_lun))
{
_lun_data(sensep) = &sense_none;
result = k_command_passed ;
}
else
{
_lun_data(sensep) = &sense_no_media;
}
break;
}
_thread_return_dfa(result);
}
//+-----------------------------------------------------------------------------
// Name:
// dfa_lun_prevent_allow_access()
//
// Declaration:
// void dfa_lun_prevent_allow_access(void) reentrant ;
//
// Purpose:
//
// Arguments:
//
// Return:
//
// Notes:
// - This is a dfa.
// - Should not need to be overridden. This function will automatically use
// lun instance data to respond to the host.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
void dfa_lun_prevent_allow_access(void)reentrant
{
if (g_bot_cbw.cdb[4] & 0x01)
{
TRACE0(165, lun, 0, "dfa_lun_prevent_allow_access(prevent) - warning: impossible to control with this hardware");
_lun_data(sensep) = &sense_illegal_cmdpkt;
_thread_return_dfa(k_command_failed);
}
TRACE0(166, lun, 0, "dfa_lun_prevent_allow_access(allow) - warning: impossible to control with this hardware");
_lun_data(sensep) = &sense_none;
_thread_return_dfa(k_command_passed);
}
//+-----------------------------------------------------------------------------
// Name:
// dfa_lun_sync_cache()
//
// Declaration:
// void dfa_lun_sync_cache(void) reentrant ;
//
// Purpose:
//
// Arguments:
//
// Return:
//
// Notes:
// - This is a dfa.
// - Should not need to be overridden. This function will automatically use
// lun instance data to respond to the host.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -