/** * * @param[in] device This is the SCI base object which is cast into a * SCIC_SDS_REMOTE_DEVICE object. * * @return none */ static void scic_sds_stp_remote_device_ready_idle_substate_enter( SCI_BASE_OBJECT_T * device ) { SCIC_SDS_REMOTE_DEVICE_T * this_device; this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device; SET_STATE_HANDLER( this_device, scic_sds_stp_remote_device_ready_substate_handler_table, SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE ); this_device->working_request = NULL; if (scic_sds_remote_node_context_is_ready(this_device->rnc)) { // Since the RNC is ready, it's alright to finish completion // processing (e.g. signal the remote device is ready). scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler( this_device ); } else { scic_sds_remote_node_context_resume( this_device->rnc, scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler, this_device ); } }
/** * This method will handle the event for a ATAPI device that is in * the ATAPI ERROR state. We pick up suspension events to handle specifically * to this state. We resume the RNC right away. We then complete the outstanding * IO to this device. * * @param [in] device The device received event. * @param [in] event_code The event code. * * @return SCI_STATUS */ static SCI_STATUS scic_sds_stp_remote_device_ready_atapi_error_substate_event_handler( SCIC_SDS_REMOTE_DEVICE_T * this_device, U32 event_code ) { SCI_STATUS status; status = scic_sds_remote_device_general_event_handler(this_device, event_code); if (status == SCI_SUCCESS) { if (scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX || scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX) { status = scic_sds_remote_node_context_resume( this_device->rnc, (SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK) this_device->working_request->state_handlers->parent.complete_handler, (void *)this_device->working_request ); } } return status; }
/** * This method will report a success or failure attempt to start a new task * request to the hardware. Since all task requests are sent on the high * priority queue they can be sent when the RCN is in a TX suspend state. * * @param[in] this_rnc The remote node context which is to receive the task * request. * @param[in] the_request The task request to be transmitted to to the remote * target device. * * @return SCI_STATUS * @retval SCI_SUCCESS */ static SCI_STATUS scic_sds_remote_node_context_suspended_start_task_handler( struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc, struct SCIC_SDS_REQUEST * the_request ) { scic_sds_remote_node_context_resume(this_rnc, NULL, NULL); return SCI_SUCCESS; }
/** * This method will handle the event for a sata device that is in * the idle state. We pick up suspension events to handle specifically * to this state. We resume the RNC right away. * * @param [in] device The device received event. * @param [in] event_code The event code. * * @return SCI_STATUS */ static SCI_STATUS scic_sds_stp_remote_device_ready_idle_substate_event_handler( SCIC_SDS_REMOTE_DEVICE_T * this_device, U32 event_code ) { SCI_STATUS status; status = scic_sds_remote_device_general_event_handler(this_device, event_code); if (status == SCI_SUCCESS) { if ((scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX || scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX) && (this_device->rnc->destination_state != SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY)) { status = scic_sds_remote_node_context_resume( this_device->rnc, NULL, NULL); } } return status; }
/** * This is the READY NCQ substate handler to start task management request. In this * routine, we suspend and resume the RNC. * * @param[in] device The target device a task management request towards to. * @param[in] request The task request. * * @return SCI_STATUS Always return SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS status * to let controller_start_task_handler know that the controller can't post TC for * task request yet, instead, when RNC gets resumed, a controller_continue_task * callback will be called. */ static SCI_STATUS scic_sds_stp_remote_device_ready_substate_start_request_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 * this_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, this_request ); if (SCI_SUCCESS == status) { status = scic_sds_remote_node_context_start_task(this_device->rnc, this_request); if (SCI_SUCCESS == status) { status = this_request->state_handlers->parent.start_handler(request); } if (status == SCI_SUCCESS) { /// @note If the remote device state is not IDLE this will replace /// the request that probably resulted in the task management /// request. this_device->working_request = this_request; sci_base_state_machine_change_state( &this_device->ready_substate_machine, SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD ); //The remote node context must cleanup the TCi to NCQ mapping table. //The only way to do this correctly is to either write to the TLCR //register or to invalidate and repost the RNC. In either case the //remote node context state machine will take the correct action when //the remote node context is suspended and later resumed. scic_sds_remote_node_context_suspend( this_device->rnc, SCI_SOFTWARE_SUSPENSION, NULL, NULL); scic_sds_remote_node_context_resume( this_device->rnc, (SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK) scic_sds_remote_device_continue_request, this_device); } scic_sds_remote_device_start_request(this_device,this_request,status); //We need to let the controller start request handler know that it can't //post TC yet. We will provide a callback function to post TC when RNC gets //resumed. return SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS; } return status; }