📄 ata.c
字号:
}
//+-----------------------------------------------------------------------------
// Name:
// ata_reset
//
// Declaration:
// void ata_reset(void);
//
// Purpose:
// Perform a hard reset on the ata drive via the reset pin in the ata cable.
//
// Arguments:
// None.
//
// Return:
// None.
//
// Notes:
// This is a FUNCTION, not a DFA.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
#define kix_ata_reset_pin 0x05
void ata_reset() reentrant
{
trace0(0, ata, 0, "ata_reset()");
_mcu_register_set_bits(x_cfc_ata_mode_ctl, kbm_cfc_ata_mode_ctl_dev_rst);
thread_set_timer(1);
while (!thread_got_sync(kbm_sync_timer));
_mcu_register_clr_bits(x_cfc_ata_mode_ctl, kbm_cfc_ata_mode_ctl_dev_rst);
// spec requires at least 2msec wait here... make sure other code induces wait...
thread_set_timer(3);
while (!thread_got_sync(kbm_sync_timer));
}
//+-----------------------------------------------------------------------------
// Name:
// dfa_ata_reset_media
//
// Declaration:
// void dfa_ata_reset_media(void);
//
// Purpose:
// Perform a hard reset on the ata drive via the reset pin in the ata cable.
//
// Arguments:
// None.
//
// Return:
// None.
//
// Notes:
// This is a DFA, not a FUNCTION.
// It overrides dfa_lun_reset.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
void dfa_ata_reset_media() reentrant
{
trace0(0, ata, 0, "dfa_ata_reset_media()");
ata_reset();
_thread_return_dfa(k_success);
}
//+-----------------------------------------------------------------------------
// Name:
// ata_poll_status_not_busy
//
// Declaration:
// void ata_poll_status_not_busy(void);
//
// Purpose:
// Poll the ata status register to watch for BSY going inactive.
// When it does deliver kbm_sync_ata_rdy to the active thread.
//
// Arguments:
// None.
//
// Return:
// None.
//
// Notes:
// MinimOS installable thread poller.
// Watches for synchronizing events that don't have associated interrupts
// in situations where the thread must yield to avoid blocking other threads.
// Uninstalls itself when sync delivered to its thread.
// This is a FUNCTION, not a DFA.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
void ata_poll_status_not_busy(void) reentrant;
void ata_poll_status_not_busy() reentrant
{
trace0(0, ata, 90, "ata_poll_status_not_busy()");
if (!(ata_read_status() & kbm_ata_status_bsy))
{
thread_set_sync(g_tid, kbm_sync_ata_rdy);
thread_set_poller((t_thd_entry)NULL);
}
}
//+-----------------------------------------------------------------------------
// Name:
// ata_wait_status_with_timeout
//
// Declaration:
// t_result ata_wait_status_with_timeout(uint8 mask, uint8 val, uint16 ticks, uint8 *statusp);
//
// Purpose:
// Poll the ata status register to watch for specific bits matching specific values.
//
// Arguments:
// mask - a uint8 with 1's in the bits to be compared
// val - a uint8 representing the desired value
// ticks - a uint16 representing the timeout limit
// statusp - a pointer to a uint8, where the value of the status register is returned.
// statusp can be NULL, in which case no value is returned.
//
// Return:
// A t_result indicating:
// k_success - the ata status register logically anded with the mask equals the value.
// k_usbrst - usb reset signalling was detected while waiting.
// k_aborted - traffic occurred on the control pipe while waiting (probably a mass storage reset).
// k_timeout - timeout limit exceeded.
//
// Notes:
// This is a FUNCTION, not a DFA.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
t_result ata_wait_status_with_timeout(uint8 mask, uint8 val, uint16 ticks, uint8 *statusp) reentrant;
t_result ata_wait_status_with_timeout(uint8 mask, uint8 val, uint16 ticks, uint8 *statusp) reentrant
{
uint8 status;
t_sync sync;
trace2(0, ata, 1, "ata_wait_status_with_timeout(mask:0x%02X ticks:%d)", mask, ticks);
//_stack_check();
// do this to get kbm_sync_abort delivered of there is traffic on the control pipe
_isr_bind_dma_owner(g_tid, kbm_sync_none);
// wait until the device is no longer busy
thread_set_timer(ticks+1);
status = ata_read_status();
do
{
sync = thread_got_sync(kbm_sync_abort |kbm_sync_usbrst |kbm_sync_timer);
_thread_clr_sync(sync);
if (sync & kbm_sync_usbrst)
{
trace0(0, ata, 1, "ata_wait_status_with_timeout() - error: kbm_sync_usbrst");
return k_usbreset;
}
if (sync & kbm_sync_abort)
{
trace0(0, ata, 1, "ata_wait_status_with_timeout() - error: kbm_sync_abort");
return k_aborted;
}
if (sync & kbm_sync_timer)
{
trace0(0, ata, 1, "ata_wait_status_with_timeout() - error: hung busy");
return k_timeout;
}
status = ata_read_status();
if (status & kbm_ata_status_err)
{
status = ata_register_rd(&ata_error);
trace1(0, ata, 1, "ata_wait_status_with_timeout() - error: 0x%02X", status);
return k_error;
}
} while ((status & mask) != val);
if (statusp)
*statusp = status;
return k_success;
}
//+-----------------------------------------------------------------------------
// Name:
// ata_wait_irq_with_timeout
//
// Declaration:
// t_result ata_wait_irq_with_timeout(uint16 ticks);
//
// Purpose:
// Poll for the ata interrupt.
//
// Arguments:
// ticks - a uint16 representing the timeout limit
//
// Return:
// A t_result indicating:
// k_success - the ata interrupt occurred.
// k_usbrst - usb reset signalling was detected while waiting.
// k_aborted - traffic occurred on the control pipe while waiting (probably a mass storage reset).
// k_timeout - timeout limit exceeded.
//
// Notes:
// This is a FUNCTION, not a DFA.
//
// Since:
// fmc-1.0
//
// History:
// 06/18/02 tbh - modified ata_read_status() to leave the ata interrupt masked.
// - modified this routine to break out if ata irq bit seen via polling.
// - this cut about 270usec off the begin burst, decreasing cbw time.
//------------------------------------------------------------------------------
t_result ata_wait_irq_with_timeout(uint16 ticks) reentrant;
t_result ata_wait_irq_with_timeout(uint16 ticks) reentrant
{
t_sync sync;
trace1(0, ata, 1, "ata_wait_irq_with_timeout(ticks:%d)", ticks);
//_stack_check();
// do this to get kbm_sync_abort delivered of there is traffic on the control pipe
_isr_bind_dma_owner(g_tid, kbm_sync_none);
thread_set_timer(ticks+1);
do
{
sync = thread_got_sync(kbm_sync_abort |kbm_sync_usbrst |kbm_sync_timer |kbm_sync_ata_irq);
_thread_clr_sync(sync);
if (sync & kbm_sync_usbrst)
{
trace0(0, ata, 1, "ata_wait_irq_with_timeout() - error: kbm_sync_usbrst");
return k_usbreset;
}
if (sync & kbm_sync_abort)
{
trace0(0, ata, 1, "ata_wait_irq_with_timeout() - error: kbm_sync_abort");
return k_aborted;
}
if (sync & kbm_sync_timer)
{
trace0(0, ata, 1, "ata_wait_irq_with_timeout() - error: timeout awaiting irq");
return k_timeout;
}
if (_mcu_register_rd(x_isr0) & kbm_isr0_ata_irq) break;
} while (!(sync & kbm_sync_ata_irq));
trace0(0, ata, 1, "ata_wait_irq_with_timeout() - got the ata irq");
return k_success;
}
extern xdata uint8 g_sector_buffer[];
//+-----------------------------------------------------------------------------
// Name:
// iddev_word
//
// Declaration:
// static uint16 iddev_word(uint16 word_offset);
//
// Purpose:
// Build a 16 bit word by extracting 2 bytee from pnr 4 at the specified offset.
//
// Arguments:
// word_offset - a uint16 specifying the offset into pnr 4 to get the result from.
//
// Return:
// A uint16 containing the 2 bytes extracted from pnr 4.
//
// Notes:
// This is a FUNCTION, not a DFA.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
static uint16 iddev_word(uint16 word_offset) reentrant;
static uint16 iddev_word(uint16 word_offset) reentrant
{
uint16 byte_offset;
t_uw16 word;
byte_offset = 2 * word_offset;
#if 0
_mcu_register_wr(x_sram_addr_lo, k_pkt_addrlo[4] + _l(byte_offset));
_mcu_register_wr(x_sram_addr_hi, k_pkt_addrhi[4] + _h(byte_offset));
word.u8.lo = _mcu_register_rd(x_sram_data);
word.u8.hi = _mcu_register_rd(x_sram_data);
#else
word.u8.lo = g_sector_buffer[byte_offset++];
word.u8.hi = g_sector_buffer[byte_offset];
#endif
return word.u16;
}
//+-----------------------------------------------------------------------------
// Name:
// ata_identify_device
//
// Declaration:
// void ata_identify_device(uint8 cmd);
//
// Purpose:
// Poll the ata status register to watch for specific bits matching specific values.
//
// Arguments:
// cmd - a uint8 representing the "identify" command to issue to the drive.
//
// Return:
// A t_result indicating:
// k_success - device successfully identified.
// k_error - device failed to identify in a potentially recoverable way.
// OR
// No return - dfa ends on unrecoverable error.
//
// Notes:
// This is a FUNCTION, not a DFA, but must be called from within a DFA.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
t_result ata_identify_device(uint8 cmd) reentrant
{
uint8 status;
t_result result;
#if 0
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -