/**
 * This method will perform the STP request (both io or task) completion
 * processing for await reset state.
 *
 * @param[in] device This parameter specifies the device for which the
 *            request is being completed.
 * @param[in] request This parameter specifies the request being completed.
 *
 * @return This method returns an indication as to whether the request
 *         processing completed successfully.
 */
static
SCI_STATUS scic_sds_stp_remote_device_ready_await_reset_substate_complete_request_handler(
   SCI_BASE_REMOTE_DEVICE_T * device,
   SCI_BASE_REQUEST_T       * request
)
{
   SCIC_SDS_REMOTE_DEVICE_T * this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
   SCIC_SDS_REQUEST_T       * the_request = (SCIC_SDS_REQUEST_T *)request;
   SCI_STATUS                 status;

   status = scic_sds_io_request_complete(the_request);

   if (status == SCI_SUCCESS)
   {
      status = scic_sds_port_complete_io(
                  this_device->owning_port, this_device, the_request
               );

      if (status == SCI_SUCCESS)
         scic_sds_remote_device_decrement_request_count(this_device);
   }

   if (status != SCI_SUCCESS)
   {
      SCIC_LOG_ERROR((
         sci_base_object_get_logger(this_device),
         SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
         "Port:0x%x Device:0x%x Request:0x%x Status:0x%x could not complete\n",
         this_device->owning_port, this_device, the_request, status
      ));
   }

   return status;
}
/**
 * This method will construct the port configuration agent for this controller.
 *
 * @param[in] controller This is the controller object for which the port
 *            agent is being initialized.
 *
 * @param[in] port_agent This is the port configuration agent that is being
 *            initialized.  The initialization path is handled differntly
 *            for the automatic port configuration agent and the manual port
 *            configuration agent.
 *
 * @return
 */
SCI_STATUS scic_sds_port_configuration_agent_initialize(
   SCIC_SDS_CONTROLLER_T               * controller,
   SCIC_SDS_PORT_CONFIGURATION_AGENT_T * port_agent
)
{
   SCI_STATUS status = SCI_SUCCESS;
   enum SCIC_PORT_CONFIGURATION_MODE mode;

   SCIC_LOG_TRACE((
      sci_base_object_get_logger(controller),
      SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_PORT,
      "scic_sds_port_configuration_agent_initialize(0x%08x, 0x%08x) enter\n",
      controller, port_agent
   ));

   mode = controller->oem_parameters.sds1.controller.mode_type;

   if (mode == SCIC_PORT_MANUAL_CONFIGURATION_MODE)
   {
      status = scic_sds_mpc_agent_validate_phy_configuration(controller, port_agent);

      port_agent->link_up_handler = scic_sds_mpc_agent_link_up;
      port_agent->link_down_handler = scic_sds_mpc_agent_link_down;

      port_agent->timer = scic_cb_timer_create(
                              controller,
                              scic_sds_mpc_agent_timeout_handler,
                              controller
                          );
   }
   else
   {
      status = scic_sds_apc_agent_validate_phy_configuration(controller, port_agent);

      port_agent->link_up_handler = scic_sds_apc_agent_link_up;
      port_agent->link_down_handler = scic_sds_apc_agent_link_down;

      port_agent->timer = scic_cb_timer_create(
                              controller,
                              scic_sds_apc_agent_timeout_handler,
                              controller
                          );
   }

   // Make sure we have actually gotten a timer
   if (status == SCI_SUCCESS && port_agent->timer == NULL)
   {
      SCIC_LOG_ERROR((
         sci_base_object_get_logger(controller),
         SCIC_LOG_OBJECT_CONTROLLER,
         "Controller 0x%x automatic port configuration agent could not get timer.\n",
         controller
     ));

     status = SCI_FAILURE;
   }

   return status;
}
/**
 * This method will perform the STP request completion processing common
 * to IO requests and task requests of all types
 *
 * @param[in] device This parameter specifies the device for which the
 *            request is being completed.
 * @param[in] request This parameter specifies the request being completed.
 *
 * @return This method returns an indication as to whether the request
 *         processing completed successfully.
 */
