static void
e1000_phy_disable_receiver(struct e1000_adapter *adapter)
{
	/* Write out to PHY registers 29 and 30 to disable the Receiver. */
	e1000_write_phy_reg(&adapter->hw, 29, 0x001F);
	e1000_write_phy_reg(&adapter->hw, 30, 0x8FFC);
	e1000_write_phy_reg(&adapter->hw, 29, 0x001A);
	e1000_write_phy_reg(&adapter->hw, 30, 0x8FF0);
}
static int
e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
{
	uint32_t ctrl_reg = 0;
	uint32_t stat_reg = 0;

	adapter->hw.autoneg = FALSE;

	if(adapter->hw.phy_type == e1000_phy_m88) {
		/* Auto-MDI/MDIX Off */
		e1000_write_phy_reg(&adapter->hw,
				    M88E1000_PHY_SPEC_CTRL, 0x0808);
		/* reset to update Auto-MDI/MDIX */
		e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x9140);
		/* autoneg off */
		e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x8140);
	}
	/* force 1000, set loopback */
	e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x4140);

	/* Now set up the MAC to the same speed/duplex as the PHY. */
	ctrl_reg = E1000_READ_REG(&adapter->hw, CTRL);
	ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */
	ctrl_reg |= (E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */
		     E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */
		     E1000_CTRL_SPD_1000 |/* Force Speed to 1000 */
		     E1000_CTRL_FD);	 /* Force Duplex to FULL */

	if(adapter->hw.media_type == e1000_media_type_copper &&
	   adapter->hw.phy_type == e1000_phy_m88) {
		ctrl_reg |= E1000_CTRL_ILOS; /* Invert Loss of Signal */
	} else {
		/* Set the ILOS bit on the fiber Nic is half
		 * duplex link is detected. */
		stat_reg = E1000_READ_REG(&adapter->hw, STATUS);
		if((stat_reg & E1000_STATUS_FD) == 0)
			ctrl_reg |= (E1000_CTRL_ILOS | E1000_CTRL_SLU);
	}

	E1000_WRITE_REG(&adapter->hw, CTRL, ctrl_reg);

	/* Disable the receiver on the PHY so when a cable is plugged in, the
	 * PHY does not begin to autoneg when a cable is reconnected to the NIC.
	 */
	if(adapter->hw.phy_type == e1000_phy_m88)
		e1000_phy_disable_receiver(adapter);

	udelay(500);

	return 0;
}
static void
e1000_loopback_cleanup(struct e1000_adapter *adapter)
{
	uint32_t rctl;
	uint16_t phy_reg;

	rctl = E1000_READ_REG(&adapter->hw, RCTL);
	rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC);
	E1000_WRITE_REG(&adapter->hw, RCTL, rctl);

	if(adapter->hw.media_type == e1000_media_type_copper ||
	   ((adapter->hw.media_type == e1000_media_type_fiber ||
	     adapter->hw.media_type == e1000_media_type_internal_serdes) &&
	    (adapter->hw.mac_type == e1000_82545 ||
	     adapter->hw.mac_type == e1000_82546 ||
	     adapter->hw.mac_type == e1000_82545_rev_3 ||
	     adapter->hw.mac_type == e1000_82546_rev_3))) {
		adapter->hw.autoneg = TRUE;
		e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg);
		if(phy_reg & MII_CR_LOOPBACK) {
			phy_reg &= ~MII_CR_LOOPBACK;
			e1000_write_phy_reg(&adapter->hw, PHY_CTRL, phy_reg);
			e1000_phy_reset(&adapter->hw);
		}
	}
}
static void
e1000_phy_reset_clk_and_crs(struct e1000_adapter *adapter)
{
	uint16_t phy_reg;

	/* Because we reset the PHY above, we need to re-force TX_CLK in the
	 * Extended PHY Specific Control Register to 25MHz clock.  This
	 * value defaults back to a 2.5MHz clock when the PHY is reset.
	 */
	e1000_read_phy_reg(&adapter->hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_reg);
	phy_reg |= M88E1000_EPSCR_TX_CLK_25;
	e1000_write_phy_reg(&adapter->hw,
		M88E1000_EXT_PHY_SPEC_CTRL, phy_reg);

	/* In addition, because of the s/w reset above, we need to enable
	 * CRS on TX.  This must be set for both full and half duplex
	 * operation.
	 */
	e1000_read_phy_reg(&adapter->hw, M88E1000_PHY_SPEC_CTRL, &phy_reg);
	phy_reg |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
	e1000_write_phy_reg(&adapter->hw,
		M88E1000_PHY_SPEC_CTRL, phy_reg);
}
static int
e1000_set_phy_loopback(struct e1000_adapter *adapter)
{
	uint16_t phy_reg = 0;
	uint16_t count = 0;

	switch (adapter->hw.mac_type) {
	case e1000_82543:
		if(adapter->hw.media_type == e1000_media_type_copper) {
			/* Attempt to setup Loopback mode on Non-integrated PHY.
			 * Some PHY registers get corrupted at random, so
			 * attempt this 10 times.
			 */
			while(e1000_nonintegrated_phy_loopback(adapter) &&
			      count++ < 10);
			if(count < 11)
				return 0;
		}
		break;

	case e1000_82544:
	case e1000_82540:
	case e1000_82545:
	case e1000_82545_rev_3:
	case e1000_82546:
	case e1000_82546_rev_3:
	case e1000_82541:
	case e1000_82541_rev_2:
	case e1000_82547:
	case e1000_82547_rev_2:
		return e1000_integrated_phy_loopback(adapter);
		break;

	default:
		/* Default PHY loopback work is to read the MII
		 * control register and assert bit 14 (loopback mode).
		 */
		e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg);
		phy_reg |= MII_CR_LOOPBACK;
		e1000_write_phy_reg(&adapter->hw, PHY_CTRL, phy_reg);
		return 0;
		break;
	}

	return 8;
}
Beispiel #6
0
/*
 * phy_spd_state - set smart-power-down (SPD) state
 *
 * This only acts on the silicon families that have the SPD feature.
 * For any others, return without doing anything.
 */
