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/** 57230557Sjimharris * @file 58230557Sjimharris * 59230557Sjimharris * @brief This file contains all of the entrance and exit methods for each 60230557Sjimharris * of the domain states defined by the SCI_BASE_DOMAIN state 61230557Sjimharris * machine. 62230557Sjimharris */ 63230557Sjimharris 64230557Sjimharris#include <dev/isci/scil/intel_sas.h> 65230557Sjimharris#include <dev/isci/scil/scic_port.h> 66230557Sjimharris 67230557Sjimharris#include <dev/isci/scil/scif_sas_logger.h> 68230557Sjimharris#include <dev/isci/scil/scif_sas_domain.h> 69230557Sjimharris#include <dev/isci/scil/scif_sas_controller.h> 70230557Sjimharris#include <dev/isci/scil/scic_controller.h> 71230557Sjimharris 72230557Sjimharris//****************************************************************************** 73230557Sjimharris//* P R O T E C T E D M E T H O D S 74230557Sjimharris//****************************************************************************** 75230557Sjimharris 76230557Sjimharris/** 77230557Sjimharris * @brief This method will attempt to transition to the stopped state. 78230557Sjimharris * The transition will only occur if the criteria for transition is 79230557Sjimharris * met (i.e. all IOs are complete and all devices are stopped). 80230557Sjimharris * 81230557Sjimharris * @param[in] fw_domain This parameter specifies the domain in which to 82230557Sjimharris * to attempt to perform the transition. 83230557Sjimharris * 84230557Sjimharris * @return none 85230557Sjimharris */ 86230557Sjimharrisvoid scif_sas_domain_transition_to_stopped_state( 87230557Sjimharris SCIF_SAS_DOMAIN_T * fw_domain 88230557Sjimharris) 89230557Sjimharris{ 90230557Sjimharris SCIF_LOG_TRACE(( 91230557Sjimharris sci_base_object_get_logger(fw_domain), 92230557Sjimharris SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 93230557Sjimharris "scif_sas_domain_transition_to_stopped_state(0x%x) enter\n", 94230557Sjimharris fw_domain 95230557Sjimharris )); 96230557Sjimharris 97230557Sjimharris // If IOs are quiesced, and all remote devices are stopped, 98230557Sjimharris // then transition directly to the STOPPED state. 99230557Sjimharris if ( (fw_domain->request_list.element_count == 0) 100230557Sjimharris && (fw_domain->device_start_count == 0) ) 101230557Sjimharris { 102230557Sjimharris SCIF_LOG_INFO(( 103230557Sjimharris sci_base_object_get_logger(fw_domain), 104230557Sjimharris SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 105230557Sjimharris "Domain:0x%x immediate transition to STOPPED\n", 106230557Sjimharris fw_domain 107230557Sjimharris )); 108230557Sjimharris 109230557Sjimharris sci_base_state_machine_change_state( 110230557Sjimharris &fw_domain->parent.state_machine, SCI_BASE_DOMAIN_STATE_STOPPED 111230557Sjimharris ); 112230557Sjimharris } 113230557Sjimharris} 114230557Sjimharris 115230557Sjimharris 116230557Sjimharris/** 117230557Sjimharris * @brief This method is called upon entrance to all states where the 118230557Sjimharris * previous state may have been the DISCOVERING state. 119230557Sjimharris * We issue the scif_cb_domain_discovery_complete() notification 120230557Sjimharris * from this method, assuming pre-requisites are met, as opposed 121230557Sjimharris * to in the exit handler of the DISCOVERING state, so that the 122230557Sjimharris * appropriate state handlers are in place should the user decide 123230557Sjimharris * to call scif_domain_discover() again. 124230557Sjimharris * 125230557Sjimharris * @param[in] fw_domain This parameter specifies the domain for which 126230557Sjimharris * the state transition has occurred. 127230557Sjimharris * 128230557Sjimharris * @return none 129230557Sjimharris */ 130230557Sjimharrisstatic 131230557Sjimharrisvoid scif_sas_domain_transition_from_discovering_state( 132230557Sjimharris SCIF_SAS_DOMAIN_T * fw_domain 133230557Sjimharris) 134230557Sjimharris{ 135230557Sjimharris SCIF_LOG_TRACE(( 136230557Sjimharris sci_base_object_get_logger(fw_domain), 137230557Sjimharris SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 138230557Sjimharris "scif_sas_domain_transition_from_discovering_state(0x%x) enter\n", 139230557Sjimharris fw_domain 140230557Sjimharris )); 141230557Sjimharris 142230557Sjimharris if (fw_domain->parent.state_machine.previous_state_id 143230557Sjimharris == SCI_BASE_DOMAIN_STATE_DISCOVERING) 144230557Sjimharris { 145230557Sjimharris scif_sas_controller_restore_interrupt_coalescence(fw_domain->controller); 146230557Sjimharris 147230557Sjimharris scif_cb_timer_stop(fw_domain->controller, fw_domain->operation.timer); 148230557Sjimharris 149230557Sjimharris scif_cb_domain_discovery_complete( 150230557Sjimharris fw_domain->controller, fw_domain, fw_domain->operation.status 151230557Sjimharris ); 152230557Sjimharris } 153230557Sjimharris} 154230557Sjimharris 155230557Sjimharris 156230557Sjimharris/** 157230557Sjimharris * @brief This method is called upon entrance to DISCOVERING state. Right before 158230557Sjimharris * transitioning to DISCOVERING state, we temporarily change interrupt 159230557Sjimharris * coalescence scheme. 160230557Sjimharris * 161230557Sjimharris * @param[in] fw_domain This parameter specifies the domain for which 162230557Sjimharris * the state transition has occurred. 163230557Sjimharris * 164230557Sjimharris * @return none 165230557Sjimharris */ 166230557Sjimharrisvoid scif_sas_domain_transition_to_discovering_state( 167230557Sjimharris SCIF_SAS_DOMAIN_T * fw_domain 168230557Sjimharris) 169230557Sjimharris{ 170230557Sjimharris scif_sas_controller_save_interrupt_coalescence(fw_domain->controller); 171230557Sjimharris 172230557Sjimharris sci_base_state_machine_change_state( 173230557Sjimharris &fw_domain->parent.state_machine, SCI_BASE_DOMAIN_STATE_DISCOVERING 174230557Sjimharris ); 175230557Sjimharris} 176230557Sjimharris 177230557Sjimharris 178230557Sjimharris/** 179230557Sjimharris * @brief This method implements the actions taken when entering the 180230557Sjimharris * INITIAL state. 181230557Sjimharris * 182230557Sjimharris * @param[in] object This parameter specifies the base object for which 183230557Sjimharris * the state transition is occurring. This is cast into a 184230557Sjimharris * SCIF_SAS_DOMAIN object in the method implementation. 185230557Sjimharris * 186230557Sjimharris * @return none 187230557Sjimharris */ 188230557Sjimharrisstatic 189230557Sjimharrisvoid scif_sas_domain_initial_state_enter( 190230557Sjimharris SCI_BASE_OBJECT_T * object 191230557Sjimharris) 192230557Sjimharris{ 193230557Sjimharris SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T *)object; 194230557Sjimharris 195230557Sjimharris SET_STATE_HANDLER( 196230557Sjimharris fw_domain, 197230557Sjimharris scif_sas_domain_state_handler_table, 198230557Sjimharris SCI_BASE_DOMAIN_STATE_INITIAL 199230557Sjimharris ); 200230557Sjimharris 201230557Sjimharris SCIF_LOG_TRACE(( 202230557Sjimharris sci_base_object_get_logger(fw_domain), 203230557Sjimharris SCIF_LOG_OBJECT_DOMAIN, 204230557Sjimharris "scif_sas_domain_initial_state_enter(0x%x) enter\n", 205230557Sjimharris fw_domain 206230557Sjimharris )); 207230557Sjimharris} 208230557Sjimharris 209230557Sjimharris/** 210230557Sjimharris * @brief This method implements the actions taken when entering the 211230557Sjimharris * STARTING state. This includes setting the state handlers and 212230557Sjimharris * checking to see if the core port has already become READY. 213230557Sjimharris * 214230557Sjimharris * @param[in] object This parameter specifies the base object for which 215230557Sjimharris * the state transition is occurring. This is cast into a 216230557Sjimharris * SCIF_SAS_DOMAIN object in the method implementation. 217230557Sjimharris * 218230557Sjimharris * @return none 219230557Sjimharris */ 220230557Sjimharrisstatic 221230557Sjimharrisvoid scif_sas_domain_starting_state_enter( 222230557Sjimharris SCI_BASE_OBJECT_T * object 223230557Sjimharris) 224230557Sjimharris{ 225230557Sjimharris SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T *)object; 226230557Sjimharris 227230557Sjimharris SET_STATE_HANDLER( 228230557Sjimharris fw_domain, 229230557Sjimharris scif_sas_domain_state_handler_table, 230230557Sjimharris SCI_BASE_DOMAIN_STATE_STARTING 231230557Sjimharris ); 232230557Sjimharris 233230557Sjimharris SCIF_LOG_TRACE(( 234230557Sjimharris sci_base_object_get_logger(fw_domain), 235230557Sjimharris SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 236230557Sjimharris "scif_sas_domain_starting_state_enter(0x%x) enter\n", 237230557Sjimharris fw_domain 238230557Sjimharris )); 239230557Sjimharris 240230557Sjimharris scif_sas_domain_transition_from_discovering_state(fw_domain); 241230557Sjimharris 242230557Sjimharris // If we entered the STARTING state and the core port is actually ready, 243230557Sjimharris // then directly transition into the READY state. This can occur 244230557Sjimharris // if we were in the middle of discovery when the port failed 245230557Sjimharris // (causing a transition to STOPPING), then before reaching STOPPED 246230557Sjimharris // the port becomes ready again. 247230557Sjimharris if (fw_domain->is_port_ready == TRUE) 248230557Sjimharris { 249230557Sjimharris sci_base_state_machine_change_state( 250230557Sjimharris &fw_domain->parent.state_machine, SCI_BASE_DOMAIN_STATE_READY 251230557Sjimharris ); 252230557Sjimharris } 253230557Sjimharris} 254230557Sjimharris 255230557Sjimharris/** 256230557Sjimharris * @brief This method implements the actions taken when entering the 257230557Sjimharris * READY state. If the transition into this state came from: 258230557Sjimharris * - the STARTING state, then alert the user via a 259230557Sjimharris * scif_cb_domain_change_notification() that the domain 260230557Sjimharris * has at least 1 device ready for discovery. 261230557Sjimharris * - the DISCOVERING state, then alert the user that 262230557Sjimharris * discovery is complete via the 263230557Sjimharris * scif_cb_domain_discovery_complete() notification that 264230557Sjimharris * discovery is finished. 265230557Sjimharris * 266230557Sjimharris * @param[in] object This parameter specifies the base object for which 267230557Sjimharris * the state transition is occurring. This is cast into a 268230557Sjimharris * SCIF_SAS_DOMAIN object in the method implementation. 269230557Sjimharris * 270230557Sjimharris * @return none 271230557Sjimharris */ 272230557Sjimharrisstatic 273230557Sjimharrisvoid scif_sas_domain_ready_state_enter( 274230557Sjimharris SCI_BASE_OBJECT_T * object 275230557Sjimharris) 276230557Sjimharris{ 277230557Sjimharris SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T *)object; 278230557Sjimharris 279230557Sjimharris SET_STATE_HANDLER( 280230557Sjimharris fw_domain, 281230557Sjimharris scif_sas_domain_state_handler_table, 282230557Sjimharris SCI_BASE_DOMAIN_STATE_READY 283230557Sjimharris ); 284230557Sjimharris 285230557Sjimharris SCIF_LOG_TRACE(( 286230557Sjimharris sci_base_object_get_logger(fw_domain), 287230557Sjimharris SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 288230557Sjimharris "scif_sas_domain_ready_state_enter(0x%x) enter\n", 289230557Sjimharris fw_domain 290230557Sjimharris )); 291230557Sjimharris 292230557Sjimharris if (fw_domain->parent.state_machine.previous_state_id 293230557Sjimharris == SCI_BASE_DOMAIN_STATE_STARTING) 294230557Sjimharris { 295230557Sjimharris scif_cb_domain_ready(fw_domain->controller, fw_domain); 296230557Sjimharris 297230557Sjimharris // Only indicate the domain change notification if the previous 298230557Sjimharris // state was the STARTING state. We issue the notification here 299230557Sjimharris // as opposed to exit of the STARTING state so that the appropriate 300230557Sjimharris // state handlers are in place should the user call 301230557Sjimharris // scif_domain_discover() from scif_cb_domain_change_notification() 302230557Sjimharris scif_cb_domain_change_notification(fw_domain->controller, fw_domain); 303230557Sjimharris } 304230557Sjimharris else if (fw_domain->parent.state_machine.previous_state_id 305230557Sjimharris == SCI_BASE_DOMAIN_STATE_DISCOVERING) 306230557Sjimharris { 307230557Sjimharris //if domain discovery timed out, we will NOT go back to discover even 308230557Sjimharris //the broadcast change count is not zero. Instead we finish the discovery 309230557Sjimharris //back to user. User can check the operation status and decide to 310230557Sjimharris //retry discover all over again. 311230557Sjimharris if (fw_domain->operation.status == SCI_FAILURE_TIMEOUT) 312230557Sjimharris fw_domain->broadcast_change_count = 0; 313230557Sjimharris 314230557Sjimharris // Check the broadcast change count to determine if discovery 315230557Sjimharris // is indeed complete. 316230557Sjimharris if (fw_domain->broadcast_change_count == 0) 317230557Sjimharris { 318230557Sjimharris scif_sas_domain_transition_from_discovering_state(fw_domain); 319230557Sjimharris scif_cb_domain_ready(fw_domain->controller, fw_domain); 320230557Sjimharris } 321230557Sjimharris else 322230557Sjimharris { 323230557Sjimharris // The broadcast change count indicates something my have 324230557Sjimharris // changed in the domain, while a discovery was ongoing. 325230557Sjimharris // Thus, we should start discovery over again. 326230557Sjimharris sci_base_state_machine_change_state( 327230557Sjimharris &fw_domain->parent.state_machine, SCI_BASE_DOMAIN_STATE_DISCOVERING 328230557Sjimharris ); 329230557Sjimharris } 330230557Sjimharris 331230557Sjimharris // Enable the BCN because underneath hardware may disabled any further 332230557Sjimharris // BCN. 333230557Sjimharris scic_port_enable_broadcast_change_notification(fw_domain->core_object); 334230557Sjimharris } 335230557Sjimharris} 336230557Sjimharris 337230557Sjimharris/** 338230557Sjimharris * @brief This method implements the actions taken when exiting the 339230557Sjimharris * READY state. 340230557Sjimharris * 341230557Sjimharris * @param[in] object This parameter specifies the base object for which 342230557Sjimharris * the state transition is occurring. This is cast into a 343230557Sjimharris * SCIF_SAS_DOMAIN object in the method implementation. 344230557Sjimharris * 345230557Sjimharris * @return none 346230557Sjimharris */ 347230557Sjimharrisstatic 348230557Sjimharrisvoid scif_sas_domain_ready_state_exit( 349230557Sjimharris SCI_BASE_OBJECT_T * object 350230557Sjimharris) 351230557Sjimharris{ 352230557Sjimharris SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T *)object; 353230557Sjimharris 354230557Sjimharris SCIF_LOG_TRACE(( 355230557Sjimharris sci_base_object_get_logger(fw_domain), 356230557Sjimharris SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 357230557Sjimharris "scif_sas_domain_ready_state_exit(0x%x) enter\n", 358230557Sjimharris fw_domain 359230557Sjimharris )); 360230557Sjimharris 361230557Sjimharris scif_cb_domain_not_ready(fw_domain->controller, fw_domain); 362230557Sjimharris} 363230557Sjimharris 364230557Sjimharris/** 365230557Sjimharris * @brief This method implements the actions taken when entering the 366230557Sjimharris * STOPPING state. 367230557Sjimharris * 368230557Sjimharris * @param[in] object This parameter specifies the base object for which 369230557Sjimharris * the state transition is occurring. This is cast into a 370230557Sjimharris * SCIF_SAS_DOMAIN object in the method implementation. 371230557Sjimharris * 372230557Sjimharris * @return none 373230557Sjimharris */ 374230557Sjimharrisstatic 375230557Sjimharrisvoid scif_sas_domain_stopping_state_enter( 376230557Sjimharris SCI_BASE_OBJECT_T * object 377230557Sjimharris) 378230557Sjimharris{ 379230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device; 380230557Sjimharris SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T *)object; 381230557Sjimharris SCI_ABSTRACT_ELEMENT_T * element = sci_abstract_list_get_front( 382230557Sjimharris &fw_domain->remote_device_list 383230557Sjimharris ); 384230557Sjimharris 385230557Sjimharris SET_STATE_HANDLER( 386230557Sjimharris fw_domain, 387230557Sjimharris scif_sas_domain_state_handler_table, 388230557Sjimharris SCI_BASE_DOMAIN_STATE_STOPPING 389230557Sjimharris ); 390230557Sjimharris 391230557Sjimharris // This must be invoked after the state handlers are set to ensure 392230557Sjimharris // appropriate processing will occur if the user attempts to perform 393230557Sjimharris // additional actions. 394230557Sjimharris scif_sas_domain_transition_from_discovering_state(fw_domain); 395230557Sjimharris 396230557Sjimharris SCIF_LOG_TRACE(( 397230557Sjimharris sci_base_object_get_logger(fw_domain), 398230557Sjimharris SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 399230557Sjimharris "scif_sas_domain_stopping_state_enter(0x%x) enter\n", 400230557Sjimharris fw_domain 401230557Sjimharris )); 402230557Sjimharris 403230557Sjimharris scif_sas_high_priority_request_queue_purge_domain( 404230557Sjimharris &fw_domain->controller->hprq, fw_domain 405230557Sjimharris ); 406230557Sjimharris 407230557Sjimharris // Search the domain's list of devices and put them all in the STOPPING 408230557Sjimharris // state. 409230557Sjimharris while (element != NULL) 410230557Sjimharris { 411230557Sjimharris fw_device = (SCIF_SAS_REMOTE_DEVICE_T*) 412230557Sjimharris sci_abstract_list_get_object(element); 413230557Sjimharris 414230557Sjimharris // This method will stop the core device. The core will terminate 415230557Sjimharris // all IO requests currently outstanding. 416230557Sjimharris fw_device->state_handlers->parent.stop_handler(&fw_device->parent); 417230557Sjimharris 418230557Sjimharris element = sci_abstract_list_get_next(element); 419230557Sjimharris } 420230557Sjimharris 421230557Sjimharris // Attempt to transition to the stopped state. 422230557Sjimharris scif_sas_domain_transition_to_stopped_state(fw_domain); 423230557Sjimharris} 424230557Sjimharris 425230557Sjimharris/** 426230557Sjimharris * @brief This method implements the actions taken when entering the 427230557Sjimharris * STOPPED state. 428230557Sjimharris * 429230557Sjimharris * @param[in] object This parameter specifies the base object for which 430230557Sjimharris * the state transition is occurring. This is cast into a 431230557Sjimharris * SCIF_SAS_DOMAIN object in the method implementation. 432230557Sjimharris * 433230557Sjimharris * @return none 434230557Sjimharris */ 435230557Sjimharrisstatic 436230557Sjimharrisvoid scif_sas_domain_stopped_state_enter( 437230557Sjimharris SCI_BASE_OBJECT_T * object 438230557Sjimharris) 439230557Sjimharris{ 440230557Sjimharris SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T *)object; 441230557Sjimharris 442230557Sjimharris SET_STATE_HANDLER( 443230557Sjimharris fw_domain, 444230557Sjimharris scif_sas_domain_state_handler_table, 445230557Sjimharris SCI_BASE_DOMAIN_STATE_STOPPED 446230557Sjimharris ); 447230557Sjimharris 448230557Sjimharris SCIF_LOG_TRACE(( 449230557Sjimharris sci_base_object_get_logger(fw_domain), 450230557Sjimharris SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 451230557Sjimharris "scif_sas_domain_stopped_state_enter(0x%x) enter\n", 452230557Sjimharris fw_domain 453230557Sjimharris )); 454230557Sjimharris 455230557Sjimharris // A hot unplug of the direct attached device has occurred. Thus, 456230557Sjimharris // notify the user. Note, if the controller is not in READY state, 457230557Sjimharris // mostly likely the controller is in STOPPING or STOPPED state, 458230557Sjimharris // meaning the controller is in the process of stopping, we should 459230557Sjimharris // not call back to user in the middle of controller stopping. 460230557Sjimharris if(fw_domain->controller->parent.state_machine.current_state_id 461230557Sjimharris == SCI_BASE_CONTROLLER_STATE_READY) 462230557Sjimharris scif_cb_domain_change_notification(fw_domain->controller, fw_domain); 463230557Sjimharris} 464230557Sjimharris 465230557Sjimharris/** 466230557Sjimharris * @brief This method implements the actions taken when entering the 467230557Sjimharris * DISCOVERING state. This includes determining from which 468230557Sjimharris * state we entered. If we entered from stopping that some sort 469230557Sjimharris * of hot-remove of the port occurred. In the hot-remove case 470230557Sjimharris * all devices should be in the STOPPED state already and, as 471230557Sjimharris * a result, are removed from the domain with a notification sent 472230557Sjimharris * to the framework user. 473230557Sjimharris * 474230557Sjimharris * @note This method currently only handles hot-insert/hot-remove of 475230557Sjimharris * direct attached SSP devices. 476230557Sjimharris * 477230557Sjimharris * @param[in] object This parameter specifies the base object for which 478230557Sjimharris * the state transition is occurring. This is cast into a 479230557Sjimharris * SCIF_SAS_DOMAIN object in the method implementation. 480230557Sjimharris * 481230557Sjimharris * @return none 482230557Sjimharris */ 483230557Sjimharrisstatic 484230557Sjimharrisvoid scif_sas_domain_discovering_state_enter( 485230557Sjimharris SCI_BASE_OBJECT_T * object 486230557Sjimharris) 487230557Sjimharris{ 488230557Sjimharris SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T *)object; 489230557Sjimharris 490230557Sjimharris SET_STATE_HANDLER( 491230557Sjimharris fw_domain, 492230557Sjimharris scif_sas_domain_state_handler_table, 493230557Sjimharris SCI_BASE_DOMAIN_STATE_DISCOVERING 494230557Sjimharris ); 495230557Sjimharris 496230557Sjimharris SCIF_LOG_TRACE(( 497230557Sjimharris sci_base_object_get_logger(fw_domain), 498230557Sjimharris SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 499230557Sjimharris "scif_sas_domain_discovering_state_enter(0x%x) enter\n", 500230557Sjimharris fw_domain 501230557Sjimharris )); 502230557Sjimharris 503230557Sjimharris fw_domain->broadcast_change_count = 0; 504230557Sjimharris 505230557Sjimharris // Did the domain just go through a port not ready action? If it did, 506230557Sjimharris // then we will be entering from the STOPPED state. 507230557Sjimharris if (fw_domain->parent.state_machine.previous_state_id 508230557Sjimharris != SCI_BASE_DOMAIN_STATE_STOPPED) 509230557Sjimharris { 510230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * remote_device; 511230557Sjimharris SCIC_PORT_PROPERTIES_T properties; 512230557Sjimharris 513230557Sjimharris scic_port_get_properties(fw_domain->core_object, &properties); 514230557Sjimharris 515230557Sjimharris // If the device has not yet been added to the domain, then 516230557Sjimharris // inform the user that the device is new. 517230557Sjimharris remote_device = (SCIF_SAS_REMOTE_DEVICE_T *) 518230557Sjimharris scif_domain_get_device_by_sas_address( 519230557Sjimharris fw_domain, &properties.remote.sas_address 520230557Sjimharris ); 521230557Sjimharris if (remote_device == SCI_INVALID_HANDLE) 522230557Sjimharris { 523230557Sjimharris // simply notify the user of the new DA device and be done 524230557Sjimharris // with discovery. 525230557Sjimharris scif_cb_domain_da_device_added( 526230557Sjimharris fw_domain->controller, 527230557Sjimharris fw_domain, 528230557Sjimharris &properties.remote.sas_address, 529230557Sjimharris &properties.remote.protocols 530230557Sjimharris ); 531230557Sjimharris } 532230557Sjimharris else 533230557Sjimharris { 534230557Sjimharris if(properties.remote.protocols.u.bits.smp_target) 535230557Sjimharris //kick off the smp discover process. 536230557Sjimharris scif_sas_domain_start_smp_discover(fw_domain, remote_device); 537230557Sjimharris } 538230557Sjimharris } 539230557Sjimharris else //entered from STOPPED state. 540230557Sjimharris { 541230557Sjimharris SCI_ABSTRACT_ELEMENT_T * current_element = 542230557Sjimharris sci_abstract_list_get_front(&(fw_domain->remote_device_list) ); 543230557Sjimharris 544230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device; 545230557Sjimharris 546230557Sjimharris while (current_element != NULL) 547230557Sjimharris { 548230557Sjimharris fw_device = (SCIF_SAS_REMOTE_DEVICE_T *) 549230557Sjimharris sci_abstract_list_get_object(current_element); 550230557Sjimharris 551230557Sjimharris ASSERT(fw_device->parent.state_machine.current_state_id 552230557Sjimharris == SCI_BASE_REMOTE_DEVICE_STATE_STOPPED); 553230557Sjimharris 554230557Sjimharris current_element = 555230557Sjimharris sci_abstract_list_get_next(current_element); 556230557Sjimharris 557230557Sjimharris SCIF_LOG_INFO(( 558230557Sjimharris sci_base_object_get_logger(fw_domain), 559230557Sjimharris SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 560230557Sjimharris "Controller:0x%x Domain:0x%x Device:0x%x removed\n", 561230557Sjimharris fw_domain->controller, fw_domain, fw_device 562230557Sjimharris )); 563230557Sjimharris 564230557Sjimharris // Notify the framework user of the device removal. 565230557Sjimharris scif_cb_domain_device_removed( 566230557Sjimharris fw_domain->controller, fw_domain, fw_device 567230557Sjimharris ); 568230557Sjimharris } 569230557Sjimharris 570230557Sjimharris ASSERT(fw_domain->request_list.element_count == 0); 571230557Sjimharris ASSERT(sci_abstract_list_size(&fw_domain->remote_device_list) == 0); 572230557Sjimharris 573230557Sjimharris sci_base_state_machine_change_state( 574230557Sjimharris &fw_domain->parent.state_machine, SCI_BASE_DOMAIN_STATE_STARTING 575230557Sjimharris ); 576230557Sjimharris } 577230557Sjimharris} 578230557Sjimharris 579230557SjimharrisSCI_BASE_STATE_T scif_sas_domain_state_table[SCI_BASE_DOMAIN_MAX_STATES] = 580230557Sjimharris{ 581230557Sjimharris { 582230557Sjimharris SCI_BASE_DOMAIN_STATE_INITIAL, 583230557Sjimharris scif_sas_domain_initial_state_enter, 584230557Sjimharris NULL, 585230557Sjimharris }, 586230557Sjimharris { 587230557Sjimharris SCI_BASE_DOMAIN_STATE_STARTING, 588230557Sjimharris scif_sas_domain_starting_state_enter, 589230557Sjimharris NULL, 590230557Sjimharris }, 591230557Sjimharris { 592230557Sjimharris SCI_BASE_DOMAIN_STATE_READY, 593230557Sjimharris scif_sas_domain_ready_state_enter, 594230557Sjimharris scif_sas_domain_ready_state_exit, 595230557Sjimharris }, 596230557Sjimharris { 597230557Sjimharris SCI_BASE_DOMAIN_STATE_STOPPING, 598230557Sjimharris scif_sas_domain_stopping_state_enter, 599230557Sjimharris NULL, 600230557Sjimharris }, 601230557Sjimharris { 602230557Sjimharris SCI_BASE_DOMAIN_STATE_STOPPED, 603230557Sjimharris scif_sas_domain_stopped_state_enter, 604230557Sjimharris NULL, 605230557Sjimharris }, 606230557Sjimharris { 607230557Sjimharris SCI_BASE_DOMAIN_STATE_DISCOVERING, 608230557Sjimharris scif_sas_domain_discovering_state_enter, 609230557Sjimharris NULL, 610230557Sjimharris } 611230557Sjimharris}; 612230557Sjimharris 613