003 File Manager
Current Path:
/usr/src/sys/dev/isci/scil
usr
/
src
/
sys
/
dev
/
isci
/
scil
/
📁
..
📄
intel_ata.h
(25.31 KB)
📄
intel_pci.h
(3.08 KB)
📄
intel_sas.h
(30.43 KB)
📄
intel_sat.h
(3.79 KB)
📄
intel_sata.h
(8.02 KB)
📄
intel_scsi.h
(20.25 KB)
📄
sati.c
(39.3 KB)
📄
sati.h
(10.92 KB)
📄
sati_abort_task_set.c
(6.05 KB)
📄
sati_abort_task_set.h
(3.27 KB)
📄
sati_atapi.c
(8.5 KB)
📄
sati_atapi.h
(7.71 KB)
📄
sati_callbacks.h
(16.32 KB)
📄
sati_design.h
(7.36 KB)
📄
sati_device.c
(8.93 KB)
📄
sati_device.h
(6.68 KB)
📄
sati_inquiry.c
(27.11 KB)
📄
sati_inquiry.h
(4.15 KB)
📄
sati_log_sense.c
(24.41 KB)
📄
sati_log_sense.h
(3.44 KB)
📄
sati_lun_reset.c
(4.82 KB)
📄
sati_lun_reset.h
(3.16 KB)
📄
sati_mode_pages.c
(9.41 KB)
📄
sati_mode_pages.h
(4.89 KB)
📄
sati_mode_select.c
(37.17 KB)
📄
sati_mode_select.h
(3.29 KB)
📄
sati_mode_sense.c
(29.7 KB)
📄
sati_mode_sense.h
(5.1 KB)
📄
sati_mode_sense_10.c
(19.27 KB)
📄
sati_mode_sense_10.h
(4.23 KB)
📄
sati_mode_sense_6.c
(15.91 KB)
📄
sati_mode_sense_6.h
(4.22 KB)
📄
sati_move.c
(22.63 KB)
📄
sati_move.h
(4.43 KB)
📄
sati_passthrough.c
(17.55 KB)
📄
sati_passthrough.h
(3.36 KB)
📄
sati_read.c
(11.59 KB)
📄
sati_read.h
(3.45 KB)
📄
sati_read_buffer.c
(8.13 KB)
📄
sati_read_buffer.h
(3.15 KB)
📄
sati_read_capacity.c
(13.36 KB)
📄
sati_read_capacity.h
(3.55 KB)
📄
sati_reassign_blocks.c
(21.91 KB)
📄
sati_reassign_blocks.h
(3.12 KB)
📄
sati_report_luns.c
(5.04 KB)
📄
sati_report_luns.h
(3.11 KB)
📄
sati_request_sense.c
(12.11 KB)
📄
sati_request_sense.h
(3.41 KB)
📄
sati_start_stop_unit.c
(14.45 KB)
📄
sati_start_stop_unit.h
(4.2 KB)
📄
sati_synchronize_cache.c
(4.66 KB)
📄
sati_synchronize_cache.h
(2.94 KB)
📄
sati_test_unit_ready.c
(6.63 KB)
📄
sati_test_unit_ready.h
(3.18 KB)
📄
sati_translator_sequence.h
(10.92 KB)
📄
sati_types.h
(5.14 KB)
📄
sati_unmap.c
(22.99 KB)
📄
sati_unmap.h
(4.66 KB)
📄
sati_util.c
(72.2 KB)
📄
sati_util.h
(13.53 KB)
📄
sati_verify.c
(10.08 KB)
📄
sati_verify.h
(3.23 KB)
📄
sati_write.c
(11.64 KB)
📄
sati_write.h
(3.45 KB)
📄
sati_write_and_verify.c
(8.64 KB)
📄
sati_write_and_verify.h
(3.45 KB)
📄
sati_write_buffer.c
(8.94 KB)
📄
sati_write_buffer.h
(3.06 KB)
📄
sati_write_long.c
(8.25 KB)
📄
sati_write_long.h
(3.2 KB)
📄
sci_abstract_list.c
(15.87 KB)
📄
sci_abstract_list.h
(36.67 KB)
📄
sci_base_controller.c
(4.18 KB)
📄
sci_base_controller.h
(11.67 KB)
📄
sci_base_domain.c
(3.36 KB)
📄
sci_base_domain.h
(9.88 KB)
📄
sci_base_iterator.c
(5.56 KB)
📄
sci_base_iterator.h
(4.34 KB)
📄
sci_base_library.c
(3.71 KB)
📄
sci_base_library.h
(6.19 KB)
📄
sci_base_logger.c
(9.68 KB)
📄
sci_base_logger.h
(4.12 KB)
📄
sci_base_memory_descriptor_list.c
(5.99 KB)
📄
sci_base_memory_descriptor_list.h
(5.97 KB)
📄
sci_base_memory_descriptor_list_decorator.c
(5.42 KB)
📄
sci_base_object.c
(4.06 KB)
📄
sci_base_object.h
(4.74 KB)
📄
sci_base_observer.c
(3.79 KB)
📄
sci_base_observer.h
(5.39 KB)
📄
sci_base_phy.c
(3.32 KB)
📄
sci_base_phy.h
(6.67 KB)
📄
sci_base_port.c
(3.29 KB)
📄
sci_base_port.h
(7.1 KB)
📄
sci_base_remote_device.c
(3 KB)
📄
sci_base_remote_device.h
(9.65 KB)
📄
sci_base_request.c
(2.98 KB)
📄
sci_base_request.h
(6.48 KB)
📄
sci_base_state.h
(3.6 KB)
📄
sci_base_state_machine.c
(7.36 KB)
📄
sci_base_state_machine.h
(5.04 KB)
📄
sci_base_state_machine_logger.c
(8.77 KB)
📄
sci_base_state_machine_logger.h
(5.47 KB)
📄
sci_base_state_machine_observer.c
(3.81 KB)
📄
sci_base_state_machine_observer.h
(4.67 KB)
📄
sci_base_subject.c
(4.91 KB)
📄
sci_base_subject.h
(4.8 KB)
📄
sci_controller.h
(4.38 KB)
📄
sci_controller_constants.h
(7.19 KB)
📄
sci_fast_list.h
(11.91 KB)
📄
sci_iterator.h
(4.23 KB)
📄
sci_library.h
(3.71 KB)
📄
sci_logger.h
(9.93 KB)
📄
sci_memory_descriptor_list.h
(6.25 KB)
📄
sci_memory_descriptor_list_decorator.h
(5.28 KB)
📄
sci_object.h
(5.19 KB)
📄
sci_overview.h
(10.95 KB)
📄
sci_pool.h
(6.18 KB)
📄
sci_simple_list.h
(11.04 KB)
📄
sci_status.h
(14.61 KB)
📄
sci_types.h
(8.59 KB)
📄
sci_util.c
(2.72 KB)
📄
sci_util.h
(5.54 KB)
📄
scic_config_parameters.h
(11.02 KB)
📄
scic_controller.h
(35.07 KB)
📄
scic_io_request.h
(27 KB)
📄
scic_library.h
(9.29 KB)
📄
scic_logger.h
(5.26 KB)
📄
scic_overview.h
(3.58 KB)
📄
scic_phy.h
(15.08 KB)
📄
scic_port.h
(8.01 KB)
📄
scic_remote_device.h
(16.95 KB)
📄
scic_sds_controller.c
(219.91 KB)
📄
scic_sds_controller.h
(25.17 KB)
📄
scic_sds_controller_registers.h
(15.37 KB)
📄
scic_sds_library.c
(8.78 KB)
📄
scic_sds_library.h
(3.81 KB)
📄
scic_sds_logger.h
(3.33 KB)
📄
scic_sds_pci.c
(8.47 KB)
📄
scic_sds_pci.h
(4.64 KB)
📄
scic_sds_phy.c
(120.86 KB)
📄
scic_sds_phy.h
(14.08 KB)
📄
scic_sds_phy_registers.h
(9.56 KB)
📄
scic_sds_port.c
(104.9 KB)
📄
scic_sds_port.h
(16.3 KB)
📄
scic_sds_port_configuration_agent.c
(38.16 KB)
📄
scic_sds_port_configuration_agent.h
(4.26 KB)
📄
scic_sds_port_registers.h
(4.69 KB)
📄
scic_sds_remote_device.c
(85.08 KB)
📄
scic_sds_remote_device.h
(20.58 KB)
📄
scic_sds_remote_node_context.c
(45.54 KB)
📄
scic_sds_remote_node_context.h
(12.77 KB)
📄
scic_sds_remote_node_table.c
(22.19 KB)
📄
scic_sds_remote_node_table.h
(6.63 KB)
📄
scic_sds_request.c
(88.54 KB)
📄
scic_sds_request.h
(16.53 KB)
📄
scic_sds_sgpio.c
(8.43 KB)
📄
scic_sds_smp_remote_device.c
(12.13 KB)
📄
scic_sds_smp_request.c
(29.64 KB)
📄
scic_sds_smp_request.h
(3.01 KB)
📄
scic_sds_ssp_request.c
(11.96 KB)
📄
scic_sds_stp_packet_request.c
(32.87 KB)
📄
scic_sds_stp_packet_request.h
(6.06 KB)
📄
scic_sds_stp_pio_request.h
(4.49 KB)
📄
scic_sds_stp_remote_device.c
(35.79 KB)
📄
scic_sds_stp_request.c
(80.59 KB)
📄
scic_sds_stp_request.h
(8.91 KB)
📄
scic_sds_unsolicited_frame_control.c
(14.8 KB)
📄
scic_sds_unsolicited_frame_control.h
(9.62 KB)
📄
scic_sgpio.h
(9.79 KB)
📄
scic_task_request.h
(7.41 KB)
📄
scic_user_callback.h
(41.37 KB)
📄
scif_config_parameters.h
(6.19 KB)
📄
scif_controller.h
(17.94 KB)
📄
scif_domain.h
(7.18 KB)
📄
scif_io_request.h
(10.26 KB)
📄
scif_library.h
(6.96 KB)
📄
scif_logger.h
(4.54 KB)
📄
scif_overview.h
(5.27 KB)
📄
scif_remote_device.h
(12.12 KB)
📄
scif_sas_constants.h
(2.97 KB)
📄
scif_sas_controller.c
(39.23 KB)
📄
scif_sas_controller.h
(9.32 KB)
📄
scif_sas_controller_state_handlers.c
(66.96 KB)
📄
scif_sas_controller_states.c
(13.31 KB)
📄
scif_sas_design.h
(15.75 KB)
📄
scif_sas_domain.c
(49.41 KB)
📄
scif_sas_domain.h
(9.6 KB)
📄
scif_sas_domain_state_handlers.c
(58.4 KB)
📄
scif_sas_domain_states.c
(20.18 KB)
📄
scif_sas_high_priority_request_queue.c
(5.86 KB)
📄
scif_sas_high_priority_request_queue.h
(4.5 KB)
📄
scif_sas_internal_io_request.c
(9.31 KB)
📄
scif_sas_internal_io_request.h
(5.11 KB)
📄
scif_sas_io_request.c
(27.08 KB)
📄
scif_sas_io_request.h
(5.08 KB)
📄
scif_sas_io_request_state_handlers.c
(13.93 KB)
📄
scif_sas_io_request_states.c
(8.65 KB)
📄
scif_sas_library.c
(8.96 KB)
📄
scif_sas_library.h
(3.54 KB)
📄
scif_sas_logger.h
(3.33 KB)
📄
scif_sas_remote_device.c
(26.69 KB)
📄
scif_sas_remote_device.h
(16.3 KB)
📄
scif_sas_remote_device_ready_substate_handlers.c
(28.59 KB)
📄
scif_sas_remote_device_ready_substates.c
(9.95 KB)
📄
scif_sas_remote_device_starting_substate_handlers.c
(11.85 KB)
📄
scif_sas_remote_device_starting_substates.c
(5.1 KB)
📄
scif_sas_remote_device_state_handlers.c
(43.12 KB)
📄
scif_sas_remote_device_states.c
(17.46 KB)
📄
scif_sas_request.c
(6.87 KB)
📄
scif_sas_request.h
(6.91 KB)
📄
scif_sas_sati_binding.h
(11.21 KB)
📄
scif_sas_smp_activity_clear_affiliation.c
(8.52 KB)
📄
scif_sas_smp_io_request.c
(19.84 KB)
📄
scif_sas_smp_io_request.h
(4.87 KB)
📄
scif_sas_smp_phy.c
(11.61 KB)
📄
scif_sas_smp_phy.h
(5.88 KB)
📄
scif_sas_smp_remote_device.c
(92.85 KB)
📄
scif_sas_smp_remote_device.h
(13.24 KB)
📄
scif_sas_stp_io_request.c
(21.64 KB)
📄
scif_sas_stp_io_request.h
(3.7 KB)
📄
scif_sas_stp_remote_device.c
(7.46 KB)
📄
scif_sas_stp_remote_device.h
(3.99 KB)
📄
scif_sas_stp_task_request.c
(9.92 KB)
📄
scif_sas_stp_task_request.h
(3.73 KB)
📄
scif_sas_task_request.c
(16.16 KB)
📄
scif_sas_task_request.h
(4.92 KB)
📄
scif_sas_task_request_state_handlers.c
(13.5 KB)
📄
scif_sas_task_request_states.c
(8.87 KB)
📄
scif_sas_timer.c
(4.4 KB)
📄
scif_task_request.h
(5.28 KB)
📄
scif_user_callback.h
(37.98 KB)
📄
scu_bios_definitions.h
(36.53 KB)
📄
scu_completion_codes.h
(10.96 KB)
📄
scu_constants.h
(6.55 KB)
📄
scu_event_codes.h
(11.77 KB)
📄
scu_registers.h
(83.65 KB)
📄
scu_remote_node_context.h
(7.11 KB)
📄
scu_task_context.h
(26.33 KB)
📄
scu_unsolicited_frame.h
(4.1 KB)
📄
scu_viit_data.h
(6.23 KB)
Editing: sati_util.c
/*- * SPDX-License-Identifier: BSD-2-Clause OR GPL-2.0 * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * BSD LICENSE * * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); /** * @file * @brief This file contains all of the method implementations that * provide generic support for SATI. Some methods can be utilized * by a user to construct ATA/ATAPI commands, copy ATA device * structure data, fill in sense data, etc. */ #include <dev/isci/scil/sati_util.h> #include <dev/isci/scil/sati_callbacks.h> #include <dev/isci/scil/intel_scsi.h> #include <dev/isci/scil/intel_ata.h> #include <dev/isci/scil/intel_sat.h> #include <dev/isci/scil/intel_sas.h> /** * @brief This method will set the data direction, protocol, and transfer * kength for an ATA non-data command. * * @pre It is expected that the user will use this method for setting these * values in a non-data ATA command constuct. * * @param[out] ata_io This parameter specifies the ATA IO request structure * for which to build the IDENTIFY DEVICE command. * @param[in] sequence This parameter specifies the translator sequence * for which the command is being constructed. * * @return none. */ void sati_ata_non_data_command( void * ata_io, SATI_TRANSLATOR_SEQUENCE_T * sequence ) { sequence->data_direction = SATI_DATA_DIRECTION_NONE; sequence->protocol = SAT_PROTOCOL_NON_DATA; sequence->ata_transfer_length = 0; } /** * @brief This method will construct the ATA identify device command. * * @pre It is expected that the user has properly set the current contents * of the register FIS to 0. * * @param[out] ata_io This parameter specifies the ATA IO request structure * for which to build the IDENTIFY DEVICE command. * @param[in] sequence This parameter specifies the translator sequence * for which the command is being constructed. * * @return none. */ void sati_ata_identify_device_construct( void * ata_io, SATI_TRANSLATOR_SEQUENCE_T * sequence ) { U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); sati_set_ata_command(register_fis, ATA_IDENTIFY_DEVICE); sequence->data_direction = SATI_DATA_DIRECTION_IN; sequence->protocol = SAT_PROTOCOL_PIO_DATA_IN; sequence->ata_transfer_length = sizeof(ATA_IDENTIFY_DEVICE_DATA_T); } /** * @brief This method will construct the ATA Execute Device Diagnostic command. * * @param[out] ata_io This parameter specifies the ATA IO request structure * for which to build the IDENTIFY DEVICE command. * @param[in] sequence This parameter specifies the translator sequence * for which the command is being constructed. * * @return none. */ void sati_ata_execute_device_diagnostic_construct( void * ata_io, SATI_TRANSLATOR_SEQUENCE_T * sequence ) { U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); sati_set_ata_command(register_fis, ATA_EXECUTE_DEVICE_DIAG); sequence->data_direction = SATI_DATA_DIRECTION_IN; sequence->protocol = SAT_PROTOCOL_DEVICE_DIAGNOSTIC; sequence->ata_transfer_length = 16; } /** * @brief This method will set data bytes in the user data area. If the * caller requests it, the data written will be forced to ascii * printable characters if it isn't already a printable character. * A printable character is considered to be >= 0x20 and <= 0x70. * * @param[in] sequence This parameter specifies the translation sequence * for which to copy and swap the data. * @param[out] destination_scsi_io This parameter specifies the SCSI IO * request containing the destination buffer into which to copy. * @param[in] destination_offset This parameter specifies the offset into * the data buffer where the information will be copied to. * @param[in] source_value This parameter specifies the value retrieved * from the source buffer that is to be copied into the user * buffer area. * @param[in] use_printable_chars This parameter indicates if the copy should * ensure that the value copied is considered an ASCII printable * character (e.g. A, B, " ", etc.). These characters reside * in the 0x20 - 0x7E ASCII range. * * @return none */ static void sati_set_ascii_data_byte( SATI_TRANSLATOR_SEQUENCE_T * sequence, void * destination_scsi_io, U32 destination_offset, U8 source_value, BOOL use_printable_chars ) { // if the user requests that the copied data be ascii printable, then // default to " " (i.e. 0x20) for all non-ascii printable characters. if((use_printable_chars == TRUE) && ((source_value < 0x20) || (source_value > 0x7E))) { source_value = 0x20; } sati_set_data_byte( sequence, destination_scsi_io, destination_offset, source_value ); } /** * @brief This method performs a copy operation using an offset into the * source buffer, an offset into the destination buffer, and a length. * It will perform the byte swap from the 16-bit identify field * into the network byte order SCSI location. * * @param[in] sequence This parameter specifies the translation sequence * for which to copy and swap the data. * @param[out] destination_scsi_io This parameter specifies the SCSI IO * request containing the destination buffer into which to copy. * @param[in] destination_offset This parameter specifies the offset into * the data buffer where the information will be copied to. * @param[in] source_buffer This parameter specifies the source buffer from * which the data will be copied. * @param[in] source_offset This parameter specifies the offset into the * source buffer where the copy shall begin. * @param[in] length This parameter specifies the number of bytes to copy * during this operation. * @param[in] use_printable_chars This parameter indicates if the copy should * ensure that the value copied is considered an ASCII printable * character (e.g. A, B, " ", etc.). These characters reside * in the 0x20 - 0x7E ASCII range. * * @return none */ void sati_ata_identify_device_copy_data( SATI_TRANSLATOR_SEQUENCE_T * sequence, void * destination_scsi_io, U32 destination_offset, U8 * source_buffer, U32 source_offset, U32 length, BOOL use_printable_chars ) { source_buffer += source_offset; while (length > 0) { sati_set_ascii_data_byte( sequence, destination_scsi_io, destination_offset, *(source_buffer+1), use_printable_chars ); sati_set_ascii_data_byte( sequence, destination_scsi_io, destination_offset+1, *source_buffer, use_printable_chars ); destination_offset += 2; source_buffer += 2; length -= 2; } } /** * @brief This method performs a copy operation using a source buffer, * an offset into the destination buffer, and a length. * * @param[in] sequence This parameter specifies the translation sequence * for which to copy and swap the data. * @param[out] destination_scsi_io This parameter specifies the SCSI IO * request containing the destination buffer into which to copy. * @param[in] destination_offset This parameter specifies the offset into * the data buffer where the information will be copied to. * @param[in] source_buffer This parameter specifies the source buffer from * which the data will be copied. * @param[in] length This parameter specifies the number of bytes to copy * during this operation. * * @return none */ void sati_copy_data( SATI_TRANSLATOR_SEQUENCE_T * sequence, void * destination_scsi_io, U32 destination_offset, U8 * source_buffer, U32 length ) { while (length > 0) { sati_set_data_byte( sequence, destination_scsi_io, destination_offset, *source_buffer ); destination_offset++; source_buffer++; length--; } } /** * @brief This method extracts the Logical Block Address high and low 32-bit * values and the sector count 32-bit value from the ATA identify * device data. * * @param[in] identify This parameter specifies the ATA_IDENTIFY_DEVICE_DATA * from which to extract the sector information. * @param[out] lba_high This parameter specifies the upper 32 bits for the * number of logical block addresses for the device. The upper * 16-bits should always be 0, since 48-bits of LBA is the most * supported by an ATA device. * @param[out] lba_low This parameter specifies the lower 32 bits for the * number of logical block addresses for the device. * @param[out] sector_size This parameter specifies the 32-bits of sector * size. If the ATA device doesn't support reporting it's * sector size, then 512 bytes is utilized as the default value. * * @return none */ void sati_ata_identify_device_get_sector_info( ATA_IDENTIFY_DEVICE_DATA_T * identify, U32 * lba_high, U32 * lba_low, U32 * sector_size ) { // Calculate the values to be returned // Calculation will be different if the SATA device supports // 48-bit addressing. Bit 10 of Word 86 of ATA Identify if (identify->command_set_enabled1 & ATA_IDENTIFY_COMMAND_SET_SUPPORTED1_48BIT_ENABLE) { // This drive supports 48-bit addressing *lba_high = identify->max_48bit_lba[7] << 24; *lba_high |= identify->max_48bit_lba[6] << 16; *lba_high |= identify->max_48bit_lba[5] << 8; *lba_high |= identify->max_48bit_lba[4]; *lba_low = identify->max_48bit_lba[3] << 24; *lba_low |= identify->max_48bit_lba[2] << 16; *lba_low |= identify->max_48bit_lba[1] << 8; *lba_low |= identify->max_48bit_lba[0]; } else { // This device doesn't support 48-bit addressing // Pull out the largest LBA from words 60 and 61. *lba_high = 0; *lba_low = identify->total_num_sectors[3] << 24; *lba_low |= identify->total_num_sectors[2] << 16; *lba_low |= identify->total_num_sectors[1] << 8; *lba_low |= identify->total_num_sectors[0]; } // If the ATA device reports its sector size (bit 12 of Word 106), // then use that instead. if (identify->physical_logical_sector_info & ATA_IDENTIFY_SECTOR_LARGER_THEN_512_ENABLE) { *sector_size = identify->words_per_logical_sector[3] << 24; *sector_size |= identify->words_per_logical_sector[2] << 16; *sector_size |= identify->words_per_logical_sector[1] << 8; *sector_size |= identify->words_per_logical_sector[0]; } else { // Default the sector size to 512 bytes *sector_size = 512; } } /** * @brief This method will construct the ATA check power mode command. * * @pre It is expected that the user has properly set the current contents * of the register FIS to 0. * * @param[out] ata_io This parameter specifies the ATA IO request structure * for which to build the CHECK POWER MODE command. * @param[in] sequence This parameter specifies the translator sequence * for which the command is being constructed. * * @return none. */ void sati_ata_check_power_mode_construct( void * ata_io, SATI_TRANSLATOR_SEQUENCE_T * sequence ) { U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); sati_set_ata_command(register_fis, ATA_CHECK_POWER_MODE); sati_ata_non_data_command(ata_io, sequence); } /** * @brief This method is utilized to set a specific byte in the sense * data area. It will ensure that the supplied byte offset * isn't larger then the length of the requested sense data. * * @param[in] scsi_io This parameter specifies the user SCSI IO request * for which to set the sense data byte. * @param[in] byte_offset This parameter specifies the byte offset into * the sense data buffer where the data should be written. * @param[in] value This parameter specifies the 8-bit value to be written * into the sense data area. * * @return none */ void sati_set_sense_data_byte( U8 * sense_data, U32 max_sense_data_len, U32 byte_offset, U8 value ) { // Ensure that we don't attempt to write past the end of the sense // data buffer. if (byte_offset < max_sense_data_len) sense_data[byte_offset] = value; } /** * @brief This method will construct the common response IU in the user * request's response IU location. * * @param[out] rsp_iu This parameter specifies the user request's * response IU to be constructed. * @param[in] scsi_status This parameter specifies the SCSI status * value for the user's IO request. * @param[in] sense_data_length This parameter specifies the sense data * length for response IU. * @param[in] data_present The parameter specifies the specific * data present value for response IU. * * @return none */ void sati_scsi_common_response_iu_construct( SCI_SSP_RESPONSE_IU_T * rsp_iu, U8 scsi_status, U8 sense_data_length, U8 data_present ) { rsp_iu->sense_data_length[3] = sense_data_length; rsp_iu->sense_data_length[2] = 0; rsp_iu->sense_data_length[1] = 0; rsp_iu->sense_data_length[0] = 0; rsp_iu->status = scsi_status; rsp_iu->data_present = data_present; } /** * @brief This method will construct the buffer for sense data * sense data buffer location. Additionally, it will set the user's * SCSI status. * * @param[in,out] scsi_io This parameter specifies the user's IO request * for which to construct the buffer for sense data. * @param[in] scsi_status This parameter specifies the SCSI status * value for the user's IO request. * @param[out] sense_data This paramater * * @return none */ static void sati_scsi_get_sense_data_buffer( SATI_TRANSLATOR_SEQUENCE_T * sequence, void * scsi_io, U8 scsi_status, U8 ** sense_data, U32 * sense_len) { #ifdef SATI_TRANSPORT_SUPPORTS_SAS SCI_SSP_RESPONSE_IU_T * rsp_iu = (SCI_SSP_RESPONSE_IU_T*) sati_cb_get_response_iu_address(scsi_io); sati_scsi_common_response_iu_construct( rsp_iu, scsi_status, sati_scsi_get_sense_data_length(sequence, scsi_io), SCSI_RESPONSE_DATA_PRES_SENSE_DATA ); *sense_data = (U8*) rsp_iu->data; *sense_len = SSP_RESPONSE_IU_MAX_DATA * 4; // dwords to bytes #else *sense_data = sati_cb_get_sense_data_address(scsi_io); *sense_len = sati_cb_get_sense_data_length(scsi_io); sati_cb_set_scsi_status(scsi_io, scsi_status); #endif // SATI_TRANSPORT_SUPPORTS_SAS } /** * @brief This method extract response code based on on device settings. * * @return response code */ static U8 sati_scsi_get_sense_data_response_code(SATI_TRANSLATOR_SEQUENCE_T * sequence) { if (sequence->device->descriptor_sense_enable) { return SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE; } else { return SCSI_FIXED_CURRENT_RESPONSE_CODE; } } /** * @brief This method will return length of descriptor sense data for executed command. * * @return sense data length */ static U8 sati_scsi_get_descriptor_sense_data_length(SATI_TRANSLATOR_SEQUENCE_T * sequence, void * scsi_io) { U8 * cdb = sati_cb_get_cdb_address(scsi_io); //Initial value is descriptor header length U8 length = 8; switch (sati_get_cdb_byte(cdb, 0)) { #if !defined(DISABLE_SATI_WRITE_LONG) case SCSI_WRITE_LONG_10: case SCSI_WRITE_LONG_16: length += SCSI_BLOCK_DESCRIPTOR_LENGTH + SCSI_INFORMATION_DESCRIPTOR_LENGTH; break; #endif // !defined(DISABLE_SATI_WRITE_LONG) #if !defined(DISABLE_SATI_REASSIGN_BLOCKS) case SCSI_REASSIGN_BLOCKS: length += SCSI_CMD_SPECIFIC_DESCRIPTOR_LENGTH + SCSI_INFORMATION_DESCRIPTOR_LENGTH; break; #endif // !defined(DISABLE_SATI_REASSIGN_BLOCKS) case SCSI_READ_6: case SCSI_READ_10: case SCSI_READ_12: case SCSI_READ_16: case SCSI_WRITE_6: case SCSI_WRITE_10: case SCSI_WRITE_12: case SCSI_WRITE_16: #if !defined(DISABLE_SATI_VERIFY) case SCSI_VERIFY_10: case SCSI_VERIFY_12: case SCSI_VERIFY_16: #endif // !defined(DISABLE_SATI_VERIFY) #if !defined(DISABLE_SATI_WRITE_AND_VERIFY) \ && !defined(DISABLE_SATI_VERIFY) \ && !defined(DISABLE_SATI_WRITE) case SCSI_WRITE_AND_VERIFY_10: case SCSI_WRITE_AND_VERIFY_12: case SCSI_WRITE_AND_VERIFY_16: #endif // !defined(DISABLE_SATI_WRITE_AND_VERIFY) // && !defined(DISABLE_SATI_VERIFY) // && !defined(DISABLE_SATI_WRITE) length += SCSI_INFORMATION_DESCRIPTOR_LENGTH; break; } return length; } /** * @brief This method will return length of sense data. * * @return sense data length */ U8 sati_scsi_get_sense_data_length(SATI_TRANSLATOR_SEQUENCE_T * sequence, void * scsi_io) { U8 response_code; response_code = sati_scsi_get_sense_data_response_code(sequence); switch (response_code) { case SCSI_FIXED_CURRENT_RESPONSE_CODE: case SCSI_FIXED_DEFERRED_RESPONSE_CODE: return SCSI_FIXED_SENSE_DATA_BASE_LENGTH; break; case SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE: case SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE: return sati_scsi_get_descriptor_sense_data_length(sequence, scsi_io); break; } return SCSI_FIXED_SENSE_DATA_BASE_LENGTH; } /** * @brief This method will construct the sense data buffer in the user's * sense data buffer location. Additionally, it will set the user's * SCSI status. * * @param[in] sequence This parameter specifies the translation sequence * for which to construct the sense data. * @param[in,out] scsi_io This parameter specifies the user's IO request * for which to construct the sense data. * @param[in] scsi_status This parameter specifies the SCSI status * value for the user's IO request. * @param[in] sense_key This parameter specifies the sense key to * be set for the user's IO request. * @param[in] additional_sense_code This parameter specifies the * additional sense code (ASC) key to be set for the user's * IO request. * @param[in] additional_sense_code_qualifier This parameter specifies * the additional sense code qualifier (ASCQ) key to be set * for the user's IO request. * * @return none */ void sati_scsi_sense_data_construct( SATI_TRANSLATOR_SEQUENCE_T * sequence, void * scsi_io, U8 scsi_status, U8 sense_key, U8 additional_sense_code, U8 additional_sense_code_qualifier ) { U8 response_code; response_code = sati_scsi_get_sense_data_response_code(sequence); switch (response_code) { case SCSI_FIXED_CURRENT_RESPONSE_CODE: case SCSI_FIXED_DEFERRED_RESPONSE_CODE: sati_scsi_fixed_sense_data_construct(sequence, scsi_io, scsi_status, response_code, sense_key, additional_sense_code, additional_sense_code_qualifier); break; case SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE: case SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE: sati_scsi_descriptor_sense_data_construct(sequence, scsi_io, scsi_status, response_code, sense_key, additional_sense_code, additional_sense_code_qualifier); break; } sequence->is_sense_response_set = TRUE; } /** * @brief This method will construct the block descriptor in the user's descriptor * sense data buffer location. * * @param[in] sense_data This parameter specifies the user SCSI IO request * for which to set the sense data byte. * @param[in] sense_len This parameter specifies length of the sense data * to be returned by SATI. * @param[out] descriptor_len This parameter returns the length of constructed * descriptor. * * @return none */ static void sati_scsi_block_descriptor_construct( U8 * sense_data, U32 sense_len) { U8 ili = 1; sati_set_sense_data_byte(sense_data, sense_len, 0, SCSI_BLOCK_DESCRIPTOR_TYPE); sati_set_sense_data_byte(sense_data, sense_len, 1, SCSI_BLOCK_DESCRIPTOR_ADDITIONAL_LENGTH); sati_set_sense_data_byte(sense_data, sense_len, 2, 0); sati_set_sense_data_byte(sense_data, sense_len, 3, (ili << 5)); } /** * @brief This method will construct the command-specific descriptor for * the descriptor sense data buffer in the user's sense data buffer * location. * * @param[in] sense_data This parameter specifies the user SCSI IO request * for which to set the sense data byte. * @param[in] sense_len This parameter specifies length of the sense data * to be returned by SATI. * @param[out] descriptor_len This parameter returns the length of constructed * descriptor. * @param[in] information_buff This parameter specifies the address for which * to set the command-specific information buffer. * * @return none */ static void sati_scsi_command_specific_descriptor_construct( U8 * sense_data, U32 sense_len, U8 * information_buff) { U8 i; sati_set_sense_data_byte(sense_data, sense_len, 0, SCSI_CMD_SPECIFIC_DESCRIPTOR_TYPE); sati_set_sense_data_byte(sense_data, sense_len, 1, SCSI_CMD_SPECIFIC_DESCRIPTOR_ADDITIONAL_LENGTH); sati_set_sense_data_byte(sense_data, sense_len, 2, 0); sati_set_sense_data_byte(sense_data, sense_len, 3, 0); // fill information buffer // SBC 5.20.1 REASSIGN BLOCKS command overview // If information about the first LBA not reassigned is not available // COMMAND-SPECIFIC INFORMATION field shall be set to FFFF_FFFF_FFFF_FFFFh for (i=0; i<8; i++) sati_set_sense_data_byte(sense_data, sense_len, 4 + i, information_buff==NULL?0xFF:information_buff[i]); } /** * @brief This method will construct the information descriptor for * the descriptor sense data buffer in the user's sense data buffer * location. * * @param[in] sense_data This parameter specifies the user SCSI IO request * for which to set the sense data byte. * @param[in] sense_len This parameter specifies length of the sense data * to be returned by SATI. * @param[out] descriptor_len This parameter returns the length of constructed * descriptor. * @param[in] information_buff This parameter specifies the address for which * to set the information buffer. * * @return none */ static void sati_scsi_information_descriptor_construct( U8 * sense_data, U32 sense_len, U8 * information_buff) { U8 i; U8 valid = 1; sati_set_sense_data_byte(sense_data, sense_len, 0, SCSI_INFORMATION_DESCRIPTOR_TYPE); sati_set_sense_data_byte(sense_data, sense_len, 1, SCSI_INFORMATION_DESCRIPTOR_ADDITIONAL_LENGTH); sati_set_sense_data_byte(sense_data, sense_len, 2, (valid << 7)); sati_set_sense_data_byte(sense_data, sense_len, 3, 0); // fill information buffer for (i=0; i<8; i++) sati_set_sense_data_byte(sense_data, sense_len, 4 + i, information_buff==NULL?0:information_buff[i]); } /** * @brief This method will construct the descriptors in the user's descriptor * sense data buffer location. * * @param[in,out] scsi_io This parameter specifies the user's IO request * for which to construct the sense data. * @param[in] sense_data This parameter specifies the user SCSI IO request * for which to set the sense data byte. * @param[in] sense_len This parameter specifies length of the sense data * to be returned by SATI. * @param[out] descriptor_len This parameter returns the length of constructed * descriptor. * @param[in] information_buff This parameter specifies the address for which * to set the information buffer. * * @return none */ static void sati_scsi_common_descriptors_construct( void * scsi_io, U8 * sense_data, U32 sense_len, U8 * information_buff) { U8 * cdb = sati_cb_get_cdb_address(scsi_io); U8 offset = 0; switch (sati_get_cdb_byte(cdb, 0)) { #if !defined(DISABLE_SATI_WRITE_LONG) case SCSI_WRITE_LONG_10: case SCSI_WRITE_LONG_16: sati_scsi_block_descriptor_construct( sense_data + offset, sense_len - offset); offset += SCSI_BLOCK_DESCRIPTOR_LENGTH; sati_scsi_information_descriptor_construct( sense_data + offset, sense_len - offset, information_buff); offset += SCSI_INFORMATION_DESCRIPTOR_LENGTH; break; #endif // !defined(DISABLE_SATI_WRITE_LONG) #if !defined(DISABLE_SATI_REASSIGN_BLOCKS) case SCSI_REASSIGN_BLOCKS: sati_scsi_command_specific_descriptor_construct( sense_data + offset, sense_len - offset, NULL); offset += SCSI_CMD_SPECIFIC_DESCRIPTOR_LENGTH; sati_scsi_information_descriptor_construct( sense_data + offset, sense_len - offset, information_buff); offset += SCSI_INFORMATION_DESCRIPTOR_LENGTH; break; #endif // !defined(DISABLE_SATI_REASSIGN_BLOCKS) case SCSI_READ_6: case SCSI_READ_10: case SCSI_READ_12: case SCSI_READ_16: case SCSI_WRITE_6: case SCSI_WRITE_10: case SCSI_WRITE_12: case SCSI_WRITE_16: #if !defined(DISABLE_SATI_VERIFY) case SCSI_VERIFY_10: case SCSI_VERIFY_12: case SCSI_VERIFY_16: #endif // !defined(DISABLE_SATI_VERIFY) #if !defined(DISABLE_SATI_WRITE_AND_VERIFY) \ && !defined(DISABLE_SATI_VERIFY) \ && !defined(DISABLE_SATI_WRITE) case SCSI_WRITE_AND_VERIFY_10: case SCSI_WRITE_AND_VERIFY_12: case SCSI_WRITE_AND_VERIFY_16: #endif // !defined(DISABLE_SATI_WRITE_AND_VERIFY) // && !defined(DISABLE_SATI_VERIFY) // && !defined(DISABLE_SATI_WRITE) sati_scsi_information_descriptor_construct( sense_data + offset, sense_len - offset, information_buff); offset += SCSI_INFORMATION_DESCRIPTOR_LENGTH; break; } } /** * @brief This method will construct the descriptor sense data buffer in * the user's sense data buffer location. Additionally, it will set * the user's SCSI status. * * @param[in] sequence This parameter specifies the translation sequence * for which to construct the sense data. * @param[in,out] scsi_io This parameter specifies the user's IO request * for which to construct the sense data. * @param[in] scsi_status This parameter specifies the SCSI status * value for the user's IO request. * @param[in] sense_key This parameter specifies the sense key to * be set for the user's IO request. * @param[in] additional_sense_code This parameter specifies the * additional sense code (ASC) key to be set for the user's * IO request. * @param[in] additional_sense_code_qualifier This parameter specifies * the additional sense code qualifier (ASCQ) key to be set * for the user's IO request. * * @return none */ void sati_scsi_descriptor_sense_data_construct( SATI_TRANSLATOR_SEQUENCE_T * sequence, void * scsi_io, U8 scsi_status, U8 response_code, U8 sense_key, U8 additional_sense_code, U8 additional_sense_code_qualifier ) { U8 * sense_data; U32 sense_len; sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len); sati_set_sense_data_byte( sense_data, sense_len, 0, response_code ); sati_set_sense_data_byte(sense_data, sense_len, 1, sense_key); sati_set_sense_data_byte(sense_data, sense_len, 2, additional_sense_code); sati_set_sense_data_byte(sense_data, sense_len, 3, additional_sense_code_qualifier); sati_set_sense_data_byte(sense_data, sense_len, 4, 0); sati_set_sense_data_byte(sense_data, sense_len, 5, 0); sati_set_sense_data_byte(sense_data, sense_len, 6, 0); sati_scsi_common_descriptors_construct(scsi_io, sense_data + 8, sense_len, NULL); sati_set_sense_data_byte(sense_data, sense_len, 7, sati_scsi_get_descriptor_sense_data_length(sequence, scsi_io) - 8); } /** * @brief This method will construct the fixed format sense data buffer * in the user's sense data buffer location. Additionally, it will * set the user's SCSI status. * * @param[in] sequence This parameter specifies the translation sequence * for which to construct the sense data. * @param[in,out] scsi_io This parameter specifies the user's IO request * for which to construct the sense data. * @param[in] scsi_status This parameter specifies the SCSI status * value for the user's IO request. * @param[in] sense_key This parameter specifies the sense key to * be set for the user's IO request. * @param[in] additional_sense_code This parameter specifies the * additional sense code (ASC) key to be set for the user's * IO request. * @param[in] additional_sense_code_qualifier This parameter specifies * the additional sense code qualifier (ASCQ) key to be set * for the user's IO request. * * @return none */ void sati_scsi_fixed_sense_data_construct( SATI_TRANSLATOR_SEQUENCE_T * sequence, void * scsi_io, U8 scsi_status, U8 response_code, U8 sense_key, U8 additional_sense_code, U8 additional_sense_code_qualifier ) { U8 * sense_data; U32 sense_len; sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len); // Write out the sense data format per SPC-4. // We utilize the fixed format sense data format. sati_set_sense_data_byte( sense_data, sense_len, 0, response_code | SCSI_FIXED_SENSE_DATA_VALID_BIT ); sati_set_sense_data_byte(sense_data, sense_len, 1, 0); sati_set_sense_data_byte(sense_data, sense_len, 2, sense_key); sati_set_sense_data_byte(sense_data, sense_len, 3, 0); sati_set_sense_data_byte(sense_data, sense_len, 4, 0); sati_set_sense_data_byte(sense_data, sense_len, 5, 0); sati_set_sense_data_byte(sense_data, sense_len, 6, 0); sati_set_sense_data_byte(sense_data, sense_len, 7, (sense_len < 18 ? sense_len - 1 : 17) - 7); sati_set_sense_data_byte(sense_data, sense_len, 8, 0); sati_set_sense_data_byte(sense_data, sense_len, 9, 0); sati_set_sense_data_byte(sense_data, sense_len, 10, 0); sati_set_sense_data_byte(sense_data, sense_len, 11, 0); sati_set_sense_data_byte(sense_data, sense_len, 12, additional_sense_code); sati_set_sense_data_byte(sense_data, sense_len, 13, additional_sense_code_qualifier); sati_set_sense_data_byte(sense_data, sense_len, 14, 0); sati_set_sense_data_byte(sense_data, sense_len, 15, 0); sati_set_sense_data_byte(sense_data, sense_len, 16, 0); sati_set_sense_data_byte(sense_data, sense_len, 17, 0); } /** * @brief This method will construct common sense data that will be identical in * both read error sense construct functions. * sati_scsi_read_ncq_error_sense_construct, * sati_scsi_read_error_sense_construct * * @param[in] sense_data This parameter specifies the user SCSI IO request * for which to set the sense data byte. * @param[in] sense_len This parameter specifies length of the sense data * to be returned by SATI. * @param[in] sense_key This parameter specifies the sense key to * be set for the user's IO request. * @param[in] additional_sense_code This parameter specifies the * additional sense code (ASC) key to be set for the user's * IO request. * @param[in] additional_sense_code_qualifier This parameter specifies * the additional sense code qualifier (ASCQ) key to be set * for the user's IO request. * * @return none */ static void sati_scsi_common_fixed_sense_construct( U8 * sense_data, U32 sense_len, U8 sense_key, U8 additional_sense_code, U8 additional_sense_code_qualifier ) { sati_set_sense_data_byte(sense_data, sense_len, 1, 0); sati_set_sense_data_byte(sense_data, sense_len, 2, sense_key); //Bytes 3, 4, 5, 6 are set in read_error_sense_construct functions sati_set_sense_data_byte(sense_data, sense_len, 7, (sense_len < 18 ? sense_len - 1 : 17) - 7); sati_set_sense_data_byte(sense_data, sense_len, 8, 0); sati_set_sense_data_byte(sense_data, sense_len, 9, 0); sati_set_sense_data_byte(sense_data, sense_len, 10, 0); sati_set_sense_data_byte(sense_data, sense_len, 11, 0); sati_set_sense_data_byte(sense_data, sense_len, 12, additional_sense_code); sati_set_sense_data_byte(sense_data, sense_len, 13, additional_sense_code_qualifier); sati_set_sense_data_byte(sense_data, sense_len, 14, 0); sati_set_sense_data_byte(sense_data, sense_len, 15, 0x80); sati_set_sense_data_byte(sense_data, sense_len, 16, 0); sati_set_sense_data_byte(sense_data, sense_len, 17, 0); } /** * @brief This method will construct the descriptor sense data buffer in * the user's sense data buffer location. Additionally, it will set * the user's SCSI status. * * @param[in] sequence This parameter specifies the translation sequence * for which to construct the sense data. * @param[in,out] scsi_io This parameter specifies the user's IO request * for which to construct the sense data. * @param[in] scsi_status This parameter specifies the SCSI status * value for the user's IO request. * @param[in] sense_key This parameter specifies the sense key to * be set for the user's IO request. * @param[in] additional_sense_code This parameter specifies the * additional sense code (ASC) key to be set for the user's * IO request. * @param[in] additional_sense_code_qualifier This parameter specifies * the additional sense code qualifier (ASCQ) key to be set * for the user's IO request. * * @return none */ static void sati_scsi_common_descriptor_sense_construct( SATI_TRANSLATOR_SEQUENCE_T * sequence, void * scsi_io, U8 * sense_data, U32 sense_len, U8 sense_key, U8 additional_sense_code, U8 additional_sense_code_qualifier, U8 * information_buff ) { sati_set_sense_data_byte(sense_data, sense_len, 1, sense_key); sati_set_sense_data_byte(sense_data, sense_len, 2, additional_sense_code); sati_set_sense_data_byte(sense_data, sense_len, 3, additional_sense_code_qualifier); sati_set_sense_data_byte(sense_data, sense_len, 4, 0); sati_set_sense_data_byte(sense_data, sense_len, 5, 0); sati_set_sense_data_byte(sense_data, sense_len, 6, 0); sati_scsi_common_descriptors_construct(scsi_io, sense_data + 8, sense_len, information_buff); sati_set_sense_data_byte(sense_data, sense_len, 7, sati_scsi_get_descriptor_sense_data_length(sequence, scsi_io) - 8); } /** * @brief This method will construct the sense data buffer in the user's * descriptor sense data buffer location. Additionally, it will set * the user's SCSI status. This is only used for NCQ uncorrectable * read errors * * @param[in] sequence This parameter specifies the translation sequence * for which to construct the sense data. * @param[in,out] scsi_io This parameter specifies the user's IO request * for which to construct the sense data. * @param[in] ata_input_data This parameter specifies the user's ATA IO * response from a Read Log Ext command. * @param[in] scsi_status This parameter specifies the SCSI status * value for the user's IO request. * @param[in] sense_key This parameter specifies the sense key to * be set for the user's IO request. * @param[in] additional_sense_code This parameter specifies the * additional sense code (ASC) key to be set for the user's * IO request. * @param[in] additional_sense_code_qualifier This parameter specifies * the additional sense code qualifier (ASCQ) key to be set * for the user's IO request. * * @return none */ static void sati_scsi_read_ncq_error_descriptor_sense_construct( SATI_TRANSLATOR_SEQUENCE_T * sequence, void * scsi_io, void * ata_input_data, U8 scsi_status, U8 response_code, U8 sense_key, U8 additional_sense_code, U8 additional_sense_code_qualifier ) { U8 * sense_data; U32 sense_len; U8 information_buff[8] = {0}; ATA_NCQ_COMMAND_ERROR_LOG_T * ncq_log = (ATA_NCQ_COMMAND_ERROR_LOG_T *) ata_input_data; sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len); sati_set_sense_data_byte( sense_data, sense_len, 0, response_code ); information_buff[2] = ncq_log->lba_47_40; information_buff[3] = ncq_log->lba_39_32; information_buff[4] = ncq_log->lba_31_24; information_buff[5] = ncq_log->lba_23_16; information_buff[6] = ncq_log->lba_15_8; information_buff[7] = ncq_log->lba_7_0; sati_scsi_common_descriptor_sense_construct( sequence, scsi_io, sense_data, sense_len, sense_key, additional_sense_code, additional_sense_code_qualifier, information_buff ); } /** * @brief This method will construct the sense data buffer in the user's * sense data buffer location. Additionally, it will set the user's * SCSI status. This is only used for NCQ uncorrectable read errors * * @param[in] sequence This parameter specifies the translation sequence * for which to construct the sense data. * @param[in,out] scsi_io This parameter specifies the user's IO request * for which to construct the sense data. * @param[in] ata_input_data This parameter specifies the user's ATA IO * response from a Read Log Ext command. * @param[in] scsi_status This parameter specifies the SCSI status * value for the user's IO request. * @param[in] sense_key This parameter specifies the sense key to * be set for the user's IO request. * @param[in] additional_sense_code This parameter specifies the * additional sense code (ASC) key to be set for the user's * IO request. * @param[in] additional_sense_code_qualifier This parameter specifies * the additional sense code qualifier (ASCQ) key to be set * for the user's IO request. * * @return none */ static void sati_scsi_read_ncq_error_fixed_sense_construct( SATI_TRANSLATOR_SEQUENCE_T * sequence, void * scsi_io, void * ata_input_data, U8 scsi_status, U8 response_code, U8 sense_key, U8 additional_sense_code, U8 additional_sense_code_qualifier ) { U8 * sense_data; U32 sense_len; U8 valid = TRUE; ATA_NCQ_COMMAND_ERROR_LOG_T * ncq_log = (ATA_NCQ_COMMAND_ERROR_LOG_T *) ata_input_data; sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len); if(ncq_log->lba_39_32 > 0) { valid = FALSE; } sati_set_sense_data_byte( sense_data, sense_len, 0, (valid << 7) | response_code ); sati_set_sense_data_byte(sense_data, sense_len, 3, ncq_log->lba_31_24); sati_set_sense_data_byte(sense_data, sense_len, 4, ncq_log->lba_23_16); sati_set_sense_data_byte(sense_data, sense_len, 5, ncq_log->lba_15_8); sati_set_sense_data_byte(sense_data, sense_len, 6, ncq_log->lba_7_0); sati_scsi_common_fixed_sense_construct( sense_data, sense_len, sense_key, additional_sense_code, additional_sense_code_qualifier ); } void sati_scsi_read_ncq_error_sense_construct( SATI_TRANSLATOR_SEQUENCE_T * sequence, void * scsi_io, void * ata_input_data, U8 scsi_status, U8 sense_key, U8 additional_sense_code, U8 additional_sense_code_qualifier ) { U8 response_code; response_code = sati_scsi_get_sense_data_response_code(sequence); switch (response_code) { case SCSI_FIXED_CURRENT_RESPONSE_CODE: case SCSI_FIXED_DEFERRED_RESPONSE_CODE: sati_scsi_read_ncq_error_fixed_sense_construct(sequence, scsi_io, ata_input_data, scsi_status, response_code, sense_key, additional_sense_code, additional_sense_code_qualifier); break; case SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE: case SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE: sati_scsi_read_ncq_error_descriptor_sense_construct(sequence, scsi_io, ata_input_data, scsi_status, response_code, sense_key, additional_sense_code, additional_sense_code_qualifier); break; } sequence->is_sense_response_set = TRUE; } /** * @brief This method will construct the sense data buffer in the user's * sense data buffer location. Additionally, it will set the user's * SCSI status. This is used for uncorrectable read errors. * * @param[in] sequence This parameter specifies the translation sequence * for which to construct the sense data. * @param[in,out] scsi_io This parameter specifies the user's IO request * for which to construct the sense data. * @param[in] ata_io This parameter is a pointer to the ATA IO data used * to get the ATA register fis. * @param[in] scsi_status This parameter specifies the SCSI status * value for the user's IO request. * @param[in] sense_key This parameter specifies the sense key to * be set for the user's IO request. * @param[in] additional_sense_code This parameter specifies the * additional sense code (ASC) key to be set for the user's * IO request. * @param[in] additional_sense_code_qualifier This parameter specifies * the additional sense code qualifier (ASCQ) key to be set * for the user's IO request. * * @return none */ static void sati_scsi_read_error_descriptor_sense_construct( SATI_TRANSLATOR_SEQUENCE_T * sequence, void * scsi_io, void * ata_io, U8 scsi_status, U8 response_code, U8 sense_key, U8 additional_sense_code, U8 additional_sense_code_qualifier ) { U8 * sense_data; U32 sense_len; U8 information_buff[8] = {0}; U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io); sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len); information_buff[2] = sati_get_ata_lba_high_ext(register_fis); information_buff[3] = sati_get_ata_lba_mid_ext(register_fis); information_buff[4] = sati_get_ata_lba_low_ext(register_fis); information_buff[5] = sati_get_ata_lba_high(register_fis); information_buff[6] = sati_get_ata_lba_mid(register_fis); information_buff[7] = sati_get_ata_lba_low(register_fis); sati_set_sense_data_byte( sense_data, sense_len, 0, SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE ); sati_scsi_common_descriptor_sense_construct( sequence, scsi_io, sense_data, sense_len, sense_key, additional_sense_code, additional_sense_code_qualifier, information_buff ); } /** * @brief This method will construct the sense data buffer in the user's * sense data buffer location. Additionally, it will set the user's * SCSI status. This is used for uncorrectable read errors. * * @param[in] sequence This parameter specifies the translation sequence * for which to construct the sense data. * @param[in,out] scsi_io This parameter specifies the user's IO request * for which to construct the sense data. * @param[in] ata_io This parameter is a pointer to the ATA IO data used * to get the ATA register fis. * @param[in] scsi_status This parameter specifies the SCSI status * value for the user's IO request. * @param[in] sense_key This parameter specifies the sense key to * be set for the user's IO request. * @param[in] additional_sense_code This parameter specifies the * additional sense code (ASC) key to be set for the user's * IO request. * @param[in] additional_sense_code_qualifier This parameter specifies * the additional sense code qualifier (ASCQ) key to be set * for the user's IO request. * * @return none */ static void sati_scsi_read_error_fixed_sense_construct( SATI_TRANSLATOR_SEQUENCE_T * sequence, void * scsi_io, void * ata_io, U8 scsi_status, U8 response_code, U8 sense_key, U8 additional_sense_code, U8 additional_sense_code_qualifier ) { U8 * sense_data; U32 sense_len; U8 valid = TRUE; U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io); sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len); if(sati_get_ata_lba_mid_ext(register_fis) > 0) { valid = FALSE; } sati_set_sense_data_byte(sense_data, sense_len, 3, sati_get_ata_lba_low_ext(register_fis)); sati_set_sense_data_byte(sense_data, sense_len, 4, sati_get_ata_lba_high(register_fis)); sati_set_sense_data_byte(sense_data, sense_len, 5, sati_get_ata_lba_mid(register_fis)); sati_set_sense_data_byte(sense_data, sense_len, 6, sati_get_ata_lba_low(register_fis)); sati_set_sense_data_byte( sense_data, sense_len, 0, (valid << 7) | SCSI_FIXED_CURRENT_RESPONSE_CODE ); sati_scsi_common_fixed_sense_construct( sense_data, sense_len, sense_key, additional_sense_code, additional_sense_code_qualifier ); } void sati_scsi_read_error_sense_construct( SATI_TRANSLATOR_SEQUENCE_T * sequence, void * scsi_io, void * ata_input_data, U8 scsi_status, U8 sense_key, U8 additional_sense_code, U8 additional_sense_code_qualifier ) { U8 response_code; response_code = sati_scsi_get_sense_data_response_code(sequence); switch (response_code) { case SCSI_FIXED_CURRENT_RESPONSE_CODE: case SCSI_FIXED_DEFERRED_RESPONSE_CODE: sati_scsi_read_error_fixed_sense_construct(sequence, scsi_io, ata_input_data, scsi_status, response_code, sense_key, additional_sense_code, additional_sense_code_qualifier); break; case SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE: case SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE: sati_scsi_read_error_descriptor_sense_construct(sequence, scsi_io, ata_input_data, scsi_status, response_code, sense_key, additional_sense_code, additional_sense_code_qualifier); break; } sequence->is_sense_response_set = TRUE; } /* * @brief This method builds the scsi response data for a sata task management * request. * * @param[in] sequence This parameter specifies the translation sequence * for which to construct the sense data. * @param[in,out] scsi_io This parameter specifies the user's IO request * for which to construct the sense data. * @param[in] response_data The response status for the task management * request. */ void sati_scsi_response_data_construct( SATI_TRANSLATOR_SEQUENCE_T * sequence, void * scsi_io, U8 response_data ) { #ifdef SATI_TRANSPORT_SUPPORTS_SAS SCI_SSP_RESPONSE_IU_T * rsp_iu = (SCI_SSP_RESPONSE_IU_T*) sati_cb_get_response_iu_address(scsi_io); rsp_iu->data_present = 0x01; rsp_iu->response_data_length[3] = sizeof(U32); rsp_iu->status = 0; ((U8 *)rsp_iu->data)[3] = response_data; #else #endif // SATI_TRANSPORT_SUPPORTS_SAS } /** * @brief This method checks to make sure that the translation isn't * exceeding the allocation length specified in the CDB prior * to retrieving the payload data byte from the user's buffer. * * @param[in,out] scsi_io This parameter specifies the user's IO request * for which to set the user payload data byte. * @param[in] byte_offset This parameter specifies the offset into * the user's payload buffer at which to write the supplied * value. * @param[in] value This parameter specifies the memory location into * which to read the value from the user's payload buffer. * * @return none */ void sati_get_data_byte( SATI_TRANSLATOR_SEQUENCE_T * sequence, void * scsi_io, U32 byte_offset, U8 * value ) { if (byte_offset < sequence->allocation_length) sati_cb_get_data_byte(scsi_io, byte_offset, value); } /** * @brief This method checks to make sure that the translation isn't * exceeding the allocation length specified in the CDB while * translating payload data into the user's buffer. * * @param[in] sequence This parameter specifies the translation sequence * for which to set the user payload data byte. * @param[in,out] scsi_io This parameter specifies the user's IO request * for which to set the user payload data byte. * @param[in] byte_offset This parameter specifies the offset into * the user's payload buffer at which to write the supplied * value. * @param[in] value This parameter specifies the new value to be * written out into the user's payload buffer. * * @return none */ void sati_set_data_byte( SATI_TRANSLATOR_SEQUENCE_T * sequence, void * scsi_io, U32 byte_offset, U8 value ) { if (byte_offset < sequence->allocation_length) { sequence->number_data_bytes_set++; sati_cb_set_data_byte(scsi_io, byte_offset, value); } } /** * @brief This method checks to make sure that the translation isn't * exceeding the allocation length specified in the CDB while * translating payload data into the user's buffer. * * @param[in] sequence This parameter specifies the translation sequence * for which to set the user payload data dword. * @param[in,out] scsi_io This parameter specifies the user's IO request * for which to set the user payload data dword. * @param[in] byte_offset This parameter specifies the offset into * the user's payload buffer at which to write the supplied * value. * @param[in] value This parameter specifies the new value to be * written out into the user's payload buffer. * * @return none */ void sati_set_data_dword( SATI_TRANSLATOR_SEQUENCE_T * sequence, void * scsi_io, U32 byte_offset, U32 value ) { /// @todo Check to ensure that the bytes appear correctly (SAS Address). sati_set_data_byte(sequence, scsi_io, byte_offset, (U8)value & 0xFF); byte_offset++; sati_set_data_byte(sequence, scsi_io, byte_offset, (U8)(value >> 8) & 0xFF); byte_offset++; sati_set_data_byte(sequence, scsi_io, byte_offset, (U8)(value >> 16) & 0xFF); byte_offset++; sati_set_data_byte(sequence, scsi_io, byte_offset, (U8)(value >> 24) & 0xFF); } /** * @brief This method will construct the ATA flush cache command. * * @pre It is expected that the user has properly set the current contents * of the register FIS to 0. * * @param[out] ata_io This parameter specifies the ATA IO request structure * for which to build the FLUSH CACHE command. * @param[in] sequence This parameter specifies the translator sequence * for which the command is being constructed. * * @return none. */ void sati_ata_flush_cache_construct( void * ata_io, SATI_TRANSLATOR_SEQUENCE_T * sequence ) { U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); sati_set_ata_command(register_fis, ATA_FLUSH_CACHE); sati_ata_non_data_command(ata_io, sequence); } /** * @brief This method will construct the ATA standby immediate command. * * @pre It is expected that the user has properly set the current contents * of the register FIS to 0. * * @param[out] ata_io This parameter specifies the ATA IO request structure * for which to build the STANDBY IMMEDIATE command. * @param[in] sequence This parameter specifies the translator sequence * for which the command is being constructed. * * @param[in] count This parameter specifies the time period programmed * into the Standby Timer. See ATA8 spec for more details * @return none. */ void sati_ata_standby_construct( void * ata_io, SATI_TRANSLATOR_SEQUENCE_T * sequence, U16 count ) { U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); sati_set_ata_command(register_fis, ATA_STANDBY); sati_set_ata_sector_count(register_fis, count); sequence->device->ata_standby_timer = (U8) count; sati_ata_non_data_command(ata_io, sequence); } /** * @brief This method will construct the ATA standby immediate command. * * @pre It is expected that the user has properly set the current contents * of the register FIS to 0. * * @param[out] ata_io This parameter specifies the ATA IO request structure * for which to build the STANDBY IMMEDIATE command. * @param[in] sequence This parameter specifies the translator sequence * for which the command is being constructed. * * @return none. */ void sati_ata_standby_immediate_construct( void * ata_io, SATI_TRANSLATOR_SEQUENCE_T * sequence ) { U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); sati_set_ata_command(register_fis, ATA_STANDBY_IMMED); sati_ata_non_data_command(ata_io, sequence); } /** * @brief This method will construct the ATA idle immediate command. * * @pre It is expected that the user has properly set the current contents * of the register FIS to 0. * * @param[out] ata_io This parameter specifies the ATA IO request structure * for which to build the IDLE IMMEDIATE command. * @param[in] sequence This parameter specifies the translator sequence * for which the command is being constructed. * * @return none. */ void sati_ata_idle_immediate_construct( void * ata_io, SATI_TRANSLATOR_SEQUENCE_T * sequence ) { U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); sati_set_ata_command(register_fis, ATA_IDLE_IMMED); sati_set_ata_features(register_fis, 0x00); sati_set_ata_sector_count(register_fis, 0x00); sati_set_ata_lba_high(register_fis, 0x00); sati_set_ata_lba_mid(register_fis, 0x00); sati_set_ata_lba_low(register_fis, 0x00); sati_ata_non_data_command(ata_io, sequence); } /** * @brief This method will construct the ATA idle immediate command for Unload Features. * * @pre It is expected that the user has properly set the current contents * of the register FIS to 0. * * @param[out] ata_io This parameter specifies the ATA IO request structure * for which to build the IDLE IMMEDIATE command. * @param[in] sequence This parameter specifies the translator sequence * for which the command is being constructed. * * @return none. */ void sati_ata_idle_immediate_unload_construct( void * ata_io, SATI_TRANSLATOR_SEQUENCE_T * sequence ) { U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); sati_set_ata_command(register_fis, ATA_IDLE_IMMED); sati_set_ata_features(register_fis, 0x44); sati_set_ata_sector_count(register_fis, 0x00); sati_set_ata_lba_high(register_fis, 0x55); sati_set_ata_lba_mid(register_fis, 0x4E); sati_set_ata_lba_low(register_fis, 0x4C); sati_ata_non_data_command(ata_io, sequence); } /** * @brief This method will construct the ATA IDLE command.\ * * @pre It is expected that the user has properly set the current contents * of the register FIS to 0. * * @param[out] ata_io This parameter specifies the ATA IO request structure * for which to build the ATA IDLE command. * @param[in] sequence This parameter specifies the translator sequence * for which the command is being constructed. * * @return none. */ void sati_ata_idle_construct( void * ata_io, SATI_TRANSLATOR_SEQUENCE_T * sequence ) { U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); sati_set_ata_command(register_fis, ATA_IDLE); sati_set_ata_features(register_fis, 0x00); sati_set_ata_sector_count(register_fis, 0x00); sequence->device->ata_standby_timer = 0x00; sati_set_ata_lba_high(register_fis, 0x00); sati_set_ata_lba_mid(register_fis, 0x00); sati_set_ata_lba_low(register_fis, 0x00); sati_ata_non_data_command(ata_io, sequence); } /** * @brief This method will construct the ATA MEDIA EJECT command. * * @pre It is expected that the user has properly set the current contents * of the register FIS to 0. * * @param[out] ata_io This parameter specifies the ATA IO request structure * for which to build the MEDIA EJCT command. * @param[in] sequence This parameter specifies the translator sequence * for which the command is being constructed. * * @return none. */ void sati_ata_media_eject_construct( void * ata_io, SATI_TRANSLATOR_SEQUENCE_T * sequence ) { U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); sati_set_ata_command(register_fis, ATA_MEDIA_EJECT); sati_ata_non_data_command(ata_io, sequence); } /** * @brief This method will construct the ATA read verify sector(s) command. * * @pre It is expected that the user has properly set the current contents * of the register FIS to 0. * * @param[out] ata_io This parameter specifies the ATA IO request structure * for which to build the ATA READ VERIFY SECTOR(S) command. * @param[in] sequence This parameter specifies the translator sequence * for which the command is being constructed. * * @return none. */ void sati_ata_read_verify_sectors_construct( void * ata_io, SATI_TRANSLATOR_SEQUENCE_T * sequence ) { U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); sati_set_ata_command(register_fis, ATA_READ_VERIFY_SECTORS); //According to SAT-2 (v7) 9.11.3 sati_set_ata_sector_count(register_fis, 1); //According to SAT-2 (v7) 9.11.3, set LBA to a value between zero and the //maximum LBA supported by the ATA device in its current configuration. //From the unit test, it seems we have to set LBA to a non-zero value. sati_set_ata_lba_low(register_fis, 1); sati_ata_non_data_command(ata_io, sequence); } /** * @brief This method will construct a ATA SMART Return Status command so the * status of the ATA device can be returned. The status of the SMART * threshold will be returned by this command. * * @return N/A * */ void sati_ata_smart_return_status_construct( void * ata_io, SATI_TRANSLATOR_SEQUENCE_T * sequence, U8 feature_value ) { U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); sati_set_ata_command(register_fis, ATA_SMART); sati_set_ata_features(register_fis, feature_value); sati_set_ata_lba_high(register_fis, 0xC2); sati_set_ata_lba_mid(register_fis, 0x4F); sati_ata_non_data_command(ata_io, sequence); } /** * @brief This method will construct a ATA SMART Return Status command so the * status of the ATA device can be returned. The status of the SMART * threshold will be returned by this command. * * @return N/A * */ void sati_ata_smart_read_log_construct( void * ata_io, SATI_TRANSLATOR_SEQUENCE_T * sequence, U8 log_address, U32 transfer_length ) { U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); sati_set_ata_command(register_fis, ATA_SMART); sati_set_ata_features(register_fis, ATA_SMART_SUB_CMD_READ_LOG); sati_set_ata_lba_high(register_fis, 0xC2); sati_set_ata_lba_mid(register_fis, 0x4F); sati_set_ata_lba_low(register_fis, log_address); sequence->data_direction = SATI_DATA_DIRECTION_IN; sequence->protocol = SAT_PROTOCOL_PIO_DATA_IN; sequence->ata_transfer_length = transfer_length; } /** * @brief This method will construct a Write Uncorrectable ATA command that * will write one sector with a pseudo or flagged error. The type of * error is specified by the feature value. * * @return N/A * */ void sati_ata_write_uncorrectable_construct( void * ata_io, SATI_TRANSLATOR_SEQUENCE_T * sequence, U8 feature_value ) { U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); sati_set_ata_command(register_fis, ATA_WRITE_UNCORRECTABLE); sati_set_ata_features(register_fis, feature_value); sati_set_ata_sector_count(register_fis, 0x0001); sati_ata_non_data_command(ata_io, sequence); } /** * @brief This method will construct a Mode Select ATA SET FEATURES command * For example, Enable/Disable Write Cache, Enable/Disable Read Ahead * * @return N/A * */ void sati_ata_set_features_construct( void * ata_io, SATI_TRANSLATOR_SEQUENCE_T * sequence, U8 feature ) { U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); sati_set_ata_command(register_fis, ATA_SET_FEATURES); sati_set_ata_features(register_fis, feature); sati_ata_non_data_command(ata_io, sequence); } /** * @brief This method will construct a Read Log ext ATA command that * will request a log page based on the log_address. * * @param[in] log_address This parameter specifies the log page * to be returned from Read Log Ext. * * @param[in] transfer_length This parameter specifies the size of the * log page response returned by Read Log Ext. * * @return N/A * */ void sati_ata_read_log_ext_construct( void * ata_io, SATI_TRANSLATOR_SEQUENCE_T * sequence, U8 log_address, U32 transfer_length ) { U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); sati_set_ata_command(register_fis, ATA_READ_LOG_EXT); sati_set_ata_lba_low(register_fis, log_address); sati_set_ata_lba_mid(register_fis, 0x00); sati_set_ata_lba_mid_exp(register_fis, 0x00); sati_set_ata_sector_count(register_fis, 0x01); sequence->data_direction = SATI_DATA_DIRECTION_IN; sequence->protocol = SAT_PROTOCOL_PIO_DATA_IN; sequence->ata_transfer_length = transfer_length; } /** * @brief This method will check if the ATA device is in the stopped power * state. This is used for all medium access commands for SAT * compliance. See SAT2r07 section 9.11.1 * * @param[in] sequence - SATI sequence data with the device state. * * @return TRUE If device is stopped * */ BOOL sati_device_state_stopped( SATI_TRANSLATOR_SEQUENCE_T * sequence, void * scsi_io ) { if(sequence->device->state == SATI_DEVICE_STATE_STOPPED) { sati_scsi_sense_data_construct( sequence, scsi_io, SCSI_STATUS_CHECK_CONDITION, SCSI_SENSE_NOT_READY , SCSI_ASC_INITIALIZING_COMMAND_REQUIRED, SCSI_ASCQ_INITIALIZING_COMMAND_REQUIRED ); return TRUE; } return FALSE; } /** * @brief This method will construct a ATA Read Buffer command that * will request PIO in data containing the target device's buffer. * * @param[out] ata_io This parameter specifies the ATA IO request structure * for which to build the ATA READ VERIFY SECTOR(S) command. * @param[in] sequence This parameter specifies the translator sequence * for which the command is being constructed. * @return N/A * */ void sati_ata_read_buffer_construct( void * ata_io, SATI_TRANSLATOR_SEQUENCE_T * sequence ) { U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); sati_set_ata_command(register_fis, ATA_READ_BUFFER); sequence->data_direction = SATI_DATA_DIRECTION_IN; sequence->protocol = SAT_PROTOCOL_PIO_DATA_IN; sequence->ata_transfer_length = 512; } /** * @brief This method will construct a ATA Write Buffer command that * will send PIO out data to the target device's buffer. * * @param[out] ata_io This parameter specifies the ATA IO request structure * for which to build the ATA READ VERIFY SECTOR(S) command. * @param[in] sequence This parameter specifies the translator sequence * for which the command is being constructed. * @return N/A * */ void sati_ata_write_buffer_construct( void * ata_io, SATI_TRANSLATOR_SEQUENCE_T * sequence ) { U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); sati_set_ata_command(register_fis, ATA_WRITE_BUFFER); sequence->data_direction = SATI_DATA_DIRECTION_OUT; sequence->protocol = SAT_PROTOCOL_PIO_DATA_OUT; sequence->ata_transfer_length = 512; } /** * @brief This method will construct a ATA Download Microcode command that * will send PIO out data containing new firmware for the target drive. * * @param[out] ata_io This parameter specifies the ATA IO request structure * for which to build the ATA READ VERIFY SECTOR(S) command. * @param[in] sequence This parameter specifies the translator sequence * for which the command is being constructed. * @param[in] mode This parameter specifies the download microcode sub-command * code. * @param[in] allocation_length This parameter specifies the number of bytes * being sent to the target device. * @param[in] buffer_offset This parameter specifies the buffer offset for the * data sent to the target device. * * @return N/A * */ void sati_ata_download_microcode_construct( void * ata_io, SATI_TRANSLATOR_SEQUENCE_T * sequence, U8 mode, U32 allocation_length, U32 buffer_offset ) { U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io); U32 allocation_blocks = allocation_length >> 9; U32 buffer_blkoffset = buffer_offset >> 9; sati_set_ata_command(register_fis, ATA_DOWNLOAD_MICROCODE); sati_set_ata_features(register_fis, mode); if(mode == ATA_MICROCODE_DOWNLOAD_SAVE) { sati_set_ata_sector_count(register_fis, (U8) (allocation_length >> 9)); sati_set_ata_lba_low(register_fis, (U8) (allocation_length >> 17)); } else //mode == 0x03 { sati_set_ata_sector_count(register_fis, (U8) (allocation_blocks & 0xff)); sati_set_ata_lba_low(register_fis, (U8) ((allocation_blocks >> 8) & 0xff)); sati_set_ata_lba_mid(register_fis, (U8) (buffer_blkoffset & 0xff)); sati_set_ata_lba_high(register_fis, (U8) ((buffer_blkoffset >> 8) & 0xff)); } if((allocation_length == 0) && (buffer_offset == 0)) { sati_ata_non_data_command(ata_io, sequence); } else { sequence->data_direction = SATI_DATA_DIRECTION_OUT; sequence->protocol = SAT_PROTOCOL_PIO_DATA_OUT; sequence->ata_transfer_length = allocation_length; } }
Upload File
Create Folder