void
phy_spd_state(struct e1000_hw *hw, boolean_t enable)
{
	int32_t offset;		/* offset to register */
	uint16_t spd_bit;	/* bit to be set */
	uint16_t reg;		/* register contents */

	switch (hw->mac.type) {
	case e1000_82541:
	case e1000_82547:
	case e1000_82541_rev_2:
	case e1000_82547_rev_2:
		offset = IGP01E1000_GMII_FIFO;
		spd_bit = IGP01E1000_GMII_SPD;
		break;
	case e1000_82571:
	case e1000_82572:
	case e1000_82573:
	case e1000_82574:
	case e1000_82583:
		offset = IGP02E1000_PHY_POWER_MGMT;
		spd_bit = IGP02E1000_PM_SPD;
		break;
	default:
		return;		/* no action */
	}

	(void) e1000_read_phy_reg(hw, offset, &reg);

	if (enable)
		reg |= spd_bit;		/* enable: set the spd bit */
	else
		reg &= ~spd_bit;	/* disable: clear the spd bit */

	(void) e1000_write_phy_reg(hw, offset, reg);
}
/*
 * e1000g_rx_setup - setup rx data structures
 *
 * This routine initializes all of the receive related
 * structures. This includes the receive descriptors, the
 * actual receive buffers, and the rx_sw_packet software
 * structures.
 */
