/** * 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; }
/** * @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; }