예제 #1
0
/**
 * @brief This methods check each smp device in this domain. If there is at
 *        least one smp device in discover or target reset activity, this
 *        domain is considered in smp activity. Note this routine is not
 *        called on fast IO path.
 *
 * @param[in] fw_domain The framework domain object
 *
 * @return BOOL value to indicate whether a domain is in SMP activity.
 */
BOOL scif_sas_domain_is_in_smp_activity(
   SCIF_SAS_DOMAIN_T        * fw_domain
)
{
   SCI_ABSTRACT_ELEMENT_T * current_element =
      sci_abstract_list_get_front(&fw_domain->remote_device_list);

   SCIF_SAS_REMOTE_DEVICE_T * current_device;

   while ( current_element != NULL )
   {
      SMP_DISCOVER_RESPONSE_PROTOCOLS_T  dev_protocols;

      current_device = (SCIF_SAS_REMOTE_DEVICE_T *)
                       sci_abstract_list_get_object(current_element);

      scic_remote_device_get_protocols(current_device->core_object,
                                       &dev_protocols
      );

      if (dev_protocols.u.bits.attached_smp_target &&
          scif_sas_smp_remote_device_is_in_activity(current_device))
         return TRUE;

      current_element =
         sci_abstract_list_get_next(current_element);
   }

   return FALSE;
}
예제 #2
0
/**
 * @brief This methods finds the first device that has specific activity scheduled.
 *
 * @param[in] fw_domain The framework domain object
 * @param[in] smp_activity A specified smp activity. The valid range is [1,5].
 *
 * @return SCIF_SAS_REMOTE_DEVICE_T The device that has specified smp activity scheduled.
 */
SCIF_SAS_REMOTE_DEVICE_T * scif_sas_domain_find_device_has_scheduled_activity(
   SCIF_SAS_DOMAIN_T        * fw_domain,
   U8                         smp_activity
)
{
   SCI_ABSTRACT_ELEMENT_T * current_element =
      sci_abstract_list_get_front(&fw_domain->remote_device_list);

   SCIF_SAS_REMOTE_DEVICE_T * current_device;
   SMP_DISCOVER_RESPONSE_PROTOCOLS_T  dev_protocols;

   //config route table activity has higher priority than discover activity.
   while ( current_element != NULL )
   {
      current_device = (SCIF_SAS_REMOTE_DEVICE_T *)
                       sci_abstract_list_get_object(current_element);

      scic_remote_device_get_protocols(current_device->core_object,
                                       &dev_protocols);

      current_element =
         sci_abstract_list_get_next(current_element);

      if ( dev_protocols.u.bits.attached_smp_target
          && current_device->protocol_device.smp_device.scheduled_activity ==
                smp_activity)
      {
         return current_device;
      }
   }

   return NULL;
}
예제 #3
0
/**
 * @brief This method searches the whole domain and finds all the smp devices to
 *        cancel their smp activities if there is any.
 *
 * @param[in] fw_domain The domain that its smp activities are to be canceled.
 *
 * @return none.
 */
void scif_sas_domain_cancel_smp_activities(
   SCIF_SAS_DOMAIN_T * fw_domain
)
{
   SCI_ABSTRACT_ELEMENT_T * current_element =
      sci_abstract_list_get_front(&fw_domain->remote_device_list);

   SCIF_SAS_REMOTE_DEVICE_T * current_device;

   //purge all the outstanding internal IOs in HPQ.
   scif_sas_high_priority_request_queue_purge_domain(
      &fw_domain->controller->hprq, fw_domain
   );

   while ( current_element != NULL )
   {
      SMP_DISCOVER_RESPONSE_PROTOCOLS_T  dev_protocols;

      current_device = (SCIF_SAS_REMOTE_DEVICE_T *)
                       sci_abstract_list_get_object(current_element);

      scic_remote_device_get_protocols(current_device->core_object,
                                       &dev_protocols
      );

      if (dev_protocols.u.bits.attached_smp_target)
      {
         scif_sas_smp_remote_device_cancel_smp_activity(current_device);
      }

      current_element =
         sci_abstract_list_get_next(current_element);
   }
}
예제 #4
0
/**
 * @brief This method schedule clear affiliation activities for smp devices in
 *           this domain.
 *
 * @param[in] fw_domain The domain that its smp devices are scheduled to clear
 *                affiliation for all the EA SATA devices.
 *
 * @return none.
 */