static
SCI_STATUS scic_sds_stp_remote_device_complete_request(
   SCI_BASE_REMOTE_DEVICE_T * device,
   SCI_BASE_REQUEST_T       * request
)
{
   SCIC_SDS_REMOTE_DEVICE_T * this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
   SCIC_SDS_REQUEST_T       * the_request = (SCIC_SDS_REQUEST_T *)request;
   SCI_STATUS                 status;

   status = scic_sds_io_request_complete(the_request);

   if (status == SCI_SUCCESS)
   {
      status = scic_sds_port_complete_io(
                  this_device->owning_port, this_device, the_request
               );

      if (status == SCI_SUCCESS)
      {
         scic_sds_remote_device_decrement_request_count(this_device);
         if (the_request->sci_status == SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED)
         {
            //This request causes hardware error, device needs to be Lun Reset.
            //So here we force the state machine to IDLE state so the rest IOs
            //can reach RNC state handler, these IOs will be completed by RNC with
            //status of "DEVICE_RESET_REQUIRED", instead of "INVALID STATE".
            sci_base_state_machine_change_state(
               &this_device->ready_substate_machine,
               SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET
            );
         }
         else if (scic_sds_remote_device_get_request_count(this_device) == 0)
         {
            sci_base_state_machine_change_state(
               &this_device->ready_substate_machine,
               SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE
            );
         }
      }
   }

   if (status != SCI_SUCCESS)
   {
      SCIC_LOG_ERROR((
         sci_base_object_get_logger(this_device),
         SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
         "Port:0x%x Device:0x%x Request:0x%x Status:0x%x could not complete\n",
         this_device->owning_port, this_device, the_request, status
      ));
   }

   return status;
}
/**
 * @brief this is the complete_io_handler for smp device at ready cmd substate.
 *
 * @param[in] device This is the device object that is receiving the IO.
 * @param[in] request The io to start.
 *
 * @return SCI_STATUS
 */
static
SCI_STATUS scic_sds_smp_remote_device_ready_cmd_substate_complete_io_handler(
   SCI_BASE_REMOTE_DEVICE_T * device,
   SCI_BASE_REQUEST_T       * request
)
{
   SCI_STATUS                 status;
   SCIC_SDS_REMOTE_DEVICE_T * this_device;
   SCIC_SDS_REQUEST_T       * the_request;

   this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
   the_request = (SCIC_SDS_REQUEST_T       *)request;

   status = scic_sds_io_request_complete(the_request);

   if (status == SCI_SUCCESS)
   {
      status = scic_sds_port_complete_io(
         this_device->owning_port, this_device, the_request);

      if (status == SCI_SUCCESS)
      {
       scic_sds_remote_device_decrement_request_count(this_device);
         sci_base_state_machine_change_state(
            &this_device->ready_substate_machine,
            SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE
         );
      }
      else
      {
         SCIC_LOG_ERROR((
            sci_base_object_get_logger(this_device),
            SCIC_LOG_OBJECT_SMP_REMOTE_TARGET,
            "SCIC SDS Remote Device 0x%x io request 0x%x could not be completd on the port 0x%x failed with status %d.\n",
            this_device, the_request, this_device->owning_port, status
         ));
      }
   }

   return status;
}
Beispiel #5
0
/**
 * @brief This method processes an unsolicited frame while the SMP request is
 *        waiting for a response frame.  It will copy the response data, release
 *        the unsolicited frame, and transition the request to the
 *        SCI_BASE_REQUEST_STATE_COMPLETED state.
 *
 * @param[in] this_request This parameter specifies the request for which
 *            the unsolicited frame was received.
 * @param[in] frame_index This parameter indicates the unsolicited frame
 *            index that should contain the response.
 *
 * @return This method returns an indication of whether the response
 *         frame was handled successfully or not.
 * @retval SCI_SUCCESS Currently this value is always returned and indicates
 *         successful processing of the TC response.
 */
