/** * This routine will find a matching port for the phy. This means that the * port and phy both have the same broadcast sas address and same received * sas address. * * @param[in] controller The controller object used for the port search. * @param[in] phy The phy object to match. * * @return The port address or the SCI_INVALID_HANDLE if there is no matching * port. * * @retvalue port address if the port can be found to match the phy. * @retvalue SCI_INVALID_HANDLE if there is no matching port for the phy. */ static SCIC_SDS_PORT_T * scic_sds_port_configuration_agent_find_port( SCIC_SDS_CONTROLLER_T * controller, SCIC_SDS_PHY_T * phy ) { U8 port_index; SCI_PORT_HANDLE_T port_handle; SCI_SAS_ADDRESS_T port_sas_address; SCI_SAS_ADDRESS_T port_attached_device_address; SCI_SAS_ADDRESS_T phy_sas_address; SCI_SAS_ADDRESS_T phy_attached_device_address; SCIC_LOG_TRACE(( sci_base_object_get_logger(controller), SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_PORT | SCIC_LOG_OBJECT_PHY, "scic_sds_port_confgiruation_agent_find_port(0x%08x, 0x%08x) enter\n", controller, phy )); // Since this phy can be a member of a wide port check to see if one or // more phys match the sent and received SAS address as this phy in which // case it should participate in the same port. scic_sds_phy_get_sas_address(phy, &phy_sas_address); scic_sds_phy_get_attached_sas_address(phy, &phy_attached_device_address); for (port_index = 0; port_index < SCI_MAX_PORTS; port_index++) { if (scic_controller_get_port_handle(controller, port_index, &port_handle) == SCI_SUCCESS) { SCIC_SDS_PORT_T * port = (SCIC_SDS_PORT_T *)port_handle; scic_sds_port_get_sas_address(port, &port_sas_address); scic_sds_port_get_attached_sas_address(port, &port_attached_device_address); if ( (sci_sas_address_compare(port_sas_address, phy_sas_address) == 0) && (sci_sas_address_compare(port_attached_device_address, phy_attached_device_address) == 0) ) { return port; } } } return SCI_INVALID_HANDLE; }
/** * @brief This method constructs the framework's SAS domain object. During * the construction process a linkage to the corresponding core port * object. * * @param[in] domain This parameter specifies the domain object to be * constructed. * @param[in] domain_id This parameter specifies the ID for the domain * object. * @param[in] fw_controller This parameter specifies the controller managing * the domain being constructed. * * @return none */ void scif_sas_domain_construct( SCIF_SAS_DOMAIN_T * fw_domain, U8 domain_id, SCIF_SAS_CONTROLLER_T * fw_controller ) { SCIF_LOG_TRACE(( sci_base_object_get_logger(fw_controller), SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_INITIALIZATION, "scif_sas_domain_construct(0x%x, 0x%x, 0x%x) enter\n", fw_domain, domain_id, fw_controller )); sci_base_domain_construct( &fw_domain->parent, sci_base_object_get_logger(fw_controller), scif_sas_domain_state_table ); scif_sas_domain_initialize_state_logging(fw_domain); sci_abstract_list_construct( &fw_domain->remote_device_list, &fw_controller->free_remote_device_pool ); // Retrieve the core's port object that directly corresponds to this // domain. scic_controller_get_port_handle( fw_controller->core_object, domain_id, &fw_domain->core_object ); // Set the association in the core port to this framework domain object. sci_object_set_association( (SCI_OBJECT_HANDLE_T) fw_domain->core_object, fw_domain ); sci_fast_list_init(&fw_domain->request_list); fw_domain->operation.timer = NULL; fw_domain->is_port_ready = FALSE; fw_domain->device_start_count = 0; fw_domain->controller = fw_controller; fw_domain->operation.status = SCI_SUCCESS; fw_domain->is_config_route_table_needed = FALSE; }
/** * This method handles the automatic port configuration for link up notifications. * * @param[in] controller This is the controller object that receives the * link up notification. * @param[in] phy This is the phy object which has gone link up. * @param[in] start_timer This tells the routine if it should start the timer for * any phys that might be added to a port in the future. */ static void scic_sds_apc_agent_configure_ports( SCIC_SDS_CONTROLLER_T * controller, SCIC_SDS_PORT_CONFIGURATION_AGENT_T * port_agent, SCIC_SDS_PHY_T * phy, BOOL start_timer ) { U8 port_index; SCI_STATUS status; SCIC_SDS_PORT_T * port; SCI_PORT_HANDLE_T port_handle; enum SCIC_SDS_APC_ACTIVITY apc_activity = SCIC_SDS_APC_SKIP_PHY; SCIC_LOG_TRACE(( sci_base_object_get_logger(controller), SCIC_LOG_OBJECT_CONTROLLER | SCIC_LOG_OBJECT_PORT | SCIC_LOG_OBJECT_PHY, "scic_sds_apc_agent_configure_ports(0x%08x, 0x%08x, 0x%08x, %d) enter\n", controller, port_agent, phy, start_timer )); port = scic_sds_port_configuration_agent_find_port(controller, phy); if (port != SCI_INVALID_HANDLE) { if (scic_sds_port_is_valid_phy_assignment(port, phy->phy_index)) apc_activity = SCIC_SDS_APC_ADD_PHY; else apc_activity = SCIC_SDS_APC_SKIP_PHY; } else { // There is no matching Port for this PHY so lets search through the // Ports and see if we can add the PHY to its own port or maybe start // the timer and wait to see if a wider port can be made. // // Note the break when we reach the condition of the port id == phy id for ( port_index = port_agent->phy_valid_port_range[phy->phy_index].min_index; port_index <= port_agent->phy_valid_port_range[phy->phy_index].max_index; port_index++ ) { scic_controller_get_port_handle(controller, port_index, &port_handle); port = (SCIC_SDS_PORT_T *)port_handle; // First we must make sure that this PHY can be added to this Port. if (scic_sds_port_is_valid_phy_assignment(port, phy->phy_index)) { // Port contains a PHY with a greater PHY ID than the current // PHY that has gone link up. This phy can not be part of any // port so skip it and move on. if (port->active_phy_mask > (1 << phy->phy_index)) { apc_activity = SCIC_SDS_APC_SKIP_PHY; break; } // We have reached the end of our Port list and have not found // any reason why we should not either add the PHY to the port // or wait for more phys to become active. if (port->physical_port_index == phy->phy_index) { // The Port either has no active PHYs. // Consider that if the port had any active PHYs we would have // or active PHYs with // a lower PHY Id than this PHY. if (apc_activity != SCIC_SDS_APC_START_TIMER) { apc_activity = SCIC_SDS_APC_ADD_PHY; } break; } // The current Port has no active PHYs and this PHY could be part // of this Port. Since we dont know as yet setup to start the // timer and see if there is a better configuration. if (port->active_phy_mask == 0) { apc_activity = SCIC_SDS_APC_START_TIMER; } } else if (port->active_phy_mask != 0) { // The Port has an active phy and the current Phy can not // participate in this port so skip the PHY and see if // there is a better configuration. apc_activity = SCIC_SDS_APC_SKIP_PHY; } } } // Check to see if the start timer operations should instead map to an // add phy operation. This is caused because we have been waiting to // add a phy to a port but could not becuase the automatic port // configuration engine had a choice of possible ports for the phy. // Since we have gone through a timeout we are going to restrict the // choice to the smallest possible port. if ( (start_timer == FALSE) && (apc_activity == SCIC_SDS_APC_START_TIMER) ) { apc_activity = SCIC_SDS_APC_ADD_PHY; } switch (apc_activity) { case SCIC_SDS_APC_ADD_PHY: status = scic_sds_port_add_phy(port, phy); if (status == SCI_SUCCESS) { port_agent->phy_configured_mask |= (1 << phy->phy_index); } break; case SCIC_SDS_APC_START_TIMER: scic_sds_apc_agent_start_timer( controller, port_agent, phy, SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION ); break; case SCIC_SDS_APC_SKIP_PHY: default: // do nothing the PHY can not be made part of a port at this time. break; } }