void scif_sas_domain_schedule_clear_affiliation(
   SCIF_SAS_DOMAIN_T * fw_domain
)
{
   SCI_ABSTRACT_ELEMENT_T * current_element =
      sci_abstract_list_get_front(&fw_domain->remote_device_list);

   SCIF_SAS_REMOTE_DEVICE_T * current_device;
   SMP_DISCOVER_RESPONSE_PROTOCOLS_T  dev_protocols;

   //config route table activity has higher priority than discover activity.
   while ( current_element != NULL )
   {
      current_device = (SCIF_SAS_REMOTE_DEVICE_T *)
                       sci_abstract_list_get_object(current_element);

      scic_remote_device_get_protocols(current_device->core_object,
                                       &dev_protocols);

      current_element =
         sci_abstract_list_get_next(current_element);

      if ( dev_protocols.u.bits.attached_smp_target )
      {
         current_device->protocol_device.smp_device.scheduled_activity =
            SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_CLEAR_AFFILIATION;
      }
   }
}
/**
 * @brief This method finds the next smp phy (from the anchor_phy) that link to
 *           a SATA end device.
 *
 * @param[in] fw_device the framework SMP device that is clearing affiliation for
 *               its remote SATA devices'
 *
 * @return SCIF_SAS_SMP_PHY_T a smp phy, to which clear affiliation phy control command
 *            is to be sent.
 */
static
SCIF_SAS_SMP_PHY_T * scif_sas_smp_remote_device_find_next_smp_phy_link_to_sata(
   SCIF_SAS_SMP_PHY_T * anchor_phy
)
{
   SCI_FAST_LIST_ELEMENT_T  * element = &anchor_phy->list_element;
   SCIF_SAS_SMP_PHY_T * curr_smp_phy = NULL;

   while (element != NULL)
   {
      curr_smp_phy = (SCIF_SAS_SMP_PHY_T*) sci_fast_list_get_object(element);
      element = sci_fast_list_get_next(element);

      if (curr_smp_phy->attached_device_type == SMP_END_DEVICE_ONLY
          && curr_smp_phy->u.end_device != NULL)
      {
         SMP_DISCOVER_RESPONSE_PROTOCOLS_T  dev_protocols;
         scic_remote_device_get_protocols(
            curr_smp_phy->u.end_device->core_object, &dev_protocols);

         if (dev_protocols.u.bits.attached_stp_target)
            return curr_smp_phy;
      }
   }

   return NULL;
}
/**
 * @brief This method provides OPERATIONAL sub-state specific handling for
 *        when a user attempts to start a high priority IO request on a remote
 *        device.
 *
 * @param[in]  remote_device This parameter specifies the remote device
 *             object on which the user is attempting to perform a start
 *             IO operation.
 * @param[in]  io_request This parameter specifies the IO request to be
 *             started.
 *
 * @return This method returns an indication as to whether the IO request
 *         started successfully.
 */