static
SCI_STATUS scic_sds_smp_request_await_response_frame_handler(
   SCIC_SDS_REQUEST_T * this_request,
   U32                  frame_index
)
{
   SCI_STATUS              status;
   void                  * frame_header;
   SMP_RESPONSE_HEADER_T * this_frame_header;
   U8                    * user_smp_buffer = this_request->response_buffer;

   // Save off the controller, so that we do not touch the request after it
   //  is completed.
   SCIC_SDS_CONTROLLER_T * controller = scic_sds_request_get_controller(this_request);

   SCIC_LOG_TRACE((
      sci_base_object_get_logger(this_request),
      SCIC_LOG_OBJECT_SMP_IO_REQUEST,
      "scic_sds_smp_request_await_response_frame_handler(0x%x, 0x%x) enter\n",
      this_request, frame_index
   ));

   status = scic_sds_unsolicited_frame_control_get_header(
      &(controller->uf_control),
      frame_index,
      &frame_header
   );

   //byte swap the header.
   scic_word_copy_with_swap(
      (U32*) user_smp_buffer,
      frame_header,
      sizeof(SMP_RESPONSE_HEADER_T)/sizeof(U32)
   );
   this_frame_header = (SMP_RESPONSE_HEADER_T*) user_smp_buffer;

   if (this_frame_header->smp_frame_type == SMP_FRAME_TYPE_RESPONSE)
   {
      void * smp_response_buffer;

      status = scic_sds_unsolicited_frame_control_get_buffer(
         &(controller->uf_control),
         frame_index,
         &smp_response_buffer
      );

      scic_word_copy_with_swap(
         (U32*) (user_smp_buffer + sizeof(SMP_RESPONSE_HEADER_T)),
         smp_response_buffer,
         sizeof(SMP_RESPONSE_BODY_T)/sizeof(U32)
      );
      if (this_frame_header->function == SMP_FUNCTION_DISCOVER)
      {
          SMP_RESPONSE_T * this_smp_response;

          this_smp_response = (SMP_RESPONSE_T *)user_smp_buffer;

          // Some expanders only report an attached SATA device, and
          // not an STP target.  Since the core depends on the STP
          // target attribute to correctly build I/O, set the bit now
          // if necessary.
          if (this_smp_response->response.discover.protocols.u.bits.attached_sata_device
           && !this_smp_response->response.discover.protocols.u.bits.attached_stp_target)
          {
              this_smp_response->response.discover.protocols.u.bits.attached_stp_target = 1;

              SCIC_LOG_TRACE((
                  sci_base_object_get_logger(this_request),
                 SCIC_LOG_OBJECT_SMP_IO_REQUEST,
                 "scic_sds_smp_request_await_response_frame_handler(0x%x) Found SATA dev, setting STP bit.\n",
                 this_request
              ));
          }
      }

     //Don't need to copy to user space. User instead will refer to
     //core request's response buffer.

     //copy the smp response to framework smp request's response buffer.
     //scic_sds_smp_request_copy_response(this_request);

      scic_sds_request_set_status(
         this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
      );

      sci_base_state_machine_change_state(
         &this_request->started_substate_machine,
         SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION
      );
   }
   else
   {
      // This was not a response frame why did it get forwarded?
      SCIC_LOG_ERROR((
         sci_base_object_get_logger(this_request),
         SCIC_LOG_OBJECT_SMP_IO_REQUEST,
         "SCIC SMP Request 0x%08x received unexpected frame %d type 0x%02x\n",
         this_request, frame_index, this_frame_header->smp_frame_type
      ));

     scic_sds_request_set_status(
        this_request,
        SCU_TASK_DONE_SMP_FRM_TYPE_ERR,
        SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
     );

     sci_base_state_machine_change_state(
         &this_request->parent.state_machine,
         SCI_BASE_REQUEST_STATE_COMPLETED
      );
   }

   scic_sds_controller_release_frame(
      controller, frame_index
   );

   return SCI_SUCCESS;
}