void
e1000g_rx_setup(struct e1000g *Adapter)
{
	struct e1000_hw *hw;
	p_rx_sw_packet_t packet;
	struct e1000_rx_desc *descriptor;
	uint32_t buf_low;
	uint32_t buf_high;
	uint32_t reg_val;
	uint32_t rctl;
	uint32_t rxdctl;
	uint32_t ert;
	uint16_t phy_data;
	int i;
	int size;
	e1000g_rx_data_t *rx_data;

	hw = &Adapter->shared;
	rx_data = Adapter->rx_ring->rx_data;

	/*
	 * zero out all of the receive buffer descriptor memory
	 * assures any previous data or status is erased
	 */
	bzero(rx_data->rbd_area,
	    sizeof (struct e1000_rx_desc) * Adapter->rx_desc_num);

	if (!Adapter->rx_buffer_setup) {
		/* Init the list of "Receive Buffer" */
		QUEUE_INIT_LIST(&rx_data->recv_list);

		/* Init the list of "Free Receive Buffer" */
		QUEUE_INIT_LIST(&rx_data->free_list);

		/* Init the list of "Free Receive Buffer" */
		QUEUE_INIT_LIST(&rx_data->recycle_list);
		/*
		 * Setup Receive list and the Free list. Note that
		 * the both were allocated in one packet area.
		 */
		packet = rx_data->packet_area;
		descriptor = rx_data->rbd_first;

		for (i = 0; i < Adapter->rx_desc_num;
		    i++, packet = packet->next, descriptor++) {
			ASSERT(packet != NULL);
			ASSERT(descriptor != NULL);
			descriptor->buffer_addr =
			    packet->rx_buf->dma_address;

			/* Add this rx_sw_packet to the receive list */
			QUEUE_PUSH_TAIL(&rx_data->recv_list,
			    &packet->Link);
		}

		for (i = 0; i < Adapter->rx_freelist_num;
		    i++, packet = packet->next) {
			ASSERT(packet != NULL);
			/* Add this rx_sw_packet to the free list */
			QUEUE_PUSH_TAIL(&rx_data->free_list,
			    &packet->Link);
		}
		rx_data->avail_freepkt = Adapter->rx_freelist_num;
		rx_data->recycle_freepkt = 0;

		Adapter->rx_buffer_setup = B_TRUE;
	} else {
		/* Setup the initial pointer to the first rx descriptor */
		packet = (p_rx_sw_packet_t)
		    QUEUE_GET_HEAD(&rx_data->recv_list);
		descriptor = rx_data->rbd_first;

		for (i = 0; i < Adapter->rx_desc_num; i++) {
			ASSERT(packet != NULL);
			ASSERT(descriptor != NULL);
			descriptor->buffer_addr =
			    packet->rx_buf->dma_address;

			/* Get next rx_sw_packet */
			packet = (p_rx_sw_packet_t)
			    QUEUE_GET_NEXT(&rx_data->recv_list, &packet->Link);
			descriptor++;
		}
	}

	E1000_WRITE_REG(&Adapter->shared, E1000_RDTR, Adapter->rx_intr_delay);
	E1000G_DEBUGLOG_1(Adapter, E1000G_INFO_LEVEL,
	    "E1000_RDTR: 0x%x\n", Adapter->rx_intr_delay);
	if (hw->mac.type >= e1000_82540) {
		E1000_WRITE_REG(&Adapter->shared, E1000_RADV,
		    Adapter->rx_intr_abs_delay);
		E1000G_DEBUGLOG_1(Adapter, E1000G_INFO_LEVEL,
		    "E1000_RADV: 0x%x\n", Adapter->rx_intr_abs_delay);
	}

	/*
	 * Setup our descriptor pointers
	 */
	rx_data->rbd_next = rx_data->rbd_first;

	size = Adapter->rx_desc_num * sizeof (struct e1000_rx_desc);
	E1000_WRITE_REG(hw, E1000_RDLEN(0), size);
	size = E1000_READ_REG(hw, E1000_RDLEN(0));

	/* To get lower order bits */
	buf_low = (uint32_t)rx_data->rbd_dma_addr;
	/* To get the higher order bits */
	buf_high = (uint32_t)(rx_data->rbd_dma_addr >> 32);

	E1000_WRITE_REG(hw, E1000_RDBAH(0), buf_high);
	E1000_WRITE_REG(hw, E1000_RDBAL(0), buf_low);

	/*
	 * Setup our HW Rx Head & Tail descriptor pointers
	 */
	E1000_WRITE_REG(hw, E1000_RDT(0),
	    (uint32_t)(rx_data->rbd_last - rx_data->rbd_first));
	E1000_WRITE_REG(hw, E1000_RDH(0), 0);

	/*
	 * Setup the Receive Control Register (RCTL), and ENABLE the
	 * receiver. The initial configuration is to: Enable the receiver,
	 * accept broadcasts, discard bad packets (and long packets),
	 * disable VLAN filter checking, set the receive descriptor
	 * minimum threshold size to 1/2, and the receive buffer size to
	 * 2k.
	 */
	rctl = E1000_RCTL_EN |		/* Enable Receive Unit */
	    E1000_RCTL_BAM |		/* Accept Broadcast Packets */
	    E1000_RCTL_LPE |		/* Large Packet Enable bit */
	    (hw->mac.mc_filter_type << E1000_RCTL_MO_SHIFT) |
	    E1000_RCTL_RDMTS_HALF |
	    E1000_RCTL_LBM_NO;		/* Loopback Mode = none */

	if (Adapter->strip_crc)
		rctl |= E1000_RCTL_SECRC;	/* Strip Ethernet CRC */

	if (Adapter->mem_workaround_82546 &&
	    ((hw->mac.type == e1000_82545) ||
	    (hw->mac.type == e1000_82546) ||
	    (hw->mac.type == e1000_82546_rev_3))) {
		rctl |= E1000_RCTL_SZ_2048;
	} else {
		if ((Adapter->max_frame_size > FRAME_SIZE_UPTO_2K) &&
		    (Adapter->max_frame_size <= FRAME_SIZE_UPTO_4K))
			rctl |= E1000_RCTL_SZ_4096 | E1000_RCTL_BSEX;
		else if ((Adapter->max_frame_size > FRAME_SIZE_UPTO_4K) &&
		    (Adapter->max_frame_size <= FRAME_SIZE_UPTO_8K))
			rctl |= E1000_RCTL_SZ_8192 | E1000_RCTL_BSEX;
		else if ((Adapter->max_frame_size > FRAME_SIZE_UPTO_8K) &&
		    (Adapter->max_frame_size <= FRAME_SIZE_UPTO_16K))
			rctl |= E1000_RCTL_SZ_16384 | E1000_RCTL_BSEX;
		else
			rctl |= E1000_RCTL_SZ_2048;
	}

	if (e1000_tbi_sbp_enabled_82543(hw))
		rctl |= E1000_RCTL_SBP;

	/*
	 * Enable Early Receive Threshold (ERT) on supported devices.
	 * Only takes effect when packet size is equal or larger than the
	 * specified value (in 8 byte units), e.g. using jumbo frames.
	 */
	if ((hw->mac.type == e1000_82573) ||
	    (hw->mac.type == e1000_82574) ||
	    (hw->mac.type == e1000_ich9lan) ||
	    (hw->mac.type == e1000_ich10lan)) {

		ert = E1000_ERT_2048;

		/*
		 * Special modification when ERT and
		 * jumbo frames are enabled
		 */
		if (Adapter->default_mtu > ETHERMTU) {
			rxdctl = E1000_READ_REG(hw, E1000_RXDCTL(0));
			E1000_WRITE_REG(hw, E1000_RXDCTL(0), rxdctl | 0x3);
			ert |= (1 << 13);
		}

		E1000_WRITE_REG(hw, E1000_ERT, ert);
	}

	/* Workaround errata on 82577/8 adapters with large frames */
	if ((hw->mac.type == e1000_pchlan) &&
	    (Adapter->default_mtu > ETHERMTU)) {

		(void) e1000_read_phy_reg(hw, PHY_REG(770, 26), &phy_data);
		phy_data &= 0xfff8;
		phy_data |= (1 << 2);
		(void) e1000_write_phy_reg(hw, PHY_REG(770, 26), phy_data);

		if (hw->phy.type == e1000_phy_82577) {
			(void) e1000_read_phy_reg(hw, 22, &phy_data);
			phy_data &= 0x0fff;
			phy_data |= (1 << 14);
			(void) e1000_write_phy_reg(hw, 0x10, 0x2823);
			(void) e1000_write_phy_reg(hw, 0x11, 0x0003);
			(void) e1000_write_phy_reg(hw, 22, phy_data);
		}
	}

	reg_val =
	    E1000_RXCSUM_TUOFL |	/* TCP/UDP checksum offload Enable */
	    E1000_RXCSUM_IPOFL;		/* IP checksum offload Enable */

	E1000_WRITE_REG(hw, E1000_RXCSUM, reg_val);

	/*
	 * Workaround: Set bit 16 (IPv6_ExDIS) to disable the
	 * processing of received IPV6 extension headers
	 */
	if ((hw->mac.type == e1000_82571) || (hw->mac.type == e1000_82572)) {
		reg_val = E1000_READ_REG(hw, E1000_RFCTL);
		reg_val |= (E1000_RFCTL_IPV6_EX_DIS |
		    E1000_RFCTL_NEW_IPV6_EXT_DIS);
		E1000_WRITE_REG(hw, E1000_RFCTL, reg_val);
	}

	/* Write to enable the receive unit */
	E1000_WRITE_REG(hw, E1000_RCTL, rctl);
}
Beispiel #8
0
/**
 * e1000_reset - Put e1000 NIC in known initial state
 *
 * @v adapter	e1000 private structure
 **/