static
SCI_STATUS scif_sas_remote_device_ready_operational_start_high_priority_io_handler(
   SCI_BASE_REMOTE_DEVICE_T * remote_device,
   SCI_BASE_REQUEST_T       * io_request
)
{
   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
                                          remote_device;
   SCIF_SAS_IO_REQUEST_T    * fw_io     = (SCIF_SAS_IO_REQUEST_T*) io_request;

   SMP_DISCOVER_RESPONSE_PROTOCOLS_T  dev_protocols;

   scic_remote_device_get_protocols(fw_device->core_object, &dev_protocols);

   if (dev_protocols.u.bits.attached_smp_target)
   {
      //transit to task management state for smp request phase.
      if (fw_device->ready_substate_machine.current_state_id
       != SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_TASK_MGMT)
      {
         sci_base_state_machine_change_state(
            &fw_device->ready_substate_machine,
            SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_TASK_MGMT
         );
      }
   }

   fw_device->request_count++;

   return fw_io->parent.state_handlers->start_handler(&fw_io->parent.parent);
}
예제 #7
0
BOOL scic_cb_request_is_initial_construction(
   void * scic_user_io_request
)
{
   SCIF_SAS_REQUEST_T * fw_request = (SCIF_SAS_REQUEST_T*)
                                   scic_user_io_request;
   SCIF_SAS_REMOTE_DEVICE_T* fw_device = fw_request->device;

   SMP_DISCOVER_RESPONSE_PROTOCOLS_T  dev_protocols;
   scic_remote_device_get_protocols(fw_device->core_object, &dev_protocols);

   if (dev_protocols.u.bits.attached_stp_target
       && fw_request->stp.sequence.state == SATI_SEQUENCE_STATE_INCOMPLETE)
      return FALSE;

   return TRUE;
}
예제 #8
0
/**
 * @brief This method performs domain object handling for core remote
 *        device start complete notifications.  Core remote device starts
 *        and start completes are only done during discovery.  This could
 *        ultimately be wrapped into a handler method on the domain (they
 *        actually already exist).  This method will decrement the number
 *        of device start operations ongoing and attempt to determine if
 *        discovery is complete.
 *
 * @param[in]  fw_domain This parameter specifies the domain object for
 *             which to perform initialization.
 *
 * @return none
 */
void scif_sas_domain_remote_device_start_complete(
   SCIF_SAS_DOMAIN_T        * fw_domain,
   SCIF_SAS_REMOTE_DEVICE_T * fw_device
)
{
   SMP_DISCOVER_RESPONSE_PROTOCOLS_T  dev_protocols;

   SCIF_LOG_TRACE((
      sci_base_object_get_logger(fw_domain),
      SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
      "scif_sas_domain_remote_device_start_complete(0x%x, 0x%x) enter\n",
      fw_domain, fw_device
   ));

   // If a device is being started/start completed, then we must be
   // during discovery.
   ASSERT(fw_domain->parent.state_machine.current_state_id
          == SCI_BASE_DOMAIN_STATE_DISCOVERING);

   scic_remote_device_get_protocols(fw_device->core_object, &dev_protocols);

   // Decrement the number of devices being started and check to see
   // if all have finished being started or failed as the case may be.
   fw_domain->device_start_in_progress_count--;

   if ( dev_protocols.u.bits.attached_smp_target )
   {
      if ( fw_device->containing_device == NULL )
         //kick off the smp discover process if this expander is direct attached.
         scif_sas_smp_remote_device_start_discover(fw_device);
      else
         //mark this device, the discover process of this device will start after
         //its containing smp device finish discover.
         fw_device->protocol_device.smp_device.scheduled_activity =
            SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_DISCOVER;
   }
   else
   {
      fw_domain->state_handlers->device_start_complete_handler(
         &fw_domain->parent, &fw_device->parent
      );
   }
}
static
SCI_STATUS scic_sds_remote_node_context_tx_suspended_state_resume_handler(
   SCIC_SDS_REMOTE_NODE_CONTEXT_T         * this_rnc,
   SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK   the_callback,
   void                                   * callback_parameter
)
{
   SMP_DISCOVER_RESPONSE_PROTOCOLS_T protocols;

   scic_sds_remote_node_context_setup_to_resume(
      this_rnc, the_callback, callback_parameter
         );

   // If this is an expander attached SATA device we must invalidate
   // and repost the RNC since this is the only way to clear the
   // TCi to NCQ tag mapping table for the RNi
   // All other device types we can just resume.
   scic_remote_device_get_protocols(this_rnc->device, &protocols);

   if (
      (protocols.u.bits.attached_stp_target == 1)
         && !(this_rnc->device->is_direct_attached)
         )
   {
      sci_base_state_machine_change_state(
         &this_rnc->state_machine,
         SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
            );
   }
   else
   {
      sci_base_state_machine_change_state(
         &this_rnc->state_machine,
         SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
            );
   }

   return SCI_SUCCESS;
}
예제 #10
0
/**
 * @brief This method update the direct attached device port width.
 *
 * @param[in] fw_domain The framework domain object
 * @param[in] port The associated port object which recently has link up/down
 *                 event happened.
 *
 * @return none
 */
