📄 ata.c
字号:
//
// Notes:
// This is the start STATE of the dfa_ata_read DFA.
// It overrides dfa_lun_read.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
void dfa_ata_read(void) reentrant
{
trace0(0, ata, 0, "dfa_ata_read");
_stack_check();
_fmc_set_callback(fmc_dflt_callback, ata_read_end_xfer,
ata_read_begin_split, fmc_dflt_callback,
ata_read_begin_burst, fmc_dflt_callback, ata_read_end_burst);
_fmc_set_options(0);
dfa_lun_read();
}
//+-----------------------------------------------------------------------------
// Name:
// ata_write_end_xfer
//
// Declaration:
// t_result ata_write_end_xfer(void);
//
// Purpose:
// Turn off multiple emulation if there was an error.
//
// Arguments:
// None.
//
// Return:
// A t_result indicating:
// k_success - done.
// k_usbrst - usb reset signalling was detected while executing the command.
// k_aborted - traffic occurred on the control pipe while wexecuting the command (probably a mass storage reset).
// k_timeout - a timeout limit exceeded while executing the command.
//
// Notes:
// This is a FUNCTION, not a DFA.
// Do not yeild, or run a DFA, from within this callback.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
t_result ata_write_end_xfer(void) reentrant;
t_result ata_write_end_xfer() reentrant
{
trace0(0, ata, 1, "ata_write_end_xfer()");
_stack_check();
// turn off the multiple emulation bit
_mcu_register_clr_bits(x_cfc_ata_mode_ctl, kbm_cfc_ata_mode_ctl_mult_emu_en);
trace0(0, ata, 0, "multiple emulation off");
// check to see if the fmc xfer was aborted... if so, reset the drive and return k_aborted
if (k_success != _fmc_get_result())
{
trace0(0, ata, 0, "fmc xfer was aborted. reset the device to stop it");
ata_reset();
return _fmc_get_result();
}
return k_success;
}
//+-----------------------------------------------------------------------------
// Name:
// ata_write_begin_split
//
// Declaration:
// t_result ata_write_begin_split(void);
//
// Purpose:
// Issue the write command to the ata drive.
//
// Arguments:
// None.
//
// Return:
// A t_result indicating:
// k_success - command completed.
//
// Notes:
// This is a FUNCTION, not a DFA.
// Do not yeild, or run a DFA, from within this callback.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
t_result ata_write_begin_split(void) reentrant;
t_result ata_write_begin_split() reentrant
{
trace0(0, ata, 1, "ata_write_begin_split()");
_stack_check();
_fmc_set_options(0);
_fmc_set_timeout(10000);
// clear any stale ata irq
ata_read_status();
_ata_register_wr(&ata_device_head,
(kbm_ata_dev_lba|
(g_start_lb_this_xfer.u8.hi & kbm_msk_ata_dev_lba_hi)));
_ata_register_wr(&ata_cylinder_hi, g_start_lb_this_xfer.u8.lh);
_ata_register_wr(&ata_cylinder_lo, g_start_lb_this_xfer.u8.hl);
_ata_register_wr(&ata_sector_num, g_start_lb_this_xfer.u8.lo);
_ata_register_wr(&ata_sector_cnt, g_n_lb_this_split.u8.lo);
_ata_register_wr(&ata_command, k_ata_command_write_sectors);
return k_success;
}
//+-----------------------------------------------------------------------------
// Name:
// ata_write_begin_burst
//
// Declaration:
// t_result ata_write_begin_burst(void);
//
// Purpose:
// Wait until the drive is ready to accept the data.
//
// Arguments:
// None.
//
// Return:
// A t_result indicating:
// k_success - ready to transfer data.
// k_usbrst - usb reset signalling was detected while executing the command.
// k_aborted - traffic occurred on the control pipe while wexecuting the command (probably a mass storage reset).
// k_timeout - a timeout limit exceeded while executing the command.
//
// Notes:
// This is a FUNCTION, not a DFA.
// Do not yeild, or run a DFA, from within this callback.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
t_result ata_write_begin_burst(void) reentrant;
t_result ata_write_begin_burst() reentrant
{
t_result rslt;
trace0(0, ata, 1, "ata_write_begin_burst()");
_stack_check();
// poll the status register until the bsy bit goes inactive
rslt = ata_wait_status_with_timeout(kbm_ata_status_bsy, 0, 5000, NULL);
if (k_error == rslt)
{
// error... put in the appropriate sense code
trace0(0, ata, 0, "sense_write_error");
_lun_data(sensep) = &sense_write_error;
return k_error;
}
// some other error waiting for the drq
if (k_success != rslt)
return rslt;
// poll the status register until the drq bit goes active
rslt = ata_wait_status_with_timeout(kbm_ata_status_drq, kbm_ata_status_drq, 5000, NULL);
if (k_error == rslt)
{
// error... put in the appropriate sense code
trace0(0, ata, 0, "sense_write_error");
_lun_data(sensep) = &sense_write_error;
return k_error;
}
// some other error waiting for the drq
if (k_success != rslt)
return rslt;
// mask the isr from the cf device
_mcu_register_set_bits(x_cfc_stat_msk, kbm_cfc_stat_intrq);
// turn on the multiple emulation bit
_mcu_register_set_bits(x_cfc_ata_mode_ctl, kbm_cfc_ata_mode_ctl_mult_emu_en);
trace0(0, ata, 0, "multiple emulation on");
// got the drq
return k_success;
}
//+-----------------------------------------------------------------------------
// Name:
// ata_write_end_burst
//
// Declaration:
// t_result ata_write_end_burst(void);
//
// Purpose:
// Wait until the drive is done writing the data (flushing its buffers).
//
// Arguments:
// None.
//
// Return:
// A t_result indicating:
// k_success - done.
// k_usbrst - usb reset signalling was detected while executing the command.
// k_aborted - traffic occurred on the control pipe while wexecuting the command (probably a mass storage reset).
// k_timeout - a timeout limit exceeded while executing the command.
//
// Notes:
// This is a FUNCTION, not a DFA.
// Do not yeild, or run a DFA, from within this callback.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
t_result ata_write_end_burst(void) reentrant;
t_result ata_write_end_burst() reentrant
{
t_result rslt;
trace0(0, ata, 1, "ata_write_end_burst()");
_stack_check();
// turn off the multiple emulation bit
_mcu_register_clr_bits(x_cfc_ata_mode_ctl, kbm_cfc_ata_mode_ctl_mult_emu_en);
trace0(0, ata, 0, "multiple emulation off");
// check to see if the fmc xfer was aborted... if so, reset the drive and return k_aborted
rslt = _fmc_get_result();
if( rslt != k_success )
{
trace0(0, ata, 0, "fmc xfer was aborted. reset the device to stop it");
ata_reset();
return rslt;
}
// wait for the drive to provide the data
rslt = ata_read_status();
// poll the status register just to check for errors
rslt = ata_wait_status_with_timeout(kbm_ata_status_bsy |kbm_ata_status_drq, 0, 5000, NULL);
if (k_error == rslt)
{
// error... put in the appropriate sense code
trace0(0, ata, 0, "sense_write_error");
_lun_data(sensep) = &sense_write_error;
return k_error;
}
// some other error
if (k_success != rslt)
return rslt;
return k_success;
}
//+-----------------------------------------------------------------------------
// Name:
// dfa_ata_write
//
// Declaration:
// void dfa_ata_write(void);
//
// Purpose:
// Write data to 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:
// This is the start STATE of the dfa_ata_write DFA.
// It overrides dfa_lun_write.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
void dfa_ata_write() reentrant
{
trace0(0, ata, 0, "dfa_ata_write");
_stack_check();
_fmc_set_callback(fmc_dflt_callback, ata_write_end_xfer,
ata_write_begin_split, fmc_dflt_callback,
ata_write_begin_burst, fmc_dflt_callback, ata_write_end_burst);
_fmc_set_options(0);
dfa_lun_write();
}
//------------------------------------------------------------------------------
// verify options
#define kbm_verify_options_dpo 0x04
#define kbm_verify_options_bytchk 0x02
#define kbm_verify_options_reladr 0x01
//+-----------------------------------------------------------------------------
// Name:
// dfa_ata_verify
//
// Declaration:
// void dfa_ata_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 is the start STATE of the dfa_ata_verify DFA.
// It overrides dfa_lun_verify.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
void dfa_ata_verify() reentrant
{
trace0(0, ata, 0, "dfa_ata_verify");
_fmc_set_callback(fmc_dflt_callback, ata_write_end_xfer,
ata_write_begin_split, fmc_dflt_callback,
ata_write_begin_burst, fmc_dflt_callback, ata_write_end_burst);
dfa_lun_verify();
}
//---eof------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -