/** * @brief This methods finds the first device that is in STOPPED state and its * connection_rate is still in SPINUP_HOLD(value 3). * * @param[in] fw_domain The framework domain object * * @return SCIF_SAS_REMOTE_DEVICE_T The device that is in SPINUP_HOLD or NULL. */ SCIF_SAS_REMOTE_DEVICE_T * scif_sas_domain_find_device_in_spinup_hold( SCIF_SAS_DOMAIN_T * fw_domain ) { SCI_ABSTRACT_ELEMENT_T * current_element; SCIF_SAS_REMOTE_DEVICE_T * current_device; SCIF_LOG_TRACE(( sci_base_object_get_logger(fw_domain), SCIF_LOG_OBJECT_DOMAIN, "scif_sas_domain_find_device_in_spinup_hold(0x%x) enter\n", fw_domain )); //search throught domain's device list to find the first sata device on spinup_hold current_element = sci_abstract_list_get_front(&fw_domain->remote_device_list); while (current_element != NULL ) { current_device = (SCIF_SAS_REMOTE_DEVICE_T *) sci_abstract_list_get_object(current_element); //We must get the next element before we remove the current //device. Or else, we will get wrong next_element, since the erased //element has been put into free pool. current_element = sci_abstract_list_get_next(current_element); if ( sci_base_state_machine_get_state(¤t_device->parent.state_machine) == SCI_BASE_REMOTE_DEVICE_STATE_STOPPED && scic_remote_device_get_connection_rate(current_device->core_object) == SCI_SATA_SPINUP_HOLD ) { return current_device; } } return NULL; }
/** * @brief This method will fill in the SCU Task Context for a SMP request. The * following important settings are utilized: * * -# task_type == SCU_TASK_TYPE_SMP. This simply indicates * that a normal request type (i.e. non-raw frame) is being * utilized to perform task management. * -# control_frame == 1. This ensures that the proper endianess * is set so that the bytes are transmitted in the right order * for a smp request frame. * * @param[in] this_request This parameter specifies the smp request object * being constructed. * * @return none */ void scu_smp_request_construct_task_context( SCIC_SDS_REQUEST_T *this_request, SMP_REQUEST_T *smp_request ) { SCI_PHYSICAL_ADDRESS physical_address; SCIC_SDS_CONTROLLER_T *owning_controller; SCIC_SDS_REMOTE_DEVICE_T *target_device; SCIC_SDS_PORT_T *target_port; SCU_TASK_CONTEXT_T *task_context; //byte swap the smp request. scic_word_copy_with_swap( this_request->command_buffer, (U32*) smp_request, sizeof(SMP_REQUEST_T)/sizeof(U32) ); task_context = scic_sds_request_get_task_context(this_request); owning_controller = scic_sds_request_get_controller(this_request); target_device = scic_sds_request_get_device(this_request); target_port = scic_sds_request_get_port(this_request); SCIC_LOG_TRACE(( sci_base_object_get_logger(this_request), SCIC_LOG_OBJECT_SMP_IO_REQUEST, "scu_smp_request_construct_task_context(0x%x) contents\n" " reqlen=%x; function=%x;\n", this_request, smp_request->header.request_length, smp_request->header.function )); // Fill in the TC with the its required data // 00h task_context->priority = 0; task_context->initiator_request = 1; task_context->connection_rate = scic_remote_device_get_connection_rate(target_device); task_context->protocol_engine_index = scic_sds_controller_get_protocol_engine_group(owning_controller); task_context->logical_port_index = scic_sds_port_get_index(target_port); task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SMP; task_context->abort = 0; task_context->valid = SCU_TASK_CONTEXT_VALID; task_context->context_type = SCU_TASK_CONTEXT_TYPE; //04h task_context->remote_node_index = this_request->target_device->rnc->remote_node_index; task_context->command_code = 0; task_context->task_type = SCU_TASK_TYPE_SMP_REQUEST; //08h task_context->link_layer_control = 0; task_context->do_not_dma_ssp_good_response = 1; task_context->strict_ordering = 0; task_context->control_frame = 1; task_context->timeout_enable = 0; task_context->block_guard_enable = 0; //0ch task_context->address_modifier = 0; //10h task_context->ssp_command_iu_length = smp_request->header.request_length; //14h task_context->transfer_length_bytes = 0; //18h ~ 30h, protocol specific // since commandIU has been build by framework at this point, we just // copy the frist DWord from command IU to this location. memcpy((void *)(&task_context->type.smp), this_request->command_buffer, sizeof(U32) ); //40h // "For SMP you could program it to zero. We would prefer that way so that // done code will be consistent." - Venki task_context->task_phase = 0; if (this_request->was_tag_assigned_by_user) { // Build the task context now since we have already read the data this_request->post_context = ( SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | ( scic_sds_controller_get_protocol_engine_group(owning_controller) << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT ) | ( scic_sds_port_get_index(target_port) << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT ) | scic_sds_io_tag_get_index(this_request->io_tag) ); } else { // Build the task context now since we have already read the data this_request->post_context = ( SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | ( scic_sds_controller_get_protocol_engine_group(owning_controller) << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT ) | ( scic_sds_port_get_index(target_port) << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT ) // This is not assigned because we have to wait until we get a TCi ); } // Copy the physical address for the command buffer to the SCU Task Context // command buffer should not contain command header. scic_cb_io_request_get_physical_address( scic_sds_request_get_controller(this_request), this_request, ((char *)(this_request->command_buffer) + sizeof(U32)), &physical_address ); task_context->command_iu_upper = sci_cb_physical_address_upper(physical_address); task_context->command_iu_lower = sci_cb_physical_address_lower(physical_address); //SMP response comes as UF, so no need to set response IU address. task_context->response_iu_upper = 0; task_context->response_iu_lower = 0; }