1230557Sjimharris/*- 2230557Sjimharris * This file is provided under a dual BSD/GPLv2 license. When using or 3230557Sjimharris * redistributing this file, you may do so under either license. 4230557Sjimharris * 5230557Sjimharris * GPL LICENSE SUMMARY 6230557Sjimharris * 7230557Sjimharris * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 8230557Sjimharris * 9230557Sjimharris * This program is free software; you can redistribute it and/or modify 10230557Sjimharris * it under the terms of version 2 of the GNU General Public License as 11230557Sjimharris * published by the Free Software Foundation. 12230557Sjimharris * 13230557Sjimharris * This program is distributed in the hope that it will be useful, but 14230557Sjimharris * WITHOUT ANY WARRANTY; without even the implied warranty of 15230557Sjimharris * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16230557Sjimharris * General Public License for more details. 17230557Sjimharris * 18230557Sjimharris * You should have received a copy of the GNU General Public License 19230557Sjimharris * along with this program; if not, write to the Free Software 20230557Sjimharris * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 21230557Sjimharris * The full GNU General Public License is included in this distribution 22230557Sjimharris * in the file called LICENSE.GPL. 23230557Sjimharris * 24230557Sjimharris * BSD LICENSE 25230557Sjimharris * 26230557Sjimharris * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 27230557Sjimharris * All rights reserved. 28230557Sjimharris * 29230557Sjimharris * Redistribution and use in source and binary forms, with or without 30230557Sjimharris * modification, are permitted provided that the following conditions 31230557Sjimharris * are met: 32230557Sjimharris * 33230557Sjimharris * * Redistributions of source code must retain the above copyright 34230557Sjimharris * notice, this list of conditions and the following disclaimer. 35230557Sjimharris * * Redistributions in binary form must reproduce the above copyright 36230557Sjimharris * notice, this list of conditions and the following disclaimer in 37230557Sjimharris * the documentation and/or other materials provided with the 38230557Sjimharris * distribution. 39230557Sjimharris * 40230557Sjimharris * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 41230557Sjimharris * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 42230557Sjimharris * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 43230557Sjimharris * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 44230557Sjimharris * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45230557Sjimharris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 46230557Sjimharris * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 47230557Sjimharris * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 48230557Sjimharris * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 49230557Sjimharris * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 50230557Sjimharris * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 51230557Sjimharris */ 52230557Sjimharris 53230557Sjimharris#include <sys/cdefs.h> 54230557Sjimharris__FBSDID("$FreeBSD$"); 55230557Sjimharris 56230557Sjimharris#include <dev/isci/scil/intel_sat.h> 57230557Sjimharris#include <dev/isci/scil/intel_sata.h> 58230557Sjimharris#include <dev/isci/scil/sci_types.h> 59230557Sjimharris#include <dev/isci/scil/scic_remote_device.h> 60230557Sjimharris#include <dev/isci/scil/scic_user_callback.h> 61230557Sjimharris#include <dev/isci/scil/scic_sds_controller.h> 62230557Sjimharris#include <dev/isci/scil/scic_sds_remote_device.h> 63230557Sjimharris#include <dev/isci/scil/scic_sds_stp_request.h> 64230557Sjimharris#include <dev/isci/scil/scic_sds_stp_pio_request.h> 65230557Sjimharris#include <dev/isci/scil/scic_sds_logger.h> 66230557Sjimharris#include <dev/isci/sci_environment.h> 67230557Sjimharris#include <dev/isci/scil/sci_base_state_machine.h> 68230557Sjimharris#include <dev/isci/scil/scu_task_context.h> 69230557Sjimharris#include <dev/isci/scil/intel_ata.h> 70230557Sjimharris#include <dev/isci/scil/sci_util.h> 71230557Sjimharris#include <dev/isci/scil/scic_sds_logger.h> 72230557Sjimharris#include <dev/isci/scil/scic_sds_request.h> 73230557Sjimharris#include <dev/isci/scil/scic_sds_stp_request.h> 74230557Sjimharris#include <dev/isci/scil/scu_completion_codes.h> 75230557Sjimharris#include <dev/isci/scil/scu_event_codes.h> 76230557Sjimharris#include <dev/isci/scil/sci_base_state.h> 77230557Sjimharris#include <dev/isci/scil/scic_sds_unsolicited_frame_control.h> 78230557Sjimharris#include <dev/isci/scil/scic_io_request.h> 79230557Sjimharris 80230557Sjimharris#if !defined(DISABLE_ATAPI) 81230557Sjimharris#include <dev/isci/scil/scic_sds_stp_packet_request.h> 82230557Sjimharris#endif 83230557Sjimharris 84230557Sjimharris/** 85230557Sjimharris * This macro returns the address of the stp h2d reg fis buffer in the io 86230557Sjimharris * request memory 87230557Sjimharris */ 88230557Sjimharris#define scic_sds_stp_request_get_h2d_reg_buffer_unaligned(memory) \ 89230557Sjimharris ((SATA_FIS_REG_H2D_T *)( \ 90230557Sjimharris ((char *)(memory)) + sizeof(SCIC_SDS_STP_REQUEST_T) \ 91230557Sjimharris )) 92230557Sjimharris 93230557Sjimharris/** 94230557Sjimharris * This macro aligns the stp command buffer in DWORD alignment 95230557Sjimharris*/ 96230557Sjimharris#define scic_sds_stp_request_align_h2d_reg_buffer(address) \ 97230557Sjimharris ((SATA_FIS_REG_H2D_T *)( \ 98230557Sjimharris (((POINTER_UINT)(address)) + (sizeof(U32) - 1)) \ 99230557Sjimharris & ~(sizeof(U32)- 1) \ 100230557Sjimharris )) 101230557Sjimharris 102230557Sjimharris/** 103230557Sjimharris * This macro returns the DWORD-aligned stp command buffer 104230557Sjimharris*/ 105230557Sjimharris#define scic_sds_stp_request_get_h2d_reg_buffer(memory) \ 106230557Sjimharris ((SATA_FIS_REG_H2D_T *) \ 107230557Sjimharris ((char *)scic_sds_stp_request_align_h2d_reg_buffer( \ 108230557Sjimharris (char *) scic_sds_stp_request_get_h2d_reg_buffer_unaligned(memory) \ 109230557Sjimharris ))) 110230557Sjimharris 111230557Sjimharris/** 112230557Sjimharris * This macro returns the address of the stp response buffer in the io 113230557Sjimharris * request memory 114230557Sjimharris */ 115230557Sjimharris#define scic_sds_stp_request_get_response_buffer_unaligned(memory) \ 116230557Sjimharris ((SATA_FIS_REG_D2H_T *)( \ 117230557Sjimharris ((char *)(scic_sds_stp_request_get_h2d_reg_buffer(memory))) \ 118230557Sjimharris + sizeof(SATA_FIS_REG_H2D_T) \ 119230557Sjimharris )) 120230557Sjimharris 121230557Sjimharris 122230557Sjimharris/** 123230557Sjimharris * This macro aligns the stp response buffer in DWORD alignment 124230557Sjimharris*/ 125230557Sjimharris#define scic_sds_stp_request_align_response_buffer(address) \ 126230557Sjimharris ((SATA_FIS_REG_D2H_T *)( \ 127230557Sjimharris (((POINTER_UINT)(address)) + (sizeof(U32) - 1)) \ 128230557Sjimharris & ~(sizeof(U32)- 1) \ 129230557Sjimharris )) 130230557Sjimharris 131230557Sjimharris/** 132230557Sjimharris * This macro returns the DWORD-aligned stp response buffer 133230557Sjimharris*/ 134230557Sjimharris#define scic_sds_stp_request_get_response_buffer(memory) \ 135230557Sjimharris ((SATA_FIS_REG_D2H_T *) \ 136230557Sjimharris ((char *)scic_sds_stp_request_align_response_buffer( \ 137230557Sjimharris (char *)scic_sds_stp_request_get_response_buffer_unaligned(memory) \ 138230557Sjimharris ))) 139230557Sjimharris 140230557Sjimharris 141230557Sjimharris/** 142230557Sjimharris * This macro returns the address of the task context buffer in the io 143230557Sjimharris * request memory 144230557Sjimharris */ 145230557Sjimharris#define scic_sds_stp_request_get_task_context_buffer_unaligned(memory) \ 146230557Sjimharris ((SCU_TASK_CONTEXT_T *)( \ 147230557Sjimharris ((char *)(scic_sds_stp_request_get_response_buffer(memory))) \ 148230557Sjimharris + sizeof(SCI_SSP_RESPONSE_IU_T) \ 149230557Sjimharris )) 150230557Sjimharris 151230557Sjimharris/** 152230557Sjimharris * This macro returns the aligned task context buffer 153230557Sjimharris */ 154230557Sjimharris#define scic_sds_stp_request_get_task_context_buffer(memory) \ 155230557Sjimharris ((SCU_TASK_CONTEXT_T *)( \ 156230557Sjimharris ((char *)scic_sds_request_align_task_context_buffer( \ 157230557Sjimharris (char *)scic_sds_stp_request_get_task_context_buffer_unaligned(memory)) \ 158230557Sjimharris ))) 159230557Sjimharris 160230557Sjimharris/** 161230557Sjimharris * This macro returns the address of the sgl elment pairs in the io request 162230557Sjimharris * memory buffer 163230557Sjimharris */ 164230557Sjimharris#define scic_sds_stp_request_get_sgl_element_buffer(memory) \ 165230557Sjimharris ((SCU_SGL_ELEMENT_PAIR_T *)( \ 166230557Sjimharris ((char *)(scic_sds_stp_request_get_task_context_buffer(memory))) \ 167230557Sjimharris + sizeof(SCU_TASK_CONTEXT_T) \ 168230557Sjimharris )) 169230557Sjimharris 170230557Sjimharris 171230557Sjimharris/** 172230557Sjimharris * This method return the memory space commonly required for STP IO and 173230557Sjimharris * task requests. 174230557Sjimharris * 175230557Sjimharris * @return U32 176230557Sjimharris */ 177230557Sjimharrisstatic 178230557SjimharrisU32 scic_sds_stp_common_request_get_object_size(void) 179230557Sjimharris{ 180230557Sjimharris return sizeof(SCIC_SDS_STP_REQUEST_T) 181230557Sjimharris + sizeof(SATA_FIS_REG_H2D_T) 182230557Sjimharris + sizeof(U32) 183230557Sjimharris + sizeof(SATA_FIS_REG_D2H_T) 184230557Sjimharris + sizeof(U32) 185230557Sjimharris + sizeof(SCU_TASK_CONTEXT_T) 186230557Sjimharris + CACHE_LINE_SIZE; 187230557Sjimharris} 188230557Sjimharris 189230557Sjimharris 190230557Sjimharris/** 191230557Sjimharris * This method return the memory space required for STP PIO requests. 192230557Sjimharris * 193230557Sjimharris * @return U32 194230557Sjimharris */ 195230557SjimharrisU32 scic_sds_stp_request_get_object_size(void) 196230557Sjimharris{ 197230557Sjimharris return scic_sds_stp_common_request_get_object_size() 198230557Sjimharris + sizeof(SCU_SGL_ELEMENT_PAIR_T) * SCU_MAX_SGL_ELEMENT_PAIRS; 199230557Sjimharris} 200230557Sjimharris 201230557Sjimharris 202230557Sjimharris/** 203230557Sjimharris * This method return the memory space required for STP task requests. 204230557Sjimharris * 205230557Sjimharris * @return U32 206230557Sjimharris */ 207230557SjimharrisU32 scic_sds_stp_task_request_get_object_size(void) 208230557Sjimharris{ 209230557Sjimharris return scic_sds_stp_common_request_get_object_size(); 210230557Sjimharris} 211230557Sjimharris 212230557Sjimharris 213230557Sjimharris/** 214230557Sjimharris * 215230557Sjimharris * 216230557Sjimharris * @param[in] this_request 217230557Sjimharris */ 218230557Sjimharrisvoid scic_sds_stp_request_assign_buffers( 219230557Sjimharris SCIC_SDS_REQUEST_T * request 220230557Sjimharris) 221230557Sjimharris{ 222230557Sjimharris SCIC_SDS_STP_REQUEST_T * this_request = (SCIC_SDS_STP_REQUEST_T *)request; 223230557Sjimharris 224230557Sjimharris this_request->parent.command_buffer = 225230557Sjimharris scic_sds_stp_request_get_h2d_reg_buffer(this_request); 226230557Sjimharris this_request->parent.response_buffer = 227230557Sjimharris scic_sds_stp_request_get_response_buffer(this_request); 228230557Sjimharris this_request->parent.sgl_element_pair_buffer = 229230557Sjimharris scic_sds_stp_request_get_sgl_element_buffer(this_request); 230230557Sjimharris this_request->parent.sgl_element_pair_buffer = 231230557Sjimharris scic_sds_request_align_sgl_element_buffer(this_request->parent.sgl_element_pair_buffer); 232230557Sjimharris 233230557Sjimharris if (this_request->parent.was_tag_assigned_by_user == FALSE) 234230557Sjimharris { 235230557Sjimharris this_request->parent.task_context_buffer = 236230557Sjimharris scic_sds_stp_request_get_task_context_buffer(this_request); 237230557Sjimharris } 238230557Sjimharris} 239230557Sjimharris 240230557Sjimharris/** 241230557Sjimharris * @brief This method is will fill in the SCU Task Context for any type of 242230557Sjimharris * SATA request. This is called from the various SATA constructors. 243230557Sjimharris * 244230557Sjimharris * @pre The general io request construction is complete. 245230557Sjimharris * @pre The buffer assignment for the command buffer is complete. 246230557Sjimharris * 247230557Sjimharris * @param[in] this_request The general IO request object which is to be used 248230557Sjimharris * in constructing the SCU task context. 249230557Sjimharris * @param[in] task_context The buffer pointer for the SCU task context which 250230557Sjimharris * is being constructed. 251230557Sjimharris * 252230557Sjimharris * @return none 253230557Sjimharris * 254230557Sjimharris * @todo Revisit task context construction to determine what is common for 255230557Sjimharris * SSP/SMP/STP task context structures. 256230557Sjimharris */ 257230557Sjimharrisvoid scu_sata_reqeust_construct_task_context( 258230557Sjimharris SCIC_SDS_REQUEST_T * this_request, 259230557Sjimharris SCU_TASK_CONTEXT_T * task_context 260230557Sjimharris) 261230557Sjimharris{ 262230557Sjimharris SCI_PHYSICAL_ADDRESS physical_address; 263230557Sjimharris SCIC_SDS_CONTROLLER_T *owning_controller; 264230557Sjimharris SCIC_SDS_REMOTE_DEVICE_T *target_device; 265230557Sjimharris SCIC_SDS_PORT_T *target_port; 266230557Sjimharris 267230557Sjimharris owning_controller = scic_sds_request_get_controller(this_request); 268230557Sjimharris target_device = scic_sds_request_get_device(this_request); 269230557Sjimharris target_port = scic_sds_request_get_port(this_request); 270230557Sjimharris 271230557Sjimharris // Fill in the TC with the its required data 272230557Sjimharris task_context->abort = 0; 273230557Sjimharris task_context->priority = SCU_TASK_PRIORITY_NORMAL; 274230557Sjimharris task_context->initiator_request = 1; 275230557Sjimharris task_context->connection_rate = 276230557Sjimharris scic_remote_device_get_connection_rate(target_device); 277230557Sjimharris task_context->protocol_engine_index = 278230557Sjimharris scic_sds_controller_get_protocol_engine_group(owning_controller); 279230557Sjimharris task_context->logical_port_index = 280230557Sjimharris scic_sds_port_get_index(target_port); 281230557Sjimharris task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_STP; 282230557Sjimharris task_context->valid = SCU_TASK_CONTEXT_VALID; 283230557Sjimharris task_context->context_type = SCU_TASK_CONTEXT_TYPE; 284230557Sjimharris 285230557Sjimharris task_context->remote_node_index = 286230557Sjimharris scic_sds_remote_device_get_index(this_request->target_device); 287230557Sjimharris task_context->command_code = 0; 288230557Sjimharris 289230557Sjimharris task_context->link_layer_control = 0; 290230557Sjimharris task_context->do_not_dma_ssp_good_response = 1; 291230557Sjimharris task_context->strict_ordering = 0; 292230557Sjimharris task_context->control_frame = 0; 293230557Sjimharris task_context->timeout_enable = 0; 294230557Sjimharris task_context->block_guard_enable = 0; 295230557Sjimharris 296230557Sjimharris task_context->address_modifier = 0; 297230557Sjimharris task_context->task_phase = 0x01; 298230557Sjimharris 299230557Sjimharris task_context->ssp_command_iu_length = 300230557Sjimharris (sizeof(SATA_FIS_REG_H2D_T) - sizeof(U32)) / sizeof(U32); 301230557Sjimharris 302230557Sjimharris // Set the first word of the H2D REG FIS 303230557Sjimharris task_context->type.words[0] = *(U32 *)this_request->command_buffer; 304230557Sjimharris 305230557Sjimharris if (this_request->was_tag_assigned_by_user) 306230557Sjimharris { 307230557Sjimharris // Build the task context now since we have already read the data 308230557Sjimharris this_request->post_context = ( 309230557Sjimharris SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC 310230557Sjimharris | ( 311230557Sjimharris scic_sds_controller_get_protocol_engine_group(owning_controller) 312230557Sjimharris << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT 313230557Sjimharris ) 314230557Sjimharris | ( 315230557Sjimharris scic_sds_port_get_index(target_port) 316230557Sjimharris << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT 317230557Sjimharris ) 318230557Sjimharris | scic_sds_io_tag_get_index(this_request->io_tag) 319230557Sjimharris ); 320230557Sjimharris } 321230557Sjimharris else 322230557Sjimharris { 323230557Sjimharris // Build the task context now since we have already read the data 324230557Sjimharris this_request->post_context = ( 325230557Sjimharris SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC 326230557Sjimharris | ( 327230557Sjimharris scic_sds_controller_get_protocol_engine_group(owning_controller) 328230557Sjimharris << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT 329230557Sjimharris ) 330230557Sjimharris | ( 331230557Sjimharris scic_sds_port_get_index(target_port) 332230557Sjimharris << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT 333230557Sjimharris ) 334230557Sjimharris // This is not assigned because we have to wait until we get a TCi 335230557Sjimharris ); 336230557Sjimharris } 337230557Sjimharris 338230557Sjimharris // Copy the physical address for the command buffer to the SCU Task Context 339230557Sjimharris // We must offset the command buffer by 4 bytes because the first 4 bytes are 340230557Sjimharris // transfered in the body of the TC 341230557Sjimharris scic_cb_io_request_get_physical_address( 342230557Sjimharris scic_sds_request_get_controller(this_request), 343230557Sjimharris this_request, 344230557Sjimharris ((char *)this_request->command_buffer) + sizeof(U32), 345230557Sjimharris &physical_address 346230557Sjimharris ); 347230557Sjimharris 348230557Sjimharris task_context->command_iu_upper = 349230557Sjimharris sci_cb_physical_address_upper(physical_address); 350230557Sjimharris task_context->command_iu_lower = 351230557Sjimharris sci_cb_physical_address_lower(physical_address); 352230557Sjimharris 353230557Sjimharris // SATA Requests do not have a response buffer 354230557Sjimharris task_context->response_iu_upper = 0; 355230557Sjimharris task_context->response_iu_lower = 0; 356230557Sjimharris} 357230557Sjimharris 358230557Sjimharris/** 359230557Sjimharris * This method will perform any general sata request construction. 360230557Sjimharris * 361230557Sjimharris * @todo What part of SATA IO request construction is general? 362230557Sjimharris * 363230557Sjimharris * @param[in] this_request 364230557Sjimharris * 365230557Sjimharris * @return none 366230557Sjimharris */ 367230557Sjimharrisvoid scic_sds_stp_non_ncq_request_construct( 368230557Sjimharris SCIC_SDS_REQUEST_T * this_request 369230557Sjimharris) 370230557Sjimharris{ 371230557Sjimharris this_request->has_started_substate_machine = TRUE; 372230557Sjimharris} 373230557Sjimharris 374230557Sjimharris/** 375230557Sjimharris * This method will perform request construction common to all types of 376230557Sjimharris * STP requests that are optimized by the silicon (i.e. UDMA, NCQ). 377230557Sjimharris * 378230557Sjimharris * @param[in,out] this_request This parameter specifies the request to be 379230557Sjimharris * constructed as an optimized request. 380230557Sjimharris * @param[in] optimized_task_type This parameter specifies whether the 381230557Sjimharris * request is to be an UDMA request or a NCQ request. 382230557Sjimharris * - A value of 0 indicates UDMA. 383230557Sjimharris * - A value of 1 indicates NCQ. 384230557Sjimharris * 385230557Sjimharris * @return This method returns an indication as to whether the construction 386230557Sjimharris * was successful. 387230557Sjimharris */ 388230557Sjimharrisstatic 389230557Sjimharrisvoid scic_sds_stp_optimized_request_construct( 390230557Sjimharris SCIC_SDS_REQUEST_T * this_request, 391230557Sjimharris U8 optimized_task_type, 392230557Sjimharris U32 transfer_length, 393230557Sjimharris SCI_IO_REQUEST_DATA_DIRECTION data_direction 394230557Sjimharris) 395230557Sjimharris{ 396230557Sjimharris SCU_TASK_CONTEXT_T * task_context = this_request->task_context_buffer; 397230557Sjimharris 398230557Sjimharris // Build the STP task context structure 399230557Sjimharris scu_sata_reqeust_construct_task_context(this_request, task_context); 400230557Sjimharris 401230557Sjimharris // Copy over the number of bytes to be transfered 402230557Sjimharris task_context->transfer_length_bytes = transfer_length; 403230557Sjimharris 404230557Sjimharris if ( data_direction == SCI_IO_REQUEST_DATA_OUT ) 405230557Sjimharris { 406230557Sjimharris // The difference between the DMA IN and DMA OUT request task type 407230557Sjimharris // values are consistent with the difference between FPDMA READ 408230557Sjimharris // and FPDMA WRITE values. Add the supplied task type parameter 409230557Sjimharris // to this difference to set the task type properly for this 410230557Sjimharris // DATA OUT (WRITE) case. 411230557Sjimharris task_context->task_type = optimized_task_type + (SCU_TASK_TYPE_DMA_OUT 412230557Sjimharris - SCU_TASK_TYPE_DMA_IN); 413230557Sjimharris } 414230557Sjimharris else 415230557Sjimharris { 416230557Sjimharris // For the DATA IN (READ) case, simply save the supplied 417230557Sjimharris // optimized task type. 418230557Sjimharris task_context->task_type = optimized_task_type; 419230557Sjimharris } 420230557Sjimharris} 421230557Sjimharris 422230557Sjimharris/** 423230557Sjimharris * This method performs the operations common to all SATA/STP requests 424230557Sjimharris * utilizing the raw frame method. 425230557Sjimharris * 426230557Sjimharris * @param[in] this_request This parameter specifies the STP request object 427230557Sjimharris * for which to construct a RAW command frame task context. 428230557Sjimharris * @param[in] task_context This parameter specifies the SCU specific 429230557Sjimharris * task context buffer to construct. 430230557Sjimharris * 431230557Sjimharris * @return none 432230557Sjimharris */ 433230557Sjimharrisvoid scu_stp_raw_request_construct_task_context( 434230557Sjimharris SCIC_SDS_STP_REQUEST_T * this_request, 435230557Sjimharris SCU_TASK_CONTEXT_T * task_context 436230557Sjimharris) 437230557Sjimharris{ 438230557Sjimharris scu_sata_reqeust_construct_task_context(&this_request->parent, task_context); 439230557Sjimharris 440230557Sjimharris task_context->control_frame = 0; 441230557Sjimharris task_context->priority = SCU_TASK_PRIORITY_NORMAL; 442230557Sjimharris task_context->task_type = SCU_TASK_TYPE_SATA_RAW_FRAME; 443230557Sjimharris task_context->type.stp.fis_type = SATA_FIS_TYPE_REGH2D; 444230557Sjimharris task_context->transfer_length_bytes = sizeof(SATA_FIS_REG_H2D_T) - sizeof(U32); 445230557Sjimharris} 446230557Sjimharris 447230557Sjimharris/** 448230557Sjimharris * This method will construct the STP Non-data request and its associated 449230557Sjimharris * TC data. A non-data request essentially behaves like a 0 length read 450230557Sjimharris * request in the SCU. 451230557Sjimharris * 452230557Sjimharris * @param[in] this_request This parameter specifies the core request 453230557Sjimharris * object to construction into an STP/SATA non-data request. 454230557Sjimharris * 455230557Sjimharris * @return This method currently always returns SCI_SUCCESS 456230557Sjimharris */ 457230557SjimharrisSCI_STATUS scic_sds_stp_non_data_request_construct( 458230557Sjimharris SCIC_SDS_REQUEST_T * this_request 459230557Sjimharris) 460230557Sjimharris{ 461230557Sjimharris scic_sds_stp_non_ncq_request_construct(this_request); 462230557Sjimharris 463230557Sjimharris // Build the STP task context structure 464230557Sjimharris scu_stp_raw_request_construct_task_context( 465230557Sjimharris (SCIC_SDS_STP_REQUEST_T*) this_request, 466230557Sjimharris this_request->task_context_buffer 467230557Sjimharris ); 468230557Sjimharris 469230557Sjimharris sci_base_state_machine_construct( 470230557Sjimharris &this_request->started_substate_machine, 471230557Sjimharris &this_request->parent.parent, 472230557Sjimharris scic_sds_stp_request_started_non_data_substate_table, 473230557Sjimharris SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE 474230557Sjimharris ); 475230557Sjimharris 476230557Sjimharris return SCI_SUCCESS; 477230557Sjimharris} 478230557Sjimharris 479230557Sjimharris 480230557SjimharrisSCI_STATUS scic_sds_stp_soft_reset_request_construct( 481230557Sjimharris SCIC_SDS_REQUEST_T * this_request 482230557Sjimharris) 483230557Sjimharris{ 484230557Sjimharris scic_sds_stp_non_ncq_request_construct(this_request); 485230557Sjimharris 486230557Sjimharris // Build the STP task context structure 487230557Sjimharris scu_stp_raw_request_construct_task_context( 488230557Sjimharris (SCIC_SDS_STP_REQUEST_T*) this_request, 489230557Sjimharris this_request->task_context_buffer 490230557Sjimharris ); 491230557Sjimharris 492230557Sjimharris sci_base_state_machine_construct( 493230557Sjimharris &this_request->started_substate_machine, 494230557Sjimharris &this_request->parent.parent, 495230557Sjimharris scic_sds_stp_request_started_soft_reset_substate_table, 496230557Sjimharris SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE 497230557Sjimharris ); 498230557Sjimharris 499230557Sjimharris return SCI_SUCCESS; 500230557Sjimharris} 501230557Sjimharris 502230557Sjimharris/** 503230557Sjimharris * @brief This method constructs the SATA request object. 504230557Sjimharris * 505230557Sjimharris * @param[in] this_request 506230557Sjimharris * @param[in] sat_protocol 507230557Sjimharris * @param[in] transfer_length 508230557Sjimharris * @param[in] data_direction 509230557Sjimharris * @param[in] copy_rx_frame 510230557Sjimharris * @param[in] do_translate_sgl This parameter specifies whether SGL 511230557Sjimharris * translation should be performed or if the user is handling 512230557Sjimharris * it. 513230557Sjimharris * 514230557Sjimharris * @return SCI_STATUS 515230557Sjimharris */ 516230557SjimharrisSCI_STATUS scic_sds_io_request_construct_sata( 517230557Sjimharris SCIC_SDS_REQUEST_T * this_request, 518230557Sjimharris U8 sat_protocol, 519230557Sjimharris U32 transfer_length, 520230557Sjimharris SCI_IO_REQUEST_DATA_DIRECTION data_direction, 521230557Sjimharris BOOL copy_rx_frame, 522230557Sjimharris BOOL do_translate_sgl 523230557Sjimharris) 524230557Sjimharris{ 525230557Sjimharris SCI_STATUS status = SCI_SUCCESS; 526230557Sjimharris 527230557Sjimharris this_request->protocol = SCIC_STP_PROTOCOL; 528230557Sjimharris 529230557Sjimharris this_request->sat_protocol = sat_protocol; 530230557Sjimharris 531230557Sjimharris switch (sat_protocol) 532230557Sjimharris { 533230557Sjimharris case SAT_PROTOCOL_FPDMA: 534230557Sjimharris scic_sds_stp_optimized_request_construct( 535230557Sjimharris this_request, 536230557Sjimharris SCU_TASK_TYPE_FPDMAQ_READ, 537230557Sjimharris transfer_length, 538230557Sjimharris data_direction 539230557Sjimharris ); 540230557Sjimharris 541230557Sjimharris // Copy over the SGL elements 542230557Sjimharris if (do_translate_sgl == TRUE) 543230557Sjimharris scic_sds_request_build_sgl(this_request); 544230557Sjimharris break; 545230557Sjimharris 546230557Sjimharris case SAT_PROTOCOL_UDMA_DATA_IN: 547230557Sjimharris case SAT_PROTOCOL_UDMA_DATA_OUT: 548230557Sjimharris scic_sds_stp_non_ncq_request_construct(this_request); 549230557Sjimharris 550230557Sjimharris scic_sds_stp_optimized_request_construct( 551230557Sjimharris this_request, SCU_TASK_TYPE_DMA_IN, transfer_length, data_direction 552230557Sjimharris ); 553230557Sjimharris 554230557Sjimharris // Copy over the SGL elements 555230557Sjimharris if (do_translate_sgl == TRUE) 556230557Sjimharris scic_sds_request_build_sgl(this_request); 557230557Sjimharris 558230557Sjimharris sci_base_state_machine_construct( 559230557Sjimharris &this_request->started_substate_machine, 560230557Sjimharris &this_request->parent.parent, 561230557Sjimharris scic_sds_stp_request_started_udma_substate_table, 562230557Sjimharris SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE 563230557Sjimharris ); 564230557Sjimharris break; 565230557Sjimharris 566230557Sjimharris case SAT_PROTOCOL_PIO_DATA_IN: 567230557Sjimharris case SAT_PROTOCOL_PIO_DATA_OUT: 568230557Sjimharris status = scic_sds_stp_pio_request_construct( 569230557Sjimharris this_request, sat_protocol, copy_rx_frame); 570230557Sjimharris break; 571230557Sjimharris 572230557Sjimharris case SAT_PROTOCOL_ATA_HARD_RESET: 573230557Sjimharris case SAT_PROTOCOL_SOFT_RESET: 574230557Sjimharris status = scic_sds_stp_soft_reset_request_construct(this_request); 575230557Sjimharris break; 576230557Sjimharris 577230557Sjimharris case SAT_PROTOCOL_NON_DATA: 578230557Sjimharris status = scic_sds_stp_non_data_request_construct(this_request); 579230557Sjimharris break; 580230557Sjimharris 581230557Sjimharris#if !defined(DISABLE_ATAPI) 582230557Sjimharris case SAT_PROTOCOL_PACKET_NON_DATA: 583230557Sjimharris case SAT_PROTOCOL_PACKET_DMA_DATA_IN: 584230557Sjimharris case SAT_PROTOCOL_PACKET_DMA_DATA_OUT: 585230557Sjimharris case SAT_PROTOCOL_PACKET_PIO_DATA_IN: 586230557Sjimharris case SAT_PROTOCOL_PACKET_PIO_DATA_OUT: 587230557Sjimharris status = scic_sds_stp_packet_request_construct(this_request); 588230792Sjimharris if (do_translate_sgl == TRUE) 589230792Sjimharris scic_sds_request_build_sgl(this_request); 590230557Sjimharris break; 591230557Sjimharris#endif 592230557Sjimharris 593230557Sjimharris case SAT_PROTOCOL_DMA_QUEUED: 594230557Sjimharris case SAT_PROTOCOL_DMA: 595230557Sjimharris case SAT_PROTOCOL_DEVICE_DIAGNOSTIC: 596230557Sjimharris case SAT_PROTOCOL_DEVICE_RESET: 597230557Sjimharris case SAT_PROTOCOL_RETURN_RESPONSE_INFO: 598230557Sjimharris default: 599230557Sjimharris SCIC_LOG_ERROR(( 600230557Sjimharris sci_base_object_get_logger(this_request), 601230557Sjimharris SCIC_LOG_OBJECT_STP_IO_REQUEST, 602230557Sjimharris "SCIC IO Request 0x%x received un-handled SAT Protocol %d.\n", 603230557Sjimharris this_request, sat_protocol 604230557Sjimharris )); 605230557Sjimharris 606230557Sjimharris status = SCI_FAILURE; 607230557Sjimharris break; 608230557Sjimharris } 609230557Sjimharris 610230557Sjimharris if (status == SCI_SUCCESS) 611230557Sjimharris { 612230557Sjimharris scic_sds_request_initialize_state_logging(this_request); 613230557Sjimharris 614230557Sjimharris sci_base_state_machine_change_state( 615230557Sjimharris &this_request->parent.state_machine, 616230557Sjimharris SCI_BASE_REQUEST_STATE_CONSTRUCTED 617230557Sjimharris ); 618230557Sjimharris } 619230557Sjimharris 620230557Sjimharris return status; 621230557Sjimharris} 622230557Sjimharris 623230557Sjimharris//**************************************************************************** 624230557Sjimharris//* SCIC Interface Implementation 625230557Sjimharris//**************************************************************************** 626230557Sjimharris 627230557Sjimharrisvoid scic_stp_io_request_set_ncq_tag( 628230557Sjimharris SCI_IO_REQUEST_HANDLE_T scic_io_request, 629230557Sjimharris U16 ncq_tag 630230557Sjimharris) 631230557Sjimharris{ 632230557Sjimharris /** 633230557Sjimharris * @note This could be made to return an error to the user if the user 634230557Sjimharris * attempts to set the NCQ tag in the wrong state. 635230557Sjimharris */ 636230557Sjimharris SCIC_SDS_REQUEST_T * this_request = (SCIC_SDS_REQUEST_T *)scic_io_request; 637230557Sjimharris this_request->task_context_buffer->type.stp.ncq_tag = ncq_tag; 638230557Sjimharris} 639230557Sjimharris 640230557Sjimharris// --------------------------------------------------------------------------- 641230557Sjimharris 642230557Sjimharrisvoid * scic_stp_io_request_get_h2d_reg_address( 643230557Sjimharris SCI_IO_REQUEST_HANDLE_T scic_io_request 644230557Sjimharris) 645230557Sjimharris{ 646230557Sjimharris SCIC_SDS_REQUEST_T * this_request = (SCIC_SDS_REQUEST_T *)scic_io_request; 647230557Sjimharris 648230557Sjimharris return this_request->command_buffer; 649230557Sjimharris} 650230557Sjimharris 651230557Sjimharris// --------------------------------------------------------------------------- 652230557Sjimharris 653230557Sjimharrisvoid * scic_stp_io_request_get_d2h_reg_address( 654230557Sjimharris SCI_IO_REQUEST_HANDLE_T scic_io_request 655230557Sjimharris) 656230557Sjimharris{ 657230557Sjimharris SCIC_SDS_STP_REQUEST_T * this_request = (SCIC_SDS_STP_REQUEST_T *)scic_io_request; 658230557Sjimharris 659230557Sjimharris return &this_request->d2h_reg_fis; 660230557Sjimharris} 661230557Sjimharris 662230557Sjimharris/** 663230557Sjimharris * Get the next SGL element from the request. 664230557Sjimharris * - Check on which SGL element pair we are working 665230557Sjimharris * - if working on SLG pair element A 666230557Sjimharris * - advance to element B 667230557Sjimharris * - else 668230557Sjimharris * - check to see if there are more SGL element pairs 669230557Sjimharris * for this IO request 670230557Sjimharris * - if there are more SGL element pairs 671230557Sjimharris * - advance to the next pair and return element A 672230557Sjimharris * 673230557Sjimharris * @param[in] this_request 674230557Sjimharris * 675230557Sjimharris * @return SCU_SGL_ELEMENT_T* 676230557Sjimharris */ 677230557SjimharrisSCU_SGL_ELEMENT_T * scic_sds_stp_request_pio_get_next_sgl( 678230557Sjimharris SCIC_SDS_STP_REQUEST_T * this_request 679230557Sjimharris) 680230557Sjimharris{ 681230557Sjimharris SCU_SGL_ELEMENT_T * current_sgl; 682230557Sjimharris 683230557Sjimharris if (this_request->type.pio.request_current.sgl_set == SCU_SGL_ELEMENT_PAIR_A) 684230557Sjimharris { 685230557Sjimharris if ( 686230557Sjimharris (this_request->type.pio.request_current.sgl_pair->B.address_lower == 0) 687230557Sjimharris && (this_request->type.pio.request_current.sgl_pair->B.address_upper == 0) 688230557Sjimharris ) 689230557Sjimharris { 690230557Sjimharris current_sgl = NULL; 691230557Sjimharris } 692230557Sjimharris else 693230557Sjimharris { 694230557Sjimharris this_request->type.pio.request_current.sgl_set = SCU_SGL_ELEMENT_PAIR_B; 695230557Sjimharris current_sgl = &(this_request->type.pio.request_current.sgl_pair->B); 696230557Sjimharris } 697230557Sjimharris } 698230557Sjimharris else 699230557Sjimharris { 700230557Sjimharris if ( 701230557Sjimharris (this_request->type.pio.request_current.sgl_pair->next_pair_lower == 0) 702230557Sjimharris && (this_request->type.pio.request_current.sgl_pair->next_pair_upper == 0) 703230557Sjimharris ) 704230557Sjimharris { 705230557Sjimharris current_sgl = NULL; 706230557Sjimharris } 707230557Sjimharris else 708230557Sjimharris { 709230557Sjimharris this_request->type.pio.request_current.sgl_pair = 710230557Sjimharris scic_sds_request_get_sgl_element_pair( 711230557Sjimharris &(this_request->parent), 712230557Sjimharris ++this_request->type.pio.sgl_pair_index 713230557Sjimharris ); 714230557Sjimharris 715230557Sjimharris this_request->type.pio.request_current.sgl_set = SCU_SGL_ELEMENT_PAIR_A; 716230557Sjimharris 717230557Sjimharris current_sgl = &(this_request->type.pio.request_current.sgl_pair->A); 718230557Sjimharris } 719230557Sjimharris } 720230557Sjimharris 721230557Sjimharris return current_sgl; 722230557Sjimharris} 723230557Sjimharris 724230557Sjimharris/** 725230557Sjimharris * This method will construct the SATA PIO request. 726230557Sjimharris * 727230557Sjimharris * @param[in] scic_io_request The core request object which is cast to a SATA 728230557Sjimharris * PIO request object. 729230557Sjimharris * 730230557Sjimharris * @return This method returns an indication as to whether the construction 731230557Sjimharris * was successful. 732230557Sjimharris * @retval SCI_SUCCESS Currently this method always returns this value. 733230557Sjimharris */ 734230557SjimharrisSCI_STATUS scic_sds_stp_pio_request_construct( 735230557Sjimharris SCIC_SDS_REQUEST_T * scic_io_request, 736230557Sjimharris U8 sat_protocol, 737230557Sjimharris BOOL copy_rx_frame 738230557Sjimharris) 739230557Sjimharris{ 740230557Sjimharris SCIC_SDS_STP_REQUEST_T * this_request; 741230557Sjimharris 742230557Sjimharris this_request = (SCIC_SDS_STP_REQUEST_T *)scic_io_request; 743230557Sjimharris 744230557Sjimharris scic_sds_stp_non_ncq_request_construct(&this_request->parent); 745230557Sjimharris 746230557Sjimharris scu_stp_raw_request_construct_task_context( 747230557Sjimharris this_request, this_request->parent.task_context_buffer 748230557Sjimharris ); 749230557Sjimharris 750230557Sjimharris this_request->type.pio.current_transfer_bytes = 0; 751230557Sjimharris this_request->type.pio.ending_error = 0; 752230557Sjimharris this_request->type.pio.ending_status = 0; 753230557Sjimharris 754230557Sjimharris this_request->type.pio.request_current.sgl_offset = 0; 755230557Sjimharris this_request->type.pio.request_current.sgl_set = SCU_SGL_ELEMENT_PAIR_A; 756230557Sjimharris this_request->type.pio.sat_protocol = sat_protocol; 757230557Sjimharris this_request->type.pio.sgl_pair_index = 0; 758230557Sjimharris 759230557Sjimharris if ((copy_rx_frame) || (sat_protocol == SAT_PROTOCOL_PIO_DATA_OUT)) 760230557Sjimharris { 761230557Sjimharris scic_sds_request_build_sgl(&this_request->parent); 762230557Sjimharris // Since the IO request copy of the TC contains the same data as 763230557Sjimharris // the actual TC this pointer is vaild for either. 764230557Sjimharris this_request->type.pio.request_current.sgl_pair = 765230557Sjimharris &this_request->parent.task_context_buffer->sgl_pair_ab; 766230557Sjimharris } 767230557Sjimharris else 768230557Sjimharris { 769230557Sjimharris // The user does not want the data copied to the SGL buffer location 770230557Sjimharris this_request->type.pio.request_current.sgl_pair = NULL; 771230557Sjimharris } 772230557Sjimharris 773230557Sjimharris sci_base_state_machine_construct( 774230557Sjimharris &this_request->parent.started_substate_machine, 775230557Sjimharris &this_request->parent.parent.parent, 776230557Sjimharris scic_sds_stp_request_started_pio_substate_table, 777230557Sjimharris SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE 778230557Sjimharris ); 779230557Sjimharris 780230557Sjimharris return SCI_SUCCESS; 781230557Sjimharris} 782230557Sjimharris 783230557Sjimharris//****************************************************************************** 784230557Sjimharris//* STP NON-DATA STATE MACHINE 785230557Sjimharris//****************************************************************************** 786230557Sjimharris 787230557Sjimharris/** 788230557Sjimharris * This method processes a TC completion. The expected TC completion is 789230557Sjimharris * for the transmission of the H2D register FIS containing the SATA/STP 790230557Sjimharris * non-data request. 791230557Sjimharris * 792230557Sjimharris * @param[in] this_request 793230557Sjimharris * @param[in] completion_code 794230557Sjimharris * 795230557Sjimharris * @return This method always successfully processes the TC completion. 796230557Sjimharris * @retval SCI_SUCCESS This value is always returned. 797230557Sjimharris */ 798230557Sjimharrisstatic 799230557SjimharrisSCI_STATUS scic_sds_stp_request_non_data_await_h2d_tc_completion_handler( 800230557Sjimharris SCIC_SDS_REQUEST_T * this_request, 801230557Sjimharris U32 completion_code 802230557Sjimharris) 803230557Sjimharris{ 804230557Sjimharris SCIC_LOG_TRACE(( 805230557Sjimharris sci_base_object_get_logger(this_request), 806230557Sjimharris SCIC_LOG_OBJECT_STP_IO_REQUEST, 807230557Sjimharris "scic_sds_stp_request_non_data_await_h2d_tc_completion_handler(0x%x, 0x%x) enter\n", 808230557Sjimharris this_request, completion_code 809230557Sjimharris )); 810230557Sjimharris 811230557Sjimharris switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) 812230557Sjimharris { 813230557Sjimharris case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): 814230557Sjimharris scic_sds_request_set_status( 815230557Sjimharris this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS 816230557Sjimharris ); 817230557Sjimharris 818230557Sjimharris sci_base_state_machine_change_state( 819230557Sjimharris &this_request->started_substate_machine, 820230557Sjimharris SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE 821230557Sjimharris ); 822230557Sjimharris break; 823230557Sjimharris 824230557Sjimharris default: 825230557Sjimharris // All other completion status cause the IO to be complete. If a NAK 826230557Sjimharris // was received, then it is up to the user to retry the request. 827230557Sjimharris scic_sds_request_set_status( 828230557Sjimharris this_request, 829230557Sjimharris SCU_NORMALIZE_COMPLETION_STATUS(completion_code), 830230557Sjimharris SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR 831230557Sjimharris ); 832230557Sjimharris 833230557Sjimharris sci_base_state_machine_change_state( 834230557Sjimharris &this_request->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED 835230557Sjimharris ); 836230557Sjimharris break; 837230557Sjimharris } 838230557Sjimharris 839230557Sjimharris return SCI_SUCCESS; 840230557Sjimharris} 841230557Sjimharris 842230557Sjimharris/** 843230557Sjimharris * This method processes frames received from the target while waiting 844230557Sjimharris * for a device to host register FIS. If a non-register FIS is received 845230557Sjimharris * during this time, it is treated as a protocol violation from an 846230557Sjimharris * IO perspective. 847230557Sjimharris * 848230557Sjimharris * @param[in] request This parameter specifies the request for which a 849230557Sjimharris * frame has been received. 850230557Sjimharris * @param[in] frame_index This parameter specifies the index of the frame 851230557Sjimharris * that has been received. 852230557Sjimharris * 853230557Sjimharris * @return Indicate if the received frame was processed successfully. 854230557Sjimharris */ 855230557Sjimharrisstatic 856230557SjimharrisSCI_STATUS scic_sds_stp_request_non_data_await_d2h_frame_handler( 857230557Sjimharris SCIC_SDS_REQUEST_T * request, 858230557Sjimharris U32 frame_index 859230557Sjimharris) 860230557Sjimharris{ 861230557Sjimharris SCI_STATUS status; 862230557Sjimharris SATA_FIS_HEADER_T * frame_header; 863230557Sjimharris U32 * frame_buffer; 864230557Sjimharris SCIC_SDS_STP_REQUEST_T * this_request = (SCIC_SDS_STP_REQUEST_T *)request; 865230557Sjimharris 866230557Sjimharris // Save off the controller, so that we do not touch the request after it 867230557Sjimharris // is completed. 868230557Sjimharris SCIC_SDS_CONTROLLER_T * owning_controller = this_request->parent.owning_controller; 869230557Sjimharris 870230557Sjimharris SCIC_LOG_TRACE(( 871230557Sjimharris sci_base_object_get_logger(this_request), 872230557Sjimharris SCIC_LOG_OBJECT_STP_IO_REQUEST, 873230557Sjimharris "scic_sds_stp_request_non_data_await_d2h_frame_handler(0x%x, 0x%x) enter\n", 874230557Sjimharris this_request, frame_index 875230557Sjimharris )); 876230557Sjimharris 877230557Sjimharris status = scic_sds_unsolicited_frame_control_get_header( 878230557Sjimharris &(owning_controller->uf_control), 879230557Sjimharris frame_index, 880230557Sjimharris (void**) &frame_header 881230557Sjimharris ); 882230557Sjimharris 883230557Sjimharris if (status == SCI_SUCCESS) 884230557Sjimharris { 885230557Sjimharris switch (frame_header->fis_type) 886230557Sjimharris { 887230557Sjimharris case SATA_FIS_TYPE_REGD2H: 888230557Sjimharris scic_sds_unsolicited_frame_control_get_buffer( 889230557Sjimharris &(owning_controller->uf_control), 890230557Sjimharris frame_index, 891230557Sjimharris (void**) &frame_buffer 892230557Sjimharris ); 893230557Sjimharris 894230557Sjimharris scic_sds_controller_copy_sata_response( 895230557Sjimharris &this_request->d2h_reg_fis, (U32 *)frame_header, frame_buffer 896230557Sjimharris ); 897230557Sjimharris 898230557Sjimharris // The command has completed with error 899230557Sjimharris scic_sds_request_set_status( 900230557Sjimharris &this_request->parent, 901230557Sjimharris SCU_TASK_DONE_CHECK_RESPONSE, 902230557Sjimharris SCI_FAILURE_IO_RESPONSE_VALID 903230557Sjimharris ); 904230557Sjimharris break; 905230557Sjimharris 906230557Sjimharris default: 907230557Sjimharris SCIC_LOG_WARNING(( 908230557Sjimharris sci_base_object_get_logger(this_request), 909230557Sjimharris SCIC_LOG_OBJECT_STP_IO_REQUEST, 910230557Sjimharris "IO Request:0x%x Frame Id:%d protocol violation occurred\n", 911230557Sjimharris this_request, frame_index 912230557Sjimharris )); 913230557Sjimharris 914230557Sjimharris scic_sds_request_set_status( 915230557Sjimharris &this_request->parent, 916230557Sjimharris SCU_TASK_DONE_UNEXP_FIS, 917230557Sjimharris SCI_FAILURE_PROTOCOL_VIOLATION 918230557Sjimharris ); 919230557Sjimharris break; 920230557Sjimharris } 921230557Sjimharris 922230557Sjimharris sci_base_state_machine_change_state( 923230557Sjimharris &this_request->parent.parent.state_machine, 924230557Sjimharris SCI_BASE_REQUEST_STATE_COMPLETED 925230557Sjimharris ); 926230557Sjimharris 927230557Sjimharris // Frame has been decoded return it to the controller 928230557Sjimharris scic_sds_controller_release_frame( 929230557Sjimharris owning_controller, frame_index 930230557Sjimharris ); 931230557Sjimharris } 932230557Sjimharris else 933230557Sjimharris { 934230557Sjimharris SCIC_LOG_ERROR(( 935230557Sjimharris sci_base_object_get_logger(this_request), 936230557Sjimharris SCIC_LOG_OBJECT_STP_IO_REQUEST, 937230557Sjimharris "SCIC IO Request 0x%x could not get frame header for frame index %d, status %x\n", 938230557Sjimharris this_request, frame_index, status 939230557Sjimharris )); 940230557Sjimharris } 941230557Sjimharris 942230557Sjimharris return status; 943230557Sjimharris} 944230557Sjimharris 945230557Sjimharris// --------------------------------------------------------------------------- 946230557Sjimharris 947230557SjimharrisSCIC_SDS_IO_REQUEST_STATE_HANDLER_T 948230557Sjimharris scic_sds_stp_request_started_non_data_substate_handler_table 949230557Sjimharris [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_MAX_SUBSTATES] = 950230557Sjimharris{ 951230557Sjimharris // SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE 952230557Sjimharris { 953230557Sjimharris { 954230557Sjimharris scic_sds_request_default_start_handler, 955230557Sjimharris scic_sds_request_started_state_abort_handler, 956230557Sjimharris scic_sds_request_default_complete_handler, 957230557Sjimharris scic_sds_request_default_destruct_handler 958230557Sjimharris }, 959230557Sjimharris scic_sds_stp_request_non_data_await_h2d_tc_completion_handler, 960230557Sjimharris scic_sds_request_default_event_handler, 961230557Sjimharris scic_sds_request_default_frame_handler 962230557Sjimharris }, 963230557Sjimharris // SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE 964230557Sjimharris { 965230557Sjimharris { 966230557Sjimharris scic_sds_request_default_start_handler, 967230557Sjimharris scic_sds_request_started_state_abort_handler, 968230557Sjimharris scic_sds_request_default_complete_handler, 969230557Sjimharris scic_sds_request_default_destruct_handler 970230557Sjimharris }, 971230557Sjimharris scic_sds_request_default_tc_completion_handler, 972230557Sjimharris scic_sds_request_default_event_handler, 973230557Sjimharris scic_sds_stp_request_non_data_await_d2h_frame_handler 974230557Sjimharris } 975230557Sjimharris}; 976230557Sjimharris 977230557Sjimharrisstatic 978230557Sjimharrisvoid scic_sds_stp_request_started_non_data_await_h2d_completion_enter( 979230557Sjimharris SCI_BASE_OBJECT_T *object 980230557Sjimharris) 981230557Sjimharris{ 982230557Sjimharris SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object; 983230557Sjimharris 984230557Sjimharris SET_STATE_HANDLER( 985230557Sjimharris this_request, 986230557Sjimharris scic_sds_stp_request_started_non_data_substate_handler_table, 987230557Sjimharris SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE 988230557Sjimharris ); 989230557Sjimharris 990230557Sjimharris scic_sds_remote_device_set_working_request( 991230557Sjimharris this_request->target_device, this_request 992230557Sjimharris ); 993230557Sjimharris} 994230557Sjimharris 995230557Sjimharrisstatic 996230557Sjimharrisvoid scic_sds_stp_request_started_non_data_await_d2h_enter( 997230557Sjimharris SCI_BASE_OBJECT_T *object 998230557Sjimharris) 999230557Sjimharris{ 1000230557Sjimharris SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object; 1001230557Sjimharris 1002230557Sjimharris SET_STATE_HANDLER( 1003230557Sjimharris this_request, 1004230557Sjimharris scic_sds_stp_request_started_non_data_substate_handler_table, 1005230557Sjimharris SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE 1006230557Sjimharris ); 1007230557Sjimharris} 1008230557Sjimharris 1009230557Sjimharris// --------------------------------------------------------------------------- 1010230557Sjimharris 1011230557SjimharrisSCI_BASE_STATE_T scic_sds_stp_request_started_non_data_substate_table 1012230557Sjimharris[SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_MAX_SUBSTATES] = 1013230557Sjimharris{ 1014230557Sjimharris { 1015230557Sjimharris SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE, 1016230557Sjimharris scic_sds_stp_request_started_non_data_await_h2d_completion_enter, 1017230557Sjimharris NULL 1018230557Sjimharris }, 1019230557Sjimharris { 1020230557Sjimharris SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE, 1021230557Sjimharris scic_sds_stp_request_started_non_data_await_d2h_enter, 1022230557Sjimharris NULL 1023230557Sjimharris } 1024230557Sjimharris}; 1025230557Sjimharris 1026230557Sjimharris//****************************************************************************** 1027230557Sjimharris//* STP PIO STATE MACHINE 1028230557Sjimharris//****************************************************************************** 1029230557Sjimharris 1030230557Sjimharris#define SCU_MAX_FRAME_BUFFER_SIZE 0x400 // 1K is the maximum SCU frame data payload 1031230557Sjimharris 1032230557Sjimharris/** 1033230557Sjimharris * This function will transmit DATA_FIS from (current sgl + offset) for input parameter length. 1034230557Sjimharris * current sgl and offset is alreay stored in the IO request 1035230557Sjimharris * 1036230557Sjimharris * @param[in] this_request 1037230557Sjimharris * @param[in] length 1038230557Sjimharris * 1039230557Sjimharris * @return SCI_STATUS 1040230557Sjimharris */ 1041230557Sjimharrisstatic 1042230557SjimharrisSCI_STATUS scic_sds_stp_request_pio_data_out_trasmit_data_frame ( 1043230557Sjimharris SCIC_SDS_REQUEST_T * this_request, 1044230557Sjimharris U32 length 1045230557Sjimharris) 1046230557Sjimharris{ 1047230557Sjimharris SCI_STATUS status = SCI_SUCCESS; 1048230557Sjimharris SCU_SGL_ELEMENT_T * current_sgl; 1049230557Sjimharris SCIC_SDS_STP_REQUEST_T * this_sds_stp_request = (SCIC_SDS_STP_REQUEST_T *)this_request; 1050230557Sjimharris 1051230557Sjimharris // Recycle the TC and reconstruct it for sending out DATA FIS containing 1052230557Sjimharris // for the data from current_sgl+offset for the input length 1053230557Sjimharris SCU_TASK_CONTEXT_T * task_context = scic_sds_controller_get_task_context_buffer( 1054230557Sjimharris this_request->owning_controller, 1055230557Sjimharris this_request->io_tag 1056230557Sjimharris ); 1057230557Sjimharris 1058230557Sjimharris if (this_sds_stp_request->type.pio.request_current.sgl_set == SCU_SGL_ELEMENT_PAIR_A) 1059230557Sjimharris { 1060230557Sjimharris current_sgl = &(this_sds_stp_request->type.pio.request_current.sgl_pair->A); 1061230557Sjimharris } 1062230557Sjimharris else 1063230557Sjimharris { 1064230557Sjimharris current_sgl = &(this_sds_stp_request->type.pio.request_current.sgl_pair->B); 1065230557Sjimharris } 1066230557Sjimharris 1067230557Sjimharris //update the TC 1068230557Sjimharris task_context->command_iu_upper = current_sgl->address_upper; 1069230557Sjimharris task_context->command_iu_lower = current_sgl->address_lower; 1070230557Sjimharris task_context->transfer_length_bytes = length; 1071230557Sjimharris task_context->type.stp.fis_type = SATA_FIS_TYPE_DATA; 1072230557Sjimharris 1073230557Sjimharris // send the new TC out. 1074230557Sjimharris status = this_request->owning_controller->state_handlers->parent.continue_io_handler( 1075230557Sjimharris &this_request->owning_controller->parent, 1076230557Sjimharris &this_request->target_device->parent, 1077230557Sjimharris &this_request->parent 1078230557Sjimharris ); 1079230557Sjimharris 1080230557Sjimharris return status; 1081230557Sjimharris 1082230557Sjimharris} 1083230557Sjimharris 1084230557Sjimharris/** 1085230557Sjimharris * 1086230557Sjimharris * 1087230557Sjimharris * @param[in] this_request 1088230557Sjimharris * 1089230557Sjimharris * @return SCI_STATUS 1090230557Sjimharris */ 1091230557Sjimharrisstatic 1092230557SjimharrisSCI_STATUS scic_sds_stp_request_pio_data_out_transmit_data( 1093230557Sjimharris SCIC_SDS_REQUEST_T * this_sds_request 1094230557Sjimharris) 1095230557Sjimharris{ 1096230557Sjimharris 1097230557Sjimharris SCU_SGL_ELEMENT_T * current_sgl; 1098230557Sjimharris U32 sgl_offset; 1099230557Sjimharris U32 remaining_bytes_in_current_sgl = 0; 1100230557Sjimharris SCI_STATUS status = SCI_SUCCESS; 1101230557Sjimharris 1102230557Sjimharris SCIC_SDS_STP_REQUEST_T * this_sds_stp_request = (SCIC_SDS_STP_REQUEST_T *)this_sds_request; 1103230557Sjimharris 1104230557Sjimharris sgl_offset = this_sds_stp_request->type.pio.request_current.sgl_offset; 1105230557Sjimharris 1106230557Sjimharris if (this_sds_stp_request->type.pio.request_current.sgl_set == SCU_SGL_ELEMENT_PAIR_A) 1107230557Sjimharris { 1108230557Sjimharris current_sgl = &(this_sds_stp_request->type.pio.request_current.sgl_pair->A); 1109230557Sjimharris remaining_bytes_in_current_sgl = this_sds_stp_request->type.pio.request_current.sgl_pair->A.length - sgl_offset; 1110230557Sjimharris } 1111230557Sjimharris else 1112230557Sjimharris { 1113230557Sjimharris current_sgl = &(this_sds_stp_request->type.pio.request_current.sgl_pair->B); 1114230557Sjimharris remaining_bytes_in_current_sgl = this_sds_stp_request->type.pio.request_current.sgl_pair->B.length - sgl_offset; 1115230557Sjimharris } 1116230557Sjimharris 1117230557Sjimharris 1118230557Sjimharris if (this_sds_stp_request->type.pio.pio_transfer_bytes > 0) 1119230557Sjimharris { 1120230557Sjimharris if (this_sds_stp_request->type.pio.pio_transfer_bytes >= remaining_bytes_in_current_sgl ) 1121230557Sjimharris { 1122230557Sjimharris //recycle the TC and send the H2D Data FIS from (current sgl + sgl_offset) and length = remaining_bytes_in_current_sgl 1123230557Sjimharris status = scic_sds_stp_request_pio_data_out_trasmit_data_frame (this_sds_request, remaining_bytes_in_current_sgl); 1124230557Sjimharris if (status == SCI_SUCCESS) 1125230557Sjimharris { 1126230557Sjimharris this_sds_stp_request->type.pio.pio_transfer_bytes -= remaining_bytes_in_current_sgl; 1127230557Sjimharris sgl_offset = 0; 1128230557Sjimharris } 1129230557Sjimharris } 1130230557Sjimharris else if (this_sds_stp_request->type.pio.pio_transfer_bytes < remaining_bytes_in_current_sgl ) 1131230557Sjimharris { 1132230557Sjimharris //recycle the TC and send the H2D Data FIS from (current sgl + sgl_offset) and length = type.pio.pio_transfer_bytes 1133230557Sjimharris scic_sds_stp_request_pio_data_out_trasmit_data_frame (this_sds_request, this_sds_stp_request->type.pio.pio_transfer_bytes); 1134230557Sjimharris 1135230557Sjimharris if (status == SCI_SUCCESS) 1136230557Sjimharris { 1137230557Sjimharris //Sgl offset will be adjusted and saved for future 1138230557Sjimharris sgl_offset += this_sds_stp_request->type.pio.pio_transfer_bytes; 1139230557Sjimharris current_sgl->address_lower += this_sds_stp_request->type.pio.pio_transfer_bytes; 1140230557Sjimharris this_sds_stp_request->type.pio.pio_transfer_bytes = 0; 1141230557Sjimharris } 1142230557Sjimharris } 1143230557Sjimharris } 1144230557Sjimharris 1145230557Sjimharris if (status == SCI_SUCCESS) 1146230557Sjimharris { 1147230557Sjimharris this_sds_stp_request->type.pio.request_current.sgl_offset = sgl_offset; 1148230557Sjimharris } 1149230557Sjimharris 1150230557Sjimharris return status; 1151230557Sjimharris} 1152230557Sjimharris 1153230557Sjimharris/** 1154230557Sjimharris * Copy the data from the buffer for the length specified to the IO reqeust 1155230557Sjimharris * SGL specified data region. 1156230557Sjimharris * 1157230557Sjimharris * @param[in] this_request The request that is used for the SGL processing. 1158230557Sjimharris * @param[in] data_buffer The buffer of data to be copied. 1159230557Sjimharris * @param[in] length The length of the data transfer. 1160230557Sjimharris * 1161230557Sjimharris * @return SCI_STATUS 1162230557Sjimharris */ 1163230557Sjimharrisstatic 1164230557SjimharrisSCI_STATUS scic_sds_stp_request_pio_data_in_copy_data_buffer( 1165230557Sjimharris SCIC_SDS_STP_REQUEST_T * this_request, 1166230557Sjimharris U8 * data_buffer, 1167230557Sjimharris U32 length 1168230557Sjimharris) 1169230557Sjimharris{ 1170230557Sjimharris SCI_STATUS status; 1171230557Sjimharris SCU_SGL_ELEMENT_T * current_sgl; 1172230557Sjimharris U32 sgl_offset; 1173230557Sjimharris U32 data_offset; 1174230557Sjimharris U8 * source_address; 1175230557Sjimharris 1176230557Sjimharris // Initial setup to get the current working SGL and the offset within the buffer 1177230557Sjimharris current_sgl = 1178230557Sjimharris (this_request->type.pio.request_current.sgl_set == SCU_SGL_ELEMENT_PAIR_A) ? 1179230557Sjimharris &(this_request->type.pio.request_current.sgl_pair->A) : 1180230557Sjimharris &(this_request->type.pio.request_current.sgl_pair->B) ; 1181230557Sjimharris 1182230557Sjimharris sgl_offset = this_request->type.pio.request_current.sgl_offset; 1183230557Sjimharris 1184230557Sjimharris source_address = data_buffer; 1185230557Sjimharris data_offset = this_request->type.pio.current_transfer_bytes; 1186230557Sjimharris status = SCI_SUCCESS; 1187230557Sjimharris 1188230557Sjimharris // While we are still doing Ok and there is more data to transfer 1189230557Sjimharris while ( 1190230557Sjimharris (length > 0) 1191230557Sjimharris && (status == SCI_SUCCESS) 1192230557Sjimharris ) 1193230557Sjimharris { 1194230557Sjimharris if (current_sgl->length == sgl_offset) 1195230557Sjimharris { 1196230557Sjimharris // This SGL has been exauhasted so we need to get the next SGL 1197230557Sjimharris current_sgl = scic_sds_stp_request_pio_get_next_sgl(this_request); 1198230557Sjimharris 1199230557Sjimharris if (current_sgl == NULL) 1200230557Sjimharris status = SCI_FAILURE; 1201230557Sjimharris else 1202230557Sjimharris sgl_offset = 0; 1203230557Sjimharris } 1204230557Sjimharris else 1205230557Sjimharris { 1206230557Sjimharris#ifdef ENABLE_OSSL_COPY_BUFFER 1207230557Sjimharris scic_cb_io_request_copy_buffer(this_request, data_buffer, data_offset, length); 1208230557Sjimharris length = 0; 1209230557Sjimharris#else 1210230557Sjimharris U8 * destination_address; 1211230557Sjimharris U32 copy_length; 1212230557Sjimharris 1213230557Sjimharris destination_address = (U8 *)scic_cb_io_request_get_virtual_address_from_sgl( 1214230557Sjimharris this_request, 1215230557Sjimharris data_offset 1216230557Sjimharris ); 1217230557Sjimharris 1218230557Sjimharris copy_length = MIN(length, current_sgl->length - sgl_offset); 1219230557Sjimharris 1220230557Sjimharris memcpy(destination_address, source_address, copy_length); 1221230557Sjimharris 1222230557Sjimharris length -= copy_length; 1223230557Sjimharris sgl_offset += copy_length; 1224230557Sjimharris data_offset += copy_length; 1225268073Sscottl source_address += copy_length; 1226230557Sjimharris#endif 1227230557Sjimharris } 1228230557Sjimharris } 1229230557Sjimharris 1230230557Sjimharris this_request->type.pio.request_current.sgl_offset = sgl_offset; 1231230557Sjimharris 1232230557Sjimharris return status; 1233230557Sjimharris} 1234230557Sjimharris 1235230557Sjimharris/** 1236230557Sjimharris * Copy the data buffer to the io request data region. 1237230557Sjimharris * 1238230557Sjimharris * @param[in] this_request The PIO DATA IN request that is to receive the 1239230557Sjimharris * data. 1240230557Sjimharris * @param[in] data_buffer The buffer to copy from. 1241230557Sjimharris * 1242230557Sjimharris * @return SCI_STATUS 1243230557Sjimharris */ 1244230557Sjimharrisstatic 1245230557SjimharrisSCI_STATUS scic_sds_stp_request_pio_data_in_copy_data( 1246230557Sjimharris SCIC_SDS_STP_REQUEST_T * this_request, 1247230557Sjimharris U8 * data_buffer 1248230557Sjimharris) 1249230557Sjimharris{ 1250230557Sjimharris SCI_STATUS status; 1251230557Sjimharris 1252230557Sjimharris // If there is less than 1K remaining in the transfer request 1253230557Sjimharris // copy just the data for the transfer 1254230557Sjimharris if (this_request->type.pio.pio_transfer_bytes < SCU_MAX_FRAME_BUFFER_SIZE) 1255230557Sjimharris { 1256230557Sjimharris status = scic_sds_stp_request_pio_data_in_copy_data_buffer( 1257230557Sjimharris this_request,data_buffer,this_request->type.pio.pio_transfer_bytes); 1258230557Sjimharris 1259230557Sjimharris if (status == SCI_SUCCESS) 1260230557Sjimharris { 1261230557Sjimharris // All data for this PIO request has now been copied, so we don't 1262230557Sjimharris // technically need to update current_transfer_bytes here - just 1263230557Sjimharris // doing it for completeness. 1264230557Sjimharris this_request->type.pio.current_transfer_bytes += this_request->type.pio.pio_transfer_bytes; 1265230557Sjimharris this_request->type.pio.pio_transfer_bytes = 0; 1266230557Sjimharris } 1267230557Sjimharris } 1268230557Sjimharris else 1269230557Sjimharris { 1270230557Sjimharris // We are transfering the whole frame so copy 1271230557Sjimharris status = scic_sds_stp_request_pio_data_in_copy_data_buffer( 1272230557Sjimharris this_request, data_buffer, SCU_MAX_FRAME_BUFFER_SIZE); 1273230557Sjimharris 1274230557Sjimharris if (status == SCI_SUCCESS) 1275230557Sjimharris { 1276230557Sjimharris this_request->type.pio.pio_transfer_bytes -= SCU_MAX_FRAME_BUFFER_SIZE; 1277230557Sjimharris this_request->type.pio.current_transfer_bytes += SCU_MAX_FRAME_BUFFER_SIZE; 1278230557Sjimharris } 1279230557Sjimharris } 1280230557Sjimharris 1281230557Sjimharris return status; 1282230557Sjimharris} 1283230557Sjimharris 1284230557Sjimharris/** 1285230557Sjimharris * 1286230557Sjimharris * 1287230557Sjimharris * @param[in] this_request 1288230557Sjimharris * @param[in] completion_code 1289230557Sjimharris * 1290230557Sjimharris * @return SCI_STATUS 1291230557Sjimharris */ 1292230557Sjimharrisstatic 1293230557SjimharrisSCI_STATUS scic_sds_stp_request_pio_await_h2d_completion_tc_completion_handler( 1294230557Sjimharris SCIC_SDS_REQUEST_T * this_request, 1295230557Sjimharris U32 completion_code 1296230557Sjimharris) 1297230557Sjimharris{ 1298230557Sjimharris SCI_STATUS status = SCI_SUCCESS; 1299230557Sjimharris 1300230557Sjimharris SCIC_LOG_TRACE(( 1301230557Sjimharris sci_base_object_get_logger(this_request), 1302230557Sjimharris SCIC_LOG_OBJECT_STP_IO_REQUEST, 1303230557Sjimharris "scic_sds_stp_request_pio_data_in_await_h2d_completion_tc_completion_handler(0x%x, 0x%x) enter\n", 1304230557Sjimharris this_request, completion_code 1305230557Sjimharris )); 1306230557Sjimharris 1307230557Sjimharris switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) 1308230557Sjimharris { 1309230557Sjimharris case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): 1310230557Sjimharris scic_sds_request_set_status( 1311230557Sjimharris this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS 1312230557Sjimharris ); 1313230557Sjimharris 1314230557Sjimharris sci_base_state_machine_change_state( 1315230557Sjimharris &this_request->started_substate_machine, 1316230557Sjimharris SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE 1317230557Sjimharris ); 1318230557Sjimharris break; 1319230557Sjimharris 1320230557Sjimharris default: 1321230557Sjimharris // All other completion status cause the IO to be complete. If a NAK 1322230557Sjimharris // was received, then it is up to the user to retry the request. 1323230557Sjimharris scic_sds_request_set_status( 1324230557Sjimharris this_request, 1325230557Sjimharris SCU_NORMALIZE_COMPLETION_STATUS(completion_code), 1326230557Sjimharris SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR 1327230557Sjimharris ); 1328230557Sjimharris 1329230557Sjimharris sci_base_state_machine_change_state( 1330230557Sjimharris &this_request->parent.state_machine, 1331230557Sjimharris SCI_BASE_REQUEST_STATE_COMPLETED 1332230557Sjimharris ); 1333230557Sjimharris break; 1334230557Sjimharris } 1335230557Sjimharris 1336230557Sjimharris return status; 1337230557Sjimharris} 1338230557Sjimharris 1339230557Sjimharris/** 1340230557Sjimharris * 1341230557Sjimharris * 1342230557Sjimharris * @param[in] this_request 1343230557Sjimharris * @param[in] frame_index 1344230557Sjimharris * 1345230557Sjimharris * @return SCI_STATUS 1346230557Sjimharris */ 1347230557Sjimharrisstatic 1348230557SjimharrisSCI_STATUS scic_sds_stp_request_pio_await_frame_frame_handler( 1349230557Sjimharris SCIC_SDS_REQUEST_T * request, 1350230557Sjimharris U32 frame_index 1351230557Sjimharris) 1352230557Sjimharris{ 1353230557Sjimharris SCI_STATUS status; 1354230557Sjimharris SATA_FIS_HEADER_T * frame_header; 1355230557Sjimharris U32 * frame_buffer; 1356230557Sjimharris SCIC_SDS_STP_REQUEST_T * this_request; 1357230557Sjimharris SCIC_SDS_CONTROLLER_T * owning_controller; 1358230557Sjimharris 1359230557Sjimharris this_request = (SCIC_SDS_STP_REQUEST_T *)request; 1360230557Sjimharris 1361230557Sjimharris // Save off the controller, so that we do not touch the request after it 1362230557Sjimharris // is completed. 1363230557Sjimharris owning_controller = this_request->parent.owning_controller; 1364230557Sjimharris 1365230557Sjimharris SCIC_LOG_TRACE(( 1366230557Sjimharris sci_base_object_get_logger(this_request), 1367230557Sjimharris SCIC_LOG_OBJECT_STP_IO_REQUEST, 1368230557Sjimharris "scic_sds_stp_request_pio_data_in_await_frame_frame_handler(0x%x, 0x%x) enter\n", 1369230557Sjimharris this_request, frame_index 1370230557Sjimharris )); 1371230557Sjimharris 1372230557Sjimharris status = scic_sds_unsolicited_frame_control_get_header( 1373230557Sjimharris &(owning_controller->uf_control), 1374230557Sjimharris frame_index, 1375230557Sjimharris (void**) &frame_header 1376230557Sjimharris ); 1377230557Sjimharris 1378230557Sjimharris if (status == SCI_SUCCESS) 1379230557Sjimharris { 1380230557Sjimharris switch (frame_header->fis_type) 1381230557Sjimharris { 1382230557Sjimharris case SATA_FIS_TYPE_PIO_SETUP: 1383230557Sjimharris // Get from the frame buffer the PIO Setup Data 1384230557Sjimharris scic_sds_unsolicited_frame_control_get_buffer( 1385230557Sjimharris &(owning_controller->uf_control), 1386230557Sjimharris frame_index, 1387230557Sjimharris (void**) &frame_buffer 1388230557Sjimharris ); 1389230557Sjimharris 1390230557Sjimharris // Get the data from the PIO Setup 1391230557Sjimharris // The SCU Hardware returns first word in the frame_header and the rest 1392230557Sjimharris // of the data is in the frame buffer so we need to back up one dword 1393230557Sjimharris this_request->type.pio.pio_transfer_bytes = 1394230557Sjimharris (U16)((SATA_FIS_PIO_SETUP_T *)(&frame_buffer[-1]))->transfter_count; 1395230557Sjimharris this_request->type.pio.ending_status = 1396230557Sjimharris (U8)((SATA_FIS_PIO_SETUP_T *)(&frame_buffer[-1]))->ending_status; 1397230557Sjimharris 1398230557Sjimharris scic_sds_controller_copy_sata_response( 1399230557Sjimharris &this_request->d2h_reg_fis, (U32 *)frame_header, frame_buffer 1400230557Sjimharris ); 1401230557Sjimharris 1402230557Sjimharris this_request->d2h_reg_fis.status = 1403230557Sjimharris this_request->type.pio.ending_status; 1404230557Sjimharris 1405230557Sjimharris //The next state is dependent on whether the request was PIO Data-in or Data out 1406230557Sjimharris if (this_request->type.pio.sat_protocol == SAT_PROTOCOL_PIO_DATA_IN) 1407230557Sjimharris { 1408230557Sjimharris sci_base_state_machine_change_state( 1409230557Sjimharris &this_request->parent.started_substate_machine, 1410230557Sjimharris SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE 1411230557Sjimharris ); 1412230557Sjimharris } 1413230557Sjimharris else if (this_request->type.pio.sat_protocol == SAT_PROTOCOL_PIO_DATA_OUT) 1414230557Sjimharris { 1415230557Sjimharris //Transmit data 1416230557Sjimharris status = scic_sds_stp_request_pio_data_out_transmit_data ( request); 1417230557Sjimharris if (status == SCI_SUCCESS) 1418230557Sjimharris { 1419230557Sjimharris sci_base_state_machine_change_state( 1420230557Sjimharris &this_request->parent.started_substate_machine, 1421230557Sjimharris SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE 1422230557Sjimharris ); 1423230557Sjimharris } 1424230557Sjimharris } 1425230557Sjimharris break; 1426230557Sjimharris 1427230557Sjimharris case SATA_FIS_TYPE_SETDEVBITS: 1428230557Sjimharris sci_base_state_machine_change_state( 1429230557Sjimharris &this_request->parent.started_substate_machine, 1430230557Sjimharris SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE 1431230557Sjimharris ); 1432230557Sjimharris break; 1433230557Sjimharris 1434230557Sjimharris case SATA_FIS_TYPE_REGD2H: 1435230557Sjimharris if ( (frame_header->status & ATA_STATUS_REG_BSY_BIT) == 0) 1436230557Sjimharris { 1437230557Sjimharris scic_sds_unsolicited_frame_control_get_buffer( 1438230557Sjimharris &(owning_controller->uf_control), 1439230557Sjimharris frame_index, 1440230557Sjimharris (void**) &frame_buffer 1441230557Sjimharris ); 1442230557Sjimharris 1443230557Sjimharris scic_sds_controller_copy_sata_response( 1444230557Sjimharris &this_request->d2h_reg_fis, (U32 *)frame_header, frame_buffer); 1445230557Sjimharris 1446230557Sjimharris scic_sds_request_set_status( 1447230557Sjimharris &this_request->parent, 1448230557Sjimharris SCU_TASK_DONE_CHECK_RESPONSE, 1449230557Sjimharris SCI_FAILURE_IO_RESPONSE_VALID 1450230557Sjimharris ); 1451230557Sjimharris 1452230557Sjimharris sci_base_state_machine_change_state( 1453230557Sjimharris &this_request->parent.parent.state_machine, 1454230557Sjimharris SCI_BASE_REQUEST_STATE_COMPLETED 1455230557Sjimharris ); 1456230557Sjimharris } 1457230557Sjimharris else 1458230557Sjimharris { 1459230557Sjimharris // Now why is the drive sending a D2H Register FIS when it is still busy? 1460230557Sjimharris // Do nothing since we are still in the right state. 1461230557Sjimharris SCIC_LOG_INFO(( 1462230557Sjimharris sci_base_object_get_logger(this_request), 1463230557Sjimharris SCIC_LOG_OBJECT_STP_IO_REQUEST, 1464230557Sjimharris "SCIC PIO Request 0x%x received D2H Register FIS with BSY status 0x%x\n", 1465230557Sjimharris this_request, frame_header->status 1466230557Sjimharris )); 1467230557Sjimharris } 1468230557Sjimharris break; 1469230557Sjimharris 1470230557Sjimharris default: 1471230557Sjimharris break; 1472230557Sjimharris } 1473230557Sjimharris 1474230557Sjimharris // Frame is decoded return it to the controller 1475230557Sjimharris scic_sds_controller_release_frame( 1476230557Sjimharris owning_controller, 1477230557Sjimharris frame_index 1478230557Sjimharris ); 1479230557Sjimharris } 1480230557Sjimharris else 1481230557Sjimharris { 1482230557Sjimharris SCIC_LOG_ERROR(( 1483230557Sjimharris sci_base_object_get_logger(this_request), 1484230557Sjimharris SCIC_LOG_OBJECT_STP_IO_REQUEST, 1485230557Sjimharris "SCIC IO Request 0x%x could not get frame header for frame index %d, status %x\n", 1486230557Sjimharris this_request, frame_index, status 1487230557Sjimharris )); 1488230557Sjimharris } 1489230557Sjimharris 1490230557Sjimharris return status; 1491230557Sjimharris} 1492230557Sjimharris 1493230557Sjimharris/** 1494230557Sjimharris * 1495230557Sjimharris * 1496230557Sjimharris * @param[in] this_request 1497230557Sjimharris * @param[in] frame_index 1498230557Sjimharris * 1499230557Sjimharris * @return SCI_STATUS 1500230557Sjimharris */ 1501230557Sjimharrisstatic 1502230557SjimharrisSCI_STATUS scic_sds_stp_request_pio_data_in_await_data_frame_handler( 1503230557Sjimharris SCIC_SDS_REQUEST_T * request, 1504230557Sjimharris U32 frame_index 1505230557Sjimharris) 1506230557Sjimharris{ 1507230557Sjimharris SCI_STATUS status; 1508230557Sjimharris SATA_FIS_HEADER_T * frame_header; 1509230557Sjimharris SATA_FIS_DATA_T * frame_buffer; 1510230557Sjimharris SCIC_SDS_STP_REQUEST_T * this_request; 1511230557Sjimharris SCIC_SDS_CONTROLLER_T * owning_controller; 1512230557Sjimharris 1513230557Sjimharris this_request = (SCIC_SDS_STP_REQUEST_T *)request; 1514230557Sjimharris 1515230557Sjimharris // Save off the controller, so that we do not touch the request after it 1516230557Sjimharris // is completed. 1517230557Sjimharris owning_controller = this_request->parent.owning_controller; 1518230557Sjimharris 1519230557Sjimharris SCIC_LOG_TRACE(( 1520230557Sjimharris sci_base_object_get_logger(this_request), 1521230557Sjimharris SCIC_LOG_OBJECT_STP_IO_REQUEST, 1522230557Sjimharris "scic_sds_stp_request_pio_data_in_await_data_frame_handler(0x%x, 0x%x) enter\n", 1523230557Sjimharris this_request, frame_index 1524230557Sjimharris )); 1525230557Sjimharris 1526230557Sjimharris status = scic_sds_unsolicited_frame_control_get_header( 1527230557Sjimharris &(owning_controller->uf_control), 1528230557Sjimharris frame_index, 1529230557Sjimharris (void**) &frame_header 1530230557Sjimharris ); 1531230557Sjimharris 1532230557Sjimharris if (status == SCI_SUCCESS) 1533230557Sjimharris { 1534230557Sjimharris if (frame_header->fis_type == SATA_FIS_TYPE_DATA) 1535230557Sjimharris { 1536230557Sjimharris if (this_request->type.pio.request_current.sgl_pair == NULL) 1537230557Sjimharris { 1538230557Sjimharris this_request->parent.saved_rx_frame_index = frame_index; 1539230557Sjimharris this_request->type.pio.pio_transfer_bytes = 0; 1540230557Sjimharris } 1541230557Sjimharris else 1542230557Sjimharris { 1543230557Sjimharris status = scic_sds_unsolicited_frame_control_get_buffer( 1544230557Sjimharris &(owning_controller->uf_control), 1545230557Sjimharris frame_index, 1546230557Sjimharris (void**) &frame_buffer 1547230557Sjimharris ); 1548230557Sjimharris 1549230557Sjimharris status = scic_sds_stp_request_pio_data_in_copy_data(this_request, (U8 *)frame_buffer); 1550230557Sjimharris 1551230557Sjimharris // Frame is decoded return it to the controller 1552230557Sjimharris scic_sds_controller_release_frame( 1553230557Sjimharris owning_controller, 1554230557Sjimharris frame_index 1555230557Sjimharris ); 1556230557Sjimharris } 1557230557Sjimharris 1558230557Sjimharris // Check for the end of the transfer, are there more bytes remaining 1559230557Sjimharris // for this data transfer 1560230557Sjimharris if ( 1561230557Sjimharris (status == SCI_SUCCESS) 1562230557Sjimharris && (this_request->type.pio.pio_transfer_bytes == 0) 1563230557Sjimharris ) 1564230557Sjimharris { 1565230557Sjimharris if ((this_request->type.pio.ending_status & ATA_STATUS_REG_BSY_BIT) == 0) 1566230557Sjimharris { 1567230557Sjimharris scic_sds_request_set_status( 1568230557Sjimharris &this_request->parent, 1569230557Sjimharris SCU_TASK_DONE_CHECK_RESPONSE, 1570230557Sjimharris SCI_FAILURE_IO_RESPONSE_VALID 1571230557Sjimharris ); 1572230557Sjimharris 1573230557Sjimharris sci_base_state_machine_change_state( 1574230557Sjimharris &this_request->parent.parent.state_machine, 1575230557Sjimharris SCI_BASE_REQUEST_STATE_COMPLETED 1576230557Sjimharris ); 1577230557Sjimharris } 1578230557Sjimharris else 1579230557Sjimharris { 1580230557Sjimharris sci_base_state_machine_change_state( 1581230557Sjimharris &this_request->parent.started_substate_machine, 1582230557Sjimharris SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE 1583230557Sjimharris ); 1584230557Sjimharris } 1585230557Sjimharris } 1586230557Sjimharris } 1587230557Sjimharris else 1588230557Sjimharris { 1589230557Sjimharris SCIC_LOG_ERROR(( 1590230557Sjimharris sci_base_object_get_logger(this_request), 1591230557Sjimharris SCIC_LOG_OBJECT_STP_IO_REQUEST, 1592230557Sjimharris "SCIC PIO Request 0x%x received frame %d with fis type 0x%02x when expecting a data fis.\n", 1593230557Sjimharris this_request, frame_index, frame_header->fis_type 1594230557Sjimharris )); 1595230557Sjimharris 1596230557Sjimharris scic_sds_request_set_status( 1597230557Sjimharris &this_request->parent, 1598230557Sjimharris SCU_TASK_DONE_GOOD, 1599230557Sjimharris SCI_FAILURE_IO_REQUIRES_SCSI_ABORT 1600230557Sjimharris ); 1601230557Sjimharris 1602230557Sjimharris sci_base_state_machine_change_state( 1603230557Sjimharris &this_request->parent.parent.state_machine, 1604230557Sjimharris SCI_BASE_REQUEST_STATE_COMPLETED 1605230557Sjimharris ); 1606230557Sjimharris 1607230557Sjimharris // Frame is decoded return it to the controller 1608230557Sjimharris scic_sds_controller_release_frame( 1609230557Sjimharris owning_controller, 1610230557Sjimharris frame_index 1611230557Sjimharris ); 1612230557Sjimharris } 1613230557Sjimharris } 1614230557Sjimharris else 1615230557Sjimharris { 1616230557Sjimharris SCIC_LOG_ERROR(( 1617230557Sjimharris sci_base_object_get_logger(this_request), 1618230557Sjimharris SCIC_LOG_OBJECT_STP_IO_REQUEST, 1619230557Sjimharris "SCIC IO Request 0x%x could not get frame header for frame index %d, status %x\n", 1620230557Sjimharris this_request, frame_index, status 1621230557Sjimharris )); 1622230557Sjimharris } 1623230557Sjimharris 1624230557Sjimharris return status; 1625230557Sjimharris} 1626230557Sjimharris 1627230557Sjimharris 1628230557Sjimharris/** 1629230557Sjimharris * 1630230557Sjimharris * 1631230557Sjimharris * @param[in] this_request 1632230557Sjimharris * @param[in] completion_code 1633230557Sjimharris * 1634230557Sjimharris * @return SCI_STATUS 1635230557Sjimharris */ 1636230557Sjimharrisstatic 1637230557SjimharrisSCI_STATUS scic_sds_stp_request_pio_data_out_await_data_transmit_completion_tc_completion_handler( 1638230557Sjimharris 1639230557Sjimharris SCIC_SDS_REQUEST_T * this_request, 1640230557Sjimharris U32 completion_code 1641230557Sjimharris) 1642230557Sjimharris{ 1643230557Sjimharris SCI_STATUS status = SCI_SUCCESS; 1644230557Sjimharris BOOL all_frames_transferred = FALSE; 1645230557Sjimharris 1646230557Sjimharris SCIC_SDS_STP_REQUEST_T *this_scic_sds_stp_request = (SCIC_SDS_STP_REQUEST_T *) this_request; 1647230557Sjimharris 1648230557Sjimharris SCIC_LOG_TRACE(( 1649230557Sjimharris sci_base_object_get_logger(this_request), 1650230557Sjimharris SCIC_LOG_OBJECT_STP_IO_REQUEST, 1651230557Sjimharris "scic_sds_stp_request_pio_data_in_await_h2d_completion_tc_completion_handler(0x%x, 0x%x) enter\n", 1652230557Sjimharris this_request, completion_code 1653230557Sjimharris )); 1654230557Sjimharris 1655230557Sjimharris switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) 1656230557Sjimharris { 1657230557Sjimharris case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): 1658230557Sjimharris //Transmit data 1659230557Sjimharris if (this_scic_sds_stp_request->type.pio.pio_transfer_bytes != 0) 1660230557Sjimharris { 1661230557Sjimharris status = scic_sds_stp_request_pio_data_out_transmit_data ( this_request); 1662230557Sjimharris if (status == SCI_SUCCESS) 1663230557Sjimharris { 1664230557Sjimharris if (this_scic_sds_stp_request->type.pio.pio_transfer_bytes == 0) 1665230557Sjimharris all_frames_transferred = TRUE; 1666230557Sjimharris } 1667230557Sjimharris } 1668230557Sjimharris else if (this_scic_sds_stp_request->type.pio.pio_transfer_bytes == 0) 1669230557Sjimharris { 1670230557Sjimharris //this will happen if the all data is written at the first time after the pio setup fis is recieved 1671230557Sjimharris all_frames_transferred = TRUE; 1672230557Sjimharris } 1673230557Sjimharris 1674230557Sjimharris //all data transferred. 1675230557Sjimharris if (all_frames_transferred) 1676230557Sjimharris { 1677230557Sjimharris //Change the state to SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_FRAME_SUBSTATE 1678230557Sjimharris //and wait for PIO_SETUP fis / or D2H REg fis. 1679230557Sjimharris sci_base_state_machine_change_state( 1680230557Sjimharris &this_request->started_substate_machine, 1681230557Sjimharris SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE 1682230557Sjimharris ); 1683230557Sjimharris } 1684230557Sjimharris break; 1685230557Sjimharris 1686230557Sjimharris default: 1687230557Sjimharris // All other completion status cause the IO to be complete. If a NAK 1688230557Sjimharris // was received, then it is up to the user to retry the request. 1689230557Sjimharris scic_sds_request_set_status( 1690230557Sjimharris this_request, 1691230557Sjimharris SCU_NORMALIZE_COMPLETION_STATUS(completion_code), 1692230557Sjimharris SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR 1693230557Sjimharris ); 1694230557Sjimharris 1695230557Sjimharris sci_base_state_machine_change_state( 1696230557Sjimharris &this_request->parent.state_machine, 1697230557Sjimharris SCI_BASE_REQUEST_STATE_COMPLETED 1698230557Sjimharris ); 1699230557Sjimharris break; 1700230557Sjimharris } 1701230557Sjimharris 1702230557Sjimharris return status; 1703230557Sjimharris} 1704230557Sjimharris 1705230557Sjimharris/** 1706230557Sjimharris * This method will handle any link layer events while waiting for the data 1707230557Sjimharris * frame. 1708230557Sjimharris * 1709230557Sjimharris * @param[in] request This is the request which is receiving the event. 1710230557Sjimharris * @param[in] event_code This is the event code that the request on which the 1711230557Sjimharris * request is expected to take action. 1712230557Sjimharris * 1713230557Sjimharris * @return SCI_STATUS 1714230557Sjimharris * @retval SCI_SUCCESS 1715230557Sjimharris * @retval SCI_FAILURE 1716230557Sjimharris */ 1717230557Sjimharrisstatic 1718230557SjimharrisSCI_STATUS scic_sds_stp_request_pio_data_in_await_data_event_handler( 1719230557Sjimharris SCIC_SDS_REQUEST_T * request, 1720230557Sjimharris U32 event_code 1721230557Sjimharris) 1722230557Sjimharris{ 1723230557Sjimharris SCI_STATUS status; 1724230557Sjimharris 1725230557Sjimharris switch (scu_get_event_specifier(event_code)) 1726230557Sjimharris { 1727230557Sjimharris case SCU_TASK_DONE_CRC_ERR << SCU_EVENT_SPECIFIC_CODE_SHIFT: 1728230557Sjimharris // We are waiting for data and the SCU has R_ERR the data frame. 1729230557Sjimharris // Go back to waiting for the D2H Register FIS 1730230557Sjimharris sci_base_state_machine_change_state( 1731230557Sjimharris &request->started_substate_machine, 1732230557Sjimharris SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE 1733230557Sjimharris ); 1734230557Sjimharris 1735230557Sjimharris status = SCI_SUCCESS; 1736230557Sjimharris break; 1737230557Sjimharris 1738230557Sjimharris default: 1739230557Sjimharris SCIC_LOG_ERROR(( 1740230557Sjimharris sci_base_object_get_logger(request), 1741230557Sjimharris SCIC_LOG_OBJECT_STP_IO_REQUEST, 1742230557Sjimharris "SCIC PIO Request 0x%x received unexpected event 0x%08x\n", 1743230557Sjimharris request, event_code 1744230557Sjimharris )); 1745230557Sjimharris 1746230557Sjimharris /// @todo Should we fail the PIO request when we get an unexpected event? 1747230557Sjimharris status = SCI_FAILURE; 1748230557Sjimharris break; 1749230557Sjimharris } 1750230557Sjimharris 1751230557Sjimharris return status; 1752230557Sjimharris} 1753230557Sjimharris 1754230557Sjimharris// --------------------------------------------------------------------------- 1755230557Sjimharris 1756230557SjimharrisSCIC_SDS_IO_REQUEST_STATE_HANDLER_T 1757230557Sjimharris scic_sds_stp_request_started_pio_substate_handler_table 1758230557Sjimharris [SCIC_SDS_STP_REQUEST_STARTED_PIO_MAX_SUBSTATES] = 1759230557Sjimharris{ 1760230557Sjimharris // SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE 1761230557Sjimharris { 1762230557Sjimharris { 1763230557Sjimharris scic_sds_request_default_start_handler, 1764230557Sjimharris scic_sds_request_started_state_abort_handler, 1765230557Sjimharris scic_sds_request_default_complete_handler, 1766230557Sjimharris scic_sds_request_default_destruct_handler 1767230557Sjimharris }, 1768230557Sjimharris scic_sds_stp_request_pio_await_h2d_completion_tc_completion_handler, 1769230557Sjimharris scic_sds_request_default_event_handler, 1770230557Sjimharris scic_sds_request_default_frame_handler 1771230557Sjimharris }, 1772230557Sjimharris // SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE 1773230557Sjimharris { 1774230557Sjimharris { 1775230557Sjimharris scic_sds_request_default_start_handler, 1776230557Sjimharris //scic_sds_stp_pio_request_data_in_await_frame_abort_handler, 1777230557Sjimharris scic_sds_request_started_state_abort_handler, 1778230557Sjimharris scic_sds_request_default_complete_handler, 1779230557Sjimharris scic_sds_request_default_destruct_handler 1780230557Sjimharris }, 1781230557Sjimharris scic_sds_request_default_tc_completion_handler, 1782230557Sjimharris scic_sds_request_default_event_handler, 1783230557Sjimharris scic_sds_stp_request_pio_await_frame_frame_handler 1784230557Sjimharris }, 1785230557Sjimharris // SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE 1786230557Sjimharris { 1787230557Sjimharris { 1788230557Sjimharris scic_sds_request_default_start_handler, 1789230557Sjimharris //scic_sds_stp_pio_request_data_in_await_data_abort_handler, 1790230557Sjimharris scic_sds_request_started_state_abort_handler, 1791230557Sjimharris scic_sds_request_default_complete_handler, 1792230557Sjimharris scic_sds_request_default_destruct_handler 1793230557Sjimharris }, 1794230557Sjimharris scic_sds_request_default_tc_completion_handler, 1795230557Sjimharris scic_sds_stp_request_pio_data_in_await_data_event_handler, 1796230557Sjimharris scic_sds_stp_request_pio_data_in_await_data_frame_handler 1797230557Sjimharris }, 1798230557Sjimharris //SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE 1799230557Sjimharris { 1800230557Sjimharris { 1801230557Sjimharris scic_sds_request_default_start_handler, 1802230557Sjimharris scic_sds_request_started_state_abort_handler, 1803230557Sjimharris scic_sds_request_default_complete_handler, 1804230557Sjimharris scic_sds_request_default_destruct_handler 1805230557Sjimharris }, 1806230557Sjimharris scic_sds_stp_request_pio_data_out_await_data_transmit_completion_tc_completion_handler, 1807230557Sjimharris scic_sds_request_default_event_handler, 1808230557Sjimharris scic_sds_request_default_frame_handler 1809230557Sjimharris } 1810230557Sjimharris}; 1811230557Sjimharris 1812230557Sjimharrisstatic 1813230557Sjimharrisvoid scic_sds_stp_request_started_pio_await_h2d_completion_enter( 1814230557Sjimharris SCI_BASE_OBJECT_T *object 1815230557Sjimharris) 1816230557Sjimharris{ 1817230557Sjimharris SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object; 1818230557Sjimharris 1819230557Sjimharris SET_STATE_HANDLER( 1820230557Sjimharris this_request, 1821230557Sjimharris scic_sds_stp_request_started_pio_substate_handler_table, 1822230557Sjimharris SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE 1823230557Sjimharris ); 1824230557Sjimharris 1825230557Sjimharris scic_sds_remote_device_set_working_request( 1826230557Sjimharris this_request->target_device, this_request); 1827230557Sjimharris} 1828230557Sjimharris 1829230557Sjimharrisstatic 1830230557Sjimharrisvoid scic_sds_stp_request_started_pio_await_frame_enter( 1831230557Sjimharris SCI_BASE_OBJECT_T *object 1832230557Sjimharris) 1833230557Sjimharris{ 1834230557Sjimharris SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object; 1835230557Sjimharris 1836230557Sjimharris SET_STATE_HANDLER( 1837230557Sjimharris this_request, 1838230557Sjimharris scic_sds_stp_request_started_pio_substate_handler_table, 1839230557Sjimharris SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE 1840230557Sjimharris ); 1841230557Sjimharris} 1842230557Sjimharris 1843230557Sjimharrisstatic 1844230557Sjimharrisvoid scic_sds_stp_request_started_pio_data_in_await_data_enter( 1845230557Sjimharris SCI_BASE_OBJECT_T *object 1846230557Sjimharris) 1847230557Sjimharris{ 1848230557Sjimharris SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object; 1849230557Sjimharris 1850230557Sjimharris SET_STATE_HANDLER( 1851230557Sjimharris this_request, 1852230557Sjimharris scic_sds_stp_request_started_pio_substate_handler_table, 1853230557Sjimharris SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE 1854230557Sjimharris ); 1855230557Sjimharris} 1856230557Sjimharris 1857230557Sjimharrisstatic 1858230557Sjimharrisvoid scic_sds_stp_request_started_pio_data_out_transmit_data_enter( 1859230557Sjimharris SCI_BASE_OBJECT_T *object 1860230557Sjimharris) 1861230557Sjimharris{ 1862230557Sjimharris SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object; 1863230557Sjimharris 1864230557Sjimharris SET_STATE_HANDLER( 1865230557Sjimharris this_request, 1866230557Sjimharris scic_sds_stp_request_started_pio_substate_handler_table, 1867230557Sjimharris SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE 1868230557Sjimharris ); 1869230557Sjimharris} 1870230557Sjimharris 1871230557Sjimharris// --------------------------------------------------------------------------- 1872230557Sjimharris 1873230557SjimharrisSCI_BASE_STATE_T 1874230557Sjimharris scic_sds_stp_request_started_pio_substate_table 1875230557Sjimharris [SCIC_SDS_STP_REQUEST_STARTED_PIO_MAX_SUBSTATES] = 1876230557Sjimharris{ 1877230557Sjimharris { 1878230557Sjimharris SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE, 1879230557Sjimharris scic_sds_stp_request_started_pio_await_h2d_completion_enter, 1880230557Sjimharris NULL 1881230557Sjimharris }, 1882230557Sjimharris { 1883230557Sjimharris SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE, 1884230557Sjimharris scic_sds_stp_request_started_pio_await_frame_enter, 1885230557Sjimharris NULL 1886230557Sjimharris }, 1887230557Sjimharris { 1888230557Sjimharris SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE, 1889230557Sjimharris scic_sds_stp_request_started_pio_data_in_await_data_enter, 1890230557Sjimharris NULL 1891230557Sjimharris }, 1892230557Sjimharris { 1893230557Sjimharris SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE, 1894230557Sjimharris scic_sds_stp_request_started_pio_data_out_transmit_data_enter, 1895230557Sjimharris NULL 1896230557Sjimharris } 1897230557Sjimharris}; 1898230557Sjimharris 1899230557Sjimharris//****************************************************************************** 1900230557Sjimharris//* UDMA REQUEST STATE MACHINE 1901230557Sjimharris//****************************************************************************** 1902230557Sjimharris 1903230557Sjimharrisstatic 1904230557Sjimharrisvoid scic_sds_stp_request_udma_complete_request( 1905230557Sjimharris SCIC_SDS_REQUEST_T * this_request, 1906230557Sjimharris U32 scu_status, 1907230557Sjimharris SCI_STATUS sci_status 1908230557Sjimharris) 1909230557Sjimharris{ 1910230557Sjimharris scic_sds_request_set_status( 1911230557Sjimharris this_request, scu_status, sci_status 1912230557Sjimharris ); 1913230557Sjimharris 1914230557Sjimharris sci_base_state_machine_change_state( 1915230557Sjimharris &this_request->parent.state_machine, 1916230557Sjimharris SCI_BASE_REQUEST_STATE_COMPLETED 1917230557Sjimharris ); 1918230557Sjimharris} 1919230557Sjimharris 1920230557Sjimharris/** 1921230557Sjimharris * 1922230557Sjimharris * 1923230557Sjimharris * @param[in] this_request 1924230557Sjimharris * @param[in] frame_index 1925230557Sjimharris * 1926230557Sjimharris * @return SCI_STATUS 1927230557Sjimharris */ 1928230557Sjimharrisstatic 1929230557SjimharrisSCI_STATUS scic_sds_stp_request_udma_general_frame_handler( 1930230557Sjimharris SCIC_SDS_REQUEST_T * this_request, 1931230557Sjimharris U32 frame_index 1932230557Sjimharris) 1933230557Sjimharris{ 1934230557Sjimharris SCI_STATUS status; 1935230557Sjimharris SATA_FIS_HEADER_T * frame_header; 1936230557Sjimharris U32 * frame_buffer; 1937230557Sjimharris 1938230557Sjimharris SCIC_LOG_TRACE(( 1939230557Sjimharris sci_base_object_get_logger(this_request), 1940230557Sjimharris SCIC_LOG_OBJECT_STP_IO_REQUEST, 1941230557Sjimharris "scic_sds_stp_pio_request_data_in_await_frame_frame_handler(0x%x, 0x%x) enter\n", 1942230557Sjimharris this_request, frame_index 1943230557Sjimharris )); 1944230557Sjimharris 1945230557Sjimharris status = scic_sds_unsolicited_frame_control_get_header( 1946230557Sjimharris &this_request->owning_controller->uf_control, 1947230557Sjimharris frame_index, 1948230557Sjimharris (void**) &frame_header 1949230557Sjimharris ); 1950230557Sjimharris 1951230557Sjimharris if ( 1952230557Sjimharris (status == SCI_SUCCESS) 1953230557Sjimharris && (frame_header->fis_type == SATA_FIS_TYPE_REGD2H) 1954230557Sjimharris ) 1955230557Sjimharris { 1956230557Sjimharris scic_sds_unsolicited_frame_control_get_buffer( 1957230557Sjimharris &this_request->owning_controller->uf_control, 1958230557Sjimharris frame_index, 1959230557Sjimharris (void**) &frame_buffer 1960230557Sjimharris ); 1961230557Sjimharris 1962230557Sjimharris scic_sds_controller_copy_sata_response( 1963230557Sjimharris &((SCIC_SDS_STP_REQUEST_T *)this_request)->d2h_reg_fis, 1964230557Sjimharris (U32 *)frame_header, 1965230557Sjimharris frame_buffer 1966230557Sjimharris ); 1967230557Sjimharris } 1968230557Sjimharris 1969230557Sjimharris scic_sds_controller_release_frame( 1970230557Sjimharris this_request->owning_controller, frame_index); 1971230557Sjimharris 1972230557Sjimharris return status; 1973230557Sjimharris} 1974230557Sjimharris 1975230557Sjimharris/** 1976230557Sjimharris * @brief This method process TC completions while in the state where 1977230557Sjimharris * we are waiting for TC completions. 1978230557Sjimharris * 1979230557Sjimharris * @param[in] this_request 1980230557Sjimharris * @param[in] completion_code 1981230557Sjimharris * 1982230557Sjimharris * @return SCI_STATUS 1983230557Sjimharris */ 1984230557Sjimharrisstatic 1985230557SjimharrisSCI_STATUS scic_sds_stp_request_udma_await_tc_completion_tc_completion_handler( 1986230557Sjimharris SCIC_SDS_REQUEST_T * request, 1987230557Sjimharris U32 completion_code 1988230557Sjimharris) 1989230557Sjimharris{ 1990230557Sjimharris SCI_STATUS status = SCI_SUCCESS; 1991230557Sjimharris SCIC_SDS_STP_REQUEST_T * this_request = (SCIC_SDS_STP_REQUEST_T *)request; 1992230557Sjimharris 1993230557Sjimharris switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) 1994230557Sjimharris { 1995230557Sjimharris case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): 1996230557Sjimharris scic_sds_stp_request_udma_complete_request( 1997230557Sjimharris &this_request->parent, SCU_TASK_DONE_GOOD, SCI_SUCCESS 1998230557Sjimharris ); 1999230557Sjimharris break; 2000230557Sjimharris 2001230557Sjimharris case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_FIS): 2002230557Sjimharris case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_REG_ERR): 2003230557Sjimharris // We must check ther response buffer to see if the D2H Register FIS was 2004230557Sjimharris // received before we got the TC completion. 2005230557Sjimharris if (this_request->d2h_reg_fis.fis_type == SATA_FIS_TYPE_REGD2H) 2006230557Sjimharris { 2007230557Sjimharris scic_sds_remote_device_suspend( 2008230557Sjimharris this_request->parent.target_device, 2009230557Sjimharris SCU_EVENT_SPECIFIC(SCU_NORMALIZE_COMPLETION_STATUS(completion_code)) 2010230557Sjimharris ); 2011230557Sjimharris 2012230557Sjimharris scic_sds_stp_request_udma_complete_request( 2013230557Sjimharris &this_request->parent, 2014230557Sjimharris SCU_TASK_DONE_CHECK_RESPONSE, 2015230557Sjimharris SCI_FAILURE_IO_RESPONSE_VALID 2016230557Sjimharris ); 2017230557Sjimharris } 2018230557Sjimharris else 2019230557Sjimharris { 2020230557Sjimharris // If we have an error completion status for the TC then we can expect a 2021230557Sjimharris // D2H register FIS from the device so we must change state to wait for it 2022230557Sjimharris sci_base_state_machine_change_state( 2023230557Sjimharris &this_request->parent.started_substate_machine, 2024230557Sjimharris SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE 2025230557Sjimharris ); 2026230557Sjimharris } 2027230557Sjimharris break; 2028230557Sjimharris 2029230557Sjimharris /// @todo Check to see if any of these completion status need to wait for 2030230557Sjimharris /// the device to host register fis. 2031230557Sjimharris /// @todo We can retry the command for SCU_TASK_DONE_CMD_LL_R_ERR - this comes only for B0 2032230557Sjimharris case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_INV_FIS_LEN): 2033230557Sjimharris case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_MAX_PLD_ERR): 2034230557Sjimharris case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LL_R_ERR): 2035230557Sjimharris case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CMD_LL_R_ERR): 2036230557Sjimharris case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CRC_ERR): 2037230557Sjimharris scic_sds_remote_device_suspend( 2038230557Sjimharris this_request->parent.target_device, 2039230557Sjimharris SCU_EVENT_SPECIFIC(SCU_NORMALIZE_COMPLETION_STATUS(completion_code)) 2040230557Sjimharris ); 2041230557Sjimharris // Fall through to the default case 2042230557Sjimharris default: 2043230557Sjimharris // All other completion status cause the IO to be complete. 2044230557Sjimharris SCIC_LOG_ERROR(( 2045230557Sjimharris sci_base_object_get_logger(&this_request->parent), 2046230557Sjimharris SCIC_LOG_OBJECT_STP_IO_REQUEST, 2047230557Sjimharris "SCIC IO Request 0x%x returning CONTROLLER_SPECIFIC_IO_ERR for completion code 0x%x\n", 2048230557Sjimharris &this_request->parent, completion_code 2049230557Sjimharris )); 2050230557Sjimharris scic_sds_stp_request_udma_complete_request( 2051230557Sjimharris &this_request->parent, 2052230557Sjimharris SCU_NORMALIZE_COMPLETION_STATUS(completion_code), 2053230557Sjimharris SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR 2054230557Sjimharris ); 2055230557Sjimharris break; 2056230557Sjimharris } 2057230557Sjimharris 2058230557Sjimharris return status; 2059230557Sjimharris} 2060230557Sjimharris 2061230557Sjimharrisstatic 2062230557SjimharrisSCI_STATUS scic_sds_stp_request_udma_await_d2h_reg_fis_frame_handler( 2063230557Sjimharris SCIC_SDS_REQUEST_T * this_request, 2064230557Sjimharris U32 frame_index 2065230557Sjimharris) 2066230557Sjimharris{ 2067230557Sjimharris SCI_STATUS status; 2068230557Sjimharris 2069230557Sjimharris // Use the general frame handler to copy the resposne data 2070230557Sjimharris status = scic_sds_stp_request_udma_general_frame_handler(this_request, frame_index); 2071230557Sjimharris 2072230557Sjimharris if (status == SCI_SUCCESS) 2073230557Sjimharris { 2074230557Sjimharris scic_sds_stp_request_udma_complete_request( 2075230557Sjimharris this_request, 2076230557Sjimharris SCU_TASK_DONE_CHECK_RESPONSE, 2077230557Sjimharris SCI_FAILURE_IO_RESPONSE_VALID 2078230557Sjimharris ); 2079230557Sjimharris } 2080230557Sjimharris 2081230557Sjimharris return status; 2082230557Sjimharris} 2083230557Sjimharris 2084230557Sjimharris// --------------------------------------------------------------------------- 2085230557Sjimharris 2086230557SjimharrisSCIC_SDS_IO_REQUEST_STATE_HANDLER_T 2087230557Sjimharris scic_sds_stp_request_started_udma_substate_handler_table 2088230557Sjimharris [SCIC_SDS_STP_REQUEST_STARTED_UDMA_MAX_SUBSTATES] = 2089230557Sjimharris{ 2090230557Sjimharris // SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE 2091230557Sjimharris { 2092230557Sjimharris { 2093230557Sjimharris scic_sds_request_default_start_handler, 2094230557Sjimharris scic_sds_request_started_state_abort_handler, 2095230557Sjimharris scic_sds_request_default_complete_handler, 2096230557Sjimharris scic_sds_request_default_destruct_handler 2097230557Sjimharris }, 2098230557Sjimharris scic_sds_stp_request_udma_await_tc_completion_tc_completion_handler, 2099230557Sjimharris scic_sds_request_default_event_handler, 2100230557Sjimharris scic_sds_stp_request_udma_general_frame_handler 2101230557Sjimharris }, 2102230557Sjimharris // SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE 2103230557Sjimharris { 2104230557Sjimharris { 2105230557Sjimharris scic_sds_request_default_start_handler, 2106230557Sjimharris scic_sds_request_started_state_abort_handler, 2107230557Sjimharris scic_sds_request_default_complete_handler, 2108230557Sjimharris scic_sds_request_default_destruct_handler 2109230557Sjimharris }, 2110230557Sjimharris scic_sds_request_default_tc_completion_handler, 2111230557Sjimharris scic_sds_request_default_event_handler, 2112230557Sjimharris scic_sds_stp_request_udma_await_d2h_reg_fis_frame_handler 2113230557Sjimharris } 2114230557Sjimharris}; 2115230557Sjimharris 2116230557Sjimharris/** 2117230557Sjimharris * 2118230557Sjimharris * 2119230557Sjimharris * @param[in] object 2120230557Sjimharris */ 2121230557Sjimharrisstatic 2122230557Sjimharrisvoid scic_sds_stp_request_started_udma_await_tc_completion_enter( 2123230557Sjimharris SCI_BASE_OBJECT_T *object 2124230557Sjimharris) 2125230557Sjimharris{ 2126230557Sjimharris SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object; 2127230557Sjimharris 2128230557Sjimharris SET_STATE_HANDLER( 2129230557Sjimharris this_request, 2130230557Sjimharris scic_sds_stp_request_started_udma_substate_handler_table, 2131230557Sjimharris SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE 2132230557Sjimharris ); 2133230557Sjimharris} 2134230557Sjimharris 2135230557Sjimharris/** 2136230557Sjimharris * This state is entered when there is an TC completion failure. The hardware 2137230557Sjimharris * received an unexpected condition while processing the IO request and now 2138230557Sjimharris * will UF the D2H register FIS to complete the IO. 2139230557Sjimharris * 2140230557Sjimharris * @param[in] object 2141230557Sjimharris */ 2142230557Sjimharrisstatic 2143230557Sjimharrisvoid scic_sds_stp_request_started_udma_await_d2h_reg_fis_enter( 2144230557Sjimharris SCI_BASE_OBJECT_T *object 2145230557Sjimharris) 2146230557Sjimharris{ 2147230557Sjimharris SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object; 2148230557Sjimharris 2149230557Sjimharris SET_STATE_HANDLER( 2150230557Sjimharris this_request, 2151230557Sjimharris scic_sds_stp_request_started_udma_substate_handler_table, 2152230557Sjimharris SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE 2153230557Sjimharris ); 2154230557Sjimharris} 2155230557Sjimharris 2156230557Sjimharris// --------------------------------------------------------------------------- 2157230557Sjimharris 2158230557SjimharrisSCI_BASE_STATE_T 2159230557Sjimharris scic_sds_stp_request_started_udma_substate_table 2160230557Sjimharris [SCIC_SDS_STP_REQUEST_STARTED_UDMA_MAX_SUBSTATES] = 2161230557Sjimharris{ 2162230557Sjimharris { 2163230557Sjimharris SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE, 2164230557Sjimharris scic_sds_stp_request_started_udma_await_tc_completion_enter, 2165230557Sjimharris NULL 2166230557Sjimharris }, 2167230557Sjimharris { 2168230557Sjimharris SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE, 2169230557Sjimharris scic_sds_stp_request_started_udma_await_d2h_reg_fis_enter, 2170230557Sjimharris NULL 2171230557Sjimharris } 2172230557Sjimharris}; 2173230557Sjimharris 2174230557Sjimharris//****************************************************************************** 2175230557Sjimharris//* STP SOFT RESET STATE MACHINE 2176230557Sjimharris//****************************************************************************** 2177230557Sjimharris 2178230557Sjimharris/** 2179230557Sjimharris * This method processes a TC completion. The expected TC completion is 2180230557Sjimharris * for the transmission of the H2D register FIS containing the SATA/STP 2181230557Sjimharris * non-data request. 2182230557Sjimharris * 2183230557Sjimharris * @param[in] this_request 2184230557Sjimharris * @param[in] completion_code 2185230557Sjimharris * 2186230557Sjimharris * @return This method always successfully processes the TC completion. 2187230557Sjimharris * @retval SCI_SUCCESS This value is always returned. 2188230557Sjimharris */ 2189230557Sjimharrisstatic 2190230557SjimharrisSCI_STATUS scic_sds_stp_request_soft_reset_await_h2d_asserted_tc_completion_handler( 2191230557Sjimharris SCIC_SDS_REQUEST_T * this_request, 2192230557Sjimharris U32 completion_code 2193230557Sjimharris) 2194230557Sjimharris{ 2195230557Sjimharris SCIC_LOG_TRACE(( 2196230557Sjimharris sci_base_object_get_logger(this_request), 2197230557Sjimharris SCIC_LOG_OBJECT_STP_IO_REQUEST, 2198230557Sjimharris "scic_sds_stp_request_soft_reset_await_h2d_tc_completion_handler(0x%x, 0x%x) enter\n", 2199230557Sjimharris this_request, completion_code 2200230557Sjimharris )); 2201230557Sjimharris 2202230557Sjimharris switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) 2203230557Sjimharris { 2204230557Sjimharris case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): 2205230557Sjimharris scic_sds_request_set_status( 2206230557Sjimharris this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS 2207230557Sjimharris ); 2208230557Sjimharris 2209230557Sjimharris sci_base_state_machine_change_state( 2210230557Sjimharris &this_request->started_substate_machine, 2211230557Sjimharris SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE 2212230557Sjimharris ); 2213230557Sjimharris break; 2214230557Sjimharris 2215230557Sjimharris default: 2216230557Sjimharris // All other completion status cause the IO to be complete. If a NAK 2217230557Sjimharris // was received, then it is up to the user to retry the request. 2218230557Sjimharris scic_sds_request_set_status( 2219230557Sjimharris this_request, 2220230557Sjimharris SCU_NORMALIZE_COMPLETION_STATUS(completion_code), 2221230557Sjimharris SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR 2222230557Sjimharris ); 2223230557Sjimharris 2224230557Sjimharris sci_base_state_machine_change_state( 2225230557Sjimharris &this_request->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED 2226230557Sjimharris ); 2227230557Sjimharris break; 2228230557Sjimharris } 2229230557Sjimharris 2230230557Sjimharris return SCI_SUCCESS; 2231230557Sjimharris} 2232230557Sjimharris 2233230557Sjimharris/** 2234230557Sjimharris * This method processes a TC completion. The expected TC completion is 2235230557Sjimharris * for the transmission of the H2D register FIS containing the SATA/STP 2236230557Sjimharris * non-data request. 2237230557Sjimharris * 2238230557Sjimharris * @param[in] this_request 2239230557Sjimharris * @param[in] completion_code 2240230557Sjimharris * 2241230557Sjimharris * @return This method always successfully processes the TC completion. 2242230557Sjimharris * @retval SCI_SUCCESS This value is always returned. 2243230557Sjimharris */ 2244230557Sjimharrisstatic 2245230557SjimharrisSCI_STATUS scic_sds_stp_request_soft_reset_await_h2d_diagnostic_tc_completion_handler( 2246230557Sjimharris SCIC_SDS_REQUEST_T * this_request, 2247230557Sjimharris U32 completion_code 2248230557Sjimharris) 2249230557Sjimharris{ 2250230557Sjimharris SCIC_LOG_TRACE(( 2251230557Sjimharris sci_base_object_get_logger(this_request), 2252230557Sjimharris SCIC_LOG_OBJECT_STP_IO_REQUEST, 2253230557Sjimharris "scic_sds_stp_request_soft_reset_await_h2d_tc_completion_handler(0x%x, 0x%x) enter\n", 2254230557Sjimharris this_request, completion_code 2255230557Sjimharris )); 2256230557Sjimharris 2257230557Sjimharris switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) 2258230557Sjimharris { 2259230557Sjimharris case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): 2260230557Sjimharris scic_sds_request_set_status( 2261230557Sjimharris this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS 2262230557Sjimharris ); 2263230557Sjimharris 2264230557Sjimharris sci_base_state_machine_change_state( 2265230557Sjimharris &this_request->started_substate_machine, 2266230557Sjimharris SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE 2267230557Sjimharris ); 2268230557Sjimharris break; 2269230557Sjimharris 2270230557Sjimharris default: 2271230557Sjimharris // All other completion status cause the IO to be complete. If a NAK 2272230557Sjimharris // was received, then it is up to the user to retry the request. 2273230557Sjimharris scic_sds_request_set_status( 2274230557Sjimharris this_request, 2275230557Sjimharris SCU_NORMALIZE_COMPLETION_STATUS(completion_code), 2276230557Sjimharris SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR 2277230557Sjimharris ); 2278230557Sjimharris 2279230557Sjimharris sci_base_state_machine_change_state( 2280230557Sjimharris &this_request->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED 2281230557Sjimharris ); 2282230557Sjimharris break; 2283230557Sjimharris } 2284230557Sjimharris 2285230557Sjimharris return SCI_SUCCESS; 2286230557Sjimharris} 2287230557Sjimharris 2288230557Sjimharris/** 2289230557Sjimharris * This method processes frames received from the target while waiting 2290230557Sjimharris * for a device to host register FIS. If a non-register FIS is received 2291230557Sjimharris * during this time, it is treated as a protocol violation from an 2292230557Sjimharris * IO perspective. 2293230557Sjimharris * 2294230557Sjimharris * @param[in] request This parameter specifies the request for which a 2295230557Sjimharris * frame has been received. 2296230557Sjimharris * @param[in] frame_index This parameter specifies the index of the frame 2297230557Sjimharris * that has been received. 2298230557Sjimharris * 2299230557Sjimharris * @return Indicate if the received frame was processed successfully. 2300230557Sjimharris */ 2301230557Sjimharrisstatic 2302230557SjimharrisSCI_STATUS scic_sds_stp_request_soft_reset_await_d2h_frame_handler( 2303230557Sjimharris SCIC_SDS_REQUEST_T * request, 2304230557Sjimharris U32 frame_index 2305230557Sjimharris) 2306230557Sjimharris{ 2307230557Sjimharris SCI_STATUS status; 2308230557Sjimharris SATA_FIS_HEADER_T * frame_header; 2309230557Sjimharris U32 * frame_buffer; 2310230557Sjimharris SCIC_SDS_STP_REQUEST_T * this_request = (SCIC_SDS_STP_REQUEST_T *)request; 2311230557Sjimharris 2312230557Sjimharris // Save off the controller, so that we do not touch the request after it 2313230557Sjimharris // is completed. 2314230557Sjimharris SCIC_SDS_CONTROLLER_T * owning_controller = this_request->parent.owning_controller; 2315230557Sjimharris 2316230557Sjimharris SCIC_LOG_TRACE(( 2317230557Sjimharris sci_base_object_get_logger(this_request), 2318230557Sjimharris SCIC_LOG_OBJECT_STP_IO_REQUEST, 2319230557Sjimharris "scic_sds_stp_request_soft_reset_await_d2h_frame_handler(0x%x, 0x%x) enter\n", 2320230557Sjimharris this_request, frame_index 2321230557Sjimharris )); 2322230557Sjimharris 2323230557Sjimharris status = scic_sds_unsolicited_frame_control_get_header( 2324230557Sjimharris &(owning_controller->uf_control), 2325230557Sjimharris frame_index, 2326230557Sjimharris (void**) &frame_header 2327230557Sjimharris ); 2328230557Sjimharris 2329230557Sjimharris if (status == SCI_SUCCESS) 2330230557Sjimharris { 2331230557Sjimharris switch (frame_header->fis_type) 2332230557Sjimharris { 2333230557Sjimharris case SATA_FIS_TYPE_REGD2H: 2334230557Sjimharris scic_sds_unsolicited_frame_control_get_buffer( 2335230557Sjimharris &(owning_controller->uf_control), 2336230557Sjimharris frame_index, 2337230557Sjimharris (void**) &frame_buffer 2338230557Sjimharris ); 2339230557Sjimharris 2340230557Sjimharris scic_sds_controller_copy_sata_response( 2341230557Sjimharris &this_request->d2h_reg_fis, (U32 *)frame_header, frame_buffer 2342230557Sjimharris ); 2343230557Sjimharris 2344230557Sjimharris // The command has completed with error 2345230557Sjimharris scic_sds_request_set_status( 2346230557Sjimharris &this_request->parent, 2347230557Sjimharris SCU_TASK_DONE_CHECK_RESPONSE, 2348230557Sjimharris SCI_FAILURE_IO_RESPONSE_VALID 2349230557Sjimharris ); 2350230557Sjimharris break; 2351230557Sjimharris 2352230557Sjimharris default: 2353230557Sjimharris SCIC_LOG_WARNING(( 2354230557Sjimharris sci_base_object_get_logger(this_request), 2355230557Sjimharris SCIC_LOG_OBJECT_STP_IO_REQUEST, 2356230557Sjimharris "IO Request:0x%x Frame Id:%d protocol violation occurred\n", 2357230557Sjimharris this_request, frame_index 2358230557Sjimharris )); 2359230557Sjimharris 2360230557Sjimharris scic_sds_request_set_status( 2361230557Sjimharris &this_request->parent, 2362230557Sjimharris SCU_TASK_DONE_UNEXP_FIS, 2363230557Sjimharris SCI_FAILURE_PROTOCOL_VIOLATION 2364230557Sjimharris ); 2365230557Sjimharris break; 2366230557Sjimharris } 2367230557Sjimharris 2368230557Sjimharris sci_base_state_machine_change_state( 2369230557Sjimharris &this_request->parent.parent.state_machine, 2370230557Sjimharris SCI_BASE_REQUEST_STATE_COMPLETED 2371230557Sjimharris ); 2372230557Sjimharris 2373230557Sjimharris // Frame has been decoded return it to the controller 2374230557Sjimharris scic_sds_controller_release_frame( 2375230557Sjimharris owning_controller, frame_index 2376230557Sjimharris ); 2377230557Sjimharris } 2378230557Sjimharris else 2379230557Sjimharris { 2380230557Sjimharris SCIC_LOG_ERROR(( 2381230557Sjimharris sci_base_object_get_logger(this_request), 2382230557Sjimharris SCIC_LOG_OBJECT_STP_IO_REQUEST, 2383230557Sjimharris "SCIC IO Request 0x%x could not get frame header for frame index %d, status %x\n", 2384230557Sjimharris this_request, frame_index, status 2385230557Sjimharris )); 2386230557Sjimharris } 2387230557Sjimharris 2388230557Sjimharris return status; 2389230557Sjimharris} 2390230557Sjimharris 2391230557Sjimharris// --------------------------------------------------------------------------- 2392230557Sjimharris 2393230557SjimharrisSCIC_SDS_IO_REQUEST_STATE_HANDLER_T 2394230557Sjimharris scic_sds_stp_request_started_soft_reset_substate_handler_table 2395230557Sjimharris [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_MAX_SUBSTATES] = 2396230557Sjimharris{ 2397230557Sjimharris // SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE 2398230557Sjimharris { 2399230557Sjimharris { 2400230557Sjimharris scic_sds_request_default_start_handler, 2401230557Sjimharris scic_sds_request_started_state_abort_handler, 2402230557Sjimharris scic_sds_request_default_complete_handler, 2403230557Sjimharris scic_sds_request_default_destruct_handler 2404230557Sjimharris }, 2405230557Sjimharris scic_sds_stp_request_soft_reset_await_h2d_asserted_tc_completion_handler, 2406230557Sjimharris scic_sds_request_default_event_handler, 2407230557Sjimharris scic_sds_request_default_frame_handler 2408230557Sjimharris }, 2409230557Sjimharris // SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE 2410230557Sjimharris { 2411230557Sjimharris { 2412230557Sjimharris scic_sds_request_default_start_handler, 2413230557Sjimharris scic_sds_request_started_state_abort_handler, 2414230557Sjimharris scic_sds_request_default_complete_handler, 2415230557Sjimharris scic_sds_request_default_destruct_handler 2416230557Sjimharris }, 2417230557Sjimharris scic_sds_stp_request_soft_reset_await_h2d_diagnostic_tc_completion_handler, 2418230557Sjimharris scic_sds_request_default_event_handler, 2419230557Sjimharris scic_sds_request_default_frame_handler 2420230557Sjimharris }, 2421230557Sjimharris // SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE 2422230557Sjimharris { 2423230557Sjimharris { 2424230557Sjimharris scic_sds_request_default_start_handler, 2425230557Sjimharris scic_sds_request_started_state_abort_handler, 2426230557Sjimharris scic_sds_request_default_complete_handler, 2427230557Sjimharris scic_sds_request_default_destruct_handler 2428230557Sjimharris }, 2429230557Sjimharris scic_sds_request_default_tc_completion_handler, 2430230557Sjimharris scic_sds_request_default_event_handler, 2431230557Sjimharris scic_sds_stp_request_soft_reset_await_d2h_frame_handler 2432230557Sjimharris } 2433230557Sjimharris}; 2434230557Sjimharris 2435230557Sjimharrisstatic 2436230557Sjimharrisvoid scic_sds_stp_request_started_soft_reset_await_h2d_asserted_completion_enter( 2437230557Sjimharris SCI_BASE_OBJECT_T *object 2438230557Sjimharris) 2439230557Sjimharris{ 2440230557Sjimharris SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object; 2441230557Sjimharris 2442230557Sjimharris SET_STATE_HANDLER( 2443230557Sjimharris this_request, 2444230557Sjimharris scic_sds_stp_request_started_soft_reset_substate_handler_table, 2445230557Sjimharris SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE 2446230557Sjimharris ); 2447230557Sjimharris 2448230557Sjimharris scic_sds_remote_device_set_working_request( 2449230557Sjimharris this_request->target_device, this_request 2450230557Sjimharris ); 2451230557Sjimharris} 2452230557Sjimharris 2453230557Sjimharrisstatic 2454230557Sjimharrisvoid scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_completion_enter( 2455230557Sjimharris SCI_BASE_OBJECT_T *object 2456230557Sjimharris) 2457230557Sjimharris{ 2458230557Sjimharris SCI_STATUS status; 2459230557Sjimharris SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object; 2460230557Sjimharris SATA_FIS_REG_H2D_T *h2d_fis; 2461230557Sjimharris SCU_TASK_CONTEXT_T *task_context; 2462230557Sjimharris 2463230557Sjimharris // Clear the SRST bit 2464230557Sjimharris h2d_fis = scic_stp_io_request_get_h2d_reg_address(this_request); 2465230557Sjimharris h2d_fis->control = 0; 2466230557Sjimharris 2467230557Sjimharris // Clear the TC control bit 2468230557Sjimharris task_context = scic_sds_controller_get_task_context_buffer( 2469230557Sjimharris this_request->owning_controller, this_request->io_tag); 2470230557Sjimharris task_context->control_frame = 0; 2471230557Sjimharris 2472230557Sjimharris status = this_request->owning_controller->state_handlers->parent.continue_io_handler( 2473230557Sjimharris &this_request->owning_controller->parent, 2474230557Sjimharris &this_request->target_device->parent, 2475230557Sjimharris &this_request->parent 2476230557Sjimharris ); 2477230557Sjimharris 2478230557Sjimharris if (status == SCI_SUCCESS) 2479230557Sjimharris { 2480230557Sjimharris SET_STATE_HANDLER( 2481230557Sjimharris this_request, 2482230557Sjimharris scic_sds_stp_request_started_soft_reset_substate_handler_table, 2483230557Sjimharris SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE 2484230557Sjimharris ); 2485230557Sjimharris } 2486230557Sjimharris} 2487230557Sjimharris 2488230557Sjimharrisstatic 2489230557Sjimharrisvoid scic_sds_stp_request_started_soft_reset_await_d2h_response_enter( 2490230557Sjimharris SCI_BASE_OBJECT_T *object 2491230557Sjimharris) 2492230557Sjimharris{ 2493230557Sjimharris SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object; 2494230557Sjimharris 2495230557Sjimharris SET_STATE_HANDLER( 2496230557Sjimharris this_request, 2497230557Sjimharris scic_sds_stp_request_started_soft_reset_substate_handler_table, 2498230557Sjimharris SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE 2499230557Sjimharris ); 2500230557Sjimharris} 2501230557Sjimharris 2502230557Sjimharris// --------------------------------------------------------------------------- 2503230557Sjimharris 2504230557SjimharrisSCI_BASE_STATE_T 2505230557Sjimharris scic_sds_stp_request_started_soft_reset_substate_table 2506230557Sjimharris [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_MAX_SUBSTATES] = 2507230557Sjimharris{ 2508230557Sjimharris { 2509230557Sjimharris SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE, 2510230557Sjimharris scic_sds_stp_request_started_soft_reset_await_h2d_asserted_completion_enter, 2511230557Sjimharris NULL 2512230557Sjimharris }, 2513230557Sjimharris { 2514230557Sjimharris SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE, 2515230557Sjimharris scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_completion_enter, 2516230557Sjimharris NULL 2517230557Sjimharris }, 2518230557Sjimharris { 2519230557Sjimharris SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE, 2520230557Sjimharris scic_sds_stp_request_started_soft_reset_await_d2h_response_enter, 2521230557Sjimharris NULL 2522230557Sjimharris } 2523230557Sjimharris}; 2524230557Sjimharris 2525230557Sjimharris// --------------------------------------------------------------------------- 2526230557Sjimharris 2527230557SjimharrisSCI_STATUS scic_io_request_construct_basic_sata( 2528230557Sjimharris SCI_IO_REQUEST_HANDLE_T scic_io_request 2529230557Sjimharris) 2530230557Sjimharris{ 2531230557Sjimharris SCI_STATUS status; 2532230557Sjimharris SCIC_SDS_REQUEST_T * request = (SCIC_SDS_REQUEST_T *)scic_io_request; 2533230557Sjimharris 2534230557Sjimharris SCIC_LOG_TRACE(( 2535230557Sjimharris sci_base_object_get_logger(scic_io_request), 2536230557Sjimharris SCIC_LOG_OBJECT_STP_IO_REQUEST, 2537230557Sjimharris "scic_io_request_construct_basic_sata(0x%x) enter\n", 2538230557Sjimharris scic_io_request 2539230557Sjimharris )); 2540230557Sjimharris 2541230557Sjimharris status = scic_sds_io_request_construct_sata( 2542230557Sjimharris request, 2543230557Sjimharris scic_cb_request_get_sat_protocol(request->user_request), 2544230557Sjimharris scic_cb_io_request_get_transfer_length(request->user_request), 2545230557Sjimharris scic_cb_io_request_get_data_direction(request->user_request), 2546230557Sjimharris scic_cb_io_request_do_copy_rx_frames(request->user_request), 2547230557Sjimharris TRUE 2548230557Sjimharris ); 2549230557Sjimharris 2550230557Sjimharris return status; 2551230557Sjimharris} 2552230557Sjimharris 2553230557Sjimharris// --------------------------------------------------------------------------- 2554230557Sjimharris 2555230557SjimharrisSCI_STATUS scic_io_request_construct_advanced_sata( 2556230557Sjimharris SCI_IO_REQUEST_HANDLE_T scic_io_request, 2557230557Sjimharris SCIC_IO_SATA_PARAMETERS_T * io_parameters 2558230557Sjimharris) 2559230557Sjimharris{ 2560230557Sjimharris SCI_STATUS status; 2561230557Sjimharris SCIC_SDS_REQUEST_T * request = (SCIC_SDS_REQUEST_T *)scic_io_request; 2562230557Sjimharris 2563230557Sjimharris SCIC_LOG_TRACE(( 2564230557Sjimharris sci_base_object_get_logger(scic_io_request), 2565230557Sjimharris SCIC_LOG_OBJECT_STP_IO_REQUEST, 2566230557Sjimharris "scic_io_request_construct_basic_sata(0x%x) enter\n", 2567230557Sjimharris scic_io_request 2568230557Sjimharris )); 2569230557Sjimharris 2570230557Sjimharris status = scic_sds_io_request_construct_sata( 2571230557Sjimharris request, 2572230557Sjimharris scic_cb_request_get_sat_protocol(request->user_request), 2573230557Sjimharris scic_sds_request_get_sgl_element_pair(request, 0)->A.length, 2574230557Sjimharris scic_cb_io_request_get_data_direction(request->user_request), 2575230557Sjimharris scic_cb_io_request_do_copy_rx_frames(request->user_request), 2576230557Sjimharris io_parameters->do_translate_sgl 2577230557Sjimharris ); 2578230557Sjimharris 2579230557Sjimharris return status; 2580230557Sjimharris} 2581230557Sjimharris 2582