Exemplo n.º 1
0
/**
 * @brief This method will translate the lun reset SCSI task request into an
 *        ATA SOFT RESET command. For more information on the parameters
 *        passed to this method, please reference sati_translate_command().
 *
 * @return Indicate if the command translation succeeded.
 * @retval SCI_SUCCESS This is returned if the command translation was
 *         successful.
 *
 * @note It is up to the user of the sata translator to set the command bit
 *       and clear the control softreset bit and send the second register fis.
 */
SATI_STATUS sati_lun_reset_translate_command(
   SATI_TRANSLATOR_SEQUENCE_T * sequence,
   void                       * scsi_io,
   void                       * ata_io
)
{
   U8* register_fis = sati_cb_get_h2d_register_fis_address(ata_io);

   sati_set_ata_command(register_fis, ATA_NOP);
   sati_set_ata_control(register_fis, ATA_CONTROL_REG_SOFT_RESET_BIT);

   //set all other fields to zero.
   sati_clear_sata_command_flag(register_fis);
   sati_set_ata_features(register_fis, 0);
   sati_set_ata_features_exp(register_fis, 0);
   sati_set_ata_sector_count(register_fis, 0);
   sati_set_ata_sector_count_exp(register_fis, 0);
   sati_set_ata_lba_low(register_fis, 0);
   sati_set_ata_lba_mid(register_fis, 0);
   sati_set_ata_lba_high(register_fis, 0);
   sati_set_ata_lba_low_exp(register_fis, 0);
   sati_set_ata_lba_mid_exp(register_fis, 0);
   sati_set_ata_lba_high_exp(register_fis, 0);
   sati_set_ata_device_head(register_fis, 0);

   sequence->type                = SATI_SEQUENCE_LUN_RESET;
   sequence->data_direction      = SATI_DATA_DIRECTION_NONE;
   sequence->protocol            = SAT_PROTOCOL_SOFT_RESET;
   sequence->ata_transfer_length = 0;

   return SATI_SUCCESS;
}
Exemplo n.º 2
0
/**
 * @brief This method performs the SCSI SYNCHRONIZE_CACHE 10 and 16 command translation
 *        functionality common to all SYNCHRONIZE_CACHE command sizes.
 *        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_synchronize_cache_translate_command(
   SATI_TRANSLATOR_SEQUENCE_T * sequence,
   void                       * scsi_io,
   void                       * ata_io
)
{
   U8 * cdb          = sati_cb_get_cdb_address(scsi_io);
   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);

   sequence->type           = SATI_SEQUENCE_SYNCHRONIZE_CACHE;
   sequence->protocol       = SAT_PROTOCOL_NON_DATA;
   sequence->data_direction = SATI_DATA_DIRECTION_NONE;

   if (sati_get_cdb_byte(cdb, 1) & SCSI_SYNCHRONIZE_CACHE_IMMED_ENABLED)
   {
      //currently we ignore immed bit.
      ;
   }

   // Ensure the device supports the 48 bit feature set.
   if (sequence->device->capabilities & SATI_DEVICE_CAP_48BIT_ENABLE)
      sati_set_ata_command(register_fis, ATA_FLUSH_CACHE_EXT);
   else
      sati_set_ata_command(register_fis, ATA_FLUSH_CACHE);

   return SATI_SUCCESS;
}
Exemplo n.º 3
0
/**
 * @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;
}
Exemplo n.º 4
0
/**
 * @brief This method performs the SCSI VERIFY command translation
 *        functionality common to all VERIFY command sizes.
 *        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.
 */
