/** * @brief construct a smp REPORT PHY SATA command to the fw_device. * @param[in] fw_controller The framework controller object. * @param[in] fw_device the framework smp device that DISCOVER command targets * to. * @param[in] phy_identifier The phy index the DISCOVER command targets to. * * @return void * address to the built scif sas smp request. */ void * scif_sas_smp_request_construct_report_phy_sata( SCIF_SAS_CONTROLLER_T * fw_controller, SCIF_SAS_REMOTE_DEVICE_T * fw_device, U8 phy_identifier ) { SMP_REQUEST_T report_phy_sata; scif_sas_smp_protocol_request_construct( &report_phy_sata, SMP_FUNCTION_REPORT_PHY_SATA, sizeof(SMP_RESPONSE_REPORT_PHY_SATA_T) / sizeof(U32), sizeof(SMP_REQUEST_PHY_IDENTIFIER_T) / sizeof(U32) ); report_phy_sata.request.report_phy_sata.phy_identifier = phy_identifier; SCIF_LOG_INFO(( sci_base_object_get_logger(fw_device), SCIF_LOG_OBJECT_IO_REQUEST | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, "SMP REPORT PHY SATA - Device:0x%x PhyId:0x%x\n", fw_device, phy_identifier )); return scif_sas_smp_request_build( fw_controller, fw_device, &report_phy_sata, NULL, NULL); }
/** * @brief This method implements the actions taken when entering the * FAILED state. This includes setting the state handler methods * and issuing a scif_cb_remote_device_failed() notification to * the user. * * @param[in] object This parameter specifies the base object for which * the state transition is occurring. This is cast into a * SCIF_SAS_REMOTE_DEVICE object in the method implementation. * * @return none */ static void scif_sas_remote_device_failed_state_enter( SCI_BASE_OBJECT_T *object ) { SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object; SET_STATE_HANDLER( fw_device, scif_sas_remote_device_state_handler_table, SCI_BASE_REMOTE_DEVICE_STATE_FAILED ); SCIF_LOG_INFO(( sci_base_object_get_logger(fw_device), SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_REMOTE_DEVICE_CONFIG, "Domain:0x%x Device:0x%x Status:0x%x device failed\n", fw_device->domain, fw_device, fw_device->operation_status )); // Notify the user that the device has failed. scif_cb_remote_device_failed( fw_device->domain->controller, fw_device->domain, fw_device, fw_device->operation_status ); // Only call start_complete for the remote device if the device failed // from the STARTING state. if (fw_device->parent.state_machine.previous_state_id == SCI_BASE_REMOTE_DEVICE_STATE_STARTING) scif_sas_domain_remote_device_start_complete(fw_device->domain,fw_device); }
/** * @brief construct a smp Discover command to the fw_device. * @param[in] fw_controller The framework controller object. * @param[in] fw_device the framework smp device that DISCOVER command targets * to. * @param[in] phy_identifier The phy index the DISCOVER command targets to. * * @return void * address to the built scif sas smp request. */ void * scif_sas_smp_request_construct_discover( SCIF_SAS_CONTROLLER_T * fw_controller, SCIF_SAS_REMOTE_DEVICE_T * fw_device, U8 phy_identifier, void * external_request_object, void * external_memory ) { SMP_REQUEST_T smp_discover; scif_sas_smp_protocol_request_construct( &smp_discover, SMP_FUNCTION_DISCOVER, sizeof(SMP_RESPONSE_DISCOVER_T) / sizeof(U32), sizeof(SMP_REQUEST_PHY_IDENTIFIER_T) / sizeof(U32) ); smp_discover.request.discover.phy_identifier = phy_identifier; SCIF_LOG_INFO(( sci_base_object_get_logger(fw_device), SCIF_LOG_OBJECT_IO_REQUEST | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, "SMP DISCOVER - Device:0x%x PhyId:0x%x\n", fw_device, phy_identifier )); return scif_sas_smp_request_build( fw_controller, fw_device, &smp_discover, external_request_object, external_memory ); }
/** * @brief construct a SMP Report Manufacturer Info request to the fw_device. * * @param[in] fw_controller The framework controller object. * @param[in] fw_device the framework device that the REPORT MANUFACTURER * INFO targets to. * * @return void * address to the built scif sas smp request. */ void * scif_sas_smp_request_construct_report_manufacturer_info( SCIF_SAS_CONTROLLER_T * fw_controller, SCIF_SAS_REMOTE_DEVICE_T * fw_device ) { SMP_REQUEST_T smp_report_manufacturer_info; scif_sas_smp_protocol_request_construct( &smp_report_manufacturer_info, SMP_FUNCTION_REPORT_MANUFACTURER_INFORMATION, sizeof(SMP_RESPONSE_REPORT_MANUFACTURER_INFORMATION_T) / sizeof(U32), 0 ); smp_report_manufacturer_info.request.report_general.crc = 0; SCIF_LOG_INFO(( sci_base_object_get_logger(fw_device), SCIF_LOG_OBJECT_IO_REQUEST | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, "SMP REPORT MANUFACTURER_INFO - Device:0x%x\n", fw_device )); return scif_sas_smp_request_build( fw_controller, fw_device, &smp_report_manufacturer_info, NULL, NULL ); }
/** * @brief construct a smp Report Genernal command to the fw_device. * * @param[in] fw_controller The framework controller object. * @param[in] fw_device the framework device that the REPORT GENERAL command * targets to. * * @return void * address to the built scif sas smp request. */ void * scif_sas_smp_request_construct_report_general( SCIF_SAS_CONTROLLER_T * fw_controller, SCIF_SAS_REMOTE_DEVICE_T * fw_device ) { SMP_REQUEST_T smp_report_general; // Build the REPORT GENERAL request. scif_sas_smp_protocol_request_construct( &smp_report_general, SMP_FUNCTION_REPORT_GENERAL, sizeof(SMP_RESPONSE_REPORT_GENERAL_T) / sizeof(U32), 0 ); smp_report_general.request.report_general.crc = 0; SCIF_LOG_INFO(( sci_base_object_get_logger(fw_device), SCIF_LOG_OBJECT_IO_REQUEST | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, "SMP REPORT GENERAL - Device:0x%x\n", fw_device )); return scif_sas_smp_request_build( fw_controller, fw_device, &smp_report_general, NULL, NULL); }
/** * @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 * READY OPERATIONAL substate. This includes setting the state * handler methods and issuing a scif_cb_remote_device_ready() * notification to the user. * * @param[in] object This parameter specifies the base object for which * the state transition is occurring. This is cast into a * SCIF_SAS_REMOTE_DEVICE object in the method implementation. * * @return none */ static void scif_sas_remote_device_ready_operational_substate_enter( SCI_BASE_OBJECT_T *object ) { SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object; SET_STATE_HANDLER( fw_device, scif_sas_remote_device_ready_substate_handler_table, SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_OPERATIONAL ); SCIF_LOG_INFO(( sci_base_object_get_logger(fw_device), SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_REMOTE_DEVICE_CONFIG, "Domain:0x%x Device:0x%x device ready\n", fw_device->domain, fw_device )); // Notify the user that the device has become ready. scif_cb_remote_device_ready( fw_device->domain->controller, fw_device->domain, fw_device ); }
/** * @brief This method attempts to allocate a valid NCQ tag from the list * of available tags in the remote device. * * @todo Attempt to find a CLZ like instruction to optimize this routine * down into a few instructions. I know there is one like it for IA. * * @param[in] fw_device This parameter specifies the remote device * for which to allocate an available NCQ tag. * * @return Return an available NCQ tag. * @retval 0-31 These values indicate an available tag was successfully * allocated. * @return SCIF_SAS_STP_INVALID_NCQ_TAG This value indicates that there are * no available NCQ tags. */ U8 scif_sas_stp_remote_device_allocate_ncq_tag( SCIF_SAS_REMOTE_DEVICE_T * fw_device ) { U8 ncq_tag = 0; U32 tag_mask = 1; SCIF_LOG_TRACE(( sci_base_object_get_logger(fw_device), SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_IO_REQUEST, "scif_sas_stp_remote_device_allocate_ncq_tag(0x%x)\n", fw_device )); // Try to find an unused NCQ tag. while ( (fw_device->protocol_device.stp_device.s_active & tag_mask) && (ncq_tag < fw_device->protocol_device.stp_device.sati_device.ncq_depth) ) { tag_mask <<= 1; ncq_tag++; } // Check to see if we were able to find an available NCQ tag. if (ncq_tag < fw_device->protocol_device.stp_device.sati_device.ncq_depth) { SCIF_LOG_INFO(( sci_base_object_get_logger(fw_device), SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_IO_REQUEST, "RemoteDevice:0x%x NcqTag:0x%x successful NCQ TAG allocation\n", fw_device, ncq_tag )); fw_device->protocol_device.stp_device.s_active |= tag_mask; return ncq_tag; } SCIF_LOG_INFO(( sci_base_object_get_logger(fw_device), SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_IO_REQUEST, "RemoteDevice:0x%x unable to allocate NCQ TAG\n", fw_device )); // All NCQ tags are in use. return SCIF_SAS_INVALID_NCQ_TAG; }
/** * @brief This method removes the specified tag from the list of * outstanding tags. It doesn't return any values. * * @param[in] fw_device This parameter specifies the remote device for * which to free an NCQ tag. * @param[in] ncq_tag This parameter specifies the NCQ tag that is * to be freed. * * @return none */ void scif_sas_stp_remote_device_free_ncq_tag( struct SCIF_SAS_REMOTE_DEVICE * fw_device, U8 ncq_tag ) { SCIF_LOG_INFO(( sci_base_object_get_logger(fw_device), SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_IO_REQUEST, "RemoteDevice:0x%x NcqTag:0x%x freeing NCQ TAG\n", fw_device, ncq_tag )); fw_device->protocol_device.stp_device.s_active &= ~(1 << ncq_tag); }
/** * @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 performs functionality required after a task management * operation (either a task management request or a silicon task * termination) has finished. * * @param[in] fw_task This parameter specifies the request that has * the operation completing. * * @return none */ void scif_sas_task_request_operation_complete( SCIF_SAS_TASK_REQUEST_T * fw_task ) { SCIF_LOG_TRACE(( sci_base_object_get_logger(fw_task), SCIF_LOG_OBJECT_TASK_MANAGEMENT, "scif_sas_task_request_operation_complete(0x%x) enter\n", fw_task )); fw_task->affected_request_count--; SCIF_LOG_INFO(( sci_base_object_get_logger(fw_task), SCIF_LOG_OBJECT_TASK_MANAGEMENT, "TaskRequest:0x%x current affected request count:0x%x\n", fw_task, fw_task->affected_request_count )); }
/** * @brief This method provides handling of device stop complete duing * UPDATING_PORT_WIDTH state. * * @param[in] remote_device This parameter specifies the remote device object * which is stop complete. * * @return none. */ static void scif_sas_remote_device_updating_port_width_state_stop_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 stop 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 ) { //Device directly transits to STOPPED STATE from UPDATING_PORT_WIDTH state, fw_device->domain->device_start_count--; //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 STOPPED state. sci_base_state_machine_change_state( &fw_device->parent.state_machine, SCI_BASE_REMOTE_DEVICE_STATE_STOPPED ); } else { scic_remote_device_set_port_width( fw_device->core_object, fw_device->device_port_width ); //Device stop complete, means the RNC has been destructed. Now we need to //start core device so the RNC with updated port width will be posted. scic_remote_device_start( fw_device->core_object, SCIF_SAS_REMOTE_DEVICE_CORE_OP_TIMEOUT); } }
/** * @brief This method implements the actions taken when entering the * STARTING state. This method will attempt to start the core * remote device and will kick-start the starting sub-state machine * if no errors are encountered. * * @param[in] object This parameter specifies the base object for which * the state transition is occurring. This is cast into a * SCIF_SAS_REMOTE_DEVICE object in the method implementation. * * @return none */ static void scif_sas_remote_device_starting_state_enter( SCI_BASE_OBJECT_T *object ) { SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object; SET_STATE_HANDLER( fw_device, scif_sas_remote_device_state_handler_table, SCI_BASE_REMOTE_DEVICE_STATE_STARTING ); SCIF_LOG_INFO(( sci_base_object_get_logger(fw_device), SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_REMOTE_DEVICE_CONFIG, "RemoteDevice:0x%x starting/configuring\n", fw_device )); fw_device->destination_state = SCIF_SAS_REMOTE_DEVICE_DESTINATION_STATE_READY; sci_base_state_machine_start(&fw_device->starting_substate_machine); fw_device->operation_status = scic_remote_device_start( fw_device->core_object, SCIF_SAS_REMOTE_DEVICE_CORE_OP_TIMEOUT ); if (fw_device->operation_status != SCI_SUCCESS) { fw_device->state_handlers->parent.fail_handler(&fw_device->parent); // Something is seriously wrong. Starting the core remote device // shouldn't fail in anyway in this state. scif_cb_controller_error(fw_device->domain->controller, SCI_CONTROLLER_REMOTE_DEVICE_ERROR); } }
/** * @brief This method provides handling (i.e. returns an error); * when a user attempts to stop a remote device during the updating * port width state, it will record the destination state for this * device to be STOPPING, instead of usually READY state. * * @param[in] remote_device This parameter specifies the remote device object * on which the user is attempting to perform a stop operation. * * @return This method always return SCI_SUCCESS. */ static SCI_STATUS scif_sas_remote_device_updating_port_width_state_stop_handler( SCI_BASE_REMOTE_DEVICE_T * remote_device ) { SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)remote_device; SCIF_LOG_INFO(( sci_base_object_get_logger(fw_device), SCIF_LOG_OBJECT_REMOTE_DEVICE, "RemoteDevice:0x%x updating port width state stop handler\n", fw_device, sci_base_state_machine_get_state(&fw_device->parent.state_machine) )); //Can't stop the device right now. Remember the pending stopping request. //When exit the UPDATING_PORT_WIDTH state, we will check this variable //to decide which state to go. fw_device->destination_state = SCIF_SAS_REMOTE_DEVICE_DESTINATION_STATE_STOPPING; return SCI_SUCCESS; }
/** * @brief This method provides startig sub-state specific handling for * when the remote device is requested to stop. This will occur * when there is a link failure during the starting operation. * * @param[in] remote_device This parameter specifies the remote device * object for which the failure condition occurred. * * @return This method returns an indication as to whether the failure * operation completed successfully. */ static SCI_STATUS scif_sas_remote_device_starting_state_general_stop_handler( SCI_BASE_REMOTE_DEVICE_T * remote_device ) { SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *) remote_device; SCIF_LOG_INFO(( sci_base_object_get_logger(fw_device), SCIF_LOG_OBJECT_REMOTE_DEVICE, "RemoteDevice:0x%x starting device requested to stop\n", fw_device )); fw_device->domain->device_start_in_progress_count--; sci_base_state_machine_change_state( &fw_device->parent.state_machine, SCI_BASE_REMOTE_DEVICE_STATE_STOPPING ); return SCI_SUCCESS; }
/** * @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_io_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 ) { SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T *) fw_request; SCIF_LOG_TRACE(( sci_base_object_get_logger(fw_controller), SCIF_LOG_OBJECT_IO_REQUEST, "scif_sas_stp_core_cb_io_request_complete_handler(0x%x, 0x%x, 0x%x, 0x%x) enter\n", fw_controller, fw_device, fw_request, *completion_status )); if (fw_io->parent.stp.sequence.protocol == SAT_PROTOCOL_FPDMA) scif_sas_stp_remote_device_free_ncq_tag( fw_request->device, fw_io->parent.stp.ncq_tag ); // 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. // - the command returns information in the register FIS itself, // which requires translation. // - the request completed ok but the sequence requires a callback // to possibly continue the translation if ((*completion_status == SCI_FAILURE_IO_RESPONSE_VALID) || ((sati_cb_do_translate_response(fw_request)) && (*completion_status != SCI_FAILURE_IO_TERMINATED))) { SATI_STATUS sati_status = sati_translate_command_response( &fw_io->parent.stp.sequence, fw_io, fw_io ); 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. return SCI_WARNING_SEQUENCE_INCOMPLETE; } else if (sati_status == SATI_COMPLETE_IO_DONE_EARLY) *completion_status = SCI_SUCCESS_IO_DONE_EARLY; else { // Something unexpected occurred during translation. Fail the // IO request to the user. *completion_status = SCI_FAILURE; } } else if (*completion_status != SCI_SUCCESS) { SCIF_LOG_INFO(( sci_base_object_get_logger(fw_controller), SCIF_LOG_OBJECT_IO_REQUEST, "Sequence Terminated(0x%x, 0x%x, 0x%x)\n", fw_controller, fw_device, fw_request )); sati_sequence_terminate(&fw_io->parent.stp.sequence, fw_io, fw_io); } return SCI_SUCCESS; }
/** * @brief This method implements the actions taken when entering the * DISCOVERING state. This includes determining from which * state we entered. If we entered from stopping that some sort * of hot-remove of the port occurred. In the hot-remove case * all devices should be in the STOPPED state already and, as * a result, are removed from the domain with a notification sent * to the framework user. * * @note This method currently only handles hot-insert/hot-remove of * direct attached SSP devices. * * @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_discovering_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_DISCOVERING ); SCIF_LOG_TRACE(( sci_base_object_get_logger(fw_domain), SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, "scif_sas_domain_discovering_state_enter(0x%x) enter\n", fw_domain )); fw_domain->broadcast_change_count = 0; // Did the domain just go through a port not ready action? If it did, // then we will be entering from the STOPPED state. if (fw_domain->parent.state_machine.previous_state_id != SCI_BASE_DOMAIN_STATE_STOPPED) { SCIF_SAS_REMOTE_DEVICE_T * remote_device; SCIC_PORT_PROPERTIES_T properties; scic_port_get_properties(fw_domain->core_object, &properties); // If the device has not yet been added to the domain, then // inform the user that the device is new. remote_device = (SCIF_SAS_REMOTE_DEVICE_T *) scif_domain_get_device_by_sas_address( fw_domain, &properties.remote.sas_address ); if (remote_device == SCI_INVALID_HANDLE) { // simply notify the user of the new DA device and be done // with discovery. scif_cb_domain_da_device_added( fw_domain->controller, fw_domain, &properties.remote.sas_address, &properties.remote.protocols ); } else { if(properties.remote.protocols.u.bits.smp_target) //kick off the smp discover process. scif_sas_domain_start_smp_discover(fw_domain, remote_device); } } else //entered from STOPPED state. { SCI_ABSTRACT_ELEMENT_T * current_element = sci_abstract_list_get_front(&(fw_domain->remote_device_list) ); SCIF_SAS_REMOTE_DEVICE_T * fw_device; while (current_element != NULL) { fw_device = (SCIF_SAS_REMOTE_DEVICE_T *) sci_abstract_list_get_object(current_element); ASSERT(fw_device->parent.state_machine.current_state_id == SCI_BASE_REMOTE_DEVICE_STATE_STOPPED); current_element = sci_abstract_list_get_next(current_element); SCIF_LOG_INFO(( sci_base_object_get_logger(fw_domain), SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, "Controller:0x%x Domain:0x%x Device:0x%x removed\n", fw_domain->controller, fw_domain, fw_device )); // Notify the framework user of the device removal. scif_cb_domain_device_removed( fw_domain->controller, fw_domain, fw_device ); } ASSERT(fw_domain->request_list.element_count == 0); ASSERT(sci_abstract_list_size(&fw_domain->remote_device_list) == 0); sci_base_state_machine_change_state( &fw_domain->parent.state_machine, SCI_BASE_DOMAIN_STATE_STARTING ); } }