📄 ata.c
字号:
device->no_reconnect_timeout = false; access_finished( bus, device ); return; } } start_dma( device, qrequest ); } else { if( qrequest->is_write ) { xpt->schedule_dpc( bus->xpt_cookie, bus->irq_dpc, ide_dpc, bus ); } } return; err_setup: abort_dma( device, qrequest ); finish_checksense( qrequest ); return; err_send: abort_dma( device, qrequest ); finish_reset_queue( qrequest ); return;}bool check_rw_error( ide_device_info *device, ide_qrequest *qrequest ){ ide_bus_info *bus = device->bus; int status; status = bus->controller->get_altstatus( bus->channel ); if( (status & ide_status_err) != 0 ) { int error; if( bus->controller->read_command_block_regs( bus->channel, &device->tf, ide_mask_error ) != NO_ERROR ) { set_sense( device, SCSIS_KEY_HARDWARE_ERROR, SCSIS_ASC_INTERNAL_FAILURE ); return false; } error = device->tf.read.error; if( (error & ide_error_icrc) != 0 ) { set_sense( device, SCSIS_KEY_HARDWARE_ERROR, SCSIS_ASC_LUN_COM_CRC ); return false; } if( qrequest->is_write ) { if( (error & ide_error_wp) != 0 ) { set_sense( device, SCSIS_KEY_DATA_PROTECT, SCSIS_ASC_WRITE_PROTECTED ); return false; } } else { if( (error & ide_error_unc) != 0 ) { set_sense( device, SCSIS_KEY_MEDIUM_ERROR, SCSIS_ASC_UNREC_READ_ERR ); return false; } } if( (error & ide_error_mc) != 0 ) { set_sense( device, SCSIS_KEY_UNIT_ATTENTION, SCSIS_ASC_MEDIUM_CHANGED ); return false; } if( (error & ide_error_idnf) != 0 ) { // ID not found - invalid CHS mapping (was: seek error?) set_sense( device, SCSIS_KEY_MEDIUM_ERROR, SCSIS_ASC_RANDOM_POS_ERROR ); return false; } if( (error & ide_error_mcr) != 0 ) { // XXX proper sense key? // for TUR this case is not defined !? set_sense( device, SCSIS_KEY_UNIT_ATTENTION, SCSIS_ASC_REMOVAL_REQUESTED ); return false; } if( (error & ide_error_nm) != 0 ) { set_sense( device, SCSIS_KEY_NOT_READY, SCSIS_ASC_NO_MEDIUM ); return false; } if( (error & ide_error_abrt) != 0 ) { set_sense( device, SCSIS_KEY_ABORTED_COMMAND, SCSIS_ASC_NO_SENSE ); return false; } set_sense( device, SCSIS_KEY_HARDWARE_ERROR, SCSIS_ASC_INTERNAL_FAILURE ); return false; } return true;}bool check_output( ide_device_info *device, bool drdy_required, int error_mask, bool is_write ){ ide_bus_info *bus = device->bus; int status; if( bus->sync_wait_timeout ) { bus->sync_wait_timeout = false; set_sense( device, SCSIS_KEY_HARDWARE_ERROR, SCSIS_ASC_LUN_TIMEOUT ); return false; } status = bus->controller->get_altstatus( bus->channel ); if( (status & ide_status_bsy) != 0 ) { set_sense( device, SCSIS_KEY_HARDWARE_ERROR, SCSIS_ASC_LUN_TIMEOUT ); return false; } if( drdy_required && ((status & ide_status_drdy) == 0) ) { set_sense( device, SCSIS_KEY_HARDWARE_ERROR, SCSIS_ASC_INTERNAL_FAILURE ); return false; } if( (status & ide_status_err) != 0 ) { int error; if( bus->controller->read_command_block_regs( bus->channel, &device->tf, ide_mask_error ) != NO_ERROR ) { set_sense( device, SCSIS_KEY_HARDWARE_ERROR, SCSIS_ASC_INTERNAL_FAILURE ); return false; } error = device->tf.read.error & error_mask; if( (error & ide_error_icrc) != 0 ) { set_sense( device, SCSIS_KEY_HARDWARE_ERROR, SCSIS_ASC_LUN_COM_CRC ); return false; } if( is_write ) { if( (error & ide_error_wp) != 0 ) { set_sense( device, SCSIS_KEY_DATA_PROTECT, SCSIS_ASC_WRITE_PROTECTED ); return false; } } else { if( (error & ide_error_unc) != 0 ) { set_sense( device, SCSIS_KEY_MEDIUM_ERROR, SCSIS_ASC_UNREC_READ_ERR ); return false; } } if( (error & ide_error_mc) != 0 ) { // XXX what are the additional sense data for "medium changed" ? set_sense( device, SCSIS_KEY_UNIT_ATTENTION, SCSIS_ASC_NO_SENSE ); return false; } if( (error & ide_error_idnf) != 0 ) { // XXX strange error code, don't really know what it means set_sense( device, SCSIS_KEY_MEDIUM_ERROR, SCSIS_ASC_RANDOM_POS_ERROR ); return false; } if( (error & ide_error_mcr) != 0 ) { // XXX proper sense key? set_sense( device, SCSIS_KEY_UNIT_ATTENTION, SCSIS_ASC_REMOVAL_REQUESTED ); return false; } if( (error & ide_error_nm) != 0 ) { set_sense( device, SCSIS_KEY_MEDIUM_ERROR, SCSIS_ASC_NO_MEDIUM ); return false; } if( (error & ide_error_abrt) != 0 ) { set_sense( device, SCSIS_KEY_ABORTED_COMMAND, SCSIS_ASC_NO_SENSE ); return false; } set_sense( device, SCSIS_KEY_HARDWARE_ERROR, SCSIS_ASC_INTERNAL_FAILURE ); return false; } return true;}// set subcommand before callingstatic bool device_set_feature( ide_device_info *device, int feature ){ device->tf_param_mask = ide_mask_features; device->tf.write.features = feature; device->tf.write.command = IDE_CMD_SET_FEATURES; if( !send_command( device, true, 1000000, ide_state_sync_waiting )) return false; sem_acquire( device->bus->sync_wait_sem, 1 ); return check_output( device, true, ide_error_abrt, false );}static bool configure_rmsn( ide_device_info *device ){ ide_bus_info *bus = device->bus; int i; if( !device->infoblock.RMSN_supported || device->infoblock._127_RMSN_support != 1 ) return true; if( !device_set_feature( device, IDE_CMD_SET_FEATURES_ENABLE_MSN )) return false; bus->controller->read_command_block_regs( bus->channel, &device->tf, ide_mask_LBA_mid | ide_mask_LBA_high ); for( i = 0; i < 5; ++i ) { // don't use TUR as it checks not ide_error_mcr | ide_error_mc | ide_error_wp // but: we don't check wp as well device->combined_sense = 0; device->tf_param_mask = 0; device->tf.write.command = IDE_CMD_GET_MEDIA_STATUS; if( !send_command( device, true, 15000000, ide_state_sync_waiting )) continue; if( check_output( device, true, ide_error_nm | ide_error_abrt | ide_error_mcr | ide_error_mc, true ) || decode_sense_asc_ascq( device->combined_sense ) == SCSIS_ASC_NO_MEDIUM ) return true; } return false;}static bool configure_CQ( ide_device_info *device ){ device->CQ_enabled = device->CQ_supported = false; if( !device->bus->controller_params.can_CQ || !device->infoblock.DMA_QUEUED_supported ) return initialize_qreq_array( device, 1 ); // seems like the following functions always fail if( !device_set_feature( device, IDE_CMD_SET_FEATURES_DISABLE_REL_INT )) { dprintf( "Cannot disable release int\n" ); } if( !device_set_feature( device, IDE_CMD_SET_FEATURES_DISABLE_SERV_INT )) { dprintf( "Cannot disable release int\n" ); } device->CQ_enabled = device->CQ_supported = true; // official IBM docs talk about 31 queue entries, though // their disks report 32; let's hope their docs are wrong return initialize_qreq_array( device, device->infoblock.queue_depth + 1 );}bool prep_ata( ide_device_info *device ){ ide_device_infoblock *infoblock = &device->infoblock; uint32 chs_capacity; SHOW_FLOW0( 3, "" ); device->is_atapi = false; device->exec_io = ata_exec_io; // warning: ata == 0 means "this is ata"... if( infoblock->_0.ata.ATA != 0 ) { // CF has either magic header or CFA bit set // we merge it to "CFA bit set" for easier (later) testing if( *(uint16 *)infoblock == 0x848a ) infoblock->CFA_supported = true; else return false; } SHOW_FLOW0( 3, "1" ); if( !infoblock->_54_58_valid ) { // normally, current_xxx contains active CHS mapping, // but if BIOS didn't call INITIALIZE DEVICE PARAMETERS // the default mapping is used infoblock->current_sectors = infoblock->sectors; infoblock->current_cylinders = infoblock->cylinders; infoblock->current_heads = infoblock->heads; } // just in case capacity_xxx isn't initialized - calculate it manually // (seems that this information is really redundant; hopefully) chs_capacity = infoblock->current_sectors * infoblock->current_cylinders * infoblock->current_heads; infoblock->capacity_low = chs_capacity & 0xff; infoblock->capacity_high = chs_capacity >> 8; // checking LBA_supported flag should be sufficient, but it seems // that checking LBA_total_sectors is a good idea device->use_LBA = infoblock->LBA_supported && infoblock->LBA_total_sectors != 0; if( device->use_LBA ) { device->total_sectors = infoblock->LBA_total_sectors; device->tf.lba.mode = ide_mode_lba; } else { device->total_sectors = chs_capacity; device->tf.chs.mode = ide_mode_chs; } device->use_48bits = infoblock->_48_bit_addresses_supported; if( device->use_48bits ) device->total_sectors = infoblock->LBA48_total_sectors; SHOW_FLOW0( 3, "2" ); if( !configure_DMA( device ) || !configure_CQ( device ) || !configure_rmsn( device )) return false; SHOW_FLOW0( 3, "3" ); return true;}void enable_CQ( ide_device_info *device, bool enable ){}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -