U8 scic_cb_ssp_task_request_get_function( void * scic_user_task_request ) { SCIF_SAS_TASK_REQUEST_T * fw_task = (SCIF_SAS_TASK_REQUEST_T*) scic_user_task_request; return scif_sas_task_request_get_function(fw_task); }
void scic_cb_port_hard_reset_complete( SCI_CONTROLLER_HANDLE_T controller, SCI_PORT_HANDLE_T port, SCI_STATUS completion_status ) { SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T*) sci_object_get_association(port); SCIF_SAS_REMOTE_DEVICE_T * fw_device; SCI_FAST_LIST_ELEMENT_T * element = fw_domain->request_list.list_head; SCIF_SAS_TASK_REQUEST_T * task_request = NULL; SCIF_LOG_TRACE(( sci_base_object_get_logger(fw_domain), SCIF_LOG_OBJECT_DOMAIN, "scic_cb_port_hard_reset_complete(0x%x, 0x%x, 0x%x) enter\n", controller, port, completion_status )); while (element != NULL) { task_request = (SCIF_SAS_TASK_REQUEST_T*) sci_fast_list_get_object(element); element = sci_fast_list_get_next(element); if (scif_sas_task_request_get_function(task_request) == SCI_SAS_HARD_RESET) { fw_device = task_request->parent.device; if (fw_device->domain == fw_domain) { scic_remote_device_reset_complete(fw_device->core_object); scif_cb_task_request_complete( sci_object_get_association(controller), fw_device, task_request, (SCI_TASK_STATUS) completion_status ); break; } } } }
/** * @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; }
void scic_cb_task_request_complete( SCI_CONTROLLER_HANDLE_T controller, SCI_REMOTE_DEVICE_HANDLE_T remote_device, SCI_TASK_REQUEST_HANDLE_T task_request, SCI_TASK_STATUS completion_status ) { SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) sci_object_get_association(controller); SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*) sci_object_get_association(remote_device); SCIF_SAS_TASK_REQUEST_T * fw_task = (SCIF_SAS_TASK_REQUEST_T*) sci_object_get_association(task_request); SCI_STATUS status; SCIF_LOG_TRACE(( sci_base_object_get_logger(fw_controller), SCIF_LOG_OBJECT_TASK_MANAGEMENT, "scic_cb_task_request_complete(0x%x, 0x%x, 0x%x, 0x%x) enter\n", controller, remote_device, task_request, completion_status )); status = fw_task->parent.state_handlers->complete_handler( &fw_task->parent.parent ); if (status == SCI_SUCCESS) { if (fw_task->parent.protocol_complete_handler != NULL) { status = fw_task->parent.protocol_complete_handler( fw_controller, fw_device, &fw_task->parent, (SCI_STATUS *)&completion_status ); } if (status == SCI_SUCCESS) { SCIF_LOG_WARNING(( sci_base_object_get_logger(fw_task), SCIF_LOG_OBJECT_TASK_MANAGEMENT, "RemoteDevice:0x%x TaskRequest:0x%x Function:0x%x CompletionStatus:0x%x " "completed\n", fw_device, fw_task, scif_sas_task_request_get_function(fw_task), completion_status )); // If this isn't an internal framework IO request, then simply pass the // notification up to the SCIF user. Otherwise, immediately complete the // task since there is no SCIF user to notify. if (fw_task->parent.is_internal == FALSE) { scif_cb_task_request_complete( fw_controller, fw_device, fw_task, completion_status ); } else { scif_controller_complete_task( fw_controller, fw_device, fw_task ); } } } }
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; }
/** * @brief This method provides SATA/STP STARTED state specific handling for * when the user attempts to complete the supplied IO request. * It will perform data/response translation and free NCQ tags * if necessary. * * @param[in] io_request This parameter specifies the IO request object * to be started. * * @return This method returns a value indicating if the IO request was * successfully completed or not. */ static SCI_STATUS scif_sas_stp_core_cb_task_request_complete_handler( SCIF_SAS_CONTROLLER_T * fw_controller, SCIF_SAS_REMOTE_DEVICE_T * fw_device, SCIF_SAS_REQUEST_T * fw_request, SCI_STATUS * completion_status ) { #if !defined(DISABLE_SATI_TASK_MANAGEMENT) SCIF_SAS_TASK_REQUEST_T * fw_task = (SCIF_SAS_TASK_REQUEST_T *) fw_request; SCIF_LOG_TRACE(( sci_base_object_get_logger(fw_controller), SCIF_LOG_OBJECT_TASK_MANAGEMENT, "scif_sas_stp_core_cb_task_request_complete_handler(0x%x, 0x%x, 0x%x, 0x%x) enter\n", fw_controller, fw_device, fw_request, *completion_status )); // Translating the response is only necessary if some sort of error // occurred resulting in having the error bit set in the ATA status // register and values to decode in the ATA error register. if ( (*completion_status == SCI_SUCCESS) || (*completion_status == SCI_FAILURE_IO_RESPONSE_VALID) ) { SATI_STATUS sati_status = sati_translate_task_response( &fw_task->parent.stp.sequence, fw_task, fw_task ); if (sati_status == SATI_COMPLETE) *completion_status = SCI_SUCCESS; else if (sati_status == SATI_FAILURE_CHECK_RESPONSE_DATA) *completion_status = SCI_FAILURE_IO_RESPONSE_VALID; else if (sati_status == SATI_SEQUENCE_INCOMPLETE) { // The translation indicates that additional SATA requests are // necessary to finish the original SCSI request. As a result, // do not complete the IO and begin the next stage of the // translation. /// @todo multiple ATA commands are required, but not supported yet. return SCI_FAILURE; } else { // Something unexpected occurred during translation. Fail the // IO request to the user. *completion_status = SCI_FAILURE; } } else //A stp task request sometimes fails. { if (scif_sas_task_request_get_function(fw_task) == SCI_SAS_ABORT_TASK_SET) { scif_sas_stp_task_request_abort_task_set_failure_handler( fw_device, fw_task); } } return SCI_SUCCESS; #else // !defined(DISABLE_SATI_TASK_MANAGEMENT) return SCI_FAILURE; #endif // !defined(DISABLE_SATI_TASK_MANAGEMENT) }