summaryrefslogtreecommitdiffstats
path: root/sys/dev/isci/scil/sati_unmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/isci/scil/sati_unmap.c')
-rw-r--r--sys/dev/isci/scil/sati_unmap.c609
1 files changed, 609 insertions, 0 deletions
diff --git a/sys/dev/isci/scil/sati_unmap.c b/sys/dev/isci/scil/sati_unmap.c
new file mode 100644
index 0000000..cc8327b
--- /dev/null
+++ b/sys/dev/isci/scil/sati_unmap.c
@@ -0,0 +1,609 @@
+/*-
+ * 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 the method implementations required to
+ * translate the SCSI unmap command.
+ */
+
+#if !defined(DISABLE_SATI_UNMAP)
+
+#include <dev/isci/scil/sati_unmap.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+#include <dev/isci/scil/sati_util.h>
+#include <dev/isci/scil/intel_ata.h>
+#include <dev/isci/scil/intel_scsi.h>
+#include <dev/isci/scil/intel_sat.h>
+
+//******************************************************************************
+//* P R I V A T E M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method translates a given number of DSM
+ * requests into DSM blocks based on the devices logical block size
+ *
+ * @return Number of DSM blocks required for the DSM descriptor count
+ */
+U32 sati_unmap_calculate_dsm_blocks(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ U32 dsm_descriptor_count
+)
+{
+ U32 blocks = (dsm_descriptor_count * sizeof(TRIM_PAIR))/sequence->device->logical_block_size;
+ if ((dsm_descriptor_count * sizeof(TRIM_PAIR)) % sequence->device->logical_block_size)
+ {
+ blocks++;
+ }
+ return blocks;
+}
+
+/**
+ * @brief This method performs the SCSI Unmap command translation
+ * functionality.
+ * This includes:
+ * - setting the command register
+ * - setting the device head register
+ * - filling in fields in the SATI_TRANSLATOR_SEQUENCE object.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @return Indicate if the method was successfully completed.
+ * @retval SATI_SUCCESS This is returned in all other cases.
+ */
+SATI_STATUS sati_unmap_construct(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io,
+ U32 sector_count
+)
+{
+ U8 * h2d_register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+ U8 * d2h_register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
+
+ sati_set_ata_command(h2d_register_fis, ATA_DATA_SET_MANAGEMENT);
+ sati_set_ata_features(h2d_register_fis, 0x01);
+ sati_set_ata_sector_count(h2d_register_fis, (U8)sector_count);
+ sati_set_ata_device_head(h2d_register_fis, ATA_DEV_HEAD_REG_LBA_MODE_ENABLE);
+
+ // Set the completion status since the core will not do that for
+ // the udma fast path.
+ sati_set_ata_status(d2h_register_fis, 0x00);
+
+ // Set up the direction and protocol for SCIC
+ sequence->data_direction = SATI_DATA_DIRECTION_OUT;
+ sequence->protocol = SAT_PROTOCOL_UDMA_DATA_OUT;
+ // The UNMAP translation will always require a callback
+ // on every response so it can free memory if an error
+ // occurs.
+ sequence->is_translate_response_required = TRUE;
+
+ ASSERT(sector_count < 0x100);
+
+ return SATI_SUCCESS;
+}
+
+/**
+ * @brief This method updates the unmap sequence state to the next
+ * unmap descriptor
+ *
+ * @return Indicate if the method was successfully completed.
+ * @retval SATI_SUCCESS This is returned in all other cases.
+ */
+SATI_STATUS sati_unmap_load_next_descriptor(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io
+)
+{
+ SATI_UNMAP_PROCESSING_STATE_T * unmap_process_state;
+ U32 index;
+ U8 unmap_block_descriptor[16];
+
+ unmap_process_state = &sequence->command_specific_data.unmap_process_state;
+
+ // Load the next descriptor
+ for(index = unmap_process_state->current_unmap_block_descriptor_index;
+ index < unmap_process_state->current_unmap_block_descriptor_index +
+ SATI_UNMAP_SIZEOF_SCSI_UNMAP_BLOCK_DESCRIPTOR;
+ index++)
+ {
+ sati_get_data_byte(sequence,
+ scsi_io,
+ index,
+ &unmap_block_descriptor[index-unmap_process_state->current_unmap_block_descriptor_index]);
+ }
+
+ // Update the internal state for the next translation pass
+ unmap_process_state->current_lba_count = (unmap_block_descriptor[8] << 24) |
+ (unmap_block_descriptor[9] << 16) |
+ (unmap_block_descriptor[10] << 8) |
+ (unmap_block_descriptor[11]);
+ unmap_process_state->current_lba = ((SATI_LBA)(unmap_block_descriptor[0]) << 56) |
+ ((SATI_LBA)(unmap_block_descriptor[1]) << 48) |
+ ((SATI_LBA)(unmap_block_descriptor[2]) << 40) |
+ ((SATI_LBA)(unmap_block_descriptor[3]) << 32) |
+ ((SATI_LBA)(unmap_block_descriptor[4]) << 24) |
+ ((SATI_LBA)(unmap_block_descriptor[5]) << 16) |
+ ((SATI_LBA)(unmap_block_descriptor[6]) << 8) |
+ ((SATI_LBA)(unmap_block_descriptor[7]));
+ unmap_process_state->next_lba = 0;
+
+ // Update the index for the next descriptor to translate
+ unmap_process_state->current_unmap_block_descriptor_index += SATI_UNMAP_SIZEOF_SCSI_UNMAP_BLOCK_DESCRIPTOR;
+
+ return SATI_SUCCESS;
+}
+
+/**
+ * @brief This method determines the max number of blocks of DSM data
+ * that can be satisfied by the device and the SW
+ *
+ * @return Number of blocks supported
+ * @retval Number of blocks supported
+ */
+U32 sati_unmap_get_max_buffer_size_in_blocks(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence
+)
+{
+ // Currently this SATI implementation only supports a single
+ // 4k block of memory for the DMA write operation for simplicity
+ // (no need to handle more than one SG element).
+ // Since most run time UNMAP requests use 1K or less buffer space,
+ // there is no performance degradation with only supporting a
+ // single physical page. For best results allocate the maximum
+ // amount of memory the device can handle up to the maximum of 4K.
+ return MIN(SATI_DSM_MAX_BUFFER_SIZE/sequence->device->logical_block_size,
+ sequence->device->max_lba_range_entry_blocks);
+}
+
+/**
+ * @brief This method will be called before starting the first unmap translation
+ *
+ * @return Indicate if the translation was successful.
+ * @retval SATI_SUCCESS This is returned if the command translation was
+ * successful and no further processing.
+ * @retval SATI_COMPLETE - The initial processing was completed successfully
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA - Failed the initial processing
+ */
+SATI_STATUS sati_unmap_initial_processing(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ SATI_UNMAP_PROCESSING_STATE_T * unmap_process_state;
+ U8 * cdb;
+ U16 unmap_length;
+ U32 descriptor_length;
+ U32 index;
+ U32 max_dsm_blocks;
+ U8 unmap_param_list[8];
+
+ unmap_process_state = &sequence->command_specific_data.unmap_process_state;
+
+ // Set up the sequence type for unmap translation
+ sequence->type = SATI_SEQUENCE_UNMAP;
+
+ // Make sure the device is TRIM capable
+ if ((sequence->device->capabilities & SATI_DEVICE_CAP_DSM_TRIM_SUPPORT)
+ != SATI_DEVICE_CAP_DSM_TRIM_SUPPORT)
+ {
+ // Can't send TRIM request to device that does not support it
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_INVALID_FIELD_IN_CDB,
+ SCSI_ASCQ_INVALID_FIELD_IN_CDB
+ );
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+
+ // get the amount of data being sent from the cdb
+ cdb = sati_cb_get_cdb_address(scsi_io);
+ unmap_length = (sati_get_cdb_byte(cdb, 7) << 8) | sati_get_cdb_byte(cdb, 8);
+
+ // If nothing has been requested return success now.
+ if (unmap_length == 0)
+ {
+ // SAT: This is not an error
+ return SATI_SUCCESS;
+ }
+ if (unmap_length < SATI_UNMAP_SIZEOF_SCSI_UNMAP_PARAMETER_LIST)
+ {
+ // Not enough length specified in the CDB
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_INVALID_FIELD_IN_CDB,
+ SCSI_ASCQ_INVALID_FIELD_IN_CDB
+ );
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+
+ sequence->allocation_length = unmap_length;
+
+ // Get the unmap parameter header
+ for(index = 0; index < SATI_UNMAP_SIZEOF_SCSI_UNMAP_PARAMETER_LIST; index++)
+ {
+ sati_get_data_byte(sequence, scsi_io, index, &unmap_param_list[index]);
+ }
+ descriptor_length = (unmap_param_list[2] << 8) | unmap_param_list[3];
+
+ // Check length again
+ if (descriptor_length == 0)
+ {
+ // SAT: This is not an error
+ return SATI_SUCCESS;
+ }
+
+ if ((U32)(unmap_length - SATI_UNMAP_SIZEOF_SCSI_UNMAP_PARAMETER_LIST) < descriptor_length)
+ {
+ // Not enough length specified in the CDB
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_INVALID_FIELD_IN_CDB,
+ SCSI_ASCQ_INVALID_FIELD_IN_CDB
+ );
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+
+ // Save the maximum unmap block descriptors in this request
+ unmap_process_state->max_unmap_block_descriptors =
+ descriptor_length/SATI_UNMAP_SIZEOF_SCSI_UNMAP_BLOCK_DESCRIPTOR;
+
+ // Determine the maximum size of the write buffer that will be required
+ // for the translation in terms of number of blocks
+ max_dsm_blocks = sati_unmap_get_max_buffer_size_in_blocks(sequence);
+
+ // Save the maximum number of DSM descriptors we can send during the translation
+ unmap_process_state->max_lba_range_entries =
+ (max_dsm_blocks*sequence->device->logical_block_size)/sizeof(TRIM_PAIR);
+
+ // Get the write buffer for the translation
+ sati_cb_allocate_dma_buffer(
+ scsi_io,
+ max_dsm_blocks*sequence->device->logical_block_size,
+ &(unmap_process_state->virtual_unmap_buffer),
+ &(unmap_process_state->physical_unmap_buffer_low),
+ &(unmap_process_state->physical_unmap_buffer_high));
+
+ // Makes sure we have a buffer
+ if (unmap_process_state->virtual_unmap_buffer == NULL)
+ {
+ // Resource failure
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ABORTED_COMMAND,
+ SCSI_ASC_NO_ADDITIONAL_SENSE,
+ SCSI_ASCQ_NO_ADDITIONAL_SENSE
+ );
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+
+ // Get the first SGL entry. This code will only use one 4K page so will
+ // only utilize the first sge.
+ sati_cb_sgl_next_sge(scsi_io,
+ ata_io,
+ NULL,
+ &(unmap_process_state->unmap_buffer_sgl_pair));
+
+ // Load the first descriptor to start the translation loop
+ unmap_process_state->current_unmap_block_descriptor_index =
+ SATI_UNMAP_SIZEOF_SCSI_UNMAP_PARAMETER_LIST;
+ sati_unmap_load_next_descriptor(sequence,scsi_io);
+
+ // Next state will be incomplete since translation
+ // will require a callback and possibly more requests.
+ sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE;
+
+ return SATI_COMPLETE;
+}
+
+/**
+ * @brief This method will process each unmap sequence.
+ *
+ * @return Indicate if the translation was successful.
+ * @retval SATI_SUCCESS
+ */
+SATI_STATUS sati_unmap_process(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ SATI_UNMAP_PROCESSING_STATE_T * unmap_process_state;
+ SATI_LBA dsm_descriptor_lba_count;
+ U32 dsm_descriptor;
+ U32 dsm_bytes;
+ U32 dsm_remainder_bytes;
+ U32 dsm_blocks;
+ U32 max_dsm_blocks;
+
+ unmap_process_state = &sequence->command_specific_data.unmap_process_state;
+
+ // Set up the starting address of the buffer for this portion of the translation
+ unmap_process_state->current_dsm_descriptor = unmap_process_state->virtual_unmap_buffer;
+ dsm_descriptor = 0;
+
+ // Translate as much as we can
+ while ((dsm_descriptor < unmap_process_state->max_lba_range_entries) &&
+ (unmap_process_state->current_lba_count > 0)) {
+ // See if the LBA count will fit in to a single descriptor
+ if (unmap_process_state->current_lba_count > SATI_DSM_MAX_SECTOR_COUNT) {
+ // Can't fit all of the lbas for this descriptor in to
+ // one DSM request. Adjust the current LbaCount and total
+ // remaining for the next descriptor
+ dsm_descriptor_lba_count = SATI_DSM_MAX_SECTOR_COUNT;
+ unmap_process_state->current_lba_count -= SATI_DSM_MAX_SECTOR_COUNT;
+ unmap_process_state->next_lba =
+ unmap_process_state->current_lba + SATI_DSM_MAX_SECTOR_COUNT;
+ } else {
+ // It all fits in to one descriptor
+ dsm_descriptor_lba_count = unmap_process_state->current_lba_count;
+ unmap_process_state->current_lba_count = 0;
+ }
+
+ // Fill in the ATA DSM descriptor
+ ((PTRIM_PAIR)(unmap_process_state->current_dsm_descriptor))->sector_address =
+ unmap_process_state->current_lba;
+ ((PTRIM_PAIR)(unmap_process_state->current_dsm_descriptor))->sector_count =
+ dsm_descriptor_lba_count;
+
+ // See if we can move on to the next descriptor
+ if (unmap_process_state->current_lba_count == 0) {
+ // See if there is another descriptor
+ --unmap_process_state->max_unmap_block_descriptors;
+ if (unmap_process_state->max_unmap_block_descriptors > 0) {
+ // Move on to the next descriptor
+ sati_unmap_load_next_descriptor(sequence,scsi_io);
+ }
+ } else {
+ // Move to the next LBA in this descriptor
+ unmap_process_state->current_lba = unmap_process_state->next_lba;
+ }
+
+ // Make sure the LBA does not exceed 48 bits...
+ ASSERT(unmap_process_state->current_lba <= SATI_DSM_MAX_SECTOR_ADDRESS);
+
+ // Increment the number of descriptors used and point to the next entry
+ dsm_descriptor++;
+ unmap_process_state->current_dsm_descriptor =
+ (U8 *)(unmap_process_state->current_dsm_descriptor) + sizeof(TRIM_PAIR);
+ }
+
+ // Calculate number of blocks we have filled in
+ dsm_blocks = sati_unmap_calculate_dsm_blocks(sequence,dsm_descriptor);
+ dsm_bytes = dsm_blocks * sequence->device->logical_block_size;
+ max_dsm_blocks = sati_unmap_get_max_buffer_size_in_blocks(sequence);
+
+ // The current_dsm_descriptor points to the next location in the buffer
+ // Get the remaining bytes from the last translated descriptor
+ // to the end of the 4k buffer.
+ dsm_remainder_bytes = sequence->device->logical_block_size;
+ dsm_remainder_bytes -= (U32)((POINTER_UINT)unmap_process_state->current_dsm_descriptor &
+ (sequence->device->logical_block_size-1));
+
+ // If there was no remainder, the complete buffer was filled in.
+ if (dsm_remainder_bytes != sequence->device->logical_block_size)
+ {
+ // Add on the remaining unfilled blocks
+ dsm_remainder_bytes += (sequence->device->logical_block_size * (max_dsm_blocks - dsm_blocks));
+
+ // According to ATA-8, if the DSM buffer is not completely filled with
+ // valid DSM descriptor data, the remaining portion of the
+ // buffer must be filled in with zeros.
+ memset((U8 *)unmap_process_state->current_dsm_descriptor, 0, dsm_remainder_bytes);
+ }
+
+ // Tell scic to utilize this sgl pair for write DMA processing of
+ // the SCSI UNMAP translation with the total number of bytes for this transfer
+ sati_cb_sge_write(unmap_process_state->unmap_buffer_sgl_pair,
+ unmap_process_state->physical_unmap_buffer_low,
+ unmap_process_state->physical_unmap_buffer_high,
+ dsm_bytes);
+
+ // Construct the unmap ATA request
+ sati_unmap_construct(sequence,
+ scsi_io,
+ ata_io,
+ dsm_blocks);
+
+ // Determine sequence next state based on whether there is more translation
+ // to complete
+ if (unmap_process_state->current_lba_count == 0)
+ {
+ // used for completion routine to determine if there is more processing
+ sequence->state = SATI_SEQUENCE_STATE_FINAL;
+ }
+ // This requests has already translated the SGL, have SCIC skip SGL translataion
+ return SATI_SUCCESS_SGL_TRANSLATED;
+}
+
+//******************************************************************************
+//* P U B L I C M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method will handle termination of the
+ * SCSI unmap translation and frees previously allocated
+ * dma buffer.
+ *
+ * @return None
+ */
+void sati_unmap_terminate(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ SATI_UNMAP_PROCESSING_STATE_T * unmap_process_state;
+ unmap_process_state = &sequence->command_specific_data.unmap_process_state;
+
+ if (unmap_process_state->virtual_unmap_buffer != NULL)
+ {
+ sati_cb_free_dma_buffer(scsi_io, unmap_process_state->virtual_unmap_buffer);
+ unmap_process_state->virtual_unmap_buffer = NULL;
+ }
+}
+
+/**
+ * @brief This method will translate the SCSI Unmap command
+ * into corresponding ATA commands. Depending upon the capabilities
+ * supported by the target different ATA commands can be selected.
+ * Additionally, in some cases more than a single ATA command may
+ * be required.
+ *
+ * @return Indicate if the command translation succeeded.
+ * @retval SATI_SUCCESS This is returned if the command translation was
+ * successful.
+ * @retval SATI_COMPLETE This is returned if the command translation was
+ * successful and no ATA commands need to be set.
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if
+ * sense data has been created as a result of something specified
+ * in the parameter data fields.
+ */
+SATI_STATUS sati_unmap_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+ SATI_UNMAP_PROCESSING_STATE_T * unmap_process_state;
+
+ unmap_process_state = &sequence->command_specific_data.unmap_process_state;
+
+ // Determine if this is the first step in the unmap sequence
+ if ( sequence->state == SATI_SEQUENCE_STATE_INITIAL )
+ {
+ status = sati_unmap_initial_processing(sequence,scsi_io,ata_io);
+ if (status != SATI_COMPLETE)
+ {
+ return status;
+ }
+ }
+ // Translate the next portion of the UNMAP request
+ return sati_unmap_process(sequence, scsi_io, ata_io);
+}
+
+/**
+ * @brief This method will translate the ATA command register FIS
+ * response into an appropriate SCSI response for Unmap.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_response().
+ *
+ * @return Indicate if the response translation succeeded.
+ * @retval SATI_SUCCESS This is returned if the command translation was
+ * successful.
+ * @retval SATI_COMPLETE This is returned if the command translation was
+ * successful and no ATA commands need to be set.
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if
+ * sense data has been created as a result of something specified
+ * in the parameter data fields.
+ */
+SATI_STATUS sati_unmap_translate_response(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
+ SATI_UNMAP_PROCESSING_STATE_T * unmap_process_state;
+ SATI_STATUS sati_status = SATI_COMPLETE;
+
+ unmap_process_state = &sequence->command_specific_data.unmap_process_state;
+
+ if (sati_get_ata_status(register_fis) & ATA_STATUS_REG_ERROR_BIT)
+ {
+ sequence->state = SATI_SEQUENCE_STATE_FINAL;
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ABORTED_COMMAND,
+ SCSI_ASC_NO_ADDITIONAL_SENSE,
+ SCSI_ASCQ_NO_ADDITIONAL_SENSE
+ );
+ // All done, terminate the translation
+ sati_unmap_terminate(sequence, scsi_io, ata_io);
+ }
+ else
+ {
+ if (sequence->state != SATI_SEQUENCE_STATE_INCOMPLETE)
+ {
+ // All done, terminate the translation
+ sati_unmap_terminate(sequence, scsi_io, ata_io);
+ }
+ else
+ {
+ // Still translating
+ sati_status = SATI_SEQUENCE_STATE_INCOMPLETE;
+ }
+ }
+ return sati_status;
+}
+
+#endif // !defined(DISABLE_SATI_UNMAP)
OpenPOWER on IntegriCloud