static void
e1000_reset ( struct e1000_adapter *adapter )
{
	uint32_t pba = 0;
	uint16_t fc_high_water_mark = E1000_FC_HIGH_DIFF;

	DBG ( "e1000_reset\n" );

	switch (adapter->hw.mac_type) {
	case e1000_82542_rev2_0:
	case e1000_82542_rev2_1:
	case e1000_82543:
	case e1000_82544:
	case e1000_82540:
	case e1000_82541:
	case e1000_82541_rev_2:
		pba = E1000_PBA_48K;
		break;
	case e1000_82545:
	case e1000_82545_rev_3:
	case e1000_82546:
	case e1000_82546_rev_3:
		pba = E1000_PBA_48K;
		break;
	case e1000_82547:
	case e1000_82547_rev_2:
		pba = E1000_PBA_30K;
		break;
	case e1000_82571:
	case e1000_82572:
	case e1000_80003es2lan:
		pba = E1000_PBA_38K;
		break;
	case e1000_82573:
		pba = E1000_PBA_20K;
		break;
	case e1000_82576:
		pba = E1000_PBA_64K;
		break;
	case e1000_ich8lan:
		pba = E1000_PBA_8K;
	case e1000_undefined:
	case e1000_num_macs:
		break;
	}

	E1000_WRITE_REG ( &adapter->hw, PBA, pba );
	
	/* flow control settings */
	/* Set the FC high water mark to 90% of the FIFO size.
	 * Required to clear last 3 LSB */
	fc_high_water_mark = ((pba * 9216)/10) & 0xFFF8;

	/* We can't use 90% on small FIFOs because the remainder
	 * would be less than 1 full frame.  In this case, we size
	 * it to allow at least a full frame above the high water
	 *  mark. */
	if (pba < E1000_PBA_16K)
		fc_high_water_mark = (pba * 1024) - 1600;

	/* This actually applies to < e1000_82575, one revision less than
	 * e1000_82576, but e1000_82575 isn't currently defined in the code */
	if (adapter->hw.mac_type < e1000_82576) {
		/* 8-byte granularity */
		adapter->hw.fc_high_water = fc_high_water_mark & 0xFFF8;
		adapter->hw.fc_low_water = adapter->hw.fc_high_water - 8;
	} else {
		/* 16-byte granularity */
		adapter->hw.fc_high_water = fc_high_water_mark & 0xFFF0;
		adapter->hw.fc_low_water = adapter->hw.fc_high_water - 16;
	}

	if (adapter->hw.mac_type == e1000_80003es2lan ||
	    adapter->hw.mac_type == e1000_82576)
		adapter->hw.fc_pause_time = 0xFFFF;
	else
		adapter->hw.fc_pause_time = E1000_FC_PAUSE_TIME;
	adapter->hw.fc_send_xon = 1;
	adapter->hw.fc = adapter->hw.original_fc;
	/* Allow time for pending master requests to run */

	e1000_reset_hw ( &adapter->hw );

	if ( adapter->hw.mac_type >= e1000_82544 )
		E1000_WRITE_REG ( &adapter->hw, WUC, 0 );

	if ( e1000_init_hw ( &adapter->hw ) )
		DBG ( "Hardware Error\n" );

	/* if (adapter->hwflags & HWFLAGS_PHY_PWR_BIT) { */
	if (adapter->hw.mac_type >= e1000_82544 &&
	    adapter->hw.mac_type <= e1000_82547_rev_2 &&
	    adapter->hw.autoneg == 1 &&
	    adapter->hw.autoneg_advertised == ADVERTISE_1000_FULL) {
		uint32_t ctrl = E1000_READ_REG(&adapter->hw, CTRL);
		/* clear phy power management bit if we are in gig only mode,
		 * which if enabled will attempt negotiation to 100Mb, which
		 * can cause a loss of link at power off or driver unload */
		ctrl &= ~E1000_CTRL_SWDPIN3;
		E1000_WRITE_REG(&adapter->hw, CTRL, ctrl);
	}

	e1000_phy_get_info ( &adapter->hw, &adapter->phy_info );

	if (!adapter->smart_power_down &&
	    (adapter->hw.mac_type == e1000_82571 ||
	     adapter->hw.mac_type == e1000_82572)) {
		uint16_t phy_data = 0;
		/* speed up time to link by disabling smart power down, ignore
		 * the return value of this function because there is nothing
		 * different we would do if it failed */
		e1000_read_phy_reg(&adapter->hw, IGP02E1000_PHY_POWER_MGMT,
		                   &phy_data);
		phy_data &= ~IGP02E1000_PM_SPD;
		e1000_write_phy_reg(&adapter->hw, IGP02E1000_PHY_POWER_MGMT,
		                    phy_data);
	}
}
static void
e1000_get_regs(struct net_device *netdev,
	       struct ethtool_regs *regs, void *p)
{
	struct e1000_adapter *adapter = netdev->priv;
	struct e1000_hw *hw = &adapter->hw;
	uint32_t *regs_buff = p;
	uint16_t phy_data;

