📄 ata.c
字号:
_thread_clr_sync(kbm_sync_ata_rdy);
trace1(0, ata, 0, "-- after _lun_data:0x%02X", x_imr0);
#ifdef k_mcu_97201
// setup IDE timing register - compatible PIO, fast time for non-udma dma only
_mcu_register_clr_bits(x_ide_tim, kbm_ide_tim_dte); //clear bit 3 dte so both MWDMA and PIO transfers use fast timing mode
_mcu_register_set_bits(x_ide_tim, (kbm_ide_tim_ftb |k_ide_iordy_3clocks |k_ide_recover_1clocks));
#endif
// check for diagnostic results
error = ata_register_rd(&ata_error);
switch (error)
{
case 0x00:
trace0(0, ata, 0, "ata_initialize_media2() - error: no unit found");
break;
case 0x01:
trace0(0, ata, 0, "ata_initialize_media2() - DEV0 Passed, DEV1 Passed/Not Present");
break;
case 0x81:
trace0(0, ata, 0, "ata_initialize_media2() - DEV0 Passed, DEV1 Failed");
break;
default:
trace1(0, ata, 0, "ata_initialize_media2() - error: diagnostic:0x%02X", error);
break;
}
// check for a signature telling us what type of device we have
sector_cnt = ata_register_rd(&ata_sector_cnt);
sector_num = ata_register_rd(&ata_sector_num);
cylinder_lo = ata_register_rd(&ata_cylinder_lo);
cylinder_hi = ata_register_rd(&ata_cylinder_hi);
trace4(0, ata, 0, "dev signature: sc:0x%02X sn:0x%02X cl:0x%02X sh:0x%02X", sector_cnt, sector_num, cylinder_lo, cylinder_hi);
// check for ATA
if (sector_cnt == 0x01 && sector_num == 0x01 && cylinder_lo == 0x00 && cylinder_hi == 0x00)
{
trace0(0, ata, 0, "ata_initialize_media2() - lun is ATA");
_lun_data_wr(k_lun_ata, media, (_lun_data_rd(k_lun_ata, media)&~kbm_lun_media_changed));
// m'kay - here is the biggest optimization yet...
// use pio mode 4 instead of the default mode 0 and viola...
// 1.1R:960K 1.1W:923K 2.0R:5.57M 2.0W:3.37M
// it is safe to or in the mode bits ONLY because this is after POR and the por value is 0
// if it was done elsewhere it would need to be
// $$$ cds -> 4 not working for some devices... set it to 0 until media is identified
// 0x07 is the mask that covers all modes
// _mcu_register_clr_bits(x_cfc_ata_mode_ctl, k_cfc_ata_mode_4);
_thread_return_dfa(k_success);
}
trace0(0, ata, 0, "ata_initialize_media2() - error: bad signature - cannot identify device");
_thread_return_dfa(k_error);
}
dev_exception(k_err_unreachable_code+11);
}
//+-----------------------------------------------------------------------------
// Name:
// dfa_ata_initialize_media
//
// Declaration:
// void dfa_ata_initialize_media(void);
//
// Purpose:
// Setup to detect the BSY bit clearing, then yield hoping to initialize the ata drive.
//
// Arguments:
// None.
//
// Return:
// No return value.
// However, on exit the DFA's argument pointer is written with a t_result indicating:
// k_success - command completed.
// 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.
// (This allows the caller to see the return value, via the argp, after the DFA terminates).
//
// Notes:
// This is the start STATE of the dfa_ata_initialize_media DFA.
// It overrides dfa_lun_initialize.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
void dfa_ata_initialize_media() reentrant
{
trace0(0, ata, 1, "dfa_ata_initialize_media()");
//read status to clear a pending irq, and to reset isr&imr 0
ata_read_status();
thread_set_poller((t_thd_entry)ata_poll_status_not_busy);
thread_yield_ex(kbm_sync_none, kbm_sync_ata_rdy, ata_initialize_media2);
}
//+-----------------------------------------------------------------------------
// Name:
// ata_read_end_xfer
//
// Declaration:
// t_result ata_read_end_xfer(void);
//
// Purpose:
// Wait until the drive is not busy.
//
// 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_read_end_xfer(void) reentrant;
t_result ata_read_end_xfer() reentrant
{
t_result rslt;
uint8 status;
trace0(0, ata, 1, "ata_read_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");
if (k_success != _fmc_get_result())
return _fmc_get_result();
status = ata_read_status();
if (status & kbm_ata_status_err)
return k_error;
if (status & (kbm_ata_status_bsy |kbm_ata_status_drq))
if (k_success != (rslt = ata_wait_status_with_timeout(kbm_ata_status_bsy |kbm_ata_status_drq, 0, 5000, NULL)))
return rslt;
return k_success;
}
//+-----------------------------------------------------------------------------
// Name:
// ata_read_begin_split
//
// Declaration:
// t_result ata_read_begin_split(void);
//
// Purpose:
// Issue the read 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_read_begin_split(void) reentrant;
t_result ata_read_begin_split() reentrant
{
t_udw32 start_lb;
t_udw32 lb_count;
trace0(0, ata, 1, "ata_read_begin_split()");
_stack_check();
_fmc_set_options(0);
_fmc_set_timeout(10000);
start_lb.u32 = _fmc_get_start_lb_32();
lb_count.u32 = _fmc_get_lb_count_32();
// clear any stale ata irq
ata_read_status();
_ata_register_wr(&ata_device_head,
(kbm_ata_dev_lba|
(start_lb.u8.hi & kbm_msk_ata_dev_lba_hi)));
_ata_register_wr(&ata_cylinder_hi, start_lb.u8.lh);
_ata_register_wr(&ata_cylinder_lo, start_lb.u8.hl);
_ata_register_wr(&ata_sector_num, start_lb.u8.lo);
_ata_register_wr(&ata_sector_cnt, lb_count.u8.lo);
_ata_register_wr(&ata_command, k_ata_command_read_sectors);
return k_success;
}
//+-----------------------------------------------------------------------------
// Name:
// ata_read_begin_burst
//
// Declaration:
// t_result ata_read_begin_burst(void);
//
// Purpose:
// Issue the read command to the ata drive.
//
// 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_read_begin_burst(void) reentrant;
t_result ata_read_begin_burst() reentrant
{
uint8 status;
t_result rslt;
trace0(0, ata, 1, "ata_read_begin_burst()");
_stack_check();
// wait for the drive to interrupt
// NOTE: this 'optimization' seems to slow it down
//rslt = k_success;
//if (!_thread_got_sync(kbm_sync_ata_irq))
// it takes about 250 usec minimum to get the interrupt...
// on the 24x lexar 256mb card (the fastest yet seen)
if (k_success != (rslt = ata_wait_irq_with_timeout(5000)))
return rslt;
// NOTE: this optimization speeds it up
status = ata_read_status();
if (status & kbm_ata_status_err)
return k_error;
if (status & kbm_ata_status_drq != kbm_ata_status_drq)
// 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, &status);
if (k_error == rslt)
{
// error... put in the appropriate sense code
trace0(0, ata, 0, "sense_read_error");
_lun_data_wr(k_lun_ata, sensep, &sense_read_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_read_end_burst
//
// Declaration:
// t_result ata_read_end_burst(void);
//
// Purpose:
// Issue the read command to the ata drive.
//
// Arguments:
// None.
//
// Return:
// k_success - ready to transfer data.
//
// 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_read_end_burst(void) reentrant;
t_result ata_read_end_burst() reentrant
{
t_result rslt;
trace0(0, ata, 0, "ata_read_end_burst()");
// 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");
_stack_check();
_mcu_register_clr_bits(x_cfc_ata_mode_ctl, kbm_cfc_ata_mode_ctl_mult_emu_en);
// 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;
}
//+-----------------------------------------------------------------------------
// Name:
// dfa_ata_read
//
// Declaration:
// void dfa_ata_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.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -