📄 ata.c
字号:
if (g_use_dma)
{
devword = iddev_word(k_ata_iddev_mwdma_mode_support);
mode_sel = (devword & kbm_ata_iddev_mwdma_mode_0_selected) ? 0 :
(devword & kbm_ata_iddev_mwdma_mode_1_selected) ? 1 :
(devword & kbm_ata_iddev_mwdma_mode_2_selected) ? 2 :
(0xff);
g_dev_max_dma_mode = (devword & kbm_ata_iddev_mwdma_mode_2_supported) ? k_dma_mode_multiword_2 :
(devword & kbm_ata_iddev_mwdma_mode_1_supported) ? k_dma_mode_multiword_1 :
(devword & kbm_ata_iddev_mwdma_mode_0_supported) ? k_dma_mode_multiword_0 :
(k_dma_mode_disabled);
if (mode_sel != 0xff)
{
trace1(0, ata, 0, "Multiword DMA Mode %d selected", mode_sel);
}
if (g_dev_max_dma_mode)
{
trace1(0, ata, 0, "Device Supports Multiword DMA up to mode %d", g_dev_max_dma_mode & 0x0f);
}
if (iddev_word(k_ata_iddev_valid_fields) & kbm_ata_iddev_valid_fields_udma_modes)
{
g_use_dma = k_true;
// Read the Ultra DMA Mode word (word 88)
devword = iddev_word(k_ata_iddev_udma_mode_support);
trace1(0, ata, 0, "Ultra DMA Mode Enabled/Supported: %04X", devword);
if (mode_sel == 0xff)
{
mode_sel = (devword & kbm_ata_iddev_udma_mode_0_selected) ? 0 :
(devword & kbm_ata_iddev_udma_mode_1_selected) ? 1 :
(devword & kbm_ata_iddev_udma_mode_2_selected) ? 2 :
(devword & kbm_ata_iddev_udma_mode_3_selected) ? 3 :
(devword & kbm_ata_iddev_udma_mode_4_selected) ? 4 :
(devword & kbm_ata_iddev_udma_mode_5_selected) ? 5 :
(0xff);
if (mode_sel != 0xff)
{
trace1(0, ata, 0, "Ultra DMA Mode %d currently selected", mode_sel);
}
}
g_dev_max_dma_mode = (devword & kbm_ata_iddev_udma_mode_5_supported) ? k_dma_mode_ultra_dma_5 :
(devword & kbm_ata_iddev_udma_mode_4_supported) ? k_dma_mode_ultra_dma_4 :
(devword & kbm_ata_iddev_udma_mode_3_supported) ? k_dma_mode_ultra_dma_3 :
(devword & kbm_ata_iddev_udma_mode_2_supported) ? k_dma_mode_ultra_dma_2 :
(devword & kbm_ata_iddev_udma_mode_1_supported) ? k_dma_mode_ultra_dma_1 :
(devword & kbm_ata_iddev_udma_mode_0_supported) ? k_dma_mode_ultra_dma_0 :
(g_dev_max_dma_mode);
trace1(0, ata, 0, "Device Supports up to Ultra DMA mode %d", g_dev_max_dma_mode & 0x0f);
}
}
#endif
// feature sets - surprisingly, identical for ata or atapi
// store local copy of device support/enabled values
g_ata_dev_cmdset_support_1 = iddev_word(k_ata_dev_cmdset_support_1);
g_ata_dev_cmdset_enabled_1 = iddev_word(k_ata_dev_cmdset_enabled_1);
g_ata_dev_cmdset_support_2 = iddev_word(k_ata_dev_cmdset_support_2);
g_ata_dev_cmdset_enabled_2 = iddev_word(k_ata_dev_cmdset_enabled_2);
g_ata_dev_cmdset_support_3 = iddev_word(k_ata_dev_cmdset_support_3);
g_ata_dev_cmdset_enabled_3 = iddev_word(k_ata_dev_cmdset_enabled_3);
// support_1 options
trace2(0, ata, 0, "command/feature set (1) support:%04X enabled:%04X", g_ata_dev_cmdset_support_1, g_ata_dev_cmdset_enabled_1);
trace2(0, ata, 0, "command/feature set (2) support:%04X enabled:%04X", g_ata_dev_cmdset_support_2, g_ata_dev_cmdset_enabled_2);
trace2(0, ata, 0, "command/feature set (3) support:%04X enabled:%04X", g_ata_dev_cmdset_support_3, g_ata_dev_cmdset_enabled_3);
trace1(0, ata, 2, "Command NOP Supported...................................%c", (g_ata_dev_cmdset_support_1&kbm_ata_iddev_cmd_nop)?'Y':'N' );
trace1(0, ata, 2, "Command READ BUFFER Supported...........................%c", (g_ata_dev_cmdset_support_1&kbm_ata_iddev_cmd_read_buffer)?'Y':'N' );
trace1(0, ata, 2, "Command WRITE BUFFER Supported..........................%c", (g_ata_dev_cmdset_support_1&kbm_ata_iddev_cmd_write_buffer)?'Y':'N' );
trace1(0, ata, 2, "Host Protected Area Supported...........................%c", (g_ata_dev_cmdset_support_1&kbm_ata_iddev_host_protected_area)?'Y':'N' );
trace1(0, ata, 2, "Command DEVICE RESET Supported..........................%c", (g_ata_dev_cmdset_support_1&kbm_ata_iddev_cmd_device_reset)?'Y':'N' );
trace1(0, ata, 2, "Command DEVICE RESET Enabled............................%c", (g_ata_dev_cmdset_enabled_1&kbm_ata_iddev_cmd_device_reset)?'Y':'N' );
trace1(0, ata, 2, "SERVICE interrupt Supported.............................%c", (g_ata_dev_cmdset_support_1&kbm_ata_iddev_service_intrpt)?'Y':'N' );
trace1(0, ata, 2, "Release interrupt Supported.............................%c", (g_ata_dev_cmdset_support_1&kbm_ata_iddev_release_intrpt)?'Y':'N' );
trace1(0, ata, 2, "write cache supported...................................%c", (g_ata_dev_cmdset_support_1&kbm_ata_iddev_cmd_write_cache)?'Y':'N' );
trace1(0, ata, 2, "Feature Set - PACKET Supported..........................%c", (g_ata_dev_cmdset_support_1&kbm_ata_iddev_fs_packet)?'Y':'N' );
trace1(0, ata, 2, "Feature Set - PACKET Supported..........................%c", (g_ata_dev_cmdset_enabled_1&kbm_ata_iddev_fs_packet)?'Y':'N' );
trace1(0, ata, 2, "Feature Set - Power Mgmt Supported......................%c", (g_ata_dev_cmdset_support_1&kbm_ata_iddev_fs_power_mgmt)?'Y':'N' );
trace1(0, ata, 2, "Feature Set - Power Mgmt Enabled........................%c", (g_ata_dev_cmdset_enabled_1&kbm_ata_iddev_fs_power_mgmt)?'Y':'N' );
trace1(0, ata, 2, "Removable Media Feature Set Supported...................%c", (g_ata_dev_cmdset_support_1&kbm_ata_iddev_fs_removable_media)?'Y':'N' );
trace1(0, ata, 2, "Security Mode Feature Set Supported.....................%c", (g_ata_dev_cmdset_support_1&kbm_ata_iddev_fs_security_mode)?'Y':'N' );
trace1(0, ata, 2, "SMART Feature Set Supported.............................%c", (g_ata_dev_cmdset_support_1&kbm_ata_iddev_fs_smart)?'Y':'N' );
// support_2 options
trace1(0, ata, 2, "Command FLUSH CACHE EXT Supported.......................%c", (g_ata_dev_cmdset_support_2&kbm_ata_iddev_cmd_flush_cache_ext)?'Y':'N' );
trace1(0, ata, 2, "Command FLUSH CACHE Supported...........................%c", (g_ata_dev_cmdset_support_2&kbm_ata_iddev_cmd_flush_cache)?'Y':'N' );
trace1(0, ata, 2, "Feature Set - Device Configuration Overlay Supported....%c", (g_ata_dev_cmdset_support_2&kbm_ata_iddev_fs_device_cfg_overlay)?'Y':'N' );
trace1(0, ata, 2, "Feature Set - 48 Bit Addressing Support.................%c", (g_ata_dev_cmdset_support_2&kbm_ata_iddev_fs_48bit_address)?'Y':'N' );
trace1(0, ata, 2, "Feature Set - Auto Acoustic Mgmt Support................%c", (g_ata_dev_cmdset_support_2&kbm_ata_iddev_fs_auto_acoustic_mgmt)?'Y':'N' );
trace1(0, ata, 2, "Command Set - Max Security Extension Supported..........%c", (g_ata_dev_cmdset_support_2&kbm_ata_iddev_cmd_set_max_security_ext)?'Y':'N' );
trace1(0, ata, 2, "Command Set - Support Set Features to spin-up after por.%c", (g_ata_dev_cmdset_support_2&kbm_ata_iddev_cfg_set_features_spinup_req_on_por)?'Y':'N' );
trace1(0, ata, 2, "Command Set - Enable Set Features to spin-up after por..%c", (g_ata_dev_cmdset_enabled_2&kbm_ata_iddev_cfg_set_features_spinup_req_on_por)?'Y':'N' );
trace1(0, ata, 2, "Feature Set - Support Powerup in Standby................%c", (g_ata_dev_cmdset_support_2&kbm_ata_iddev_fs_powerup_in_standby)?'Y':'N' );
trace1(0, ata, 2, "Feature Set - Enable Powerup in Standby.................%c", (g_ata_dev_cmdset_enabled_2&kbm_ata_iddev_fs_powerup_in_standby)?'Y':'N' );
trace1(0, ata, 2, "Feature Set - Removable Media Status Notification Supported:%c", (g_ata_dev_cmdset_support_2&kbm_ata_iddev_fs_removable_media_status_notify)?'Y':'N' );
trace1(0, ata, 2, "Feature Set - Advanced Power Management Supported.......%c", (g_ata_dev_cmdset_support_2&kbm_ata_iddev_fs_adv_power_mgmt)?'Y':'N' );
trace1(0, ata, 2, "Feature Set - CFA Supported.............................%c", (g_ata_dev_cmdset_support_2& kbm_ata_iddev_fs_cfa)?'Y':'N' );
trace1(0, ata, 2, "Command READ/WRITE DMA QUEUED Supported.................%c", (g_ata_dev_cmdset_support_2&kbm_ata_iddev_cmd_rw_dma_queued)?'Y':'N' );
trace1(0, ata, 2, "Command Download Microcode Supported....................%c", (g_ata_dev_cmdset_support_2&kbm_ata_iddev_cmd_download_microcode)?'Y':'N' );
_mcu_end_critical_section();
if (k_success != ata_wait_status_with_timeout(kbm_ata_status_bsy, 0, 5000, &status))
{
// blow all the way out of dfa_ata_initialize_media.
// back to the dev thread, which will reinit the unit and restart the mscbot dfa.
//thread_end_dfa(); //<--EXIT
return k_error;
}
if (status & kbm_ata_status_err)
{
status = ata_register_rd(&ata_error);
trace1(0, ata, 1, "ata_identify_device() - error: 0x%02X", status);
return k_error;
}
//set features
/*
trace0(0, ata, 0, "Setting the Feature ");
ata_register_wr(&ata_device_head, kbm_ata_dev_0);
ata_register_wr(&ata_sector_cnt, 0x01);
ata_register_wr(&ata_error , 0x03);
ata_register_wr(&ata_command, k_ata_command_set_features);
status= ata_read_status();
trace1(0, ata, 0, "ATA_Status = %02x",status); */
// cf always fails set pio mode cause it can only be set to 4
//return ata_set_pio_transfer_mode();
return k_success;
}
//+-----------------------------------------------------------------------------
// Name:
// dfa_ata_identify_media
//
// Declaration:
// void dfa_ata_identify_media(void);
//
// Purpose:
// Go figure out what drive/card type is plugged in.
//
// Arguments:
// None.
//
// 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 a DFA, not a FUNCTION.
// It overrides dfa_lun_identify.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
void dfa_ata_identify_media() reentrant
{
trace0(0, ata, 0, "dfa_ata_identify_media()");
if (k_success != ata_identify_device(k_ata_command_identify_device))
{
_thread_return_dfa(k_command_failed);
}
// looks like media exists
_lun_data(media) &= ~kbm_lun_media_unknown;
_lun_data(sensep) = &sense_media_change;
_thread_return_dfa(k_command_passed);
}
//+-----------------------------------------------------------------------------
// Name:
// ata_initialize_media2
//
// Declaration:
// void ata_initialize_media2(void);
//
// Purpose:
// Wait for the BSY bit to clear, then initialize the ata drive.
//
// Arguments:
// None.
//
// Return:
// No return value.
// However, 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 a STATE of the dfa_ata_initialize_media DFA.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
void ata_initialize_media2(void) reentrant;
void ata_initialize_media2() reentrant
{
uint8 error;
uint8 sector_cnt;
uint8 sector_num;
uint8 cylinder_lo;
uint8 cylinder_hi;
trace0(0, ata, 1, "ata_initialize_media2()");
trace1(0, ata, 0, "-- imr0:0x%02X", x_imr0);
if (thread_got_sync(kbm_sync_ata_rdy))
{
_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);
_lun_data_wr(k_lun_ata, media, (_lun_data_rd(k_lun_ata, media)&~kbm_lun_media_changed));
// 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");
// 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");
//DS/SBS: The line clear the bit media_changed did not exist previously, for this code path. In some cards like the Iodata Compact
//flash, we see that the ata_error register reads as 0x00, thus causing the dfa to fail. But since the above mentioned bit is not cleared,
//this causes the whole reset/intialize process to keep repeating, infinitely. Thus the other luns never get intialized and reported.
//To prevent this we go ahead and clear the bit, so that the firmware will try to do the identify_media process as well.
//We have seen that the card responds to the identify process and everything goes fine from there. This scenario happens only on a
//self-powered mode, during the plug-out /plug-in of the USB Cable. On a normal good case, we will never get to this path. But on a error
//case like this we will try to identify the media, and if it still fails the host will be notified.
_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.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -