scic_sds_smp_request.c revision 230843
160786Sps/*- 2128345Stjr * This file is provided under a dual BSD/GPLv2 license. When using or 360786Sps * redistributing this file, you may do so under either license. 460786Sps * 560786Sps * GPL LICENSE SUMMARY 660786Sps * 760786Sps * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 860786Sps * 960786Sps * This program is free software; you can redistribute it and/or modify 1060786Sps * it under the terms of version 2 of the GNU General Public License as 1160786Sps * published by the Free Software Foundation. 1260786Sps * 1360786Sps * This program is distributed in the hope that it will be useful, but 1460786Sps * WITHOUT ANY WARRANTY; without even the implied warranty of 1560786Sps * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1660786Sps * General Public License for more details. 1760786Sps * 1860786Sps * You should have received a copy of the GNU General Public License 1960786Sps * along with this program; if not, write to the Free Software 2060786Sps * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 2160786Sps * The full GNU General Public License is included in this distribution 2260786Sps * in the file called LICENSE.GPL. 2360786Sps * 2460786Sps * BSD LICENSE 2560786Sps * 2660786Sps * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 2760786Sps * All rights reserved. 2860786Sps * 2960786Sps * Redistribution and use in source and binary forms, with or without 3060786Sps * modification, are permitted provided that the following conditions 3160786Sps * are met: 3260786Sps * 3360786Sps * * Redistributions of source code must retain the above copyright 3460786Sps * notice, this list of conditions and the following disclaimer. 3560786Sps * * Redistributions in binary form must reproduce the above copyright 3660786Sps * notice, this list of conditions and the following disclaimer in 3760786Sps * the documentation and/or other materials provided with the 3860786Sps * distribution. 3960786Sps * 4060786Sps * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 4160786Sps * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 4260786Sps * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 4360786Sps * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 4460786Sps * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 4560786Sps * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 4660786Sps * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 4760786Sps * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 4860786Sps * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 4960786Sps * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 5060786Sps * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 5160786Sps */ 5260786Sps 5360786Sps#include <sys/cdefs.h> 5460786Sps__FBSDID("$FreeBSD$"); 5560786Sps 5660786Sps#include <dev/isci/scil/scic_sds_smp_request.h> 5760786Sps#include <dev/isci/scil/scic_sds_logger.h> 5860786Sps#include <dev/isci/scil/scic_sds_controller.h> 5960786Sps#include <dev/isci/scil/scic_sds_remote_device.h> 6060786Sps#include <dev/isci/scil/scic_remote_device.h> 6160786Sps#include <dev/isci/scil/sci_util.h> 6260786Sps#include <dev/isci/sci_environment.h> 6360786Sps#include <dev/isci/scil/intel_sas.h> 6460786Sps#include <dev/isci/scil/scic_sds_request.h> 6560786Sps#include <dev/isci/scil/scic_controller.h> 6660786Sps#include <dev/isci/scil/scu_completion_codes.h> 67128345Stjr#include <dev/isci/scil/scu_task_context.h> 6860786Sps#include <dev/isci/scil/sci_base_state_machine.h> 6960786Sps 7060786Sps/** 71128345Stjr * This method return the memory space required for STP PIO requests. 7260786Sps * 7360786Sps * @return U32 7460786Sps */ 7560786SpsU32 scic_sds_smp_request_get_object_size(void) 76128345Stjr{ 7760786Sps return sizeof(SCIC_SDS_REQUEST_T) 7860786Sps + sizeof(SMP_REQUEST_T) 7960786Sps + sizeof(U32) 8060786Sps + sizeof(SMP_RESPONSE_T) 8160786Sps + sizeof(U32) 82128345Stjr + sizeof(SCU_TASK_CONTEXT_T) 83128345Stjr + CACHE_LINE_SIZE; 8460786Sps} 85128345Stjr 8660786Sps/** 8760786Sps * This macro returns the address of the smp command buffer in the smp request 8860786Sps * memory. No need to cast to SMP request type. 8960786Sps */ 9060786Sps#define scic_sds_smp_request_get_command_buffer_unaligned(memory) \ 9160786Sps ( ((char *)(memory)) + sizeof(SCIC_SDS_REQUEST_T) ) 9260786Sps 9360786Sps/** 9460786Sps * This macro aligns the smp command buffer in DWORD alignment 9560786Sps*/ 9660786Sps#define scic_sds_smp_request_align_command_buffer(address) \ 9760786Sps ((char *)( \ 9860786Sps (((POINTER_UINT)(address)) + (sizeof(U32) - 1)) \ 9960786Sps & ~(sizeof(U32)- 1) \ 10060786Sps )) 10160786Sps 10260786Sps/** 10360786Sps * This macro returns the DWORD-aligned smp command buffer 10460786Sps*/ 10560786Sps#define scic_sds_smp_request_get_command_buffer(memory) \ 10660786Sps ((char *) \ 10760786Sps ((char *)scic_sds_smp_request_align_command_buffer( \ 10860786Sps (char *) scic_sds_smp_request_get_command_buffer_unaligned(memory) \ 10960786Sps ))) 11060786Sps 11160786Sps/** 11260786Sps * This macro returns the address of the smp response buffer in the smp request 11360786Sps * memory. 11460786Sps */ 11560786Sps#define scic_sds_smp_request_get_response_buffer_unaligned(memory) \ 11660786Sps ( ((char *)(scic_sds_smp_request_get_command_buffer(memory))) \ 11760786Sps + sizeof(SMP_REQUEST_T) ) 11860786Sps 11960786Sps/** 12060786Sps * This macro aligns the smp command buffer in DWORD alignment 12160786Sps*/ 12260786Sps#define scic_sds_smp_request_align_response_buffer(address) \ 12360786Sps ((char *)( \ 12460786Sps (((POINTER_UINT)(address)) + (sizeof(U32) - 1)) \ 12560786Sps & ~(sizeof(U32)- 1) \ 12660786Sps )) 12760786Sps 12860786Sps/** 12960786Sps * This macro returns the DWORD-aligned smp resposne buffer 13060786Sps*/ 13160786Sps#define scic_sds_smp_request_get_response_buffer(memory) \ 13260786Sps ((char *) \ 13360786Sps ((char *)scic_sds_smp_request_align_response_buffer( \ 13460786Sps (char *) scic_sds_smp_request_get_response_buffer_unaligned(memory) \ 13560786Sps ))) 13660786Sps 13760786Sps/** 13860786Sps * This macro returs the task context buffer for the SMP request. 13960786Sps */ 14060786Sps#define scic_sds_smp_request_get_task_context_buffer_unaligned(memory) \ 14160786Sps ((SCU_TASK_CONTEXT_T *)( \ 14260786Sps ((char *)(scic_sds_smp_request_get_response_buffer(memory))) \ 14360786Sps + sizeof(SMP_RESPONSE_T) \ 14460786Sps )) 14560786Sps 14660786Sps/** 14760786Sps * This macro returns the dword-aligned smp task context buffer 14860786Sps */ 14960786Sps#define scic_sds_smp_request_get_task_context_buffer(memory) \ 15060786Sps ((SCU_TASK_CONTEXT_T *)( \ 15160786Sps ((char *)scic_sds_request_align_task_context_buffer( \ 15260786Sps (char *)scic_sds_smp_request_get_task_context_buffer_unaligned(memory)) \ 15360786Sps ))) 15460786Sps 15560786Sps/** 15660786Sps * @brief This method build the remainder of the IO request object. 15760786Sps * 15889019Sps * @pre The scic_sds_general_request_construct() must be called before this 15960786Sps * call is valid. 16060786Sps * 16160786Sps * @param[in] this_request This parameter specifies the request object being 16260786Sps * constructed. 16360786Sps * 16460786Sps * @return none 16560786Sps */ 16660786Sps 16760786Spsvoid scic_sds_smp_request_assign_buffers( 16860786Sps SCIC_SDS_REQUEST_T *this_request 16960786Sps) 17060786Sps{ 17160786Sps // Assign all of the buffer pointers 17260786Sps this_request->command_buffer = 17360786Sps scic_sds_smp_request_get_command_buffer(this_request); 17460786Sps this_request->response_buffer = 17560786Sps scic_sds_smp_request_get_response_buffer(this_request); 17660786Sps this_request->sgl_element_pair_buffer = NULL; 17760786Sps 17860786Sps if (this_request->was_tag_assigned_by_user == FALSE) 17960786Sps { 18060786Sps this_request->task_context_buffer = 18160786Sps scic_sds_smp_request_get_task_context_buffer(this_request); 18260786Sps } 18360786Sps 18460786Sps} 18560786Sps/** 18660786Sps * @brief This method is called by the SCI user to build an SMP 18760786Sps * IO request. 18860786Sps * 18960786Sps * @pre 19060786Sps * - The user must have previously called scic_io_request_construct() 19160786Sps * on the supplied IO request. 19260786Sps * 19360786Sps * @param[in] scic_io_request This parameter specifies the handle to the 19460786Sps * io request object to be built. 19560786Sps * 19660786Sps * @return Indicate if the controller successfully built the IO request. 19760786Sps * @retval SCI_SUCCESS This value is returned if the IO request was 19860786Sps * successfully built. 19960786Sps * @retval SCI_FAILURE_UNSUPPORTED_PROTOCOL This value is returned if the 20060786Sps * remote_device does not support the SMP protocol. 20160786Sps * @retval SCI_FAILURE_INVALID_ASSOCIATION This value is returned if the 20260786Sps * user did not properly set the association between the SCIC IO 20360786Sps * request and the user's IO request. Please refer to the 20460786Sps * sci_object_set_association() routine for more 20560786Sps * information. 20660786Sps */ 20760786SpsSCI_STATUS scic_io_request_construct_smp( 20860786Sps SCI_IO_REQUEST_HANDLE_T scic_smp_request 20960786Sps) 21060786Sps{ 21160786Sps SMP_REQUEST_T smp_request; 21260786Sps 21360786Sps SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *) scic_smp_request; 21460786Sps SCIC_LOG_TRACE(( 21560786Sps sci_base_object_get_logger(this_request), 21660786Sps SCIC_LOG_OBJECT_SMP_IO_REQUEST, 21760786Sps "scic_io_request_construct_smp(0x%x) enter\n", 21860786Sps this_request 21960786Sps )); 22060786Sps 22160786Sps this_request->protocol = SCIC_SMP_PROTOCOL; 22260786Sps this_request->has_started_substate_machine = TRUE; 22360786Sps 22460786Sps // Construct the started sub-state machine. 22560786Sps sci_base_state_machine_construct( 22660786Sps &this_request->started_substate_machine, 22760786Sps &this_request->parent.parent, 22860786Sps scic_sds_smp_request_started_substate_table, 22960786Sps SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE 23060786Sps ); 23160786Sps 23260786Sps // Construct the SMP SCU Task Context 23360786Sps memcpy((char *)&smp_request, 23460786Sps this_request->command_buffer, 23560786Sps sizeof(SMP_REQUEST_T)); 23660786Sps 23760786Sps // Look at the SMP requests' header fields; for certain SAS 1.x SMP 23860786Sps // functions under SAS 2.0, a zero request length really indicates 23960786Sps // a non-zero default length. 24060786Sps if( smp_request.header.request_length == 0 ) 24160786Sps { 24260786Sps switch( smp_request.header.function ) 24360786Sps { 24460786Sps case SMP_FUNCTION_DISCOVER: 24560786Sps case SMP_FUNCTION_REPORT_PHY_ERROR_LOG: 24660786Sps case SMP_FUNCTION_REPORT_PHY_SATA: 24760786Sps case SMP_FUNCTION_REPORT_ROUTE_INFORMATION: 24860786Sps smp_request.header.request_length = 2; 24960786Sps break; 25060786Sps case SMP_FUNCTION_CONFIGURE_ROUTE_INFORMATION: 25160786Sps case SMP_FUNCTION_PHY_CONTROL: 25260786Sps case SMP_FUNCTION_PHY_TEST: 25360786Sps smp_request.header.request_length = 9; 25460786Sps break; 25560786Sps // Default - zero is a valid default for 2.0. 25660786Sps } 25760786Sps } 25889019Sps 25960786Sps scu_smp_request_construct_task_context( 26089019Sps this_request, 26160786Sps &smp_request 26260786Sps ); 26360786Sps 26460786Sps sci_base_state_machine_change_state( 26560786Sps &this_request->parent.state_machine, 26660786Sps SCI_BASE_REQUEST_STATE_CONSTRUCTED 26760786Sps ); 26860786Sps 26960786Sps return SCI_SUCCESS; 27060786Sps} 27160786Sps 27260786Sps/** 27360786Sps * @brief This method is called by the SCI user to build an SMP pass-through 27460786Sps * IO request. 27560786Sps * 27660786Sps * @pre 27760786Sps * - The user must have previously called scic_io_request_construct() 27860786Sps * on the supplied IO request. 27960786Sps * 28060786Sps * @param[in] scic_smp_request This parameter specifies the handle to the 28160786Sps * io request object to be built. 28289019Sps * 28360786Sps * @param[in] passthru_cb This parameter specifies the pointer to the callback 28460786Sps * structure that contains the function pointers 28560786Sps * 28660786Sps * @return Indicate if the controller successfully built the IO request. 28760786Sps */ 28860786SpsSCI_STATUS scic_io_request_construct_smp_pass_through( 28960786Sps SCI_IO_REQUEST_HANDLE_T scic_smp_request, 29060786Sps SCIC_SMP_PASSTHRU_REQUEST_CALLBACKS_T *passthru_cb 29160786Sps) 29260786Sps{ 29360786Sps SMP_REQUEST_T smp_request; 29460786Sps U8 * request_buffer; 29560786Sps U32 request_buffer_length_in_bytes; 29660786Sps 29760786Sps SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *) scic_smp_request; 29860786Sps SCIC_LOG_TRACE(( 29960786Sps sci_base_object_get_logger(this_request), 30060786Sps SCIC_LOG_OBJECT_SMP_IO_REQUEST, 30160786Sps "scic_io_request_construct_smp_pass_through(0x%x) enter\n", 30260786Sps this_request 30360786Sps )); 30460786Sps 30560786Sps this_request->protocol = SCIC_SMP_PROTOCOL; 30660786Sps this_request->has_started_substate_machine = TRUE; 30760786Sps 30860786Sps // Call the callback function to retrieve the SMP passthrough request 30960786Sps request_buffer_length_in_bytes = passthru_cb->scic_cb_smp_passthru_get_request ( 31060786Sps (void *)this_request, 31160786Sps &request_buffer 31260786Sps ); 31360786Sps 31460786Sps //copy the request to smp request 31560786Sps memcpy((char *)&smp_request.request.vendor_specific_request, 31660786Sps request_buffer, 31760786Sps request_buffer_length_in_bytes); 31860786Sps 31960786Sps //the header length in smp_request is in dwords - the sas spec has similar way, 32060786Sps //but the csmi header contains the number of bytes, so we need to convert the 32160786Sps //number of bytes to number of dwords 32260786Sps smp_request.header.request_length = (U8) (request_buffer_length_in_bytes / sizeof (U32)); 32360786Sps 32460786Sps //Grab the other needed fields from the smp request using callbacks 32560786Sps smp_request.header.smp_frame_type = passthru_cb->scic_cb_smp_passthru_get_frame_type ((void *)this_request); 32660786Sps smp_request.header.function = passthru_cb->scic_cb_smp_passthru_get_function ((void *)this_request); 32760786Sps smp_request.header.allocated_response_length = passthru_cb->scic_cb_smp_passthru_get_allocated_response_length((void *)this_request); 32860786Sps 32960786Sps // Construct the started sub-state machine. 33060786Sps sci_base_state_machine_construct( 33160786Sps &this_request->started_substate_machine, 33260786Sps &this_request->parent.parent, 33360786Sps scic_sds_smp_request_started_substate_table, 33460786Sps SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE 33560786Sps ); 33660786Sps 33760786Sps // Construct the SMP SCU Task Context 33860786Sps scu_smp_request_construct_task_context (this_request, &smp_request); 33960786Sps 34060786Sps sci_base_state_machine_change_state( 34160786Sps &this_request->parent.state_machine, 34260786Sps SCI_BASE_REQUEST_STATE_CONSTRUCTED 34360786Sps ); 34460786Sps 34560786Sps return SCI_SUCCESS; 34660786Sps} 34760786Sps 34860786Sps/** 34960786Sps * @brief This method will fill in the SCU Task Context for a SMP request. The 35060786Sps * following important settings are utilized: 35160786Sps * 35260786Sps * -# task_type == SCU_TASK_TYPE_SMP. This simply indicates 35360786Sps * that a normal request type (i.e. non-raw frame) is being 35460786Sps * utilized to perform task management. 35560786Sps * -# control_frame == 1. This ensures that the proper endianess 35660786Sps * is set so that the bytes are transmitted in the right order 35760786Sps * for a smp request frame. 35860786Sps * 35960786Sps * @param[in] this_request This parameter specifies the smp request object 36060786Sps * being constructed. 36160786Sps * 36260786Sps * @return none 36360786Sps */ 36460786Spsvoid scu_smp_request_construct_task_context( 36560786Sps SCIC_SDS_REQUEST_T *this_request, 36660786Sps SMP_REQUEST_T *smp_request 36760786Sps) 36860786Sps{ 36960786Sps SCI_PHYSICAL_ADDRESS physical_address; 37060786Sps SCIC_SDS_CONTROLLER_T *owning_controller; 37160786Sps SCIC_SDS_REMOTE_DEVICE_T *target_device; 37260786Sps SCIC_SDS_PORT_T *target_port; 37360786Sps SCU_TASK_CONTEXT_T *task_context; 37460786Sps 37560786Sps //byte swap the smp request. 37660786Sps scic_word_copy_with_swap( 37760786Sps this_request->command_buffer, 37860786Sps (U32*) smp_request, 37960786Sps sizeof(SMP_REQUEST_T)/sizeof(U32) 38060786Sps ); 38160786Sps 38260786Sps task_context = scic_sds_request_get_task_context(this_request); 38360786Sps 38460786Sps owning_controller = scic_sds_request_get_controller(this_request); 38560786Sps target_device = scic_sds_request_get_device(this_request); 38660786Sps target_port = scic_sds_request_get_port(this_request); 38760786Sps 38860786Sps SCIC_LOG_TRACE(( 38960786Sps sci_base_object_get_logger(this_request), 39060786Sps SCIC_LOG_OBJECT_SMP_IO_REQUEST, 39160786Sps "scu_smp_request_construct_task_context(0x%x) contents\n" 39260786Sps " reqlen=%x; function=%x;\n", 39360786Sps this_request, 39460786Sps smp_request->header.request_length, 39560786Sps smp_request->header.function 39660786Sps )); 39760786Sps 39860786Sps // Fill in the TC with the its required data 39960786Sps // 00h 40060786Sps task_context->priority = 0; 40160786Sps task_context->initiator_request = 1; 40260786Sps task_context->connection_rate = 40360786Sps scic_remote_device_get_connection_rate(target_device); 40460786Sps task_context->protocol_engine_index = 40560786Sps scic_sds_controller_get_protocol_engine_group(owning_controller); 40660786Sps task_context->logical_port_index = 40760786Sps scic_sds_port_get_index(target_port); 40860786Sps task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SMP; 40960786Sps task_context->abort = 0; 41060786Sps task_context->valid = SCU_TASK_CONTEXT_VALID; 41160786Sps task_context->context_type = SCU_TASK_CONTEXT_TYPE; 41260786Sps 41360786Sps //04h 41460786Sps task_context->remote_node_index = this_request->target_device->rnc->remote_node_index; 41560786Sps task_context->command_code = 0; 41660786Sps task_context->task_type = SCU_TASK_TYPE_SMP_REQUEST; 41760786Sps 41860786Sps //08h 41960786Sps task_context->link_layer_control = 0; 42060786Sps task_context->do_not_dma_ssp_good_response = 1; 42160786Sps task_context->strict_ordering = 0; 42260786Sps task_context->control_frame = 1; 42360786Sps task_context->timeout_enable = 0; 42460786Sps task_context->block_guard_enable = 0; 42560786Sps 42660786Sps //0ch 42760786Sps task_context->address_modifier = 0; 42860786Sps 42960786Sps //10h 43060786Sps task_context->ssp_command_iu_length = smp_request->header.request_length; 43160786Sps 43260786Sps //14h 43360786Sps task_context->transfer_length_bytes = 0; 43460786Sps 43560786Sps //18h ~ 30h, protocol specific 43660786Sps // since commandIU has been build by framework at this point, we just 43760786Sps // copy the frist DWord from command IU to this location. 43860786Sps memcpy((void *)(&task_context->type.smp), this_request->command_buffer, sizeof(U32) ); 43960786Sps 44060786Sps //40h 44160786Sps // "For SMP you could program it to zero. We would prefer that way so that 44260786Sps // done code will be consistent." - Venki 44360786Sps task_context->task_phase = 0; 44460786Sps 44560786Sps if (this_request->was_tag_assigned_by_user) 44660786Sps { 44760786Sps // Build the task context now since we have already read the data 44860786Sps this_request->post_context = ( 44960786Sps SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC 45060786Sps | ( 45160786Sps scic_sds_controller_get_protocol_engine_group(owning_controller) 45260786Sps << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT 45360786Sps ) 45460786Sps | ( 45560786Sps scic_sds_port_get_index(target_port) 45660786Sps << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT 45760786Sps ) 45860786Sps | scic_sds_io_tag_get_index(this_request->io_tag) 45960786Sps ); 46060786Sps } 46160786Sps else 46260786Sps { 46360786Sps // Build the task context now since we have already read the data 46460786Sps this_request->post_context = ( 46560786Sps SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC 46660786Sps | ( 46760786Sps scic_sds_controller_get_protocol_engine_group(owning_controller) 46860786Sps << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT 46960786Sps ) 47060786Sps | ( 47160786Sps scic_sds_port_get_index(target_port) 47260786Sps << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT 47360786Sps ) 47460786Sps // This is not assigned because we have to wait until we get a TCi 47560786Sps ); 47660786Sps } 47760786Sps 47860786Sps // Copy the physical address for the command buffer to the SCU Task Context 47960786Sps // command buffer should not contain command header. 48060786Sps scic_cb_io_request_get_physical_address( 48160786Sps scic_sds_request_get_controller(this_request), 48260786Sps this_request, 48360786Sps ((char *)(this_request->command_buffer) + sizeof(U32)), 48460786Sps &physical_address 48560786Sps ); 48660786Sps 48760786Sps task_context->command_iu_upper = 48860786Sps sci_cb_physical_address_upper(physical_address); 48960786Sps task_context->command_iu_lower = 49060786Sps sci_cb_physical_address_lower(physical_address); 49160786Sps 49260786Sps 49360786Sps //SMP response comes as UF, so no need to set response IU address. 49460786Sps task_context->response_iu_upper = 0; 49560786Sps task_context->response_iu_lower = 0; 49660786Sps} 49760786Sps 49860786Sps//****************************************************************************** 49960786Sps//* SMP REQUEST STATE MACHINE 50060786Sps//****************************************************************************** 50160786Sps 50260786Sps/** 50360786Sps * @brief This method processes an unsolicited frame while the SMP request is 50460786Sps * waiting for a response frame. It will copy the response data, release 50560786Sps * the unsolicited frame, and transition the request to the 50660786Sps * SCI_BASE_REQUEST_STATE_COMPLETED state. 50760786Sps * 50860786Sps * @param[in] this_request This parameter specifies the request for which 50960786Sps * the unsolicited frame was received. 51060786Sps * @param[in] frame_index This parameter indicates the unsolicited frame 51160786Sps * index that should contain the response. 51260786Sps * 51360786Sps * @return This method returns an indication of whether the response 51460786Sps * frame was handled successfully or not. 51560786Sps * @retval SCI_SUCCESS Currently this value is always returned and indicates 51660786Sps * successful processing of the TC response. 51760786Sps */ 51860786Spsstatic 51960786SpsSCI_STATUS scic_sds_smp_request_await_response_frame_handler( 52060786Sps SCIC_SDS_REQUEST_T * this_request, 52160786Sps U32 frame_index 52260786Sps) 52360786Sps{ 52460786Sps SCI_STATUS status; 52560786Sps void * frame_header; 52660786Sps SMP_RESPONSE_HEADER_T * this_frame_header; 52760786Sps U8 * user_smp_buffer = this_request->response_buffer; 52860786Sps 52960786Sps // Save off the controller, so that we do not touch the request after it 53060786Sps // is completed. 53160786Sps SCIC_SDS_CONTROLLER_T * controller = scic_sds_request_get_controller(this_request); 53260786Sps 53360786Sps SCIC_LOG_TRACE(( 53460786Sps sci_base_object_get_logger(this_request), 53560786Sps SCIC_LOG_OBJECT_SMP_IO_REQUEST, 53660786Sps "scic_sds_smp_request_await_response_frame_handler(0x%x, 0x%x) enter\n", 53760786Sps this_request, frame_index 53860786Sps )); 53960786Sps 54060786Sps status = scic_sds_unsolicited_frame_control_get_header( 54160786Sps &(controller->uf_control), 54260786Sps frame_index, 54360786Sps &frame_header 54460786Sps ); 54560786Sps 54660786Sps //byte swap the header. 54760786Sps scic_word_copy_with_swap( 54860786Sps (U32*) user_smp_buffer, 54960786Sps frame_header, 55060786Sps sizeof(SMP_RESPONSE_HEADER_T)/sizeof(U32) 55160786Sps ); 55260786Sps this_frame_header = (SMP_RESPONSE_HEADER_T*) user_smp_buffer; 55360786Sps 55460786Sps if (this_frame_header->smp_frame_type == SMP_FRAME_TYPE_RESPONSE) 55560786Sps { 55660786Sps void * smp_response_buffer; 55760786Sps 55860786Sps status = scic_sds_unsolicited_frame_control_get_buffer( 55960786Sps &(controller->uf_control), 56060786Sps frame_index, 56160786Sps &smp_response_buffer 56260786Sps ); 56360786Sps 56460786Sps scic_word_copy_with_swap( 56560786Sps (U32*) (user_smp_buffer + sizeof(SMP_RESPONSE_HEADER_T)), 56660786Sps smp_response_buffer, 56760786Sps sizeof(SMP_RESPONSE_BODY_T)/sizeof(U32) 56860786Sps ); 56960786Sps if (this_frame_header->function == SMP_FUNCTION_DISCOVER) 57060786Sps { 57160786Sps SMP_RESPONSE_T * this_smp_response; 57260786Sps 57360786Sps this_smp_response = (SMP_RESPONSE_T *)user_smp_buffer; 57460786Sps 57560786Sps // Some expanders only report an attached SATA device, and 57660786Sps // not an STP target. Since the core depends on the STP 57760786Sps // target attribute to correctly build I/O, set the bit now 57860786Sps // if necessary. 57960786Sps if (this_smp_response->response.discover.protocols.u.bits.attached_sata_device 58060786Sps && !this_smp_response->response.discover.protocols.u.bits.attached_stp_target) 58160786Sps { 58260786Sps this_smp_response->response.discover.protocols.u.bits.attached_stp_target = 1; 58360786Sps 58460786Sps SCIC_LOG_TRACE(( 58560786Sps sci_base_object_get_logger(this_request), 58660786Sps SCIC_LOG_OBJECT_SMP_IO_REQUEST, 58760786Sps "scic_sds_smp_request_await_response_frame_handler(0x%x) Found SATA dev, setting STP bit.\n", 58860786Sps this_request 58960786Sps )); 59060786Sps } 59160786Sps } 59260786Sps 59360786Sps //Don't need to copy to user space. User instead will refer to 59460786Sps //core request's response buffer. 59560786Sps 59660786Sps //copy the smp response to framework smp request's response buffer. 59760786Sps //scic_sds_smp_request_copy_response(this_request); 59860786Sps 59960786Sps scic_sds_request_set_status( 60060786Sps this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS 60160786Sps ); 60260786Sps 60360786Sps sci_base_state_machine_change_state( 60460786Sps &this_request->started_substate_machine, 60560786Sps SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION 60660786Sps ); 60760786Sps } 60860786Sps else 60960786Sps { 61060786Sps // This was not a response frame why did it get forwarded? 61160786Sps SCIC_LOG_ERROR(( 61260786Sps sci_base_object_get_logger(this_request), 61360786Sps SCIC_LOG_OBJECT_SMP_IO_REQUEST, 61460786Sps "SCIC SMP Request 0x%08x received unexpected frame %d type 0x%02x\n", 61560786Sps this_request, frame_index, this_frame_header->smp_frame_type 61660786Sps )); 61760786Sps 61860786Sps scic_sds_request_set_status( 61960786Sps this_request, 62060786Sps SCU_TASK_DONE_SMP_FRM_TYPE_ERR, 62160786Sps SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR 62260786Sps ); 62360786Sps 62460786Sps sci_base_state_machine_change_state( 62560786Sps &this_request->parent.state_machine, 62660786Sps SCI_BASE_REQUEST_STATE_COMPLETED 62760786Sps ); 62860786Sps } 62960786Sps 63060786Sps scic_sds_controller_release_frame( 63160786Sps controller, frame_index 63260786Sps ); 63360786Sps 63460786Sps return SCI_SUCCESS; 63560786Sps} 63660786Sps 63760786Sps 63860786Sps/** 63960786Sps * @brief This method processes an abnormal TC completion while the SMP 64060786Sps * request is waiting for a response frame. It decides what 64160786Sps * happened to the IO based on TC completion status. 64260786Sps * 64360786Sps * @param[in] this_request This parameter specifies the request for which 64460786Sps * the TC completion was received. 64560786Sps * @param[in] completion_code This parameter indicates the completion status 64660786Sps * information for the TC. 64760786Sps * 64860786Sps * @return Indicate if the tc completion handler was successful. 64960786Sps * @retval SCI_SUCCESS currently this method always returns success. 65060786Sps */ 65160786Spsstatic 65260786SpsSCI_STATUS scic_sds_smp_request_await_response_tc_completion_handler( 65360786Sps SCIC_SDS_REQUEST_T * this_request, 65460786Sps U32 completion_code 65560786Sps) 65660786Sps{ 65760786Sps SCIC_LOG_TRACE(( 65860786Sps sci_base_object_get_logger(this_request), 65960786Sps SCIC_LOG_OBJECT_SMP_IO_REQUEST, 66060786Sps "scic_sds_smp_request_await_response_tc_completion_handler(0x%x, 0x%x) enter\n", 66160786Sps this_request, completion_code 66260786Sps )); 66360786Sps 66460786Sps switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) 66560786Sps { 66660786Sps case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): 66760786Sps //In the AWAIT RESPONSE state, any TC completion is unexpected. 66860786Sps //but if the TC has success status, we complete the IO anyway. 66960786Sps scic_sds_request_set_status( 67060786Sps this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS 67160786Sps ); 67260786Sps 67360786Sps sci_base_state_machine_change_state( 67460786Sps &this_request->parent.state_machine, 67560786Sps SCI_BASE_REQUEST_STATE_COMPLETED 67660786Sps ); 67760786Sps break; 67860786Sps 67960786Sps case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_RESP_TO_ERR): 68060786Sps case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_UFI_ERR): 68160786Sps case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_FRM_TYPE_ERR): 68260786Sps case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_LL_RX_ERR): 68360786Sps //These status has been seen in a specific LSI expander, which sometimes 68460786Sps //is not able to send smp response within 2 ms. This causes our hardware 68560786Sps //break the connection and set TC completion with one of these SMP_XXX_XX_ERR 68660786Sps //status. For these type of error, we ask scic user to retry the request. 68760786Sps scic_sds_request_set_status( 68860786Sps this_request, SCU_TASK_DONE_SMP_RESP_TO_ERR, SCI_FAILURE_RETRY_REQUIRED 68960786Sps ); 69060786Sps 69160786Sps sci_base_state_machine_change_state( 69260786Sps &this_request->parent.state_machine, 69360786Sps SCI_BASE_REQUEST_STATE_COMPLETED 69460786Sps ); 69560786Sps break; 69660786Sps 69760786Sps default: 69860786Sps // All other completion status cause the IO to be complete. If a NAK 69960786Sps // was received, then it is up to the user to retry the request. 70060786Sps scic_sds_request_set_status( 70160786Sps this_request, 70260786Sps SCU_NORMALIZE_COMPLETION_STATUS(completion_code), 70360786Sps SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR 70460786Sps ); 70560786Sps 70660786Sps sci_base_state_machine_change_state( 70760786Sps &this_request->parent.state_machine, 70860786Sps SCI_BASE_REQUEST_STATE_COMPLETED 70960786Sps ); 71060786Sps break; 71160786Sps } 71260786Sps 71360786Sps return SCI_SUCCESS; 71460786Sps} 71560786Sps 71660786Sps 71760786Sps/** 71860786Sps * @brief This method processes the completions transport layer (TL) status 71960786Sps * to determine if the SMP request was sent successfully. If the SMP 72060786Sps * request was sent successfully, then the state for the SMP request 72160786Sps * transits to waiting for a response frame. 72260786Sps * 72360786Sps * @param[in] this_request This parameter specifies the request for which 72460786Sps * the TC completion was received. 72560786Sps * @param[in] completion_code This parameter indicates the completion status 72660786Sps * information for the TC. 72760786Sps * 72860786Sps * @return Indicate if the tc completion handler was successful. 72960786Sps * @retval SCI_SUCCESS currently this method always returns success. 73060786Sps */ 73160786Spsstatic 73260786SpsSCI_STATUS scic_sds_smp_request_await_tc_completion_tc_completion_handler( 733128345Stjr SCIC_SDS_REQUEST_T * this_request, 734128345Stjr U32 completion_code 735128345Stjr) 736128345Stjr{ 73760786Sps SCIC_LOG_TRACE(( 73860786Sps sci_base_object_get_logger(this_request), 73960786Sps SCIC_LOG_OBJECT_SMP_IO_REQUEST, 74060786Sps "scic_sds_smp_request_await_tc_completion_tc_completion_handler(0x%x, 0x%x) enter\n", 74160786Sps this_request, completion_code 74260786Sps )); 74360786Sps 74460786Sps switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) 74560786Sps { 74660786Sps case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): 74760786Sps scic_sds_request_set_status( 74860786Sps this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS 74960786Sps ); 75060786Sps 75160786Sps sci_base_state_machine_change_state( 75260786Sps &this_request->parent.state_machine, 75360786Sps SCI_BASE_REQUEST_STATE_COMPLETED 75460786Sps ); 75560786Sps break; 75660786Sps 757128345Stjr default: 75860786Sps // All other completion status cause the IO to be complete. If a NAK 75960786Sps // was received, then it is up to the user to retry the request. 76060786Sps scic_sds_request_set_status( 76160786Sps this_request, 76260786Sps SCU_NORMALIZE_COMPLETION_STATUS(completion_code), 76360786Sps SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR 76460786Sps ); 765128345Stjr 76660786Sps sci_base_state_machine_change_state( 76760786Sps &this_request->parent.state_machine, 768128345Stjr SCI_BASE_REQUEST_STATE_COMPLETED 76960786Sps ); 77060786Sps break; 77160786Sps } 77260786Sps 77360786Sps return SCI_SUCCESS; 77460786Sps} 77560786Sps 77660786Sps 77760786SpsSCIC_SDS_IO_REQUEST_STATE_HANDLER_T 778128345Stjrscic_sds_smp_request_started_substate_handler_table 779128345Stjr[SCIC_SDS_SMP_REQUEST_STARTED_MAX_SUBSTATES] = 780128345Stjr{ 781128345Stjr // SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE 782128345Stjr { 78360786Sps { 78460786Sps scic_sds_request_default_start_handler, 785128345Stjr scic_sds_request_started_state_abort_handler, 78660786Sps scic_sds_request_default_complete_handler, 787128345Stjr scic_sds_request_default_destruct_handler 788128345Stjr }, 789128345Stjr scic_sds_smp_request_await_response_tc_completion_handler, 79060786Sps scic_sds_request_default_event_handler, 791128345Stjr scic_sds_smp_request_await_response_frame_handler 792128345Stjr }, 793128345Stjr // SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION 794128345Stjr { 795128345Stjr { 796128345Stjr scic_sds_request_default_start_handler, 797128345Stjr scic_sds_request_started_state_abort_handler, 798128345Stjr scic_sds_request_default_complete_handler, 799128345Stjr scic_sds_request_default_destruct_handler 800128345Stjr }, 801128345Stjr scic_sds_smp_request_await_tc_completion_tc_completion_handler, 802128345Stjr scic_sds_request_default_event_handler, 80360786Sps scic_sds_request_default_frame_handler 80460786Sps } 80560786Sps}; 80660786Sps 80760786Sps/** 80860786Sps * @brief This method performs the actions required when entering the 80960786Sps * SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_RESPONSE sub-state. 81060786Sps * This includes setting the IO request state handlers for this 81160786Sps * sub-state. 81260786Sps * 81360786Sps * @param[in] object This parameter specifies the request object for which 81460786Sps * the sub-state change is occuring. 81560786Sps * 81660786Sps * @return none. 81760786Sps */ 81860786Spsstatic 81960786Spsvoid scic_sds_smp_request_started_await_response_substate_enter( 82060786Sps SCI_BASE_OBJECT_T *object 82160786Sps) 82260786Sps{ 82360786Sps SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object; 82460786Sps 82560786Sps SET_STATE_HANDLER( 82660786Sps this_request, 82760786Sps scic_sds_smp_request_started_substate_handler_table, 82860786Sps SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE 82960786Sps ); 83060786Sps} 83160786Sps 83260786Sps/** 83360786Sps * @brief This method performs the actions required when entering the 83460786Sps * SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION 83560786Sps * sub-state. This includes setting the SMP request state handlers for 83660786Sps * this sub-state. 83760786Sps * 83860786Sps * @param[in] object This parameter specifies the request object for which 83960786Sps * the sub-state change is occuring. 84060786Sps * 84160786Sps * @return none. 84260786Sps */ 84360786Spsstatic 84460786Spsvoid scic_sds_smp_request_started_await_tc_completion_substate_enter( 84560786Sps SCI_BASE_OBJECT_T *object 84660786Sps) 84760786Sps{ 84860786Sps SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object; 84960786Sps 85060786Sps SET_STATE_HANDLER( 85160786Sps this_request, 85260786Sps scic_sds_smp_request_started_substate_handler_table, 853128345Stjr SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION 854128345Stjr ); 855128345Stjr} 856128345Stjr 857128345StjrSCI_BASE_STATE_T scic_sds_smp_request_started_substate_table 858128345Stjr[SCIC_SDS_SMP_REQUEST_STARTED_MAX_SUBSTATES] = 859128345Stjr{ 860128345Stjr { 861128345Stjr SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE, 862128345Stjr scic_sds_smp_request_started_await_response_substate_enter, 863128345Stjr NULL 864128345Stjr }, 865128345Stjr { 866128345Stjr SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION, 86760786Sps scic_sds_smp_request_started_await_tc_completion_substate_enter, 86860786Sps NULL 86960786Sps } 87060786Sps}; 87160786Sps 87260786Sps 87360786Sps