The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/isci/scil/sati_unmap.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause OR GPL-2.0
    3  *
    4  * This file is provided under a dual BSD/GPLv2 license.  When using or
    5  * redistributing this file, you may do so under either license.
    6  *
    7  * GPL LICENSE SUMMARY
    8  *
    9  * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
   10  *
   11  * This program is free software; you can redistribute it and/or modify
   12  * it under the terms of version 2 of the GNU General Public License as
   13  * published by the Free Software Foundation.
   14  *
   15  * This program is distributed in the hope that it will be useful, but
   16  * WITHOUT ANY WARRANTY; without even the implied warranty of
   17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   18  * General Public License for more details.
   19  *
   20  * You should have received a copy of the GNU General Public License
   21  * along with this program; if not, write to the Free Software
   22  * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
   23  * The full GNU General Public License is included in this distribution
   24  * in the file called LICENSE.GPL.
   25  *
   26  * BSD LICENSE
   27  *
   28  * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
   29  * All rights reserved.
   30  *
   31  * Redistribution and use in source and binary forms, with or without
   32  * modification, are permitted provided that the following conditions
   33  * are met:
   34  *
   35  *   * Redistributions of source code must retain the above copyright
   36  *     notice, this list of conditions and the following disclaimer.
   37  *   * Redistributions in binary form must reproduce the above copyright
   38  *     notice, this list of conditions and the following disclaimer in
   39  *     the documentation and/or other materials provided with the
   40  *     distribution.
   41  *
   42  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   43  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   44  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   45  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
   46  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   47  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   48  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   49  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   50  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   51  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
   52  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   53  */
   54 
   55 #include <sys/cdefs.h>
   56 __FBSDID("$FreeBSD$");
   57 
   58 /**
   59  * @file
   60  * @brief This file contains the method implementations required to
   61  *        translate the SCSI unmap command.
   62  */
   63 
   64 #if !defined(DISABLE_SATI_UNMAP)
   65 
   66 #include <dev/isci/scil/sati_unmap.h>
   67 #include <dev/isci/scil/sati_callbacks.h>
   68 #include <dev/isci/scil/sati_translator_sequence.h>
   69 #include <dev/isci/scil/sati_util.h>
   70 #include <dev/isci/scil/intel_ata.h>
   71 #include <dev/isci/scil/intel_scsi.h>
   72 #include <dev/isci/scil/intel_sat.h>
   73 
   74 //******************************************************************************
   75 //* P R I V A T E   M E T H O D S
   76 //******************************************************************************
   77 
   78 /**
   79  * @brief This method translates a given number of DSM
   80  *        requests into DSM blocks based on the devices logical block size
   81  *
   82  * @return Number of DSM blocks required for the DSM descriptor count
   83  */
   84 U32 sati_unmap_calculate_dsm_blocks(
   85    SATI_TRANSLATOR_SEQUENCE_T * sequence,
   86    U32                          dsm_descriptor_count
   87 )
   88 {
   89    U32 blocks = (dsm_descriptor_count * sizeof(TRIM_PAIR))/sequence->device->logical_block_size;
   90    if ((dsm_descriptor_count * sizeof(TRIM_PAIR)) % sequence->device->logical_block_size)
   91    {
   92        blocks++;
   93    }
   94    return blocks;
   95 }
   96 
   97 /**
   98  * @brief This method performs the SCSI Unmap command translation
   99  *        functionality.
  100  *        This includes:
  101  *        - setting the command register
  102  *        - setting the device head register
  103  *        - filling in fields in the SATI_TRANSLATOR_SEQUENCE object.
  104  *        For more information on the parameters passed to this method,
  105  *        please reference sati_translate_command().
  106  *
  107  * @return Indicate if the method was successfully completed.
  108  * @retval SATI_SUCCESS This is returned in all other cases.
  109  */
  110 SATI_STATUS sati_unmap_construct(
  111    SATI_TRANSLATOR_SEQUENCE_T * sequence,
  112    void                       * scsi_io,
  113    void                       * ata_io,
  114    U32                          sector_count
  115 )
  116 {
  117    U8 * h2d_register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
  118    U8 * d2h_register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
  119 
  120    sati_set_ata_command(h2d_register_fis, ATA_DATA_SET_MANAGEMENT);
  121    sati_set_ata_features(h2d_register_fis, 0x01);
  122    sati_set_ata_sector_count(h2d_register_fis, (U8)sector_count);
  123    sati_set_ata_device_head(h2d_register_fis, ATA_DEV_HEAD_REG_LBA_MODE_ENABLE);
  124 
  125    // Set the completion status since the core will not do that for
  126    // the udma fast path.
  127    sati_set_ata_status(d2h_register_fis, 0x00);
  128 
  129    // Set up the direction and protocol for SCIC
  130    sequence->data_direction                 = SATI_DATA_DIRECTION_OUT;
  131    sequence->protocol                       = SAT_PROTOCOL_UDMA_DATA_OUT;
  132    // The UNMAP translation will always require a callback
  133    // on every response so it can free memory if an error
  134    // occurs.
  135    sequence->is_translate_response_required = TRUE;
  136 
  137    ASSERT(sector_count < 0x100);
  138 
  139    return SATI_SUCCESS;
  140 }
  141 
  142 /**
  143  * @brief This method updates the unmap sequence state to the next
  144  *        unmap descriptor
  145  *
  146  * @return Indicate if the method was successfully completed.
  147  * @retval SATI_SUCCESS This is returned in all other cases.
  148  */
  149 SATI_STATUS sati_unmap_load_next_descriptor(
  150    SATI_TRANSLATOR_SEQUENCE_T * sequence,
  151    void                       * scsi_io
  152 )
  153 {
  154    SATI_UNMAP_PROCESSING_STATE_T * unmap_process_state;
  155    U32                             index;
  156    U8                              unmap_block_descriptor[16];
  157 
  158    unmap_process_state = &sequence->command_specific_data.unmap_process_state;
  159 
  160    // Load the next descriptor
  161    for(index = unmap_process_state->current_unmap_block_descriptor_index;
  162        index < unmap_process_state->current_unmap_block_descriptor_index +
  163                SATI_UNMAP_SIZEOF_SCSI_UNMAP_BLOCK_DESCRIPTOR;
  164        index++)
  165    {
  166       sati_get_data_byte(sequence,
  167          scsi_io,
  168          index,
  169          &unmap_block_descriptor[index-unmap_process_state->current_unmap_block_descriptor_index]);
  170    }
  171 
  172    // Update the internal state for the next translation pass
  173    unmap_process_state->current_lba_count = (unmap_block_descriptor[8] << 24) |
  174                                             (unmap_block_descriptor[9] << 16) |
  175                                             (unmap_block_descriptor[10] << 8) |
  176                                             (unmap_block_descriptor[11]);
  177    unmap_process_state->current_lba       = ((SATI_LBA)(unmap_block_descriptor[0]) << 56) |
  178                                             ((SATI_LBA)(unmap_block_descriptor[1]) << 48) |
  179                                             ((SATI_LBA)(unmap_block_descriptor[2]) << 40) |
  180                                             ((SATI_LBA)(unmap_block_descriptor[3]) << 32) |
  181                                             ((SATI_LBA)(unmap_block_descriptor[4]) << 24) |
  182                                             ((SATI_LBA)(unmap_block_descriptor[5]) << 16) |
  183                                             ((SATI_LBA)(unmap_block_descriptor[6]) << 8) |
  184                                             ((SATI_LBA)(unmap_block_descriptor[7]));
  185    unmap_process_state->next_lba          = 0;
  186 
  187    // Update the index for the next descriptor to translate
  188    unmap_process_state->current_unmap_block_descriptor_index += SATI_UNMAP_SIZEOF_SCSI_UNMAP_BLOCK_DESCRIPTOR;
  189 
  190    return SATI_SUCCESS;
  191 }
  192 
  193 /**
  194  * @brief This method determines the max number of blocks of DSM data
  195  *        that can be satisfied by the device and the SW
  196  *
  197  * @return Number of blocks supported
  198  * @retval Number of blocks supported
  199  */
  200 U32 sati_unmap_get_max_buffer_size_in_blocks(
  201    SATI_TRANSLATOR_SEQUENCE_T * sequence
  202 )
  203 {
  204    // Currently this SATI implementation only supports a single
  205    // 4k block of memory for the DMA write operation for simplicity
  206    // (no need to handle more than one SG element).
  207    // Since most run time UNMAP requests use 1K or less buffer space,
  208    // there is no performance degradation with only supporting a
  209    // single physical page.  For best results allocate the maximum
  210    // amount of memory the device can handle up to the maximum of 4K.
  211    return MIN(SATI_DSM_MAX_BUFFER_SIZE/sequence->device->logical_block_size,
  212               sequence->device->max_lba_range_entry_blocks);
  213 }
  214 
  215 /**
  216  * @brief This method will be called before starting the first unmap translation
  217  *
  218  * @return Indicate if the translation was successful.
  219  * @retval SATI_SUCCESS This is returned if the command translation was
  220  *         successful and no further processing.
  221  * @retval SATI_COMPLETE - The initial processing was completed successfully
  222  * @retval SATI_FAILURE_CHECK_RESPONSE_DATA - Failed the initial processing
  223  */
  224 SATI_STATUS sati_unmap_initial_processing(
  225    SATI_TRANSLATOR_SEQUENCE_T * sequence,
  226    void                       * scsi_io,
  227    void                       * ata_io
  228 )
  229 {
  230    SATI_UNMAP_PROCESSING_STATE_T * unmap_process_state;
  231    U8 * cdb;
  232    U16 unmap_length;
  233    U32 descriptor_length;
  234    U32 index;
  235    U32 max_dsm_blocks;
  236    U8  unmap_param_list[8];
  237 
  238    unmap_process_state = &sequence->command_specific_data.unmap_process_state;
  239 
  240    // Set up the sequence type for unmap translation
  241    sequence->type = SATI_SEQUENCE_UNMAP;
  242 
  243    // Make sure the device is TRIM capable
  244    if ((sequence->device->capabilities & SATI_DEVICE_CAP_DSM_TRIM_SUPPORT)
  245        != SATI_DEVICE_CAP_DSM_TRIM_SUPPORT)
  246    {
  247       // Can't send TRIM request to device that does not support it
  248       sati_scsi_sense_data_construct(
  249          sequence,
  250          scsi_io,
  251          SCSI_STATUS_CHECK_CONDITION,
  252          SCSI_SENSE_ILLEGAL_REQUEST,
  253          SCSI_ASC_INVALID_FIELD_IN_CDB,
  254          SCSI_ASCQ_INVALID_FIELD_IN_CDB
  255       );
  256       return SATI_FAILURE_CHECK_RESPONSE_DATA;
  257    }
  258 
  259    // get the amount of data being sent from the cdb
  260    cdb = sati_cb_get_cdb_address(scsi_io);
  261    unmap_length = (sati_get_cdb_byte(cdb, 7) << 8) | sati_get_cdb_byte(cdb, 8);
  262 
  263    // If nothing has been requested return success now.
  264    if (unmap_length == 0)
  265    {
  266        // SAT: This is not an error
  267        return SATI_SUCCESS;
  268    }
  269    if (unmap_length < SATI_UNMAP_SIZEOF_SCSI_UNMAP_PARAMETER_LIST)
  270    {
  271       // Not enough length specified in the CDB
  272       sati_scsi_sense_data_construct(
  273          sequence,
  274          scsi_io,
  275          SCSI_STATUS_CHECK_CONDITION,
  276          SCSI_SENSE_ILLEGAL_REQUEST,
  277          SCSI_ASC_INVALID_FIELD_IN_CDB,
  278          SCSI_ASCQ_INVALID_FIELD_IN_CDB
  279       );
  280       return SATI_FAILURE_CHECK_RESPONSE_DATA;
  281    }
  282 
  283    sequence->allocation_length = unmap_length;
  284 
  285    // Get the unmap parameter header
  286    for(index = 0; index < SATI_UNMAP_SIZEOF_SCSI_UNMAP_PARAMETER_LIST; index++)
  287    {
  288       sati_get_data_byte(sequence, scsi_io, index,   &unmap_param_list[index]);
  289    }
  290    descriptor_length = (unmap_param_list[2] << 8) | unmap_param_list[3];
  291 
  292    // Check length again
  293    if (descriptor_length == 0)
  294    {
  295        // SAT: This is not an error
  296        return SATI_SUCCESS;
  297    }
  298 
  299    if ((U32)(unmap_length - SATI_UNMAP_SIZEOF_SCSI_UNMAP_PARAMETER_LIST) < descriptor_length)
  300    {
  301       // Not enough length specified in the CDB
  302       sati_scsi_sense_data_construct(
  303          sequence,
  304          scsi_io,
  305          SCSI_STATUS_CHECK_CONDITION,
  306          SCSI_SENSE_ILLEGAL_REQUEST,
  307          SCSI_ASC_INVALID_FIELD_IN_CDB,
  308          SCSI_ASCQ_INVALID_FIELD_IN_CDB
  309       );
  310       return SATI_FAILURE_CHECK_RESPONSE_DATA;
  311    }
  312 
  313    // Save the maximum unmap block descriptors in this request
  314    unmap_process_state->max_unmap_block_descriptors =
  315        descriptor_length/SATI_UNMAP_SIZEOF_SCSI_UNMAP_BLOCK_DESCRIPTOR;
  316 
  317    // Determine the maximum size of the write buffer that will be required
  318    // for the translation in terms of number of blocks
  319    max_dsm_blocks = sati_unmap_get_max_buffer_size_in_blocks(sequence);
  320 
  321    // Save the maximum number of DSM descriptors we can send during the translation
  322    unmap_process_state->max_lba_range_entries =
  323        (max_dsm_blocks*sequence->device->logical_block_size)/sizeof(TRIM_PAIR);
  324 
  325    // Get the write buffer for the translation
  326    sati_cb_allocate_dma_buffer(
  327       scsi_io,
  328       max_dsm_blocks*sequence->device->logical_block_size,
  329       &(unmap_process_state->virtual_unmap_buffer),
  330       &(unmap_process_state->physical_unmap_buffer_low),
  331       &(unmap_process_state->physical_unmap_buffer_high));
  332 
  333    // Makes sure we have a buffer
  334    if (unmap_process_state->virtual_unmap_buffer == NULL)
  335    {
  336       // Resource failure
  337       sati_scsi_sense_data_construct(
  338          sequence,
  339          scsi_io,
  340          SCSI_STATUS_BUSY,
  341          SCSI_SENSE_NO_SENSE,
  342          SCSI_ASC_NO_ADDITIONAL_SENSE,
  343          SCSI_ASCQ_NO_ADDITIONAL_SENSE
  344       );
  345       return SATI_FAILURE_CHECK_RESPONSE_DATA;
  346    }
  347 
  348    // Get the first SGL entry.  This code will only use one 4K page so will
  349    // only utilize the first sge.
  350    sati_cb_sgl_next_sge(scsi_io,
  351                         ata_io,
  352                         NULL,
  353                         &(unmap_process_state->unmap_buffer_sgl_pair));
  354 
  355    // Load the first descriptor to start the translation loop
  356    unmap_process_state->current_unmap_block_descriptor_index =
  357       SATI_UNMAP_SIZEOF_SCSI_UNMAP_PARAMETER_LIST;
  358    sati_unmap_load_next_descriptor(sequence,scsi_io);
  359 
  360    // Next state will be incomplete since translation
  361    // will require a callback and possibly more requests.
  362    sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE;
  363 
  364    return SATI_COMPLETE;
  365 }
  366 
  367 /**
  368  * @brief This method will process each unmap sequence.
  369  *
  370  * @return Indicate if the translation was successful.
  371  * @retval SATI_SUCCESS
  372  */
  373 SATI_STATUS sati_unmap_process(
  374    SATI_TRANSLATOR_SEQUENCE_T * sequence,
  375    void                       * scsi_io,
  376    void                       * ata_io
  377 )
  378 {
  379    SATI_UNMAP_PROCESSING_STATE_T * unmap_process_state;
  380    SATI_LBA dsm_descriptor_lba_count;
  381    U32 dsm_descriptor;
  382    U32 dsm_bytes;
  383    U32 dsm_remainder_bytes;
  384    U32 dsm_blocks;
  385    U32 max_dsm_blocks;
  386 
  387    unmap_process_state = &sequence->command_specific_data.unmap_process_state;
  388 
  389    // Set up the starting address of the buffer for this portion of the translation
  390    unmap_process_state->current_dsm_descriptor = unmap_process_state->virtual_unmap_buffer;
  391    dsm_descriptor = 0;
  392 
  393    // Translate as much as we can
  394    while ((dsm_descriptor < unmap_process_state->max_lba_range_entries) &&
  395           (unmap_process_state->current_lba_count > 0)) {
  396       // See if the LBA count will fit in to a single descriptor
  397       if (unmap_process_state->current_lba_count > SATI_DSM_MAX_SECTOR_COUNT) {
  398          // Can't fit all of the lbas for this descriptor in to
  399          // one DSM request.  Adjust the current LbaCount and total
  400          // remaining for the next descriptor
  401          dsm_descriptor_lba_count = SATI_DSM_MAX_SECTOR_COUNT;
  402          unmap_process_state->current_lba_count -= SATI_DSM_MAX_SECTOR_COUNT;
  403          unmap_process_state->next_lba =
  404              unmap_process_state->current_lba + SATI_DSM_MAX_SECTOR_COUNT;
  405       } else {
  406          // It all fits in to one descriptor
  407          dsm_descriptor_lba_count = unmap_process_state->current_lba_count;
  408          unmap_process_state->current_lba_count = 0;
  409       }
  410 
  411       // Fill in the ATA DSM descriptor
  412       ((PTRIM_PAIR)(unmap_process_state->current_dsm_descriptor))->sector_address =
  413           unmap_process_state->current_lba;
  414       ((PTRIM_PAIR)(unmap_process_state->current_dsm_descriptor))->sector_count =
  415           dsm_descriptor_lba_count;
  416 
  417       // See if we can move on to the next descriptor
  418       if (unmap_process_state->current_lba_count == 0) {
  419          // See if there is another descriptor
  420          --unmap_process_state->max_unmap_block_descriptors;
  421          if (unmap_process_state->max_unmap_block_descriptors > 0) {
  422             // Move on to the next descriptor
  423             sati_unmap_load_next_descriptor(sequence,scsi_io);
  424          }
  425       } else {
  426          // Move to the next LBA in this descriptor
  427          unmap_process_state->current_lba = unmap_process_state->next_lba;
  428       }
  429 
  430       // Make sure the LBA does not exceed 48 bits...
  431       ASSERT(unmap_process_state->current_lba <= SATI_DSM_MAX_SECTOR_ADDRESS);
  432 
  433       // Increment the number of descriptors used and point to the next entry
  434       dsm_descriptor++;
  435       unmap_process_state->current_dsm_descriptor =
  436           (U8 *)(unmap_process_state->current_dsm_descriptor) + sizeof(TRIM_PAIR);
  437    }
  438 
  439    // Calculate number of blocks we have filled in
  440    dsm_blocks     = sati_unmap_calculate_dsm_blocks(sequence,dsm_descriptor);
  441    dsm_bytes      = dsm_blocks * sequence->device->logical_block_size;
  442    max_dsm_blocks = sati_unmap_get_max_buffer_size_in_blocks(sequence);
  443 
  444    // The current_dsm_descriptor points to the next location in the buffer
  445    // Get the remaining bytes from the last translated descriptor
  446    // to the end of the 4k buffer.
  447    dsm_remainder_bytes = sequence->device->logical_block_size;
  448    dsm_remainder_bytes -= (U32)((POINTER_UINT)unmap_process_state->current_dsm_descriptor &
  449                                 (sequence->device->logical_block_size-1));
  450 
  451    // If there was no remainder, the complete buffer was filled in.
  452    if (dsm_remainder_bytes != sequence->device->logical_block_size)
  453    {
  454        // Add on the remaining unfilled blocks
  455        dsm_remainder_bytes += (sequence->device->logical_block_size * (max_dsm_blocks - dsm_blocks));
  456 
  457        // According to ATA-8, if the DSM buffer is not completely filled with
  458        // valid DSM descriptor data, the remaining portion of the
  459        // buffer must be filled in with zeros.
  460        memset((U8 *)unmap_process_state->current_dsm_descriptor, 0, dsm_remainder_bytes);
  461    }
  462 
  463    // Tell scic to utilize this sgl pair for write DMA processing of
  464    // the SCSI UNMAP translation with the total number of bytes for this transfer
  465    sati_cb_sge_write(unmap_process_state->unmap_buffer_sgl_pair,
  466                      unmap_process_state->physical_unmap_buffer_low,
  467                      unmap_process_state->physical_unmap_buffer_high,
  468                      dsm_bytes);
  469 
  470    // Construct the unmap ATA request
  471    sati_unmap_construct(sequence,
  472                         scsi_io,
  473                         ata_io,
  474                         dsm_blocks);
  475 
  476    // Determine sequence next state based on whether there is more translation
  477    // to complete
  478    if (unmap_process_state->current_lba_count == 0)
  479    {
  480        // used for completion routine to determine if there is more processing
  481        sequence->state = SATI_SEQUENCE_STATE_FINAL;
  482    }
  483    // This requests has already translated the SGL, have SCIC skip SGL translataion
  484    return SATI_SUCCESS_SGL_TRANSLATED;
  485 }
  486 
  487 //******************************************************************************
  488 //* P U B L I C   M E T H O D S
  489 //******************************************************************************
  490 
  491 /**
  492  * @brief This method will handle termination of the
  493  *        SCSI unmap translation and frees previously allocated
  494  *        dma buffer.
  495  *
  496  * @return None
  497  */
  498 void sati_unmap_terminate(
  499    SATI_TRANSLATOR_SEQUENCE_T * sequence,
  500    void                       * scsi_io,
  501    void                       * ata_io
  502 )
  503 {
  504    SATI_UNMAP_PROCESSING_STATE_T * unmap_process_state;
  505    unmap_process_state = &sequence->command_specific_data.unmap_process_state;
  506 
  507    if (unmap_process_state->virtual_unmap_buffer != NULL)
  508    {
  509       sati_cb_free_dma_buffer(scsi_io, unmap_process_state->virtual_unmap_buffer);
  510       unmap_process_state->virtual_unmap_buffer = NULL;
  511    }
  512 }
  513 
  514 /**
  515  * @brief This method will translate the SCSI Unmap command
  516  *        into corresponding ATA commands.  Depending upon the capabilities
  517  *        supported by the target different ATA commands can be selected.
  518  *        Additionally, in some cases more than a single ATA command may
  519  *        be required.
  520  *
  521  * @return Indicate if the command translation succeeded.
  522  * @retval SATI_SUCCESS This is returned if the command translation was
  523  *         successful.
  524  * @retval SATI_COMPLETE This is returned if the command translation was
  525  *         successful and no ATA commands need to be set.
  526  * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if
  527  *         sense data has been created as a result of something specified
  528  *         in the parameter data fields.
  529  */
  530 SATI_STATUS sati_unmap_translate_command(
  531    SATI_TRANSLATOR_SEQUENCE_T * sequence,
  532    void                       * scsi_io,
  533    void                       * ata_io
  534 )
  535 {
  536    SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA;
  537    SATI_UNMAP_PROCESSING_STATE_T * unmap_process_state;
  538 
  539    unmap_process_state = &sequence->command_specific_data.unmap_process_state;
  540 
  541    // Determine if this is the first step in the unmap sequence
  542    if ( sequence->state == SATI_SEQUENCE_STATE_INITIAL )
  543    {
  544        status = sati_unmap_initial_processing(sequence,scsi_io,ata_io);
  545        if (status != SATI_COMPLETE)
  546        {
  547           return status;
  548        }
  549    }
  550    // Translate the next portion of the UNMAP request
  551    return sati_unmap_process(sequence, scsi_io, ata_io);
  552 }
  553 
  554 /**
  555  * @brief This method will translate the ATA command register FIS
  556  *        response into an appropriate SCSI response for Unmap.
  557  *        For more information on the parameters passed to this method,
  558  *        please reference sati_translate_response().
  559  *
  560  * @return Indicate if the response translation succeeded.
  561  * @retval SATI_SUCCESS This is returned if the command translation was
  562  *         successful.
  563  * @retval SATI_COMPLETE This is returned if the command translation was
  564  *         successful and no ATA commands need to be set.
  565  * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if
  566  *         sense data has been created as a result of something specified
  567  *         in the parameter data fields.
  568  */
  569 SATI_STATUS sati_unmap_translate_response(
  570    SATI_TRANSLATOR_SEQUENCE_T * sequence,
  571    void                       * scsi_io,
  572    void                       * ata_io
  573 )
  574 {
  575    U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
  576    SATI_UNMAP_PROCESSING_STATE_T * unmap_process_state;
  577    SATI_STATUS sati_status = SATI_COMPLETE;
  578 
  579    unmap_process_state = &sequence->command_specific_data.unmap_process_state;
  580 
  581    if (sati_get_ata_status(register_fis) & ATA_STATUS_REG_ERROR_BIT)
  582    {
  583       sequence->state = SATI_SEQUENCE_STATE_FINAL;
  584       sati_scsi_sense_data_construct(
  585          sequence,
  586          scsi_io,
  587          SCSI_STATUS_CHECK_CONDITION,
  588          SCSI_SENSE_ABORTED_COMMAND,
  589          SCSI_ASC_NO_ADDITIONAL_SENSE,
  590          SCSI_ASCQ_NO_ADDITIONAL_SENSE
  591       );
  592       // All done, terminate the translation
  593       sati_unmap_terminate(sequence, scsi_io, ata_io);
  594    }
  595    else
  596    {
  597       if (sequence->state != SATI_SEQUENCE_STATE_INCOMPLETE)
  598       {
  599           // All done, terminate the translation
  600           sati_unmap_terminate(sequence, scsi_io, ata_io);
  601       }
  602       else
  603       {
  604           // Still translating
  605           sati_status = SATI_SEQUENCE_STATE_INCOMPLETE;
  606       }
  607    }
  608    return sati_status;
  609 }
  610 
  611 #endif // !defined(DISABLE_SATI_UNMAP)

Cache object: 67a799c25373c57162c25ecb72a45f38


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.