📄 lun.c
字号:
//+-----------------------------------------------------------------------------
// Name:
// dfa_lun_read_capacity()
//
// Declaration:
// void dfa_lun_read_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_capacity(void)reentrant
{
uint8* ptr;
uint8 i;
TRACE0(110, lun, 0, "dfa_lun_read_capacity()");
lun_dump_sense(g_active_lun);
g_tmp = _lun_data(media);
// check for no media
if (!(g_tmp & kbm_lun_media_present))
{
TRACE0(111, lun, 0, "no media present... setting command failed") ;
_lun_data(sensep) = &sense_no_media;
_thread_return_dfa(k_command_failed);
}
// check for media changed
if (g_tmp & kbm_lun_media_unknown)
{
TRACE0(112, lun, 0, "media unknown... setting media change sense") ;
_lun_data(sensep) = &sense_media_change;
_thread_return_dfa(k_command_failed);
}
// validate command parameters
//reladr = (g_bot_cbw.cdb[1] & 0x01);
//lba = _uint32(g_bot_cbw.cdb[2], g_bot_cbw.cdb[3], g_bot_cbw.cdb[4], g_bot_cbw.cdb[5]);
//pmi = (g_bot_cbw.cdb[8] & 0x01);
//if (!reladr || !pmi || lba)
//{
// _lun_data(g_active_lun, sensep) = &sense_illegal_rqst;
//}
// check for any error
if (_lun_data(sensep) != &sense_none)
{
TRACE0(113, lun, 0, "active lun sensep != sense_none. failing command") ;
lun_dump_sense(g_active_lun);
_thread_return_dfa(k_command_failed);
}
// report the data to the host
stream_open(2, k_data_in);
ptr = (uint8*) &(_lun_data(capacity));
//lba = _lun_data(g_active_lun, capacity).lba_max.u32 - 1;
for (i=0; i<8; i++)
{
while (!stream_put(2, ptr[i]));
}
_mscbot_zero_residue();
stream_close(2);
_lun_data(sensep) = &sense_none;
_thread_return_dfa(k_command_passed);
}
//+-----------------------------------------------------------------------------
// Name:
// dfa_lun_read
//
// Declaration:
// void dfa_lun_read(void);
//
// Purpose:
// Read data from an ata drive.
//
// Arguments:
// None.
// Uses _lun_data and g_bot_cbw to get its parameters.
//
// Return:
// No return value.
// However, on exit the DFA's argument pointer is written with a t_csw_status indicating:
// k_command_passed - command completed.
// k_command_failed - an error occurred.
//
// Notes:
// Should be overridden. Derived method should set callbacks, then call this.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
// BBB: the first optimization to this was to call it directly from dfa_lun_process_cb.
// that eliminated a dfa layer (55usec push, 66usec pop) and required no changes here.
// the second optimization was to call it directly from dev_thread_wait_cbw.
// that eliminated another dfa layer cutting out 240 to 270 usec in toto (as measured)
// but required a change here. all of the _thread_return_dfa() calls had to be replaced
// with __thread_return_dfa() calls to eliminate the final call to thread_end_dfa()
// (because its not run as a dfa any more, it just looks very much like one due to
// mildly clever macroitization) and replace it with a simple return.
// 07/01/02 - tbh - moved to lun.h
//#define __thread_return_dfa(__val) { (*(uint8 *)thread_rd_dfa_argp())=(__val); return; }
void dfa_lun_read(void)reentrant
{
// profile: ~46..49 usec
#if 0
TRACE0(114, lun, 0, "dfa_lun_read() - error: pure virtual method must be overridden");
_lun_data(sensep) = &sense_illegal_opcode;
__thread_return_dfa(k_command_failed);
#else
//_profile_on(7);
TRACE0(115, fmc, 0, "dfa_lun_read()");
if (_lun_data(sensep) != &sense_none)
{
TRACE1(116, fmc, 0, "sensep: %04x", ((uint16) _lun_data(sensep))); // use lun_dump_sense()
__thread_return_dfa(k_command_failed);
}
_fmc_set_start_lb_8(g_bot_cbw.cdb[2], g_bot_cbw.cdb[3], g_bot_cbw.cdb[4], g_bot_cbw.cdb[5]);
// do you trust the host enough to sacrifice robustness for speed here? are you sure?
#ifndef k_optimizeXXX
// valid lba range - required if host just wants to validate a range of addresses w/o a data xfer
if (_fmc_get_start_lb_32() > _lun_data(capacity).lba_max.u32)
{
TRACE2(117, fmc, 0, "dfa_lun_read() - error bad lba:%04X%04X", (_fmc_get_start_lb_32() >> 16), (_fmc_get_start_lb_32() & 0xffff));
_lun_data(sensep) = &sense_illegal_address;
__thread_return_dfa(k_command_failed);
}
#endif
if (g_bot_cbw.cdb[0] == k_protocol_read_10)
{
TRACE0(118, fmc, 1, "read_10 command");
_fmc_set_lb_count_8(0, 0, g_bot_cbw.cdb[7], g_bot_cbw.cdb[8]);
}
else
{
TRACE0(119, fmc, 1, "read 12 command");
_fmc_set_lb_count_8(g_bot_cbw.cdb[6], g_bot_cbw.cdb[7], g_bot_cbw.cdb[8], g_bot_cbw.cdb[9]);
}
TRACE4(120, fmc, 0, "read lba:%04X%04X xfer_length:%04X%04X", _hw(_fmc_get_start_lb_32()), _lw(_fmc_get_start_lb_32()), _hw(g_n_lb_this_xfer.u32), _lw(g_n_lb_this_xfer.u32));
// do you trust the host enough to sacrifice robustness for speed here? are you sure?
#ifndef k_optimizeXXX
if ((_fmc_get_start_lb_32() + _fmc_get_lb_count_32() - 1L) > _lun_data(capacity).lba_max.u32)
{
TRACE0(121, fmc, 0, "dfa_lun_read() - lba range invalid\n");
TRACE2(122, fmc, 0, "dfa_lun_read() - error bad start:%04X%04X", (_fmc_get_start_lb_32() >> 16), (_fmc_get_start_lb_32() & 0xffff));
TRACE2(123, fmc, 0, "dfa_lun_read() - error bad count:%04X%04X", (_fmc_get_lb_count_32() >> 16), (_fmc_get_lb_count_32() & 0xffff));
TRACE2(124, fmc, 0, "dfa_lun_read() - capacity:%04X%04X", (_lun_data(capacity).lba_max.u32 >> 16), (_lun_data(capacity).lba_max.u32 & 0xffff));
_lun_data(sensep) = &sense_illegal_address;
__thread_return_dfa(k_command_failed);
}
#endif
//_profile_off(7); //ABOUT 46 usec
if (k_success != fmc_transfer())
__thread_return_dfa(k_command_failed);
if (_lun_data(sensep) != &sense_none)
__thread_return_dfa(k_command_failed);
__thread_return_dfa(k_command_passed);
#endif
}
//+-----------------------------------------------------------------------------
// Name:
// dfa_lun_write
//
// Declaration:
// void dfa_lun_write(void);
//
// Purpose:
// Write data.
//
// Arguments:
// None.
// Uses _lun_data and g_bot_cbw to get its parameters.
//
// Return:
// No return value.
// However, on exit the DFA's argument pointer is written with a t_csw_status indicating:
// k_command_passed - command completed.
// k_command_failed - an error occurred.
//
// Notes:
// Should be overridden. Derived method should set callbacks, then call this.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
// BBB: the first optimization to this was to cal it directly from dfa_lun_process_cb.
// that eliminated a dfa layer (55usec push, 66usec pop) and required no changes here.
// the second optimization was to call it directly from dev_thread_wait_cbw.
// that eliminated another dfa layer cutting out 240 to 270 usec in toto (as measured)
// but required a change here. all of the _thread_return_dfa() calls had to be replaced
// with __thread_return_dfa() calls to eliminate the final call to thread_end_dfa()
// (because its not run as a dfa any more, it just looks very much like one due to
// mildly clever macroitization) and replace it with a simple return.
void dfa_lun_write(void)reentrant
{
#if 0
TRACE0(125, lun, 0, "dfa_lun_write() - error: pure virtual method must be overridden");
_lun_data(sensep) = &sense_illegal_opcode;
__thread_return_dfa(k_command_failed);
#else
TRACE0(126, lun, 0, "dfa_lun_write");
if (_lun_data(media) & kbm_lun_media_wrprot)
{
TRACE0(127, lun, 10, "write protected");
_lun_data(sensep) = &sense_write_protect;
__thread_return_dfa(k_command_failed);
}
if (_lun_data(sensep) != &sense_none)
{
__thread_return_dfa(k_command_failed);
}
_fmc_set_start_lb_8(g_bot_cbw.cdb[2], g_bot_cbw.cdb[3], g_bot_cbw.cdb[4], g_bot_cbw.cdb[5]);
// do you trust the host enough to sacrifice robustness for speed here? are you sure?
#ifndef k_optimizeXXX
if (_fmc_get_start_lb_32() > _lun_data(capacity).lba_max.u32)
{
TRACE2(128, fmc, 0, "dfa_lun_write() - error bad lba:%04X%04X", (_fmc_get_start_lb_32() >> 16), (_fmc_get_start_lb_32() & 0xffff));
_lun_data(sensep) = &sense_illegal_address;
__thread_return_dfa(k_command_failed);
}
#endif
if (g_bot_cbw.cdb[0] == k_protocol_write_10)
{
TRACE0(129, fmc, 1, "write 10 command");
_fmc_set_lb_count_8(0, 0, g_bot_cbw.cdb[7], g_bot_cbw.cdb[8]);
}
else
{
TRACE0(130, fmc, 1, "write 12 command");
_fmc_set_lb_count_8(g_bot_cbw.cdb[6], g_bot_cbw.cdb[7], g_bot_cbw.cdb[8], g_bot_cbw.cdb[9]);
}
TRACE4(131, fmc, 0, "write lba:%04X%04X xfer_length:%04X%04X", _hw(_fmc_get_start_lb_32()), _lw(_fmc_get_start_lb_32()), _hw(g_n_lb_this_xfer.u32), _lw(g_n_lb_this_xfer.u32));
// do you trust the host enough to sacrifice robustness for speed here? are you sure?
#ifndef k_optimizeXXX
if ((_fmc_get_start_lb_32() + _fmc_get_lb_count_32() - 1L) > _lun_data(capacity).lba_max.u32)
{
TRACE0(132, fmc, 0, "dfa_lun_write() - lba range invalid\n");
_lun_data(sensep) = &sense_illegal_address;
__thread_return_dfa(k_command_failed);
}
#endif
if (k_success != fmc_transfer())
__thread_return_dfa(k_command_failed);
if (_lun_data(sensep) != &sense_none)
__thread_return_dfa(k_command_failed);
__thread_return_dfa(k_command_passed);
#endif
}
//------------------------------------------------------------------------------
// verify options
#define kbm_verify_options_dpo 0x04
#define kbm_verify_options_bytchk 0x02
#define kbm_verify_options_reladr 0x01
//+-----------------------------------------------------------------------------
// Name:
// dfa_lun_verify
//
// Declaration:
// void dfa_lun_verify(void);
//
// Purpose:
// Verify that the data on the drive matches the data sent down.
//
// Arguments:
// None.
// Uses _lun_data and g_bot_cbw to get its parameters.
//
// Return:
// No return value.
// However, on exit the DFA's argument pointer is written with a t_csw_status indicating:
// k_command_passed - command completed.
// k_command_failed - an error occurred.
//
// Notes:
// !!!???This implementation is incorrect. It should not write the data to the drive,
// but should read the drive and compare to the provided data???
// Should be overridden. Derived method should set callbacks, then call this.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
void dfa_lun_verify(void)reentrant
{
#if 0
TRACE0(133, lun, 0, "dfa_lun_verify() - error: pure virtual method must be overridden");
_lun_data(sensep) = &sense_illegal_opcode;
_thread_return_dfa(k_command_failed);
#else
uint8 vopt;
TRACE0(134, fmc, 0, "dfa_lun_verify");
if (_lun_data(sensep) != &sense_none)
{
_thread_return_dfa(k_command_failed);
}
vopt = g_bot_cbw.cdb[1];
_fmc_get_start_lb_8(g_bot_cbw.cdb[2], g_bot_cbw.cdb[3], g_bot_cbw.cdb[4], g_bot_cbw.cdb[5]);
// valid lba range - required if host just wants to validate a range of addresses w/o a data xfer
if (_fmc_get_start_lb_32() > _lun_data(capacity).lba_max.u32)
{
TRACE0(135, fmc, 0, "verify error: invalid lba");
_lun_data(sensep) = &sense_illegal_address;
_thread_return_dfa(k_command_failed);
}
_fmc_set_lb_count_8(0, 0, g_bot_cbw.cdb[7], g_bot_cbw.cdb[8]);
if ((_fmc_get_start_lb_32() + _fmc_get_lb_count_32() - 1L) > _lun_data(capacity).lba_max.u32)
{
TRACE0(136, fmc, 0, "verify error: lba range invalid\n");
_lun_data(sensep) = &sense_illegal_address;
_thread_return_dfa(k_command_failed);
}
// check to see if there is any data transfer
if (!(vopt & kbm_verify_options_bytchk))
{
// no data comparrison, so just return a-ok.
TRACE0(137, fmc, 0, "verify: no data comparison... just say ok\n");
_lun_data(sensep) = &sense_none;
_thread_return_dfa(k_command_passed);
}
TRACE4(138, fmc, 0, "verify lba:%04X%04X xfer_length:%04X%04X", _hw(_fmc_get_start_lb_32()), _lw(_fmc_get_start_lb_32()), _hw(g_n_lb_this_xfer.u32), _lw(g_n_lb_this_xfer.u32));
TRACE4(139, fmc, 0, "verify - opts:0x%02X vlba:%04X%04X vlen:%04X", vopt, _hw(_fmc_get_start_lb_32()), _lw(_fmc_get_start_lb_32()), g_n_lb_this_xfer.u32);
if (k_success != fmc_transfer())
_thread_return_dfa(k_command_failed);
if (_lun_data(sensep) != &sense_none)
_thread_return_dfa(k_command_failed);
_thread_return_dfa(k_command_passed);
#endif
}
//+-----------------------------------------------------------------------------
// Name:
// dfa_lun_mode_sense()
//
// Declaration:
// void dfa_lun_mode_sense(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
//------------------------------------------------------------------------------
// spc3r07 8.4 - 4 bytes of header: mode-data-length, medium-type, device-parm, block-len
uint8 code _msense[4] = { 0x03, 0x00, 0x00, 0x00};
uint8 code _msense_wp[4] = { 0x03, 0x00, 0x80, 0x00};
uint8 code _msense10[8] = { 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8 code _msense10_wp[8] = { 0x00, 0x06, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00};
void dfa_lun_mode_sense(void) reentrant
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -