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: releng/10.3/sys/dev/isci/scil/scif_sas_remote_device.c 231137 2012-02-07 17:45:11Z jimharris $"); 55230557Sjimharris 56230557Sjimharris/** 57230557Sjimharris * @file 58230557Sjimharris * 59230557Sjimharris * @brief This file contains the implementation of the SCIF_SAS_REMOTE_DEVICE 60230557Sjimharris * object. 61230557Sjimharris */ 62230557Sjimharris 63230557Sjimharris 64230557Sjimharris#include <dev/isci/scil/scic_remote_device.h> 65230557Sjimharris#include <dev/isci/scil/scic_port.h> 66230557Sjimharris#include <dev/isci/scil/scic_user_callback.h> 67230557Sjimharris 68230557Sjimharris#include <dev/isci/scil/scif_sas_logger.h> 69230557Sjimharris#include <dev/isci/scil/scif_sas_remote_device.h> 70230557Sjimharris#include <dev/isci/scil/scif_sas_stp_remote_device.h> 71230557Sjimharris#include <dev/isci/scil/scif_sas_domain.h> 72230557Sjimharris#include <dev/isci/scil/scif_sas_controller.h> 73230557Sjimharris#include <dev/isci/scil/sci_controller.h> 74230557Sjimharris#include <dev/isci/scil/sci_util.h> 75230557Sjimharris 76230557Sjimharris 77230557Sjimharris//****************************************************************************** 78230557Sjimharris//* P U B L I C M E T H O D S 79230557Sjimharris//****************************************************************************** 80230557Sjimharris 81230557SjimharrisU32 scif_remote_device_get_object_size( 82230557Sjimharris void 83230557Sjimharris) 84230557Sjimharris{ 85230557Sjimharris return ( sizeof(SCIF_SAS_REMOTE_DEVICE_T) 86230557Sjimharris + scic_remote_device_get_object_size() ); 87230557Sjimharris} 88230557Sjimharris 89230557Sjimharris// --------------------------------------------------------------------------- 90230557Sjimharris 91230557Sjimharrisvoid scif_remote_device_construct( 92230557Sjimharris SCI_DOMAIN_HANDLE_T domain, 93230557Sjimharris void * remote_device_memory, 94230557Sjimharris SCI_REMOTE_DEVICE_HANDLE_T * new_scif_remote_device_handle 95230557Sjimharris) 96230557Sjimharris{ 97230557Sjimharris SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T *) domain; 98230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *) 99230557Sjimharris remote_device_memory; 100230557Sjimharris 101230557Sjimharris SCIF_LOG_TRACE(( 102230557Sjimharris sci_base_object_get_logger(fw_domain), 103230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE, 104230557Sjimharris "scif_remote_device_construct(0x%x, 0x%x, 0x%x) enter\n", 105230557Sjimharris domain, remote_device_memory, new_scif_remote_device_handle 106230557Sjimharris )); 107230557Sjimharris 108230557Sjimharris memset(remote_device_memory, 0, sizeof(SCIF_SAS_REMOTE_DEVICE_T)); 109230557Sjimharris 110230557Sjimharris // The user's handle to the remote device evaluates to the memory 111230557Sjimharris // address where the remote device object is stored. 112230557Sjimharris *new_scif_remote_device_handle = remote_device_memory; 113230557Sjimharris 114230557Sjimharris fw_device->domain = fw_domain; 115230557Sjimharris fw_device->destruct_when_stopped = FALSE; 116230557Sjimharris //fw_device->parent.is_failed = FALSE; 117230557Sjimharris fw_device->operation_status = SCI_SUCCESS; 118230557Sjimharris fw_device->request_count = 0; 119230557Sjimharris fw_device->task_request_count = 0; 120230557Sjimharris fw_device->is_currently_discovered = TRUE; 121230557Sjimharris fw_device->containing_device = NULL; 122230557Sjimharris fw_device->device_port_width = 1; 123230557Sjimharris fw_device->expander_phy_identifier = 0; 124230557Sjimharris fw_device->destination_state = 125230557Sjimharris SCIF_SAS_REMOTE_DEVICE_DESTINATION_STATE_UNSPECIFIED; 126230557Sjimharris fw_device->ea_target_reset_request_scheduled = NULL; 127230557Sjimharris 128230557Sjimharris // Construct the base object first in order to ensure logging can 129230557Sjimharris // function. 130230557Sjimharris sci_base_remote_device_construct( 131230557Sjimharris &fw_device->parent, 132230557Sjimharris sci_base_object_get_logger(fw_domain), 133230557Sjimharris scif_sas_remote_device_state_table 134230557Sjimharris ); 135230557Sjimharris 136230557Sjimharris sci_base_state_machine_construct( 137230557Sjimharris &fw_device->starting_substate_machine, 138230557Sjimharris &fw_device->parent.parent, 139230557Sjimharris scif_sas_remote_device_starting_substate_table, 140230557Sjimharris SCIF_SAS_REMOTE_DEVICE_STARTING_SUBSTATE_AWAIT_COMPLETE 141230557Sjimharris ); 142230557Sjimharris 143230557Sjimharris sci_base_state_machine_construct( 144230557Sjimharris &fw_device->ready_substate_machine, 145230557Sjimharris &fw_device->parent.parent, 146230557Sjimharris scif_sas_remote_device_ready_substate_table, 147230557Sjimharris SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_OPERATIONAL 148230557Sjimharris ); 149230557Sjimharris 150230557Sjimharris scif_sas_remote_device_initialize_state_logging(fw_device); 151230557Sjimharris 152230557Sjimharris scic_remote_device_construct( 153230557Sjimharris fw_domain->core_object, 154230557Sjimharris ((U8*) remote_device_memory) + sizeof(SCIF_SAS_REMOTE_DEVICE_T), 155230557Sjimharris &fw_device->core_object 156230557Sjimharris ); 157230557Sjimharris 158230557Sjimharris // Set the association in the core object, so that we are able to 159230557Sjimharris // determine our framework remote device object from the core remote 160230557Sjimharris // device. 161230557Sjimharris sci_object_set_association(fw_device->core_object, fw_device); 162230557Sjimharris} 163230557Sjimharris 164230557Sjimharris// --------------------------------------------------------------------------- 165230557Sjimharris 166230557SjimharrisSCI_STATUS scif_remote_device_da_construct( 167230557Sjimharris SCI_REMOTE_DEVICE_HANDLE_T remote_device, 168230557Sjimharris SCI_SAS_ADDRESS_T * sas_address, 169230557Sjimharris SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS_T * protocols 170230557Sjimharris) 171230557Sjimharris{ 172230557Sjimharris SCI_STATUS status = SCI_SUCCESS; 173230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *) 174230557Sjimharris remote_device; 175230557Sjimharris 176230557Sjimharris SCIF_LOG_TRACE(( 177230557Sjimharris sci_base_object_get_logger(fw_device), 178230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE, 179230557Sjimharris "scif_remote_device_da_construct(0x%x, 0x%x, 0x%x) enter\n", 180230557Sjimharris remote_device, sas_address, protocols 181230557Sjimharris )); 182230557Sjimharris 183230557Sjimharris // Make sure the device hasn't already been constructed and added 184230557Sjimharris // to the domain. 185230557Sjimharris if (scif_domain_get_device_by_sas_address(fw_device->domain, sas_address) 186230557Sjimharris == SCI_INVALID_HANDLE) 187230557Sjimharris { 188230557Sjimharris SCIC_PORT_PROPERTIES_T properties; 189230557Sjimharris 190230557Sjimharris scic_port_get_properties(fw_device->domain->core_object, &properties); 191230557Sjimharris 192230557Sjimharris // Check to see if this is the direct attached device. 193230557Sjimharris if ( (sas_address->low == properties.remote.sas_address.low) 194230557Sjimharris && (sas_address->high == properties.remote.sas_address.high) ) 195230557Sjimharris { 196230557Sjimharris //Get accurate port width from port's phy mask for a DA device. 197230557Sjimharris SCI_GET_BITS_SET_COUNT(properties.phy_mask, fw_device->device_port_width); 198230557Sjimharris 199230557Sjimharris status = scic_remote_device_da_construct(fw_device->core_object); 200230557Sjimharris } 201230557Sjimharris else 202230557Sjimharris // Don't allow the user to construct a direct attached device 203230557Sjimharris // if it's not a direct attached device. 204230557Sjimharris status = SCI_FAILURE_UNSUPPORTED_PROTOCOL; 205230557Sjimharris } 206230557Sjimharris else 207230557Sjimharris status = SCI_FAILURE_DEVICE_EXISTS; 208230557Sjimharris 209230557Sjimharris if (status == SCI_SUCCESS) 210230557Sjimharris { 211230557Sjimharris // Add the device to the domain list. 212230557Sjimharris sci_abstract_list_pushback( 213230557Sjimharris &fw_device->domain->remote_device_list, fw_device 214230557Sjimharris ); 215230557Sjimharris 216230557Sjimharris // If a SATA/STP device is connected, then construct it. 217230557Sjimharris if (protocols->u.bits.stp_target) 218230557Sjimharris scif_sas_stp_remote_device_construct(fw_device); 219230557Sjimharris else if (protocols->u.bits.smp_target) 220230557Sjimharris scif_sas_smp_remote_device_construct(fw_device); 221230557Sjimharris 222230557Sjimharris SCIF_LOG_INFO(( 223230557Sjimharris sci_base_object_get_logger(fw_device), 224230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 225230557Sjimharris "Domain:0x%x SasAddress:0x%x,0x%x remote device constructed\n", 226230557Sjimharris fw_device->domain, sas_address->low, sas_address->high 227230557Sjimharris )); 228230557Sjimharris 229230557Sjimharris status = fw_device->state_handlers->parent.start_handler( 230230557Sjimharris &fw_device->parent 231230557Sjimharris ); 232230557Sjimharris } 233230557Sjimharris else 234230557Sjimharris { 235230557Sjimharris SCIF_LOG_WARNING(( 236230557Sjimharris sci_base_object_get_logger(fw_device), 237230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 238230557Sjimharris "Domain:0x%x SasAddress:0x%x,0x%x Status:0x%x remote device construct failure\n", 239230557Sjimharris fw_device->domain, sas_address->low, sas_address->high, status 240230557Sjimharris )); 241230557Sjimharris } 242230557Sjimharris 243230557Sjimharris return status; 244230557Sjimharris} 245230557Sjimharris 246230557Sjimharris// --------------------------------------------------------------------------- 247230557Sjimharris 248230557SjimharrisSCI_STATUS scif_remote_device_ea_construct( 249230557Sjimharris SCI_REMOTE_DEVICE_HANDLE_T remote_device, 250230557Sjimharris SCI_REMOTE_DEVICE_HANDLE_T containing_device, 251230557Sjimharris SMP_RESPONSE_DISCOVER_T * smp_response 252230557Sjimharris) 253230557Sjimharris{ 254230557Sjimharris SCI_SAS_ADDRESS_T * sas_address; 255230557Sjimharris SCI_STATUS status = SCI_SUCCESS; 256230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *) 257230557Sjimharris remote_device; 258230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_smp_device = (SCIF_SAS_REMOTE_DEVICE_T *) 259230557Sjimharris containing_device; 260230557Sjimharris 261230557Sjimharris fw_device->containing_device = fw_smp_device; 262230557Sjimharris fw_device->expander_phy_identifier = 263230557Sjimharris fw_smp_device->protocol_device.smp_device.current_activity_phy_index; 264230557Sjimharris 265230557Sjimharris sas_address = &smp_response->attached_sas_address; 266230557Sjimharris 267230557Sjimharris SCIF_LOG_TRACE(( 268230557Sjimharris sci_base_object_get_logger(fw_device), 269230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE, 270230557Sjimharris "scif_remote_device_ea_construct(0x%x, 0x%x) enter\n", 271230557Sjimharris remote_device, smp_response 272230557Sjimharris )); 273230557Sjimharris 274230557Sjimharris // Make sure the device hasn't already been constructed and added 275230557Sjimharris // to the domain. 276230557Sjimharris if (scif_domain_get_device_by_sas_address(fw_device->domain, sas_address) 277230557Sjimharris == SCI_INVALID_HANDLE) 278230557Sjimharris { 279230557Sjimharris //for sata device, we need another routine. likely 280230557Sjimharris //scif_remote_device_ea_sata_construct. 281230557Sjimharris status = scic_remote_device_ea_construct(fw_device->core_object, smp_response); 282230557Sjimharris } 283230557Sjimharris else 284230557Sjimharris status = SCI_FAILURE_DEVICE_EXISTS; 285230557Sjimharris 286230557Sjimharris if (status == SCI_SUCCESS) 287230557Sjimharris { 288230557Sjimharris // Add the device to the domain list. 289230557Sjimharris sci_abstract_list_pushback( 290230557Sjimharris &fw_device->domain->remote_device_list, fw_device 291230557Sjimharris ); 292230557Sjimharris 293230557Sjimharris if (smp_response->protocols.u.bits.attached_smp_target) 294230557Sjimharris scif_sas_smp_remote_device_construct(fw_device); 295230557Sjimharris else if (smp_response->protocols.u.bits.attached_stp_target) 296230557Sjimharris scif_sas_stp_remote_device_construct(fw_device); 297230557Sjimharris 298230557Sjimharris SCIF_LOG_INFO(( 299230557Sjimharris sci_base_object_get_logger(fw_device), 300230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 301230557Sjimharris "Domain:0x%x SasAddress:0x%x,0x%x remote device constructed\n", 302230557Sjimharris fw_device->domain, sas_address->low, sas_address->high 303230557Sjimharris )); 304230557Sjimharris 305230557Sjimharris //only start the device if the device is not a SATA disk on SPINUP_HOLD state. 306230557Sjimharris if ( scic_remote_device_get_connection_rate(fw_device->core_object) != 307230557Sjimharris SCI_SATA_SPINUP_HOLD ) 308230557Sjimharris { 309230557Sjimharris status = fw_device->state_handlers->parent.start_handler( 310230557Sjimharris &fw_device->parent 311230557Sjimharris ); 312230557Sjimharris } 313230557Sjimharris } 314230557Sjimharris else 315230557Sjimharris { 316230557Sjimharris SCIF_LOG_WARNING(( 317230557Sjimharris sci_base_object_get_logger(fw_device), 318230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 319230557Sjimharris "Domain:0x%x SasAddress:0x%x,0x%x Status:0x%x remote device construct failure\n", 320230557Sjimharris fw_device->domain, sas_address->low, sas_address->high, status 321230557Sjimharris )); 322230557Sjimharris } 323230557Sjimharris 324230557Sjimharris return status; 325230557Sjimharris} 326230557Sjimharris 327230557Sjimharris// --------------------------------------------------------------------------- 328230557Sjimharris 329230557SjimharrisSCI_STATUS scif_remote_device_destruct( 330230557Sjimharris SCI_REMOTE_DEVICE_HANDLE_T remote_device 331230557Sjimharris) 332230557Sjimharris{ 333230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*) 334230557Sjimharris remote_device; 335230557Sjimharris 336230557Sjimharris SCIF_LOG_TRACE(( 337230557Sjimharris sci_base_object_get_logger(fw_device), 338230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE, 339230557Sjimharris "scif_remote_device_destruct(0x%x) enter\n", 340230557Sjimharris remote_device 341230557Sjimharris )); 342230557Sjimharris 343230557Sjimharris //remove the device from domain's remote_device_list 344230557Sjimharris fw_device->domain->state_handlers->device_destruct_handler( 345230557Sjimharris &fw_device->domain->parent, &fw_device->parent 346230557Sjimharris ); 347230557Sjimharris 348230557Sjimharris // The destruct process may not complete immediately, since the core 349230557Sjimharris // remote device likely needs to be stopped first. However, the user 350230557Sjimharris // is not given a callback notification for destruction. 351230557Sjimharris return fw_device->state_handlers->parent.destruct_handler( 352230557Sjimharris &fw_device->parent 353230557Sjimharris ); 354230557Sjimharris} 355230557Sjimharris 356230557Sjimharris// --------------------------------------------------------------------------- 357230557Sjimharris 358230557SjimharrisSCI_REMOTE_DEVICE_HANDLE_T scif_remote_device_get_scic_handle( 359230557Sjimharris SCI_REMOTE_DEVICE_HANDLE_T scif_remote_device 360230557Sjimharris) 361230557Sjimharris{ 362230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*) 363230557Sjimharris scif_remote_device; 364230557Sjimharris 365231137Sjimharris if ( (fw_device == NULL) || (fw_device->core_object == SCI_INVALID_HANDLE) ) 366231137Sjimharris return SCI_INVALID_HANDLE; 367230557Sjimharris 368230557Sjimharris SCIF_LOG_WARNING(( 369230557Sjimharris sci_base_object_get_logger(fw_device), 370230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE, 371230557Sjimharris "RemoteDevice:0x%x no associated core device found\n", 372230557Sjimharris fw_device 373230557Sjimharris )); 374230557Sjimharris 375231137Sjimharris return fw_device->core_object; 376230557Sjimharris} 377230557Sjimharris 378230557Sjimharris// --------------------------------------------------------------------------- 379230557Sjimharris 380230557Sjimharrisvoid scic_cb_remote_device_start_complete( 381230557Sjimharris SCI_CONTROLLER_HANDLE_T controller, 382230557Sjimharris SCI_REMOTE_DEVICE_HANDLE_T remote_device, 383230557Sjimharris SCI_STATUS completion_status 384230557Sjimharris) 385230557Sjimharris{ 386230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*) 387230557Sjimharris sci_object_get_association(remote_device); 388230557Sjimharris 389230557Sjimharris SCIF_LOG_TRACE(( 390230557Sjimharris sci_base_object_get_logger(fw_device), 391230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_REMOTE_DEVICE_CONFIG, 392230557Sjimharris "scic_cb_remote_device_start_complete(0x%x, 0x%x, 0x%x) enter\n", 393230557Sjimharris controller, remote_device, completion_status 394230557Sjimharris )); 395230557Sjimharris 396230557Sjimharris fw_device->state_handlers->start_complete_handler( 397230557Sjimharris fw_device, completion_status 398230557Sjimharris ); 399230557Sjimharris} 400230557Sjimharris 401230557Sjimharris// --------------------------------------------------------------------------- 402230557Sjimharris 403230557Sjimharrisvoid scic_cb_remote_device_stop_complete( 404230557Sjimharris SCI_CONTROLLER_HANDLE_T controller, 405230557Sjimharris SCI_REMOTE_DEVICE_HANDLE_T remote_device, 406230557Sjimharris SCI_STATUS completion_status 407230557Sjimharris) 408230557Sjimharris{ 409230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*) 410230557Sjimharris sci_object_get_association(remote_device); 411230557Sjimharris 412230557Sjimharris SCIF_LOG_TRACE(( 413230557Sjimharris sci_base_object_get_logger(fw_device), 414230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_REMOTE_DEVICE_CONFIG, 415230557Sjimharris "scic_cb_remote_device_stop_complete(0x%x, 0x%x, 0x%x) enter\n", 416230557Sjimharris controller, remote_device, completion_status 417230557Sjimharris )); 418230557Sjimharris 419230557Sjimharris fw_device->state_handlers->stop_complete_handler( 420230557Sjimharris fw_device, completion_status 421230557Sjimharris ); 422230557Sjimharris} 423230557Sjimharris 424230557Sjimharris// --------------------------------------------------------------------------- 425230557Sjimharris 426230557Sjimharrisvoid scic_cb_remote_device_ready( 427230557Sjimharris SCI_CONTROLLER_HANDLE_T controller, 428230557Sjimharris SCI_REMOTE_DEVICE_HANDLE_T remote_device 429230557Sjimharris) 430230557Sjimharris{ 431230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*) 432230557Sjimharris sci_object_get_association(remote_device); 433230557Sjimharris 434230557Sjimharris fw_device->state_handlers->ready_handler(fw_device); 435230557Sjimharris} 436230557Sjimharris 437230557Sjimharris// --------------------------------------------------------------------------- 438230557Sjimharris 439230557Sjimharrisvoid scic_cb_remote_device_not_ready( 440230557Sjimharris SCI_CONTROLLER_HANDLE_T controller, 441230557Sjimharris SCI_REMOTE_DEVICE_HANDLE_T remote_device, 442230557Sjimharris U32 reason_code 443230557Sjimharris) 444230557Sjimharris{ 445230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*) 446230557Sjimharris sci_object_get_association(remote_device); 447230557Sjimharris 448230557Sjimharris fw_device->state_handlers->not_ready_handler(fw_device,reason_code); 449230557Sjimharris} 450230557Sjimharris 451230557Sjimharris// --------------------------------------------------------------------------- 452230557Sjimharris 453230557SjimharrisU16 scif_remote_device_get_max_queue_depth( 454230557Sjimharris SCI_REMOTE_DEVICE_HANDLE_T remote_device 455230557Sjimharris) 456230557Sjimharris{ 457230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*) 458230557Sjimharris remote_device; 459230557Sjimharris SMP_DISCOVER_RESPONSE_PROTOCOLS_T protocols; 460230557Sjimharris 461230557Sjimharris scic_remote_device_get_protocols(fw_device->core_object, &protocols); 462230557Sjimharris 463230557Sjimharris // If the target is a SATA/STP target, then determine the queue depth 464230557Sjimharris // for either NCQ or for UDMA. 465230557Sjimharris if (protocols.u.bits.attached_stp_target) 466230557Sjimharris { 467230557Sjimharris if (fw_device->protocol_device.stp_device.sati_device.capabilities 468230557Sjimharris & SATI_DEVICE_CAP_NCQ_SUPPORTED_ENABLE) 469230557Sjimharris { 470230557Sjimharris return fw_device->protocol_device.stp_device.sati_device.ncq_depth; 471230557Sjimharris } 472230557Sjimharris else 473230557Sjimharris { 474230557Sjimharris // At the moment, we only allow a single UDMA request to be queued. 475230557Sjimharris return 1; 476230557Sjimharris } 477230557Sjimharris } 478230557Sjimharris 479230557Sjimharris // For SSP devices return a no maximum queue depth supported. 480230557Sjimharris return SCIF_REMOTE_DEVICE_NO_MAX_QUEUE_DEPTH; 481230557Sjimharris} 482230557Sjimharris 483230557Sjimharris// --------------------------------------------------------------------------- 484230557Sjimharris 485230557SjimharrisSCI_STATUS scif_remote_device_get_containing_device( 486230557Sjimharris SCI_REMOTE_DEVICE_HANDLE_T remote_device, 487230557Sjimharris SCI_REMOTE_DEVICE_HANDLE_T * containing_device 488230557Sjimharris) 489230557Sjimharris{ 490230557Sjimharris SCI_STATUS status = SCI_FAILURE; 491230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * this_device = (SCIF_SAS_REMOTE_DEVICE_T *) 492230557Sjimharris remote_device; 493230557Sjimharris 494230557Sjimharris if ( (this_device != NULL) && (containing_device != NULL) ) 495230557Sjimharris { 496230557Sjimharris *containing_device = (SCI_REMOTE_DEVICE_HANDLE_T)(this_device->containing_device); 497230557Sjimharris if (*containing_device != NULL) 498230557Sjimharris { 499230557Sjimharris status = SCI_SUCCESS; 500230557Sjimharris } 501230557Sjimharris } 502230557Sjimharris 503230557Sjimharris return status; 504230557Sjimharris} 505230557Sjimharris 506230557Sjimharris// --------------------------------------------------------------------------- 507230557Sjimharris 508230557SjimharrisU32 scif_remote_device_get_started_io_count( 509230557Sjimharris SCI_REMOTE_DEVICE_HANDLE_T remote_device 510230557Sjimharris) 511230557Sjimharris{ 512230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * this_device = (SCIF_SAS_REMOTE_DEVICE_T *) 513230557Sjimharris remote_device; 514230557Sjimharris 515230557Sjimharris return this_device->request_count - this_device->task_request_count; 516230557Sjimharris} 517230557Sjimharris//****************************************************************************** 518230557Sjimharris//* P R O T E C T E D M E T H O D S 519230557Sjimharris//****************************************************************************** 520230557Sjimharris 521230557Sjimharris/* 522230557Sjimharrisvoid scif_sas_remote_device_failure( 523230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device 524230557Sjimharris) 525230557Sjimharris{ 526230557Sjimharris fw_device->parent.is_failed = TRUE; 527230557Sjimharris sci_base_state_machine_change_state( 528230557Sjimharris &fw_device->parent.state_machine, SCI_BASE_REMOTE_DEVICE_STATE_STOPPING 529230557Sjimharris ); 530230557Sjimharris} 531230557Sjimharris*/ 532230557Sjimharris 533230557Sjimharris 534230557Sjimharris/** 535230557Sjimharris * @brief This method retrieves info from Report Phy Sata response and 536230557Sjimharris * save the additional data for a SATA remote device, if necessary. 537230557Sjimharris * 538230557Sjimharris * @param[in] report_phy_sata_response SMP Report Phy Sata response 539230557Sjimharris * 540230557Sjimharris * @return none 541230557Sjimharris */ 542230557Sjimharrisvoid scif_sas_remote_device_save_report_phy_sata_information( 543230557Sjimharris SMP_RESPONSE_REPORT_PHY_SATA_T * report_phy_sata_response 544230557Sjimharris) 545230557Sjimharris{ 546230557Sjimharris //do nothing currently. Later, if needed, we will search the existed 547230557Sjimharris //remote device by stp_sas_address, then save more information for 548230557Sjimharris //that device off the report_phy_sata_response. This assumes the 549230557Sjimharris //stp_sas_address from report_phy_sata response is the same sas address 550230557Sjimharris //from discover response. 551230557Sjimharris 552230557Sjimharris return; 553230557Sjimharris} 554230557Sjimharris 555230557Sjimharris/** 556230557Sjimharris * @brief This method does target reset for DA or EA remote device. 557230557Sjimharris * 558230557Sjimharris * @param[in] fw_controller, the controller object the target device belongs 559230557Sjimharris * to. 560230557Sjimharris * @param[in] fw_device, the target device to be hard reset. 561230557Sjimharris * @param[in] fw_request, the scif task request object that asked for this 562230557Sjimharris * target reset. 563230557Sjimharris */ 564230557Sjimharrisvoid scif_sas_remote_device_target_reset( 565230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device, 566230557Sjimharris SCIF_SAS_REQUEST_T * fw_request 567230557Sjimharris) 568230557Sjimharris{ 569230557Sjimharris SCIF_LOG_INFO(( 570230557Sjimharris sci_base_object_get_logger(fw_device), 571230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE, 572230557Sjimharris "scif_sas_remote_device_target_reset! fw_device:0x%x fw_request:0x%x\n", 573230557Sjimharris fw_device, fw_request 574230557Sjimharris )); 575230557Sjimharris 576230557Sjimharris if (fw_device->containing_device == NULL) 577230557Sjimharris { 578230557Sjimharris SCI_PORT_HANDLE_T port; 579230557Sjimharris 580230557Sjimharris port = scif_domain_get_scic_port_handle(fw_device->domain); 581230557Sjimharris 582230557Sjimharris //Direct attached device target reset. 583230557Sjimharris //calling core to do port reset. The fw_request will not be used here. 584230557Sjimharris scic_port_hard_reset( 585230557Sjimharris port, 586230557Sjimharris scic_remote_device_get_suggested_reset_timeout(fw_device->core_object) 587230557Sjimharris ); 588230557Sjimharris } 589230557Sjimharris else 590230557Sjimharris { //Expander attached device target reset. 591230557Sjimharris 592230557Sjimharris if ( fw_device->containing_device->protocol_device.smp_device.current_activity 593230557Sjimharris == SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_TARGET_RESET ) 594230557Sjimharris { 595230557Sjimharris //The containing expander is in the middle of target resetting other of its 596230557Sjimharris //remote disks. Flag this remote device to be target reset later. 597230557Sjimharris SCIF_LOG_INFO(( 598230557Sjimharris sci_base_object_get_logger(fw_device), 599230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE, 600230557Sjimharris "scif_sas_remote_device_target_reset DELAYED! fw_device:0x%x fw_request:0x%x\n", 601230557Sjimharris fw_device, fw_request 602230557Sjimharris )); 603230557Sjimharris 604230557Sjimharris fw_device->ea_target_reset_request_scheduled = fw_request; 605230557Sjimharris return; 606230557Sjimharris } 607230557Sjimharris 608230557Sjimharris //set current_activity and current_smp_request to expander device. 609230557Sjimharris scif_sas_smp_remote_device_start_target_reset( 610230557Sjimharris fw_device->containing_device, fw_device, fw_request); 611230557Sjimharris } 612230557Sjimharris 613230557Sjimharris scic_remote_device_reset(fw_device->core_object); 614230557Sjimharris} 615230557Sjimharris 616230557Sjimharris 617230557Sjimharris/** 618230557Sjimharris * @brief This method completes target reset for DA or EA remote device. 619230557Sjimharris * 620230557Sjimharris * @param[in] fw_device, the target device to be hard reset. 621230557Sjimharris * @param[in] fw_request, the scif task request object that asked for this 622230557Sjimharris * target reset. 623230557Sjimharris * @param[in] completion_status 624230557Sjimharris */ 625230557Sjimharrisvoid scif_sas_remote_device_target_reset_complete( 626230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device, 627230557Sjimharris SCIF_SAS_REQUEST_T * fw_request, 628230557Sjimharris SCI_STATUS completion_status 629230557Sjimharris) 630230557Sjimharris{ 631230557Sjimharris SCIF_LOG_INFO(( 632230557Sjimharris sci_base_object_get_logger(fw_device), 633230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE, 634230557Sjimharris "scif_sas_remote_device_target_reset_complete! " 635230557Sjimharris "fw_device:0x%x fw_request:0x%x completion_status 0x%x\n", 636230557Sjimharris fw_device, fw_request, completion_status 637230557Sjimharris )); 638230557Sjimharris 639230557Sjimharris scif_cb_task_request_complete( 640230557Sjimharris fw_device->domain->controller, 641230557Sjimharris fw_device, 642230557Sjimharris fw_request, 643230557Sjimharris (SCI_TASK_STATUS) completion_status 644230557Sjimharris ); 645230557Sjimharris 646230557Sjimharris scic_remote_device_reset_complete(fw_device->core_object); 647230557Sjimharris 648230557Sjimharris //For expander attached device done target reset. 649230557Sjimharris if (fw_device->containing_device != NULL) 650230557Sjimharris { 651230557Sjimharris //search for all the devices in the domain to find other remote devices 652230557Sjimharris //needs to be target reset. 653230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * next_device; 654230557Sjimharris 655230557Sjimharris scif_sas_smp_remote_device_clear(fw_device->containing_device); 656230557Sjimharris 657230557Sjimharris if( (next_device = scif_sas_domain_find_next_ea_target_reset(fw_device->domain)) 658230557Sjimharris != NULL ) 659230557Sjimharris { 660230557Sjimharris scif_sas_smp_remote_device_start_target_reset( 661230557Sjimharris next_device->containing_device, 662230557Sjimharris next_device, 663230557Sjimharris next_device->ea_target_reset_request_scheduled 664230557Sjimharris ); 665230557Sjimharris 666230557Sjimharris next_device->ea_target_reset_request_scheduled = NULL; 667230557Sjimharris } 668230557Sjimharris else 669230557Sjimharris { 670230557Sjimharris //if the domain is in the DISCOVER state, we should resume the DISCOVER. 671230557Sjimharris if (fw_device->domain->parent.state_machine.current_state_id == 672230557Sjimharris SCI_BASE_DOMAIN_STATE_DISCOVERING) 673230557Sjimharris { 674230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * top_expander = fw_device->containing_device; 675230557Sjimharris 676230557Sjimharris while(top_expander->containing_device != NULL) 677230557Sjimharris top_expander = top_expander->containing_device; 678230557Sjimharris 679230557Sjimharris scif_sas_domain_start_smp_discover(fw_device->domain, top_expander); 680230557Sjimharris } 681230557Sjimharris else 682230557Sjimharris { 683230557Sjimharris //Tell driver to kick off Discover process. If the domain is already 684230557Sjimharris //in Discovery state, this discovery requst will not be carried on. 685230557Sjimharris scif_cb_domain_change_notification( 686230557Sjimharris fw_device->domain->controller, fw_device->domain ); 687230557Sjimharris } 688230557Sjimharris } 689230557Sjimharris } 690230557Sjimharris else 691230557Sjimharris { 692230557Sjimharris //Tell driver to kick off Discover process. If the domain is already 693230557Sjimharris //in Discovery state, this discovery requst will not be carried on. 694230557Sjimharris scif_cb_domain_change_notification( 695230557Sjimharris fw_device->domain->controller, fw_device->domain ); 696230557Sjimharris } 697230557Sjimharris} 698230557Sjimharris 699230557Sjimharris#if !defined(DISABLE_WIDE_PORTED_TARGETS) 700230557SjimharrisSCI_STATUS scif_sas_remote_device_update_port_width( 701230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device, 702230557Sjimharris U8 new_port_width 703230557Sjimharris) 704230557Sjimharris{ 705230557Sjimharris SCIF_LOG_INFO(( 706230557Sjimharris sci_base_object_get_logger(fw_device), 707230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE, 708230557Sjimharris "scif_sas_remote_device_update_port_width (0x%x, 0x%x) enter\n", 709230557Sjimharris fw_device, new_port_width 710230557Sjimharris )); 711230557Sjimharris 712230557Sjimharris fw_device->device_port_width = new_port_width; 713230557Sjimharris 714230557Sjimharris //Don't Start a new update of port width if a device is already in 715230557Sjimharris //UPDATING PORT WIDTH state. 716230557Sjimharris if (fw_device->parent.state_machine.current_state_id == SCI_BASE_REMOTE_DEVICE_STATE_READY) 717230557Sjimharris { 718230557Sjimharris if (fw_device->device_port_width != 0) 719230557Sjimharris { 720230557Sjimharris //Change state to UPDATING_PORT_WIDTH 721230557Sjimharris sci_base_state_machine_change_state( 722230557Sjimharris &fw_device->parent.state_machine, 723230557Sjimharris SCI_BASE_REMOTE_DEVICE_STATE_UPDATING_PORT_WIDTH 724230557Sjimharris ); 725230557Sjimharris } 726230557Sjimharris 727230557Sjimharris return SCI_SUCCESS; 728230557Sjimharris } 729230557Sjimharris else if (fw_device->parent.state_machine.current_state_id == 730230557Sjimharris SCI_BASE_REMOTE_DEVICE_STATE_STARTING) 731230557Sjimharris { 732230557Sjimharris fw_device->destination_state = 733230557Sjimharris SCIF_SAS_REMOTE_DEVICE_DESTINATION_STATE_UPDATING_PORT_WIDTH; 734230557Sjimharris } 735230557Sjimharris 736230557Sjimharris return SCI_FAILURE_INVALID_STATE; 737230557Sjimharris} 738230557Sjimharris#endif //#if !defined(DISABLE_WIDE_PORTED_TARGETS) 739230557Sjimharris 740230557Sjimharris 741230557Sjimharris#ifdef SCI_LOGGING 742230557Sjimharrisvoid scif_sas_remote_device_initialize_state_logging( 743230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * remote_device 744230557Sjimharris) 745230557Sjimharris{ 746230557Sjimharris sci_base_state_machine_logger_initialize( 747230557Sjimharris &remote_device->parent.state_machine_logger, 748230557Sjimharris &remote_device->parent.state_machine, 749230557Sjimharris &remote_device->parent.parent, 750230557Sjimharris scif_cb_logger_log_states, 751230557Sjimharris "SCIF_SAS_REMOTE_DEVICE_T", "base_state_machine", 752230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE 753230557Sjimharris ); 754230557Sjimharris 755230557Sjimharris sci_base_state_machine_logger_initialize( 756230557Sjimharris &remote_device->starting_substate_machine_logger, 757230557Sjimharris &remote_device->starting_substate_machine, 758230557Sjimharris &remote_device->parent.parent, 759230557Sjimharris scif_cb_logger_log_states, 760230557Sjimharris "SCIF_SAS_REMOTE_DEVICE_T", "starting substate machine", 761230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE 762230557Sjimharris ); 763230557Sjimharris 764230557Sjimharris sci_base_state_machine_logger_initialize( 765230557Sjimharris &remote_device->ready_substate_machine_logger, 766230557Sjimharris &remote_device->ready_substate_machine, 767230557Sjimharris &remote_device->parent.parent, 768230557Sjimharris scif_cb_logger_log_states, 769230557Sjimharris "SCIF_SAS_REMOTE_DEVICE_T", "ready substate machine", 770230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE 771230557Sjimharris ); 772230557Sjimharris} 773230557Sjimharris 774230557Sjimharrisvoid scif_sas_remote_device_deinitialize_state_logging( 775230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * remote_device 776230557Sjimharris) 777230557Sjimharris{ 778230557Sjimharris sci_base_state_machine_logger_deinitialize( 779230557Sjimharris &remote_device->parent.state_machine_logger, 780230557Sjimharris &remote_device->parent.state_machine 781230557Sjimharris ); 782230557Sjimharris 783230557Sjimharris sci_base_state_machine_logger_deinitialize( 784230557Sjimharris &remote_device->starting_substate_machine_logger, 785230557Sjimharris &remote_device->starting_substate_machine 786230557Sjimharris ); 787230557Sjimharris 788230557Sjimharris sci_base_state_machine_logger_deinitialize( 789230557Sjimharris &remote_device->ready_substate_machine_logger, 790230557Sjimharris &remote_device->ready_substate_machine 791230557Sjimharris ); 792230557Sjimharris} 793230557Sjimharris#endif // SCI_LOGGING 794230557Sjimharris 795