static enum sci_status
sci_apc_agent_validate_phy_configuration(struct isci_host *ihost,
					      struct sci_port_configuration_agent *port_agent)
{
	u8 phy_index;
	u8 port_index;
	struct sci_sas_address sas_address;
	struct sci_sas_address phy_assigned_address;

	phy_index = 0;

	while (phy_index < SCI_MAX_PHYS) {
		port_index = phy_index;

		
		sci_phy_get_sas_address(&ihost->phys[phy_index],
					    &sas_address);

		while (++phy_index < SCI_MAX_PHYS) {
			sci_phy_get_sas_address(&ihost->phys[phy_index],
						     &phy_assigned_address);

			
			if (sci_sas_address_compare(sas_address, phy_assigned_address) == 0) {
				port_agent->phy_valid_port_range[phy_index].min_index = port_index;
				port_agent->phy_valid_port_range[phy_index].max_index = phy_index;
			} else {
				port_agent->phy_valid_port_range[phy_index].min_index = phy_index;
				port_agent->phy_valid_port_range[phy_index].max_index = phy_index;
				break;
			}
		}
	}

	return sci_port_configuration_agent_validate_ports(ihost, port_agent);
}
/* verify phys are assigned a valid SAS address for automatic port
 * configuration mode.
 */
static enum sci_status
sci_apc_agent_validate_phy_configuration(struct isci_host *ihost,
					      struct sci_port_configuration_agent *port_agent)
{
	u8 phy_index;
	u8 port_index;
	struct sci_sas_address sas_address;
	struct sci_sas_address phy_assigned_address;

	phy_index = 0;

	while (phy_index < SCI_MAX_PHYS) {
		port_index = phy_index;

		/* Get the assigned SAS Address for the first PHY on the controller. */
		sci_phy_get_sas_address(&ihost->phys[phy_index],
					    &sas_address);

		while (++phy_index < SCI_MAX_PHYS) {
			sci_phy_get_sas_address(&ihost->phys[phy_index],
						     &phy_assigned_address);

			/* Verify each of the SAS address are all the same for every PHY */
			if (sci_sas_address_compare(sas_address, phy_assigned_address) == 0) {
				port_agent->phy_valid_port_range[phy_index].min_index = port_index;
				port_agent->phy_valid_port_range[phy_index].max_index = phy_index;
			} else {
				port_agent->phy_valid_port_range[phy_index].min_index = phy_index;
				port_agent->phy_valid_port_range[phy_index].max_index = phy_index;
				break;
			}
		}
	}

	return sci_port_configuration_agent_validate_ports(ihost, port_agent);
}
static enum sci_status
sci_mpc_agent_validate_phy_configuration(struct isci_host *ihost,
					      struct sci_port_configuration_agent *port_agent)
{
	u32 phy_mask;
	u32 assigned_phy_mask;
	struct sci_sas_address sas_address;
	struct sci_sas_address phy_assigned_address;
	u8 port_index;
	u8 phy_index;

	assigned_phy_mask = 0;
	sas_address.high = 0;
	sas_address.low = 0;

	for (port_index = 0; port_index < SCI_MAX_PORTS; port_index++) {
		phy_mask = ihost->oem_parameters.ports[port_index].phy_mask;

		if (!phy_mask)
			continue;
		if ((phy_mask & ~assigned_phy_mask) == 0) {
			return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
		}

		
		for (phy_index = 0; phy_index < SCI_MAX_PHYS; phy_index++) {
			if ((phy_mask & (1 << phy_index)) == 0)
				continue;
			sci_phy_get_sas_address(&ihost->phys[phy_index],
						     &sas_address);

			port_agent->phy_valid_port_range[phy_index].min_index = port_index;
			port_agent->phy_valid_port_range[phy_index].max_index = phy_index;

			if (phy_index != port_index) {
				return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
			}

			break;
		}

		while (phy_index < SCI_MAX_PHYS) {
			if ((phy_mask & (1 << phy_index)) == 0)
				continue;
			sci_phy_get_sas_address(&ihost->phys[phy_index],
						     &phy_assigned_address);

			if (sci_sas_address_compare(sas_address, phy_assigned_address) != 0) {
				return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
			}

			port_agent->phy_valid_port_range[phy_index].min_index = port_index;
			port_agent->phy_valid_port_range[phy_index].max_index = phy_index;

			sci_port_add_phy(&ihost->ports[port_index],
					      &ihost->phys[phy_index]);

			assigned_phy_mask |= (1 << phy_index);
		}

		phy_index++;
	}

	return sci_port_configuration_agent_validate_ports(ihost, port_agent);
}
/* verify all of the phys in the same port are using the same SAS address */
static enum sci_status
sci_mpc_agent_validate_phy_configuration(struct isci_host *ihost,
					      struct sci_port_configuration_agent *port_agent)
{
	u32 phy_mask;
	u32 assigned_phy_mask;
	struct sci_sas_address sas_address;
	struct sci_sas_address phy_assigned_address;
	u8 port_index;
	u8 phy_index;

	assigned_phy_mask = 0;
	sas_address.high = 0;
	sas_address.low = 0;

	for (port_index = 0; port_index < SCI_MAX_PORTS; port_index++) {
		phy_mask = ihost->oem_parameters.ports[port_index].phy_mask;

		if (!phy_mask)
			continue;
		/*
		 * Make sure that one or more of the phys were not already assinged to
		 * a different port. */
		if ((phy_mask & ~assigned_phy_mask) == 0) {
			return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
		}

		/* Find the starting phy index for this round through the loop */
		for (phy_index = 0; phy_index < SCI_MAX_PHYS; phy_index++) {
			if ((phy_mask & (1 << phy_index)) == 0)
				continue;
			sci_phy_get_sas_address(&ihost->phys[phy_index],
						     &sas_address);

			/*
			 * The phy_index can be used as the starting point for the
			 * port range since the hardware starts all logical ports
			 * the same as the PE index. */
			port_agent->phy_valid_port_range[phy_index].min_index = port_index;
			port_agent->phy_valid_port_range[phy_index].max_index = phy_index;

			if (phy_index != port_index) {
				return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
			}

			break;
		}

		/*
		 * See how many additional phys are being added to this logical port.
		 * Note: We have not moved the current phy_index so we will actually
		 *       compare the startting phy with itself.
		 *       This is expected and required to add the phy to the port. */
		while (phy_index < SCI_MAX_PHYS) {
			if ((phy_mask & (1 << phy_index)) == 0)
				continue;
			sci_phy_get_sas_address(&ihost->phys[phy_index],
						     &phy_assigned_address);

			if (sci_sas_address_compare(sas_address, phy_assigned_address) != 0) {
				/*
				 * The phy mask specified that this phy is part of the same port
				 * as the starting phy and it is not so fail this configuration */
				return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
			}

			port_agent->phy_valid_port_range[phy_index].min_index = port_index;
			port_agent->phy_valid_port_range[phy_index].max_index = phy_index;

			sci_port_add_phy(&ihost->ports[port_index],
					      &ihost->phys[phy_index]);

			assigned_phy_mask |= (1 << phy_index);
		}

		phy_index++;
	}

	return sci_port_configuration_agent_validate_ports(ihost, port_agent);
}