void scif_sas_domain_update_device_port_width(
   SCIF_SAS_DOMAIN_T * fw_domain,
   SCI_PORT_HANDLE_T   port
)
{
   SCIF_SAS_REMOTE_DEVICE_T * fw_device;
   SCIC_PORT_PROPERTIES_T     properties;
   U8                         new_port_width = 0;

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

   scic_port_get_properties(port, &properties);

   fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)
                  scif_domain_get_device_by_sas_address(
                  fw_domain, &properties.remote.sas_address
               );

   // If the device already existed in the domain, it is a wide port SSP target,
   // we need to update its port width.
   if (fw_device != SCI_INVALID_HANDLE)
   {
      SMP_DISCOVER_RESPONSE_PROTOCOLS_T  dev_protocols;
      scic_remote_device_get_protocols(fw_device->core_object, &dev_protocols);

      if (dev_protocols.u.bits.attached_ssp_target)
      {
         //Get accurate port width from port's phy mask for a DA device.
         SCI_GET_BITS_SET_COUNT(properties.phy_mask, new_port_width);

         scif_sas_remote_device_update_port_width(fw_device, new_port_width);
      }
   }
}
/**
 * @brief This method provides STOPPED state specific handling for
 *        when the user attempts to destruct the remote device.
 *
 * @param[in]  remote_device This parameter specifies the remote device
 *             object for which the framework is attempting to start.
 *
 * @return This method returns an indication as to whether the destruct
 *         operation completed successfully.
 */
static
SCI_STATUS scif_sas_remote_device_stopped_destruct_handler(
   SCI_BASE_REMOTE_DEVICE_T * remote_device
)
{
   SCI_STATUS                 status;
   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)
                                          remote_device;

   SMP_DISCOVER_RESPONSE_PROTOCOLS_T  dev_protocols;
   scic_remote_device_get_protocols(fw_device->core_object, &dev_protocols);

   //For smp device, need to clear its smp phy list first.
   if(dev_protocols.u.bits.attached_smp_target)
      scif_sas_smp_remote_device_removed(fw_device);

   status = scic_remote_device_destruct(fw_device->core_object);
   if (status == SCI_SUCCESS)
   {
      sci_base_state_machine_change_state(
         &fw_device->parent.state_machine, SCI_BASE_REMOTE_DEVICE_STATE_FINAL
      );

      scif_sas_remote_device_deinitialize_state_logging(fw_device);
   }
   else
   {
      SCIF_LOG_ERROR((
         sci_base_object_get_logger(fw_device),
         SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_REMOTE_DEVICE_CONFIG,
         "Device:0x%x Status:0x%x failed to destruct core device\n",
         fw_device
      ));
   }

   return status;
}
/**
*
*
* @param[in] object
*/
static
void scic_sds_remote_node_context_resuming_state_enter(
   SCI_BASE_OBJECT_T * object
)
{
   SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
   SMP_DISCOVER_RESPONSE_PROTOCOLS_T protocols;
   rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T  *)object;

   SET_STATE_HANDLER(
      rnc,
      scic_sds_remote_node_context_state_handler_table,
      SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
         );

   // For direct attached SATA devices we need to clear the TLCR
   // NCQ to TCi tag mapping on the phy and in cases where we
   // resume because of a target reset we also need to update
   // the STPTLDARNI register with the RNi of the device
   scic_remote_device_get_protocols(rnc->device, &protocols);

   if (
      (protocols.u.bits.attached_stp_target == 1)
         && (rnc->device->is_direct_attached)
         )
   {
      scic_sds_port_setup_transports(
         rnc->device->owning_port, rnc->remote_node_index
            );
   }

   scic_sds_remote_device_post_request(
      rnc->device,
      SCU_CONTEXT_COMMAND_POST_RNC_RESUME
         );
}
/**
 * @brief This method provides OPERATIONAL sub-state specific handling for
 *        when a user attempts to start a task management request on
 *        a remote device.  This includes terminating all of the affected
 *        ongoing IO requests (i.e. aborting them in the silicon) and then
 *        issuing the task management request to the silicon.
 *
 * @param[in]  remote_device This parameter specifies the remote device
 *             object on which the user is attempting to perform a start
 *             task operation.
 * @param[in]  task_request This parameter specifies the task management
 *             request to be started.
 *
 * @return This method returns an indication as to whether the task
 *         management request started successfully.
 */
