FreeBSD/sys/dev/isci/scil/sati_mode_select.c
/**
 * @brief This method will translate the SCSI Mode Select 6 byte or 10 byte 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 SCI_SUCCESS This is returned if the command translation was
 *         successful.
 * @retval SCI_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.
 */
@brief This method will translate the SCSI Mode Select 6 byte or 10 byte 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 SCI_SUCCESS This is returned if the command translation was
successful.
@retval SCI_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.
@brief This method will translate the SCSI Mode Select 6 byte or 10 byte 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 SCI_SUCCESS This is returned if the command translation was successful . @retval SCI_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 .
static
SATI_STATUS sati_mode_select_translate_command(
   SATI_TRANSLATOR_SEQUENCE_T   * sequence,
   void                         * scsi_io,
   void                         * ata_io,
   U32                          cdb_size
)
{
   SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA;
   U32 mode_page_offset;
   U32 block_descriptor_length;
   U32 index;
   U16 data_transfer_length;
   U8 current_mode_parameters[8]={0,0,0,0,0,0,0,0};
   U8 * cdb = sati_cb_get_cdb_address(scsi_io);
   if(FALSE == (cdb_size == 6 || cdb_size == 10))
   {
      return status;
   }
   if(sequence->state == SATI_SEQUENCE_STATE_INITIAL)
   {
      sequence->command_specific_data.process_state.ata_command_sent_for_cmp = 0;
      sequence->state = SATI_SEQUENCE_STATE_TRANSLATE_DATA;
   }
   if ( sequence->command_specific_data.process_state.ata_command_sent_for_cmp == 0 )
   {
      if (cdb_size == 6)
      {
         data_transfer_length = sati_get_cdb_byte(cdb, 4);
      }
      else
      {
         data_transfer_length = (sati_get_cdb_byte(cdb, 7) << 8) + sati_get_cdb_byte(cdb, 8);
      }
      sequence->allocation_length = data_transfer_length;
      for( index = 0; index < 8; index++ )
      {
         sati_get_data_byte(sequence, scsi_io, index, &current_mode_parameters[index]);
      }
      if ( sati_mode_select_get_medium_type(current_mode_parameters, cdb_size) != 0 )
      {
         sati_scsi_sense_data_construct(
            sequence,
            scsi_io,
            SCSI_STATUS_CHECK_CONDITION,
            SCSI_SENSE_ILLEGAL_REQUEST,
            SCSI_ASC_INVALID_FIELD_IN_PARM_LIST,
            SCSI_ASCQ_INVALID_FIELD_IN_PARM_LIST
         );
         return status;
      }
      block_descriptor_length = sati_mode_select_get_mode_block_descriptor_length(
                                   current_mode_parameters,
                                   cdb_size
                                );
      mode_page_offset = sati_mode_select_get_mode_page_offset(
                            block_descriptor_length,
                            cdb_size
                         );
      if(mode_page_offset > data_transfer_length)
      {
         sequence->state = SATI_SEQUENCE_STATE_FINAL;
         status = SATI_FAILURE_CHECK_RESPONSE_DATA;
      }
      else
      {
         sati_mode_select_initialize_mode_sel_processing_state(
            sequence,
            scsi_io,
            ata_io,
            data_transfer_length,
            mode_page_offset
         );
      }
    }
   if(sequence->command_specific_data.process_state.current_mode_page_processed)
   {
      sequence->command_specific_data.process_state.ata_command_sent_for_cmp = 0;
      sequence->command_specific_data.process_state.current_mode_page_processed = FALSE;
   }
   status = sati_mode_select_process_mode_page(sequence, scsi_io, ata_io);
   if(sequence->command_specific_data.process_state.current_mode_page_processed != FALSE)
   {
      sequence->state = SATI_SEQUENCE_STATE_FINAL;
   }
   else
   {
      sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE;
   }
   if(status == SATI_FAILURE_CHECK_RESPONSE_DATA)
   {
      sequence->state = SATI_SEQUENCE_STATE_FINAL;
      sati_scsi_sense_data_construct(
         sequence,
         scsi_io,
         SCSI_STATUS_CHECK_CONDITION,
         SCSI_SENSE_ILLEGAL_REQUEST,
         SCSI_ASC_INVALID_FIELD_IN_PARM_LIST,
         SCSI_ASCQ_INVALID_FIELD_IN_PARM_LIST
      );
   }
   return status;
}
static SATI_STATUS sati_mode_select_translate_command ( SATI_TRANSLATOR_SEQUENCE_T * sequence , void * scsi_io , void * ata_io , U32 cdb_size ) { SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA ; U32 mode_page_offset ; U32 block_descriptor_length ; U32 index ; U16 data_transfer_length ; U8 current_mode_parameters [ 8 ] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } ; U8 * cdb = sati_cb_get_cdb_address ( scsi_io ) ; if ( FALSE == ( cdb_size == 6 || cdb_size == 10 ) ) { return status ; } if ( sequence -> state == SATI_SEQUENCE_STATE_INITIAL ) { sequence -> command_specific_data . process_state . ata_command_sent_for_cmp = 0 ; sequence -> state = SATI_SEQUENCE_STATE_TRANSLATE_DATA ; } if ( sequence -> command_specific_data . process_state . ata_command_sent_for_cmp == 0 ) { if ( cdb_size == 6 ) { data_transfer_length = sati_get_cdb_byte ( cdb , 4 ) ; } else { data_transfer_length = ( sati_get_cdb_byte ( cdb , 7 ) << 8 ) + sati_get_cdb_byte ( cdb , 8 ) ; } sequence -> allocation_length = data_transfer_length ; for ( index = 0 ; index < 8 ; index ++ ) { sati_get_data_byte ( sequence , scsi_io , index , & current_mode_parameters [ index ] ) ; } if ( sati_mode_select_get_medium_type ( current_mode_parameters , cdb_size ) != 0 ) { sati_scsi_sense_data_construct ( sequence , scsi_io , SCSI_STATUS_CHECK_CONDITION , SCSI_SENSE_ILLEGAL_REQUEST , SCSI_ASC_INVALID_FIELD_IN_PARM_LIST , SCSI_ASCQ_INVALID_FIELD_IN_PARM_LIST ) ; return status ; } block_descriptor_length = sati_mode_select_get_mode_block_descriptor_length ( current_mode_parameters , cdb_size ) ; mode_page_offset = sati_mode_select_get_mode_page_offset ( block_descriptor_length , cdb_size ) ; if ( mode_page_offset > data_transfer_length ) { sequence -> state = SATI_SEQUENCE_STATE_FINAL ; status = SATI_FAILURE_CHECK_RESPONSE_DATA ; } else { sati_mode_select_initialize_mode_sel_processing_state ( sequence , scsi_io , ata_io , data_transfer_length , mode_page_offset ) ; } } if ( sequence -> command_specific_data . process_state . current_mode_page_processed ) { sequence -> command_specific_data . process_state . ata_command_sent_for_cmp = 0 ; sequence -> command_specific_data . process_state . current_mode_page_processed = FALSE ; } status = sati_mode_select_process_mode_page ( sequence , scsi_io , ata_io ) ; if ( sequence -> command_specific_data . process_state . current_mode_page_processed != FALSE ) { sequence -> state = SATI_SEQUENCE_STATE_FINAL ; } else { sequence -> state = SATI_SEQUENCE_STATE_INCOMPLETE ; } if ( status == SATI_FAILURE_CHECK_RESPONSE_DATA ) { sequence -> state = SATI_SEQUENCE_STATE_FINAL ; sati_scsi_sense_data_construct ( sequence , scsi_io , SCSI_STATUS_CHECK_CONDITION , SCSI_SENSE_ILLEGAL_REQUEST , SCSI_ASC_INVALID_FIELD_IN_PARM_LIST , SCSI_ASCQ_INVALID_FIELD_IN_PARM_LIST ) ; } return status ; }
@brief This method will translate the SCSI Mode Select 6 byte or 10 byte command
        into corresponding ATA commands.
@brief This method will translate the SCSI Mode Select 6 byte or 10 byte command into corresponding ATA commands .
// cdb_size must be 6 or 10 //First, initializes mode_sel_processing_state //CDB byte 4 is the parameter length //CDB byte 7 and 8 for Mode Select 10 //Get 8 bytes for headers (4 bytes for Mode Select 6 and 8 bytes for Mode Select 10) //medium type should be 0 // move to next mode page // Done this page