	memset(p, 0, E1000_REGS_LEN * sizeof(uint32_t));

	regs->version = (1 << 24) | (hw->revision_id << 16) | hw->device_id;

	regs_buff[0]  = E1000_READ_REG(hw, CTRL);
	regs_buff[1]  = E1000_READ_REG(hw, STATUS);

	regs_buff[2]  = E1000_READ_REG(hw, RCTL);
	regs_buff[3]  = E1000_READ_REG(hw, RDLEN);
	regs_buff[4]  = E1000_READ_REG(hw, RDH);
	regs_buff[5]  = E1000_READ_REG(hw, RDT);
	regs_buff[6]  = E1000_READ_REG(hw, RDTR);

	regs_buff[7]  = E1000_READ_REG(hw, TCTL);
	regs_buff[8]  = E1000_READ_REG(hw, TDLEN);
	regs_buff[9]  = E1000_READ_REG(hw, TDH);
	regs_buff[10] = E1000_READ_REG(hw, TDT);
	regs_buff[11] = E1000_READ_REG(hw, TIDV);

	regs_buff[12] = adapter->hw.phy_type;  /* PHY type (IGP=1, M88=0) */
	if(hw->phy_type == e1000_phy_igp) {
		e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
				    IGP01E1000_PHY_AGC_A);
		e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_A &
				   IGP01E1000_PHY_PAGE_SELECT, &phy_data);
		regs_buff[13] = (uint32_t)phy_data; /* cable length */
		e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
				    IGP01E1000_PHY_AGC_B);
		e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_B &
				   IGP01E1000_PHY_PAGE_SELECT, &phy_data);
		regs_buff[14] = (uint32_t)phy_data; /* cable length */
		e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
				    IGP01E1000_PHY_AGC_C);
		e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_C &
				   IGP01E1000_PHY_PAGE_SELECT, &phy_data);
		regs_buff[15] = (uint32_t)phy_data; /* cable length */
		e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
				    IGP01E1000_PHY_AGC_D);
		e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_D &
				   IGP01E1000_PHY_PAGE_SELECT, &phy_data);
		regs_buff[16] = (uint32_t)phy_data; /* cable length */
		regs_buff[17] = 0; /* extended 10bt distance (not needed) */
		e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0);
		e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS &
				   IGP01E1000_PHY_PAGE_SELECT, &phy_data);
		regs_buff[18] = (uint32_t)phy_data; /* cable polarity */
		e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
				    IGP01E1000_PHY_PCS_INIT_REG);
		e1000_read_phy_reg(hw, IGP01E1000_PHY_PCS_INIT_REG &
				   IGP01E1000_PHY_PAGE_SELECT, &phy_data);
		regs_buff[19] = (uint32_t)phy_data; /* cable polarity */
		regs_buff[20] = 0; /* polarity correction enabled (always) */
		regs_buff[22] = 0; /* phy receive errors (unavailable) */
		regs_buff[23] = regs_buff[18]; /* mdix mode */
		e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0);
	} else {
        	e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
		regs_buff[13] = (uint32_t)phy_data; /* cable length */
		regs_buff[14] = 0;  /* Dummy (to align w/ IGP phy reg dump) */
		regs_buff[15] = 0;  /* Dummy (to align w/ IGP phy reg dump) */
		regs_buff[16] = 0;  /* Dummy (to align w/ IGP phy reg dump) */
        	e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
		regs_buff[17] = (uint32_t)phy_data; /* extended 10bt distance */
		regs_buff[18] = regs_buff[13]; /* cable polarity */
		regs_buff[19] = 0;  /* Dummy (to align w/ IGP phy reg dump) */
		regs_buff[20] = regs_buff[17]; /* polarity correction */
		/* phy receive errors */
		regs_buff[22] = adapter->phy_stats.receive_errors;
		regs_buff[23] = regs_buff[13]; /* mdix mode */
	}
	regs_buff[21] = adapter->phy_stats.idle_errors;  /* phy idle errors */
	e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data);
	regs_buff[24] = (uint32_t)phy_data;  /* phy local receiver status */
	regs_buff[25] = regs_buff[24];  /* phy remote receiver status */
	if(hw->mac_type >= e1000_82540 &&
	   hw->media_type == e1000_media_type_copper) {
		regs_buff[26] = E1000_READ_REG(hw, MANC);
	}
}
static int
e1000_nonintegrated_phy_loopback(struct e1000_adapter *adapter)
{
	uint32_t ctrl_reg;
	uint16_t phy_reg;

	/* Setup the Device Control Register for PHY loopback test. */

	ctrl_reg = E1000_READ_REG(&adapter->hw, CTRL);
	ctrl_reg |= (E1000_CTRL_ILOS |		/* Invert Loss-Of-Signal */
		     E1000_CTRL_FRCSPD |	/* Set the Force Speed Bit */
		     E1000_CTRL_FRCDPX |	/* Set the Force Duplex Bit */
		     E1000_CTRL_SPD_1000 |	/* Force Speed to 1000 */
		     E1000_CTRL_FD);		/* Force Duplex to FULL */

	E1000_WRITE_REG(&adapter->hw, CTRL, ctrl_reg);

	/* Read the PHY Specific Control Register (0x10) */
	e1000_read_phy_reg(&adapter->hw, M88E1000_PHY_SPEC_CTRL, &phy_reg);

	/* Clear Auto-Crossover bits in PHY Specific Control Register
	 * (bits 6:5).
	 */
	phy_reg &= ~M88E1000_PSCR_AUTO_X_MODE;
	e1000_write_phy_reg(&adapter->hw, M88E1000_PHY_SPEC_CTRL, phy_reg);

	/* Perform software reset on the PHY */
	e1000_phy_reset(&adapter->hw);

	/* Have to setup TX_CLK and TX_CRS after software reset */
	e1000_phy_reset_clk_and_crs(adapter);

	e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x8100);

	/* Wait for reset to complete. */
	udelay(500);

	/* Have to setup TX_CLK and TX_CRS after software reset */
	e1000_phy_reset_clk_and_crs(adapter);

	/* Write out to PHY registers 29 and 30 to disable the Receiver. */
	e1000_phy_disable_receiver(adapter);

	/* Set the loopback bit in the PHY control register. */
	e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg);
	phy_reg |= MII_CR_LOOPBACK;
	e1000_write_phy_reg(&adapter->hw, PHY_CTRL, phy_reg);

	/* Setup TX_CLK and TX_CRS one more time. */
	e1000_phy_reset_clk_and_crs(adapter);

	/* Check Phy Configuration */
	e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg);
	if(phy_reg != 0x4100)
		 return 9;

	e1000_read_phy_reg(&adapter->hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_reg);
	if(phy_reg != 0x0070)
		return 10;

	e1000_read_phy_reg(&adapter->hw, 29, &phy_reg);
	if(phy_reg != 0x001A)
		return 11;

	return 0;
}