static
SCI_STATUS scif_sas_remote_device_ready_operational_start_task_handler(
   SCI_BASE_REMOTE_DEVICE_T * remote_device,
   SCI_BASE_REQUEST_T       * task_request
)
{
   SCI_STATUS                 status     = SCI_FAILURE;
   SCIF_SAS_REMOTE_DEVICE_T * fw_device  = (SCIF_SAS_REMOTE_DEVICE_T*)
                                           remote_device;
   SCIF_SAS_TASK_REQUEST_T  * fw_task    = (SCIF_SAS_TASK_REQUEST_T*)
                                           task_request;
   U8 task_function =
         scif_sas_task_request_get_function(fw_task);

   SMP_DISCOVER_RESPONSE_PROTOCOLS_T  dev_protocols;

   scic_remote_device_get_protocols(fw_device->core_object, &dev_protocols);
   if (   dev_protocols.u.bits.attached_ssp_target
       || dev_protocols.u.bits.attached_stp_target)
   {
      // //NOTE: For STP/SATA targets we currently terminate all requests for
      //       any type of task management.
      if (  (task_function == SCI_SAS_ABORT_TASK_SET)
         || (task_function == SCI_SAS_CLEAR_TASK_SET)
         || (task_function == SCI_SAS_LOGICAL_UNIT_RESET)
         || (task_function == SCI_SAS_I_T_NEXUS_RESET)
         || (task_function == SCI_SAS_HARD_RESET) )
      {
         // Terminate all of the requests in the silicon for this device.
         scif_sas_domain_terminate_requests(
            fw_device->domain, fw_device, NULL, fw_task
         );

         status = scif_sas_remote_device_start_task_request(fw_device, fw_task);
      }
      else if (  (task_function == SCI_SAS_CLEAR_ACA)
              || (task_function == SCI_SAS_QUERY_TASK)
              || (task_function == SCI_SAS_QUERY_TASK_SET)
              || (task_function == SCI_SAS_QUERY_ASYNCHRONOUS_EVENT) )
      {
       ASSERT(!dev_protocols.u.bits.attached_stp_target);
         status = scif_sas_remote_device_start_task_request(fw_device, fw_task);
      }
      else if (task_function == SCI_SAS_ABORT_TASK)
      {
         SCIF_SAS_REQUEST_T * fw_request
            = scif_sas_domain_get_request_by_io_tag(
                 fw_device->domain, fw_task->io_tag_to_manage
              );

         // Determine if the request being aborted was found.
         if (fw_request != NULL)
         {
            scif_sas_domain_terminate_requests(
               fw_device->domain, fw_device, fw_request, fw_task
            );

            status = scif_sas_remote_device_start_task_request(
                        fw_device, fw_task
                     );
         }
         else
            status = SCI_FAILURE_INVALID_IO_TAG;
      }
   }
   else
      status = SCI_FAILURE_UNSUPPORTED_PROTOCOL;

   if (status != SCI_SUCCESS)
   {
      SCIF_LOG_ERROR((
         sci_base_object_get_logger(fw_device),
         SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_TASK_MANAGEMENT,
         "Controller:0x%x TaskRequest:0x%x Status:0x%x start task failure\n",
         fw_device, fw_task, status
      ));
   }

   return status;
}
예제 #14
0
static
SCI_STATUS scif_sas_task_request_generic_construct(
   SCI_CONTROLLER_HANDLE_T      scif_controller,
   SCI_REMOTE_DEVICE_HANDLE_T   scif_remote_device,
   U16                          io_tag,
   void                       * user_task_request_object,
   void                       * task_request_memory,
   SCI_TASK_REQUEST_HANDLE_T  * scif_task_request,
   U8                           task_function
)
{
   SCI_STATUS                 status;
   SCIF_SAS_CONTROLLER_T    * fw_controller   = (SCIF_SAS_CONTROLLER_T*)
                                                scif_controller;
   SCIF_SAS_TASK_REQUEST_T  * fw_task         = (SCIF_SAS_TASK_REQUEST_T*)
                                                task_request_memory;
   SCIF_SAS_REMOTE_DEVICE_T * fw_device       = (SCIF_SAS_REMOTE_DEVICE_T*)
                                                scif_remote_device;
   U8                       * core_request_memory;

   SCIF_LOG_TRACE((
      sci_base_object_get_logger(fw_controller),
      SCIF_LOG_OBJECT_TASK_MANAGEMENT,
      "scif_task_request_construct(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x) enter\n",
      scif_controller, scif_remote_device, io_tag, user_task_request_object,
      task_request_memory, scif_task_request
   ));

   // Initialize the user's handle to the framework task request.
   *scif_task_request = fw_task;

   // initialize affected request count
   fw_task->affected_request_count = 0;
   fw_task->io_tag_to_manage = SCI_CONTROLLER_INVALID_IO_TAG;
   fw_task->function = task_function;

   if (task_function == SCI_SAS_HARD_RESET )
   {
      if (fw_device->containing_device != NULL )
      {// Target Reset is for an expander attached device,
       // go down to construct smp Phy Control request.
         scif_sas_smp_request_construct_phy_control(
            fw_controller,
            fw_device->containing_device,
            PHY_OPERATION_HARD_RESET,
            fw_device->expander_phy_identifier,
            user_task_request_object,
            task_request_memory
         );
      }
      else
      {
         scif_sas_request_construct(
            &fw_task->parent,
            fw_device,
            sci_base_object_get_logger(fw_controller),
            scif_sas_task_request_state_table
         );

         // If target reset is for a DA device, don't build task at all.
         // Just set object association.
         sci_object_set_association(fw_task, user_task_request_object);
      }

      return SCI_SUCCESS;
   }

   // Construct the parent object first in order to ensure logging can
   // function.
   scif_sas_request_construct(
      &fw_task->parent,
      fw_device,
      sci_base_object_get_logger(fw_controller),
      scif_sas_task_request_state_table
   );

   core_request_memory = (U8 *)task_request_memory + sizeof(SCIF_SAS_TASK_REQUEST_T);

   status = scic_task_request_construct(
               fw_controller->core_object,
               fw_device->core_object,
               io_tag,
               fw_task,
               core_request_memory,
               &fw_task->parent.core_object
            );

   if (status == SCI_SUCCESS)
   {
      SMP_DISCOVER_RESPONSE_PROTOCOLS_T  dev_protocols;

      // These associations must be set early for the core io request
      // object construction to complete correctly as there will be
      // callbacks into the user driver framework during core construction
      sci_object_set_association(fw_task, user_task_request_object);
      sci_object_set_association(fw_task->parent.core_object, fw_task);

      // Perform protocol specific core IO request construction.
      scic_remote_device_get_protocols(fw_device->core_object, &dev_protocols);
      if (dev_protocols.u.bits.attached_ssp_target)
         status = scic_task_request_construct_ssp(fw_task->parent.core_object);
      else if (dev_protocols.u.bits.attached_stp_target)
         status = scif_sas_stp_task_request_construct(fw_task);
      else
         status = SCI_FAILURE_UNSUPPORTED_PROTOCOL;

      if (status == SCI_SUCCESS)
      {
         sci_base_state_machine_logger_initialize(
            &fw_task->parent.parent.state_machine_logger,
            &fw_task->parent.parent.state_machine,
            &fw_task->parent.parent.parent,
            scif_cb_logger_log_states,
            "SCIF_SAS_TASK_REQUEST_T", "base_state_machine",
            SCIF_LOG_OBJECT_TASK_MANAGEMENT
         );
      }
      else
      {
         SCIF_LOG_WARNING((
            sci_base_object_get_logger(fw_task),
            SCIF_LOG_OBJECT_TASK_MANAGEMENT,
            "Device:0x%x TaskRequest:0x%x Function:0x%x construct failed\n",
            fw_device, fw_task, scif_sas_task_request_get_function(fw_task)
         ));
      }
   }

   return status;
}
예제 #15
0
/**
 * @brief This method represents common functionality for the
 *        scif_io_request_construct() and scif_sas_io_request_continue()
 *        methods.
 *
 * @return This method returns an indication as to whether the
 *         construction succeeded.
 */