static
SATI_STATUS sati_verify_translate_command(
   SATI_TRANSLATOR_SEQUENCE_T * sequence,
   void                       * scsi_io,
   void                       * ata_io
)
{
   U8 * cdb          = sati_cb_get_cdb_address(scsi_io);
   U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);

   /**
    * The translator doesn't support performing the byte check operation.
    * As a result, error the request if the BYTCHK bit is set.
    */
   if ((sati_get_cdb_byte(cdb, 1) & SCSI_VERIFY_BYTCHK_ENABLED))
   {
      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->protocol       = SAT_PROTOCOL_NON_DATA;
   sequence->data_direction = SATI_DATA_DIRECTION_NONE;

   sati_set_ata_device_head(register_fis, ATA_DEV_HEAD_REG_LBA_MODE_ENABLE);

   // Ensure the device supports the 48 bit feature set.
   if (sequence->device->capabilities & SATI_DEVICE_CAP_48BIT_ENABLE)
      sati_set_ata_command(register_fis, ATA_READ_VERIFY_SECTORS_EXT);
   else
      sati_set_ata_command(register_fis, ATA_READ_VERIFY_SECTORS);

   return SATI_SUCCESS;
}
Exemplo n.º 5
0
/**
 * @brief This method will translate the abort task set SCSI task request into an
 *        ATA READ LOG EXT command. For more information on the parameters
 *        passed to this method, please reference sati_translate_command().
 *
 * @return Indicate if the command translation succeeded.
 * @retval SCI_SUCCESS This is returned if the command translation was
 *         successful.
 */
SATI_STATUS sati_abort_task_set_translate_command(
   SATI_TRANSLATOR_SEQUENCE_T * sequence,
   void                       * scsi_io,
   void                       * ata_io
)
{
   U8 * register_fis;

   //ATA Read Log Ext with log address set to 0x10
   sati_ata_read_log_ext_construct(
      ata_io,
      sequence,
      ATA_LOG_PAGE_NCQ_ERROR,
      sizeof(ATA_NCQ_COMMAND_ERROR_LOG_T)
   );

   register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
   sati_set_sata_command_flag(register_fis);

   sequence->type                = SATI_SEQUENCE_ABORT_TASK_SET;
   sequence->state               = SATI_SEQUENCE_STATE_AWAIT_RESPONSE;

   return SATI_SUCCESS;
}
Exemplo n.º 6
0
/**
 * @brief This method will translate the SCSI Passthrough command
 *        into the corresponding ATA command.
 *
 * @return Indicate if the command translation succeeded.
 * @retval SATI_SUCCESS This is returned if the command translation was
 *         successful.
 * @retval SATI_FAILURE This is returned if the command translation was
 *         unsuccessful
 */
