void scic_cb_controller_stop_complete( SCI_CONTROLLER_HANDLE_T controller, SCI_STATUS completion_status ) { SCIF_SAS_CONTROLLER_T *fw_controller = (SCIF_SAS_CONTROLLER_T*) sci_object_get_association(controller); SCIF_LOG_TRACE(( sci_base_object_get_logger(controller), SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_SHUTDOWN, "scic_cb_controller_stop_complete(0x%x, 0x%x) enter\n", controller, completion_status )); if (completion_status == SCI_SUCCESS) { sci_base_state_machine_change_state( &fw_controller->parent.state_machine, SCI_BASE_CONTROLLER_STATE_STOPPED ); } else { sci_base_state_machine_change_state( &fw_controller->parent.state_machine, SCI_BASE_CONTROLLER_STATE_FAILED ); } scif_cb_controller_stop_complete(fw_controller, completion_status); }
/** * @brief This method is responsible for processing a terminate/abort * request for this TC while the request is waiting for the task * management response unsolicited frame. * * @param[in] this_request This parameter specifies the request for which * the termination was requested. * * @return This method returns an indication as to whether the abort * request was successfully handled. * * @todo need to update to ensure the received UF doesn't cause damage * to subsequent requests (i.e. put the extended tag in a holding * pattern for this particular device). */ static SCI_STATUS scic_sds_ssp_task_request_await_tc_response_abort_handler( SCI_BASE_REQUEST_T * request ) { SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)request; SCIC_LOG_TRACE(( sci_base_object_get_logger(this_request), SCIC_LOG_OBJECT_TASK_MANAGEMENT, "scic_sds_ssp_task_request_await_tc_response_abort_handler(0x%x) enter\n", this_request )); sci_base_state_machine_change_state( &this_request->parent.state_machine, SCI_BASE_REQUEST_STATE_ABORTING ); sci_base_state_machine_change_state( &this_request->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED ); return SCI_SUCCESS; }
/** * @brief This method provides STARTING AWAIT READY sub-state specific * handling for when the core provides a device ready notification * for the remote device. This essentially, causes a transition * of the framework remote device into the READY state. * * @param[in] fw_device This parameter specifies the remote device * object for which the notification has occurred. * * @return none. */ static void scif_sas_remote_device_starting_await_ready_ready_handler( SCIF_SAS_REMOTE_DEVICE_T * fw_device ) { #if !defined(DISABLE_WIDE_PORTED_TARGETS) if (fw_device->destination_state == SCIF_SAS_REMOTE_DEVICE_DESTINATION_STATE_UPDATING_PORT_WIDTH) { { sci_base_state_machine_change_state( &fw_device->parent.state_machine, SCI_BASE_REMOTE_DEVICE_STATE_UPDATING_PORT_WIDTH ); } } else #endif { sci_base_state_machine_change_state( &fw_device->parent.state_machine, SCI_BASE_REMOTE_DEVICE_STATE_READY ); } #if !defined(DISABLE_WIDE_PORTED_TARGETS) scif_sas_domain_remote_device_start_complete(fw_device->domain,fw_device); #endif }
/** * * * @param[in] this_device * @param[in] frame_index * * @return SCI_STATUS */ static SCI_STATUS scic_sds_stp_remote_device_ready_ncq_substate_frame_handler( SCIC_SDS_REMOTE_DEVICE_T * this_device, U32 frame_index ) { SCI_STATUS status; SATA_FIS_HEADER_T * frame_header; status = scic_sds_unsolicited_frame_control_get_header( &(scic_sds_remote_device_get_controller(this_device)->uf_control), frame_index, (void **)&frame_header ); if (status == SCI_SUCCESS) { if ( (frame_header->fis_type == SATA_FIS_TYPE_SETDEVBITS) && (frame_header->status & ATA_STATUS_REG_ERROR_BIT) ) { this_device->not_ready_reason = SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED; /** @todo Check sactive and complete associated IO if any. */ sci_base_state_machine_change_state( &this_device->ready_substate_machine, SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR ); } else if ( (frame_header->fis_type == SATA_FIS_TYPE_REGD2H) && (frame_header->status & ATA_STATUS_REG_ERROR_BIT) ) { // Some devices return D2H FIS when an NCQ error is detected. // Treat this like an SDB error FIS ready reason. this_device->not_ready_reason = SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED; sci_base_state_machine_change_state( &this_device->ready_substate_machine, SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR ); } else { status = SCI_FAILURE; } scic_sds_controller_release_frame( scic_sds_remote_device_get_controller(this_device), frame_index ); } 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; }
/** * This method will handle the start io operation for a sata device that is in * the command idle state. * - Evalute the type of IO request to be started * - If its an NCQ request change to NCQ substate * - If its any other command change to the CMD substate * * @note If this is a softreset we may want to have a different substate. * * @param [in] device * @param [in] request * * @return SCI_STATUS */ static SCI_STATUS scic_sds_stp_remote_device_ready_idle_substate_start_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_REMOTE_DEVICE_T *)device; SCIC_SDS_REQUEST_T * io_request = (SCIC_SDS_REQUEST_T *)request; // Will the port allow the io request to start? status = this_device->owning_port->state_handlers->start_io_handler( this_device->owning_port, this_device, io_request ); if (status == SCI_SUCCESS) { status = scic_sds_remote_node_context_start_io(this_device->rnc, io_request); if (status == SCI_SUCCESS) { status = io_request->state_handlers->parent.start_handler(request); } if (status == SCI_SUCCESS) { if (io_request->sat_protocol == SAT_PROTOCOL_FPDMA) { sci_base_state_machine_change_state( &this_device->ready_substate_machine, SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ ); } else { this_device->working_request = io_request; sci_base_state_machine_change_state( &this_device->ready_substate_machine, SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD ); } } scic_sds_remote_device_start_request(this_device, io_request, status); } return status; }
/** * @brief This method provides STOPPED state specific handling for * when the framework attempts to start the remote device. This * method attempts to transition the state machine into the * STARTING state. If this is unsuccessful, then there is a direct * transition into the FAILED state. * * @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 start * operating began successfully. */ static SCI_STATUS scif_sas_remote_device_stopped_start_handler( SCI_BASE_REMOTE_DEVICE_T * remote_device ) { SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *) remote_device; sci_base_state_machine_change_state( &fw_device->parent.state_machine, SCI_BASE_REMOTE_DEVICE_STATE_STARTING ); // Check to see if the state transition occurred without issue. if (sci_base_state_machine_get_state(&fw_device->parent.state_machine) == SCI_BASE_REMOTE_DEVICE_STATE_FAILED) { SCIF_LOG_WARNING(( sci_base_object_get_logger(fw_device), SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, "Domain:0x%x Device:0x%x Status:0x%x failed to start\n", fw_device->domain, fw_device, fw_device->operation_status )); } return fw_device->operation_status; }
static SCI_STATUS scic_sds_remote_node_context_initial_state_resume_handler( SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc, SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, void * callback_parameter ) { if (this_rnc->remote_node_index != SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) { scic_sds_remote_node_context_setup_to_resume( this_rnc, the_callback, callback_parameter ); scic_sds_remote_node_context_construct_buffer(this_rnc); #if defined (SCI_LOGGING) // If a remote node context has a logger already, don't work on its state // logging. if (this_rnc->state_machine.previous_state_id != SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE) scic_sds_remote_node_context_initialize_state_logging(this_rnc); #endif sci_base_state_machine_change_state( &this_rnc->state_machine, SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE ); return SCI_SUCCESS; } return SCI_FAILURE_INVALID_STATE; }
/** * @brief This handler is currently solely used by smp remote device for * discovering. * * @param[in] remote_device This parameter specifies the remote device * object on which the user is attempting to perform a complete high * priority IO operation. * @param[in] io_request This parameter specifies the high priority IO request * to be completed. * * @return SCI_STATUS indicate whether the io complete successfully. */ SCI_STATUS scif_sas_remote_device_ready_task_management_complete_high_priority_io_handler( SCI_BASE_REMOTE_DEVICE_T * remote_device, SCI_BASE_REQUEST_T * io_request, void * response_data, SCI_IO_STATUS completion_status ) { SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*) remote_device; SCIF_SAS_REQUEST_T * fw_request = (SCIF_SAS_REQUEST_T*) io_request; SCI_STATUS status = SCI_SUCCESS; SCIC_TRANSPORT_PROTOCOL protocol; SCIF_LOG_TRACE(( sci_base_object_get_logger(remote_device), SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_IO_REQUEST, "scif_sas_remote_device_ready_task_management_complete_high_priority_io_handler(0x%x, 0x%x, 0x%x, 0x%x) enter\n", remote_device, io_request, response_data, completion_status )); fw_device->request_count--; // we are back to ready operational sub state here. sci_base_state_machine_change_state( &fw_device->ready_substate_machine, SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_OPERATIONAL ); protocol = scic_io_request_get_protocol(fw_request->core_object); // If this request was an SMP initiator request we created, then // decode the response. if (protocol == SCIC_SMP_PROTOCOL) { if (completion_status != SCI_IO_FAILURE_TERMINATED) { status = scif_sas_smp_remote_device_decode_smp_response( fw_device, fw_request, response_data, completion_status ); } else scif_sas_smp_remote_device_terminated_request_handler(fw_device, fw_request); } else { // Currently, there are only internal SMP requests. So, default work // is simply to clean up the internal request. if (fw_request->is_internal == TRUE) { scif_sas_internal_io_request_complete( fw_device->domain->controller, (SCIF_SAS_INTERNAL_IO_REQUEST_T *)fw_request, SCI_SUCCESS ); } } return status; }
/** * @brief This method provides STOPPING state specific handling for * when the core remote device object issues a stop completion * notification. * * @note There is no need to ensure all IO/Task requests are complete * before transitioning to the STOPPED state. The SCI Core will * ensure this is accomplished. * * @param[in] remote_device This parameter specifies the remote device * object for which the completion occurred. * @param[in] completion_status This parameter specifies the status * of the completion operation. * * @return none. */ static void scif_sas_remote_device_stopping_stop_complete_handler( SCIF_SAS_REMOTE_DEVICE_T * fw_device, SCI_STATUS completion_status ) { // Transition directly to the STOPPED state since the core ensures // all IO/Tasks are complete. sci_base_state_machine_change_state( &fw_device->parent.state_machine, SCI_BASE_REMOTE_DEVICE_STATE_STOPPED ); if (completion_status != SCI_SUCCESS) { 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 stop core device\n", fw_device, completion_status )); // Something is seriously wrong. Stopping the core remote device // shouldn't fail in anyway. scif_cb_controller_error(fw_device->domain->controller, SCI_CONTROLLER_REMOTE_DEVICE_ERROR); } }
/** * @brief This method will attempt to transition to the stopped state. * The transition will only occur if the criteria for transition is * met (i.e. all IOs are complete and all devices are stopped). * * @param[in] fw_domain This parameter specifies the domain in which to * to attempt to perform the transition. * * @return none */ void scif_sas_domain_transition_to_stopped_state( SCIF_SAS_DOMAIN_T * fw_domain ) { SCIF_LOG_TRACE(( sci_base_object_get_logger(fw_domain), SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, "scif_sas_domain_transition_to_stopped_state(0x%x) enter\n", fw_domain )); // If IOs are quiesced, and all remote devices are stopped, // then transition directly to the STOPPED state. if ( (fw_domain->request_list.element_count == 0) && (fw_domain->device_start_count == 0) ) { SCIF_LOG_INFO(( sci_base_object_get_logger(fw_domain), SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, "Domain:0x%x immediate transition to STOPPED\n", fw_domain )); sci_base_state_machine_change_state( &fw_domain->parent.state_machine, SCI_BASE_DOMAIN_STATE_STOPPED ); } }
/** * @brief This method implements the actions taken when entering the * STARTING state. This includes setting the state handlers and * checking to see if the core port has already become READY. * * @param[in] object This parameter specifies the base object for which * the state transition is occurring. This is cast into a * SCIF_SAS_DOMAIN object in the method implementation. * * @return none */ static void scif_sas_domain_starting_state_enter( SCI_BASE_OBJECT_T * object ) { SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T *)object; SET_STATE_HANDLER( fw_domain, scif_sas_domain_state_handler_table, SCI_BASE_DOMAIN_STATE_STARTING ); SCIF_LOG_TRACE(( sci_base_object_get_logger(fw_domain), SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, "scif_sas_domain_starting_state_enter(0x%x) enter\n", fw_domain )); scif_sas_domain_transition_from_discovering_state(fw_domain); // If we entered the STARTING state and the core port is actually ready, // then directly transition into the READY state. This can occur // if we were in the middle of discovery when the port failed // (causing a transition to STOPPING), then before reaching STOPPED // the port becomes ready again. if (fw_domain->is_port_ready == TRUE) { sci_base_state_machine_change_state( &fw_domain->parent.state_machine, SCI_BASE_DOMAIN_STATE_READY ); } }
static SCI_STATUS scic_sds_remote_node_context_posting_state_event_handler( struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc, U32 event_code ) { SCI_STATUS status; switch (scu_get_event_code(event_code)) { case SCU_EVENT_POST_RNC_COMPLETE: status = SCI_SUCCESS; sci_base_state_machine_change_state( &this_rnc->state_machine, SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE ); break; default: status = SCI_FAILURE; SCIC_LOG_WARNING(( sci_base_object_get_logger(this_rnc->device), SCIC_LOG_OBJECT_SSP_REMOTE_TARGET | SCIC_LOG_OBJECT_SMP_REMOTE_TARGET | SCIC_LOG_OBJECT_STP_REMOTE_TARGET, "SCIC Remote Node Context 0x%x requested to process unexpected event 0x%x while in posting state\n", this_rnc, event_code )); break; } return status; }
/** * This method will handle the suspend requests from the ready state. * * @param[in] this_rnc The remote node context object being suspended. * @param[in] the_callback The callback when the suspension is complete. * @param[in] callback_parameter The parameter that is to be passed into the * callback. * * @return SCI_SUCCESS */ static SCI_STATUS scic_sds_remote_node_context_ready_state_suspend_handler( SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc, U32 suspend_type, SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, void * callback_parameter ) { this_rnc->user_callback = the_callback; this_rnc->user_cookie = callback_parameter; this_rnc->suspension_code = suspend_type; if (suspend_type == SCI_SOFTWARE_SUSPENSION) { scic_sds_remote_device_post_request( this_rnc->device, SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX ); } sci_base_state_machine_change_state( &this_rnc->state_machine, SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE ); return SCI_SUCCESS; }
void scic_cb_controller_start_complete( SCI_CONTROLLER_HANDLE_T controller, SCI_STATUS completion_status ) { SCIF_SAS_CONTROLLER_T *fw_controller = (SCIF_SAS_CONTROLLER_T*) sci_object_get_association(controller); SCIF_LOG_TRACE(( sci_base_object_get_logger(controller), SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_INITIALIZATION, "scic_cb_controller_start_complete(0x%x, 0x%x) enter\n", controller, completion_status )); if (completion_status == SCI_SUCCESS || completion_status == SCI_FAILURE_TIMEOUT) { // Even the initialization of the core controller timed out, framework // controller should still transit to READY state. sci_base_state_machine_change_state( &fw_controller->parent.state_machine, SCI_BASE_CONTROLLER_STATE_READY ); } scif_cb_controller_start_complete(fw_controller, completion_status); }
/** * @brief This method provides COMPLETED state specific handling for * when the user attempts to destruct the supplied task request. * * @param[in] task_request This parameter specifies the task request object * to be destructed. * * @return This method returns a value indicating if the destruct * operation was successful. * @retval SCI_SUCCESS This return value indicates that the destruct * was successful. */ static SCI_STATUS scif_sas_task_request_completed_destruct_handler( SCI_BASE_REQUEST_T * task_request ) { SCIF_SAS_REQUEST_T * fw_request = (SCIF_SAS_REQUEST_T *)task_request; sci_base_state_machine_change_state( &task_request->state_machine, SCI_BASE_REQUEST_STATE_FINAL ); sci_base_state_machine_logger_deinitialize( &task_request->state_machine_logger, &task_request->state_machine ); if (fw_request->is_internal == TRUE) { scif_sas_internal_task_request_destruct( (SCIF_SAS_TASK_REQUEST_T *)fw_request ); } return SCI_SUCCESS; }
/** * @brief This method provides handling of device start complete duing * UPDATING_PORT_WIDTH state. * * @param[in] remote_device This parameter specifies the remote device object * which is start complete. * * @return none. */ static SCI_STATUS scif_sas_remote_device_updating_port_width_state_complete_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; fw_device->request_count--; //If the request count is zero, go ahead to update the RNC. if (fw_device->request_count == 0 ) { if (fw_device->destination_state == SCIF_SAS_REMOTE_DEVICE_DESTINATION_STATE_STOPPING) { //if the destination state of this device change to STOPPING, no matter //whether we need to update the port width, just make the device //go to the STOPPING state, the device will be removed anyway. sci_base_state_machine_change_state( &fw_device->parent.state_machine, SCI_BASE_REMOTE_DEVICE_STATE_STOPPING ); } else { //stop the device, upon the stop complete callback, start the device again //with the updated port width. scic_remote_device_stop( fw_device->core_object, SCIF_SAS_REMOTE_DEVICE_CORE_OP_TIMEOUT); } } return SCI_SUCCESS; }
/** * @brief This method provides TASK MANAGEMENT sub-state specific handling for * when a user attempts to complete a task management 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 complete task * operation. * @param[in] task_request This parameter specifies the task management * request to be completed. * * @return This method returns an indication as to whether the task * management request succeeded. */ SCI_STATUS scif_sas_remote_device_ready_task_management_complete_task_handler( SCI_BASE_REMOTE_DEVICE_T * remote_device, SCI_BASE_REQUEST_T * task_request ) { 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; fw_device->request_count--; fw_device->task_request_count--; // All existing task management requests and all of the IO requests // affectected by the task management request must complete before // the remote device can transition back into the READY / OPERATIONAL // state. if ( (fw_device->task_request_count == 0) && (fw_task->affected_request_count == 0) ) { sci_base_state_machine_change_state( &fw_device->ready_substate_machine, SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_OPERATIONAL ); } return SCI_SUCCESS; }
/** * @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); }
/** * @brief This method processes an unsolicited frame while the task mgmt * 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 TC response * frame was handled successfully or not. * @retval SCI_SUCCESS Currently this value is always returned and indicates * successful processing of the TC response. * * @todo Should probably update to check frame type and make sure it is * a response frame. */ static SCI_STATUS scic_sds_ssp_task_request_await_tc_response_frame_handler( SCIC_SDS_REQUEST_T * this_request, U32 frame_index ) { // Save off the controller, so that we do not touch the request after it // is completed. SCIC_SDS_CONTROLLER_T * owning_controller = this_request->owning_controller; SCIC_LOG_TRACE(( sci_base_object_get_logger(this_request), SCIC_LOG_OBJECT_TASK_MANAGEMENT, "scic_sds_ssp_task_request_await_tc_response_frame_handler(0x%x, 0x%x) enter\n", this_request, frame_index )); scic_sds_io_request_copy_response(this_request); sci_base_state_machine_change_state( &this_request->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED ); scic_sds_controller_release_frame( owning_controller, frame_index ); return SCI_SUCCESS; }
/** * @brief This method is called by the SCI user to build an SMP pass-through * IO request. * * @pre * - The user must have previously called scic_io_request_construct() * on the supplied IO request. * * @param[in] scic_smp_request This parameter specifies the handle to the * io request object to be built. * * @param[in] passthru_cb This parameter specifies the pointer to the callback * structure that contains the function pointers * * @return Indicate if the controller successfully built the IO request. */ SCI_STATUS scic_io_request_construct_smp_pass_through( SCI_IO_REQUEST_HANDLE_T scic_smp_request, SCIC_SMP_PASSTHRU_REQUEST_CALLBACKS_T *passthru_cb ) { SMP_REQUEST_T smp_request; U8 * request_buffer; U32 request_buffer_length_in_bytes; SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *) scic_smp_request; SCIC_LOG_TRACE(( sci_base_object_get_logger(this_request), SCIC_LOG_OBJECT_SMP_IO_REQUEST, "scic_io_request_construct_smp_pass_through(0x%x) enter\n", this_request )); this_request->protocol = SCIC_SMP_PROTOCOL; this_request->has_started_substate_machine = TRUE; // Call the callback function to retrieve the SMP passthrough request request_buffer_length_in_bytes = passthru_cb->scic_cb_smp_passthru_get_request ( (void *)this_request, &request_buffer ); //copy the request to smp request memcpy((char *)&smp_request.request.vendor_specific_request, request_buffer, request_buffer_length_in_bytes); //the header length in smp_request is in dwords - the sas spec has similar way, //but the csmi header contains the number of bytes, so we need to convert the //number of bytes to number of dwords smp_request.header.request_length = (U8) (request_buffer_length_in_bytes / sizeof (U32)); //Grab the other needed fields from the smp request using callbacks smp_request.header.smp_frame_type = passthru_cb->scic_cb_smp_passthru_get_frame_type ((void *)this_request); smp_request.header.function = passthru_cb->scic_cb_smp_passthru_get_function ((void *)this_request); smp_request.header.allocated_response_length = passthru_cb->scic_cb_smp_passthru_get_allocated_response_length((void *)this_request); // Construct the started sub-state machine. sci_base_state_machine_construct( &this_request->started_substate_machine, &this_request->parent.parent, scic_sds_smp_request_started_substate_table, SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE ); // Construct the SMP SCU Task Context scu_smp_request_construct_task_context (this_request, &smp_request); sci_base_state_machine_change_state( &this_request->parent.state_machine, SCI_BASE_REQUEST_STATE_CONSTRUCTED ); return SCI_SUCCESS; }
static SCI_STATUS scic_sds_remote_node_context_await_suspension_state_event_handler( struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc, U32 event_code ) { SCI_STATUS status; switch (scu_get_event_type(event_code)) { case SCU_EVENT_TL_RNC_SUSPEND_TX: sci_base_state_machine_change_state( &this_rnc->state_machine, SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE ); this_rnc->suspension_code = scu_get_event_specifier(event_code); status = SCI_SUCCESS; break; case SCU_EVENT_TL_RNC_SUSPEND_TX_RX: sci_base_state_machine_change_state( &this_rnc->state_machine, SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE ); this_rnc->suspension_code = scu_get_event_specifier(event_code); status = SCI_SUCCESS; break; default: SCIC_LOG_WARNING(( sci_base_object_get_logger(this_rnc->device), SCIC_LOG_OBJECT_SSP_REMOTE_TARGET | SCIC_LOG_OBJECT_SMP_REMOTE_TARGET | SCIC_LOG_OBJECT_STP_REMOTE_TARGET, "SCIC Remote Node Context 0x%x requested to process event 0x%x while in state %d.\n", this_rnc, event_code, sci_base_state_machine_get_state(&this_rnc->state_machine) )); status = SCI_FAILURE; break; } return status; }
SCI_STATUS scif_controller_construct( SCI_LIBRARY_HANDLE_T library, SCI_CONTROLLER_HANDLE_T controller, void * user_object ) { SCI_STATUS status = SCI_SUCCESS; SCIF_SAS_LIBRARY_T * fw_library = (SCIF_SAS_LIBRARY_T*) library; SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller; // Validate the user supplied parameters. if ((library == SCI_INVALID_HANDLE) || (controller == SCI_INVALID_HANDLE)) return SCI_FAILURE_INVALID_PARAMETER_VALUE; SCIF_LOG_TRACE(( sci_base_object_get_logger(library), SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_INITIALIZATION, "scif_controller_construct(0x%x, 0x%x) enter\n", library, controller )); // Construct the base controller. As part of constructing the base // controller we ask it to also manage the MDL iteration for the Core. sci_base_controller_construct( &fw_controller->parent, sci_base_object_get_logger(fw_library), scif_sas_controller_state_table, fw_controller->mdes, SCIF_SAS_MAX_MEMORY_DESCRIPTORS, sci_controller_get_memory_descriptor_list_handle(fw_controller->core_object) ); scif_sas_controller_initialize_state_logging(fw_controller); sci_object_set_association(fw_controller, user_object); status = scic_controller_construct( fw_library->core_object, fw_controller->core_object, fw_controller ); // If the core controller was successfully constructed, then // finish construction of the framework controller. if (status == SCI_SUCCESS) { // Set the association in the core controller to this framework // controller. sci_object_set_association( (SCI_OBJECT_HANDLE_T) fw_controller->core_object, fw_controller ); sci_base_state_machine_change_state( &fw_controller->parent.state_machine, SCI_BASE_CONTROLLER_STATE_RESET ); } return status; }
/** * @brief This method processes the completions transport layer (TL) status * to determine if the SMP request was sent successfully. If the SMP * request was sent successfully, then the state for the SMP request * transits to waiting for a response frame. * * @param[in] this_request This parameter specifies the request for which * the TC completion was received. * @param[in] completion_code This parameter indicates the completion status * information for the TC. * * @return Indicate if the tc completion handler was successful. * @retval SCI_SUCCESS currently this method always returns success. */ static SCI_STATUS scic_sds_smp_request_await_tc_completion_tc_completion_handler( SCIC_SDS_REQUEST_T * this_request, U32 completion_code ) { SCIC_LOG_TRACE(( sci_base_object_get_logger(this_request), SCIC_LOG_OBJECT_SMP_IO_REQUEST, "scic_sds_smp_request_await_tc_completion_tc_completion_handler(0x%x, 0x%x) enter\n", this_request, completion_code )); switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): scic_sds_request_set_status( this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS ); sci_base_state_machine_change_state( &this_request->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED ); break; default: // All other completion status cause the IO to be complete. If a NAK // was received, then it is up to the user to retry the request. scic_sds_request_set_status( this_request, SCU_NORMALIZE_COMPLETION_STATUS(completion_code), SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR ); sci_base_state_machine_change_state( &this_request->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED ); break; } return SCI_SUCCESS; }
/** * @brief This method is called upon entrance to DISCOVERING state. Right before * transitioning to DISCOVERING state, we temporarily change interrupt * coalescence scheme. * * @param[in] fw_domain This parameter specifies the domain for which * the state transition has occurred. * * @return none */ void scif_sas_domain_transition_to_discovering_state( SCIF_SAS_DOMAIN_T * fw_domain ) { scif_sas_controller_save_interrupt_coalescence(fw_domain->controller); sci_base_state_machine_change_state( &fw_domain->parent.state_machine, SCI_BASE_DOMAIN_STATE_DISCOVERING ); }
/** * @brief This method provides handling of device start complete duing * UPDATING_PORT_WIDTH state. * * @param[in] remote_device This parameter specifies the remote device object * which is start complete. * * @return none. */ static void scif_sas_remote_device_updating_port_width_state_start_complete_handler( SCIF_SAS_REMOTE_DEVICE_T * fw_device, SCI_STATUS completion_status ) { SCIF_LOG_INFO(( sci_base_object_get_logger(fw_device), SCIF_LOG_OBJECT_REMOTE_DEVICE, "RemoteDevice:0x%x updating port width state start complete handler\n", fw_device, sci_base_state_machine_get_state(&fw_device->parent.state_machine) )); if ( fw_device->destination_state == SCIF_SAS_REMOTE_DEVICE_DESTINATION_STATE_STOPPING ) { //if the destination state of this device change to STOPPING, no matter //whether we need to update the port width again, just make the device //go to the STOPPING state. sci_base_state_machine_change_state( &fw_device->parent.state_machine, SCI_BASE_REMOTE_DEVICE_STATE_STOPPING ); } else if ( scic_remote_device_get_port_width(fw_device->core_object) != fw_device->device_port_width && fw_device->device_port_width != 0) { scic_remote_device_stop( fw_device->core_object, SCIF_SAS_REMOTE_DEVICE_CORE_OP_TIMEOUT ); } else { //Port width updating succeeds. Transfer to destination state. sci_base_state_machine_change_state( &fw_device->parent.state_machine, SCI_BASE_REMOTE_DEVICE_STATE_READY ); } }
/** * @brief This method provides CONSTRUCTED state specific handling for * when the user attempts to abort the supplied IO request. * * @param[in] io_request This parameter specifies the IO request object * to be aborted. * * @return This method returns a value indicating if the IO request was * successfully aborted or not. * @retval SCI_SUCCESS This return value indicates successful aborting * of the IO request. */ SCI_STATUS scif_sas_io_request_constructed_abort_handler( SCI_BASE_REQUEST_T * io_request ) { sci_base_state_machine_change_state( &io_request->state_machine, SCI_BASE_REQUEST_STATE_COMPLETED ); return SCI_SUCCESS; }
/** * @brief This method provides SUSPENDED sub-state specific handling for * when the core remote device object issues a device ready * notification. This effectively causes the framework remote * device to transition back into the OPERATIONAL state. * * @param[in] remote_device This parameter specifies the remote device * object for which the notification occurred. * * @return none. */ static void scif_sas_remote_device_ready_suspended_ready_handler( SCIF_SAS_REMOTE_DEVICE_T * fw_device ) { sci_base_state_machine_change_state( &fw_device->ready_substate_machine, SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_OPERATIONAL ); }
/** * @brief This method provides ABORTING state specific handling for * when the user attempts to complete the supplied task request. * * @param[in] task_request This parameter specifies the task request object * to be completed. * * @return This method returns a value indicating if the completion * operation was successful. * @retval SCI_SUCCESS This return value indicates that the completion * was successful. */ static SCI_STATUS scif_sas_task_request_aborting_complete_handler( SCI_BASE_REQUEST_T * task_request ) { sci_base_state_machine_change_state( &task_request->state_machine, SCI_BASE_REQUEST_STATE_COMPLETED ); return SCI_SUCCESS; }
/** * @brief This method provides CONSTRUCTED state specific handling for * when the user attempts to start the supplied task request. * * @param[in] task_request This parameter specifies the task request object * to be started. * * @return This method returns a value indicating if the task request was * successfully started or not. * @retval SCI_SUCCESS This return value indicates successful starting * of the task request. */ static SCI_STATUS scif_sas_task_request_constructed_start_handler( SCI_BASE_REQUEST_T * task_request ) { sci_base_state_machine_change_state( &task_request->state_machine, SCI_BASE_REQUEST_STATE_STARTED ); return SCI_SUCCESS; }