Пример #1
0
/**
 * @brief This methods finds the first device that is in STOPPED state and its
 *        connection_rate is still in SPINUP_HOLD(value 3).
 *
 * @param[in] fw_domain The framework domain object
 *
 * @return SCIF_SAS_REMOTE_DEVICE_T The device that is in SPINUP_HOLD or NULL.
 */
SCIF_SAS_REMOTE_DEVICE_T * scif_sas_domain_find_device_in_spinup_hold(
   SCIF_SAS_DOMAIN_T        * fw_domain
)
{
   SCI_ABSTRACT_ELEMENT_T   * current_element;
   SCIF_SAS_REMOTE_DEVICE_T * current_device;

   SCIF_LOG_TRACE((
      sci_base_object_get_logger(fw_domain),
      SCIF_LOG_OBJECT_DOMAIN,
      "scif_sas_domain_find_device_in_spinup_hold(0x%x) enter\n",
      fw_domain
   ));

   //search throught domain's device list to find the first sata device on spinup_hold
   current_element = sci_abstract_list_get_front(&fw_domain->remote_device_list);
   while (current_element != NULL )
   {
      current_device = (SCIF_SAS_REMOTE_DEVICE_T *)
                       sci_abstract_list_get_object(current_element);

      //We must get the next element before we remove the current
      //device. Or else, we will get wrong next_element, since the erased
      //element has been put into free pool.
      current_element = sci_abstract_list_get_next(current_element);

      if ( sci_base_state_machine_get_state(&current_device->parent.state_machine) ==
              SCI_BASE_REMOTE_DEVICE_STATE_STOPPED
          && scic_remote_device_get_connection_rate(current_device->core_object) ==
                SCI_SATA_SPINUP_HOLD )
      {
         return current_device;
      }
   }

   return NULL;
}
Пример #2
0
/**
 * @brief This method will fill in the SCU Task Context for a SMP request. The
 *        following important settings are utilized:
 *
 *          -# task_type == SCU_TASK_TYPE_SMP.  This simply indicates
 *             that a normal request type (i.e. non-raw frame) is being
 *             utilized to perform task management.
 *          -# control_frame == 1.  This ensures that the proper endianess
 *             is set so that the bytes are transmitted in the right order
 *             for a smp request frame.
 *
 * @param[in] this_request This parameter specifies the smp request object
 *            being constructed.
 *
 * @return none
 */
void scu_smp_request_construct_task_context(
   SCIC_SDS_REQUEST_T *this_request,
   SMP_REQUEST_T      *smp_request
)
{
   SCI_PHYSICAL_ADDRESS      physical_address;
   SCIC_SDS_CONTROLLER_T    *owning_controller;
   SCIC_SDS_REMOTE_DEVICE_T *target_device;
   SCIC_SDS_PORT_T          *target_port;
   SCU_TASK_CONTEXT_T *task_context;

   //byte swap the smp request.
   scic_word_copy_with_swap(
      this_request->command_buffer,
      (U32*) smp_request,
      sizeof(SMP_REQUEST_T)/sizeof(U32)
   );

   task_context = scic_sds_request_get_task_context(this_request);

   owning_controller = scic_sds_request_get_controller(this_request);
   target_device = scic_sds_request_get_device(this_request);
   target_port = scic_sds_request_get_port(this_request);

   SCIC_LOG_TRACE((
      sci_base_object_get_logger(this_request),
      SCIC_LOG_OBJECT_SMP_IO_REQUEST,
      "scu_smp_request_construct_task_context(0x%x) contents\n"
      "   reqlen=%x; function=%x;\n",
      this_request,
      smp_request->header.request_length,
      smp_request->header.function
   ));

   // Fill in the TC with the its required data
   // 00h
   task_context->priority = 0;
   task_context->initiator_request = 1;
   task_context->connection_rate =
      scic_remote_device_get_connection_rate(target_device);
   task_context->protocol_engine_index =
      scic_sds_controller_get_protocol_engine_group(owning_controller);
   task_context->logical_port_index =
      scic_sds_port_get_index(target_port);
   task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SMP;
   task_context->abort = 0;
   task_context->valid = SCU_TASK_CONTEXT_VALID;
   task_context->context_type = SCU_TASK_CONTEXT_TYPE;

   //04h
   task_context->remote_node_index = this_request->target_device->rnc->remote_node_index;
   task_context->command_code = 0;
   task_context->task_type = SCU_TASK_TYPE_SMP_REQUEST;

   //08h
   task_context->link_layer_control = 0;
   task_context->do_not_dma_ssp_good_response = 1;
   task_context->strict_ordering = 0;
   task_context->control_frame = 1;
   task_context->timeout_enable = 0;
   task_context->block_guard_enable = 0;

   //0ch
   task_context->address_modifier = 0;

   //10h
   task_context->ssp_command_iu_length = smp_request->header.request_length;

   //14h
   task_context->transfer_length_bytes = 0;

   //18h ~ 30h, protocol specific
   // since commandIU has been build by framework at this point, we just
   // copy the frist DWord from command IU to this location.
   memcpy((void *)(&task_context->type.smp), this_request->command_buffer, sizeof(U32) );

   //40h
   // "For SMP you could program it to zero. We would prefer that way so that
   // done code will be consistent." - Venki
   task_context->task_phase = 0;

   if (this_request->was_tag_assigned_by_user)
   {
      // Build the task context now since we have already read the data
      this_request->post_context = (
           SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC
         | (
                scic_sds_controller_get_protocol_engine_group(owning_controller)
             << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT
           )
         | (
                 scic_sds_port_get_index(target_port)
              << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT
           )
         | scic_sds_io_tag_get_index(this_request->io_tag)
      );
   }
   else
   {
      // Build the task context now since we have already read the data
      this_request->post_context = (
           SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC
         | (
               scic_sds_controller_get_protocol_engine_group(owning_controller)
            << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT
           )
         | (
                scic_sds_port_get_index(target_port)
             << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT
           )
         // This is not assigned because we have to wait until we get a TCi
      );
   }

   // Copy the physical address for the command buffer to the SCU Task Context
   // command buffer should not contain command header.
   scic_cb_io_request_get_physical_address(
         scic_sds_request_get_controller(this_request),
         this_request,
         ((char *)(this_request->command_buffer) + sizeof(U32)),
         &physical_address
      );

   task_context->command_iu_upper =
      sci_cb_physical_address_upper(physical_address);
   task_context->command_iu_lower =
      sci_cb_physical_address_lower(physical_address);


   //SMP response comes as UF, so no need to set response IU address.
   task_context->response_iu_upper = 0;
   task_context->response_iu_lower = 0;
}