SATI_STATUS sati_passthrough_16_translate_command(
   SATI_TRANSLATOR_SEQUENCE_T * sequence,
   void                       * scsi_io,
   void                       * ata_io
)
{
   SATI_STATUS   status;
   U8          * cdb;
   U8          * register_fis;

   status = SATI_FAILURE;

   sequence->type = SATI_SEQUENCE_ATA_PASSTHROUGH_16;
   sequence->state = SATI_SEQUENCE_STATE_TRANSLATE_DATA;

   cdb = sati_cb_get_cdb_address(scsi_io);
   sequence->protocol = PASSTHROUGH_CDB_PROTOCOL(cdb);
   register_fis = sati_cb_get_h2d_register_fis_address(ata_io);

   /*
    * CAM will send passthrough commands with protocol set to multiword
    * DMA even though no multiword DMA mode is selected on the device.
    * This is because some controllers (LSI) will only accept
    * ATA_PASSTHROUGH commands with DMA mode - not UDMA_IN/OUT.
    *
    * Since isci does not support multiword DMA, fix this up here.
    */
   if (sequence->protocol == PASSTHROUGH_DMA)
   {
      if (PASSTHROUGH_CDB_T_DIR(cdb) == 0x1)
      {
         sequence->protocol = PASSTHROUGH_UDMA_DATA_IN;
      }
      else
      {
         sequence->protocol = PASSTHROUGH_UDMA_DATA_OUT;
      }
   }

   if (sati_passthrough_check_direction(sequence, cdb) != SATI_COMPLETE
       || sati_passthrough_multiple_count_error(cdb)
      )
   {
      // Fail due to mismatch
      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;
   }

   if (PASSTHROUGH_CDB_EXTEND(cdb) == 1)
   {
      sati_set_ata_features_exp(register_fis, sati_get_cdb_byte(cdb, 3));
      sati_set_ata_sector_count_exp(register_fis, sati_get_cdb_byte(cdb, 5));
      sati_set_ata_lba_low_exp(register_fis, sati_get_cdb_byte(cdb, 7));
      sati_set_ata_lba_mid_exp(register_fis, sati_get_cdb_byte(cdb, 9));
      sati_set_ata_lba_high_exp(register_fis, sati_get_cdb_byte(cdb, 11));
   }

   if (PASSTHROUGH_CDB_CK_COND(cdb) ||
       PASSTHROUGH_CDB_PROTOCOL(cdb) == PASSTHROUGH_RETURN_RESPONSE)
   {
      sequence->is_translate_response_required = TRUE;
   }

   sati_set_ata_features(register_fis, sati_get_cdb_byte(cdb, 4));
   sati_set_ata_sector_count(register_fis, sati_get_cdb_byte(cdb, 6));
   sati_set_ata_lba_low(register_fis, sati_get_cdb_byte(cdb, 8));
   sati_set_ata_lba_mid(register_fis, sati_get_cdb_byte(cdb, 10));
   sati_set_ata_lba_high(register_fis, sati_get_cdb_byte(cdb, 12));
   sati_set_ata_device_head(register_fis, sati_get_cdb_byte(cdb, 13));
   sati_set_ata_command(register_fis, sati_get_cdb_byte(cdb, 14));

   sequence->state = SATI_SEQUENCE_STATE_AWAIT_RESPONSE;

   return SATI_SUCCESS;
}
Exemplo n.º 7
0
SATI_STATUS sati_atapi_translate_command(
   SATI_TRANSLATOR_SEQUENCE_T * sequence,
   SATI_DEVICE_T              * sati_device,
   void                       * scsi_io,
   void                       * atapi_io
)
{
   SATI_STATUS   status;
   U8          * cdb = sati_cb_get_cdb_address(scsi_io);

   SATA_FIS_REG_H2D_T * register_fis =
      (SATA_FIS_REG_H2D_T *)sati_cb_get_h2d_register_fis_address(atapi_io);

   U8 io_direction = SATI_DATA_DIRECTION_IN;

   //No sense response has been set for the translation sequence yet
   sequence->is_sense_response_set = FALSE;
   // Default to no translation response required
   sequence->is_translate_response_required = FALSE;

   sequence->number_data_bytes_set = 0;
   sequence->device  = sati_device;
   sequence->command_specific_data.scratch = 0;

   sati_cb_get_data_direction(scsi_io, &io_direction);

   //set sat protocol.
   if (io_direction == SATI_DATA_DIRECTION_NONE)
      sequence->protocol = SAT_PROTOCOL_PACKET_NON_DATA;
   else if (io_direction == SATI_DATA_DIRECTION_IN)
      sequence->protocol = SAT_PROTOCOL_PACKET_DMA_DATA_IN;
   else if (io_direction == SATI_DATA_DIRECTION_OUT)
      sequence->protocol = SAT_PROTOCOL_PACKET_DMA_DATA_OUT;

   // We don't send Report Luns command out.
   if  (sati_get_cdb_byte(cdb, 0) == SCSI_REPORT_LUNS)
   {
      status = sati_report_luns_translate_command(
                  sequence, scsi_io, atapi_io
               );
   }
   else if (sati_cb_get_lun(scsi_io) != 0)
   {
      sati_scsi_sense_data_construct(
         sequence,
         scsi_io,
         SCSI_STATUS_CHECK_CONDITION,
         SCSI_SENSE_ILLEGAL_REQUEST,
         SCSI_ASC_LOGICAL_UNIT_NOT_SUPPORTED,
         0
      );
      status = SATI_FAILURE_CHECK_RESPONSE_DATA;
   }
   else
   {
      if (sequence->state == SATI_SEQUENCE_STATE_INCOMPLETE)
      {  //Request Sense command is required.
         U8 request_sense_cdb[SATI_ATAPI_REQUEST_SENSE_CDB_LENGTH] =
            {0x3, 0x0, 0x0, 0x0, 0x12, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};

         //set the sequence->protocol to DATA_IN anyway;
         sequence->protocol = SAT_PROTOCOL_PACKET_DMA_DATA_IN;

         //set the cdb for Request Sense using command_specific_data field.
         memcpy(sequence->command_specific_data.sati_atapi_data.request_sense_cdb,
                request_sense_cdb,
                SATI_ATAPI_REQUEST_SENSE_CDB_LENGTH
               );
      }

      //build Packet Fis for any other command translation.
      register_fis->command = ATA_PACKET;
      register_fis->features |= ATA_PACKET_FEATURE_DMA;

      register_fis->fis_type = SATA_FIS_TYPE_REGH2D;
      register_fis->command_flag = 1;

      status = SATI_SUCCESS;
   }

   return status;
}