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/scic_sds_port.c 249586 2013-04-17 11:47:32Z gabor $"); 55230557Sjimharris 56230557Sjimharris/** 57230557Sjimharris * @file 58230557Sjimharris * 59230557Sjimharris * @brief This file contains the implementation for the public and protected 60230557Sjimharris * methods for the SCIC_SDS_PORT object. 61230557Sjimharris */ 62230557Sjimharris 63230557Sjimharris#include <dev/isci/scil/scic_phy.h> 64230557Sjimharris#include <dev/isci/scil/scic_port.h> 65230557Sjimharris#include <dev/isci/scil/scic_controller.h> 66230557Sjimharris#include <dev/isci/scil/scic_user_callback.h> 67230557Sjimharris 68230557Sjimharris#include <dev/isci/scil/scic_sds_controller.h> 69230557Sjimharris#include <dev/isci/scil/scic_sds_port.h> 70230557Sjimharris#include <dev/isci/scil/scic_sds_phy.h> 71230557Sjimharris#include <dev/isci/scil/scic_sds_remote_device.h> 72230557Sjimharris#include <dev/isci/scil/scic_sds_request.h> 73230557Sjimharris#include <dev/isci/scil/scic_sds_port_registers.h> 74230557Sjimharris#include <dev/isci/scil/scic_sds_logger.h> 75230557Sjimharris#include <dev/isci/scil/scic_sds_phy_registers.h> 76230557Sjimharris 77230557Sjimharris#include <dev/isci/scil/intel_sas.h> 78230557Sjimharris#include <dev/isci/scil/scic_sds_remote_node_context.h> 79230557Sjimharris#include <dev/isci/scil/sci_util.h> 80230557Sjimharris 81230557Sjimharris#define SCIC_SDS_PORT_MIN_TIMER_COUNT (SCI_MAX_PORTS) 82230557Sjimharris#define SCIC_SDS_PORT_MAX_TIMER_COUNT (SCI_MAX_PORTS) 83230557Sjimharris 84230557Sjimharris#define SCIC_SDS_PORT_HARD_RESET_TIMEOUT (1000) 85230557Sjimharris#define SCU_DUMMY_INDEX (0xFFFF) 86230557Sjimharris 87230557Sjimharris/** 88230557Sjimharris * This method will return a TRUE value if the specified phy can be assigned 89230557Sjimharris * to this port 90230557Sjimharris * 91230557Sjimharris * The following is a list of phys for each port that are allowed: 92230557Sjimharris * - Port 0 - 3 2 1 0 93230557Sjimharris * - Port 1 - 1 94230557Sjimharris * - Port 2 - 3 2 95230557Sjimharris * - Port 3 - 3 96230557Sjimharris * 97230557Sjimharris * This method doesn't preclude all configurations. It merely ensures 98230557Sjimharris * that a phy is part of the allowable set of phy identifiers for 99230557Sjimharris * that port. For example, one could assign phy 3 to port 0 and no other 100230557Sjimharris * phys. Please refer to scic_sds_port_is_phy_mask_valid() for 101230557Sjimharris * information regarding whether the phy_mask for a port can be supported. 102230557Sjimharris * 103230557Sjimharris * @param[in] this_port This is the port object to which the phy is being 104230557Sjimharris * assigned. 105230557Sjimharris * @param[in] phy_index This is the phy index that is being assigned to the 106230557Sjimharris * port. 107230557Sjimharris * 108230557Sjimharris * @return BOOL 109230557Sjimharris * @retval TRUE if this is a valid phy assignment for the port 110230557Sjimharris * @retval FALSE if this is not a valid phy assignment for the port 111230557Sjimharris */ 112230557SjimharrisBOOL scic_sds_port_is_valid_phy_assignment( 113230557Sjimharris SCIC_SDS_PORT_T *this_port, 114230557Sjimharris U32 phy_index 115230557Sjimharris) 116230557Sjimharris{ 117230557Sjimharris // Initialize to invalid value. 118230557Sjimharris U32 existing_phy_index = SCI_MAX_PHYS; 119230557Sjimharris U32 index; 120230557Sjimharris 121230557Sjimharris if ((this_port->physical_port_index == 1) && (phy_index != 1)) 122230557Sjimharris { 123230557Sjimharris return FALSE; 124230557Sjimharris } 125230557Sjimharris 126230557Sjimharris if (this_port->physical_port_index == 3 && phy_index != 3) 127230557Sjimharris { 128230557Sjimharris return FALSE; 129230557Sjimharris } 130230557Sjimharris 131230557Sjimharris if ( 132230557Sjimharris (this_port->physical_port_index == 2) 133230557Sjimharris && ((phy_index == 0) || (phy_index == 1)) 134230557Sjimharris ) 135230557Sjimharris { 136230557Sjimharris return FALSE; 137230557Sjimharris } 138230557Sjimharris 139230557Sjimharris for (index = 0; index < SCI_MAX_PHYS; index++) 140230557Sjimharris { 141230557Sjimharris if ( (this_port->phy_table[index] != NULL) 142230557Sjimharris && (index != phy_index) ) 143230557Sjimharris { 144230557Sjimharris existing_phy_index = index; 145230557Sjimharris } 146230557Sjimharris } 147230557Sjimharris 148230557Sjimharris // Ensure that all of the phys in the port are capable of 149230557Sjimharris // operating at the same maximum link rate. 150230557Sjimharris if ( 151230557Sjimharris (existing_phy_index < SCI_MAX_PHYS) 152230557Sjimharris && (this_port->owning_controller->user_parameters.sds1.phys[ 153230557Sjimharris phy_index].max_speed_generation != 154230557Sjimharris this_port->owning_controller->user_parameters.sds1.phys[ 155230557Sjimharris existing_phy_index].max_speed_generation) 156230557Sjimharris ) 157230557Sjimharris return FALSE; 158230557Sjimharris 159230557Sjimharris return TRUE; 160230557Sjimharris} 161230557Sjimharris 162230557Sjimharris/** 163230557Sjimharris * @brief This method requests a list (mask) of the phys contained in the 164230557Sjimharris * supplied SAS port. 165230557Sjimharris * 166230557Sjimharris * @param[in] this_port a handle corresponding to the SAS port for which 167230557Sjimharris * to return the phy mask. 168230557Sjimharris * 169230557Sjimharris * @return Return a bit mask indicating which phys are a part of this port. 170230557Sjimharris * Each bit corresponds to a phy identifier (e.g. bit 0 = phy id 0). 171230557Sjimharris */ 172230557SjimharrisU32 scic_sds_port_get_phys( 173230557Sjimharris SCIC_SDS_PORT_T * this_port 174230557Sjimharris) 175230557Sjimharris{ 176230557Sjimharris U32 index; 177230557Sjimharris U32 mask; 178230557Sjimharris 179230557Sjimharris SCIC_LOG_TRACE(( 180230557Sjimharris sci_base_object_get_logger(this_port), 181230557Sjimharris SCIC_LOG_OBJECT_PORT, 182230557Sjimharris "scic_sds_port_get_phys(0x%x) enter\n", 183230557Sjimharris this_port 184230557Sjimharris )); 185230557Sjimharris 186230557Sjimharris mask = 0; 187230557Sjimharris 188230557Sjimharris for (index = 0; index < SCI_MAX_PHYS; index++) 189230557Sjimharris { 190230557Sjimharris if (this_port->phy_table[index] != NULL) 191230557Sjimharris { 192230557Sjimharris mask |= (1 << index); 193230557Sjimharris } 194230557Sjimharris } 195230557Sjimharris 196230557Sjimharris return mask; 197230557Sjimharris} 198230557Sjimharris 199230557Sjimharris/** 200230557Sjimharris * This method will return a TRUE value if the port's phy mask can be 201230557Sjimharris * supported by the SCU. 202230557Sjimharris * 203230557Sjimharris * The following is a list of valid PHY mask configurations for each 204230557Sjimharris * port: 205230557Sjimharris * - Port 0 - [[3 2] 1] 0 206230557Sjimharris * - Port 1 - [1] 207230557Sjimharris * - Port 2 - [[3] 2] 208230557Sjimharris * - Port 3 - [3] 209230557Sjimharris * 210230557Sjimharris * @param[in] this_port This is the port object for which to determine 211230557Sjimharris * if the phy mask can be supported. 212230557Sjimharris * 213230557Sjimharris * @return This method returns a boolean indication specifying if the 214230557Sjimharris * phy mask can be supported. 215230557Sjimharris * @retval TRUE if this is a valid phy assignment for the port 216230557Sjimharris * @retval FALSE if this is not a valid phy assignment for the port 217230557Sjimharris */ 218230557SjimharrisBOOL scic_sds_port_is_phy_mask_valid( 219230557Sjimharris SCIC_SDS_PORT_T *this_port, 220230557Sjimharris U32 phy_mask 221230557Sjimharris) 222230557Sjimharris{ 223230557Sjimharris if (this_port->physical_port_index == 0) 224230557Sjimharris { 225230557Sjimharris if ( ((phy_mask & 0x0F) == 0x0F) 226230557Sjimharris || ((phy_mask & 0x03) == 0x03) 227230557Sjimharris || ((phy_mask & 0x01) == 0x01) 228230557Sjimharris || (phy_mask == 0) ) 229230557Sjimharris return TRUE; 230230557Sjimharris } 231230557Sjimharris else if (this_port->physical_port_index == 1) 232230557Sjimharris { 233230557Sjimharris if ( ((phy_mask & 0x02) == 0x02) 234230557Sjimharris || (phy_mask == 0) ) 235230557Sjimharris return TRUE; 236230557Sjimharris } 237230557Sjimharris else if (this_port->physical_port_index == 2) 238230557Sjimharris { 239230557Sjimharris if ( ((phy_mask & 0x0C) == 0x0C) 240230557Sjimharris || ((phy_mask & 0x04) == 0x04) 241230557Sjimharris || (phy_mask == 0) ) 242230557Sjimharris return TRUE; 243230557Sjimharris } 244230557Sjimharris else if (this_port->physical_port_index == 3) 245230557Sjimharris { 246230557Sjimharris if ( ((phy_mask & 0x08) == 0x08) 247230557Sjimharris || (phy_mask == 0) ) 248230557Sjimharris return TRUE; 249230557Sjimharris } 250230557Sjimharris 251230557Sjimharris return FALSE; 252230557Sjimharris} 253230557Sjimharris 254230557Sjimharris/** 255230557Sjimharris * This method retrieves a currently active (i.e. connected) phy 256230557Sjimharris * contained in the port. Currently, the lowest order phy that is 257230557Sjimharris * connected is returned. 258230557Sjimharris * 259230557Sjimharris * @param[in] this_port This parameter specifies the port from which 260230557Sjimharris * to return a connected phy. 261230557Sjimharris * 262230557Sjimharris * @return This method returns a pointer to a SCIS_SDS_PHY object. 263230557Sjimharris * @retval NULL This value is returned if there are no currently 264230557Sjimharris * active (i.e. connected to a remote end point) phys 265230557Sjimharris * contained in the port. 266230557Sjimharris * @retval All other values specify a SCIC_SDS_PHY object that is 267230557Sjimharris * active in the port. 268230557Sjimharris */ 269230557SjimharrisSCIC_SDS_PHY_T * scic_sds_port_get_a_connected_phy( 270230557Sjimharris SCIC_SDS_PORT_T *this_port 271230557Sjimharris) 272230557Sjimharris{ 273230557Sjimharris U32 index; 274230557Sjimharris SCIC_SDS_PHY_T *phy; 275230557Sjimharris 276230557Sjimharris for (index = 0; index < SCI_MAX_PHYS; index++) 277230557Sjimharris { 278230557Sjimharris // Ensure that the phy is both part of the port and currently 279230557Sjimharris // connected to the remote end-point. 280230557Sjimharris phy = this_port->phy_table[index]; 281230557Sjimharris if ( 282230557Sjimharris (phy != NULL) 283230557Sjimharris && scic_sds_port_active_phy(this_port, phy) 284230557Sjimharris ) 285230557Sjimharris { 286230557Sjimharris return phy; 287230557Sjimharris } 288230557Sjimharris } 289230557Sjimharris 290230557Sjimharris return NULL; 291230557Sjimharris} 292230557Sjimharris 293230557Sjimharris/** 294230557Sjimharris * This method attempts to make the assignment of the phy to the port. 295230557Sjimharris * If successful the phy is assigned to the ports phy table. 296230557Sjimharris * 297230557Sjimharris * @param[in, out] port The port object to which the phy assignement 298230557Sjimharris * is being made. 299230557Sjimharris * @param[in, out] phy The phy which is being assigned to the port. 300230557Sjimharris * 301230557Sjimharris * @return BOOL 302230557Sjimharris * @retval TRUE if the phy assignment can be made. 303230557Sjimharris * @retval FALSE if the phy assignement can not be made. 304230557Sjimharris * 305230557Sjimharris * @note This is a functional test that only fails if the phy is currently 306230557Sjimharris * assigned to a different port. 307230557Sjimharris */ 308230557SjimharrisSCI_STATUS scic_sds_port_set_phy( 309230557Sjimharris SCIC_SDS_PORT_T *port, 310230557Sjimharris SCIC_SDS_PHY_T *phy 311230557Sjimharris) 312230557Sjimharris{ 313230557Sjimharris // Check to see if we can add this phy to a port 314230557Sjimharris // that means that the phy is not part of a port and that the port does 315230557Sjimharris // not already have a phy assinged to the phy index. 316230557Sjimharris if ( 317230557Sjimharris (port->phy_table[phy->phy_index] == SCI_INVALID_HANDLE) 318230557Sjimharris && (scic_sds_phy_get_port(phy) == SCI_INVALID_HANDLE) 319230557Sjimharris && scic_sds_port_is_valid_phy_assignment(port, phy->phy_index) 320230557Sjimharris ) 321230557Sjimharris { 322230557Sjimharris // Phy is being added in the stopped state so we are in MPC mode 323230557Sjimharris // make logical port index = physical port index 324230557Sjimharris port->logical_port_index = port->physical_port_index; 325230557Sjimharris port->phy_table[phy->phy_index] = phy; 326230557Sjimharris scic_sds_phy_set_port(phy, port); 327230557Sjimharris 328230557Sjimharris return SCI_SUCCESS; 329230557Sjimharris } 330230557Sjimharris 331230557Sjimharris return SCI_FAILURE; 332230557Sjimharris} 333230557Sjimharris 334230557Sjimharris/** 335230557Sjimharris * This method will clear the phy assigned to this port. This method fails 336230557Sjimharris * if this phy is not currently assinged to this port. 337230557Sjimharris * 338230557Sjimharris * @param[in, out] port The port from which the phy is being cleared. 339230557Sjimharris * @param[in, out] phy The phy being cleared from the port. 340230557Sjimharris * 341230557Sjimharris * @return BOOL 342230557Sjimharris * @retval TRUE if the phy is removed from the port. 343230557Sjimharris * @retval FALSE if this phy is not assined to this port. 344230557Sjimharris */ 345230557SjimharrisSCI_STATUS scic_sds_port_clear_phy( 346230557Sjimharris SCIC_SDS_PORT_T *port, 347230557Sjimharris SCIC_SDS_PHY_T *phy 348230557Sjimharris) 349230557Sjimharris{ 350230557Sjimharris // Make sure that this phy is part of this port 351230557Sjimharris if ( 352230557Sjimharris (port->phy_table[phy->phy_index] == phy) 353230557Sjimharris && (scic_sds_phy_get_port(phy) == port) 354230557Sjimharris ) 355230557Sjimharris { 356230557Sjimharris // Yep it is assigned to this port so remove it 357230557Sjimharris scic_sds_phy_set_port( 358230557Sjimharris phy, 359230557Sjimharris &scic_sds_port_get_controller(port)->port_table[SCI_MAX_PORTS] 360230557Sjimharris ); 361230557Sjimharris 362230557Sjimharris port->phy_table[phy->phy_index] = SCI_INVALID_HANDLE; 363230557Sjimharris 364230557Sjimharris return SCI_SUCCESS; 365230557Sjimharris } 366230557Sjimharris 367230557Sjimharris return SCI_FAILURE; 368230557Sjimharris} 369230557Sjimharris 370230557Sjimharris/** 371230557Sjimharris * This method will add a PHY to the selected port. 372230557Sjimharris * 373230557Sjimharris * @param[in] this_port This parameter specifies the port in which the phy will 374230557Sjimharris * be added. 375230557Sjimharris * 376230557Sjimharris * @param[in] the_phy This parameter is the phy which is to be added to the 377230557Sjimharris * port. 378230557Sjimharris * 379230557Sjimharris * @return This method returns an SCI_STATUS. 380230557Sjimharris * @retval SCI_SUCCESS the phy has been added to the port. 381230557Sjimharris * @retval Any other status is failre to add the phy to the port. 382230557Sjimharris */ 383230557SjimharrisSCI_STATUS scic_sds_port_add_phy( 384230557Sjimharris SCIC_SDS_PORT_T * this_port, 385230557Sjimharris SCIC_SDS_PHY_T * the_phy 386230557Sjimharris) 387230557Sjimharris{ 388230557Sjimharris return this_port->state_handlers->parent.add_phy_handler( 389230557Sjimharris &this_port->parent, &the_phy->parent); 390230557Sjimharris} 391230557Sjimharris 392230557Sjimharris 393230557Sjimharris/** 394230557Sjimharris * This method will remove the PHY from the selected PORT. 395230557Sjimharris * 396230557Sjimharris * @param[in] this_port This parameter specifies the port in which the phy will 397230557Sjimharris * be added. 398230557Sjimharris * 399230557Sjimharris * @param[in] the_phy This parameter is the phy which is to be added to the 400230557Sjimharris * port. 401230557Sjimharris * 402230557Sjimharris * @return This method returns an SCI_STATUS. 403230557Sjimharris * @retval SCI_SUCCESS the phy has been removed from the port. 404230557Sjimharris * @retval Any other status is failre to add the phy to the port. 405230557Sjimharris */ 406230557SjimharrisSCI_STATUS scic_sds_port_remove_phy( 407230557Sjimharris SCIC_SDS_PORT_T * this_port, 408230557Sjimharris SCIC_SDS_PHY_T * the_phy 409230557Sjimharris) 410230557Sjimharris{ 411230557Sjimharris return this_port->state_handlers->parent.remove_phy_handler( 412230557Sjimharris &this_port->parent, &the_phy->parent); 413230557Sjimharris} 414230557Sjimharris 415230557Sjimharris/** 416230557Sjimharris * @brief This method requests the SAS address for the supplied SAS port 417230557Sjimharris * from the SCI implementation. 418230557Sjimharris * 419230557Sjimharris * @param[in] this_port a handle corresponding to the SAS port for which 420230557Sjimharris * to return the SAS address. 421230557Sjimharris * @param[out] sas_address This parameter specifies a pointer to a SAS 422230557Sjimharris * address structure into which the core will copy the SAS 423230557Sjimharris * address for the port. 424230557Sjimharris * 425230557Sjimharris * @return none 426230557Sjimharris */ 427230557Sjimharrisvoid scic_sds_port_get_sas_address( 428230557Sjimharris SCIC_SDS_PORT_T * this_port, 429230557Sjimharris SCI_SAS_ADDRESS_T * sas_address 430230557Sjimharris) 431230557Sjimharris{ 432230557Sjimharris U32 index; 433230557Sjimharris 434230557Sjimharris SCIC_LOG_TRACE(( 435230557Sjimharris sci_base_object_get_logger(this_port), 436230557Sjimharris SCIC_LOG_OBJECT_PORT, 437230557Sjimharris "scic_sds_port_get_sas_address(0x%x, 0x%x) enter\n", 438230557Sjimharris this_port, sas_address 439230557Sjimharris )); 440230557Sjimharris 441230557Sjimharris sas_address->high = 0; 442230557Sjimharris sas_address->low = 0; 443230557Sjimharris 444230557Sjimharris for (index = 0; index < SCI_MAX_PHYS; index++) 445230557Sjimharris { 446230557Sjimharris if (this_port->phy_table[index] != NULL) 447230557Sjimharris { 448230557Sjimharris scic_sds_phy_get_sas_address(this_port->phy_table[index], sas_address); 449230557Sjimharris } 450230557Sjimharris } 451230557Sjimharris} 452230557Sjimharris 453230557Sjimharris/** 454230557Sjimharris * @brief This method will indicate which protocols are supported by this 455230557Sjimharris * port. 456230557Sjimharris * 457230557Sjimharris * @param[in] this_port a handle corresponding to the SAS port for which 458230557Sjimharris * to return the supported protocols. 459230557Sjimharris * @param[out] protocols This parameter specifies a pointer to an IAF 460230557Sjimharris * protocol field structure into which the core will copy 461230557Sjimharris * the protocol values for the port. The values are 462230557Sjimharris * returned as part of a bit mask in order to allow for 463230557Sjimharris * multi-protocol support. 464230557Sjimharris * 465230557Sjimharris * @return none 466230557Sjimharris */ 467230557Sjimharrisstatic 468230557Sjimharrisvoid scic_sds_port_get_protocols( 469230557Sjimharris SCIC_SDS_PORT_T * this_port, 470230557Sjimharris SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS_T * protocols 471230557Sjimharris) 472230557Sjimharris{ 473230557Sjimharris U8 index; 474230557Sjimharris 475230557Sjimharris SCIC_LOG_TRACE(( 476230557Sjimharris sci_base_object_get_logger(this_port), 477230557Sjimharris SCIC_LOG_OBJECT_PORT, 478230557Sjimharris "scic_sds_port_get_protocols(0x%x, 0x%x) enter\n", 479230557Sjimharris this_port, protocols 480230557Sjimharris )); 481230557Sjimharris 482230557Sjimharris protocols->u.all = 0; 483230557Sjimharris 484230557Sjimharris for (index = 0; index < SCI_MAX_PHYS; index++) 485230557Sjimharris { 486230557Sjimharris if (this_port->phy_table[index] != NULL) 487230557Sjimharris { 488230557Sjimharris scic_sds_phy_get_protocols(this_port->phy_table[index], protocols); 489230557Sjimharris } 490230557Sjimharris } 491230557Sjimharris} 492230557Sjimharris 493230557Sjimharris/** 494230557Sjimharris * @brief This method requests the SAS address for the device directly 495230557Sjimharris * attached to this SAS port. 496230557Sjimharris * 497230557Sjimharris * @param[in] this_port a handle corresponding to the SAS port for which 498230557Sjimharris * to return the SAS address. 499230557Sjimharris * @param[out] sas_address This parameter specifies a pointer to a SAS 500230557Sjimharris * address structure into which the core will copy the SAS 501230557Sjimharris * address for the device directly attached to the port. 502230557Sjimharris * 503230557Sjimharris * @return none 504230557Sjimharris */ 505230557Sjimharrisvoid scic_sds_port_get_attached_sas_address( 506230557Sjimharris SCIC_SDS_PORT_T * this_port, 507230557Sjimharris SCI_SAS_ADDRESS_T * sas_address 508230557Sjimharris) 509230557Sjimharris{ 510230557Sjimharris SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS_T protocols; 511230557Sjimharris SCIC_SDS_PHY_T *phy; 512230557Sjimharris 513230557Sjimharris SCIC_LOG_TRACE(( 514230557Sjimharris sci_base_object_get_logger(this_port), 515230557Sjimharris SCIC_LOG_OBJECT_PORT, 516230557Sjimharris "scic_sds_port_get_attached_sas_address(0x%x, 0x%x) enter\n", 517230557Sjimharris this_port, sas_address 518230557Sjimharris )); 519230557Sjimharris 520230557Sjimharris // Ensure that the phy is both part of the port and currently 521230557Sjimharris // connected to the remote end-point. 522230557Sjimharris phy = scic_sds_port_get_a_connected_phy(this_port); 523230557Sjimharris if (phy != NULL) 524230557Sjimharris { 525230557Sjimharris scic_sds_phy_get_attached_phy_protocols(phy, &protocols); 526230557Sjimharris 527230557Sjimharris if (!protocols.u.bits.stp_target) 528230557Sjimharris { 529230557Sjimharris scic_sds_phy_get_attached_sas_address(phy, sas_address); 530230557Sjimharris } 531230557Sjimharris else 532230557Sjimharris { 533230557Sjimharris scic_sds_phy_get_sas_address(phy, sas_address); 534230557Sjimharris sas_address->low += phy->phy_index; 535230557Sjimharris 536230557Sjimharris //Need to make up attached STP device's SAS address in 537230557Sjimharris //the same order as recorded IAF from SSP device. 538230557Sjimharris sas_address->high = SCIC_SWAP_DWORD(sas_address->high); 539230557Sjimharris sas_address->low = SCIC_SWAP_DWORD(sas_address->low); 540230557Sjimharris } 541230557Sjimharris } 542230557Sjimharris else 543230557Sjimharris { 544230557Sjimharris sas_address->high = 0; 545230557Sjimharris sas_address->low = 0; 546230557Sjimharris } 547230557Sjimharris} 548230557Sjimharris 549230557Sjimharris/** 550230557Sjimharris * @brief This method will indicate which protocols are supported by this 551230557Sjimharris * remote device. 552230557Sjimharris * 553230557Sjimharris * @param[in] this_port a handle corresponding to the SAS port for which 554230557Sjimharris * to return the supported protocols. 555230557Sjimharris * @param[out] protocols This parameter specifies a pointer to an IAF 556230557Sjimharris * protocol field structure into which the core will copy 557230557Sjimharris * the protocol values for the port. The values are 558230557Sjimharris * returned as part of a bit mask in order to allow for 559230557Sjimharris * multi-protocol support. 560230557Sjimharris * 561230557Sjimharris * @return none 562230557Sjimharris */ 563230557Sjimharrisvoid scic_sds_port_get_attached_protocols( 564230557Sjimharris SCIC_SDS_PORT_T * this_port, 565230557Sjimharris SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS_T * protocols 566230557Sjimharris) 567230557Sjimharris{ 568230557Sjimharris SCIC_SDS_PHY_T *phy; 569230557Sjimharris 570230557Sjimharris SCIC_LOG_TRACE(( 571230557Sjimharris sci_base_object_get_logger(this_port), 572230557Sjimharris SCIC_LOG_OBJECT_PORT, 573230557Sjimharris "scic_sds_port_get_attached_protocols(0x%x, 0x%x) enter\n", 574230557Sjimharris this_port, protocols 575230557Sjimharris )); 576230557Sjimharris 577230557Sjimharris // Ensure that the phy is both part of the port and currently 578230557Sjimharris // connected to the remote end-point. 579230557Sjimharris phy = scic_sds_port_get_a_connected_phy(this_port); 580230557Sjimharris if (phy != NULL) 581230557Sjimharris scic_sds_phy_get_attached_phy_protocols(phy, protocols); 582230557Sjimharris else 583230557Sjimharris protocols->u.all = 0; 584230557Sjimharris} 585230557Sjimharris 586230557Sjimharris/** 587230557Sjimharris * @brief This method returns the amount of memory requred for a port 588230557Sjimharris * object. 589230557Sjimharris * 590230557Sjimharris * @return U32 591230557Sjimharris */ 592230557SjimharrisU32 scic_sds_port_get_object_size(void) 593230557Sjimharris{ 594230557Sjimharris return sizeof(SCIC_SDS_PORT_T); 595230557Sjimharris} 596230557Sjimharris 597230557Sjimharris/** 598230557Sjimharris * @brief This method returns the minimum number of timers required for all 599230557Sjimharris * port objects. 600230557Sjimharris * 601230557Sjimharris * @return U32 602230557Sjimharris */ 603230557SjimharrisU32 scic_sds_port_get_min_timer_count(void) 604230557Sjimharris{ 605230557Sjimharris return SCIC_SDS_PORT_MIN_TIMER_COUNT; 606230557Sjimharris} 607230557Sjimharris 608230557Sjimharris/** 609230557Sjimharris * @brief This method returns the maximum number of timers required for all 610230557Sjimharris * port objects. 611230557Sjimharris * 612230557Sjimharris * @return U32 613230557Sjimharris */ 614230557SjimharrisU32 scic_sds_port_get_max_timer_count(void) 615230557Sjimharris{ 616230557Sjimharris return SCIC_SDS_PORT_MAX_TIMER_COUNT; 617230557Sjimharris} 618230557Sjimharris 619230557Sjimharris#ifdef SCI_LOGGING 620230557Sjimharrisvoid scic_sds_port_initialize_state_logging( 621230557Sjimharris SCIC_SDS_PORT_T *this_port 622230557Sjimharris) 623230557Sjimharris{ 624230557Sjimharris sci_base_state_machine_logger_initialize( 625230557Sjimharris &this_port->parent.state_machine_logger, 626230557Sjimharris &this_port->parent.state_machine, 627230557Sjimharris &this_port->parent.parent, 628230557Sjimharris scic_cb_logger_log_states, 629230557Sjimharris "SCIC_SDS_PORT_T", "base state machine", 630230557Sjimharris SCIC_LOG_OBJECT_PORT 631230557Sjimharris ); 632230557Sjimharris 633230557Sjimharris sci_base_state_machine_logger_initialize( 634230557Sjimharris &this_port->ready_substate_machine_logger, 635230557Sjimharris &this_port->ready_substate_machine, 636230557Sjimharris &this_port->parent.parent, 637230557Sjimharris scic_cb_logger_log_states, 638230557Sjimharris "SCIC_SDS_PORT_T", "ready substate machine", 639230557Sjimharris SCIC_LOG_OBJECT_PORT 640230557Sjimharris ); 641230557Sjimharris} 642230557Sjimharris#endif 643230557Sjimharris 644230557Sjimharris/** 645230557Sjimharris * This routine will construct a dummy remote node context data structure 646230557Sjimharris * This structure will be posted to the hardware to work around a scheduler 647230557Sjimharris * error in the hardware. 648230557Sjimharris * 649230557Sjimharris * @param[in] this_port The logical port on which we need to create the 650230557Sjimharris * remote node context. 651230557Sjimharris * @param[in] rni The remote node index for this remote node context. 652230557Sjimharris * 653230557Sjimharris * @return none 654230557Sjimharris */ 655230557Sjimharrisstatic 656230557Sjimharrisvoid scic_sds_port_construct_dummy_rnc( 657230557Sjimharris SCIC_SDS_PORT_T *this_port, 658230557Sjimharris U16 rni 659230557Sjimharris) 660230557Sjimharris{ 661230557Sjimharris SCU_REMOTE_NODE_CONTEXT_T * rnc; 662230557Sjimharris 663230557Sjimharris rnc = &(this_port->owning_controller->remote_node_context_table[rni]); 664230557Sjimharris 665230557Sjimharris memset(rnc, 0, sizeof(SCU_REMOTE_NODE_CONTEXT_T)); 666230557Sjimharris 667230557Sjimharris rnc->ssp.remote_sas_address_hi = 0; 668230557Sjimharris rnc->ssp.remote_sas_address_lo = 0; 669230557Sjimharris 670230557Sjimharris rnc->ssp.remote_node_index = rni; 671230557Sjimharris rnc->ssp.remote_node_port_width = 1; 672230557Sjimharris rnc->ssp.logical_port_index = this_port->physical_port_index; 673230557Sjimharris 674230557Sjimharris rnc->ssp.nexus_loss_timer_enable = FALSE; 675230557Sjimharris rnc->ssp.check_bit = FALSE; 676230557Sjimharris rnc->ssp.is_valid = TRUE; 677230557Sjimharris rnc->ssp.is_remote_node_context = TRUE; 678230557Sjimharris rnc->ssp.function_number = 0; 679230557Sjimharris rnc->ssp.arbitration_wait_time = 0; 680230557Sjimharris} 681230557Sjimharris 682230557Sjimharris/** 683230557Sjimharris * This routine will construct a dummy task context data structure. This 684230557Sjimharris * structure will be posted to the hardwre to work around a scheduler error 685230557Sjimharris * in the hardware. 686230557Sjimharris * 687230557Sjimharris * @param[in] this_port The logical port on which we need to create the 688230557Sjimharris * remote node context. 689230557Sjimharris * context. 690230557Sjimharris * @param[in] tci The remote node index for this remote node context. 691230557Sjimharris * 692230557Sjimharris */ 693230557Sjimharrisstatic 694230557Sjimharrisvoid scic_sds_port_construct_dummy_task( 695230557Sjimharris SCIC_SDS_PORT_T *this_port, 696230557Sjimharris U16 tci 697230557Sjimharris) 698230557Sjimharris{ 699230557Sjimharris SCU_TASK_CONTEXT_T * task_context; 700230557Sjimharris 701230557Sjimharris task_context = scic_sds_controller_get_task_context_buffer(this_port->owning_controller, tci); 702230557Sjimharris 703230557Sjimharris memset(task_context, 0, sizeof(SCU_TASK_CONTEXT_T)); 704230557Sjimharris 705230557Sjimharris task_context->abort = 0; 706230557Sjimharris task_context->priority = 0; 707230557Sjimharris task_context->initiator_request = 1; 708230557Sjimharris task_context->connection_rate = 1; 709230557Sjimharris task_context->protocol_engine_index = 0; 710230557Sjimharris task_context->logical_port_index = this_port->physical_port_index; 711230557Sjimharris task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SSP; 712230557Sjimharris task_context->task_index = scic_sds_io_tag_get_index(tci); 713230557Sjimharris task_context->valid = SCU_TASK_CONTEXT_VALID; 714230557Sjimharris task_context->context_type = SCU_TASK_CONTEXT_TYPE; 715230557Sjimharris 716230557Sjimharris task_context->remote_node_index = this_port->reserved_rni; 717230557Sjimharris task_context->command_code = 0; 718230557Sjimharris 719230557Sjimharris task_context->link_layer_control = 0; 720230557Sjimharris task_context->do_not_dma_ssp_good_response = 1; 721230557Sjimharris task_context->strict_ordering = 0; 722230557Sjimharris task_context->control_frame = 0; 723230557Sjimharris task_context->timeout_enable = 0; 724230557Sjimharris task_context->block_guard_enable = 0; 725230557Sjimharris 726230557Sjimharris task_context->address_modifier = 0; 727230557Sjimharris 728230557Sjimharris task_context->task_phase = 0x01; 729230557Sjimharris} 730230557Sjimharris 731230557Sjimharris/** 732230557Sjimharris * This routine will free any allocated dummy resources for this port. 733230557Sjimharris * 734230557Sjimharris * @param[in, out] this_port The port on which the resources are being destroyed. 735230557Sjimharris */ 736230557Sjimharrisstatic 737230557Sjimharrisvoid scic_sds_port_destroy_dummy_resources( 738230557Sjimharris SCIC_SDS_PORT_T * this_port 739230557Sjimharris) 740230557Sjimharris{ 741230557Sjimharris if (this_port->reserved_tci != SCU_DUMMY_INDEX) 742230557Sjimharris { 743230557Sjimharris scic_controller_free_io_tag( 744230557Sjimharris this_port->owning_controller, this_port->reserved_tci 745230557Sjimharris ); 746230557Sjimharris } 747230557Sjimharris 748230557Sjimharris if (this_port->reserved_rni != SCU_DUMMY_INDEX) 749230557Sjimharris { 750230557Sjimharris scic_sds_remote_node_table_release_remote_node_index( 751230557Sjimharris &this_port->owning_controller->available_remote_nodes, 1, this_port->reserved_rni 752230557Sjimharris ); 753230557Sjimharris } 754230557Sjimharris 755230557Sjimharris this_port->reserved_rni = SCU_DUMMY_INDEX; 756230557Sjimharris this_port->reserved_tci = SCU_DUMMY_INDEX; 757230557Sjimharris} 758230557Sjimharris 759230557Sjimharris/** 760230557Sjimharris * @brief 761230557Sjimharris * 762230557Sjimharris * @param[in] this_port 763230557Sjimharris * @param[in] port_index 764230557Sjimharris * @param[in] owning_controller 765230557Sjimharris */ 766230557Sjimharrisvoid scic_sds_port_construct( 767230557Sjimharris SCIC_SDS_PORT_T *this_port, 768230557Sjimharris U8 port_index, 769230557Sjimharris SCIC_SDS_CONTROLLER_T *owning_controller 770230557Sjimharris) 771230557Sjimharris{ 772230557Sjimharris U32 index; 773230557Sjimharris 774230557Sjimharris sci_base_port_construct( 775230557Sjimharris &this_port->parent, 776230557Sjimharris sci_base_object_get_logger(owning_controller), 777230557Sjimharris scic_sds_port_state_table 778230557Sjimharris ); 779230557Sjimharris 780230557Sjimharris sci_base_state_machine_construct( 781230557Sjimharris scic_sds_port_get_ready_substate_machine(this_port), 782230557Sjimharris &this_port->parent.parent, 783230557Sjimharris scic_sds_port_ready_substate_table, 784230557Sjimharris SCIC_SDS_PORT_READY_SUBSTATE_WAITING 785230557Sjimharris ); 786230557Sjimharris 787230557Sjimharris scic_sds_port_initialize_state_logging(this_port); 788230557Sjimharris 789230557Sjimharris this_port->logical_port_index = SCIC_SDS_DUMMY_PORT; 790230557Sjimharris this_port->physical_port_index = port_index; 791230557Sjimharris this_port->active_phy_mask = 0; 792230557Sjimharris this_port->enabled_phy_mask = 0; 793230557Sjimharris this_port->owning_controller = owning_controller; 794230557Sjimharris 795230557Sjimharris this_port->started_request_count = 0; 796230557Sjimharris this_port->assigned_device_count = 0; 797230557Sjimharris 798230557Sjimharris this_port->reserved_rni = SCU_DUMMY_INDEX; 799230557Sjimharris this_port->reserved_tci = SCU_DUMMY_INDEX; 800230557Sjimharris 801230557Sjimharris this_port->timer_handle = SCI_INVALID_HANDLE; 802230557Sjimharris 803230557Sjimharris this_port->port_task_scheduler_registers = NULL; 804230557Sjimharris 805230557Sjimharris for (index = 0; index < SCI_MAX_PHYS; index++) 806230557Sjimharris { 807230557Sjimharris this_port->phy_table[index] = NULL; 808230557Sjimharris } 809230557Sjimharris} 810230557Sjimharris 811230557Sjimharris/** 812230557Sjimharris * @brief This method performs initialization of the supplied port. 813230557Sjimharris * Initialization includes: 814230557Sjimharris * - state machine initialization 815230557Sjimharris * - member variable initialization 816230557Sjimharris * - configuring the phy_mask 817230557Sjimharris * 818230557Sjimharris * @param[in] this_port 819230557Sjimharris * @param[in] transport_layer_registers 820230557Sjimharris * @param[in] port_task_scheduler_registers 821230557Sjimharris * @param[in] port_configuration_regsiter 822230557Sjimharris * 823230557Sjimharris * @return SCI_STATUS 824230557Sjimharris * @retval SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION This value is 825230557Sjimharris * returned if the phy being added to the port 826230557Sjimharris */ 827230557SjimharrisSCI_STATUS scic_sds_port_initialize( 828230557Sjimharris SCIC_SDS_PORT_T *this_port, 829230557Sjimharris void *port_task_scheduler_registers, 830230557Sjimharris void *port_configuration_regsiter, 831230557Sjimharris void *viit_registers 832230557Sjimharris) 833230557Sjimharris{ 834230557Sjimharris this_port->port_task_scheduler_registers = port_task_scheduler_registers; 835230557Sjimharris this_port->port_pe_configuration_register = port_configuration_regsiter; 836230557Sjimharris this_port->viit_registers = viit_registers; 837230557Sjimharris 838230557Sjimharris return SCI_SUCCESS; 839230557Sjimharris} 840230557Sjimharris 841230557Sjimharris/** 842230557Sjimharris * This method is the a general link up handler for the SCIC_SDS_PORT object. 843230557Sjimharris * This function will determine if this SCIC_SDS_PHY can 844230557Sjimharris * be assigned to this SCIC_SDS_PORT object. If the SCIC_SDS_PHY object can 845230557Sjimharris * is not a valid PHY for this port then the function will notify the SCIC_USER. 846230557Sjimharris * A PHY can only be part of a port if it's attached SAS ADDRESS is the same as 847230557Sjimharris * all other PHYs in the same port. 848230557Sjimharris * 849230557Sjimharris * @param[in] this_port This is the SCIC_SDS_PORT object for which has a phy 850230557Sjimharris * that has gone link up. 851230557Sjimharris * @param[in] the_phy This is the SCIC_SDS_PHY object that has gone link up. 852230557Sjimharris * @param[in] do_notify_user This parameter specifies whether to inform 853230557Sjimharris * the user (via scic_cb_port_link_up()) as to the fact that 854230557Sjimharris * a new phy as become ready. 855230557Sjimharris * @param[in] do_resume_phy This parameter specifies whether to resume the phy. 856230557Sjimharris * If this function is called from MPC mode, it will be always true. 857230557Sjimharris * for APC, this will be false, so that phys could be resumed later 858230557Sjimharris * 859230557Sjimharris * @return none 860230557Sjimharris */ 861230557Sjimharrisvoid scic_sds_port_general_link_up_handler( 862230557Sjimharris SCIC_SDS_PORT_T * this_port, 863230557Sjimharris SCIC_SDS_PHY_T * the_phy, 864230557Sjimharris BOOL do_notify_user, 865230557Sjimharris BOOL do_resume_phy 866230557Sjimharris) 867230557Sjimharris{ 868230557Sjimharris SCI_SAS_ADDRESS_T port_sas_address; 869230557Sjimharris SCI_SAS_ADDRESS_T phy_sas_address; 870230557Sjimharris 871230557Sjimharris scic_sds_port_get_attached_sas_address(this_port, &port_sas_address); 872230557Sjimharris scic_sds_phy_get_attached_sas_address(the_phy, &phy_sas_address); 873230557Sjimharris 874230557Sjimharris // If the SAS address of the new phy matches the SAS address of 875230557Sjimharris // other phys in the port OR this is the first phy in the port, 876230557Sjimharris // then activate the phy and allow it to be used for operations 877230557Sjimharris // in this port. 878230557Sjimharris if ( 879230557Sjimharris ( 880230557Sjimharris (phy_sas_address.high == port_sas_address.high) 881230557Sjimharris && (phy_sas_address.low == port_sas_address.low ) 882230557Sjimharris ) 883230557Sjimharris || (this_port->active_phy_mask == 0) 884230557Sjimharris ) 885230557Sjimharris { 886230557Sjimharris scic_sds_port_activate_phy(this_port, the_phy, do_notify_user, do_resume_phy); 887230557Sjimharris 888230557Sjimharris if (this_port->parent.state_machine.current_state_id 889230557Sjimharris == SCI_BASE_PORT_STATE_RESETTING) 890230557Sjimharris { 891230557Sjimharris sci_base_state_machine_change_state( 892230557Sjimharris &this_port->parent.state_machine, SCI_BASE_PORT_STATE_READY 893230557Sjimharris ); 894230557Sjimharris } 895230557Sjimharris } 896230557Sjimharris else 897230557Sjimharris { 898230557Sjimharris scic_sds_port_invalid_link_up(this_port, the_phy); 899230557Sjimharris } 900230557Sjimharris} 901230557Sjimharris 902230557Sjimharris// --------------------------------------------------------------------------- 903230557Sjimharris 904230557SjimharrisSCI_STATUS scic_port_add_phy( 905230557Sjimharris SCI_PORT_HANDLE_T handle, 906230557Sjimharris SCI_PHY_HANDLE_T phy 907230557Sjimharris) 908230557Sjimharris{ 909230557Sjimharris #if defined (SCI_LOGGING) 910230557Sjimharris SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)handle; 911230557Sjimharris #endif // defined (SCI_LOGGING) 912230557Sjimharris 913230557Sjimharris SCIC_LOG_TRACE(( 914230557Sjimharris sci_base_object_get_logger(this_port), 915230557Sjimharris SCIC_LOG_OBJECT_PORT, 916230557Sjimharris "scic_port_add_phy(0x%x, 0x%x) enter\n", 917230557Sjimharris handle, phy 918230557Sjimharris )); 919230557Sjimharris 920230557Sjimharris SCIC_LOG_ERROR(( 921230557Sjimharris sci_base_object_get_logger(this_port), 922230557Sjimharris SCIC_LOG_OBJECT_PORT, 923230557Sjimharris "Interface function scic_port_add_phy() has been deprecated. " 924230557Sjimharris "PORT configuration is handled through the OEM parameters.\n" 925230557Sjimharris )); 926230557Sjimharris 927230557Sjimharris return SCI_FAILURE_ADDING_PHY_UNSUPPORTED; 928230557Sjimharris 929230557Sjimharris} 930230557Sjimharris 931230557Sjimharris// --------------------------------------------------------------------------- 932230557Sjimharris 933230557SjimharrisSCI_STATUS scic_port_remove_phy( 934230557Sjimharris SCI_PORT_HANDLE_T handle, 935230557Sjimharris SCI_PHY_HANDLE_T phy 936230557Sjimharris) 937230557Sjimharris{ 938230557Sjimharris #if defined (SCI_LOGGING) 939230557Sjimharris SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)handle; 940230557Sjimharris #endif // defined (SCI_LOGGING) 941230557Sjimharris 942230557Sjimharris SCIC_LOG_TRACE(( 943230557Sjimharris sci_base_object_get_logger(this_port), 944230557Sjimharris SCIC_LOG_OBJECT_PORT, 945230557Sjimharris "scic_port_remove_phy(0x%x, 0x%x) enter\n", 946230557Sjimharris handle, phy 947230557Sjimharris )); 948230557Sjimharris 949230557Sjimharris SCIC_LOG_ERROR(( 950230557Sjimharris sci_base_object_get_logger(this_port), 951230557Sjimharris SCIC_LOG_OBJECT_PORT, 952230557Sjimharris "Interface function scic_port_remove_phy() has been deprecated. " 953230557Sjimharris "PORT configuration is handled through the OEM parameters.\n" 954230557Sjimharris )); 955230557Sjimharris 956230557Sjimharris return SCI_FAILURE_ADDING_PHY_UNSUPPORTED; 957230557Sjimharris} 958230557Sjimharris 959230557Sjimharris// --------------------------------------------------------------------------- 960230557Sjimharris 961230557SjimharrisSCI_STATUS scic_port_get_properties( 962230557Sjimharris SCI_PORT_HANDLE_T port, 963230557Sjimharris SCIC_PORT_PROPERTIES_T * properties 964230557Sjimharris) 965230557Sjimharris{ 966230557Sjimharris SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)port; 967230557Sjimharris 968230557Sjimharris SCIC_LOG_TRACE(( 969230557Sjimharris sci_base_object_get_logger(this_port), 970230557Sjimharris SCIC_LOG_OBJECT_PORT, 971230557Sjimharris "scic_port_get_properties(0x%x, 0x%x) enter\n", 972230557Sjimharris port, properties 973230557Sjimharris )); 974230557Sjimharris 975230557Sjimharris if ( 976230557Sjimharris (port == SCI_INVALID_HANDLE) 977230557Sjimharris || (this_port->logical_port_index == SCIC_SDS_DUMMY_PORT) 978230557Sjimharris ) 979230557Sjimharris { 980230557Sjimharris return SCI_FAILURE_INVALID_PORT; 981230557Sjimharris } 982230557Sjimharris 983230557Sjimharris properties->index = this_port->logical_port_index; 984230557Sjimharris properties->phy_mask = scic_sds_port_get_phys(this_port); 985230557Sjimharris scic_sds_port_get_sas_address(this_port, &properties->local.sas_address); 986230557Sjimharris scic_sds_port_get_protocols(this_port, &properties->local.protocols); 987230557Sjimharris scic_sds_port_get_attached_sas_address(this_port, &properties->remote.sas_address); 988230557Sjimharris scic_sds_port_get_attached_protocols(this_port, &properties->remote.protocols); 989230557Sjimharris 990230557Sjimharris return SCI_SUCCESS; 991230557Sjimharris} 992230557Sjimharris 993230557Sjimharris// --------------------------------------------------------------------------- 994230557Sjimharris 995230557SjimharrisSCI_STATUS scic_port_hard_reset( 996230557Sjimharris SCI_PORT_HANDLE_T handle, 997230557Sjimharris U32 reset_timeout 998230557Sjimharris) 999230557Sjimharris{ 1000230557Sjimharris SCIC_SDS_PORT_T * this_port = (SCIC_SDS_PORT_T *)handle; 1001230557Sjimharris 1002230557Sjimharris SCIC_LOG_TRACE(( 1003230557Sjimharris sci_base_object_get_logger(this_port), 1004230557Sjimharris SCIC_LOG_OBJECT_PORT, 1005230557Sjimharris "scic_port_hard_reset(0x%x, 0x%x) enter\n", 1006230557Sjimharris handle, reset_timeout 1007230557Sjimharris )); 1008230557Sjimharris 1009230557Sjimharris return this_port->state_handlers->parent.reset_handler( 1010230557Sjimharris &this_port->parent, 1011230557Sjimharris reset_timeout 1012230557Sjimharris ); 1013230557Sjimharris} 1014230557Sjimharris 1015230557Sjimharris/** 1016230557Sjimharris * This method assigns the direct attached device ID for this port. 1017230557Sjimharris * 1018230557Sjimharris * @param[in] this_port The port for which the direct attached device id is to 1019230557Sjimharris * be assigned. 1020230557Sjimharris * @param[in] device_id The direct attached device ID to assign to the port. 1021230557Sjimharris * This will be the RNi for the device 1022230557Sjimharris */ 1023230557Sjimharrisvoid scic_sds_port_setup_transports( 1024230557Sjimharris SCIC_SDS_PORT_T * this_port, 1025230557Sjimharris U32 device_id 1026230557Sjimharris) 1027230557Sjimharris{ 1028230557Sjimharris U8 index; 1029230557Sjimharris 1030230557Sjimharris for (index = 0; index < SCI_MAX_PHYS; index++) 1031230557Sjimharris { 1032230557Sjimharris if (this_port->active_phy_mask & (1 << index)) 1033230557Sjimharris { 1034230557Sjimharris scic_sds_phy_setup_transport(this_port->phy_table[index], device_id); 1035230557Sjimharris } 1036230557Sjimharris } 1037230557Sjimharris} 1038230557Sjimharris 1039230557Sjimharris/** 1040230557Sjimharris * This method will resume the phy which is already added in the port. 1041230557Sjimharris * Activation includes: 1042230557Sjimharris * - enabling the Protocol Engine in the silicon. 1043230557Sjimharris * - update the reay mask. 1044230557Sjimharris * 1045230557Sjimharris * @param[in] this_port This is the port on which the phy should be enabled. 1046230557Sjimharris * @return none 1047230557Sjimharris */ 1048230557Sjimharrisstatic 1049230557Sjimharrisvoid scic_sds_port_resume_phy( 1050230557Sjimharris SCIC_SDS_PORT_T * this_port, 1051230557Sjimharris SCIC_SDS_PHY_T * the_phy 1052230557Sjimharris) 1053230557Sjimharris{ 1054230557Sjimharris scic_sds_phy_resume (the_phy); 1055230557Sjimharris this_port->enabled_phy_mask |= 1 << the_phy->phy_index; 1056230557Sjimharris} 1057230557Sjimharris/** 1058230557Sjimharris * This method will activate the phy in the port. 1059230557Sjimharris * Activation includes: 1060230557Sjimharris * - adding the phy to the port 1061230557Sjimharris * - enabling the Protocol Engine in the silicon. 1062230557Sjimharris * - notifying the user that the link is up. 1063230557Sjimharris * 1064230557Sjimharris * @param[in] this_port This is the port on which the phy should be enabled. 1065230557Sjimharris * @param[in] the_phy This is the specific phy which to enable. 1066230557Sjimharris * @param[in] do_notify_user This parameter specifies whether to inform 1067230557Sjimharris * the user (via scic_cb_port_link_up()) as to the fact that 1068230557Sjimharris * a new phy as become ready. 1069230557Sjimharris * @param[in] do_resume_phy This parameter specifies whether to resume the phy. 1070230557Sjimharris * If this function is called from MPC mode, it will be always true. 1071230557Sjimharris * for APC, this will be false, so that phys could be resumed later 1072230557Sjimharris * 1073230557Sjimharris 1074230557Sjimharris * @return none 1075230557Sjimharris */ 1076230557Sjimharrisvoid scic_sds_port_activate_phy( 1077230557Sjimharris SCIC_SDS_PORT_T * this_port, 1078230557Sjimharris SCIC_SDS_PHY_T * the_phy, 1079230557Sjimharris BOOL do_notify_user, 1080230557Sjimharris BOOL do_resume_phy 1081230557Sjimharris) 1082230557Sjimharris{ 1083230557Sjimharris SCIC_SDS_CONTROLLER_T * controller; 1084230557Sjimharris SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS_T protocols; 1085230557Sjimharris 1086230557Sjimharris SCIC_LOG_TRACE(( 1087230557Sjimharris sci_base_object_get_logger(this_port), 1088230557Sjimharris SCIC_LOG_OBJECT_PORT, 1089230557Sjimharris "scic_sds_port_activate_phy(0x%x,0x%x,0x%x) enter\n", 1090230557Sjimharris this_port, the_phy, do_notify_user 1091230557Sjimharris )); 1092230557Sjimharris 1093230557Sjimharris controller = scic_sds_port_get_controller(this_port); 1094230557Sjimharris scic_sds_phy_get_attached_phy_protocols(the_phy, &protocols); 1095230557Sjimharris 1096230557Sjimharris // If this is sata port then the phy has already been resumed 1097230557Sjimharris if (!protocols.u.bits.stp_target) 1098230557Sjimharris { 1099230557Sjimharris if (do_resume_phy == TRUE) 1100230557Sjimharris { 1101230557Sjimharris scic_sds_port_resume_phy(this_port, the_phy); 1102230557Sjimharris } 1103230557Sjimharris } 1104230557Sjimharris 1105230557Sjimharris this_port->active_phy_mask |= 1 << the_phy->phy_index; 1106230557Sjimharris 1107230557Sjimharris scic_sds_controller_clear_invalid_phy(controller, the_phy); 1108230557Sjimharris 1109230557Sjimharris if (do_notify_user == TRUE) 1110230557Sjimharris scic_cb_port_link_up(this_port->owning_controller, this_port, the_phy); 1111230557Sjimharris} 1112230557Sjimharris 1113230557Sjimharris/** 1114230557Sjimharris * This method will deactivate the supplied phy in the port. 1115230557Sjimharris * 1116230557Sjimharris * @param[in] this_port This is the port on which the phy should be 1117230557Sjimharris * deactivated. 1118230557Sjimharris * @param[in] the_phy This is the specific phy that is no longer 1119230557Sjimharris * active in the port. 1120230557Sjimharris * @param[in] do_notify_user This parameter specifies whether to inform 1121230557Sjimharris * the user (via scic_cb_port_link_down()) as to the fact that 1122230557Sjimharris * a new phy as become ready. 1123230557Sjimharris * 1124230557Sjimharris * @return none 1125230557Sjimharris */ 1126230557Sjimharrisvoid scic_sds_port_deactivate_phy( 1127230557Sjimharris SCIC_SDS_PORT_T * this_port, 1128230557Sjimharris SCIC_SDS_PHY_T * the_phy, 1129230557Sjimharris BOOL do_notify_user 1130230557Sjimharris) 1131230557Sjimharris{ 1132230557Sjimharris SCIC_LOG_TRACE(( 1133230557Sjimharris sci_base_object_get_logger(this_port), 1134230557Sjimharris SCIC_LOG_OBJECT_PORT, 1135230557Sjimharris "scic_sds_port_deactivate_phy(0x%x,0x%x,0x%x) enter\n", 1136230557Sjimharris this_port, the_phy, do_notify_user 1137230557Sjimharris )); 1138230557Sjimharris 1139230557Sjimharris this_port->active_phy_mask &= ~(1 << the_phy->phy_index); 1140230557Sjimharris this_port->enabled_phy_mask &= ~(1 << the_phy->phy_index); 1141230557Sjimharris 1142230557Sjimharris the_phy->max_negotiated_speed = SCI_SAS_NO_LINK_RATE; 1143230557Sjimharris 1144230557Sjimharris // Re-assign the phy back to the LP as if it were a narrow port for APC mode. 1145230557Sjimharris // For MPC mode, the phy will remain in the port 1146230557Sjimharris if (this_port->owning_controller->oem_parameters.sds1.controller.mode_type 1147230557Sjimharris == SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE) 1148230557Sjimharris { 1149230557Sjimharris SCU_PCSPExCR_WRITE(this_port, the_phy->phy_index, the_phy->phy_index); 1150230557Sjimharris } 1151230557Sjimharris 1152230557Sjimharris if (do_notify_user == TRUE) 1153230557Sjimharris scic_cb_port_link_down(this_port->owning_controller, this_port, the_phy); 1154230557Sjimharris} 1155230557Sjimharris 1156230557Sjimharris/** 1157230557Sjimharris * This method will disable the phy and report that the phy is not valid for this 1158230557Sjimharris * port object. 1159230557Sjimharris * 1160230557Sjimharris * @param[in] this_port This is the port on which the phy should be disabled. 1161230557Sjimharris * @param[in] the_phy This is the specific phy which to disabled. 1162230557Sjimharris * 1163230557Sjimharris * @return None 1164230557Sjimharris */ 1165230557Sjimharrisvoid scic_sds_port_invalid_link_up( 1166230557Sjimharris SCIC_SDS_PORT_T * this_port, 1167230557Sjimharris SCIC_SDS_PHY_T * the_phy 1168230557Sjimharris) 1169230557Sjimharris{ 1170230557Sjimharris SCIC_SDS_CONTROLLER_T * controller = scic_sds_port_get_controller(this_port); 1171230557Sjimharris 1172230557Sjimharris // Check to see if we have alreay reported this link as bad and if not go 1173230557Sjimharris // ahead and tell the SCI_USER that we have discovered an invalid link. 1174230557Sjimharris if ((controller->invalid_phy_mask & (1 << the_phy->phy_index)) == 0) 1175230557Sjimharris { 1176230557Sjimharris scic_sds_controller_set_invalid_phy(controller, the_phy); 1177230557Sjimharris 1178230557Sjimharris scic_cb_port_invalid_link_up(controller, this_port, the_phy); 1179230557Sjimharris } 1180230557Sjimharris} 1181230557Sjimharris 1182230557Sjimharris/** 1183230557Sjimharris * @brief This method returns FALSE if the port only has a single phy object 1184230557Sjimharris * assigned. If there are no phys or more than one phy then the 1185230557Sjimharris * method will return TRUE. 1186230557Sjimharris * 1187230557Sjimharris * @param[in] this_port The port for which the wide port condition is to be 1188230557Sjimharris * checked. 1189230557Sjimharris * 1190230557Sjimharris * @return BOOL 1191230557Sjimharris * @retval TRUE Is returned if this is a wide ported port. 1192230557Sjimharris * @retval FALSE Is returned if this is a narrow port. 1193230557Sjimharris */ 1194230557Sjimharrisstatic 1195230557SjimharrisBOOL scic_sds_port_is_wide( 1196230557Sjimharris SCIC_SDS_PORT_T *this_port 1197230557Sjimharris) 1198230557Sjimharris{ 1199230557Sjimharris U32 index; 1200230557Sjimharris U32 phy_count = 0; 1201230557Sjimharris 1202230557Sjimharris for (index = 0; index < SCI_MAX_PHYS; index++) 1203230557Sjimharris { 1204230557Sjimharris if (this_port->phy_table[index] != NULL) 1205230557Sjimharris { 1206230557Sjimharris phy_count++; 1207230557Sjimharris } 1208230557Sjimharris } 1209230557Sjimharris 1210230557Sjimharris return (phy_count != 1); 1211230557Sjimharris} 1212230557Sjimharris 1213230557Sjimharris/** 1214230557Sjimharris * @brief This method is called by the PHY object when the link is detected. 1215230557Sjimharris * if the port wants the PHY to continue on to the link up state then 1216230557Sjimharris * the port layer must return TRUE. If the port object returns FALSE 1217230557Sjimharris * the phy object must halt its attempt to go link up. 1218230557Sjimharris * 1219230557Sjimharris * @param[in] this_port The port associated with the phy object. 1220230557Sjimharris * @param[in] the_phy The phy object that is trying to go link up. 1221230557Sjimharris * 1222230557Sjimharris * @return TRUE if the phy object can continue to the link up condition. 1223230557Sjimharris * @retval TRUE Is returned if this phy can continue to the ready state. 1224230557Sjimharris * @retval FALSE Is returned if can not continue on to the ready state. 1225230557Sjimharris * 1226230557Sjimharris * @note This notification is in place for wide ports and direct attached 1227230557Sjimharris * phys. Since there are no wide ported SATA devices this could 1228230557Sjimharris * become an invalid port configuration. 1229230557Sjimharris */ 1230230557SjimharrisBOOL scic_sds_port_link_detected( 1231230557Sjimharris SCIC_SDS_PORT_T *this_port, 1232230557Sjimharris SCIC_SDS_PHY_T *the_phy 1233230557Sjimharris) 1234230557Sjimharris{ 1235230557Sjimharris SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS_T protocols; 1236230557Sjimharris 1237230557Sjimharris scic_sds_phy_get_attached_phy_protocols(the_phy, &protocols); 1238230557Sjimharris 1239230557Sjimharris if ( 1240230557Sjimharris (this_port->logical_port_index != SCIC_SDS_DUMMY_PORT) 1241230557Sjimharris && (protocols.u.bits.stp_target) 1242230557Sjimharris ) 1243230557Sjimharris { 1244230557Sjimharris if (scic_sds_port_is_wide(this_port)) 1245230557Sjimharris { 1246230557Sjimharris //direct attached Sata phy cannot be in wide port. 1247230557Sjimharris scic_sds_port_invalid_link_up( this_port, the_phy); 1248230557Sjimharris return FALSE; 1249230557Sjimharris } 1250230557Sjimharris else 1251230557Sjimharris { 1252230557Sjimharris SCIC_SDS_PORT_T *destination_port = &(this_port->owning_controller->port_table[the_phy->phy_index]); 1253230557Sjimharris 1254230557Sjimharris //add the phy to the its logical port for direct attached SATA. The phy will be added 1255230557Sjimharris //to port whose port_index will be the phy_index. 1256230557Sjimharris SCU_PCSPExCR_WRITE( destination_port, the_phy->phy_index, the_phy->phy_index); 1257230557Sjimharris } 1258230557Sjimharris } 1259230557Sjimharris 1260230557Sjimharris return TRUE; 1261230557Sjimharris} 1262230557Sjimharris 1263230557Sjimharris/** 1264230557Sjimharris * @brief This method is the entry point for the phy to inform 1265230557Sjimharris * the port that it is now in a ready state 1266230557Sjimharris * 1267230557Sjimharris * @param[in] this_port 1268230557Sjimharris * @param[in] phy 1269230557Sjimharris */ 1270230557Sjimharrisvoid scic_sds_port_link_up( 1271230557Sjimharris SCIC_SDS_PORT_T *this_port, 1272230557Sjimharris SCIC_SDS_PHY_T *the_phy 1273230557Sjimharris) 1274230557Sjimharris{ 1275230557Sjimharris the_phy->is_in_link_training = FALSE; 1276230557Sjimharris 1277230557Sjimharris this_port->state_handlers->link_up_handler(this_port, the_phy); 1278230557Sjimharris} 1279230557Sjimharris 1280230557Sjimharris/** 1281230557Sjimharris * @brief This method is the entry point for the phy to inform 1282230557Sjimharris * the port that it is no longer in a ready state 1283230557Sjimharris * 1284230557Sjimharris * @param[in] this_port 1285230557Sjimharris * @param[in] phy 1286230557Sjimharris */ 1287230557Sjimharrisvoid scic_sds_port_link_down( 1288230557Sjimharris SCIC_SDS_PORT_T *this_port, 1289230557Sjimharris SCIC_SDS_PHY_T *the_phy 1290230557Sjimharris) 1291230557Sjimharris{ 1292230557Sjimharris this_port->state_handlers->link_down_handler(this_port, the_phy); 1293230557Sjimharris} 1294230557Sjimharris 1295230557Sjimharris/** 1296230557Sjimharris * @brief This method is called to start an IO request on this port. 1297230557Sjimharris * 1298230557Sjimharris * @param[in] this_port 1299230557Sjimharris * @param[in] the_device 1300230557Sjimharris * @param[in] the_io_request 1301230557Sjimharris * 1302230557Sjimharris * @return SCI_STATUS 1303230557Sjimharris */ 1304230557SjimharrisSCI_STATUS scic_sds_port_start_io( 1305230557Sjimharris SCIC_SDS_PORT_T *this_port, 1306230557Sjimharris SCIC_SDS_REMOTE_DEVICE_T *the_device, 1307230557Sjimharris SCIC_SDS_REQUEST_T *the_io_request 1308230557Sjimharris) 1309230557Sjimharris{ 1310230557Sjimharris return this_port->state_handlers->start_io_handler( 1311230557Sjimharris this_port, the_device, the_io_request); 1312230557Sjimharris} 1313230557Sjimharris 1314230557Sjimharris/** 1315230557Sjimharris * @brief This method is called to complete an IO request to the port. 1316230557Sjimharris * 1317230557Sjimharris * @param[in] this_port 1318230557Sjimharris * @param[in] the_device 1319230557Sjimharris * @param[in] the_io_request 1320230557Sjimharris * 1321230557Sjimharris * @return SCI_STATUS 1322230557Sjimharris */ 1323230557SjimharrisSCI_STATUS scic_sds_port_complete_io( 1324230557Sjimharris SCIC_SDS_PORT_T *this_port, 1325230557Sjimharris SCIC_SDS_REMOTE_DEVICE_T *the_device, 1326230557Sjimharris SCIC_SDS_REQUEST_T *the_io_request 1327230557Sjimharris) 1328230557Sjimharris{ 1329230557Sjimharris return this_port->state_handlers->complete_io_handler( 1330230557Sjimharris this_port, the_device, the_io_request); 1331230557Sjimharris} 1332230557Sjimharris 1333230557Sjimharris/** 1334230557Sjimharris * @brief This method is provided to timeout requests for port operations. 1335230557Sjimharris * Mostly its for the port reset operation. 1336230557Sjimharris * 1337230557Sjimharris * @param[in] port This is the parameter or cookie value that is provided 1338230557Sjimharris * to the timer construct operation. 1339230557Sjimharris */ 1340230557Sjimharrisvoid scic_sds_port_timeout_handler( 1341230557Sjimharris void *port 1342230557Sjimharris) 1343230557Sjimharris{ 1344230557Sjimharris U32 current_state; 1345230557Sjimharris SCIC_SDS_PORT_T * this_port; 1346230557Sjimharris 1347230557Sjimharris this_port = (SCIC_SDS_PORT_T *)port; 1348230557Sjimharris current_state = sci_base_state_machine_get_state( 1349230557Sjimharris &this_port->parent.state_machine); 1350230557Sjimharris 1351230557Sjimharris if (current_state == SCI_BASE_PORT_STATE_RESETTING) 1352230557Sjimharris { 1353230557Sjimharris // if the port is still in the resetting state then the timeout fired 1354230557Sjimharris // before the reset completed. 1355230557Sjimharris sci_base_state_machine_change_state( 1356230557Sjimharris &this_port->parent.state_machine, 1357230557Sjimharris SCI_BASE_PORT_STATE_FAILED 1358230557Sjimharris ); 1359230557Sjimharris } 1360230557Sjimharris else if (current_state == SCI_BASE_PORT_STATE_STOPPED) 1361230557Sjimharris { 1362230557Sjimharris // if the port is stopped then the start request failed 1363230557Sjimharris // In this case stay in the stopped state. 1364230557Sjimharris SCIC_LOG_ERROR(( 1365230557Sjimharris sci_base_object_get_logger(this_port), 1366230557Sjimharris SCIC_LOG_OBJECT_PORT, 1367230557Sjimharris "SCIC Port 0x%x failed to stop before tiemout.\n", 1368230557Sjimharris this_port 1369230557Sjimharris )); 1370230557Sjimharris } 1371230557Sjimharris else if (current_state == SCI_BASE_PORT_STATE_STOPPING) 1372230557Sjimharris { 1373230557Sjimharris // if the port is still stopping then the stop has not completed 1374230557Sjimharris scic_cb_port_stop_complete( 1375230557Sjimharris scic_sds_port_get_controller(this_port), 1376230557Sjimharris port, 1377230557Sjimharris SCI_FAILURE_TIMEOUT 1378230557Sjimharris ); 1379230557Sjimharris } 1380230557Sjimharris else 1381230557Sjimharris { 1382230557Sjimharris // The port is in the ready state and we have a timer reporting a timeout 1383230557Sjimharris // this should not happen. 1384230557Sjimharris SCIC_LOG_ERROR(( 1385230557Sjimharris sci_base_object_get_logger(this_port), 1386230557Sjimharris SCIC_LOG_OBJECT_PORT, 1387230557Sjimharris "SCIC Port 0x%x is processing a timeout operation in state %d.\n", 1388230557Sjimharris this_port, current_state 1389230557Sjimharris )); 1390230557Sjimharris } 1391230557Sjimharris} 1392230557Sjimharris 1393230557Sjimharris// --------------------------------------------------------------------------- 1394230557Sjimharris 1395230557Sjimharris#ifdef SCIC_DEBUG_ENABLED 1396230557Sjimharrisvoid scic_sds_port_decrement_request_count( 1397230557Sjimharris SCIC_SDS_PORT_T *this_port 1398230557Sjimharris) 1399230557Sjimharris{ 1400230557Sjimharris if (this_port->started_request_count == 0) 1401230557Sjimharris { 1402230557Sjimharris SCIC_LOG_WARNING(( 1403230557Sjimharris sci_base_object_get_logger(this_port), 1404230557Sjimharris SCIC_LOG_OBJECT_PORT, 1405230557Sjimharris "SCIC Port object requested to decrement started io count past zero.\n" 1406230557Sjimharris )); 1407230557Sjimharris } 1408230557Sjimharris else 1409230557Sjimharris { 1410230557Sjimharris this_port->started_request_count--; 1411230557Sjimharris } 1412230557Sjimharris} 1413230557Sjimharris#endif 1414230557Sjimharris 1415230557Sjimharris/** 1416230557Sjimharris * @brief This function updates the hardwares VIIT entry for this port. 1417230557Sjimharris * 1418230557Sjimharris * @param[in] this_port 1419230557Sjimharris */ 1420230557Sjimharrisvoid scic_sds_port_update_viit_entry( 1421230557Sjimharris SCIC_SDS_PORT_T *this_port 1422230557Sjimharris) 1423230557Sjimharris{ 1424230557Sjimharris SCI_SAS_ADDRESS_T sas_address; 1425230557Sjimharris 1426230557Sjimharris scic_sds_port_get_sas_address(this_port, &sas_address); 1427230557Sjimharris 1428230557Sjimharris scu_port_viit_register_write( 1429230557Sjimharris this_port, initiator_sas_address_hi, sas_address.high); 1430230557Sjimharris 1431230557Sjimharris scu_port_viit_register_write( 1432230557Sjimharris this_port, initiator_sas_address_lo, sas_address.low); 1433230557Sjimharris 1434230557Sjimharris // This value get cleared just in case its not already cleared 1435230557Sjimharris scu_port_viit_register_write( 1436230557Sjimharris this_port, reserved, 0); 1437230557Sjimharris 1438230557Sjimharris 1439230557Sjimharris // We are required to update the status register last 1440230557Sjimharris scu_port_viit_register_write( 1441230557Sjimharris this_port, status, ( 1442230557Sjimharris SCU_VIIT_ENTRY_ID_VIIT 1443230557Sjimharris | SCU_VIIT_IPPT_INITIATOR 1444230557Sjimharris | ((1UL << this_port->physical_port_index) << SCU_VIIT_ENTRY_LPVIE_SHIFT) 1445230557Sjimharris | SCU_VIIT_STATUS_ALL_VALID 1446230557Sjimharris ) 1447230557Sjimharris ); 1448230557Sjimharris} 1449230557Sjimharris 1450230557Sjimharris/** 1451230557Sjimharris * @brief This method returns the maximum allowed speed for data transfers 1452230557Sjimharris * on this port. This maximum allowed speed evaluates to the maximum 1453230557Sjimharris * speed of the slowest phy in the port. 1454230557Sjimharris * 1455230557Sjimharris * @param[in] this_port This parameter specifies the port for which to 1456230557Sjimharris * retrieve the maximum allowed speed. 1457230557Sjimharris * 1458230557Sjimharris * @return This method returns the maximum negotiated speed of the slowest 1459230557Sjimharris * phy in the port. 1460230557Sjimharris */ 1461230557SjimharrisSCI_SAS_LINK_RATE scic_sds_port_get_max_allowed_speed( 1462230557Sjimharris SCIC_SDS_PORT_T * this_port 1463230557Sjimharris) 1464230557Sjimharris{ 1465230557Sjimharris U16 index = 0; 1466230557Sjimharris SCI_SAS_LINK_RATE max_allowed_speed = SCI_SAS_600_GB; 1467230557Sjimharris SCIC_SDS_PHY_T * phy = NULL; 1468230557Sjimharris 1469230557Sjimharris // Loop through all of the phys in this port and find the phy with the 1470230557Sjimharris // lowest maximum link rate. 1471230557Sjimharris for (index = 0; index < SCI_MAX_PHYS; index++) 1472230557Sjimharris { 1473230557Sjimharris phy = this_port->phy_table[index]; 1474230557Sjimharris if ( 1475230557Sjimharris (phy != NULL) 1476230557Sjimharris && (scic_sds_port_active_phy(this_port, phy) == TRUE) 1477230557Sjimharris && (phy->max_negotiated_speed < max_allowed_speed) 1478230557Sjimharris ) 1479230557Sjimharris max_allowed_speed = phy->max_negotiated_speed; 1480230557Sjimharris } 1481230557Sjimharris 1482230557Sjimharris return max_allowed_speed; 1483230557Sjimharris} 1484230557Sjimharris 1485230557Sjimharris 1486230557Sjimharris/** 1487230557Sjimharris * @brief This method passes the event to core user. 1488230557Sjimharris * @param[in] this_port The port that a BCN happens. 1489230557Sjimharris * @param[in] this_phy The phy that receives BCN. 1490230557Sjimharris * 1491230557Sjimharris * @return none 1492230557Sjimharris */ 1493230557Sjimharrisvoid scic_sds_port_broadcast_change_received( 1494230557Sjimharris SCIC_SDS_PORT_T * this_port, 1495230557Sjimharris SCIC_SDS_PHY_T * this_phy 1496230557Sjimharris) 1497230557Sjimharris{ 1498230557Sjimharris //notify the user. 1499230557Sjimharris scic_cb_port_bc_change_primitive_recieved( 1500230557Sjimharris this_port->owning_controller, this_port, this_phy 1501230557Sjimharris ); 1502230557Sjimharris} 1503230557Sjimharris 1504230557Sjimharris 1505230557Sjimharris/** 1506230557Sjimharris * @brief This API methhod enables the broadcast change notification from 1507230557Sjimharris * underneath hardware. 1508230557Sjimharris * @param[in] this_port The port that a BCN had been disabled from. 1509230557Sjimharris * 1510230557Sjimharris * @return none 1511230557Sjimharris */ 1512230557Sjimharrisvoid scic_port_enable_broadcast_change_notification( 1513230557Sjimharris SCI_PORT_HANDLE_T port 1514230557Sjimharris) 1515230557Sjimharris{ 1516230557Sjimharris SCIC_SDS_PORT_T * this_port = (SCIC_SDS_PORT_T *)port; 1517230557Sjimharris SCIC_SDS_PHY_T * phy; 1518230557Sjimharris U32 register_value; 1519230557Sjimharris U8 index; 1520230557Sjimharris 1521230557Sjimharris // Loop through all of the phys to enable BCN. 1522230557Sjimharris for (index = 0; index < SCI_MAX_PHYS; index++) 1523230557Sjimharris { 1524230557Sjimharris phy = this_port->phy_table[index]; 1525230557Sjimharris if ( phy != NULL) 1526230557Sjimharris { 1527230557Sjimharris register_value = SCU_SAS_LLCTL_READ(phy); 1528230557Sjimharris 1529230557Sjimharris // clear the bit by writing 1. 1530230557Sjimharris SCU_SAS_LLCTL_WRITE(phy, register_value); 1531230557Sjimharris } 1532230557Sjimharris } 1533230557Sjimharris} 1534230557Sjimharris 1535230557Sjimharris/** 1536230557Sjimharris * @brief This method release resources in for a scic port. 1537230557Sjimharris * 1538230557Sjimharris * @param[in] controller This parameter specifies the core controller, one of 1539230557Sjimharris * its phy's resources are to be released. 1540249586Sgabor * @param[in] this_port This parameter specifies the port whose resource is to 1541230557Sjimharris * be released. 1542230557Sjimharris */ 1543230557Sjimharrisvoid scic_sds_port_release_resource( 1544230557Sjimharris SCIC_SDS_CONTROLLER_T * controller, 1545230557Sjimharris SCIC_SDS_PORT_T *this_port 1546230557Sjimharris) 1547230557Sjimharris{ 1548230557Sjimharris SCIC_LOG_TRACE(( 1549230557Sjimharris sci_base_object_get_logger(this_port), 1550230557Sjimharris SCIC_LOG_OBJECT_PORT, 1551230557Sjimharris "scic_sds_port_release_resource(0x%x, 0x%x)\n", 1552230557Sjimharris controller, this_port 1553230557Sjimharris )); 1554230557Sjimharris 1555230557Sjimharris //Currently, the only resource to be released is a timer. 1556230557Sjimharris if (this_port->timer_handle != NULL) 1557230557Sjimharris { 1558230557Sjimharris scic_cb_timer_destroy(controller, this_port->timer_handle); 1559230557Sjimharris this_port->timer_handle = NULL; 1560230557Sjimharris } 1561230557Sjimharris} 1562230557Sjimharris 1563230557Sjimharris 1564230557Sjimharris//****************************************************************************** 1565230557Sjimharris//* PORT STATE MACHINE 1566230557Sjimharris//****************************************************************************** 1567230557Sjimharris 1568230557Sjimharris//*************************************************************************** 1569230557Sjimharris//* DEFAULT HANDLERS 1570230557Sjimharris//*************************************************************************** 1571230557Sjimharris 1572230557Sjimharris/** 1573230557Sjimharris * This is the default method for port a start request. It will report a 1574230557Sjimharris * warning and exit. 1575230557Sjimharris * 1576230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a 1577230557Sjimharris * SCIC_SDS_PORT object. 1578230557Sjimharris * 1579230557Sjimharris * @return SCI_STATUS 1580230557Sjimharris * @retval SCI_FAILURE_INVALID_STATE 1581230557Sjimharris */ 1582230557SjimharrisSCI_STATUS scic_sds_port_default_start_handler( 1583230557Sjimharris SCI_BASE_PORT_T *port 1584230557Sjimharris) 1585230557Sjimharris{ 1586230557Sjimharris SCIC_LOG_WARNING(( 1587230557Sjimharris sci_base_object_get_logger((SCIC_SDS_PORT_T *)port), 1588230557Sjimharris SCIC_LOG_OBJECT_PORT, 1589230557Sjimharris "SCIC Port 0x%08x requested to start while in invalid state %d\n", 1590230557Sjimharris port, 1591230557Sjimharris sci_base_state_machine_get_state( 1592230557Sjimharris scic_sds_port_get_base_state_machine((SCIC_SDS_PORT_T *)port)) 1593230557Sjimharris )); 1594230557Sjimharris 1595230557Sjimharris return SCI_FAILURE_INVALID_STATE; 1596230557Sjimharris} 1597230557Sjimharris 1598230557Sjimharris/** 1599230557Sjimharris * This is the default method for a port stop request. It will report a 1600230557Sjimharris * warning and exit. 1601230557Sjimharris * 1602230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a 1603230557Sjimharris * SCIC_SDS_PORT object. 1604230557Sjimharris * 1605230557Sjimharris * @return SCI_STATUS 1606230557Sjimharris * @retval SCI_FAILURE_INVALID_STATE 1607230557Sjimharris */ 1608230557SjimharrisSCI_STATUS scic_sds_port_default_stop_handler( 1609230557Sjimharris SCI_BASE_PORT_T *port 1610230557Sjimharris) 1611230557Sjimharris{ 1612230557Sjimharris SCIC_LOG_WARNING(( 1613230557Sjimharris sci_base_object_get_logger((SCIC_SDS_PORT_T *)port), 1614230557Sjimharris SCIC_LOG_OBJECT_PORT, 1615230557Sjimharris "SCIC Port 0x%08x requested to stop while in invalid state %d\n", 1616230557Sjimharris port, 1617230557Sjimharris sci_base_state_machine_get_state( 1618230557Sjimharris scic_sds_port_get_base_state_machine((SCIC_SDS_PORT_T *)port)) 1619230557Sjimharris )); 1620230557Sjimharris 1621230557Sjimharris return SCI_FAILURE_INVALID_STATE; 1622230557Sjimharris} 1623230557Sjimharris 1624230557Sjimharris/** 1625230557Sjimharris * This is the default method for a port destruct request. It will report a 1626230557Sjimharris * warning and exit. 1627230557Sjimharris * 1628230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a 1629230557Sjimharris * SCIC_SDS_PORT object. 1630230557Sjimharris * 1631230557Sjimharris * @return SCI_STATUS 1632230557Sjimharris * @retval SCI_FAILURE_INVALID_STATE 1633230557Sjimharris */ 1634230557SjimharrisSCI_STATUS scic_sds_port_default_destruct_handler( 1635230557Sjimharris SCI_BASE_PORT_T *port 1636230557Sjimharris) 1637230557Sjimharris{ 1638230557Sjimharris SCIC_LOG_WARNING(( 1639230557Sjimharris sci_base_object_get_logger((SCIC_SDS_PORT_T *)port), 1640230557Sjimharris SCIC_LOG_OBJECT_PORT, 1641230557Sjimharris "SCIC Port 0x%08x requested to destruct while in invalid state %d\n", 1642230557Sjimharris port, 1643230557Sjimharris sci_base_state_machine_get_state( 1644230557Sjimharris scic_sds_port_get_base_state_machine((SCIC_SDS_PORT_T *)port)) 1645230557Sjimharris )); 1646230557Sjimharris 1647230557Sjimharris return SCI_FAILURE_INVALID_STATE; 1648230557Sjimharris} 1649230557Sjimharris 1650230557Sjimharris/** 1651230557Sjimharris * This is the default method for a port reset request. It will report a 1652230557Sjimharris * warning and exit. 1653230557Sjimharris * 1654230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a 1655230557Sjimharris * SCIC_SDS_PORT object. 1656230557Sjimharris * @param[in] timeout This is the timeout for the reset request to complete. 1657230557Sjimharris * 1658230557Sjimharris * @return SCI_STATUS 1659230557Sjimharris * @retval SCI_FAILURE_INVALID_STATE 1660230557Sjimharris */ 1661230557SjimharrisSCI_STATUS scic_sds_port_default_reset_handler( 1662230557Sjimharris SCI_BASE_PORT_T * port, 1663230557Sjimharris U32 timeout 1664230557Sjimharris) 1665230557Sjimharris{ 1666230557Sjimharris SCIC_LOG_WARNING(( 1667230557Sjimharris sci_base_object_get_logger((SCIC_SDS_PORT_T *)port), 1668230557Sjimharris SCIC_LOG_OBJECT_PORT, 1669230557Sjimharris "SCIC Port 0x%08x requested to reset while in invalid state %d\n", 1670230557Sjimharris port, 1671230557Sjimharris sci_base_state_machine_get_state( 1672230557Sjimharris scic_sds_port_get_base_state_machine((SCIC_SDS_PORT_T *)port)) 1673230557Sjimharris )); 1674230557Sjimharris 1675230557Sjimharris return SCI_FAILURE_INVALID_STATE; 1676230557Sjimharris} 1677230557Sjimharris 1678230557Sjimharris/** 1679230557Sjimharris * This is the default method for a port add phy request. It will report a 1680230557Sjimharris * warning and exit. 1681230557Sjimharris * 1682230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a 1683230557Sjimharris * SCIC_SDS_PORT object. 1684230557Sjimharris * 1685230557Sjimharris * @return SCI_STATUS 1686230557Sjimharris * @retval SCI_FAILURE_INVALID_STATE 1687230557Sjimharris */ 1688230557SjimharrisSCI_STATUS scic_sds_port_default_add_phy_handler( 1689230557Sjimharris SCI_BASE_PORT_T *port, 1690230557Sjimharris SCI_BASE_PHY_T *phy 1691230557Sjimharris) 1692230557Sjimharris{ 1693230557Sjimharris SCIC_LOG_WARNING(( 1694230557Sjimharris sci_base_object_get_logger((SCIC_SDS_PORT_T *)port), 1695230557Sjimharris SCIC_LOG_OBJECT_PORT, 1696230557Sjimharris "SCIC Port 0x%08x requested to add phy 0x%08x while in invalid state %d\n", 1697230557Sjimharris port, phy, 1698230557Sjimharris sci_base_state_machine_get_state( 1699230557Sjimharris scic_sds_port_get_base_state_machine((SCIC_SDS_PORT_T *)port)) 1700230557Sjimharris )); 1701230557Sjimharris 1702230557Sjimharris return SCI_FAILURE_INVALID_STATE; 1703230557Sjimharris} 1704230557Sjimharris 1705230557Sjimharris/** 1706230557Sjimharris * This is the default method for a port remove phy request. It will report a 1707230557Sjimharris * warning and exit. 1708230557Sjimharris * 1709230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a 1710230557Sjimharris * SCIC_SDS_PORT object. 1711230557Sjimharris * 1712230557Sjimharris * @return SCI_STATUS 1713230557Sjimharris * @retval SCI_FAILURE_INVALID_STATE 1714230557Sjimharris */ 1715230557SjimharrisSCI_STATUS scic_sds_port_default_remove_phy_handler( 1716230557Sjimharris SCI_BASE_PORT_T *port, 1717230557Sjimharris SCI_BASE_PHY_T *phy 1718230557Sjimharris) 1719230557Sjimharris{ 1720230557Sjimharris SCIC_LOG_WARNING(( 1721230557Sjimharris sci_base_object_get_logger((SCIC_SDS_PORT_T *)port), 1722230557Sjimharris SCIC_LOG_OBJECT_PORT, 1723230557Sjimharris "SCIC Port 0x%08x requested to remove phy 0x%08x while in invalid state %d\n", 1724230557Sjimharris port, phy, 1725230557Sjimharris sci_base_state_machine_get_state( 1726230557Sjimharris scic_sds_port_get_base_state_machine((SCIC_SDS_PORT_T *)port)) 1727230557Sjimharris )); 1728230557Sjimharris 1729230557Sjimharris return SCI_FAILURE_INVALID_STATE; 1730230557Sjimharris} 1731230557Sjimharris 1732230557Sjimharris/** 1733230557Sjimharris * This is the default method for a port unsolicited frame request. It will 1734230557Sjimharris * report a warning and exit. 1735230557Sjimharris * 1736230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a 1737230557Sjimharris * SCIC_SDS_PORT object. 1738230557Sjimharris * 1739230557Sjimharris * @return SCI_STATUS 1740230557Sjimharris * @retval SCI_FAILURE_INVALID_STATE 1741230557Sjimharris * 1742230557Sjimharris * @todo Is it even possible to receive an unsolicited frame directed to a 1743230557Sjimharris * port object? It seems possible if we implementing virtual functions 1744230557Sjimharris * but until then? 1745230557Sjimharris */ 1746230557SjimharrisSCI_STATUS scic_sds_port_default_frame_handler( 1747230557Sjimharris SCIC_SDS_PORT_T * port, 1748230557Sjimharris U32 frame_index 1749230557Sjimharris) 1750230557Sjimharris{ 1751230557Sjimharris SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)port; 1752230557Sjimharris 1753230557Sjimharris SCIC_LOG_WARNING(( 1754230557Sjimharris sci_base_object_get_logger(this_port), 1755230557Sjimharris SCIC_LOG_OBJECT_PORT, 1756230557Sjimharris "SCIC Port 0x%08x requested to process frame %d while in invalid state %d\n", 1757230557Sjimharris port, frame_index, 1758230557Sjimharris sci_base_state_machine_get_state( 1759230557Sjimharris scic_sds_port_get_base_state_machine(this_port)) 1760230557Sjimharris )); 1761230557Sjimharris 1762230557Sjimharris scic_sds_controller_release_frame( 1763230557Sjimharris scic_sds_port_get_controller(this_port), frame_index 1764230557Sjimharris ); 1765230557Sjimharris 1766230557Sjimharris return SCI_FAILURE_INVALID_STATE; 1767230557Sjimharris} 1768230557Sjimharris 1769230557Sjimharris/** 1770230557Sjimharris * This is the default method for a port event request. It will report a 1771230557Sjimharris * warning and exit. 1772230557Sjimharris * 1773230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a 1774230557Sjimharris * SCIC_SDS_PORT object. 1775230557Sjimharris * 1776230557Sjimharris * @return SCI_STATUS 1777230557Sjimharris * @retval SCI_FAILURE_INVALID_STATE 1778230557Sjimharris */ 1779230557SjimharrisSCI_STATUS scic_sds_port_default_event_handler( 1780230557Sjimharris SCIC_SDS_PORT_T * port, 1781230557Sjimharris U32 event_code 1782230557Sjimharris) 1783230557Sjimharris{ 1784230557Sjimharris SCIC_LOG_WARNING(( 1785230557Sjimharris sci_base_object_get_logger((SCIC_SDS_PORT_T *)port), 1786230557Sjimharris SCIC_LOG_OBJECT_PORT, 1787230557Sjimharris "SCIC Port 0x%08x requested to process event 0x%08x while in invalid state %d\n", 1788230557Sjimharris port, event_code, 1789230557Sjimharris sci_base_state_machine_get_state( 1790230557Sjimharris scic_sds_port_get_base_state_machine((SCIC_SDS_PORT_T *)port)) 1791230557Sjimharris )); 1792230557Sjimharris 1793230557Sjimharris return SCI_FAILURE_INVALID_STATE; 1794230557Sjimharris} 1795230557Sjimharris 1796230557Sjimharris/** 1797230557Sjimharris * This is the default method for a port link up notification. It will report 1798230557Sjimharris * a warning and exit. 1799230557Sjimharris * 1800230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a 1801230557Sjimharris * SCIC_SDS_PORT object. 1802230557Sjimharris * 1803230557Sjimharris * @return SCI_STATUS 1804230557Sjimharris * @retval SCI_FAILURE_INVALID_STATE 1805230557Sjimharris */ 1806230557Sjimharrisvoid scic_sds_port_default_link_up_handler( 1807230557Sjimharris SCIC_SDS_PORT_T *this_port, 1808230557Sjimharris SCIC_SDS_PHY_T *phy 1809230557Sjimharris) 1810230557Sjimharris{ 1811230557Sjimharris SCIC_LOG_WARNING(( 1812230557Sjimharris sci_base_object_get_logger(this_port), 1813230557Sjimharris SCIC_LOG_OBJECT_PORT, 1814230557Sjimharris "SCIC Port 0x%08x received link_up notification from phy 0x%08x while in invalid state %d\n", 1815230557Sjimharris this_port, phy, 1816230557Sjimharris sci_base_state_machine_get_state( 1817230557Sjimharris scic_sds_port_get_base_state_machine(this_port)) 1818230557Sjimharris )); 1819230557Sjimharris} 1820230557Sjimharris 1821230557Sjimharris/** 1822230557Sjimharris * This is the default method for a port link down notification. It will 1823230557Sjimharris * report a warning and exit. 1824230557Sjimharris * 1825230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a 1826230557Sjimharris * SCIC_SDS_PORT object. 1827230557Sjimharris * 1828230557Sjimharris * @return SCI_STATUS 1829230557Sjimharris * @retval SCI_FAILURE_INVALID_STATE 1830230557Sjimharris */ 1831230557Sjimharrisvoid scic_sds_port_default_link_down_handler( 1832230557Sjimharris SCIC_SDS_PORT_T *this_port, 1833230557Sjimharris SCIC_SDS_PHY_T *phy 1834230557Sjimharris) 1835230557Sjimharris{ 1836230557Sjimharris SCIC_LOG_WARNING(( 1837230557Sjimharris sci_base_object_get_logger(this_port), 1838230557Sjimharris SCIC_LOG_OBJECT_PORT, 1839230557Sjimharris "SCIC Port 0x%08x received link down notification from phy 0x%08x while in invalid state %d\n", 1840230557Sjimharris this_port, phy, 1841230557Sjimharris sci_base_state_machine_get_state( 1842230557Sjimharris scic_sds_port_get_base_state_machine(this_port)) 1843230557Sjimharris )); 1844230557Sjimharris} 1845230557Sjimharris 1846230557Sjimharris/** 1847230557Sjimharris * This is the default method for a port start io request. It will report a 1848230557Sjimharris * warning and exit. 1849230557Sjimharris * 1850230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a 1851230557Sjimharris * SCIC_SDS_PORT object. 1852230557Sjimharris * 1853230557Sjimharris * @return SCI_STATUS 1854230557Sjimharris * @retval SCI_FAILURE_INVALID_STATE 1855230557Sjimharris */ 1856230557SjimharrisSCI_STATUS scic_sds_port_default_start_io_handler( 1857230557Sjimharris SCIC_SDS_PORT_T *this_port, 1858230557Sjimharris SCIC_SDS_REMOTE_DEVICE_T *device, 1859230557Sjimharris SCIC_SDS_REQUEST_T *io_request 1860230557Sjimharris) 1861230557Sjimharris{ 1862230557Sjimharris SCIC_LOG_WARNING(( 1863230557Sjimharris sci_base_object_get_logger(this_port), 1864230557Sjimharris SCIC_LOG_OBJECT_PORT, 1865230557Sjimharris "SCIC Port 0x%08x requested to start io request 0x%08x while in invalid state %d\n", 1866230557Sjimharris this_port, io_request, 1867230557Sjimharris sci_base_state_machine_get_state( 1868230557Sjimharris scic_sds_port_get_base_state_machine(this_port)) 1869230557Sjimharris )); 1870230557Sjimharris 1871230557Sjimharris return SCI_FAILURE_INVALID_STATE; 1872230557Sjimharris} 1873230557Sjimharris 1874230557Sjimharris/** 1875230557Sjimharris * This is the default method for a port complete io request. It will report 1876230557Sjimharris * a warning and exit. 1877230557Sjimharris * 1878230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a 1879230557Sjimharris * SCIC_SDS_PORT object. 1880230557Sjimharris * 1881230557Sjimharris * @return SCI_STATUS 1882230557Sjimharris * @retval SCI_FAILURE_INVALID_STATE 1883230557Sjimharris */ 1884230557SjimharrisSCI_STATUS scic_sds_port_default_complete_io_handler( 1885230557Sjimharris SCIC_SDS_PORT_T *this_port, 1886230557Sjimharris SCIC_SDS_REMOTE_DEVICE_T *device, 1887230557Sjimharris SCIC_SDS_REQUEST_T *io_request 1888230557Sjimharris) 1889230557Sjimharris{ 1890230557Sjimharris SCIC_LOG_WARNING(( 1891230557Sjimharris sci_base_object_get_logger(this_port), 1892230557Sjimharris SCIC_LOG_OBJECT_PORT, 1893230557Sjimharris "SCIC Port 0x%08x requested to complete io request 0x%08x while in invalid state %d\n", 1894230557Sjimharris this_port, io_request, 1895230557Sjimharris sci_base_state_machine_get_state( 1896230557Sjimharris scic_sds_port_get_base_state_machine(this_port)) 1897230557Sjimharris )); 1898230557Sjimharris 1899230557Sjimharris return SCI_FAILURE_INVALID_STATE; 1900230557Sjimharris} 1901230557Sjimharris 1902230557Sjimharris//**************************************************************************** 1903230557Sjimharris//* GENERAL STATE HANDLERS 1904230557Sjimharris//**************************************************************************** 1905230557Sjimharris 1906230557Sjimharris/** 1907230557Sjimharris * This is a general complete io request handler for the SCIC_SDS_PORT object. 1908230557Sjimharris * 1909230557Sjimharris * @param[in] port This is the SCIC_SDS_PORT object on which the io request 1910230557Sjimharris * count will be decremented. 1911230557Sjimharris * @param[in] device This is the SCIC_SDS_REMOTE_DEVICE object to which the io 1912230557Sjimharris * request is being directed. This parameter is not required to 1913230557Sjimharris * complete this operation. 1914230557Sjimharris * @param[in] io_request This is the request that is being completed on this 1915230557Sjimharris * port object. This parameter is not required to complete this 1916230557Sjimharris * operation. 1917230557Sjimharris * 1918230557Sjimharris * @return SCI_STATUS 1919230557Sjimharris * @retval SCI_SUCCESS 1920230557Sjimharris */ 1921230557Sjimharrisstatic 1922230557SjimharrisSCI_STATUS scic_sds_port_general_complete_io_handler( 1923230557Sjimharris SCIC_SDS_PORT_T *port, 1924230557Sjimharris SCIC_SDS_REMOTE_DEVICE_T *device, 1925230557Sjimharris SCIC_SDS_REQUEST_T *io_request 1926230557Sjimharris) 1927230557Sjimharris{ 1928230557Sjimharris SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)port; 1929230557Sjimharris 1930230557Sjimharris scic_sds_port_decrement_request_count(this_port); 1931230557Sjimharris 1932230557Sjimharris return SCI_SUCCESS; 1933230557Sjimharris} 1934230557Sjimharris 1935230557Sjimharris//**************************************************************************** 1936230557Sjimharris//* STOPPED STATE HANDLERS 1937230557Sjimharris//**************************************************************************** 1938230557Sjimharrisstatic 1939230557SjimharrisBOOL scic_sds_port_requires_scheduler_workaround( 1940230557Sjimharris SCIC_SDS_PORT_T * this_port 1941230557Sjimharris) 1942230557Sjimharris{ 1943230557Sjimharris if ( 1944230557Sjimharris ( 1945230557Sjimharris this_port->owning_controller->logical_port_entries 1946230557Sjimharris < this_port->owning_controller->task_context_entries 1947230557Sjimharris ) 1948230557Sjimharris && ( 1949230557Sjimharris this_port->owning_controller->logical_port_entries 1950230557Sjimharris < this_port->owning_controller->remote_node_entries 1951230557Sjimharris ) 1952230557Sjimharris ) 1953230557Sjimharris { 1954230557Sjimharris return TRUE; 1955230557Sjimharris } 1956230557Sjimharris 1957230557Sjimharris return FALSE; 1958230557Sjimharris} 1959230557Sjimharris 1960230557Sjimharris 1961230557Sjimharris/** 1962230557Sjimharris * This method takes the SCIC_SDS_PORT from a stopped state and attempts to 1963230557Sjimharris * start it. To start a port it must have no assiged devices and it must have 1964230557Sjimharris * at least one phy assigned to it. If those conditions are met then the port 1965230557Sjimharris * can transition to the ready state. 1966230557Sjimharris * 1967230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a 1968230557Sjimharris * SCIC_SDS_PORT object. 1969230557Sjimharris * 1970230557Sjimharris * @return SCI_STATUS 1971230557Sjimharris * @retval SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION This SCIC_SDS_PORT 1972230557Sjimharris * object could not be started because the port configuration is not 1973230557Sjimharris * valid. 1974230557Sjimharris * @retval SCI_SUCCESS the start request is successful and the SCIC_SDS_PORT 1975230557Sjimharris * object has transitioned to the SCI_BASE_PORT_STATE_READY. 1976230557Sjimharris */ 1977230557Sjimharrisstatic 1978230557SjimharrisSCI_STATUS scic_sds_port_stopped_state_start_handler( 1979230557Sjimharris SCI_BASE_PORT_T *port 1980230557Sjimharris) 1981230557Sjimharris{ 1982230557Sjimharris U32 phy_mask; 1983230557Sjimharris SCI_STATUS status = SCI_SUCCESS; 1984230557Sjimharris SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)port; 1985230557Sjimharris 1986230557Sjimharris if (this_port->assigned_device_count > 0) 1987230557Sjimharris { 1988230557Sjimharris /// @todo This is a start failure operation because there are still 1989230557Sjimharris /// devices assigned to this port. There must be no devices 1990230557Sjimharris /// assigned to a port on a start operation. 1991230557Sjimharris return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; 1992230557Sjimharris } 1993230557Sjimharris 1994230557Sjimharris this_port->timer_handle = scic_cb_timer_create( 1995230557Sjimharris scic_sds_port_get_controller(this_port), 1996230557Sjimharris scic_sds_port_timeout_handler, 1997230557Sjimharris this_port 1998230557Sjimharris ); 1999230557Sjimharris 2000230557Sjimharris if (this_port->timer_handle == SCI_INVALID_HANDLE) 2001230557Sjimharris { 2002230557Sjimharris return SCI_FAILURE_INSUFFICIENT_RESOURCES; 2003230557Sjimharris } 2004230557Sjimharris 2005230557Sjimharris if (scic_sds_port_requires_scheduler_workaround(this_port)) 2006230557Sjimharris { 2007230557Sjimharris if (this_port->reserved_rni == SCU_DUMMY_INDEX) 2008230557Sjimharris { 2009230557Sjimharris this_port->reserved_rni = 2010230557Sjimharris scic_sds_remote_node_table_allocate_remote_node( 2011230557Sjimharris &this_port->owning_controller->available_remote_nodes, 1 2012230557Sjimharris ); 2013230557Sjimharris 2014230557Sjimharris if (this_port->reserved_rni != SCU_DUMMY_INDEX) 2015230557Sjimharris { 2016230557Sjimharris scic_sds_port_construct_dummy_rnc( 2017230557Sjimharris this_port, 2018230557Sjimharris this_port->reserved_rni 2019230557Sjimharris ); 2020230557Sjimharris } 2021230557Sjimharris else 2022230557Sjimharris { 2023230557Sjimharris status = SCI_FAILURE_INSUFFICIENT_RESOURCES; 2024230557Sjimharris } 2025230557Sjimharris } 2026230557Sjimharris 2027230557Sjimharris if (this_port->reserved_tci == SCU_DUMMY_INDEX) 2028230557Sjimharris { 2029230557Sjimharris // Allocate a TCI and remove the sequence nibble 2030230557Sjimharris this_port->reserved_tci = 2031230557Sjimharris scic_controller_allocate_io_tag(this_port->owning_controller); 2032230557Sjimharris 2033230557Sjimharris if (this_port->reserved_tci != SCU_DUMMY_INDEX) 2034230557Sjimharris { 2035230557Sjimharris scic_sds_port_construct_dummy_task(this_port, this_port->reserved_tci); 2036230557Sjimharris } 2037230557Sjimharris else 2038230557Sjimharris { 2039230557Sjimharris status = SCI_FAILURE_INSUFFICIENT_RESOURCES; 2040230557Sjimharris } 2041230557Sjimharris } 2042230557Sjimharris } 2043230557Sjimharris 2044230557Sjimharris if (status == SCI_SUCCESS) 2045230557Sjimharris { 2046230557Sjimharris phy_mask = scic_sds_port_get_phys(this_port); 2047230557Sjimharris 2048230557Sjimharris // There are one or more phys assigned to this port. Make sure 2049230557Sjimharris // the port's phy mask is in fact legal and supported by the 2050230557Sjimharris // silicon. 2051230557Sjimharris if (scic_sds_port_is_phy_mask_valid(this_port, phy_mask) == TRUE) 2052230557Sjimharris { 2053230557Sjimharris sci_base_state_machine_change_state( 2054230557Sjimharris scic_sds_port_get_base_state_machine(this_port), 2055230557Sjimharris SCI_BASE_PORT_STATE_READY 2056230557Sjimharris ); 2057230557Sjimharris } 2058230557Sjimharris else 2059230557Sjimharris { 2060230557Sjimharris status = SCI_FAILURE; 2061230557Sjimharris } 2062230557Sjimharris } 2063230557Sjimharris 2064230557Sjimharris if (status != SCI_SUCCESS) 2065230557Sjimharris { 2066230557Sjimharris scic_sds_port_destroy_dummy_resources(this_port); 2067230557Sjimharris } 2068230557Sjimharris 2069230557Sjimharris return status; 2070230557Sjimharris} 2071230557Sjimharris 2072230557Sjimharris/** 2073230557Sjimharris * This method takes the SCIC_SDS_PORT that is in a stopped state and handles 2074230557Sjimharris * a stop request. This function takes no action. 2075230557Sjimharris * 2076230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a 2077230557Sjimharris * SCIC_SDS_PORT object. 2078230557Sjimharris * 2079230557Sjimharris * @return SCI_STATUS 2080230557Sjimharris * @retval SCI_SUCCESS the stop request is successful as the SCIC_SDS_PORT 2081230557Sjimharris * object is already stopped. 2082230557Sjimharris */ 2083230557Sjimharrisstatic 2084230557SjimharrisSCI_STATUS scic_sds_port_stopped_state_stop_handler( 2085230557Sjimharris SCI_BASE_PORT_T *port 2086230557Sjimharris) 2087230557Sjimharris{ 2088230557Sjimharris // We are already stopped so there is nothing to do here 2089230557Sjimharris return SCI_SUCCESS; 2090230557Sjimharris} 2091230557Sjimharris 2092230557Sjimharris/** 2093230557Sjimharris * This method takes the SCIC_SDS_PORT that is in a stopped state and handles 2094230557Sjimharris * the destruct request. The stopped state is the only state in which the 2095230557Sjimharris * SCIC_SDS_PORT can be destroyed. This function causes the port object to 2096230557Sjimharris * transition to the SCI_BASE_PORT_STATE_FINAL. 2097230557Sjimharris * 2098230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a 2099230557Sjimharris * SCIC_SDS_PORT object. 2100230557Sjimharris * 2101230557Sjimharris * @return SCI_STATUS 2102230557Sjimharris * @retval SCI_SUCCESS 2103230557Sjimharris */ 2104230557Sjimharrisstatic 2105230557SjimharrisSCI_STATUS scic_sds_port_stopped_state_destruct_handler( 2106230557Sjimharris SCI_BASE_PORT_T *port 2107230557Sjimharris) 2108230557Sjimharris{ 2109230557Sjimharris SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)port; 2110230557Sjimharris 2111230557Sjimharris sci_base_state_machine_stop(&this_port->parent.state_machine); 2112230557Sjimharris 2113230557Sjimharris return SCI_SUCCESS; 2114230557Sjimharris} 2115230557Sjimharris 2116230557Sjimharris/** 2117230557Sjimharris * This method takes the SCIC_SDS_PORT that is in a stopped state and handles 2118230557Sjimharris * the add phy request. In MPC mode the only time a phy can be added to a 2119230557Sjimharris * port is in the SCI_BASE_PORT_STATE_STOPPED. 2120230557Sjimharris * 2121230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a 2122230557Sjimharris * SCIC_SDS_PORT object. 2123230557Sjimharris * @param[in] phy This is the SCI_BASE_PHY object which is cast into a 2124230557Sjimharris * SCIC_SDS_PHY object. 2125230557Sjimharris * 2126230557Sjimharris * @return SCI_STATUS 2127230557Sjimharris * @retval SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION is returned when the phy 2128230557Sjimharris * can not be added to the port. 2129230557Sjimharris * @retval SCI_SUCCESS if the phy is added to the port. 2130230557Sjimharris */ 2131230557Sjimharrisstatic 2132230557SjimharrisSCI_STATUS scic_sds_port_stopped_state_add_phy_handler( 2133230557Sjimharris SCI_BASE_PORT_T *port, 2134230557Sjimharris SCI_BASE_PHY_T *phy 2135230557Sjimharris) 2136230557Sjimharris{ 2137230557Sjimharris SCIC_SDS_PORT_T * this_port = (SCIC_SDS_PORT_T *)port; 2138230557Sjimharris SCIC_SDS_PHY_T * this_phy = (SCIC_SDS_PHY_T *)phy; 2139230557Sjimharris SCI_SAS_ADDRESS_T port_sas_address; 2140230557Sjimharris 2141230557Sjimharris // Read the port assigned SAS Address if there is one 2142230557Sjimharris scic_sds_port_get_sas_address(this_port, &port_sas_address); 2143230557Sjimharris 2144230557Sjimharris if (port_sas_address.high != 0 && port_sas_address.low != 0) 2145230557Sjimharris { 2146230557Sjimharris SCI_SAS_ADDRESS_T phy_sas_address; 2147230557Sjimharris 2148230557Sjimharris // Make sure that the PHY SAS Address matches the SAS Address 2149230557Sjimharris // for this port. 2150230557Sjimharris scic_sds_phy_get_sas_address(this_phy, &phy_sas_address); 2151230557Sjimharris 2152230557Sjimharris if ( 2153230557Sjimharris (port_sas_address.high != phy_sas_address.high) 2154230557Sjimharris || (port_sas_address.low != phy_sas_address.low) 2155230557Sjimharris ) 2156230557Sjimharris { 2157230557Sjimharris return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; 2158230557Sjimharris } 2159230557Sjimharris } 2160230557Sjimharris 2161230557Sjimharris return scic_sds_port_set_phy(this_port, this_phy); 2162230557Sjimharris} 2163230557Sjimharris 2164230557Sjimharris 2165230557Sjimharris/** 2166230557Sjimharris * This method takes the SCIC_SDS_PORT that is in a stopped state and handles 2167230557Sjimharris * the remove phy request. In MPC mode the only time a phy can be removed 2168230557Sjimharris * from a port is in the SCI_BASE_PORT_STATE_STOPPED. 2169230557Sjimharris * 2170230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a 2171230557Sjimharris * SCIC_SDS_PORT object. 2172230557Sjimharris * @param[in] phy This is the SCI_BASE_PHY object which is cast into a 2173230557Sjimharris * SCIC_SDS_PHY object. 2174230557Sjimharris * 2175230557Sjimharris * @return SCI_STATUS 2176230557Sjimharris * @retval SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION is returned when the phy 2177230557Sjimharris * can not be added to the port. 2178230557Sjimharris * @retval SCI_SUCCESS if the phy is added to the port. 2179230557Sjimharris */ 2180230557Sjimharrisstatic 2181230557SjimharrisSCI_STATUS scic_sds_port_stopped_state_remove_phy_handler( 2182230557Sjimharris SCI_BASE_PORT_T *port, 2183230557Sjimharris SCI_BASE_PHY_T *phy 2184230557Sjimharris) 2185230557Sjimharris{ 2186230557Sjimharris SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)port; 2187230557Sjimharris SCIC_SDS_PHY_T *this_phy = (SCIC_SDS_PHY_T *)phy; 2188230557Sjimharris 2189230557Sjimharris return scic_sds_port_clear_phy(this_port, this_phy); 2190230557Sjimharris} 2191230557Sjimharris 2192230557Sjimharris//**************************************************************************** 2193230557Sjimharris//* READY STATE HANDLERS 2194230557Sjimharris//**************************************************************************** 2195230557Sjimharris 2196230557Sjimharris//**************************************************************************** 2197230557Sjimharris//* RESETTING STATE HANDLERS 2198230557Sjimharris//**************************************************************************** 2199230557Sjimharris 2200230557Sjimharris//**************************************************************************** 2201230557Sjimharris//* STOPPING STATE HANDLERS 2202230557Sjimharris//**************************************************************************** 2203230557Sjimharris 2204230557Sjimharris/** 2205230557Sjimharris * This method takes the SCIC_SDS_PORT that is in a stopping state and handles 2206230557Sjimharris * the complete io request. Should the request count reach 0 then the port 2207230557Sjimharris * object will transition to the stopped state. 2208230557Sjimharris * 2209230557Sjimharris * @param[in] port This is the SCIC_SDS_PORT object on which the io request 2210230557Sjimharris * count will be decremented. 2211230557Sjimharris * @param[in] device This is the SCIC_SDS_REMOTE_DEVICE object to which the io 2212230557Sjimharris * request is being directed. This parameter is not required to 2213230557Sjimharris * complete this operation. 2214230557Sjimharris * @param[in] io_request This is the request that is being completed on this 2215230557Sjimharris * port object. This parameter is not required to complete this 2216230557Sjimharris * operation. 2217230557Sjimharris * 2218230557Sjimharris * @return SCI_STATUS 2219230557Sjimharris * @retval SCI_SUCCESS 2220230557Sjimharris */ 2221230557Sjimharrisstatic 2222230557SjimharrisSCI_STATUS scic_sds_port_stopping_state_complete_io_handler( 2223230557Sjimharris SCIC_SDS_PORT_T *port, 2224230557Sjimharris SCIC_SDS_REMOTE_DEVICE_T *device, 2225230557Sjimharris SCIC_SDS_REQUEST_T *io_request 2226230557Sjimharris) 2227230557Sjimharris{ 2228230557Sjimharris SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)port; 2229230557Sjimharris 2230230557Sjimharris scic_sds_port_decrement_request_count(this_port); 2231230557Sjimharris 2232230557Sjimharris if (this_port->started_request_count == 0) 2233230557Sjimharris { 2234230557Sjimharris sci_base_state_machine_change_state( 2235230557Sjimharris scic_sds_port_get_base_state_machine(this_port), 2236230557Sjimharris SCI_BASE_PORT_STATE_STOPPED 2237230557Sjimharris ); 2238230557Sjimharris } 2239230557Sjimharris 2240230557Sjimharris return SCI_SUCCESS; 2241230557Sjimharris} 2242230557Sjimharris 2243230557Sjimharris//**************************************************************************** 2244230557Sjimharris//* RESETTING STATE HANDLERS 2245230557Sjimharris//**************************************************************************** 2246230557Sjimharris 2247230557Sjimharris/** 2248230557Sjimharris * This method will stop a failed port. This causes a transition to the 2249230557Sjimharris * stopping state. 2250230557Sjimharris * 2251230557Sjimharris * @param[in] port This is the port object which is being requested to stop. 2252230557Sjimharris * 2253230557Sjimharris * @return SCI_STATUS 2254230557Sjimharris * @retval SCI_SUCCESS 2255230557Sjimharris */ 2256230557Sjimharrisstatic 2257230557SjimharrisSCI_STATUS scic_sds_port_reset_state_stop_handler( 2258230557Sjimharris SCI_BASE_PORT_T *port 2259230557Sjimharris) 2260230557Sjimharris{ 2261230557Sjimharris SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)port; 2262230557Sjimharris 2263230557Sjimharris sci_base_state_machine_change_state( 2264230557Sjimharris &this_port->parent.state_machine, 2265230557Sjimharris SCI_BASE_PORT_STATE_STOPPING 2266230557Sjimharris ); 2267230557Sjimharris 2268230557Sjimharris return SCI_SUCCESS; 2269230557Sjimharris} 2270230557Sjimharris 2271230557Sjimharris/** 2272230557Sjimharris * This method will transition a failed port to its ready state. The port 2273230557Sjimharris * failed because a hard reset request timed out but at some time later one or 2274230557Sjimharris * more phys in the port became ready. 2275230557Sjimharris * 2276230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a 2277230557Sjimharris * SCIC_SDS_PORT object. 2278230557Sjimharris * 2279230557Sjimharris * @return SCI_STATUS 2280230557Sjimharris * @retval SCI_SUCCESS 2281230557Sjimharris */ 2282230557Sjimharrisstatic 2283230557Sjimharrisvoid scic_sds_port_reset_state_link_up_handler( 2284230557Sjimharris SCIC_SDS_PORT_T *this_port, 2285230557Sjimharris SCIC_SDS_PHY_T *phy 2286230557Sjimharris) 2287230557Sjimharris{ 2288230557Sjimharris /// @todo We should make sure that the phy that has gone link up is the same 2289230557Sjimharris /// one on which we sent the reset. It is possible that the phy on 2290230557Sjimharris /// which we sent the reset is not the one that has gone link up and we 2291230557Sjimharris /// want to make sure that phy being reset comes back. Consider the 2292230557Sjimharris /// case where a reset is sent but before the hardware processes the 2293230557Sjimharris /// reset it get a link up on the port because of a hot plug event. 2294230557Sjimharris /// because of the reset request this phy will go link down almost 2295230557Sjimharris /// immediately. 2296230557Sjimharris 2297230557Sjimharris // In the resetting state we don't notify the user regarding 2298230557Sjimharris // link up and link down notifications. 2299230557Sjimharris scic_sds_port_general_link_up_handler(this_port, phy, FALSE, TRUE); 2300230557Sjimharris} 2301230557Sjimharris 2302230557Sjimharris/** 2303230557Sjimharris * This method process link down notifications that occur during a 2304230557Sjimharris * port reset operation. Link downs can occur during the reset operation. 2305230557Sjimharris * 2306230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a 2307230557Sjimharris * SCIC_SDS_PORT object. 2308230557Sjimharris * 2309230557Sjimharris * @return SCI_STATUS 2310230557Sjimharris * @retval SCI_SUCCESS 2311230557Sjimharris */ 2312230557Sjimharrisstatic 2313230557Sjimharrisvoid scic_sds_port_reset_state_link_down_handler( 2314230557Sjimharris SCIC_SDS_PORT_T *this_port, 2315230557Sjimharris SCIC_SDS_PHY_T *phy 2316230557Sjimharris) 2317230557Sjimharris{ 2318230557Sjimharris // In the resetting state we don't notify the user regarding 2319230557Sjimharris // link up and link down notifications. 2320230557Sjimharris scic_sds_port_deactivate_phy(this_port, phy, FALSE); 2321230557Sjimharris} 2322230557Sjimharris 2323230557Sjimharris// --------------------------------------------------------------------------- 2324230557Sjimharris 2325230557SjimharrisSCIC_SDS_PORT_STATE_HANDLER_T 2326230557Sjimharris scic_sds_port_state_handler_table[SCI_BASE_PORT_MAX_STATES] = 2327230557Sjimharris{ 2328230557Sjimharris // SCI_BASE_PORT_STATE_STOPPED 2329230557Sjimharris { 2330230557Sjimharris { 2331230557Sjimharris scic_sds_port_stopped_state_start_handler, 2332230557Sjimharris scic_sds_port_stopped_state_stop_handler, 2333230557Sjimharris scic_sds_port_stopped_state_destruct_handler, 2334230557Sjimharris scic_sds_port_default_reset_handler, 2335230557Sjimharris scic_sds_port_stopped_state_add_phy_handler, 2336230557Sjimharris scic_sds_port_stopped_state_remove_phy_handler 2337230557Sjimharris }, 2338230557Sjimharris scic_sds_port_default_frame_handler, 2339230557Sjimharris scic_sds_port_default_event_handler, 2340230557Sjimharris scic_sds_port_default_link_up_handler, 2341230557Sjimharris scic_sds_port_default_link_down_handler, 2342230557Sjimharris scic_sds_port_default_start_io_handler, 2343230557Sjimharris scic_sds_port_default_complete_io_handler 2344230557Sjimharris }, 2345230557Sjimharris // SCI_BASE_PORT_STATE_STOPPING 2346230557Sjimharris { 2347230557Sjimharris { 2348230557Sjimharris scic_sds_port_default_start_handler, 2349230557Sjimharris scic_sds_port_default_stop_handler, 2350230557Sjimharris scic_sds_port_default_destruct_handler, 2351230557Sjimharris scic_sds_port_default_reset_handler, 2352230557Sjimharris scic_sds_port_default_add_phy_handler, 2353230557Sjimharris scic_sds_port_default_remove_phy_handler 2354230557Sjimharris }, 2355230557Sjimharris scic_sds_port_default_frame_handler, 2356230557Sjimharris scic_sds_port_default_event_handler, 2357230557Sjimharris scic_sds_port_default_link_up_handler, 2358230557Sjimharris scic_sds_port_default_link_down_handler, 2359230557Sjimharris scic_sds_port_default_start_io_handler, 2360230557Sjimharris scic_sds_port_stopping_state_complete_io_handler 2361230557Sjimharris }, 2362230557Sjimharris // SCI_BASE_PORT_STATE_READY 2363230557Sjimharris { 2364230557Sjimharris { 2365230557Sjimharris scic_sds_port_default_start_handler, 2366230557Sjimharris scic_sds_port_default_stop_handler, 2367230557Sjimharris scic_sds_port_default_destruct_handler, 2368230557Sjimharris scic_sds_port_default_reset_handler, 2369230557Sjimharris scic_sds_port_default_add_phy_handler, 2370230557Sjimharris scic_sds_port_default_remove_phy_handler 2371230557Sjimharris }, 2372230557Sjimharris scic_sds_port_default_frame_handler, 2373230557Sjimharris scic_sds_port_default_event_handler, 2374230557Sjimharris scic_sds_port_default_link_up_handler, 2375230557Sjimharris scic_sds_port_default_link_down_handler, 2376230557Sjimharris scic_sds_port_default_start_io_handler, 2377230557Sjimharris scic_sds_port_general_complete_io_handler 2378230557Sjimharris }, 2379230557Sjimharris // SCI_BASE_PORT_STATE_RESETTING 2380230557Sjimharris { 2381230557Sjimharris { 2382230557Sjimharris scic_sds_port_default_start_handler, 2383230557Sjimharris scic_sds_port_reset_state_stop_handler, 2384230557Sjimharris scic_sds_port_default_destruct_handler, 2385230557Sjimharris scic_sds_port_default_reset_handler, 2386230557Sjimharris scic_sds_port_default_add_phy_handler, 2387230557Sjimharris scic_sds_port_default_remove_phy_handler 2388230557Sjimharris }, 2389230557Sjimharris scic_sds_port_default_frame_handler, 2390230557Sjimharris scic_sds_port_default_event_handler, 2391230557Sjimharris scic_sds_port_reset_state_link_up_handler, 2392230557Sjimharris scic_sds_port_reset_state_link_down_handler, 2393230557Sjimharris scic_sds_port_default_start_io_handler, 2394230557Sjimharris scic_sds_port_general_complete_io_handler 2395230557Sjimharris }, 2396230557Sjimharris // SCI_BASE_PORT_STATE_FAILED 2397230557Sjimharris { 2398230557Sjimharris { 2399230557Sjimharris scic_sds_port_default_start_handler, 2400230557Sjimharris scic_sds_port_default_stop_handler, 2401230557Sjimharris scic_sds_port_default_destruct_handler, 2402230557Sjimharris scic_sds_port_default_reset_handler, 2403230557Sjimharris scic_sds_port_default_add_phy_handler, 2404230557Sjimharris scic_sds_port_default_remove_phy_handler 2405230557Sjimharris }, 2406230557Sjimharris scic_sds_port_default_frame_handler, 2407230557Sjimharris scic_sds_port_default_event_handler, 2408230557Sjimharris scic_sds_port_default_link_up_handler, 2409230557Sjimharris scic_sds_port_default_link_down_handler, 2410230557Sjimharris scic_sds_port_default_start_io_handler, 2411230557Sjimharris scic_sds_port_general_complete_io_handler 2412230557Sjimharris } 2413230557Sjimharris}; 2414230557Sjimharris 2415230557Sjimharris//****************************************************************************** 2416230557Sjimharris//* PORT STATE PRIVATE METHODS 2417230557Sjimharris//****************************************************************************** 2418230557Sjimharris 2419230557Sjimharris/** 2420230557Sjimharris * This method will enable the SCU Port Task Scheduler for this port object 2421230557Sjimharris * but will leave the port task scheduler in a suspended state. 2422230557Sjimharris * 2423230557Sjimharris * @param[in] this_port This is the port object which to suspend. 2424230557Sjimharris * 2425230557Sjimharris * @return none 2426230557Sjimharris */ 2427230557Sjimharrisstatic 2428230557Sjimharrisvoid scic_sds_port_enable_port_task_scheduler( 2429230557Sjimharris SCIC_SDS_PORT_T *this_port 2430230557Sjimharris) 2431230557Sjimharris{ 2432230557Sjimharris U32 pts_control_value; 2433230557Sjimharris 2434230557Sjimharris pts_control_value = scu_port_task_scheduler_read(this_port, control); 2435230557Sjimharris 2436230557Sjimharris pts_control_value |= SCU_PTSxCR_GEN_BIT(ENABLE) | SCU_PTSxCR_GEN_BIT(SUSPEND); 2437230557Sjimharris 2438230557Sjimharris scu_port_task_scheduler_write(this_port, control, pts_control_value); 2439230557Sjimharris} 2440230557Sjimharris 2441230557Sjimharris/** 2442230557Sjimharris * This method will disable the SCU port task scheduler for this port 2443230557Sjimharris * object. 2444230557Sjimharris * 2445230557Sjimharris * @param[in] this_port This is the port object which to resume. 2446230557Sjimharris * 2447230557Sjimharris * @return none 2448230557Sjimharris */ 2449230557Sjimharrisstatic 2450230557Sjimharrisvoid scic_sds_port_disable_port_task_scheduler( 2451230557Sjimharris SCIC_SDS_PORT_T *this_port 2452230557Sjimharris) 2453230557Sjimharris{ 2454230557Sjimharris U32 pts_control_value; 2455230557Sjimharris 2456230557Sjimharris pts_control_value = scu_port_task_scheduler_read(this_port, control); 2457230557Sjimharris 2458230557Sjimharris pts_control_value &= ~( SCU_PTSxCR_GEN_BIT(ENABLE) 2459230557Sjimharris | SCU_PTSxCR_GEN_BIT(SUSPEND) ); 2460230557Sjimharris 2461230557Sjimharris scu_port_task_scheduler_write(this_port, control, pts_control_value); 2462230557Sjimharris} 2463230557Sjimharris 2464230557Sjimharris/** 2465230557Sjimharris * 2466230557Sjimharris */ 2467230557Sjimharrisstatic 2468230557Sjimharrisvoid scic_sds_port_post_dummy_remote_node( 2469230557Sjimharris SCIC_SDS_PORT_T *this_port 2470230557Sjimharris) 2471230557Sjimharris{ 2472230557Sjimharris U32 command; 2473230557Sjimharris SCU_REMOTE_NODE_CONTEXT_T * rnc; 2474230557Sjimharris 2475230557Sjimharris if (this_port->reserved_rni != SCU_DUMMY_INDEX) 2476230557Sjimharris { 2477230557Sjimharris rnc = &(this_port->owning_controller->remote_node_context_table[this_port->reserved_rni]); 2478230557Sjimharris 2479230557Sjimharris rnc->ssp.is_valid = TRUE; 2480230557Sjimharris 2481230557Sjimharris command = ( 2482230557Sjimharris (SCU_CONTEXT_COMMAND_POST_RNC_32) 2483230557Sjimharris | (this_port->physical_port_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) 2484230557Sjimharris | (this_port->reserved_rni) 2485230557Sjimharris ); 2486230557Sjimharris 2487230557Sjimharris scic_sds_controller_post_request(this_port->owning_controller, command); 2488230557Sjimharris 2489230557Sjimharris scic_cb_stall_execution(10); 2490230557Sjimharris 2491230557Sjimharris command = ( 2492230557Sjimharris (SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX_RX) 2493230557Sjimharris | (this_port->physical_port_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) 2494230557Sjimharris | (this_port->reserved_rni) 2495230557Sjimharris ); 2496230557Sjimharris 2497230557Sjimharris scic_sds_controller_post_request(this_port->owning_controller, command); 2498230557Sjimharris} 2499230557Sjimharris} 2500230557Sjimharris 2501230557Sjimharris/** 2502230557Sjimharris * 2503230557Sjimharris */ 2504230557Sjimharrisstatic 2505230557Sjimharrisvoid scic_sds_port_invalidate_dummy_remote_node( 2506230557Sjimharris SCIC_SDS_PORT_T *this_port 2507230557Sjimharris) 2508230557Sjimharris{ 2509230557Sjimharris U32 command; 2510230557Sjimharris SCU_REMOTE_NODE_CONTEXT_T * rnc; 2511230557Sjimharris 2512230557Sjimharris if (this_port->reserved_rni != SCU_DUMMY_INDEX) 2513230557Sjimharris { 2514230557Sjimharris rnc = &(this_port->owning_controller->remote_node_context_table[this_port->reserved_rni]); 2515230557Sjimharris 2516230557Sjimharris rnc->ssp.is_valid = FALSE; 2517230557Sjimharris 2518230557Sjimharris scic_cb_stall_execution(10); 2519230557Sjimharris 2520230557Sjimharris command = ( 2521230557Sjimharris (SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE) 2522230557Sjimharris | (this_port->physical_port_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) 2523230557Sjimharris | (this_port->reserved_rni) 2524230557Sjimharris ); 2525230557Sjimharris 2526230557Sjimharris scic_sds_controller_post_request(this_port->owning_controller, command); 2527230557Sjimharris} 2528230557Sjimharris} 2529230557Sjimharris 2530230557Sjimharris//****************************************************************************** 2531230557Sjimharris//* PORT STATE METHODS 2532230557Sjimharris//****************************************************************************** 2533230557Sjimharris 2534230557Sjimharris/** 2535230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PORT on 2536230557Sjimharris * entering the SCI_BASE_PORT_STATE_STOPPED. This function sets the stopped 2537230557Sjimharris * state handlers for the SCIC_SDS_PORT object and disables the port task 2538230557Sjimharris * scheduler in the hardware. 2539230557Sjimharris * 2540230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a 2541230557Sjimharris * SCIC_SDS_PORT object. 2542230557Sjimharris * 2543230557Sjimharris * @return none 2544230557Sjimharris */ 2545230557Sjimharrisstatic 2546230557Sjimharrisvoid scic_sds_port_stopped_state_enter( 2547230557Sjimharris SCI_BASE_OBJECT_T *object 2548230557Sjimharris) 2549230557Sjimharris{ 2550230557Sjimharris SCIC_SDS_PORT_T *this_port; 2551230557Sjimharris this_port = (SCIC_SDS_PORT_T *)object; 2552230557Sjimharris 2553230557Sjimharris scic_sds_port_set_base_state_handlers( 2554230557Sjimharris this_port, SCI_BASE_PORT_STATE_STOPPED 2555230557Sjimharris ); 2556230557Sjimharris 2557230557Sjimharris if ( 2558230557Sjimharris SCI_BASE_PORT_STATE_STOPPING 2559230557Sjimharris == this_port->parent.state_machine.previous_state_id 2560230557Sjimharris ) 2561230557Sjimharris { 2562230557Sjimharris // If we enter this state becasuse of a request to stop 2563230557Sjimharris // the port then we want to disable the hardwares port 2564230557Sjimharris // task scheduler. 2565230557Sjimharris scic_sds_port_disable_port_task_scheduler(this_port); 2566230557Sjimharris } 2567230557Sjimharris} 2568230557Sjimharris 2569230557Sjimharris/** 2570230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PORT on 2571230557Sjimharris * exiting the SCI_BASE_STATE_STOPPED. This function enables the SCU hardware 2572230557Sjimharris * port task scheduler. 2573230557Sjimharris * 2574230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a 2575230557Sjimharris * SCIC_SDS_PORT object. 2576230557Sjimharris * 2577230557Sjimharris * @return none 2578230557Sjimharris */ 2579230557Sjimharrisstatic 2580230557Sjimharrisvoid scic_sds_port_stopped_state_exit( 2581230557Sjimharris SCI_BASE_OBJECT_T *object 2582230557Sjimharris) 2583230557Sjimharris{ 2584230557Sjimharris SCIC_SDS_PORT_T *this_port; 2585230557Sjimharris this_port = (SCIC_SDS_PORT_T *)object; 2586230557Sjimharris 2587230557Sjimharris // Enable and suspend the port task scheduler 2588230557Sjimharris scic_sds_port_enable_port_task_scheduler(this_port); 2589230557Sjimharris} 2590230557Sjimharris 2591230557Sjimharris/** 2592230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PORT on 2593230557Sjimharris * entering the SCI_BASE_PORT_STATE_READY. This function sets the ready state 2594230557Sjimharris * handlers for the SCIC_SDS_PORT object, reports the port object as not ready 2595230557Sjimharris * and starts the ready substate machine. 2596230557Sjimharris * 2597230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a 2598230557Sjimharris * SCIC_SDS_PORT object. 2599230557Sjimharris * 2600230557Sjimharris * @return none 2601230557Sjimharris */ 2602230557Sjimharrisstatic 2603230557Sjimharrisvoid scic_sds_port_ready_state_enter( 2604230557Sjimharris SCI_BASE_OBJECT_T *object 2605230557Sjimharris) 2606230557Sjimharris{ 2607230557Sjimharris SCIC_SDS_PORT_T *this_port; 2608230557Sjimharris this_port = (SCIC_SDS_PORT_T *)object; 2609230557Sjimharris 2610230557Sjimharris // Put the ready state handlers in place though they will not be there long 2611230557Sjimharris scic_sds_port_set_base_state_handlers( 2612230557Sjimharris this_port, SCI_BASE_PORT_STATE_READY 2613230557Sjimharris ); 2614230557Sjimharris 2615230557Sjimharris if ( 2616230557Sjimharris SCI_BASE_PORT_STATE_RESETTING 2617230557Sjimharris == this_port->parent.state_machine.previous_state_id 2618230557Sjimharris ) 2619230557Sjimharris { 2620230557Sjimharris scic_cb_port_hard_reset_complete( 2621230557Sjimharris scic_sds_port_get_controller(this_port), 2622230557Sjimharris this_port, 2623230557Sjimharris SCI_SUCCESS 2624230557Sjimharris ); 2625230557Sjimharris } 2626230557Sjimharris else 2627230557Sjimharris { 2628230557Sjimharris // Notify the caller that the port is not yet ready 2629230557Sjimharris scic_cb_port_not_ready( 2630230557Sjimharris scic_sds_port_get_controller(this_port), 2631230557Sjimharris this_port, 2632230557Sjimharris SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS 2633230557Sjimharris ); 2634230557Sjimharris } 2635230557Sjimharris 2636230557Sjimharris // Post and suspend the dummy remote node context for this 2637230557Sjimharris // port. 2638230557Sjimharris scic_sds_port_post_dummy_remote_node(this_port); 2639230557Sjimharris 2640230557Sjimharris // Start the ready substate machine 2641230557Sjimharris sci_base_state_machine_start( 2642230557Sjimharris scic_sds_port_get_ready_substate_machine(this_port) 2643230557Sjimharris ); 2644230557Sjimharris} 2645230557Sjimharris 2646230557Sjimharris/** 2647230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PORT on 2648230557Sjimharris * exiting the SCI_BASE_STATE_READY. This function does nothing. 2649230557Sjimharris * 2650230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a 2651230557Sjimharris * SCIC_SDS_PORT object. 2652230557Sjimharris * 2653230557Sjimharris * @return none 2654230557Sjimharris */ 2655230557Sjimharrisstatic 2656230557Sjimharrisvoid scic_sds_port_ready_state_exit( 2657230557Sjimharris SCI_BASE_OBJECT_T *object 2658230557Sjimharris) 2659230557Sjimharris{ 2660230557Sjimharris SCIC_SDS_PORT_T *this_port; 2661230557Sjimharris this_port = (SCIC_SDS_PORT_T *)object; 2662230557Sjimharris 2663230557Sjimharris sci_base_state_machine_stop(&this_port->ready_substate_machine); 2664230557Sjimharris 2665230557Sjimharris scic_cb_stall_execution(10); 2666230557Sjimharris scic_sds_port_invalidate_dummy_remote_node(this_port); 2667230557Sjimharris} 2668230557Sjimharris 2669230557Sjimharris/** 2670230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PORT on 2671230557Sjimharris * entering the SCI_BASE_PORT_STATE_RESETTING. This function sets the 2672230557Sjimharris * resetting state handlers for the SCIC_SDS_PORT object. 2673230557Sjimharris * 2674230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a 2675230557Sjimharris * SCIC_SDS_PORT object. 2676230557Sjimharris * 2677230557Sjimharris * @return none 2678230557Sjimharris */ 2679230557Sjimharrisstatic 2680230557Sjimharrisvoid scic_sds_port_resetting_state_enter( 2681230557Sjimharris SCI_BASE_OBJECT_T *object 2682230557Sjimharris) 2683230557Sjimharris{ 2684230557Sjimharris SCIC_SDS_PORT_T *this_port; 2685230557Sjimharris this_port = (SCIC_SDS_PORT_T *)object; 2686230557Sjimharris 2687230557Sjimharris scic_sds_port_set_base_state_handlers( 2688230557Sjimharris this_port, SCI_BASE_PORT_STATE_RESETTING 2689230557Sjimharris ); 2690230557Sjimharris} 2691230557Sjimharris 2692230557Sjimharris/** 2693230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PORT on 2694230557Sjimharris * exiting the SCI_BASE_STATE_RESETTING. This function does nothing. 2695230557Sjimharris * 2696230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a 2697230557Sjimharris * SCIC_SDS_PORT object. 2698230557Sjimharris * 2699230557Sjimharris * @return none 2700230557Sjimharris */ 2701230557Sjimharrisstatic 2702230557Sjimharrisvoid scic_sds_port_resetting_state_exit( 2703230557Sjimharris SCI_BASE_OBJECT_T *object 2704230557Sjimharris) 2705230557Sjimharris{ 2706230557Sjimharris SCIC_SDS_PORT_T *this_port; 2707230557Sjimharris this_port = (SCIC_SDS_PORT_T *)object; 2708230557Sjimharris 2709230557Sjimharris scic_cb_timer_stop( 2710230557Sjimharris scic_sds_port_get_controller(this_port), 2711230557Sjimharris this_port->timer_handle 2712230557Sjimharris ); 2713230557Sjimharris} 2714230557Sjimharris 2715230557Sjimharris/** 2716230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PORT on 2717230557Sjimharris * entering the SCI_BASE_PORT_STATE_STOPPING. This function sets the stopping 2718230557Sjimharris * state handlers for the SCIC_SDS_PORT object. 2719230557Sjimharris * 2720230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a 2721230557Sjimharris * SCIC_SDS_PORT object. 2722230557Sjimharris * 2723230557Sjimharris * @return none 2724230557Sjimharris */ 2725230557Sjimharrisstatic 2726230557Sjimharrisvoid scic_sds_port_stopping_state_enter( 2727230557Sjimharris SCI_BASE_OBJECT_T *object 2728230557Sjimharris) 2729230557Sjimharris{ 2730230557Sjimharris SCIC_SDS_PORT_T *this_port; 2731230557Sjimharris this_port = (SCIC_SDS_PORT_T *)object; 2732230557Sjimharris 2733230557Sjimharris scic_sds_port_set_base_state_handlers( 2734230557Sjimharris this_port, SCI_BASE_PORT_STATE_STOPPING 2735230557Sjimharris ); 2736230557Sjimharris 2737230557Sjimharris if (this_port->started_request_count == 0) 2738230557Sjimharris { 2739230557Sjimharris sci_base_state_machine_change_state( 2740230557Sjimharris &this_port->parent.state_machine, 2741230557Sjimharris SCI_BASE_PORT_STATE_STOPPED 2742230557Sjimharris ); 2743230557Sjimharris } 2744230557Sjimharris} 2745230557Sjimharris 2746230557Sjimharris/** 2747230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PORT on 2748230557Sjimharris * exiting the SCI_BASE_STATE_STOPPING. This function does nothing. 2749230557Sjimharris * 2750230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a 2751230557Sjimharris * SCIC_SDS_PORT object. 2752230557Sjimharris * 2753230557Sjimharris * @return none 2754230557Sjimharris */ 2755230557Sjimharrisstatic 2756230557Sjimharrisvoid scic_sds_port_stopping_state_exit( 2757230557Sjimharris SCI_BASE_OBJECT_T *object 2758230557Sjimharris) 2759230557Sjimharris{ 2760230557Sjimharris SCIC_SDS_PORT_T *this_port; 2761230557Sjimharris this_port = (SCIC_SDS_PORT_T *)object; 2762230557Sjimharris 2763230557Sjimharris scic_cb_timer_stop( 2764230557Sjimharris scic_sds_port_get_controller(this_port), 2765230557Sjimharris this_port->timer_handle 2766230557Sjimharris ); 2767230557Sjimharris 2768230557Sjimharris scic_cb_timer_destroy( 2769230557Sjimharris scic_sds_port_get_controller(this_port), 2770230557Sjimharris this_port->timer_handle 2771230557Sjimharris ); 2772230557Sjimharris this_port->timer_handle = NULL; 2773230557Sjimharris 2774230557Sjimharris scic_sds_port_destroy_dummy_resources(this_port); 2775230557Sjimharris} 2776230557Sjimharris 2777230557Sjimharris/** 2778230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PORT on 2779230557Sjimharris * entering the SCI_BASE_PORT_STATE_STOPPING. This function sets the stopping 2780230557Sjimharris * state handlers for the SCIC_SDS_PORT object. 2781230557Sjimharris * 2782230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a 2783230557Sjimharris * SCIC_SDS_PORT object. 2784230557Sjimharris * 2785230557Sjimharris * @return none 2786230557Sjimharris */ 2787230557Sjimharrisstatic 2788230557Sjimharrisvoid scic_sds_port_failed_state_enter( 2789230557Sjimharris SCI_BASE_OBJECT_T *object 2790230557Sjimharris) 2791230557Sjimharris{ 2792230557Sjimharris SCIC_SDS_PORT_T *this_port; 2793230557Sjimharris this_port = (SCIC_SDS_PORT_T *)object; 2794230557Sjimharris 2795230557Sjimharris scic_sds_port_set_base_state_handlers( 2796230557Sjimharris this_port, 2797230557Sjimharris SCI_BASE_PORT_STATE_FAILED 2798230557Sjimharris ); 2799230557Sjimharris 2800230557Sjimharris scic_cb_port_hard_reset_complete( 2801230557Sjimharris scic_sds_port_get_controller(this_port), 2802230557Sjimharris this_port, 2803230557Sjimharris SCI_FAILURE_TIMEOUT 2804230557Sjimharris ); 2805230557Sjimharris} 2806230557Sjimharris 2807230557Sjimharris// --------------------------------------------------------------------------- 2808230557Sjimharris 2809230557SjimharrisSCI_BASE_STATE_T scic_sds_port_state_table[SCI_BASE_PORT_MAX_STATES] = 2810230557Sjimharris{ 2811230557Sjimharris { 2812230557Sjimharris SCI_BASE_PORT_STATE_STOPPED, 2813230557Sjimharris scic_sds_port_stopped_state_enter, 2814230557Sjimharris scic_sds_port_stopped_state_exit 2815230557Sjimharris }, 2816230557Sjimharris { 2817230557Sjimharris SCI_BASE_PORT_STATE_STOPPING, 2818230557Sjimharris scic_sds_port_stopping_state_enter, 2819230557Sjimharris scic_sds_port_stopping_state_exit 2820230557Sjimharris }, 2821230557Sjimharris { 2822230557Sjimharris SCI_BASE_PORT_STATE_READY, 2823230557Sjimharris scic_sds_port_ready_state_enter, 2824230557Sjimharris scic_sds_port_ready_state_exit 2825230557Sjimharris }, 2826230557Sjimharris { 2827230557Sjimharris SCI_BASE_PORT_STATE_RESETTING, 2828230557Sjimharris scic_sds_port_resetting_state_enter, 2829230557Sjimharris scic_sds_port_resetting_state_exit 2830230557Sjimharris }, 2831230557Sjimharris { 2832230557Sjimharris SCI_BASE_PORT_STATE_FAILED, 2833230557Sjimharris scic_sds_port_failed_state_enter, 2834230557Sjimharris NULL 2835230557Sjimharris } 2836230557Sjimharris}; 2837230557Sjimharris 2838230557Sjimharris//****************************************************************************** 2839230557Sjimharris//* PORT READY SUB-STATE MACHINE 2840230557Sjimharris//****************************************************************************** 2841230557Sjimharris 2842230557Sjimharris//**************************************************************************** 2843230557Sjimharris//* READY SUBSTATE HANDLERS 2844230557Sjimharris//**************************************************************************** 2845230557Sjimharris 2846230557Sjimharris/** 2847230557Sjimharris * This method is the general ready state stop handler for the SCIC_SDS_PORT 2848230557Sjimharris * object. This function will transition the ready substate machine to its 2849230557Sjimharris * final state. 2850230557Sjimharris * 2851230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a 2852230557Sjimharris * SCIC_SDS_PORT object. 2853230557Sjimharris * 2854230557Sjimharris * @return SCI_STATUS 2855230557Sjimharris * @retval SCI_SUCCESS 2856230557Sjimharris */ 2857230557Sjimharrisstatic 2858230557SjimharrisSCI_STATUS scic_sds_port_ready_substate_stop_handler( 2859230557Sjimharris SCI_BASE_PORT_T *port 2860230557Sjimharris) 2861230557Sjimharris{ 2862230557Sjimharris SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)port; 2863230557Sjimharris 2864230557Sjimharris sci_base_state_machine_change_state( 2865230557Sjimharris &this_port->parent.state_machine, 2866230557Sjimharris SCI_BASE_PORT_STATE_STOPPING 2867230557Sjimharris ); 2868230557Sjimharris 2869230557Sjimharris return SCI_SUCCESS; 2870230557Sjimharris} 2871230557Sjimharris 2872230557Sjimharris/** 2873230557Sjimharris * This method is the general ready substate complete io handler for the 2874230557Sjimharris * SCIC_SDS_PORT object. This function decrments the outstanding request 2875230557Sjimharris * count for this port object. 2876230557Sjimharris * 2877230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a 2878230557Sjimharris * SCIC_SDS_PORT object. 2879230557Sjimharris * @param[in] device This is the SCI_BASE_REMOTE_DEVICE object which is not 2880230557Sjimharris * used in this function. 2881230557Sjimharris * @param[in] io_request This is the SCI_BASE_REQUEST object which is not used 2882230557Sjimharris * in this function. 2883230557Sjimharris * 2884230557Sjimharris * @return SCI_STATUS 2885230557Sjimharris * @retval SCI_SUCCESS 2886230557Sjimharris */ 2887230557Sjimharrisstatic 2888230557SjimharrisSCI_STATUS scic_sds_port_ready_substate_complete_io_handler( 2889230557Sjimharris SCIC_SDS_PORT_T *port, 2890230557Sjimharris struct SCIC_SDS_REMOTE_DEVICE *device, 2891230557Sjimharris struct SCIC_SDS_REQUEST *io_request 2892230557Sjimharris) 2893230557Sjimharris{ 2894230557Sjimharris SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)port; 2895230557Sjimharris 2896230557Sjimharris scic_sds_port_decrement_request_count(this_port); 2897230557Sjimharris 2898230557Sjimharris return SCI_SUCCESS; 2899230557Sjimharris} 2900230557Sjimharris 2901230557Sjimharrisstatic 2902230557SjimharrisSCI_STATUS scic_sds_port_ready_substate_add_phy_handler( 2903230557Sjimharris SCI_BASE_PORT_T *port, 2904230557Sjimharris SCI_BASE_PHY_T *phy 2905230557Sjimharris) 2906230557Sjimharris{ 2907230557Sjimharris SCIC_SDS_PORT_T * this_port = (SCIC_SDS_PORT_T *)port; 2908230557Sjimharris SCIC_SDS_PHY_T * this_phy = (SCIC_SDS_PHY_T *)phy; 2909230557Sjimharris SCI_STATUS status; 2910230557Sjimharris 2911230557Sjimharris status = scic_sds_port_set_phy(this_port, this_phy); 2912230557Sjimharris 2913230557Sjimharris if (status == SCI_SUCCESS) 2914230557Sjimharris { 2915230557Sjimharris scic_sds_port_general_link_up_handler(this_port, this_phy, TRUE, FALSE); 2916230557Sjimharris 2917230557Sjimharris this_port->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING; 2918230557Sjimharris 2919230557Sjimharris sci_base_state_machine_change_state( 2920230557Sjimharris &this_port->ready_substate_machine, 2921230557Sjimharris SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING 2922230557Sjimharris ); 2923230557Sjimharris } 2924230557Sjimharris 2925230557Sjimharris return status; 2926230557Sjimharris} 2927230557Sjimharris 2928230557Sjimharrisstatic 2929230557SjimharrisSCI_STATUS scic_sds_port_ready_substate_remove_phy_handler( 2930230557Sjimharris SCI_BASE_PORT_T *port, 2931230557Sjimharris SCI_BASE_PHY_T *phy 2932230557Sjimharris) 2933230557Sjimharris{ 2934230557Sjimharris SCIC_SDS_PORT_T * this_port = (SCIC_SDS_PORT_T *)port; 2935230557Sjimharris SCIC_SDS_PHY_T * this_phy = (SCIC_SDS_PHY_T *)phy; 2936230557Sjimharris SCI_STATUS status; 2937230557Sjimharris 2938230557Sjimharris status = scic_sds_port_clear_phy(this_port, this_phy); 2939230557Sjimharris 2940230557Sjimharris if (status == SCI_SUCCESS) 2941230557Sjimharris { 2942230557Sjimharris scic_sds_port_deactivate_phy(this_port, this_phy, TRUE); 2943230557Sjimharris 2944230557Sjimharris this_port->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING; 2945230557Sjimharris 2946230557Sjimharris sci_base_state_machine_change_state( 2947230557Sjimharris &this_port->ready_substate_machine, 2948230557Sjimharris SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING 2949230557Sjimharris ); 2950230557Sjimharris } 2951230557Sjimharris 2952230557Sjimharris return status; 2953230557Sjimharris} 2954230557Sjimharris 2955230557Sjimharris//**************************************************************************** 2956230557Sjimharris//* READY SUBSTATE WAITING HANDLERS 2957230557Sjimharris//**************************************************************************** 2958230557Sjimharris 2959230557Sjimharris/** 2960230557Sjimharris * This method is the ready waiting substate link up handler for the 2961230557Sjimharris * SCIC_SDS_PORT object. This methos will report the link up condition for 2962230557Sjimharris * this port and will transition to the ready operational substate. 2963230557Sjimharris * 2964230557Sjimharris * @param[in] this_port This is the SCIC_SDS_PORT object that which has a phy 2965230557Sjimharris * that has gone link up. 2966230557Sjimharris * @param[in] the_phy This is the SCIC_SDS_PHY object that has gone link up. 2967230557Sjimharris * 2968230557Sjimharris * @return none 2969230557Sjimharris */ 2970230557Sjimharrisstatic 2971230557Sjimharrisvoid scic_sds_port_ready_waiting_substate_link_up_handler( 2972230557Sjimharris SCIC_SDS_PORT_T *this_port, 2973230557Sjimharris SCIC_SDS_PHY_T *the_phy 2974230557Sjimharris) 2975230557Sjimharris{ 2976230557Sjimharris // Since this is the first phy going link up for the port we can just enable 2977230557Sjimharris // it and continue. 2978230557Sjimharris scic_sds_port_activate_phy(this_port, the_phy, TRUE, TRUE); 2979230557Sjimharris 2980230557Sjimharris sci_base_state_machine_change_state( 2981230557Sjimharris &this_port->ready_substate_machine, 2982230557Sjimharris SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL 2983230557Sjimharris ); 2984230557Sjimharris} 2985230557Sjimharris 2986230557Sjimharris/** 2987230557Sjimharris * This method is the ready waiting substate start io handler for the 2988230557Sjimharris * SCIC_SDS_PORT object. The port object can not accept new requests so the 2989230557Sjimharris * request is failed. 2990230557Sjimharris * 2991230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a 2992230557Sjimharris * SCIC_SDS_PORT object. 2993230557Sjimharris * @param[in] device This is the SCI_BASE_REMOTE_DEVICE object which is not 2994230557Sjimharris * used in this request. 2995230557Sjimharris * @param[in] io_request This is the SCI_BASE_REQUEST object which is not used 2996230557Sjimharris * in this function. 2997230557Sjimharris * 2998230557Sjimharris * @return SCI_STATUS 2999230557Sjimharris * @retval SCI_FAILURE_INVALID_STATE 3000230557Sjimharris */ 3001230557Sjimharrisstatic 3002230557SjimharrisSCI_STATUS scic_sds_port_ready_waiting_substate_start_io_handler( 3003230557Sjimharris SCIC_SDS_PORT_T *port, 3004230557Sjimharris SCIC_SDS_REMOTE_DEVICE_T *device, 3005230557Sjimharris SCIC_SDS_REQUEST_T *io_request 3006230557Sjimharris) 3007230557Sjimharris{ 3008230557Sjimharris return SCI_FAILURE_INVALID_STATE; 3009230557Sjimharris} 3010230557Sjimharris 3011230557Sjimharris//**************************************************************************** 3012230557Sjimharris//* READY SUBSTATE OPERATIONAL HANDLERS 3013230557Sjimharris//**************************************************************************** 3014230557Sjimharris 3015230557Sjimharris/** 3016230557Sjimharris * This method will casue the port to reset. 3017230557Sjimharris * 3018230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a 3019230557Sjimharris * SCIC_SDS_PORT object. 3020230557Sjimharris * @param[in] timeout This is the timeout for the reset request to complete. 3021230557Sjimharris * 3022230557Sjimharris * @return SCI_STATUS 3023230557Sjimharris * @retval SCI_SUCCESS 3024230557Sjimharris */ 3025230557Sjimharrisstatic 3026230557SjimharrisSCI_STATUS scic_sds_port_ready_operational_substate_reset_handler( 3027230557Sjimharris SCI_BASE_PORT_T * port, 3028230557Sjimharris U32 timeout 3029230557Sjimharris) 3030230557Sjimharris{ 3031230557Sjimharris SCI_STATUS status = SCI_FAILURE_INVALID_PHY; 3032230557Sjimharris U32 phy_index; 3033230557Sjimharris SCIC_SDS_PORT_T * this_port = (SCIC_SDS_PORT_T *)port; 3034230557Sjimharris SCIC_SDS_PHY_T * selected_phy = SCI_INVALID_HANDLE; 3035230557Sjimharris 3036230557Sjimharris 3037230557Sjimharris // Select a phy on which we can send the hard reset request. 3038230557Sjimharris for ( 3039230557Sjimharris phy_index = 0; 3040230557Sjimharris (phy_index < SCI_MAX_PHYS) 3041230557Sjimharris && (selected_phy == SCI_INVALID_HANDLE); 3042230557Sjimharris phy_index++ 3043230557Sjimharris ) 3044230557Sjimharris { 3045230557Sjimharris selected_phy = this_port->phy_table[phy_index]; 3046230557Sjimharris 3047230557Sjimharris if ( 3048230557Sjimharris (selected_phy != SCI_INVALID_HANDLE) 3049230557Sjimharris && !scic_sds_port_active_phy(this_port, selected_phy) 3050230557Sjimharris ) 3051230557Sjimharris { 3052230557Sjimharris // We found a phy but it is not ready select different phy 3053230557Sjimharris selected_phy = SCI_INVALID_HANDLE; 3054230557Sjimharris } 3055230557Sjimharris } 3056230557Sjimharris 3057230557Sjimharris // If we have a phy then go ahead and start the reset procedure 3058230557Sjimharris if (selected_phy != SCI_INVALID_HANDLE) 3059230557Sjimharris { 3060230557Sjimharris status = scic_sds_phy_reset(selected_phy); 3061230557Sjimharris 3062230557Sjimharris if (status == SCI_SUCCESS) 3063230557Sjimharris { 3064230557Sjimharris scic_cb_timer_start( 3065230557Sjimharris scic_sds_port_get_controller(this_port), 3066230557Sjimharris this_port->timer_handle, 3067230557Sjimharris timeout 3068230557Sjimharris ); 3069230557Sjimharris 3070230557Sjimharris this_port->not_ready_reason = SCIC_PORT_NOT_READY_HARD_RESET_REQUESTED; 3071230557Sjimharris 3072230557Sjimharris sci_base_state_machine_change_state( 3073230557Sjimharris &this_port->parent.state_machine, 3074230557Sjimharris SCI_BASE_PORT_STATE_RESETTING 3075230557Sjimharris ); 3076230557Sjimharris } 3077230557Sjimharris } 3078230557Sjimharris 3079230557Sjimharris return status; 3080230557Sjimharris} 3081230557Sjimharris 3082230557Sjimharris/** 3083230557Sjimharris * This method is the ready operational substate link up handler for the 3084230557Sjimharris * SCIC_SDS_PORT object. This function notifies the SCI User that the phy has 3085230557Sjimharris * gone link up. 3086230557Sjimharris * 3087230557Sjimharris * @param[in] this_port This is the SCIC_SDS_PORT object that which has a phy 3088230557Sjimharris * that has gone link up. 3089230557Sjimharris * @param[in] the_phy This is the SCIC_SDS_PHY object that has gone link up. 3090230557Sjimharris * 3091230557Sjimharris * @return none 3092230557Sjimharris */ 3093230557Sjimharrisstatic 3094230557Sjimharrisvoid scic_sds_port_ready_operational_substate_link_up_handler( 3095230557Sjimharris SCIC_SDS_PORT_T *this_port, 3096230557Sjimharris SCIC_SDS_PHY_T *the_phy 3097230557Sjimharris) 3098230557Sjimharris{ 3099230557Sjimharris scic_sds_port_general_link_up_handler(this_port, the_phy, TRUE, TRUE); 3100230557Sjimharris} 3101230557Sjimharris 3102230557Sjimharris/** 3103230557Sjimharris * This method is the ready operational substate link down handler for the 3104230557Sjimharris * SCIC_SDS_PORT object. This function notifies the SCI User that the phy has 3105230557Sjimharris * gone link down and if this is the last phy in the port the port will change 3106230557Sjimharris * state to the ready waiting substate. 3107230557Sjimharris * 3108230557Sjimharris * @param[in] this_port This is the SCIC_SDS_PORT object that which has a phy 3109230557Sjimharris * that has gone link down. 3110230557Sjimharris * @param[in] the_phy This is the SCIC_SDS_PHY object that has gone link down. 3111230557Sjimharris * 3112230557Sjimharris * @return none 3113230557Sjimharris */ 3114230557Sjimharrisstatic 3115230557Sjimharrisvoid scic_sds_port_ready_operational_substate_link_down_handler( 3116230557Sjimharris SCIC_SDS_PORT_T *this_port, 3117230557Sjimharris SCIC_SDS_PHY_T *the_phy 3118230557Sjimharris) 3119230557Sjimharris{ 3120230557Sjimharris scic_sds_port_deactivate_phy(this_port, the_phy, TRUE); 3121230557Sjimharris 3122230557Sjimharris // If there are no active phys left in the port, then transition 3123230557Sjimharris // the port to the WAITING state until such time as a phy goes 3124230557Sjimharris // link up. 3125230557Sjimharris if (this_port->active_phy_mask == 0) 3126230557Sjimharris { 3127230557Sjimharris sci_base_state_machine_change_state( 3128230557Sjimharris scic_sds_port_get_ready_substate_machine(this_port), 3129230557Sjimharris SCIC_SDS_PORT_READY_SUBSTATE_WAITING 3130230557Sjimharris ); 3131230557Sjimharris } 3132230557Sjimharris} 3133230557Sjimharris 3134230557Sjimharris/** 3135230557Sjimharris * This method is the ready operational substate start io handler for the 3136230557Sjimharris * SCIC_SDS_PORT object. This function incremetns the outstanding request 3137230557Sjimharris * count for this port object. 3138230557Sjimharris * 3139230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a 3140230557Sjimharris * SCIC_SDS_PORT object. 3141230557Sjimharris * @param[in] device This is the SCI_BASE_REMOTE_DEVICE object which is not 3142230557Sjimharris * used in this function. 3143230557Sjimharris * @param[in] io_request This is the SCI_BASE_REQUEST object which is not used 3144230557Sjimharris * in this function. 3145230557Sjimharris * 3146230557Sjimharris * @return SCI_STATUS 3147230557Sjimharris * @retval SCI_SUCCESS 3148230557Sjimharris */ 3149230557Sjimharrisstatic 3150230557SjimharrisSCI_STATUS scic_sds_port_ready_operational_substate_start_io_handler( 3151230557Sjimharris SCIC_SDS_PORT_T *port, 3152230557Sjimharris SCIC_SDS_REMOTE_DEVICE_T *device, 3153230557Sjimharris SCIC_SDS_REQUEST_T *io_request 3154230557Sjimharris) 3155230557Sjimharris{ 3156230557Sjimharris SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)port; 3157230557Sjimharris 3158230557Sjimharris scic_sds_port_increment_request_count(this_port); 3159230557Sjimharris 3160230557Sjimharris return SCI_SUCCESS; 3161230557Sjimharris} 3162230557Sjimharris 3163230557Sjimharris//**************************************************************************** 3164230557Sjimharris//* READY SUBSTATE OPERATIONAL HANDLERS 3165230557Sjimharris//**************************************************************************** 3166230557Sjimharris 3167230557Sjimharris/** 3168230557Sjimharris * This is the default method for a port add phy request. It will report a 3169230557Sjimharris * warning and exit. 3170230557Sjimharris * 3171230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a 3172230557Sjimharris * SCIC_SDS_PORT object. 3173230557Sjimharris * 3174230557Sjimharris * @return SCI_STATUS 3175230557Sjimharris * @retval SCI_FAILURE_INVALID_STATE 3176230557Sjimharris */ 3177230557Sjimharrisstatic 3178230557SjimharrisSCI_STATUS scic_sds_port_ready_configuring_substate_add_phy_handler( 3179230557Sjimharris SCI_BASE_PORT_T *port, 3180230557Sjimharris SCI_BASE_PHY_T *phy 3181230557Sjimharris) 3182230557Sjimharris{ 3183230557Sjimharris SCIC_SDS_PORT_T * this_port = (SCIC_SDS_PORT_T *)port; 3184230557Sjimharris SCIC_SDS_PHY_T * this_phy = (SCIC_SDS_PHY_T *)phy; 3185230557Sjimharris SCI_STATUS status; 3186230557Sjimharris 3187230557Sjimharris status = scic_sds_port_set_phy(this_port, this_phy); 3188230557Sjimharris 3189230557Sjimharris if (status == SCI_SUCCESS) 3190230557Sjimharris { 3191230557Sjimharris scic_sds_port_general_link_up_handler(this_port, this_phy, TRUE, FALSE); 3192230557Sjimharris 3193230557Sjimharris // Re-enter the configuring state since this may be the last phy in 3194230557Sjimharris // the port. 3195230557Sjimharris sci_base_state_machine_change_state( 3196230557Sjimharris &this_port->ready_substate_machine, 3197230557Sjimharris SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING 3198230557Sjimharris ); 3199230557Sjimharris } 3200230557Sjimharris 3201230557Sjimharris return status; 3202230557Sjimharris} 3203230557Sjimharris 3204230557Sjimharris/** 3205230557Sjimharris * This is the default method for a port remove phy request. It will report a 3206230557Sjimharris * warning and exit. 3207230557Sjimharris * 3208230557Sjimharris * @param[in] port This is the SCI_BASE_PORT object which is cast into a 3209230557Sjimharris * SCIC_SDS_PORT object. 3210230557Sjimharris * 3211230557Sjimharris * @return SCI_STATUS 3212230557Sjimharris * @retval SCI_FAILURE_INVALID_STATE 3213230557Sjimharris */ 3214230557Sjimharrisstatic 3215230557SjimharrisSCI_STATUS scic_sds_port_ready_configuring_substate_remove_phy_handler( 3216230557Sjimharris SCI_BASE_PORT_T *port, 3217230557Sjimharris SCI_BASE_PHY_T *phy 3218230557Sjimharris) 3219230557Sjimharris{ 3220230557Sjimharris SCIC_SDS_PORT_T * this_port = (SCIC_SDS_PORT_T *)port; 3221230557Sjimharris SCIC_SDS_PHY_T * this_phy = (SCIC_SDS_PHY_T *)phy; 3222230557Sjimharris SCI_STATUS status; 3223230557Sjimharris 3224230557Sjimharris status = scic_sds_port_clear_phy(this_port, this_phy); 3225230557Sjimharris 3226230557Sjimharris if (status == SCI_SUCCESS) 3227230557Sjimharris { 3228230557Sjimharris scic_sds_port_deactivate_phy(this_port, this_phy, TRUE); 3229230557Sjimharris 3230230557Sjimharris // Re-enter the configuring state since this may be the last phy in 3231230557Sjimharris // the port. 3232230557Sjimharris sci_base_state_machine_change_state( 3233230557Sjimharris &this_port->ready_substate_machine, 3234230557Sjimharris SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING 3235230557Sjimharris ); 3236230557Sjimharris } 3237230557Sjimharris 3238230557Sjimharris return status; 3239230557Sjimharris} 3240230557Sjimharris 3241230557Sjimharris/** 3242230557Sjimharris * This method will decrement the outstanding request count for this port. 3243230557Sjimharris * If the request count goes to 0 then the port can be reprogrammed with 3244230557Sjimharris * its new phy data. 3245230557Sjimharris * 3246230557Sjimharris * @param[in] port This is the port that is being requested to complete 3247230557Sjimharris * the io request. 3248230557Sjimharris * @param[in] device This is the device on which the io is completing. 3249230557Sjimharris * @param[in] io_request This is the io request that is completing. 3250230557Sjimharris */ 3251230557Sjimharrisstatic 3252230557SjimharrisSCI_STATUS scic_sds_port_ready_configuring_substate_complete_io_handler( 3253230557Sjimharris SCIC_SDS_PORT_T *port, 3254230557Sjimharris SCIC_SDS_REMOTE_DEVICE_T *device, 3255230557Sjimharris SCIC_SDS_REQUEST_T *io_request 3256230557Sjimharris) 3257230557Sjimharris{ 3258230557Sjimharris scic_sds_port_decrement_request_count(port); 3259230557Sjimharris 3260230557Sjimharris if (port->started_request_count == 0) 3261230557Sjimharris { 3262230557Sjimharris sci_base_state_machine_change_state( 3263230557Sjimharris &port->ready_substate_machine, 3264230557Sjimharris SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL 3265230557Sjimharris ); 3266230557Sjimharris } 3267230557Sjimharris 3268230557Sjimharris return SCI_SUCCESS; 3269230557Sjimharris} 3270230557Sjimharris 3271230557Sjimharris// --------------------------------------------------------------------------- 3272230557Sjimharris 3273230557SjimharrisSCIC_SDS_PORT_STATE_HANDLER_T 3274230557Sjimharris scic_sds_port_ready_substate_handler_table[SCIC_SDS_PORT_READY_MAX_SUBSTATES] = 3275230557Sjimharris{ 3276230557Sjimharris // SCIC_SDS_PORT_READY_SUBSTATE_WAITING 3277230557Sjimharris { 3278230557Sjimharris { 3279230557Sjimharris scic_sds_port_default_start_handler, 3280230557Sjimharris scic_sds_port_ready_substate_stop_handler, 3281230557Sjimharris scic_sds_port_default_destruct_handler, 3282230557Sjimharris scic_sds_port_default_reset_handler, 3283230557Sjimharris scic_sds_port_ready_substate_add_phy_handler, 3284230557Sjimharris scic_sds_port_default_remove_phy_handler 3285230557Sjimharris }, 3286230557Sjimharris scic_sds_port_default_frame_handler, 3287230557Sjimharris scic_sds_port_default_event_handler, 3288230557Sjimharris scic_sds_port_ready_waiting_substate_link_up_handler, 3289230557Sjimharris scic_sds_port_default_link_down_handler, 3290230557Sjimharris scic_sds_port_ready_waiting_substate_start_io_handler, 3291230557Sjimharris scic_sds_port_ready_substate_complete_io_handler, 3292230557Sjimharris }, 3293230557Sjimharris // SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL 3294230557Sjimharris { 3295230557Sjimharris { 3296230557Sjimharris scic_sds_port_default_start_handler, 3297230557Sjimharris scic_sds_port_ready_substate_stop_handler, 3298230557Sjimharris scic_sds_port_default_destruct_handler, 3299230557Sjimharris scic_sds_port_ready_operational_substate_reset_handler, 3300230557Sjimharris scic_sds_port_ready_substate_add_phy_handler, 3301230557Sjimharris scic_sds_port_ready_substate_remove_phy_handler 3302230557Sjimharris }, 3303230557Sjimharris scic_sds_port_default_frame_handler, 3304230557Sjimharris scic_sds_port_default_event_handler, 3305230557Sjimharris scic_sds_port_ready_operational_substate_link_up_handler, 3306230557Sjimharris scic_sds_port_ready_operational_substate_link_down_handler, 3307230557Sjimharris scic_sds_port_ready_operational_substate_start_io_handler, 3308230557Sjimharris scic_sds_port_ready_substate_complete_io_handler 3309230557Sjimharris }, 3310230557Sjimharris // SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING 3311230557Sjimharris { 3312230557Sjimharris { 3313230557Sjimharris scic_sds_port_default_start_handler, 3314230557Sjimharris scic_sds_port_ready_substate_stop_handler, 3315230557Sjimharris scic_sds_port_default_destruct_handler, 3316230557Sjimharris scic_sds_port_default_reset_handler, 3317230557Sjimharris scic_sds_port_ready_configuring_substate_add_phy_handler, 3318230557Sjimharris scic_sds_port_ready_configuring_substate_remove_phy_handler 3319230557Sjimharris }, 3320230557Sjimharris scic_sds_port_default_frame_handler, 3321230557Sjimharris scic_sds_port_default_event_handler, 3322230557Sjimharris scic_sds_port_default_link_up_handler, 3323230557Sjimharris scic_sds_port_default_link_down_handler, 3324230557Sjimharris scic_sds_port_default_start_io_handler, 3325230557Sjimharris scic_sds_port_ready_configuring_substate_complete_io_handler 3326230557Sjimharris } 3327230557Sjimharris}; 3328230557Sjimharris 3329230557Sjimharris/** 3330230557Sjimharris * This macro sets the port ready substate handlers. 3331230557Sjimharris */ 3332230557Sjimharris#define scic_sds_port_set_ready_state_handlers(port, state_id) \ 3333230557Sjimharris scic_sds_port_set_state_handlers( \ 3334230557Sjimharris port, &scic_sds_port_ready_substate_handler_table[(state_id)] \ 3335230557Sjimharris ) 3336230557Sjimharris 3337230557Sjimharris//****************************************************************************** 3338230557Sjimharris//* PORT STATE PRIVATE METHODS 3339230557Sjimharris//****************************************************************************** 3340230557Sjimharris 3341230557Sjimharris/** 3342230557Sjimharris * This method will susped the port task scheduler for this port object. 3343230557Sjimharris * 3344230557Sjimharris * @param[in] this_port This is the SCIC_SDS_PORT object to suspend. 3345230557Sjimharris * 3346230557Sjimharris * @return none 3347230557Sjimharris */ 3348230557Sjimharrisvoid scic_sds_port_suspend_port_task_scheduler( 3349230557Sjimharris SCIC_SDS_PORT_T *this_port 3350230557Sjimharris) 3351230557Sjimharris{ 3352230557Sjimharris U32 pts_control_value; 3353230557Sjimharris 3354230557Sjimharris pts_control_value = scu_port_task_scheduler_read(this_port, control); 3355230557Sjimharris pts_control_value |= SCU_PTSxCR_GEN_BIT(SUSPEND); 3356230557Sjimharris scu_port_task_scheduler_write(this_port, control, pts_control_value); 3357230557Sjimharris} 3358230557Sjimharris 3359230557Sjimharris/** 3360230557Sjimharris * This method will resume the port task scheduler for this port object. 3361230557Sjimharris * 3362230557Sjimharris * @param[in] this_port This is the SCIC_SDS_PORT object to resume. 3363230557Sjimharris * 3364230557Sjimharris * @return none 3365230557Sjimharris */ 3366230557Sjimharrisvoid scic_sds_port_resume_port_task_scheduler( 3367230557Sjimharris SCIC_SDS_PORT_T *this_port 3368230557Sjimharris) 3369230557Sjimharris{ 3370230557Sjimharris U32 pts_control_value; 3371230557Sjimharris 3372230557Sjimharris pts_control_value = scu_port_task_scheduler_read(this_port, control); 3373230557Sjimharris 3374230557Sjimharris pts_control_value &= ~SCU_PTSxCR_GEN_BIT(SUSPEND); 3375230557Sjimharris 3376230557Sjimharris scu_port_task_scheduler_write(this_port, control, pts_control_value); 3377230557Sjimharris} 3378230557Sjimharris 3379230557Sjimharris/** 3380230557Sjimharris * This routine will post the dummy request. This will prevent the hardware 3381230557Sjimharris * scheduler from posting new requests to the front of the scheduler queue 3382230557Sjimharris * causing a starvation problem for currently ongoing requests. 3383230557Sjimharris * 3384230557Sjimharris * @parm[in] this_port The port on which the task must be posted. 3385230557Sjimharris * 3386230557Sjimharris * @return none 3387230557Sjimharris */ 3388230557Sjimharrisstatic 3389230557Sjimharrisvoid scic_sds_port_post_dummy_request( 3390230557Sjimharris SCIC_SDS_PORT_T *this_port 3391230557Sjimharris) 3392230557Sjimharris{ 3393230557Sjimharris U32 command; 3394230557Sjimharris SCU_TASK_CONTEXT_T * task_context; 3395230557Sjimharris 3396230557Sjimharris if (this_port->reserved_tci != SCU_DUMMY_INDEX) 3397230557Sjimharris { 3398230557Sjimharris task_context = scic_sds_controller_get_task_context_buffer( 3399230557Sjimharris this_port->owning_controller, 3400230557Sjimharris this_port->reserved_tci 3401230557Sjimharris ); 3402230557Sjimharris 3403230557Sjimharris task_context->abort = 0; 3404230557Sjimharris 3405230557Sjimharris command = ( 3406230557Sjimharris (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC) 3407230557Sjimharris | (this_port->physical_port_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) 3408230557Sjimharris | (this_port->reserved_tci) 3409230557Sjimharris ); 3410230557Sjimharris 3411230557Sjimharris scic_sds_controller_post_request(this_port->owning_controller, command); 3412230557Sjimharris} 3413230557Sjimharris} 3414230557Sjimharris 3415230557Sjimharris/** 3416230557Sjimharris * This routine will abort the dummy request. This will alow the hardware to 3417230557Sjimharris * power down parts of the silicon to save power. 3418230557Sjimharris * 3419230557Sjimharris * @parm[in] this_port The port on which the task must be aborted. 3420230557Sjimharris * 3421230557Sjimharris * @return none 3422230557Sjimharris */ 3423230557Sjimharrisstatic 3424230557Sjimharrisvoid scic_sds_port_abort_dummy_request( 3425230557Sjimharris SCIC_SDS_PORT_T *this_port 3426230557Sjimharris) 3427230557Sjimharris{ 3428230557Sjimharris U32 command; 3429230557Sjimharris SCU_TASK_CONTEXT_T * task_context; 3430230557Sjimharris 3431230557Sjimharris if (this_port->reserved_tci != SCU_DUMMY_INDEX) 3432230557Sjimharris { 3433230557Sjimharris task_context = scic_sds_controller_get_task_context_buffer( 3434230557Sjimharris this_port->owning_controller, 3435230557Sjimharris this_port->reserved_tci 3436230557Sjimharris ); 3437230557Sjimharris 3438230557Sjimharris task_context->abort = 1; 3439230557Sjimharris 3440230557Sjimharris command = ( 3441230557Sjimharris (SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT) 3442230557Sjimharris | (this_port->physical_port_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) 3443230557Sjimharris | (this_port->reserved_tci) 3444230557Sjimharris ); 3445230557Sjimharris 3446230557Sjimharris scic_sds_controller_post_request(this_port->owning_controller, command); 3447230557Sjimharris} 3448230557Sjimharris} 3449230557Sjimharris 3450230557Sjimharris//****************************************************************************** 3451230557Sjimharris//* PORT READY SUBSTATE METHODS 3452230557Sjimharris//****************************************************************************** 3453230557Sjimharris 3454230557Sjimharris/** 3455230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PORT on 3456230557Sjimharris * entering the SCIC_SDS_PORT_READY_SUBSTATE_WAITING. This function checks the 3457230557Sjimharris * port for any ready phys. If there is at least one phy in a ready state 3458230557Sjimharris * then the port transitions to the ready operational substate. 3459230557Sjimharris * 3460230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a 3461230557Sjimharris * SCIC_SDS_PORT object. 3462230557Sjimharris * 3463230557Sjimharris * @return none 3464230557Sjimharris */ 3465230557Sjimharrisstatic 3466230557Sjimharrisvoid scic_sds_port_ready_substate_waiting_enter( 3467230557Sjimharris SCI_BASE_OBJECT_T *object 3468230557Sjimharris) 3469230557Sjimharris{ 3470230557Sjimharris SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)object; 3471230557Sjimharris 3472230557Sjimharris scic_sds_port_set_ready_state_handlers( 3473230557Sjimharris this_port, SCIC_SDS_PORT_READY_SUBSTATE_WAITING 3474230557Sjimharris ); 3475230557Sjimharris 3476230557Sjimharris scic_sds_port_suspend_port_task_scheduler(this_port); 3477230557Sjimharris 3478230557Sjimharris 3479230557Sjimharris this_port->not_ready_reason = SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS; 3480230557Sjimharris 3481230557Sjimharris if (this_port->active_phy_mask != 0) 3482230557Sjimharris { 3483230557Sjimharris // At least one of the phys on the port is ready 3484230557Sjimharris sci_base_state_machine_change_state( 3485230557Sjimharris &this_port->ready_substate_machine, 3486230557Sjimharris SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL 3487230557Sjimharris ); 3488230557Sjimharris } 3489230557Sjimharris} 3490230557Sjimharris 3491230557Sjimharris/** 3492230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PORT on 3493230557Sjimharris * exiting the SCIC_SDS_PORT_READY_SUBSTATE_WAITING. This function resume the 3494230557Sjimharris * PTSG that was suspended at the entry of this state. 3495230557Sjimharris * 3496230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a 3497230557Sjimharris * SCIC_SDS_PORT object. 3498230557Sjimharris * 3499230557Sjimharris * @return none 3500230557Sjimharris */ 3501230557Sjimharrisstatic 3502230557Sjimharrisvoid scic_sds_port_ready_substate_waiting_exit( 3503230557Sjimharris SCI_BASE_OBJECT_T *object 3504230557Sjimharris) 3505230557Sjimharris{ 3506230557Sjimharris SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)object; 3507230557Sjimharris scic_sds_port_resume_port_task_scheduler(this_port); 3508230557Sjimharris} 3509230557Sjimharris 3510230557Sjimharris/** 3511230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PORT on 3512230557Sjimharris * entering the SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL. This function sets 3513230557Sjimharris * the state handlers for the port object, notifies the SCI User that the port 3514230557Sjimharris * is ready, and resumes port operations. 3515230557Sjimharris * 3516230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a 3517230557Sjimharris * SCIC_SDS_PORT object. 3518230557Sjimharris * 3519230557Sjimharris * @return none 3520230557Sjimharris */ 3521230557Sjimharrisstatic 3522230557Sjimharrisvoid scic_sds_port_ready_substate_operational_enter( 3523230557Sjimharris SCI_BASE_OBJECT_T *object 3524230557Sjimharris) 3525230557Sjimharris{ 3526230557Sjimharris U32 index; 3527230557Sjimharris SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)object; 3528230557Sjimharris 3529230557Sjimharris scic_sds_port_set_ready_state_handlers( 3530230557Sjimharris this_port, SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL 3531230557Sjimharris ); 3532230557Sjimharris 3533230557Sjimharris scic_cb_port_ready( 3534230557Sjimharris scic_sds_port_get_controller(this_port), this_port 3535230557Sjimharris ); 3536230557Sjimharris 3537230557Sjimharris for (index = 0; index < SCI_MAX_PHYS; index++) 3538230557Sjimharris { 3539230557Sjimharris if (this_port->phy_table[index] != NULL) 3540230557Sjimharris { 3541230557Sjimharris scic_sds_port_write_phy_assignment( 3542230557Sjimharris this_port, this_port->phy_table[index] 3543230557Sjimharris ); 3544230557Sjimharris 3545230557Sjimharris //if the bit at the index location for active phy mask is set and 3546230557Sjimharris //enabled_phy_mask is not set then resume the phy 3547230557Sjimharris if ( ( (this_port->active_phy_mask ^ this_port->enabled_phy_mask) & (1 << index) ) != 0) 3548230557Sjimharris { 3549230557Sjimharris scic_sds_port_resume_phy ( 3550230557Sjimharris this_port, 3551230557Sjimharris this_port->phy_table[index] 3552230557Sjimharris ); 3553230557Sjimharris } 3554230557Sjimharris } 3555230557Sjimharris } 3556230557Sjimharris 3557230557Sjimharris scic_sds_port_update_viit_entry(this_port); 3558230557Sjimharris 3559230557Sjimharris // Post the dummy task for the port so the hardware can schedule 3560230557Sjimharris // io correctly 3561230557Sjimharris scic_sds_port_post_dummy_request(this_port); 3562230557Sjimharris} 3563230557Sjimharris 3564230557Sjimharris/** 3565230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PORT on 3566230557Sjimharris * exiting the SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL. This function reports 3567230557Sjimharris * the port not ready and suspends the port task scheduler. 3568230557Sjimharris * 3569230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a 3570230557Sjimharris * SCIC_SDS_PORT object. 3571230557Sjimharris * 3572230557Sjimharris * @return none 3573230557Sjimharris */ 3574230557Sjimharrisstatic 3575230557Sjimharrisvoid scic_sds_port_ready_substate_operational_exit( 3576230557Sjimharris SCI_BASE_OBJECT_T *object 3577230557Sjimharris) 3578230557Sjimharris{ 3579230557Sjimharris SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)object; 3580230557Sjimharris 3581230557Sjimharris // Kill the dummy task for this port if it has not yet posted 3582230557Sjimharris // the hardware will treat this as a NOP and just return abort 3583230557Sjimharris // complete. 3584230557Sjimharris scic_sds_port_abort_dummy_request(this_port); 3585230557Sjimharris 3586230557Sjimharris scic_cb_port_not_ready( 3587230557Sjimharris scic_sds_port_get_controller(this_port), 3588230557Sjimharris this_port, 3589230557Sjimharris this_port->not_ready_reason 3590230557Sjimharris ); 3591230557Sjimharris} 3592230557Sjimharris 3593230557Sjimharris//****************************************************************************** 3594230557Sjimharris//* PORT READY CONFIGURING METHODS 3595230557Sjimharris//****************************************************************************** 3596230557Sjimharris 3597230557Sjimharris/** 3598230557Sjimharris * This method will perform the actions required by the SCIC_SDS_PORT on 3599230557Sjimharris * exiting the SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL. This function reports 3600230557Sjimharris * the port not ready and suspends the port task scheduler. 3601230557Sjimharris * 3602230557Sjimharris * @param[in] object This is the SCI_BASE_OBJECT which is cast to a 3603230557Sjimharris * SCIC_SDS_PORT object. 3604230557Sjimharris * 3605230557Sjimharris * @return none 3606230557Sjimharris */ 3607230557Sjimharrisstatic 3608230557Sjimharrisvoid scic_sds_port_ready_substate_configuring_enter( 3609230557Sjimharris SCI_BASE_OBJECT_T *object 3610230557Sjimharris) 3611230557Sjimharris{ 3612230557Sjimharris SCIC_SDS_PORT_T *this_port = (SCIC_SDS_PORT_T *)object; 3613230557Sjimharris 3614230557Sjimharris scic_sds_port_set_ready_state_handlers( 3615230557Sjimharris this_port, SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING 3616230557Sjimharris ); 3617230557Sjimharris 3618230557Sjimharris if (this_port->active_phy_mask == 0) 3619230557Sjimharris { 3620230557Sjimharris scic_cb_port_not_ready( 3621230557Sjimharris scic_sds_port_get_controller(this_port), 3622230557Sjimharris this_port, 3623230557Sjimharris SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS 3624230557Sjimharris ); 3625230557Sjimharris 3626230557Sjimharris sci_base_state_machine_change_state( 3627230557Sjimharris &this_port->ready_substate_machine, 3628230557Sjimharris SCIC_SDS_PORT_READY_SUBSTATE_WAITING 3629230557Sjimharris ); 3630230557Sjimharris } 3631230557Sjimharris //do not wait for IO to go to 0 in this state. 3632230557Sjimharris else 3633230557Sjimharris { 3634230557Sjimharris sci_base_state_machine_change_state( 3635230557Sjimharris &this_port->ready_substate_machine, 3636230557Sjimharris SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL 3637230557Sjimharris ); 3638230557Sjimharris } 3639230557Sjimharris} 3640230557Sjimharris 3641230557Sjimharris// --------------------------------------------------------------------------- 3642230557Sjimharris 3643230557SjimharrisSCI_BASE_STATE_T 3644230557Sjimharris scic_sds_port_ready_substate_table[SCIC_SDS_PORT_READY_MAX_SUBSTATES] = 3645230557Sjimharris{ 3646230557Sjimharris { 3647230557Sjimharris SCIC_SDS_PORT_READY_SUBSTATE_WAITING, 3648230557Sjimharris scic_sds_port_ready_substate_waiting_enter, 3649230557Sjimharris scic_sds_port_ready_substate_waiting_exit 3650230557Sjimharris }, 3651230557Sjimharris { 3652230557Sjimharris SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL, 3653230557Sjimharris scic_sds_port_ready_substate_operational_enter, 3654230557Sjimharris scic_sds_port_ready_substate_operational_exit 3655230557Sjimharris }, 3656230557Sjimharris { 3657230557Sjimharris SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING, 3658230557Sjimharris scic_sds_port_ready_substate_configuring_enter, 3659230557Sjimharris NULL 3660230557Sjimharris } 3661230557Sjimharris}; 3662230557Sjimharris 3663