static
SCI_STATUS scif_sas_io_request_construct(
   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
   SCIF_SAS_IO_REQUEST_T    * fw_io,
   U16                        io_tag,
   void                     * user_io_request_object,
   SCI_IO_REQUEST_HANDLE_T  * scif_io_request,
   BOOL                       is_initial_construction
)
{
   SCI_STATUS                         status;
   SMP_DISCOVER_RESPONSE_PROTOCOLS_T  dev_protocols;

   scic_remote_device_get_protocols(fw_device->core_object, &dev_protocols);

   //Currently, all the io requests sent to smp target are internal.
   //so we fail all the external io toward to it.
   //Todo: is there a better way to handle external io to smp target?
   if (dev_protocols.u.bits.attached_smp_target)
      return SCI_FAILURE_INVALID_REMOTE_DEVICE;

   SCIF_LOG_TRACE((
      sci_base_object_get_logger(fw_device),
      SCIF_LOG_OBJECT_IO_REQUEST,
      "scif_sas_io_request_construct(0x%x,0x%x,0x%x,0x%x,0x%x,0x%x) enter\n",
      fw_device, fw_io, io_tag, user_io_request_object, scif_io_request,
      is_initial_construction
   ));

   // Initialize the users handle to the framework IO request.
   *scif_io_request = fw_io;

   // Construct the parent object first in order to ensure logging can
   // function.
   scif_sas_request_construct(
      &fw_io->parent,
      fw_device,
      sci_base_object_get_logger(fw_device),
      scif_sas_io_request_state_table
   );

   status = scic_io_request_construct(
               fw_device->domain->controller->core_object,
               fw_device->core_object,
               io_tag,
               fw_io,
               ((U8 *)fw_io) + sizeof(SCIF_SAS_IO_REQUEST_T),
               &fw_io->parent.core_object
            );

   if (status == SCI_SUCCESS)
   {
      // These associations must be set early for the core io request
      // object construction to complete correctly as there will be
      // callbacks into the user driver framework during core construction
      sci_object_set_association(fw_io, user_io_request_object);
      sci_object_set_association(fw_io->parent.core_object, fw_io);

      // Perform protocol specific core IO request construction.
      if (dev_protocols.u.bits.attached_ssp_target)
         status = scic_io_request_construct_basic_ssp(fw_io->parent.core_object);
      else if (dev_protocols.u.bits.attached_stp_target)
      {
         if (is_initial_construction == TRUE)
               sati_sequence_construct(&fw_io->parent.stp.sequence);

#if !defined(DISABLE_ATAPI)
         if (!scic_remote_device_is_atapi(fw_device->core_object))
         {
#endif
            status = scif_sas_stp_io_request_construct(fw_io);

#if !defined(DISABLE_ATAPI)
         }
         else
            status = scif_sas_stp_packet_io_request_construct(fw_io);
#endif
      }

      sci_base_state_machine_logger_initialize(
         &fw_io->parent.parent.state_machine_logger,
         &fw_io->parent.parent.state_machine,
         &fw_io->parent.parent.parent,
         scif_cb_logger_log_states,
         "SCIF_IO_REQUEST_T", "base_state_machine",
         SCIF_LOG_OBJECT_IO_REQUEST
      );
   }

   return status;
}