FreeBSD/sys/dev/isci/scil/sati_unmap.c
/**
 * @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
 */
@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
@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;
   sequence->type = SATI_SEQUENCE_UNMAP;
   if ((sequence->device->capabilities & SATI_DEVICE_CAP_DSM_TRIM_SUPPORT)
       != SATI_DEVICE_CAP_DSM_TRIM_SUPPORT)
   {
      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;
   }
   cdb = sati_cb_get_cdb_address(scsi_io);
   unmap_length = (sati_get_cdb_byte(cdb, 7) << 8) | sati_get_cdb_byte(cdb, 8);
   if (unmap_length == 0)
   {
       return SATI_SUCCESS;
   }
   if (unmap_length < SATI_UNMAP_SIZEOF_SCSI_UNMAP_PARAMETER_LIST)
   {
      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;
   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];
   if (descriptor_length == 0)
   {
       return SATI_SUCCESS;
   }
   if ((U32)(unmap_length - SATI_UNMAP_SIZEOF_SCSI_UNMAP_PARAMETER_LIST) < descriptor_length)
   {
      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;
   }
   unmap_process_state->max_unmap_block_descriptors =
       descriptor_length/SATI_UNMAP_SIZEOF_SCSI_UNMAP_BLOCK_DESCRIPTOR;
   max_dsm_blocks = sati_unmap_get_max_buffer_size_in_blocks(sequence);
   unmap_process_state->max_lba_range_entries =
       (max_dsm_blocks*sequence->device->logical_block_size)/sizeof(TRIM_PAIR);
   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));
   if (unmap_process_state->virtual_unmap_buffer == NULL)
   {
      sati_scsi_sense_data_construct(
         sequence,
         scsi_io,
         SCSI_STATUS_BUSY,
         SCSI_SENSE_NO_SENSE,
         SCSI_ASC_NO_ADDITIONAL_SENSE,
         SCSI_ASCQ_NO_ADDITIONAL_SENSE
      );
      return SATI_FAILURE_CHECK_RESPONSE_DATA;
   }
   sati_cb_sgl_next_sge(scsi_io,
                        ata_io,
                        NULL,
                        &(unmap_process_state->unmap_buffer_sgl_pair));
   unmap_process_state->current_unmap_block_descriptor_index =
      SATI_UNMAP_SIZEOF_SCSI_UNMAP_PARAMETER_LIST;
   sati_unmap_load_next_descriptor(sequence,scsi_io);
   sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE;
   return SATI_COMPLETE;
}
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 ; sequence -> type = SATI_SEQUENCE_UNMAP ; if ( ( sequence -> device -> capabilities & SATI_DEVICE_CAP_DSM_TRIM_SUPPORT ) != SATI_DEVICE_CAP_DSM_TRIM_SUPPORT ) { 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 ; } cdb = sati_cb_get_cdb_address ( scsi_io ) ; unmap_length = ( sati_get_cdb_byte ( cdb , 7 ) << 8 ) | sati_get_cdb_byte ( cdb , 8 ) ; if ( unmap_length == 0 ) { return SATI_SUCCESS ; } if ( unmap_length < SATI_UNMAP_SIZEOF_SCSI_UNMAP_PARAMETER_LIST ) { 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 ; 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 ] ; if ( descriptor_length == 0 ) { return SATI_SUCCESS ; } if ( ( U32 ) ( unmap_length - SATI_UNMAP_SIZEOF_SCSI_UNMAP_PARAMETER_LIST ) < descriptor_length ) { 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 ; } unmap_process_state -> max_unmap_block_descriptors = descriptor_length / SATI_UNMAP_SIZEOF_SCSI_UNMAP_BLOCK_DESCRIPTOR ; max_dsm_blocks = sati_unmap_get_max_buffer_size_in_blocks ( sequence ) ; unmap_process_state -> max_lba_range_entries = ( max_dsm_blocks * sequence -> device -> logical_block_size ) / sizeof ( TRIM_PAIR ) ; 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 ) ) ; if ( unmap_process_state -> virtual_unmap_buffer == NULL ) { sati_scsi_sense_data_construct ( sequence , scsi_io , SCSI_STATUS_BUSY , SCSI_SENSE_NO_SENSE , SCSI_ASC_NO_ADDITIONAL_SENSE , SCSI_ASCQ_NO_ADDITIONAL_SENSE ) ; return SATI_FAILURE_CHECK_RESPONSE_DATA ; } sati_cb_sgl_next_sge ( scsi_io , ata_io , NULL , & ( unmap_process_state -> unmap_buffer_sgl_pair ) ) ; unmap_process_state -> current_unmap_block_descriptor_index = SATI_UNMAP_SIZEOF_SCSI_UNMAP_PARAMETER_LIST ; sati_unmap_load_next_descriptor ( sequence , scsi_io ) ; sequence -> state = SATI_SEQUENCE_STATE_INCOMPLETE ; return SATI_COMPLETE ; }
@brief This method will be called before starting the first unmap translation
 @return Indicate if the translation was successful.
@brief This method will be called before starting the first unmap translation @return Indicate if the translation was successful .
// Set up the sequence type for unmap translation // Make sure the device is TRIM capable // Can't send TRIM request to device that does not support it // get the amount of data being sent from the cdb // If nothing has been requested return success now. // SAT: This is not an error // Not enough length specified in the CDB // Get the unmap parameter header // Check length again // SAT: This is not an error // Not enough length specified in the CDB // Save the maximum unmap block descriptors in this request // Determine the maximum size of the write buffer that will be required // for the translation in terms of number of blocks // Save the maximum number of DSM descriptors we can send during the translation // Get the write buffer for the translation // Makes sure we have a buffer // Resource failure // Get the first SGL entry.  This code will only use one 4K page so will // only utilize the first sge. // Load the first descriptor to start the translation loop // Next state will be incomplete since translation // will require a callback and possibly more requests.