xref: /illumos-gate/usr/src/uts/common/io/nxge/nxge_mac.c (revision 321febde)
144961713Sgirish /*
244961713Sgirish  * CDDL HEADER START
344961713Sgirish  *
444961713Sgirish  * The contents of this file are subject to the terms of the
544961713Sgirish  * Common Development and Distribution License (the "License").
644961713Sgirish  * You may not use this file except in compliance with the License.
744961713Sgirish  *
844961713Sgirish  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
944961713Sgirish  * or http://www.opensolaris.org/os/licensing.
1044961713Sgirish  * See the License for the specific language governing permissions
1144961713Sgirish  * and limitations under the License.
1244961713Sgirish  *
1344961713Sgirish  * When distributing Covered Code, include this CDDL HEADER in each
1444961713Sgirish  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1544961713Sgirish  * If applicable, add the following below this CDDL HEADER, with the
1644961713Sgirish  * fields enclosed by brackets "[]" replaced with your own identifying
1744961713Sgirish  * information: Portions Copyright [yyyy] [name of copyright owner]
1844961713Sgirish  *
1944961713Sgirish  * CDDL HEADER END
2044961713Sgirish  */
2144961713Sgirish /*
2253560810Ssbehera  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
2344961713Sgirish  * Use is subject to license terms.
2444961713Sgirish  */
2544961713Sgirish 
2644961713Sgirish #pragma ident	"%Z%%M%	%I%	%E% SMI"
2744961713Sgirish 
2844961713Sgirish #include <sys/nxge/nxge_impl.h>
2944961713Sgirish #include <sys/nxge/nxge_mac.h>
3044961713Sgirish 
3198ecde52Stm #define	LINK_MONITOR_PERIOD	(1000 * 1000)
3298ecde52Stm #define	LM_WAIT_MULTIPLIER	8
3398ecde52Stm 
34*321febdeSsbehera #define	SERDES_RDY_WT_INTERVAL	50
35*321febdeSsbehera #define	MAX_SERDES_RDY_RETRIES	10
36*321febdeSsbehera 
3744961713Sgirish extern uint32_t nxge_no_link_notify;
3859ac0c16Sdavemq extern boolean_t nxge_no_msg;
3944961713Sgirish extern uint32_t nxge_lb_dbg;
4044961713Sgirish extern boolean_t nxge_jumbo_enable;
414202ea4bSsbehera extern uint32_t nxge_jumbo_mtu;
4244961713Sgirish 
4398ecde52Stm typedef enum {
4498ecde52Stm 	CHECK_LINK_RESCHEDULE,
4598ecde52Stm 	CHECK_LINK_STOP
4698ecde52Stm } check_link_state_t;
4798ecde52Stm 
4898ecde52Stm static check_link_state_t nxge_check_link_stop(nxge_t *);
4998ecde52Stm 
5044961713Sgirish /*
5144961713Sgirish  * Ethernet broadcast address definition.
5244961713Sgirish  */
5344961713Sgirish static ether_addr_st etherbroadcastaddr =
5444961713Sgirish 				{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
5559ac0c16Sdavemq /*
5659ac0c16Sdavemq  * Ethernet zero address definition.
5759ac0c16Sdavemq  */
5856d930aeSspeer static ether_addr_st etherzeroaddr =
5956d930aeSspeer 				{{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
6059ac0c16Sdavemq /*
6159ac0c16Sdavemq  * Supported chip types
6259ac0c16Sdavemq  */
632d17280bSsbehera static uint32_t nxge_supported_cl45_ids[] = {BCM8704_DEV_ID, BCM8706_DEV_ID};
6459ac0c16Sdavemq static uint32_t nxge_supported_cl22_ids[] = {BCM5464R_PHY_ID};
6559ac0c16Sdavemq 
6659ac0c16Sdavemq #define	NUM_CLAUSE_45_IDS	(sizeof (nxge_supported_cl45_ids) /	\
6759ac0c16Sdavemq 				sizeof (uint32_t))
6859ac0c16Sdavemq #define	NUM_CLAUSE_22_IDS	(sizeof (nxge_supported_cl22_ids) /	\
6959ac0c16Sdavemq 				sizeof (uint32_t))
7059ac0c16Sdavemq /*
7159ac0c16Sdavemq  * static functions
7259ac0c16Sdavemq  */
732e59129aSraghus static uint32_t nxge_get_cl45_pma_pmd_id(p_nxge_t, int);
742e59129aSraghus static uint32_t nxge_get_cl45_pcs_id(p_nxge_t, int);
752e59129aSraghus static uint32_t nxge_get_cl22_phy_id(p_nxge_t, int);
7659ac0c16Sdavemq static boolean_t nxge_is_supported_phy(uint32_t, uint8_t);
772d17280bSsbehera static boolean_t nxge_is_phy_present(p_nxge_t, int, uint32_t, uint32_t);
7859ac0c16Sdavemq static nxge_status_t nxge_n2_serdes_init(p_nxge_t);
7959ac0c16Sdavemq static nxge_status_t nxge_neptune_10G_serdes_init(p_nxge_t);
8059ac0c16Sdavemq static nxge_status_t nxge_1G_serdes_init(p_nxge_t);
8159ac0c16Sdavemq static nxge_status_t nxge_10G_link_intr_stop(p_nxge_t);
8259ac0c16Sdavemq static nxge_status_t nxge_10G_link_intr_start(p_nxge_t);
8359ac0c16Sdavemq static nxge_status_t nxge_1G_copper_link_intr_stop(p_nxge_t);
8459ac0c16Sdavemq static nxge_status_t nxge_1G_copper_link_intr_start(p_nxge_t);
8559ac0c16Sdavemq static nxge_status_t nxge_1G_fiber_link_intr_stop(p_nxge_t);
8659ac0c16Sdavemq static nxge_status_t nxge_1G_fiber_link_intr_start(p_nxge_t);
8759ac0c16Sdavemq static nxge_status_t nxge_check_mii_link(p_nxge_t);
8859ac0c16Sdavemq static nxge_status_t nxge_check_10g_link(p_nxge_t);
8959ac0c16Sdavemq static nxge_status_t nxge_10G_xcvr_init(p_nxge_t);
902d17280bSsbehera static nxge_status_t nxge_BCM8704_xcvr_init(p_nxge_t);
912d17280bSsbehera static nxge_status_t nxge_BCM8706_xcvr_init(p_nxge_t);
9259ac0c16Sdavemq static nxge_status_t nxge_1G_xcvr_init(p_nxge_t);
9359ac0c16Sdavemq static void nxge_bcm5464_link_led_off(p_nxge_t);
9459ac0c16Sdavemq 
9559ac0c16Sdavemq /*
9659ac0c16Sdavemq  * xcvr tables for supported transceivers
9759ac0c16Sdavemq  */
9859ac0c16Sdavemq 
992e59129aSraghus static nxge_xcvr_table_t nxge_n2_10G_table = {
10059ac0c16Sdavemq 	nxge_n2_serdes_init,
10159ac0c16Sdavemq 	nxge_10G_xcvr_init,
10259ac0c16Sdavemq 	nxge_10G_link_intr_stop,
10359ac0c16Sdavemq 	nxge_10G_link_intr_start,
10459ac0c16Sdavemq 	nxge_check_10g_link,
1052d17280bSsbehera 	PCS_XCVR
10659ac0c16Sdavemq };
10759ac0c16Sdavemq 
1082e59129aSraghus static nxge_xcvr_table_t nxge_n2_1G_table = {
1092e59129aSraghus 	nxge_n2_serdes_init,
1102e59129aSraghus 	nxge_1G_xcvr_init,
1112e59129aSraghus 	nxge_1G_fiber_link_intr_stop,
1122e59129aSraghus 	nxge_1G_fiber_link_intr_start,
1132e59129aSraghus 	nxge_check_mii_link,
1142d17280bSsbehera 	PCS_XCVR
1152e59129aSraghus };
1162e59129aSraghus 
11759ac0c16Sdavemq static nxge_xcvr_table_t nxge_10G_fiber_table = {
11859ac0c16Sdavemq 	nxge_neptune_10G_serdes_init,
11959ac0c16Sdavemq 	nxge_10G_xcvr_init,
12059ac0c16Sdavemq 	nxge_10G_link_intr_stop,
12159ac0c16Sdavemq 	nxge_10G_link_intr_start,
12259ac0c16Sdavemq 	nxge_check_10g_link,
1232d17280bSsbehera 	PCS_XCVR
12459ac0c16Sdavemq };
12559ac0c16Sdavemq 
12659ac0c16Sdavemq static nxge_xcvr_table_t nxge_1G_copper_table = {
12759ac0c16Sdavemq 	NULL,
12859ac0c16Sdavemq 	nxge_1G_xcvr_init,
12959ac0c16Sdavemq 	nxge_1G_copper_link_intr_stop,
13059ac0c16Sdavemq 	nxge_1G_copper_link_intr_start,
13159ac0c16Sdavemq 	nxge_check_mii_link,
1322d17280bSsbehera 	INT_MII_XCVR
13359ac0c16Sdavemq };
13459ac0c16Sdavemq 
13559ac0c16Sdavemq static nxge_xcvr_table_t nxge_1G_fiber_table = {
13659ac0c16Sdavemq 	nxge_1G_serdes_init,
13759ac0c16Sdavemq 	nxge_1G_xcvr_init,
13859ac0c16Sdavemq 	nxge_1G_fiber_link_intr_stop,
13959ac0c16Sdavemq 	nxge_1G_fiber_link_intr_start,
14059ac0c16Sdavemq 	nxge_check_mii_link,
1412d17280bSsbehera 	PCS_XCVR
14259ac0c16Sdavemq };
14359ac0c16Sdavemq 
14459ac0c16Sdavemq static nxge_xcvr_table_t nxge_10G_copper_table = {
14559ac0c16Sdavemq 	nxge_neptune_10G_serdes_init,
14659ac0c16Sdavemq 	NULL,
14759ac0c16Sdavemq 	NULL,
14859ac0c16Sdavemq 	NULL,
1492e59129aSraghus 	NULL,
1502d17280bSsbehera 	PCS_XCVR
15159ac0c16Sdavemq };
15244961713Sgirish 
15344961713Sgirish nxge_status_t nxge_mac_init(p_nxge_t);
15444961713Sgirish 
155d81011f0Ssbehera #ifdef NXGE_DEBUG
156d81011f0Ssbehera static void nxge_mii_dump(p_nxge_t);
157d81011f0Ssbehera #endif
158d81011f0Ssbehera static nxge_status_t nxge_mii_get_link_mode(p_nxge_t);
159d81011f0Ssbehera 
1602e59129aSraghus nxge_status_t
1612e59129aSraghus nxge_get_xcvr_type(p_nxge_t nxgep)
1622e59129aSraghus {
1632e59129aSraghus 	nxge_status_t status = NXGE_OK;
1642e59129aSraghus 	char *phy_type;
1652e59129aSraghus 	char *prop_val;
1662e59129aSraghus 
1672e59129aSraghus 	nxgep->mac.portmode = 0;
1682d17280bSsbehera 	nxgep->xcvr_addr = 0;
1692e59129aSraghus 
1702d17280bSsbehera 	/*
1712d17280bSsbehera 	 * First check for hot swappable phy property.
1722d17280bSsbehera 	 */
1732d17280bSsbehera 	if (nxgep->hot_swappable_phy == B_TRUE) {
1742d17280bSsbehera 		nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR;
1752d17280bSsbehera 		nxgep->mac.portmode = PORT_HSP_MODE;
1762d17280bSsbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Other: Hot Swappable"));
1772d17280bSsbehera 	} else if (ddi_prop_exists(DDI_DEV_T_ANY, nxgep->dip,
1782d17280bSsbehera 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
1792d17280bSsbehera 	    "hot-swappable-phy") == 1) {
1802d17280bSsbehera 		nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR;
1812d17280bSsbehera 		nxgep->mac.portmode = PORT_HSP_MODE;
1822d17280bSsbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, ".conf: Hot Swappable"));
1832d17280bSsbehera 	} else if (nxgep->niu_type == N2_NIU &&
1842d17280bSsbehera 	    ddi_prop_exists(DDI_DEV_T_ANY, nxgep->dip, 0,
1852d17280bSsbehera 	    "hot-swappable-phy") == 1) {
1862d17280bSsbehera 		nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR;
1872d17280bSsbehera 		nxgep->mac.portmode = PORT_HSP_MODE;
1882d17280bSsbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "OBP: Hot Swappable"));
1892d17280bSsbehera 	}
1902d17280bSsbehera 
1912d17280bSsbehera 	/*
1922d17280bSsbehera 	 * MDIO polling support for Monza RTM card, Goa NEM card
1932d17280bSsbehera 	 */
1942d17280bSsbehera 	if (nxgep->mac.portmode == PORT_HSP_MODE) {
1952d17280bSsbehera 
1962d17280bSsbehera 		uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num);
1972d17280bSsbehera 
1982d17280bSsbehera 		nxgep->hot_swappable_phy = B_TRUE;
1992d17280bSsbehera 		/*
2002d17280bSsbehera 		 * If this is the 2nd NIU port, then check 2 addresses
2012d17280bSsbehera 		 * to take care of the Goa NEM card. Port 1 can have addr 17
2022d17280bSsbehera 		 * (in the eval board) or 20 (in the P0 board).
2032d17280bSsbehera 		 */
2042d17280bSsbehera 		if (portn == 1) {
2052d17280bSsbehera 			if (nxge_is_phy_present(nxgep,
2062d17280bSsbehera 			    BCM8706_ALT_GOA_PORT1_ADDR, BCM8706_DEV_ID,
2072d17280bSsbehera 			    BCM_PHY_ID_MASK)) {
2082d17280bSsbehera 				nxgep->xcvr_addr =
2092d17280bSsbehera 				    BCM8706_ALT_GOA_PORT1_ADDR;
2102d17280bSsbehera 				goto found_phy;
2112d17280bSsbehera 			}
2122d17280bSsbehera 		}
2132d17280bSsbehera 		if (nxge_is_phy_present(nxgep,
2142d17280bSsbehera 		    (BCM8706_GOA_PORT_ADDR_BASE) + portn,
2152d17280bSsbehera 		    BCM8706_DEV_ID, BCM_PHY_ID_MASK)) {
2162d17280bSsbehera 			nxgep->xcvr_addr = (BCM8706_GOA_PORT_ADDR_BASE) +
2172d17280bSsbehera 			    portn;
2182d17280bSsbehera 			goto found_phy;
2192d17280bSsbehera 		}
2202d17280bSsbehera 
2212d17280bSsbehera 		nxgep->phy_absent = B_TRUE;
2222d17280bSsbehera 		goto check_phy_done;
2232d17280bSsbehera found_phy:
2242d17280bSsbehera 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
2252d17280bSsbehera 		nxgep->mac.portmode = PORT_10G_FIBER;
2262d17280bSsbehera 		nxgep->phy_absent = B_FALSE;
2272d17280bSsbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Fiber Xcvr "
2282d17280bSsbehera 		    "found for hot swappable phy"));
2292d17280bSsbehera check_phy_done:
2302d17280bSsbehera 		return (status);
2312d17280bSsbehera 	}
2322d17280bSsbehera 
2332d17280bSsbehera 	/* Get phy-type property from the driver conf. file */
2342e59129aSraghus 	if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip,
2352e59129aSraghus 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
2362e59129aSraghus 	    "phy-type", &prop_val)) == DDI_PROP_SUCCESS) {
2372e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2382e59129aSraghus 		    "found  conf file: phy-type %s", prop_val));
2392e59129aSraghus 		if (strcmp("xgsd", prop_val) == 0) {
2402e59129aSraghus 			nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
2412e59129aSraghus 			nxgep->mac.portmode = PORT_10G_SERDES;
2422e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2432e59129aSraghus 			    "found: 10G Serdes"));
2442e59129aSraghus 		} else if (strcmp("gsd", prop_val) == 0) {
2452e59129aSraghus 			nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
2462e59129aSraghus 			nxgep->mac.portmode = PORT_1G_SERDES;
2472e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Serdes"));
2482e59129aSraghus 		} else if (strcmp("mif", prop_val) == 0) {
2492e59129aSraghus 			nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR;
2502e59129aSraghus 			nxgep->mac.portmode = PORT_1G_COPPER;
2512e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Copper Xcvr"));
2522e59129aSraghus 		} else if (strcmp("pcs", prop_val) == 0) {
2532e59129aSraghus 			nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
2542e59129aSraghus 			nxgep->mac.portmode = PORT_1G_FIBER;
2552e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G FIBER Xcvr"));
256*321febdeSsbehera 		} else if (strcmp("xgf", prop_val) == 0) {
257*321febdeSsbehera 			nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
258*321febdeSsbehera 			nxgep->mac.portmode = PORT_10G_FIBER;
259*321febdeSsbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G FIBER Xcvr"));
2602e59129aSraghus 		}
2612e59129aSraghus 
2622e59129aSraghus 		(void) ddi_prop_update_string(DDI_DEV_T_NONE, nxgep->dip,
2632e59129aSraghus 		    "phy-type", prop_val);
2642e59129aSraghus 		ddi_prop_free(prop_val);
2652e59129aSraghus 
2662e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: "
2672e59129aSraghus 		    "Got phy type [0x%x] from conf file",
2682e59129aSraghus 		    nxgep->mac.portmode));
2692e59129aSraghus 
2702e59129aSraghus 		return (NXGE_OK);
2712e59129aSraghus 	}
2722d17280bSsbehera 
2732d17280bSsbehera 	/* Get phy-type property from OBP */
2742e59129aSraghus 	if (nxgep->niu_type == N2_NIU) {
2752e59129aSraghus 		if (ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip, 0,
2762e59129aSraghus 		    "phy-type", &prop_val) == DDI_PROP_SUCCESS) {
2772e59129aSraghus 			if (strcmp("xgf", prop_val) == 0) {
2782e59129aSraghus 				nxgep->statsp->mac_stats.xcvr_inuse =
2792e59129aSraghus 				    XPCS_XCVR;
2802e59129aSraghus 				nxgep->mac.portmode = PORT_10G_FIBER;
2812e59129aSraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2822e59129aSraghus 				    "10G Fiber Xcvr"));
2832e59129aSraghus 			} else if (strcmp("mif", prop_val) == 0) {
2842e59129aSraghus 				nxgep->statsp->mac_stats.xcvr_inuse =
2852e59129aSraghus 				    INT_MII_XCVR;
2862e59129aSraghus 				nxgep->mac.portmode = PORT_1G_COPPER;
2872e59129aSraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2882e59129aSraghus 				    "1G Copper Xcvr"));
2892e59129aSraghus 			} else if (strcmp("pcs", prop_val) == 0) {
2902e59129aSraghus 				nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
2912e59129aSraghus 				nxgep->mac.portmode = PORT_1G_FIBER;
2922e59129aSraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2932e59129aSraghus 				    "1G Fiber Xcvr"));
2942e59129aSraghus 			} else if (strcmp("xgc", prop_val) == 0) {
2952e59129aSraghus 				nxgep->statsp->mac_stats.xcvr_inuse =
2962e59129aSraghus 				    XPCS_XCVR;
2972e59129aSraghus 				nxgep->mac.portmode = PORT_10G_COPPER;
2982e59129aSraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2992e59129aSraghus 				    "10G Copper Xcvr"));
3002e59129aSraghus 			} else if (strcmp("xgsd", prop_val) == 0) {
3012e59129aSraghus 				nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
3022e59129aSraghus 				nxgep->mac.portmode = PORT_10G_SERDES;
3032e59129aSraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3042e59129aSraghus 				    "OBP: 10G Serdes"));
3052e59129aSraghus 			} else if (strcmp("gsd", prop_val) == 0) {
3062e59129aSraghus 				nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
3072e59129aSraghus 				nxgep->mac.portmode = PORT_1G_SERDES;
3082e59129aSraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3092e59129aSraghus 				    "OBP: 1G Serdes"));
3102e59129aSraghus 			} else {
3112e59129aSraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3122e59129aSraghus 				    "Unknown phy-type: %s", prop_val));
3132e59129aSraghus 				ddi_prop_free(prop_val);
3142e59129aSraghus 				return (NXGE_ERROR);
3152e59129aSraghus 			}
3162e59129aSraghus 			status = NXGE_OK;
3172e59129aSraghus 			(void) ddi_prop_update_string(DDI_DEV_T_NONE,
3182e59129aSraghus 			    nxgep->dip, "phy-type", prop_val);
3192e59129aSraghus 			ddi_prop_free(prop_val);
3202e59129aSraghus 
3212e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: "
3222e59129aSraghus 			    "Got phy type [0x%x] from OBP",
3232e59129aSraghus 			    nxgep->mac.portmode));
3242e59129aSraghus 
3252e59129aSraghus 			return (status);
3262e59129aSraghus 		} else {
3272e59129aSraghus 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3282e59129aSraghus 			    "Exiting...phy-type property not found"));
3292e59129aSraghus 			return (NXGE_ERROR);
3302e59129aSraghus 		}
3312e59129aSraghus 	}
3322e59129aSraghus 
3332e59129aSraghus 
3342e59129aSraghus 	if (!nxgep->vpd_info.present) {
3352e59129aSraghus 		return (NXGE_OK);
3362e59129aSraghus 	}
3372e59129aSraghus 
3382e59129aSraghus 	if (!nxgep->vpd_info.ver_valid) {
3392e59129aSraghus 		goto read_seeprom;
3402e59129aSraghus 	}
3412e59129aSraghus 
3422e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3432e59129aSraghus 	    "Reading phy type from expansion ROM"));
3442e59129aSraghus 	/*
3452e59129aSraghus 	 * Try to read the phy type from the vpd data read off the
3462e59129aSraghus 	 * expansion ROM.
3472e59129aSraghus 	 */
3482e59129aSraghus 	phy_type = nxgep->vpd_info.phy_type;
3492e59129aSraghus 
350d81011f0Ssbehera 	if (strncmp(phy_type, "mif", 3) == 0) {
3512e59129aSraghus 		nxgep->mac.portmode = PORT_1G_COPPER;
3522e59129aSraghus 		nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR;
353d81011f0Ssbehera 	} else if (strncmp(phy_type, "xgf", 3) == 0) {
3542e59129aSraghus 		nxgep->mac.portmode = PORT_10G_FIBER;
3552e59129aSraghus 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
356d81011f0Ssbehera 	} else if (strncmp(phy_type, "pcs", 3) == 0) {
3572e59129aSraghus 		nxgep->mac.portmode = PORT_1G_FIBER;
3582e59129aSraghus 		nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
359d81011f0Ssbehera 	} else if (strncmp(phy_type, "xgc", 3) == 0) {
3602e59129aSraghus 		nxgep->mac.portmode = PORT_10G_COPPER;
3612e59129aSraghus 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
362d81011f0Ssbehera 	} else if (strncmp(phy_type, "xgsd", 4) == 0) {
363d81011f0Ssbehera 		nxgep->mac.portmode = PORT_10G_SERDES;
364d81011f0Ssbehera 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
365d81011f0Ssbehera 	} else if (strncmp(phy_type, "gsd", 3) == 0) {
366d81011f0Ssbehera 		nxgep->mac.portmode = PORT_1G_SERDES;
367d81011f0Ssbehera 		nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
3682e59129aSraghus 	} else {
369d81011f0Ssbehera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3702e59129aSraghus 		    "nxge_get_xcvr_type: Unknown phy type [%c%c%c] in EEPROM",
3712e59129aSraghus 		    phy_type[0], phy_type[1], phy_type[2]));
3722e59129aSraghus 		goto read_seeprom;
3732e59129aSraghus 	}
3742e59129aSraghus 
3752e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: "
3762e59129aSraghus 	    "Got phy type [0x%x] from VPD", nxgep->mac.portmode));
3772e59129aSraghus 
3782e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_get_xcvr_type"));
3792e59129aSraghus 	return (status);
3802e59129aSraghus 
3812e59129aSraghus read_seeprom:
3822e59129aSraghus 	/*
3832e59129aSraghus 	 * read the phy type from the SEEPROM - NCR registers
3842e59129aSraghus 	 */
3852e59129aSraghus 	status = nxge_espc_phy_type_get(nxgep);
3862e59129aSraghus 	if (status != NXGE_OK) {
3872e59129aSraghus 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3882e59129aSraghus 		    "Failed to get phy type"));
3892e59129aSraghus 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "EEPROM version "
3902e59129aSraghus 		    "[%s] invalid...please update", nxgep->vpd_info.ver));
3912e59129aSraghus 	}
3922e59129aSraghus 
3932e59129aSraghus 	return (status);
3942e59129aSraghus 
3952e59129aSraghus }
3962e59129aSraghus 
39759ac0c16Sdavemq /* Set up the PHY specific values. */
39859ac0c16Sdavemq 
39959ac0c16Sdavemq nxge_status_t
40059ac0c16Sdavemq nxge_setup_xcvr_table(p_nxge_t nxgep)
40159ac0c16Sdavemq {
40259ac0c16Sdavemq 	nxge_status_t	status = NXGE_OK;
40359ac0c16Sdavemq 	uint32_t	port_type;
40459ac0c16Sdavemq 	uint8_t		portn = NXGE_GET_PORT_NUM(nxgep->function_num);
4052e59129aSraghus 	uint32_t	pcs_id = 0;
4062e59129aSraghus 	uint32_t	pma_pmd_id = 0;
4072e59129aSraghus 	uint32_t	phy_id = 0;
4082d17280bSsbehera 	uint16_t	chip_id = 0;
40959ac0c16Sdavemq 
41059ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_setup_xcvr_table: port<%d>",
41159ac0c16Sdavemq 	    portn));
41259ac0c16Sdavemq 
4132e59129aSraghus 	switch (nxgep->niu_type) {
4142e59129aSraghus 	case N2_NIU:
4152e59129aSraghus 		switch (nxgep->mac.portmode) {
4162e59129aSraghus 		case PORT_1G_FIBER:
4172e59129aSraghus 		case PORT_1G_SERDES:
4182e59129aSraghus 			nxgep->xcvr = nxge_n2_1G_table;
4192d17280bSsbehera 			nxgep->xcvr_addr = portn;
4202e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 1G %s Xcvr",
4212e59129aSraghus 			    (nxgep->mac.portmode == PORT_1G_FIBER) ? "Fiber" :
4222e59129aSraghus 			    "Serdes"));
4232e59129aSraghus 			break;
4242e59129aSraghus 		case PORT_10G_FIBER:
4252e59129aSraghus 		case PORT_10G_SERDES:
4262e59129aSraghus 			nxgep->xcvr = nxge_n2_10G_table;
4272d17280bSsbehera 			if (nxgep->nxge_hw_p->xcvr_addr[portn]) {
4282d17280bSsbehera 				nxgep->xcvr_addr =
4292d17280bSsbehera 				    nxgep->nxge_hw_p->xcvr_addr[portn];
4302d17280bSsbehera 			}
4312e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 10G %s Xcvr",
4322e59129aSraghus 			    (nxgep->mac.portmode == PORT_10G_FIBER) ? "Fiber" :
4332e59129aSraghus 			    "Serdes"));
4342e59129aSraghus 			break;
4352d17280bSsbehera 		case PORT_HSP_MODE:
4362d17280bSsbehera 			nxgep->xcvr = nxge_n2_10G_table;
4372d17280bSsbehera 			nxgep->xcvr.xcvr_inuse = HSP_XCVR;
4382d17280bSsbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 10G Hot "
4392d17280bSsbehera 			    "Swappable Xcvr (not present)"));
4402d17280bSsbehera 			break;
4412e59129aSraghus 		default:
4422e59129aSraghus 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4432e59129aSraghus 			    "<== nxge_setup_xcvr_table: "
4442e59129aSraghus 			    "Unable to determine NIU portmode"));
4452e59129aSraghus 			return (NXGE_ERROR);
4462e59129aSraghus 		}
4472e59129aSraghus 		break;
4482e59129aSraghus 	default:
4492e59129aSraghus 		if (nxgep->mac.portmode == 0) {
4502e59129aSraghus 			/*
4512e59129aSraghus 			 * Would be the case for platforms like Maramba
4522e59129aSraghus 			 * in which the phy type could not be got from conf
4532e59129aSraghus 			 * file, OBP, VPD or Serial PROM.
4542e59129aSraghus 			 */
4552e59129aSraghus 			if (!NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
4562e59129aSraghus 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4572e59129aSraghus 				    "<== nxge_setup_xcvr_table:"
4582e59129aSraghus 				    " Invalid Neptune type [0x%x]",
4592e59129aSraghus 				    nxgep->niu_type));
4602e59129aSraghus 				return (NXGE_ERROR);
4612e59129aSraghus 			}
4622e59129aSraghus 
4632e59129aSraghus 			port_type = nxgep->niu_type >>
4642e59129aSraghus 			    (NXGE_PORT_TYPE_SHIFT * portn);
4652e59129aSraghus 			port_type = port_type & (NXGE_PORT_TYPE_MASK);
4662e59129aSraghus 
4672e59129aSraghus 			switch (port_type) {
4682e59129aSraghus 
4692e59129aSraghus 			case NXGE_PORT_1G_COPPER:
4702e59129aSraghus 				nxgep->mac.portmode = PORT_1G_COPPER;
4712e59129aSraghus 				break;
4722e59129aSraghus 			case NXGE_PORT_10G_COPPER:
4732e59129aSraghus 				nxgep->mac.portmode = PORT_10G_COPPER;
4742e59129aSraghus 				break;
4752e59129aSraghus 			case NXGE_PORT_1G_FIBRE:
4762e59129aSraghus 				nxgep->mac.portmode = PORT_1G_FIBER;
4772e59129aSraghus 				break;
4782e59129aSraghus 			case NXGE_PORT_10G_FIBRE:
4792e59129aSraghus 				nxgep->mac.portmode = PORT_10G_FIBER;
4802e59129aSraghus 				break;
4812e59129aSraghus 			case NXGE_PORT_1G_SERDES:
4822e59129aSraghus 				nxgep->mac.portmode = PORT_1G_SERDES;
4832e59129aSraghus 				break;
4842e59129aSraghus 			case NXGE_PORT_10G_SERDES:
4852e59129aSraghus 				nxgep->mac.portmode = PORT_10G_SERDES;
4862e59129aSraghus 				break;
4872e59129aSraghus 			case NXGE_PORT_1G_RGMII_FIBER:
4882e59129aSraghus 				nxgep->mac.portmode = PORT_1G_RGMII_FIBER;
4892e59129aSraghus 				break;
4902e59129aSraghus 			default:
4912e59129aSraghus 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4922e59129aSraghus 				    "<== nxge_setup_xcvr_table: "
4932e59129aSraghus 				    "Unknown port-type: 0x%x", port_type));
4942e59129aSraghus 				return (NXGE_ERROR);
4952e59129aSraghus 			}
4962e59129aSraghus 		}
4972e59129aSraghus 
4982e59129aSraghus 		switch (nxgep->mac.portmode) {
4992e59129aSraghus 		case PORT_1G_COPPER:
5002e59129aSraghus 		case PORT_1G_RGMII_FIBER:
50159ac0c16Sdavemq 			nxgep->xcvr = nxge_1G_copper_table;
5022d17280bSsbehera 			nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
50359ac0c16Sdavemq 			/*
50459ac0c16Sdavemq 			 * For Altas 4-1G copper, Xcvr port numbers are
50559ac0c16Sdavemq 			 * swapped with ethernet port number. This is
5062e59129aSraghus 			 * designed for better signal integrity in
5072e59129aSraghus 			 * routing. This is also the case for the
5082e59129aSraghus 			 * on-board Neptune copper ports on the Maramba
5092e59129aSraghus 			 * platform.
51059ac0c16Sdavemq 			 */
5112e59129aSraghus 			switch (nxgep->platform_type) {
5122e59129aSraghus 			case P_NEPTUNE_ATLAS_4PORT:
5132e59129aSraghus 			case P_NEPTUNE_MARAMBA_P0:
5142e59129aSraghus 			case P_NEPTUNE_MARAMBA_P1:
5152e59129aSraghus 				switch (portn) {
5162e59129aSraghus 				case 0:
5172d17280bSsbehera 					nxgep->xcvr_addr += 3;
5182e59129aSraghus 					break;
5192e59129aSraghus 				case 1:
5202d17280bSsbehera 					nxgep->xcvr_addr += 1;
5212e59129aSraghus 					break;
5222e59129aSraghus 				case 2:
5232d17280bSsbehera 					nxgep->xcvr_addr -= 1;
5242e59129aSraghus 					break;
5252e59129aSraghus 				case 3:
5262d17280bSsbehera 					nxgep->xcvr_addr -= 3;
5272e59129aSraghus 					break;
5282e59129aSraghus 				default:
5292e59129aSraghus 					return (NXGE_ERROR);
5302e59129aSraghus 				}
53159ac0c16Sdavemq 				break;
532d81011f0Ssbehera 			case P_NEPTUNE_ALONSO:
533d81011f0Ssbehera 			/*
534d81011f0Ssbehera 			 * The Alonso Neptune, xcvr port numbers for
535d81011f0Ssbehera 			 * ports 2 and 3 are not swapped. Port 2 has
536d81011f0Ssbehera 			 * the BCM5464_PORT_BASE_ADDR and port 3 has
537d81011f0Ssbehera 			 * next address.
538d81011f0Ssbehera 			 */
5392d17280bSsbehera 				nxgep->xcvr_addr =
5402d17280bSsbehera 				    BCM5464_NEPTUNE_PORT_ADDR_BASE;
541d81011f0Ssbehera 				if (portn == 3) {
5422d17280bSsbehera 					nxgep->xcvr_addr += 1;
543d81011f0Ssbehera 				}
544d81011f0Ssbehera 				break;
54559ac0c16Sdavemq 			default:
5462e59129aSraghus 				break;
54759ac0c16Sdavemq 			}
548d81011f0Ssbehera 
5492e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr",
5502e59129aSraghus 			    (nxgep->mac.portmode == PORT_1G_COPPER) ?
5512e59129aSraghus 			    "Copper" : "RGMII Fiber"));
55259ac0c16Sdavemq 			break;
5532e59129aSraghus 		case PORT_10G_COPPER:
55459ac0c16Sdavemq 			nxgep->xcvr = nxge_10G_copper_table;
55559ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Copper Xcvr"));
55659ac0c16Sdavemq 			break;
5572e59129aSraghus 		case PORT_1G_FIBER:
5582e59129aSraghus 		case PORT_1G_SERDES:
55959ac0c16Sdavemq 			nxgep->xcvr = nxge_1G_fiber_table;
5602d17280bSsbehera 			nxgep->xcvr_addr = portn;
5612e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr",
5622e59129aSraghus 			    (nxgep->mac.portmode == PORT_1G_FIBER) ?
5632e59129aSraghus 			    "Fiber" : "Serdes"));
56459ac0c16Sdavemq 			break;
5652e59129aSraghus 		case PORT_10G_FIBER:
5662e59129aSraghus 		case PORT_10G_SERDES:
56759ac0c16Sdavemq 			nxgep->xcvr = nxge_10G_fiber_table;
5682d17280bSsbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G xcvr "
5692d17280bSsbehera 			    "nxgep->nxge_hw_p->xcvr_addr[portn] = [%d] "
5702d17280bSsbehera 			    "nxgep->xcvr_addr = [%d]",
5712d17280bSsbehera 			    nxgep->nxge_hw_p->xcvr_addr[portn],
5722d17280bSsbehera 			    nxgep->xcvr_addr));
5732d17280bSsbehera 			if (nxgep->nxge_hw_p->xcvr_addr[portn]) {
5742d17280bSsbehera 				nxgep->xcvr_addr =
5752d17280bSsbehera 				    nxgep->nxge_hw_p->xcvr_addr[portn];
5762d17280bSsbehera 			}
5772e59129aSraghus 			switch (nxgep->platform_type) {
5782e59129aSraghus 			case P_NEPTUNE_MARAMBA_P0:
5792e59129aSraghus 			case P_NEPTUNE_MARAMBA_P1:
58059ac0c16Sdavemq 				/*
58159ac0c16Sdavemq 				 * Switch off LED for corresponding copper
58259ac0c16Sdavemq 				 * port
58359ac0c16Sdavemq 				 */
58459ac0c16Sdavemq 				nxge_bcm5464_link_led_off(nxgep);
5852e59129aSraghus 				break;
5862e59129aSraghus 			default:
5872e59129aSraghus 				break;
58859ac0c16Sdavemq 			}
5892e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G %s Xcvr",
5902e59129aSraghus 			    (nxgep->mac.portmode == PORT_10G_FIBER) ?
5912e59129aSraghus 			    "Fiber" : "Serdes"));
59259ac0c16Sdavemq 			break;
5932d17280bSsbehera 
5942d17280bSsbehera 		case PORT_HSP_MODE:
5952d17280bSsbehera 			nxgep->xcvr = nxge_10G_fiber_table;
5962d17280bSsbehera 			nxgep->xcvr.xcvr_inuse = HSP_XCVR;
5972d17280bSsbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Neptune 10G Hot "
5982d17280bSsbehera 			    "Swappable Xcvr (not present)"));
5992d17280bSsbehera 			break;
60059ac0c16Sdavemq 		default:
60159ac0c16Sdavemq 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
60259ac0c16Sdavemq 			    "Unknown port-type: 0x%x", port_type));
60359ac0c16Sdavemq 			return (NXGE_ERROR);
60459ac0c16Sdavemq 		}
60559ac0c16Sdavemq 	}
60659ac0c16Sdavemq 
6072d17280bSsbehera 	if (nxgep->mac.portmode == PORT_10G_FIBER) {
6082d17280bSsbehera 		if ((status = nxge_mdio_read(nxgep, nxgep->xcvr_addr,
6092d17280bSsbehera 		    BCM8704_PCS_DEV_ADDR, BCM8704_CHIP_ID_REG,
6102d17280bSsbehera 		    &chip_id)) == NXGE_OK) {
6112d17280bSsbehera 
6122d17280bSsbehera 			switch (chip_id) {
6132d17280bSsbehera 			case BCM8704_CHIP_ID:
6142d17280bSsbehera 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6152d17280bSsbehera 				    "nxge_setup_xcvr_table: "
6162d17280bSsbehera 				    "Chip ID 8704 [0x%x] for 10G xcvr",
6172d17280bSsbehera 				    chip_id));
6182d17280bSsbehera 				break;
6192d17280bSsbehera 			case BCM8706_CHIP_ID:
6202d17280bSsbehera 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6212d17280bSsbehera 				    "nxge_setup_xcvr_table: "
6222d17280bSsbehera 				    "Chip ID 8706 [0x%x] for 10G xcvr",
6232d17280bSsbehera 				    chip_id));
6242d17280bSsbehera 				break;
6252d17280bSsbehera 			default:
6262d17280bSsbehera 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6272d17280bSsbehera 				    "nxge_setup_xcvr_table: "
6282d17280bSsbehera 				    "Unknown Chip ID [0x%x] for 10G xcvr",
6292d17280bSsbehera 				    chip_id));
6302d17280bSsbehera 				break;
6312d17280bSsbehera 			}
6322d17280bSsbehera 		}
6332d17280bSsbehera 	}
6342d17280bSsbehera 
63559ac0c16Sdavemq 	nxgep->statsp->mac_stats.xcvr_inuse = nxgep->xcvr.xcvr_inuse;
6362d17280bSsbehera 	nxgep->statsp->mac_stats.xcvr_portn = nxgep->xcvr_addr;
6372d17280bSsbehera 	nxgep->chip_id = chip_id;
6382e59129aSraghus 
6392e59129aSraghus 	/*
6402e59129aSraghus 	 * Get the actual device ID value returned by MDIO read.
6412e59129aSraghus 	 */
6422e59129aSraghus 	nxgep->statsp->mac_stats.xcvr_id = 0;
6432e59129aSraghus 
6442d17280bSsbehera 	pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, nxgep->xcvr_addr);
6452e59129aSraghus 	if (nxge_is_supported_phy(pma_pmd_id, CLAUSE_45_TYPE)) {
6462e59129aSraghus 		nxgep->statsp->mac_stats.xcvr_id = pma_pmd_id;
6472e59129aSraghus 	} else {
6482d17280bSsbehera 		pcs_id = nxge_get_cl45_pcs_id(nxgep, nxgep->xcvr_addr);
6492e59129aSraghus 		if (nxge_is_supported_phy(pcs_id, CLAUSE_45_TYPE)) {
6502e59129aSraghus 			nxgep->statsp->mac_stats.xcvr_id = pcs_id;
6512e59129aSraghus 		} else {
6522e59129aSraghus 			phy_id = nxge_get_cl22_phy_id(nxgep,
6532d17280bSsbehera 			    nxgep->xcvr_addr);
6542e59129aSraghus 			if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) {
6552e59129aSraghus 				nxgep->statsp->mac_stats.xcvr_id = phy_id;
6562e59129aSraghus 			}
6572e59129aSraghus 		}
6582e59129aSraghus 	}
6592e59129aSraghus 
66059ac0c16Sdavemq 	nxgep->mac.linkchkmode = LINKCHK_TIMER;
66159ac0c16Sdavemq 
6622e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_setup_xcvr_table: niu_type"
6632d17280bSsbehera 	    "[0x%x] platform type[0x%x] xcvr_arr[%d]", nxgep->niu_type,
6642d17280bSsbehera 	    nxgep->platform_type, nxgep->xcvr_addr));
6652e59129aSraghus 
66659ac0c16Sdavemq 	return (status);
66759ac0c16Sdavemq }
66859ac0c16Sdavemq 
66944961713Sgirish /* Initialize the entire MAC and physical layer */
67044961713Sgirish 
67144961713Sgirish nxge_status_t
67244961713Sgirish nxge_mac_init(p_nxge_t nxgep)
67344961713Sgirish {
67444961713Sgirish 	uint8_t			portn;
67544961713Sgirish 	nxge_status_t		status = NXGE_OK;
67644961713Sgirish 
67744961713Sgirish 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
67844961713Sgirish 
67944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_init: port<%d>", portn));
68044961713Sgirish 
68144961713Sgirish 	nxgep->mac.portnum = portn;
68244961713Sgirish 	nxgep->mac.porttype = PORT_TYPE_XMAC;
68344961713Sgirish 
68444961713Sgirish 	if ((portn == BMAC_PORT_0) || (portn == BMAC_PORT_1))
68544961713Sgirish 		nxgep->mac.porttype = PORT_TYPE_BMAC;
68644961713Sgirish 
68744961713Sgirish 	/* Initialize XIF to configure a network mode */
68844961713Sgirish 	if ((status = nxge_xif_init(nxgep)) != NXGE_OK) {
68944961713Sgirish 		goto fail;
69044961713Sgirish 	}
69144961713Sgirish 
69244961713Sgirish 	if ((status = nxge_pcs_init(nxgep)) != NXGE_OK) {
69344961713Sgirish 		goto fail;
69444961713Sgirish 	}
69544961713Sgirish 
69644961713Sgirish 	/* Initialize TX and RX MACs */
69744961713Sgirish 	/*
69844961713Sgirish 	 * Always perform XIF init first, before TX and RX MAC init
69944961713Sgirish 	 */
70044961713Sgirish 	if ((status = nxge_tx_mac_reset(nxgep)) != NXGE_OK)
70144961713Sgirish 		goto fail;
70244961713Sgirish 
70344961713Sgirish 	if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK)
70444961713Sgirish 		goto fail;
70544961713Sgirish 
70644961713Sgirish 	if ((status = nxge_rx_mac_reset(nxgep)) != NXGE_OK)
70744961713Sgirish 		goto fail;
70844961713Sgirish 
70944961713Sgirish 	if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
71044961713Sgirish 		goto fail;
71144961713Sgirish 
71244961713Sgirish 	if ((status = nxge_tx_mac_enable(nxgep)) != NXGE_OK)
71344961713Sgirish 		goto fail;
71444961713Sgirish 
71544961713Sgirish 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
71644961713Sgirish 		goto fail;
71744961713Sgirish 
718cb9d3ae6Smisaki 	/* Initialize MAC control configuration */
719cb9d3ae6Smisaki 	if ((status = nxge_mac_ctrl_init(nxgep)) != NXGE_OK) {
720cb9d3ae6Smisaki 		goto fail;
721cb9d3ae6Smisaki 	}
722cb9d3ae6Smisaki 
72344961713Sgirish 	nxgep->statsp->mac_stats.mac_mtu = nxgep->mac.maxframesize;
72444961713Sgirish 
725d81011f0Ssbehera 	/* The Neptune Serdes needs to be reinitialized again */
726d81011f0Ssbehera 	if ((NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) &&
727d81011f0Ssbehera 	    ((nxgep->mac.portmode == PORT_1G_SERDES) ||
728d81011f0Ssbehera 	    (nxgep->mac.portmode == PORT_1G_FIBER)) &&
729d81011f0Ssbehera 	    ((portn == 0) || (portn == 1))) {
730d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
731d81011f0Ssbehera 		    "nxge_mac_init: reinit Neptune 1G Serdes "));
732d81011f0Ssbehera 		if ((status = nxge_1G_serdes_init(nxgep)) != NXGE_OK) {
733d81011f0Ssbehera 			goto fail;
734d81011f0Ssbehera 		}
735d81011f0Ssbehera 	}
736d81011f0Ssbehera 
7372e59129aSraghus 
73844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_init: port<%d>", portn));
73944961713Sgirish 
74044961713Sgirish 	return (NXGE_OK);
74144961713Sgirish fail:
74244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
74344961713Sgirish 			"nxge_mac_init: failed to initialize MAC port<%d>",
74444961713Sgirish 			portn));
74544961713Sgirish 	return (status);
74644961713Sgirish }
74744961713Sgirish 
74844961713Sgirish /* Initialize the Ethernet Link */
74944961713Sgirish 
75044961713Sgirish nxge_status_t
75144961713Sgirish nxge_link_init(p_nxge_t nxgep)
75244961713Sgirish {
75344961713Sgirish 	nxge_status_t		status = NXGE_OK;
7542e59129aSraghus 	nxge_port_mode_t	portmode;
75544961713Sgirish #ifdef	NXGE_DEBUG
75644961713Sgirish 	uint8_t			portn;
75744961713Sgirish 
75844961713Sgirish 	portn = nxgep->mac.portnum;
75944961713Sgirish 
76044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_init: port<%d>", portn));
76144961713Sgirish #endif
7622d17280bSsbehera 	if (nxgep->hot_swappable_phy && nxgep->phy_absent) {
7632d17280bSsbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_init: "
7642d17280bSsbehera 		    "Phy not present, cannot initialize link"));
7652d17280bSsbehera 		return (status);
7662d17280bSsbehera 	}
76744961713Sgirish 
7682e59129aSraghus 	portmode = nxgep->mac.portmode;
7692d17280bSsbehera 
7702e59129aSraghus 	if (nxgep->niu_type == N2_NIU && (portmode != PORT_10G_SERDES) &&
7712e59129aSraghus 	    (portmode != PORT_1G_SERDES)) {
77244961713Sgirish 		/* Workaround to get link up in both NIU ports */
7732e59129aSraghus 		if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK) {
77444961713Sgirish 			goto fail;
7752e59129aSraghus 		}
77644961713Sgirish 	}
77744961713Sgirish 	NXGE_DELAY(200000);
77844961713Sgirish 	/* Initialize internal serdes */
77944961713Sgirish 	if ((status = nxge_serdes_init(nxgep)) != NXGE_OK)
78044961713Sgirish 		goto fail;
78144961713Sgirish 	NXGE_DELAY(200000);
78244961713Sgirish 	if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK)
78344961713Sgirish 		goto fail;
78444961713Sgirish 
78544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_init: port<%d>", portn));
78644961713Sgirish 
78744961713Sgirish 	return (NXGE_OK);
78844961713Sgirish 
78944961713Sgirish fail:
79044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
79144961713Sgirish 		"nxge_link_init: ",
79244961713Sgirish 		"failed to initialize Ethernet link on port<%d>",
79344961713Sgirish 		portn));
79444961713Sgirish 
79544961713Sgirish 	return (status);
79644961713Sgirish }
79744961713Sgirish 
79844961713Sgirish 
79944961713Sgirish /* Initialize the XIF sub-block within the MAC */
80044961713Sgirish 
80144961713Sgirish nxge_status_t
80244961713Sgirish nxge_xif_init(p_nxge_t nxgep)
80344961713Sgirish {
80444961713Sgirish 	uint32_t		xif_cfg = 0;
80544961713Sgirish 	npi_attr_t		ap;
80644961713Sgirish 	uint8_t			portn;
80744961713Sgirish 	nxge_port_t		portt;
80844961713Sgirish 	nxge_port_mode_t	portmode;
80944961713Sgirish 	p_nxge_stats_t		statsp;
81044961713Sgirish 	npi_status_t		rs = NPI_SUCCESS;
81144961713Sgirish 	npi_handle_t		handle;
81244961713Sgirish 
81344961713Sgirish 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
81444961713Sgirish 
81544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xif_init: port<%d>", portn));
81644961713Sgirish 
81744961713Sgirish 	handle = nxgep->npi_handle;
81844961713Sgirish 	portmode = nxgep->mac.portmode;
81944961713Sgirish 	portt = nxgep->mac.porttype;
82044961713Sgirish 	statsp = nxgep->statsp;
82144961713Sgirish 
822d81011f0Ssbehera 	if ((NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) &&
823d81011f0Ssbehera 	    ((nxgep->mac.portmode == PORT_1G_SERDES) ||
824d81011f0Ssbehera 	    (nxgep->mac.portmode == PORT_1G_FIBER)) &&
825d81011f0Ssbehera 	    ((portn == 0) || (portn == 1))) {
826d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
827d81011f0Ssbehera 		    "nxge_xcvr_init: set ATCA mode"));
828d81011f0Ssbehera 		npi_mac_mif_set_atca_mode(nxgep->npi_handle, B_TRUE);
829d81011f0Ssbehera 	}
830d81011f0Ssbehera 
83144961713Sgirish 	if (portt == PORT_TYPE_XMAC) {
83244961713Sgirish 
83344961713Sgirish 		/* Setup XIF Configuration for XMAC */
83444961713Sgirish 
83544961713Sgirish 		if ((portmode == PORT_10G_FIBER) ||
8362e59129aSraghus 		    (portmode == PORT_10G_COPPER) ||
8372e59129aSraghus 		    (portmode == PORT_10G_SERDES))
83844961713Sgirish 			xif_cfg |= CFG_XMAC_XIF_LFS;
83944961713Sgirish 
84044961713Sgirish 		if (portmode == PORT_1G_COPPER) {
84144961713Sgirish 			xif_cfg |= CFG_XMAC_XIF_1G_PCS_BYPASS;
84244961713Sgirish 		}
84344961713Sgirish 
84444961713Sgirish 		/* Set MAC Internal Loopback if necessary */
84544961713Sgirish 		if (statsp->port_stats.lb_mode == nxge_lb_mac1000)
84644961713Sgirish 			xif_cfg |= CFG_XMAC_XIF_LOOPBACK;
84744961713Sgirish 
84844961713Sgirish 		if (statsp->mac_stats.link_speed == 100)
84944961713Sgirish 			xif_cfg |= CFG_XMAC_XIF_SEL_CLK_25MHZ;
85044961713Sgirish 
85144961713Sgirish 		xif_cfg |= CFG_XMAC_XIF_TX_OUTPUT;
85244961713Sgirish 
8532e59129aSraghus 		if ((portmode == PORT_10G_FIBER) ||
8542e59129aSraghus 		    (portmode == PORT_10G_SERDES)) {
85544961713Sgirish 			if (statsp->mac_stats.link_up) {
85644961713Sgirish 				xif_cfg |= CFG_XMAC_XIF_LED_POLARITY;
85744961713Sgirish 			} else {
85844961713Sgirish 				xif_cfg |= CFG_XMAC_XIF_LED_FORCE;
85944961713Sgirish 			}
86044961713Sgirish 		}
86144961713Sgirish 
86244961713Sgirish 		rs = npi_xmac_xif_config(handle, INIT, portn, xif_cfg);
86344961713Sgirish 		if (rs != NPI_SUCCESS)
86444961713Sgirish 			goto fail;
86544961713Sgirish 
86644961713Sgirish 		nxgep->mac.xif_config = xif_cfg;
86744961713Sgirish 
86844961713Sgirish 		/* Set Port Mode */
86944961713Sgirish 		if ((portmode == PORT_10G_FIBER) ||
8702e59129aSraghus 		    (portmode == PORT_10G_COPPER) ||
8712e59129aSraghus 		    (portmode == PORT_10G_SERDES)) {
87244961713Sgirish 			SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
87344961713Sgirish 						MAC_XGMII_MODE, rs);
87444961713Sgirish 			if (rs != NPI_SUCCESS)
87544961713Sgirish 				goto fail;
87644961713Sgirish 			if (statsp->mac_stats.link_up) {
87744961713Sgirish 				if (nxge_10g_link_led_on(nxgep) != NXGE_OK)
87844961713Sgirish 					goto fail;
87944961713Sgirish 			} else {
88044961713Sgirish 				if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
88144961713Sgirish 					goto fail;
88244961713Sgirish 			}
88344961713Sgirish 		} else if ((portmode == PORT_1G_FIBER) ||
8842e59129aSraghus 		    (portmode == PORT_1G_COPPER) ||
885d81011f0Ssbehera 		    (portmode == PORT_1G_SERDES) ||
886d81011f0Ssbehera 		    (portmode == PORT_1G_RGMII_FIBER)) {
887d81011f0Ssbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
888d81011f0Ssbehera 			    "nxge_xif_init: Port[%d] Mode[%d] Speed[%d]",
889d81011f0Ssbehera 			    portn, portmode, statsp->mac_stats.link_speed));
89044961713Sgirish 			if (statsp->mac_stats.link_speed == 1000) {
89144961713Sgirish 				SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
89244961713Sgirish 							MAC_GMII_MODE, rs);
89344961713Sgirish 			} else {
89444961713Sgirish 				SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
89544961713Sgirish 							MAC_MII_MODE, rs);
89644961713Sgirish 			}
89744961713Sgirish 			if (rs != NPI_SUCCESS)
89844961713Sgirish 				goto fail;
89944961713Sgirish 		} else {
90044961713Sgirish 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
90144961713Sgirish 					"nxge_xif_init: Unknown port mode (%d)"
90244961713Sgirish 					" for port<%d>", portmode, portn));
90344961713Sgirish 			goto fail;
90444961713Sgirish 		}
90544961713Sgirish 
906d81011f0Ssbehera 		/* Enable ATCA mode */
907d81011f0Ssbehera 
90844961713Sgirish 	} else if (portt == PORT_TYPE_BMAC) {
90944961713Sgirish 
91044961713Sgirish 		/* Setup XIF Configuration for BMAC */
91144961713Sgirish 
912d81011f0Ssbehera 		if ((portmode == PORT_1G_COPPER) ||
913d81011f0Ssbehera 		    (portmode == PORT_1G_RGMII_FIBER)) {
91444961713Sgirish 			if (statsp->mac_stats.link_speed == 100)
91544961713Sgirish 				xif_cfg |= CFG_BMAC_XIF_SEL_CLK_25MHZ;
91644961713Sgirish 		}
91744961713Sgirish 
91844961713Sgirish 		if (statsp->port_stats.lb_mode == nxge_lb_mac1000)
91944961713Sgirish 			xif_cfg |= CFG_BMAC_XIF_LOOPBACK;
92044961713Sgirish 
92144961713Sgirish 		if (statsp->mac_stats.link_speed == 1000)
92244961713Sgirish 			xif_cfg |= CFG_BMAC_XIF_GMII_MODE;
92344961713Sgirish 
92444961713Sgirish 		xif_cfg |= CFG_BMAC_XIF_TX_OUTPUT;
92544961713Sgirish 
92644961713Sgirish 		rs = npi_bmac_xif_config(handle, INIT, portn, xif_cfg);
92744961713Sgirish 		if (rs != NPI_SUCCESS)
92844961713Sgirish 			goto fail;
92944961713Sgirish 		nxgep->mac.xif_config = xif_cfg;
93044961713Sgirish 	}
93144961713Sgirish 
93244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xif_init: port<%d>", portn));
93344961713Sgirish 	return (NXGE_OK);
93444961713Sgirish fail:
93544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
93644961713Sgirish 			"nxge_xif_init: Failed to initialize XIF port<%d>",
93744961713Sgirish 			portn));
93844961713Sgirish 	return (NXGE_ERROR | rs);
93944961713Sgirish }
94044961713Sgirish 
94144961713Sgirish /* Initialize the PCS sub-block in the MAC */
94244961713Sgirish 
94344961713Sgirish nxge_status_t
94444961713Sgirish nxge_pcs_init(p_nxge_t nxgep)
94544961713Sgirish {
94644961713Sgirish 	pcs_cfg_t		pcs_cfg;
94744961713Sgirish 	uint32_t		val;
94844961713Sgirish 	uint8_t			portn;
94944961713Sgirish 	nxge_port_mode_t	portmode;
95044961713Sgirish 	npi_handle_t		handle;
95144961713Sgirish 	p_nxge_stats_t		statsp;
95244961713Sgirish 	npi_status_t		rs = NPI_SUCCESS;
95344961713Sgirish 
95444961713Sgirish 	handle = nxgep->npi_handle;
95544961713Sgirish 	portmode = nxgep->mac.portmode;
95644961713Sgirish 	portn = nxgep->mac.portnum;
95744961713Sgirish 	statsp = nxgep->statsp;
95844961713Sgirish 
95944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_init: port<%d>", portn));
96044961713Sgirish 
9612e59129aSraghus 	if ((portmode == PORT_1G_FIBER) || (portmode == PORT_1G_SERDES)) {
9622e59129aSraghus 		if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS) {
9632e59129aSraghus 			goto fail;
9642e59129aSraghus 		}
9652e59129aSraghus 
96644961713Sgirish 		/* Initialize port's PCS */
96744961713Sgirish 		pcs_cfg.value = 0;
96844961713Sgirish 		pcs_cfg.bits.w0.enable = 1;
96944961713Sgirish 		pcs_cfg.bits.w0.mask = 1;
97044961713Sgirish 		PCS_REG_WR(handle, portn, PCS_CONFIG_REG, pcs_cfg.value);
97144961713Sgirish 		PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 0);
97244961713Sgirish 
9732e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
9742e59129aSraghus 		    "==> nxge_pcs_init: (1G) port<%d> write config 0x%llx",
9752e59129aSraghus 		    portn, pcs_cfg.value));
97644961713Sgirish 	} else if ((portmode == PORT_10G_FIBER) ||
9772e59129aSraghus 	    (portmode == PORT_10G_COPPER) || (portmode == PORT_10G_SERDES)) {
97844961713Sgirish 		/* Use internal XPCS, bypass 1G PCS */
97944961713Sgirish 		XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val);
98044961713Sgirish 		val &= ~XMAC_XIF_XPCS_BYPASS;
98144961713Sgirish 		XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val);
98244961713Sgirish 
98344961713Sgirish 		if ((rs = npi_xmac_xpcs_reset(handle, portn)) != NPI_SUCCESS)
98444961713Sgirish 			goto fail;
98544961713Sgirish 
98644961713Sgirish 		/* Set XPCS Internal Loopback if necessary */
98744961713Sgirish 		if ((rs = npi_xmac_xpcs_read(handle, portn,
98844961713Sgirish 						XPCS_REG_CONTROL1, &val))
98944961713Sgirish 						!= NPI_SUCCESS)
99044961713Sgirish 			goto fail;
99144961713Sgirish 		if ((statsp->port_stats.lb_mode == nxge_lb_mac10g) ||
99244961713Sgirish 			(statsp->port_stats.lb_mode == nxge_lb_mac1000))
99344961713Sgirish 			val |= XPCS_CTRL1_LOOPBK;
99444961713Sgirish 		else
99544961713Sgirish 			val &= ~XPCS_CTRL1_LOOPBK;
99644961713Sgirish 		if ((rs = npi_xmac_xpcs_write(handle, portn,
99744961713Sgirish 						XPCS_REG_CONTROL1, val))
99844961713Sgirish 						!= NPI_SUCCESS)
99944961713Sgirish 			goto fail;
100044961713Sgirish 
100144961713Sgirish 		/* Clear descw errors */
100244961713Sgirish 		if ((rs = npi_xmac_xpcs_write(handle, portn,
100344961713Sgirish 						XPCS_REG_DESCWERR_COUNTER, 0))
100444961713Sgirish 						!= NPI_SUCCESS)
100544961713Sgirish 			goto fail;
100644961713Sgirish 		/* Clear symbol errors */
100744961713Sgirish 		if ((rs = npi_xmac_xpcs_read(handle, portn,
100844961713Sgirish 					XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val))
100944961713Sgirish 					!= NPI_SUCCESS)
101044961713Sgirish 			goto fail;
101144961713Sgirish 		if ((rs = npi_xmac_xpcs_read(handle, portn,
101244961713Sgirish 					XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val))
101344961713Sgirish 					!= NPI_SUCCESS)
101444961713Sgirish 			goto fail;
101544961713Sgirish 
1016d81011f0Ssbehera 	} else if ((portmode == PORT_1G_COPPER) ||
1017d81011f0Ssbehera 	    (portmode == PORT_1G_RGMII_FIBER)) {
1018d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1019d81011f0Ssbehera 		    "==> nxge_pcs_init: (1G) copper port<%d>", portn));
102044961713Sgirish 		if (portn < 4) {
102144961713Sgirish 			PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG,
102244961713Sgirish 					PCS_DATAPATH_MODE_MII);
102344961713Sgirish 		}
102444961713Sgirish 		if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS)
102544961713Sgirish 			goto fail;
102644961713Sgirish 
102744961713Sgirish 	} else {
102844961713Sgirish 		goto fail;
102944961713Sgirish 	}
103044961713Sgirish pass:
103144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_init: port<%d>", portn));
103244961713Sgirish 	return (NXGE_OK);
103344961713Sgirish fail:
103444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
103544961713Sgirish 			"nxge_pcs_init: Failed to initialize PCS port<%d>",
103644961713Sgirish 			portn));
103744961713Sgirish 	return (NXGE_ERROR | rs);
103844961713Sgirish }
103944961713Sgirish 
1040cb9d3ae6Smisaki /*
1041cb9d3ae6Smisaki  * Initialize the MAC CTRL sub-block within the MAC
1042cb9d3ae6Smisaki  * Only the receive-pause-cap is supported.
1043cb9d3ae6Smisaki  */
1044cb9d3ae6Smisaki nxge_status_t
1045cb9d3ae6Smisaki nxge_mac_ctrl_init(p_nxge_t nxgep)
1046cb9d3ae6Smisaki {
1047cb9d3ae6Smisaki 	uint8_t			portn;
1048cb9d3ae6Smisaki 	nxge_port_t		portt;
1049cb9d3ae6Smisaki 	p_nxge_stats_t		statsp;
1050cb9d3ae6Smisaki 	npi_handle_t		handle;
1051cb9d3ae6Smisaki 	uint32_t		val;
1052cb9d3ae6Smisaki 
1053cb9d3ae6Smisaki 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
1054cb9d3ae6Smisaki 
1055cb9d3ae6Smisaki 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_ctrl_init: port<%d>",
1056cb9d3ae6Smisaki 	    portn));
1057cb9d3ae6Smisaki 
1058cb9d3ae6Smisaki 	handle = nxgep->npi_handle;
1059cb9d3ae6Smisaki 	portt = nxgep->mac.porttype;
1060cb9d3ae6Smisaki 	statsp = nxgep->statsp;
1061cb9d3ae6Smisaki 
1062cb9d3ae6Smisaki 	if (portt == PORT_TYPE_XMAC) {
1063cb9d3ae6Smisaki 		/* Readin the current XMAC Config Register for XMAC */
1064cb9d3ae6Smisaki 		XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val);
1065cb9d3ae6Smisaki 
1066cb9d3ae6Smisaki 		/*
1067cb9d3ae6Smisaki 		 * Setup XMAC Configuration for XMAC
1068cb9d3ae6Smisaki 		 * XMAC only supports receive-pause
1069cb9d3ae6Smisaki 		 */
1070cb9d3ae6Smisaki 		if (statsp->mac_stats.adv_cap_asmpause) {
1071cb9d3ae6Smisaki 			if (!statsp->mac_stats.adv_cap_pause) {
1072cb9d3ae6Smisaki 				/*
1073cb9d3ae6Smisaki 				 * If adv_cap_asmpause is 1 and adv_cap_pause
1074cb9d3ae6Smisaki 				 * is 0, enable receive pause.
1075cb9d3ae6Smisaki 				 */
1076cb9d3ae6Smisaki 				val |= XMAC_RX_CFG_RX_PAUSE_EN;
1077cb9d3ae6Smisaki 			} else {
1078cb9d3ae6Smisaki 				/*
1079cb9d3ae6Smisaki 				 * If adv_cap_asmpause is 1 and adv_cap_pause
1080cb9d3ae6Smisaki 				 * is 1, disable receive pause.  Send pause is
1081cb9d3ae6Smisaki 				 * not supported.
1082cb9d3ae6Smisaki 				 */
1083cb9d3ae6Smisaki 				val &= ~XMAC_RX_CFG_RX_PAUSE_EN;
1084cb9d3ae6Smisaki 			}
1085cb9d3ae6Smisaki 		} else {
1086cb9d3ae6Smisaki 			if (statsp->mac_stats.adv_cap_pause) {
1087cb9d3ae6Smisaki 				/*
1088cb9d3ae6Smisaki 				 * If adv_cap_asmpause is 0 and adv_cap_pause
1089cb9d3ae6Smisaki 				 * is 1, enable receive pause.
1090cb9d3ae6Smisaki 				 */
1091cb9d3ae6Smisaki 				val |= XMAC_RX_CFG_RX_PAUSE_EN;
1092cb9d3ae6Smisaki 			} else {
1093cb9d3ae6Smisaki 				/*
1094cb9d3ae6Smisaki 				 * If adv_cap_asmpause is 0 and adv_cap_pause
1095cb9d3ae6Smisaki 				 * is 0, disable receive pause. Send pause is
1096cb9d3ae6Smisaki 				 * not supported
1097cb9d3ae6Smisaki 				 */
1098cb9d3ae6Smisaki 				val &= ~XMAC_RX_CFG_RX_PAUSE_EN;
1099cb9d3ae6Smisaki 			}
1100cb9d3ae6Smisaki 		}
1101cb9d3ae6Smisaki 		XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val);
1102cb9d3ae6Smisaki 	} else if (portt == PORT_TYPE_BMAC) {
1103cb9d3ae6Smisaki 		/* Readin the current MAC CTRL Config Register for BMAC */
1104cb9d3ae6Smisaki 		BMAC_REG_RD(handle, portn, MAC_CTRL_CONFIG_REG, &val);
1105cb9d3ae6Smisaki 
1106cb9d3ae6Smisaki 		/* Setup MAC CTRL Configuration for BMAC */
1107cb9d3ae6Smisaki 		if (statsp->mac_stats.adv_cap_asmpause) {
1108cb9d3ae6Smisaki 			if (statsp->mac_stats.adv_cap_pause) {
1109cb9d3ae6Smisaki 				/*
1110cb9d3ae6Smisaki 				 * If adv_cap_asmpause is 1 and adv_cap_pause
1111cb9d3ae6Smisaki 				 * is 1, disable receive pause. Send pause
1112cb9d3ae6Smisaki 				 * is not supported
1113cb9d3ae6Smisaki 				 */
1114cb9d3ae6Smisaki 				val &= ~MAC_CTRL_CFG_RECV_PAUSE_EN;
1115cb9d3ae6Smisaki 			} else {
1116cb9d3ae6Smisaki 				/*
1117cb9d3ae6Smisaki 				 * If adv_cap_asmpause is 1 and adv_cap_pause
1118cb9d3ae6Smisaki 				 * is 0, enable receive pause and disable
1119cb9d3ae6Smisaki 				 * send pause.
1120cb9d3ae6Smisaki 				 */
1121cb9d3ae6Smisaki 				val |= MAC_CTRL_CFG_RECV_PAUSE_EN;
1122cb9d3ae6Smisaki 				val &= ~MAC_CTRL_CFG_SEND_PAUSE_EN;
1123cb9d3ae6Smisaki 			}
1124cb9d3ae6Smisaki 		} else {
1125cb9d3ae6Smisaki 			if (statsp->mac_stats.adv_cap_pause) {
1126cb9d3ae6Smisaki 				/*
1127cb9d3ae6Smisaki 				 * If adv_cap_asmpause is 0 and adv_cap_pause
1128cb9d3ae6Smisaki 				 * is 1, enable receive pause. Send pause is
1129cb9d3ae6Smisaki 				 * not supported.
1130cb9d3ae6Smisaki 				 */
1131cb9d3ae6Smisaki 				val |= MAC_CTRL_CFG_RECV_PAUSE_EN;
1132cb9d3ae6Smisaki 			} else {
1133cb9d3ae6Smisaki 				/*
1134cb9d3ae6Smisaki 				 * If adv_cap_asmpause is 0 and adv_cap_pause
1135cb9d3ae6Smisaki 				 * is 0, pause capability is not available in
1136cb9d3ae6Smisaki 				 * either direction.
1137cb9d3ae6Smisaki 				 */
1138cb9d3ae6Smisaki 				val &= (~MAC_CTRL_CFG_SEND_PAUSE_EN &
1139cb9d3ae6Smisaki 					~MAC_CTRL_CFG_RECV_PAUSE_EN);
1140cb9d3ae6Smisaki 			}
1141cb9d3ae6Smisaki 		}
1142cb9d3ae6Smisaki 		BMAC_REG_WR(handle, portn, MAC_CTRL_CONFIG_REG, val);
1143cb9d3ae6Smisaki 	}
1144cb9d3ae6Smisaki 
1145cb9d3ae6Smisaki 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_ctrl_init: port<%d>",
1146cb9d3ae6Smisaki 	    portn));
1147cb9d3ae6Smisaki 
1148cb9d3ae6Smisaki 	return (NXGE_OK);
1149cb9d3ae6Smisaki }
1150cb9d3ae6Smisaki 
115144961713Sgirish /* Initialize the Internal Serdes */
115244961713Sgirish 
115344961713Sgirish nxge_status_t
115444961713Sgirish nxge_serdes_init(p_nxge_t nxgep)
115544961713Sgirish {
115644961713Sgirish 	p_nxge_stats_t		statsp;
115744961713Sgirish #ifdef	NXGE_DEBUG
115844961713Sgirish 	uint8_t			portn;
115944961713Sgirish #endif
116044961713Sgirish 	nxge_status_t		status = NXGE_OK;
116144961713Sgirish 
116244961713Sgirish #ifdef	NXGE_DEBUG
116344961713Sgirish 	portn = nxgep->mac.portnum;
116444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
116559ac0c16Sdavemq 	    "==> nxge_serdes_init port<%d>", portn));
116644961713Sgirish #endif
116744961713Sgirish 
116859ac0c16Sdavemq 	if (nxgep->xcvr.serdes_init) {
116959ac0c16Sdavemq 		statsp = nxgep->statsp;
117059ac0c16Sdavemq 		status = nxgep->xcvr.serdes_init(nxgep);
117159ac0c16Sdavemq 		if (status != NXGE_OK)
117244961713Sgirish 			goto fail;
117359ac0c16Sdavemq 		statsp->mac_stats.serdes_inits++;
117444961713Sgirish 	}
117544961713Sgirish 
117644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_serdes_init port<%d>",
117759ac0c16Sdavemq 	    portn));
117844961713Sgirish 
117944961713Sgirish 	return (NXGE_OK);
118044961713Sgirish 
118144961713Sgirish fail:
118244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
118359ac0c16Sdavemq 	    "nxge_serdes_init: Failed to initialize serdes for port<%d>",
118459ac0c16Sdavemq 	    portn));
118544961713Sgirish 
118644961713Sgirish 	return (status);
118744961713Sgirish }
118844961713Sgirish 
118944961713Sgirish /* Initialize the TI Hedwig Internal Serdes (N2-NIU only) */
119044961713Sgirish 
119159ac0c16Sdavemq static nxge_status_t
119244961713Sgirish nxge_n2_serdes_init(p_nxge_t nxgep)
119344961713Sgirish {
119444961713Sgirish 	uint8_t portn;
119544961713Sgirish 	int chan;
119644961713Sgirish 	esr_ti_cfgpll_l_t pll_cfg_l;
11972e59129aSraghus 	esr_ti_cfgpll_l_t pll_sts_l;
119844961713Sgirish 	esr_ti_cfgrx_l_t rx_cfg_l;
119944961713Sgirish 	esr_ti_cfgrx_h_t rx_cfg_h;
120044961713Sgirish 	esr_ti_cfgtx_l_t tx_cfg_l;
120144961713Sgirish 	esr_ti_cfgtx_h_t tx_cfg_h;
12022e59129aSraghus #ifdef NXGE_DEBUG
12032e59129aSraghus 	esr_ti_testcfg_t cfg;
12042e59129aSraghus #endif
120544961713Sgirish 	esr_ti_testcfg_t test_cfg;
120644961713Sgirish 	nxge_status_t status = NXGE_OK;
120744961713Sgirish 
120844961713Sgirish 	portn = nxgep->mac.portnum;
120944961713Sgirish 
121044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_n2_serdes_init port<%d>",
121144961713Sgirish 			portn));
121244961713Sgirish 
121344961713Sgirish 	tx_cfg_l.value = 0;
121444961713Sgirish 	tx_cfg_h.value = 0;
121544961713Sgirish 	rx_cfg_l.value = 0;
121644961713Sgirish 	rx_cfg_h.value = 0;
121744961713Sgirish 	pll_cfg_l.value = 0;
12182e59129aSraghus 	pll_sts_l.value = 0;
121944961713Sgirish 	test_cfg.value = 0;
122044961713Sgirish 
12212e59129aSraghus 	if ((nxgep->mac.portmode == PORT_10G_FIBER) ||
12222e59129aSraghus 	    (nxgep->mac.portmode == PORT_10G_SERDES)) {
122344961713Sgirish 		/* 0x0E01 */
122444961713Sgirish 		tx_cfg_l.bits.entx = 1;
122544961713Sgirish 		tx_cfg_l.bits.swing = CFGTX_SWING_1375MV;
122644961713Sgirish 
122744961713Sgirish 		/* 0x9101 */
122844961713Sgirish 		rx_cfg_l.bits.enrx = 1;
122944961713Sgirish 		rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT;
123044961713Sgirish 		rx_cfg_l.bits.align = CFGRX_ALIGN_EN;
123144961713Sgirish 		rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES;
123244961713Sgirish 
123344961713Sgirish 		/* 0x0008 */
123444961713Sgirish 		rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF;
123544961713Sgirish 
123644961713Sgirish 		/* Set loopback mode if necessary */
123744961713Sgirish 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
123844961713Sgirish 			tx_cfg_l.bits.entest = 1;
123944961713Sgirish 			rx_cfg_l.bits.entest = 1;
124044961713Sgirish 			test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK;
124144961713Sgirish 			if ((status = nxge_mdio_write(nxgep, portn,
124244961713Sgirish 				ESR_N2_DEV_ADDR,
124344961713Sgirish 				ESR_N2_TEST_CFG_REG, test_cfg.value))
124444961713Sgirish 				!= NXGE_OK)
124544961713Sgirish 			goto fail;
124644961713Sgirish 		}
124744961713Sgirish 
124844961713Sgirish 		/* Use default PLL value */
124944961713Sgirish 
12502e59129aSraghus 	} else if ((nxgep->mac.portmode == PORT_1G_FIBER) ||
12512e59129aSraghus 	    (nxgep->mac.portmode == PORT_1G_SERDES)) {
125244961713Sgirish 
125344961713Sgirish 		/* 0x0E21 */
125444961713Sgirish 		tx_cfg_l.bits.entx = 1;
125544961713Sgirish 		tx_cfg_l.bits.rate = CFGTX_RATE_HALF;
125644961713Sgirish 		tx_cfg_l.bits.swing = CFGTX_SWING_1375MV;
125744961713Sgirish 
125844961713Sgirish 		/* 0x9121 */
125944961713Sgirish 		rx_cfg_l.bits.enrx = 1;
126044961713Sgirish 		rx_cfg_l.bits.rate = CFGRX_RATE_HALF;
126144961713Sgirish 		rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT;
126244961713Sgirish 		rx_cfg_l.bits.align = CFGRX_ALIGN_EN;
126344961713Sgirish 		rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES;
126444961713Sgirish 
12652e59129aSraghus 		if (portn == 0) {
12662e59129aSraghus 			/* 0x8 */
12672e59129aSraghus 			rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF;
12682e59129aSraghus 		}
126944961713Sgirish 
127044961713Sgirish 		/* MPY = 0x100 */
127144961713Sgirish 		pll_cfg_l.bits.mpy = CFGPLL_MPY_8X;
127244961713Sgirish 
127344961713Sgirish 		/* Set PLL */
127444961713Sgirish 		pll_cfg_l.bits.enpll = 1;
12752e59129aSraghus 		pll_sts_l.bits.enpll = 1;
127644961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
127744961713Sgirish 				ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value))
127844961713Sgirish 				!= NXGE_OK)
127944961713Sgirish 			goto fail;
12802e59129aSraghus 
12812e59129aSraghus 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
12822e59129aSraghus 		    ESR_N2_PLL_STS_L_REG, pll_sts_l.value)) != NXGE_OK)
12832e59129aSraghus 			goto fail;
12842e59129aSraghus 
12852e59129aSraghus #ifdef  NXGE_DEBUG
12862e59129aSraghus 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
12872e59129aSraghus 		    ESR_N2_PLL_CFG_L_REG, &cfg.value);
12882e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
12892e59129aSraghus 		    "==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)",
12902e59129aSraghus 		    portn, pll_cfg_l.value, cfg.value));
12912e59129aSraghus 
12922e59129aSraghus 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
12932e59129aSraghus 		    ESR_N2_PLL_STS_L_REG, &cfg.value);
12942e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
12952e59129aSraghus 		    "==> nxge_n2_serdes_init port<%d>: PLL sts.l 0x%x (0x%x)",
12962e59129aSraghus 		    portn, pll_sts_l.value, cfg.value));
12972e59129aSraghus #endif
12982e59129aSraghus 
12992e59129aSraghus 		/* Set loopback mode if necessary */
13002e59129aSraghus 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) {
13012e59129aSraghus 			tx_cfg_l.bits.entest = 1;
13022e59129aSraghus 			rx_cfg_l.bits.entest = 1;
13032e59129aSraghus 			test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK;
13042e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
13052e59129aSraghus 			    "==> nxge_n2_serdes_init port<%d>: loopback 0x%x",
13062e59129aSraghus 			    portn, test_cfg.value));
13072e59129aSraghus 			if ((status = nxge_mdio_write(nxgep, portn,
13082e59129aSraghus 			    ESR_N2_DEV_ADDR,
13092e59129aSraghus 			    ESR_N2_TEST_CFG_REG, test_cfg.value)) != NXGE_OK) {
13102e59129aSraghus 				goto fail;
13112e59129aSraghus 			}
13122e59129aSraghus 		}
131344961713Sgirish 	} else {
131444961713Sgirish 		goto fail;
131544961713Sgirish 	}
131644961713Sgirish 
131744961713Sgirish 	/*   MIF_REG_WR(handle, MIF_MASK_REG, ~mask); */
131844961713Sgirish 
131944961713Sgirish 	NXGE_DELAY(20);
132044961713Sgirish 
132144961713Sgirish 	/* init TX channels */
132244961713Sgirish 	for (chan = 0; chan < 4; chan++) {
132344961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
132444961713Sgirish 				ESR_N2_TX_CFG_L_REG_ADDR(chan), tx_cfg_l.value))
132544961713Sgirish 				!= NXGE_OK)
132644961713Sgirish 			goto fail;
132744961713Sgirish 
132844961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
132944961713Sgirish 				ESR_N2_TX_CFG_H_REG_ADDR(chan), tx_cfg_h.value))
133044961713Sgirish 				!= NXGE_OK)
133144961713Sgirish 			goto fail;
13322e59129aSraghus 
13332e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
13342e59129aSraghus 		    "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_l 0x%x",
13352e59129aSraghus 		    portn, chan, tx_cfg_l.value));
13362e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
13372e59129aSraghus 		    "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_h 0x%x",
13382e59129aSraghus 		    portn, chan, tx_cfg_h.value));
133944961713Sgirish 	}
134044961713Sgirish 
134144961713Sgirish 	/* init RX channels */
134244961713Sgirish 	for (chan = 0; chan < 4; chan++) {
134344961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
134444961713Sgirish 				ESR_N2_RX_CFG_L_REG_ADDR(chan), rx_cfg_l.value))
134544961713Sgirish 				!= NXGE_OK)
134644961713Sgirish 			goto fail;
134744961713Sgirish 
134844961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
134944961713Sgirish 				ESR_N2_RX_CFG_H_REG_ADDR(chan), rx_cfg_h.value))
135044961713Sgirish 				!= NXGE_OK)
135144961713Sgirish 			goto fail;
13522e59129aSraghus 
13532e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
13542e59129aSraghus 		    "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_l 0x%x",
13552e59129aSraghus 		    portn, chan, rx_cfg_l.value));
13562e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
13572e59129aSraghus 		    "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_h 0x%x",
13582e59129aSraghus 		    portn, chan, rx_cfg_h.value));
135944961713Sgirish 	}
136044961713Sgirish 
136144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_n2_serdes_init port<%d>",
136244961713Sgirish 			portn));
136344961713Sgirish 
136444961713Sgirish 	return (NXGE_OK);
136544961713Sgirish fail:
13662d17280bSsbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
13672d17280bSsbehera 	    "nxge_n2_serdes_init: Failed to initialize N2 serdes for port<%d>",
13682d17280bSsbehera 	    portn));
136944961713Sgirish 
137044961713Sgirish 	return (status);
137144961713Sgirish }
137244961713Sgirish 
137359ac0c16Sdavemq /* Initialize the Neptune Internal Serdes for 10G (Neptune only) */
137444961713Sgirish 
137559ac0c16Sdavemq static nxge_status_t
137659ac0c16Sdavemq nxge_neptune_10G_serdes_init(p_nxge_t nxgep)
137744961713Sgirish {
137844961713Sgirish 	npi_handle_t		handle;
137944961713Sgirish 	uint8_t			portn;
1380*321febdeSsbehera 	int			chan, i;
138144961713Sgirish 	sr_rx_tx_ctrl_l_t	rx_tx_ctrl_l;
138244961713Sgirish 	sr_rx_tx_ctrl_h_t	rx_tx_ctrl_h;
138344961713Sgirish 	sr_glue_ctrl0_l_t	glue_ctrl0_l;
138444961713Sgirish 	sr_glue_ctrl0_h_t	glue_ctrl0_h;
138544961713Sgirish 	uint64_t		val;
138644961713Sgirish 	uint16_t		val16l;
138744961713Sgirish 	uint16_t		val16h;
138844961713Sgirish 	nxge_status_t		status = NXGE_OK;
138944961713Sgirish 
139044961713Sgirish 	portn = nxgep->mac.portnum;
139144961713Sgirish 
139244961713Sgirish 	if ((portn != 0) && (portn != 1))
139344961713Sgirish 		return (NXGE_OK);
139444961713Sgirish 
139559ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
139659ac0c16Sdavemq 	    "==> nxge_neptune_10G_serdes_init port<%d>", portn));
139744961713Sgirish 
139844961713Sgirish 	handle = nxgep->npi_handle;
139959ac0c16Sdavemq 	switch (portn) {
140059ac0c16Sdavemq 	case 0:
14014202ea4bSsbehera 		/* Reset Serdes */
14024202ea4bSsbehera 		ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0);
14034202ea4bSsbehera 		NXGE_DELAY(20);
14044202ea4bSsbehera 		ESR_REG_WR(handle, ESR_RESET_REG, 0x0);
14054202ea4bSsbehera 		NXGE_DELAY(2000);
14064202ea4bSsbehera 
14074202ea4bSsbehera 		/* Configure Serdes to 10G mode */
14084202ea4bSsbehera 		ESR_REG_WR(handle, ESR_0_PLL_CONFIG_REG,
14094202ea4bSsbehera 		    ESR_PLL_CFG_10G_SERDES);
14104202ea4bSsbehera 
141159ac0c16Sdavemq 		ESR_REG_WR(handle, ESR_0_CONTROL_REG,
141259ac0c16Sdavemq 		    ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 |
141359ac0c16Sdavemq 		    ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 |
141459ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) |
141559ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) |
141659ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) |
141759ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
141859ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
141959ac0c16Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_0_SHIFT) |
142059ac0c16Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_1_SHIFT) |
142159ac0c16Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_2_SHIFT) |
142259ac0c16Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_3_SHIFT));
142359ac0c16Sdavemq 
142459ac0c16Sdavemq 		/* Set Serdes0 Internal Loopback if necessary */
142559ac0c16Sdavemq 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
142659ac0c16Sdavemq 			ESR_REG_WR(handle,
142759ac0c16Sdavemq 			    ESR_0_TEST_CONFIG_REG,
142859ac0c16Sdavemq 			    ESR_PAD_LOOPBACK_CH3 |
142959ac0c16Sdavemq 			    ESR_PAD_LOOPBACK_CH2 |
143059ac0c16Sdavemq 			    ESR_PAD_LOOPBACK_CH1 |
143159ac0c16Sdavemq 			    ESR_PAD_LOOPBACK_CH0);
143259ac0c16Sdavemq 		} else {
143359ac0c16Sdavemq 			ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0);
143444961713Sgirish 		}
143559ac0c16Sdavemq 		break;
143659ac0c16Sdavemq 	case 1:
14374202ea4bSsbehera 		/* Reset Serdes */
14384202ea4bSsbehera 		ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_1);
14394202ea4bSsbehera 		NXGE_DELAY(20);
14404202ea4bSsbehera 		ESR_REG_WR(handle, ESR_RESET_REG, 0x0);
14414202ea4bSsbehera 		NXGE_DELAY(2000);
14424202ea4bSsbehera 
14434202ea4bSsbehera 		/* Configure Serdes to 10G mode */
14444202ea4bSsbehera 		ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG,
14454202ea4bSsbehera 		    ESR_PLL_CFG_10G_SERDES);
14464202ea4bSsbehera 
144759ac0c16Sdavemq 		ESR_REG_WR(handle, ESR_1_CONTROL_REG,
144859ac0c16Sdavemq 		    ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 |
144959ac0c16Sdavemq 		    ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 |
145059ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) |
145159ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) |
145259ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) |
145359ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
145459ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
145559ac0c16Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_0_SHIFT) |
145659ac0c16Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_1_SHIFT) |
145759ac0c16Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_2_SHIFT) |
145859ac0c16Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_3_SHIFT));
145959ac0c16Sdavemq 
146059ac0c16Sdavemq 		/* Set Serdes1 Internal Loopback if necessary */
146159ac0c16Sdavemq 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
146259ac0c16Sdavemq 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG,
146359ac0c16Sdavemq 			    ESR_PAD_LOOPBACK_CH3 | ESR_PAD_LOOPBACK_CH2 |
146459ac0c16Sdavemq 			    ESR_PAD_LOOPBACK_CH1 | ESR_PAD_LOOPBACK_CH0);
146559ac0c16Sdavemq 		} else {
146659ac0c16Sdavemq 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0);
146744961713Sgirish 		}
146859ac0c16Sdavemq 		break;
146959ac0c16Sdavemq 	default:
147059ac0c16Sdavemq 		/* Nothing to do here */
147159ac0c16Sdavemq 		goto done;
147259ac0c16Sdavemq 	}
147344961713Sgirish 
147459ac0c16Sdavemq 	/* init TX RX channels */
147559ac0c16Sdavemq 	for (chan = 0; chan < 4; chan++) {
147659ac0c16Sdavemq 		if ((status = nxge_mdio_read(nxgep, portn,
147759ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
147859ac0c16Sdavemq 		    &rx_tx_ctrl_l.value)) != NXGE_OK)
147944961713Sgirish 			goto fail;
148059ac0c16Sdavemq 		if ((status = nxge_mdio_read(nxgep, portn,
148159ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
148259ac0c16Sdavemq 		    &rx_tx_ctrl_h.value)) != NXGE_OK)
148344961713Sgirish 			goto fail;
148459ac0c16Sdavemq 		if ((status = nxge_mdio_read(nxgep, portn,
148559ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
148659ac0c16Sdavemq 		    &glue_ctrl0_l.value)) != NXGE_OK)
148759ac0c16Sdavemq 			goto fail;
148859ac0c16Sdavemq 		if ((status = nxge_mdio_read(nxgep, portn,
148959ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
149059ac0c16Sdavemq 		    &glue_ctrl0_h.value)) != NXGE_OK)
149159ac0c16Sdavemq 			goto fail;
149259ac0c16Sdavemq 		rx_tx_ctrl_l.bits.enstretch = 1;
149359ac0c16Sdavemq 		rx_tx_ctrl_h.bits.vmuxlo = 2;
149459ac0c16Sdavemq 		rx_tx_ctrl_h.bits.vpulselo = 2;
149559ac0c16Sdavemq 		glue_ctrl0_l.bits.rxlosenable = 1;
149659ac0c16Sdavemq 		glue_ctrl0_l.bits.samplerate = 0xF;
149759ac0c16Sdavemq 		glue_ctrl0_l.bits.thresholdcount = 0xFF;
149859ac0c16Sdavemq 		glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES;
149944961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn,
150059ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
150159ac0c16Sdavemq 		    rx_tx_ctrl_l.value)) != NXGE_OK)
150244961713Sgirish 			goto fail;
150344961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn,
150459ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
150559ac0c16Sdavemq 		    rx_tx_ctrl_h.value)) != NXGE_OK)
150644961713Sgirish 			goto fail;
150759ac0c16Sdavemq 		if ((status = nxge_mdio_write(nxgep, portn,
150859ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
150959ac0c16Sdavemq 		    glue_ctrl0_l.value)) != NXGE_OK)
151044961713Sgirish 			goto fail;
151159ac0c16Sdavemq 		if ((status = nxge_mdio_write(nxgep, portn,
151259ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
151359ac0c16Sdavemq 		    glue_ctrl0_h.value)) != NXGE_OK)
151444961713Sgirish 			goto fail;
151544961713Sgirish 		}
151644961713Sgirish 
151759ac0c16Sdavemq 	/* Apply Tx core reset */
151859ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn,
151959ac0c16Sdavemq 	    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(),
152059ac0c16Sdavemq 	    (uint16_t)0)) != NXGE_OK)
152159ac0c16Sdavemq 		goto fail;
152259ac0c16Sdavemq 
152359ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
152459ac0c16Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) !=
152559ac0c16Sdavemq 	    NXGE_OK)
152659ac0c16Sdavemq 		goto fail;
152759ac0c16Sdavemq 
152859ac0c16Sdavemq 	NXGE_DELAY(200);
152959ac0c16Sdavemq 
153059ac0c16Sdavemq 	/* Apply Rx core reset */
153159ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
153259ac0c16Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) !=
153359ac0c16Sdavemq 	    NXGE_OK)
153459ac0c16Sdavemq 		goto fail;
153559ac0c16Sdavemq 
153659ac0c16Sdavemq 	NXGE_DELAY(200);
153759ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
153859ac0c16Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK)
153959ac0c16Sdavemq 		goto fail;
154059ac0c16Sdavemq 
154159ac0c16Sdavemq 	NXGE_DELAY(200);
154259ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, portn,
154359ac0c16Sdavemq 	    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(),
154459ac0c16Sdavemq 	    &val16l)) != NXGE_OK)
154559ac0c16Sdavemq 		goto fail;
154659ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
154759ac0c16Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK)
154859ac0c16Sdavemq 		goto fail;
154959ac0c16Sdavemq 	if ((val16l != 0) || (val16h != 0)) {
155059ac0c16Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1551d81011f0Ssbehera 		    "Failed to reset port<%d> XAUI Serdes "
1552d81011f0Ssbehera 		    "(val16l 0x%x val16h 0x%x)",
1553d81011f0Ssbehera 		    portn, val16l, val16h));
155459ac0c16Sdavemq 	}
155559ac0c16Sdavemq 
155659ac0c16Sdavemq 	if (portn == 0) {
1557*321febdeSsbehera 		/* Wait for serdes to be ready */
1558*321febdeSsbehera 		for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) {
1559*321febdeSsbehera 			ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
1560*321febdeSsbehera 			if ((val & ESR_SIG_P0_BITS_MASK) !=
1561*321febdeSsbehera 			    (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0 |
1562*321febdeSsbehera 			    ESR_SIG_XSERDES_RDY_P0 |
1563*321febdeSsbehera 			    ESR_SIG_XDETECT_P0_CH3 |
1564*321febdeSsbehera 			    ESR_SIG_XDETECT_P0_CH2 |
1565*321febdeSsbehera 			    ESR_SIG_XDETECT_P0_CH1 |
1566*321febdeSsbehera 			    ESR_SIG_XDETECT_P0_CH0))
1567*321febdeSsbehera 
1568*321febdeSsbehera 				NXGE_DELAY(SERDES_RDY_WT_INTERVAL);
1569*321febdeSsbehera 			else
1570*321febdeSsbehera 				break;
1571*321febdeSsbehera 		}
1572*321febdeSsbehera 
1573*321febdeSsbehera 		if (i == MAX_SERDES_RDY_RETRIES) {
1574*321febdeSsbehera 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1575*321febdeSsbehera 			    "nxge_neptune_10G_serdes_init: "
1576*321febdeSsbehera 			    "Serdes/signal for port<%d> not ready", portn));
1577*321febdeSsbehera 				goto fail;
157859ac0c16Sdavemq 		}
157959ac0c16Sdavemq 	} else if (portn == 1) {
1580*321febdeSsbehera 		/* Wait for serdes to be ready */
1581*321febdeSsbehera 		for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) {
1582*321febdeSsbehera 			ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
1583*321febdeSsbehera 			if ((val & ESR_SIG_P1_BITS_MASK) !=
1584*321febdeSsbehera 			    (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1 |
1585*321febdeSsbehera 			    ESR_SIG_XSERDES_RDY_P1 |
1586*321febdeSsbehera 			    ESR_SIG_XDETECT_P1_CH3 |
1587*321febdeSsbehera 			    ESR_SIG_XDETECT_P1_CH2 |
1588*321febdeSsbehera 			    ESR_SIG_XDETECT_P1_CH1 |
1589*321febdeSsbehera 			    ESR_SIG_XDETECT_P1_CH0))
1590*321febdeSsbehera 
1591*321febdeSsbehera 				NXGE_DELAY(SERDES_RDY_WT_INTERVAL);
1592*321febdeSsbehera 			else
1593*321febdeSsbehera 				break;
1594*321febdeSsbehera 		}
1595*321febdeSsbehera 
1596*321febdeSsbehera 		if (i == MAX_SERDES_RDY_RETRIES) {
1597*321febdeSsbehera 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1598*321febdeSsbehera 			    "nxge_neptune_10G_serdes_init: "
1599*321febdeSsbehera 			    "Serdes/signal for port<%d> not ready", portn));
1600*321febdeSsbehera 				goto fail;
160144961713Sgirish 		}
160244961713Sgirish 	}
160344961713Sgirish 
160444961713Sgirish done:
160559ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
160659ac0c16Sdavemq 	    "<== nxge_neptune_10G_serdes_init port<%d>", portn));
160759ac0c16Sdavemq 
160844961713Sgirish 	return (NXGE_OK);
160944961713Sgirish fail:
16102d17280bSsbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
161159ac0c16Sdavemq 	    "nxge_neptune_10G_serdes_init: "
161259ac0c16Sdavemq 	    "Failed to initialize Neptune serdes for port<%d>", portn));
161344961713Sgirish 
161444961713Sgirish 	return (status);
161544961713Sgirish }
161644961713Sgirish 
161759ac0c16Sdavemq /* Initialize Neptune Internal Serdes for 1G (Neptune only) */
161844961713Sgirish 
161959ac0c16Sdavemq static nxge_status_t
162059ac0c16Sdavemq nxge_1G_serdes_init(p_nxge_t nxgep)
162144961713Sgirish {
162259ac0c16Sdavemq 	npi_handle_t		handle;
162359ac0c16Sdavemq 	uint8_t			portn;
1624d81011f0Ssbehera 	int			chan;
1625d81011f0Ssbehera 	sr_rx_tx_ctrl_l_t	rx_tx_ctrl_l;
1626d81011f0Ssbehera 	sr_rx_tx_ctrl_h_t	rx_tx_ctrl_h;
1627d81011f0Ssbehera 	sr_glue_ctrl0_l_t	glue_ctrl0_l;
1628d81011f0Ssbehera 	sr_glue_ctrl0_h_t	glue_ctrl0_h;
162959ac0c16Sdavemq 	uint64_t		val;
1630d81011f0Ssbehera 	uint16_t		val16l;
1631d81011f0Ssbehera 	uint16_t		val16h;
1632d81011f0Ssbehera 	nxge_status_t		status = NXGE_OK;
163344961713Sgirish 
163444961713Sgirish 	portn = nxgep->mac.portnum;
163544961713Sgirish 
163659ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
163759ac0c16Sdavemq 	    "==> nxge_1G_serdes_init port<%d>", portn));
163844961713Sgirish 
163959ac0c16Sdavemq 	handle = nxgep->npi_handle;
164044961713Sgirish 
164159ac0c16Sdavemq 	switch (portn) {
164259ac0c16Sdavemq 	case 0:
1643d81011f0Ssbehera 		/* Assert the reset register */
1644d81011f0Ssbehera 		ESR_REG_RD(handle, ESR_RESET_REG, &val);
1645d81011f0Ssbehera 		val |= ESR_RESET_0;
1646d81011f0Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, val);
1647d81011f0Ssbehera 
1648d81011f0Ssbehera 		/* Set the PLL register to 0x79 */
1649d81011f0Ssbehera 		ESR_REG_WR(handle, ESR_0_PLL_CONFIG_REG,
1650d81011f0Ssbehera 		    ESR_PLL_CFG_1G_SERDES);
1651d81011f0Ssbehera 
1652d81011f0Ssbehera 		/* Set the control register to 0x249249f */
1653d81011f0Ssbehera 		ESR_REG_WR(handle, ESR_0_CONTROL_REG, ESR_CTL_1G_SERDES);
1654d81011f0Ssbehera 
1655d81011f0Ssbehera 		/* Set Serdes0 Internal Loopback if necessary */
1656d81011f0Ssbehera 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) {
1657d81011f0Ssbehera 			/* Set pad loopback modes 0xaa */
1658d81011f0Ssbehera 			ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG,
1659d81011f0Ssbehera 			    ESR_TSTCFG_LBTEST_PAD);
1660d81011f0Ssbehera 		} else {
1661d81011f0Ssbehera 			ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0);
1662d81011f0Ssbehera 		}
1663d81011f0Ssbehera 
1664d81011f0Ssbehera 		/* Deassert the reset register */
1665d81011f0Ssbehera 		ESR_REG_RD(handle, ESR_RESET_REG, &val);
1666d81011f0Ssbehera 		val &= ~ESR_RESET_0;
1667d81011f0Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, val);
166859ac0c16Sdavemq 		break;
1669d81011f0Ssbehera 
167059ac0c16Sdavemq 	case 1:
1671d81011f0Ssbehera 		/* Assert the reset register */
1672d81011f0Ssbehera 		ESR_REG_RD(handle, ESR_RESET_REG, &val);
1673d81011f0Ssbehera 		val |= ESR_RESET_1;
1674d81011f0Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, val);
1675d81011f0Ssbehera 
1676d81011f0Ssbehera 		/* Set PLL register to 0x79 */
1677d81011f0Ssbehera 		ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG,
1678d81011f0Ssbehera 		    ESR_PLL_CFG_1G_SERDES);
1679d81011f0Ssbehera 
1680d81011f0Ssbehera 		/* Set the control register to 0x249249f */
1681d81011f0Ssbehera 		ESR_REG_WR(handle, ESR_1_CONTROL_REG, ESR_CTL_1G_SERDES);
1682d81011f0Ssbehera 
1683d81011f0Ssbehera 		/* Set Serdes1 Internal Loopback if necessary */
1684d81011f0Ssbehera 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) {
1685d81011f0Ssbehera 			/* Set pad loopback mode 0xaa */
1686d81011f0Ssbehera 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG,
1687d81011f0Ssbehera 			    ESR_TSTCFG_LBTEST_PAD);
1688d81011f0Ssbehera 		} else {
1689d81011f0Ssbehera 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0);
1690d81011f0Ssbehera 		}
1691d81011f0Ssbehera 
1692d81011f0Ssbehera 		/* Deassert the reset register */
1693d81011f0Ssbehera 		ESR_REG_RD(handle, ESR_RESET_REG, &val);
1694d81011f0Ssbehera 		val &= ~ESR_RESET_1;
1695d81011f0Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, val);
169659ac0c16Sdavemq 		break;
1697d81011f0Ssbehera 
169859ac0c16Sdavemq 	default:
1699d81011f0Ssbehera 		/* Nothing to do here */
1700d81011f0Ssbehera 		goto done;
1701d81011f0Ssbehera 	}
1702d81011f0Ssbehera 
1703d81011f0Ssbehera 	/* init TX RX channels */
1704d81011f0Ssbehera 	for (chan = 0; chan < 4; chan++) {
1705d81011f0Ssbehera 		if ((status = nxge_mdio_read(nxgep, portn,
1706d81011f0Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
1707d81011f0Ssbehera 		    &rx_tx_ctrl_l.value)) != NXGE_OK) {
1708d81011f0Ssbehera 			goto fail;
1709d81011f0Ssbehera 		}
1710d81011f0Ssbehera 		if ((status = nxge_mdio_read(nxgep, portn,
1711d81011f0Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
1712d81011f0Ssbehera 		    &rx_tx_ctrl_h.value)) != NXGE_OK) {
1713d81011f0Ssbehera 			goto fail;
1714d81011f0Ssbehera 		}
1715d81011f0Ssbehera 		if ((status = nxge_mdio_read(nxgep, portn,
1716d81011f0Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
1717d81011f0Ssbehera 		    &glue_ctrl0_l.value)) != NXGE_OK) {
1718d81011f0Ssbehera 			goto fail;
1719d81011f0Ssbehera 		}
1720d81011f0Ssbehera 		if ((status = nxge_mdio_read(nxgep, portn,
1721d81011f0Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
1722d81011f0Ssbehera 		    &glue_ctrl0_h.value)) != NXGE_OK) {
1723d81011f0Ssbehera 			goto fail;
1724d81011f0Ssbehera 		}
1725d81011f0Ssbehera 
1726d81011f0Ssbehera 		rx_tx_ctrl_l.bits.enstretch = 1;
1727d81011f0Ssbehera 		rx_tx_ctrl_h.bits.vmuxlo = 2;
1728d81011f0Ssbehera 		rx_tx_ctrl_h.bits.vpulselo = 2;
1729d81011f0Ssbehera 		glue_ctrl0_l.bits.rxlosenable = 1;
1730d81011f0Ssbehera 		glue_ctrl0_l.bits.samplerate = 0xF;
1731d81011f0Ssbehera 		glue_ctrl0_l.bits.thresholdcount = 0xFF;
1732d81011f0Ssbehera 		glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES;
1733d81011f0Ssbehera 		if ((status = nxge_mdio_write(nxgep, portn,
1734d81011f0Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
1735d81011f0Ssbehera 		    rx_tx_ctrl_l.value)) != NXGE_OK) {
1736d81011f0Ssbehera 			goto fail;
1737d81011f0Ssbehera 		}
1738d81011f0Ssbehera 		if ((status = nxge_mdio_write(nxgep, portn,
1739d81011f0Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
1740d81011f0Ssbehera 		    rx_tx_ctrl_h.value)) != NXGE_OK) {
1741d81011f0Ssbehera 			goto fail;
1742d81011f0Ssbehera 		}
1743d81011f0Ssbehera 		if ((status = nxge_mdio_write(nxgep, portn,
1744d81011f0Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
1745d81011f0Ssbehera 		    glue_ctrl0_l.value)) != NXGE_OK) {
1746d81011f0Ssbehera 			goto fail;
1747d81011f0Ssbehera 		}
1748d81011f0Ssbehera 		if ((status = nxge_mdio_write(nxgep, portn,
1749d81011f0Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
1750d81011f0Ssbehera 		    glue_ctrl0_h.value)) != NXGE_OK) {
1751d81011f0Ssbehera 			goto fail;
1752d81011f0Ssbehera 		}
1753d81011f0Ssbehera 	}
1754d81011f0Ssbehera 
1755d81011f0Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
1756d81011f0Ssbehera 	    ESR_NEP_RX_POWER_CONTROL_L_ADDR(), 0xfff)) != NXGE_OK) {
1757d81011f0Ssbehera 		goto fail;
1758d81011f0Ssbehera 	}
1759d81011f0Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
1760d81011f0Ssbehera 	    ESR_NEP_RX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) {
1761d81011f0Ssbehera 		goto fail;
1762d81011f0Ssbehera 	}
1763d81011f0Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
1764d81011f0Ssbehera 	    ESR_NEP_TX_POWER_CONTROL_L_ADDR(), 0x70)) != NXGE_OK) {
1765d81011f0Ssbehera 		goto fail;
1766d81011f0Ssbehera 	}
1767d81011f0Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
1768d81011f0Ssbehera 	    ESR_NEP_TX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) {
176959ac0c16Sdavemq 		goto fail;
177044961713Sgirish 	}
177144961713Sgirish 
1772d81011f0Ssbehera 	/* Apply Tx core reset */
1773d81011f0Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
1774d81011f0Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0)) != NXGE_OK) {
1775d81011f0Ssbehera 		goto fail;
1776d81011f0Ssbehera 	}
1777d81011f0Ssbehera 
1778d81011f0Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
1779d81011f0Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) !=
1780d81011f0Ssbehera 	    NXGE_OK) {
1781d81011f0Ssbehera 		goto fail;
1782d81011f0Ssbehera 	}
1783d81011f0Ssbehera 
1784d81011f0Ssbehera 	NXGE_DELAY(200);
1785d81011f0Ssbehera 
1786d81011f0Ssbehera 	/* Apply Rx core reset */
1787d81011f0Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
1788d81011f0Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) !=
1789d81011f0Ssbehera 	    NXGE_OK) {
1790d81011f0Ssbehera 		goto fail;
1791d81011f0Ssbehera 	}
1792d81011f0Ssbehera 
1793d81011f0Ssbehera 	NXGE_DELAY(200);
1794d81011f0Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
1795d81011f0Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK) {
1796d81011f0Ssbehera 		goto fail;
1797d81011f0Ssbehera 	}
1798d81011f0Ssbehera 
1799d81011f0Ssbehera 	NXGE_DELAY(200);
1800d81011f0Ssbehera 	if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
1801d81011f0Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), &val16l)) != NXGE_OK) {
1802d81011f0Ssbehera 		goto fail;
1803d81011f0Ssbehera 	}
1804d81011f0Ssbehera 	if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
1805d81011f0Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK) {
1806d81011f0Ssbehera 		goto fail;
1807d81011f0Ssbehera 	}
1808d81011f0Ssbehera 	if ((val16l != 0) || (val16h != 0)) {
1809d81011f0Ssbehera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1810d81011f0Ssbehera 		    "Failed to reset port<%d> XAUI Serdes "
1811d81011f0Ssbehera 		    "(val16l 0x%x val16h 0x%x)", portn, val16l, val16h));
1812d81011f0Ssbehera 		status = NXGE_ERROR;
1813d81011f0Ssbehera 		goto fail;
1814d81011f0Ssbehera 	}
1815d81011f0Ssbehera 
1816d81011f0Ssbehera 	NXGE_DELAY(200);
1817d81011f0Ssbehera 	ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
1818d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1819d81011f0Ssbehera 	    "nxge_neptune_serdes_init: read internal signal reg port<%d> "
1820d81011f0Ssbehera 	    "val 0x%x", portn, val));
1821d81011f0Ssbehera 	if (portn == 0) {
1822d81011f0Ssbehera 		if ((val & ESR_SIG_P0_BITS_MASK_1G) !=
1823d81011f0Ssbehera 		    (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0)) {
1824d81011f0Ssbehera 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1825d81011f0Ssbehera 			    "nxge_neptune_serdes_init: "
1826d81011f0Ssbehera 			    "Failed to get Serdes up for port<%d> val 0x%x",
1827d81011f0Ssbehera 			    portn, (val & ESR_SIG_P0_BITS_MASK)));
1828d81011f0Ssbehera 			status = NXGE_ERROR;
1829d81011f0Ssbehera 			goto fail;
1830d81011f0Ssbehera 		}
1831d81011f0Ssbehera 	} else if (portn == 1) {
1832d81011f0Ssbehera 		if ((val & ESR_SIG_P1_BITS_MASK_1G) !=
1833d81011f0Ssbehera 		    (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1)) {
1834d81011f0Ssbehera 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1835d81011f0Ssbehera 			    "nxge_neptune_serdes_init: "
1836d81011f0Ssbehera 			    "Failed to get Serdes up for port<%d> val 0x%x",
1837d81011f0Ssbehera 			    portn, (val & ESR_SIG_P1_BITS_MASK)));
1838d81011f0Ssbehera 			status = NXGE_ERROR;
1839d81011f0Ssbehera 			goto fail;
1840d81011f0Ssbehera 		}
1841d81011f0Ssbehera 	}
1842d81011f0Ssbehera done:
184359ac0c16Sdavemq 
184459ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
184559ac0c16Sdavemq 	    "<== nxge_1G_serdes_init port<%d>", portn));
184644961713Sgirish 	return (NXGE_OK);
184759ac0c16Sdavemq fail:
1848d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
184959ac0c16Sdavemq 	    "nxge_1G_serdes_init: "
185059ac0c16Sdavemq 	    "Failed to initialize Neptune serdes for port<%d>",
185159ac0c16Sdavemq 	    portn));
185259ac0c16Sdavemq 
1853d81011f0Ssbehera 	return (status);
185444961713Sgirish }
185544961713Sgirish 
18562d17280bSsbehera /* Initialize the BCM 8704 xcvr */
185744961713Sgirish 
185859ac0c16Sdavemq static nxge_status_t
18592d17280bSsbehera nxge_BCM8704_xcvr_init(p_nxge_t nxgep)
186044961713Sgirish {
186144961713Sgirish 	uint16_t		val;
186244961713Sgirish #ifdef	NXGE_DEBUG
186314ea4bb7Ssd 	uint8_t			portn;
186444961713Sgirish 	uint16_t		val1;
186544961713Sgirish #endif
186644961713Sgirish 	uint8_t			phy_port_addr;
186744961713Sgirish 	pmd_tx_control_t	tx_ctl;
186844961713Sgirish 	control_t		ctl;
186944961713Sgirish 	phyxs_control_t		phyxs_ctl;
187044961713Sgirish 	pcs_control_t		pcs_ctl;
187144961713Sgirish 	uint32_t		delay = 0;
187244961713Sgirish 	optics_dcntr_t		op_ctr;
187344961713Sgirish 	nxge_status_t		status = NXGE_OK;
187414ea4bb7Ssd #ifdef	NXGE_DEBUG
187544961713Sgirish 	portn = nxgep->mac.portnum;
187614ea4bb7Ssd #endif
18772d17280bSsbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>",
187859ac0c16Sdavemq 	    portn));
187944961713Sgirish 
188059ac0c16Sdavemq 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
188159ac0c16Sdavemq 
188259ac0c16Sdavemq 	/* Reset the transceiver */
188359ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
188459ac0c16Sdavemq 	    BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK)
188559ac0c16Sdavemq 		goto fail;
188659ac0c16Sdavemq 
188759ac0c16Sdavemq 	phyxs_ctl.bits.reset = 1;
188859ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
188959ac0c16Sdavemq 	    BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK)
189059ac0c16Sdavemq 		goto fail;
189159ac0c16Sdavemq 
189259ac0c16Sdavemq 	do {
189359ac0c16Sdavemq 		drv_usecwait(500);
189459ac0c16Sdavemq 		if ((status = nxge_mdio_read(nxgep, phy_port_addr,
189559ac0c16Sdavemq 		    BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG,
189659ac0c16Sdavemq 		    &phyxs_ctl.value)) != NXGE_OK)
189759ac0c16Sdavemq 			goto fail;
189859ac0c16Sdavemq 		delay++;
189959ac0c16Sdavemq 	} while ((phyxs_ctl.bits.reset) && (delay < 100));
190059ac0c16Sdavemq 	if (delay == 100) {
190159ac0c16Sdavemq 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: "
190259ac0c16Sdavemq 		    "failed to reset Transceiver on port<%d>", portn));
190359ac0c16Sdavemq 		status = NXGE_ERROR;
190459ac0c16Sdavemq 		goto fail;
190559ac0c16Sdavemq 	}
190644961713Sgirish 
190759ac0c16Sdavemq 	/* Set to 0x7FBF */
190859ac0c16Sdavemq 	ctl.value = 0;
190959ac0c16Sdavemq 	ctl.bits.res1 = 0x3F;
191059ac0c16Sdavemq 	ctl.bits.optxon_lvl = 1;
191159ac0c16Sdavemq 	ctl.bits.oprxflt_lvl = 1;
191259ac0c16Sdavemq 	ctl.bits.optrxlos_lvl = 1;
191359ac0c16Sdavemq 	ctl.bits.optxflt_lvl = 1;
191459ac0c16Sdavemq 	ctl.bits.opprflt_lvl = 1;
191559ac0c16Sdavemq 	ctl.bits.obtmpflt_lvl = 1;
191659ac0c16Sdavemq 	ctl.bits.opbiasflt_lvl = 1;
191759ac0c16Sdavemq 	ctl.bits.optxrst_lvl = 1;
191859ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
191959ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, ctl.value))
192059ac0c16Sdavemq 	    != NXGE_OK)
192159ac0c16Sdavemq 		goto fail;
192259ac0c16Sdavemq 
192359ac0c16Sdavemq 	/* Set to 0x164 */
192459ac0c16Sdavemq 	tx_ctl.value = 0;
192559ac0c16Sdavemq 	tx_ctl.bits.tsck_lpwren = 1;
192659ac0c16Sdavemq 	tx_ctl.bits.tx_dac_txck = 0x2;
192759ac0c16Sdavemq 	tx_ctl.bits.tx_dac_txd = 0x1;
192859ac0c16Sdavemq 	tx_ctl.bits.xfp_clken = 1;
192959ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
193059ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG,
193159ac0c16Sdavemq 	    tx_ctl.value)) != NXGE_OK)
193259ac0c16Sdavemq 		goto fail;
193344961713Sgirish 	/*
193459ac0c16Sdavemq 	 * According to Broadcom's instruction, SW needs to read
193559ac0c16Sdavemq 	 * back these registers twice after written.
193644961713Sgirish 	 */
193759ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
193859ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val))
193959ac0c16Sdavemq 	    != NXGE_OK)
194059ac0c16Sdavemq 		goto fail;
194144961713Sgirish 
194259ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
194359ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val))
194459ac0c16Sdavemq 	    != NXGE_OK)
194559ac0c16Sdavemq 		goto fail;
194644961713Sgirish 
194759ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
194859ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val))
194959ac0c16Sdavemq 	    != NXGE_OK)
195059ac0c16Sdavemq 		goto fail;
195144961713Sgirish 
195259ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
195359ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val))
195459ac0c16Sdavemq 	    != NXGE_OK)
195559ac0c16Sdavemq 		goto fail;
195644961713Sgirish 
195759ac0c16Sdavemq 	/* Enable Tx and Rx LEDs to be driven by traffic */
195859ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
195959ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
196059ac0c16Sdavemq 	    &op_ctr.value)) != NXGE_OK)
196159ac0c16Sdavemq 		goto fail;
1962cb9d3ae6Smisaki 	if (NXGE_IS_XAUI_PLATFORM(nxgep)) {
1963cb9d3ae6Smisaki 		op_ctr.bits.gpio_sel = 0x1;
1964cb9d3ae6Smisaki 	} else {
1965cb9d3ae6Smisaki 		op_ctr.bits.gpio_sel = 0x3;
1966cb9d3ae6Smisaki 	}
196759ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
196859ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
196959ac0c16Sdavemq 	    op_ctr.value)) != NXGE_OK)
197059ac0c16Sdavemq 		goto fail;
197144961713Sgirish 
197259ac0c16Sdavemq 	NXGE_DELAY(1000000);
197344961713Sgirish 
197459ac0c16Sdavemq 	/* Set BCM8704 Internal Loopback mode if necessary */
197559ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
197659ac0c16Sdavemq 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value))
197759ac0c16Sdavemq 	    != NXGE_OK)
197859ac0c16Sdavemq 		goto fail;
197959ac0c16Sdavemq 	if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
198059ac0c16Sdavemq 		pcs_ctl.bits.loopback = 1;
198159ac0c16Sdavemq 	else
198259ac0c16Sdavemq 		pcs_ctl.bits.loopback = 0;
198359ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
198459ac0c16Sdavemq 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value))
198559ac0c16Sdavemq 	    != NXGE_OK)
198659ac0c16Sdavemq 		goto fail;
198744961713Sgirish 
198859ac0c16Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x1, 0xA, &val);
198959ac0c16Sdavemq 	if (status != NXGE_OK)
199059ac0c16Sdavemq 		goto fail;
199159ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
199259ac0c16Sdavemq 	    "BCM8704 port<%d> Dev 1 Reg 0xA = 0x%x\n", portn, val));
199359ac0c16Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0x20, &val);
199459ac0c16Sdavemq 	if (status != NXGE_OK)
199559ac0c16Sdavemq 		goto fail;
199659ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
199759ac0c16Sdavemq 	    "BCM8704 port<%d> Dev 3 Reg 0x20 = 0x%x\n", portn, val));
199859ac0c16Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, &val);
199959ac0c16Sdavemq 	if (status != NXGE_OK)
200059ac0c16Sdavemq 		goto fail;
200159ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
200259ac0c16Sdavemq 	    "BCM8704 port<%d> Dev 4 Reg 0x18 = 0x%x\n", portn, val));
200344961713Sgirish 
200459ac0c16Sdavemq #ifdef	NXGE_DEBUG
200559ac0c16Sdavemq 	/* Diagnose link issue if link is not up */
200659ac0c16Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_USER_DEV3_ADDR,
200759ac0c16Sdavemq 	    BCM8704_USER_ANALOG_STATUS0_REG,
200859ac0c16Sdavemq 	    &val);
200959ac0c16Sdavemq 	if (status != NXGE_OK)
201059ac0c16Sdavemq 		goto fail;
201144961713Sgirish 
201259ac0c16Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr,
201344961713Sgirish 				BCM8704_USER_DEV3_ADDR,
201459ac0c16Sdavemq 				BCM8704_USER_ANALOG_STATUS0_REG,
201559ac0c16Sdavemq 				&val);
201659ac0c16Sdavemq 	if (status != NXGE_OK)
201759ac0c16Sdavemq 		goto fail;
201844961713Sgirish 
201959ac0c16Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr,
202044961713Sgirish 				BCM8704_USER_DEV3_ADDR,
202159ac0c16Sdavemq 				BCM8704_USER_TX_ALARM_STATUS_REG,
202259ac0c16Sdavemq 				&val1);
202359ac0c16Sdavemq 	if (status != NXGE_OK)
202459ac0c16Sdavemq 		goto fail;
202544961713Sgirish 
202659ac0c16Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr,
202744961713Sgirish 				BCM8704_USER_DEV3_ADDR,
202859ac0c16Sdavemq 				BCM8704_USER_TX_ALARM_STATUS_REG,
202959ac0c16Sdavemq 				&val1);
203059ac0c16Sdavemq 	if (status != NXGE_OK)
203159ac0c16Sdavemq 		goto fail;
203244961713Sgirish 
203359ac0c16Sdavemq 	if (val != 0x3FC) {
203459ac0c16Sdavemq 		if ((val == 0x43BC) && (val1 != 0)) {
203559ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
203659ac0c16Sdavemq 			    "Cable not connected to peer or bad"
203759ac0c16Sdavemq 			    " cable on port<%d>\n", portn));
203859ac0c16Sdavemq 		} else if (val == 0x639C) {
203959ac0c16Sdavemq 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
204059ac0c16Sdavemq 			    "Optical module (XFP) is bad or absent"
204159ac0c16Sdavemq 			    " on port<%d>\n", portn));
204259ac0c16Sdavemq 		}
204359ac0c16Sdavemq 	}
204459ac0c16Sdavemq #endif
204544961713Sgirish 
20462d17280bSsbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>",
20472d17280bSsbehera 	    portn));
20482d17280bSsbehera 	return (NXGE_OK);
20492d17280bSsbehera 
20502d17280bSsbehera fail:
20512d17280bSsbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
20522d17280bSsbehera 	    "nxge_BCM8704_xcvr_init: failed to initialize transceiver for "
20532d17280bSsbehera 	    "port<%d>", nxgep->mac.portnum));
20542d17280bSsbehera 	return (NXGE_ERROR);
20552d17280bSsbehera }
20562d17280bSsbehera 
20572d17280bSsbehera /* Initialize the BCM 8706 Transceiver */
20582d17280bSsbehera 
20592d17280bSsbehera static nxge_status_t
20602d17280bSsbehera nxge_BCM8706_xcvr_init(p_nxge_t nxgep)
20612d17280bSsbehera {
20622d17280bSsbehera 	uint8_t			phy_port_addr;
20632d17280bSsbehera 	phyxs_control_t		phyxs_ctl;
20642d17280bSsbehera 	pcs_control_t		pcs_ctl;
20652d17280bSsbehera 	uint32_t		delay = 0;
20662d17280bSsbehera 	optics_dcntr_t		op_ctr;
20672d17280bSsbehera 	nxge_status_t		status = NXGE_OK;
20682d17280bSsbehera #ifdef	NXGE_DEBUG
20692d17280bSsbehera 	uint8_t			portn = nxgep->mac.portnum;
20702d17280bSsbehera #endif
20712d17280bSsbehera 
20722d17280bSsbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>",
20732d17280bSsbehera 	    portn));
20742d17280bSsbehera 
20752d17280bSsbehera 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
20762d17280bSsbehera 
20772d17280bSsbehera 	/* Reset the transceiver */
20782d17280bSsbehera 	if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
20792d17280bSsbehera 	    BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK)
20802d17280bSsbehera 		goto fail;
20812d17280bSsbehera 
20822d17280bSsbehera 	phyxs_ctl.bits.reset = 1;
20832d17280bSsbehera 	if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
20842d17280bSsbehera 	    BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK)
20852d17280bSsbehera 		goto fail;
20862d17280bSsbehera 	do {
20872d17280bSsbehera 		drv_usecwait(500);
20882d17280bSsbehera 		if ((status = nxge_mdio_read(nxgep, phy_port_addr,
20892d17280bSsbehera 		    BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG,
20902d17280bSsbehera 		    &phyxs_ctl.value)) != NXGE_OK)
20912d17280bSsbehera 			goto fail;
20922d17280bSsbehera 		delay++;
20932d17280bSsbehera 	} while ((phyxs_ctl.bits.reset) && (delay < 100));
20942d17280bSsbehera 
20952d17280bSsbehera 	if (delay == 100) {
20962d17280bSsbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: "
20972d17280bSsbehera 		    "failed to reset Transceiver on port<%d>", portn));
20982d17280bSsbehera 		status = NXGE_ERROR;
20992d17280bSsbehera 		goto fail;
21002d17280bSsbehera 	}
21012d17280bSsbehera 
21022d17280bSsbehera 	NXGE_DELAY(1000000);
21032d17280bSsbehera 
21042d17280bSsbehera 	/* Set BCM8706 Internal Loopback mode if necessary */
21052d17280bSsbehera 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
21062d17280bSsbehera 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value))
21072d17280bSsbehera 	    != NXGE_OK)
21082d17280bSsbehera 		goto fail;
21092d17280bSsbehera 	if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
21102d17280bSsbehera 		pcs_ctl.bits.loopback = 1;
21112d17280bSsbehera 	else
21122d17280bSsbehera 		pcs_ctl.bits.loopback = 0;
21132d17280bSsbehera 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
21142d17280bSsbehera 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value))
21152d17280bSsbehera 	    != NXGE_OK)
21162d17280bSsbehera 		goto fail;
21172d17280bSsbehera 
21182d17280bSsbehera 	/* Enable Tx and Rx LEDs to be driven by traffic */
21192d17280bSsbehera 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
21202d17280bSsbehera 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
21212d17280bSsbehera 	    &op_ctr.value)) != NXGE_OK)
21222d17280bSsbehera 		goto fail;
21232d17280bSsbehera 	op_ctr.bits.gpio_sel = 0x3;
21242d17280bSsbehera 	op_ctr.bits.res2 = 0x1;
21252d17280bSsbehera 
21262d17280bSsbehera 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
21272d17280bSsbehera 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
21282d17280bSsbehera 	    op_ctr.value)) != NXGE_OK)
21292d17280bSsbehera 		goto fail;
21302d17280bSsbehera 
21312d17280bSsbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>",
21322d17280bSsbehera 	    portn));
21332d17280bSsbehera 	return (NXGE_OK);
21342d17280bSsbehera 
21352d17280bSsbehera fail:
21362d17280bSsbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
21372d17280bSsbehera 	    "nxge_BCM8706_xcvr_init: failed to initialize transceiver for "
21382d17280bSsbehera 	    "port<%d>", nxgep->mac.portnum));
21392d17280bSsbehera 	return (status);
21402d17280bSsbehera }
21412d17280bSsbehera 
21422d17280bSsbehera /* Initialize the 10G Transceiver */
21432d17280bSsbehera 
21442d17280bSsbehera static nxge_status_t
21452d17280bSsbehera nxge_10G_xcvr_init(p_nxge_t nxgep)
21462d17280bSsbehera {
21472d17280bSsbehera 	p_nxge_stats_t		statsp;
21482d17280bSsbehera 	nxge_status_t		status = NXGE_OK;
21492d17280bSsbehera #ifdef	NXGE_DEBUG
21502d17280bSsbehera 	uint8_t			portn = nxgep->mac.portnum;
21512d17280bSsbehera #endif
21522d17280bSsbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>",
21532d17280bSsbehera 	    portn));
21542d17280bSsbehera 
21552d17280bSsbehera 	statsp = nxgep->statsp;
21562d17280bSsbehera 
21572d17280bSsbehera 	if (nxgep->mac.portmode == PORT_10G_SERDES) {
21582d17280bSsbehera 		goto done;
21592d17280bSsbehera 	}
21602d17280bSsbehera 
21612d17280bSsbehera 	/* Disable Link LEDs */
21622d17280bSsbehera 	if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
21632d17280bSsbehera 		goto fail;
21642d17280bSsbehera 
21652d17280bSsbehera 	/* Set Clause 45 */
21662d17280bSsbehera 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE);
21672d17280bSsbehera 
21682d17280bSsbehera 	switch (nxgep->chip_id) {
21692d17280bSsbehera 	case BCM8704_CHIP_ID:
21702d17280bSsbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: "
21712d17280bSsbehera 		    "Chip ID 8704 [0x%x] for 10G xcvr", nxgep->chip_id));
21722d17280bSsbehera 		status = nxge_BCM8704_xcvr_init(nxgep);
21732d17280bSsbehera 		break;
21742d17280bSsbehera 	case BCM8706_CHIP_ID:
21752d17280bSsbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: "
21762d17280bSsbehera 		    "Chip ID 8706 [0x%x] for 10G xcvr", nxgep->chip_id));
21772d17280bSsbehera 		status = nxge_BCM8706_xcvr_init(nxgep);
21782d17280bSsbehera 		break;
21792d17280bSsbehera 	default:
21802d17280bSsbehera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_xcvr_init: "
21812d17280bSsbehera 		    "Unknown chip ID 0x%x for 10G xcvr addr[%d]",
21822d17280bSsbehera 		    nxgep->chip_id, nxgep->statsp->mac_stats.xcvr_portn));
21832d17280bSsbehera 		goto fail;
21842d17280bSsbehera 	}
21852d17280bSsbehera 
21862d17280bSsbehera 	if (status != NXGE_OK) {
21872d17280bSsbehera 		goto fail;
21882d17280bSsbehera 	}
21892e59129aSraghus done:
219059ac0c16Sdavemq 	statsp->mac_stats.cap_10gfdx = 1;
219159ac0c16Sdavemq 	statsp->mac_stats.lp_cap_10gfdx = 1;
219244961713Sgirish 
219359ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>",
219459ac0c16Sdavemq 	    portn));
219559ac0c16Sdavemq 	return (NXGE_OK);
219644961713Sgirish 
219759ac0c16Sdavemq fail:
21982d17280bSsbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
219959ac0c16Sdavemq 	    "nxge_10G_xcvr_init: failed to initialize transceiver for "
22002d17280bSsbehera 	    "port<%d>", nxgep->mac.portnum));
22012d17280bSsbehera 	return (NXGE_ERROR);
220259ac0c16Sdavemq }
220344961713Sgirish 
220459ac0c16Sdavemq /* Initialize the 1G copper (BCM 5464) Transceiver */
220544961713Sgirish 
220659ac0c16Sdavemq static nxge_status_t
220759ac0c16Sdavemq nxge_1G_xcvr_init(p_nxge_t nxgep)
220859ac0c16Sdavemq {
220959ac0c16Sdavemq 	p_nxge_param_t		param_arr = nxgep->param_arr;
221059ac0c16Sdavemq 	p_nxge_stats_t		statsp = nxgep->statsp;
221159ac0c16Sdavemq 	nxge_status_t		status = NXGE_OK;
221244961713Sgirish 
22132e59129aSraghus 	if (nxgep->mac.portmode == PORT_1G_SERDES) {
22142e59129aSraghus 		statsp->mac_stats.cap_1000fdx =
22152e59129aSraghus 		    param_arr[param_anar_1000fdx].value;
22162e59129aSraghus 		goto done;
22172e59129aSraghus 	}
22182e59129aSraghus 
221959ac0c16Sdavemq 	/* Set Clause 22 */
222059ac0c16Sdavemq 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_FALSE);
222144961713Sgirish 
222259ac0c16Sdavemq 	/* Set capability flags */
222359ac0c16Sdavemq 	statsp->mac_stats.cap_1000fdx = param_arr[param_anar_1000fdx].value;
22242e59129aSraghus 	if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
22252e59129aSraghus 	    (nxgep->mac.portmode == PORT_1G_FIBER)) {
22262e59129aSraghus 		statsp->mac_stats.cap_100fdx =
22272e59129aSraghus 		    param_arr[param_anar_100fdx].value;
22282e59129aSraghus 		statsp->mac_stats.cap_10fdx =
22292e59129aSraghus 		    param_arr[param_anar_10fdx].value;
22302e59129aSraghus 	}
223144961713Sgirish 
223259ac0c16Sdavemq 	status = nxge_mii_xcvr_init(nxgep);
22332e59129aSraghus done:
223459ac0c16Sdavemq 	return (status);
223559ac0c16Sdavemq }
223659ac0c16Sdavemq 
223759ac0c16Sdavemq /* Initialize transceiver */
223859ac0c16Sdavemq 
223959ac0c16Sdavemq nxge_status_t
224059ac0c16Sdavemq nxge_xcvr_init(p_nxge_t nxgep)
224159ac0c16Sdavemq {
224259ac0c16Sdavemq 	p_nxge_stats_t		statsp;
224359ac0c16Sdavemq #ifdef	NXGE_DEBUG
224459ac0c16Sdavemq 	uint8_t			portn;
224544961713Sgirish #endif
224644961713Sgirish 
224759ac0c16Sdavemq 	nxge_status_t		status = NXGE_OK;
224859ac0c16Sdavemq #ifdef	NXGE_DEBUG
224959ac0c16Sdavemq 	portn = nxgep->mac.portnum;
225059ac0c16Sdavemq #endif
225159ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", portn));
225259ac0c16Sdavemq 	statsp = nxgep->statsp;
225344961713Sgirish 
225459ac0c16Sdavemq 	/*
225559ac0c16Sdavemq 	 * Initialize the xcvr statistics.
225659ac0c16Sdavemq 	 */
225759ac0c16Sdavemq 	statsp->mac_stats.cap_autoneg = 0;
225859ac0c16Sdavemq 	statsp->mac_stats.cap_100T4 = 0;
225959ac0c16Sdavemq 	statsp->mac_stats.cap_100fdx = 0;
226059ac0c16Sdavemq 	statsp->mac_stats.cap_100hdx = 0;
226159ac0c16Sdavemq 	statsp->mac_stats.cap_10fdx = 0;
226259ac0c16Sdavemq 	statsp->mac_stats.cap_10hdx = 0;
226359ac0c16Sdavemq 	statsp->mac_stats.cap_asmpause = 0;
226459ac0c16Sdavemq 	statsp->mac_stats.cap_pause = 0;
226559ac0c16Sdavemq 	statsp->mac_stats.cap_1000fdx = 0;
226659ac0c16Sdavemq 	statsp->mac_stats.cap_1000hdx = 0;
226759ac0c16Sdavemq 	statsp->mac_stats.cap_10gfdx = 0;
226859ac0c16Sdavemq 	statsp->mac_stats.cap_10ghdx = 0;
226959ac0c16Sdavemq 
227059ac0c16Sdavemq 	/*
227159ac0c16Sdavemq 	 * Initialize the link statistics.
227259ac0c16Sdavemq 	 */
227359ac0c16Sdavemq 	statsp->mac_stats.link_T4 = 0;
227459ac0c16Sdavemq 	statsp->mac_stats.link_asmpause = 0;
227559ac0c16Sdavemq 	statsp->mac_stats.link_pause = 0;
227644961713Sgirish 
227759ac0c16Sdavemq 	if (nxgep->xcvr.xcvr_init) {
227859ac0c16Sdavemq 		status = nxgep->xcvr.xcvr_init(nxgep);
227959ac0c16Sdavemq 		if (status != NXGE_OK)
228044961713Sgirish 			goto fail;
228159ac0c16Sdavemq 		statsp->mac_stats.xcvr_inits++;
228244961713Sgirish 	}
228344961713Sgirish 
228459ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>",
228559ac0c16Sdavemq 	    portn));
228644961713Sgirish 	return (NXGE_OK);
228744961713Sgirish 
228844961713Sgirish fail:
228944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
229059ac0c16Sdavemq 	    "nxge_xcvr_init: failed to initialize transceiver for port<%d>",
229159ac0c16Sdavemq 	    portn));
229244961713Sgirish 	return (status);
229344961713Sgirish }
229444961713Sgirish 
22952e59129aSraghus /* Look for transceiver type */
22962e59129aSraghus 
22972e59129aSraghus nxge_status_t
22982e59129aSraghus nxge_xcvr_find(p_nxge_t nxgep)
22992e59129aSraghus {
2300d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_find: port<%d>",
2301d81011f0Ssbehera 	    nxgep->mac.portnum));
23022e59129aSraghus 
23032e59129aSraghus 	if (nxge_get_xcvr_type(nxgep) != NXGE_OK)
23042e59129aSraghus 		return (NXGE_ERROR);
23052e59129aSraghus 
23062e59129aSraghus 	if (nxge_setup_xcvr_table(nxgep) != NXGE_OK)
23072e59129aSraghus 		return (NXGE_ERROR);
23082e59129aSraghus 
23092e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xcvr_find: xcvr_inuse = %d",
23102e59129aSraghus 	    nxgep->statsp->mac_stats.xcvr_inuse));
23112e59129aSraghus 	return (NXGE_OK);
23122e59129aSraghus }
231344961713Sgirish 
231444961713Sgirish /* Initialize the TxMAC sub-block */
231544961713Sgirish 
231644961713Sgirish nxge_status_t
231744961713Sgirish nxge_tx_mac_init(p_nxge_t nxgep)
231844961713Sgirish {
231944961713Sgirish 	npi_attr_t		ap;
232044961713Sgirish 	uint8_t			portn;
232144961713Sgirish 	nxge_port_mode_t	portmode;
232244961713Sgirish 	nxge_port_t		portt;
232344961713Sgirish 	npi_handle_t		handle;
232444961713Sgirish 	npi_status_t		rs = NPI_SUCCESS;
232544961713Sgirish 
232644961713Sgirish 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
232744961713Sgirish 	portt    = nxgep->mac.porttype;
232844961713Sgirish 	handle   = nxgep->npi_handle;
232944961713Sgirish 	portmode = nxgep->mac.portmode;
233044961713Sgirish 
233144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_init: port<%d>",
233244961713Sgirish 			portn));
233344961713Sgirish 
233444961713Sgirish 	/* Set Max and Min Frame Size */
233514ea4bb7Ssd 	if (nxgep->param_arr[param_accept_jumbo].value || nxge_jumbo_enable) {
233644961713Sgirish 		SET_MAC_ATTR2(handle, ap, portn,
23374202ea4bSsbehera 		    MAC_PORT_FRAME_SIZE, 64, nxge_jumbo_mtu, rs);
233844961713Sgirish 	} else {
23394202ea4bSsbehera 		/*
23404202ea4bSsbehera 		 * Set the maxframe size to 1522 (1518 + 4) to account for
23414202ea4bSsbehera 		 * VLAN tagged packets
23424202ea4bSsbehera 		 */
234344961713Sgirish 		SET_MAC_ATTR2(handle, ap, portn,
23444202ea4bSsbehera 		    MAC_PORT_FRAME_SIZE, 64, 0x5EE + 4, rs);
234544961713Sgirish 	}
234644961713Sgirish 
234744961713Sgirish 	if (rs != NPI_SUCCESS)
234844961713Sgirish 		goto fail;
234914ea4bb7Ssd 	if (nxgep->param_arr[param_accept_jumbo].value ||
235014ea4bb7Ssd 		nxgep->mac.is_jumbo == B_TRUE)
23514202ea4bSsbehera 		nxgep->mac.maxframesize = (uint16_t)nxge_jumbo_mtu;
235244961713Sgirish 	else
235344961713Sgirish 		nxgep->mac.maxframesize = 0x5EE + 4;
235444961713Sgirish 	nxgep->mac.minframesize = 64;
235544961713Sgirish 
235644961713Sgirish 	if (portt == PORT_TYPE_XMAC) {
235744961713Sgirish 		if ((rs = npi_xmac_tx_iconfig(handle, INIT, portn,
235844961713Sgirish 				0)) != NPI_SUCCESS)
235944961713Sgirish 			goto fail;
236044961713Sgirish 		nxgep->mac.tx_iconfig = NXGE_XMAC_TX_INTRS;
236144961713Sgirish 		if ((portmode == PORT_10G_FIBER) ||
23622e59129aSraghus 		    (portmode == PORT_10G_COPPER) ||
23632e59129aSraghus 		    (portmode == PORT_10G_SERDES)) {
236444961713Sgirish 			SET_MAC_ATTR1(handle, ap, portn, XMAC_10G_PORT_IPG,
236544961713Sgirish 					XGMII_IPG_12_15, rs);
236644961713Sgirish 			if (rs != NPI_SUCCESS)
236744961713Sgirish 				goto fail;
236844961713Sgirish 			nxgep->mac.ipg[0] = XGMII_IPG_12_15;
236944961713Sgirish 		} else {
237044961713Sgirish 			SET_MAC_ATTR1(handle, ap, portn, XMAC_PORT_IPG,
237144961713Sgirish 					MII_GMII_IPG_12, rs);
237244961713Sgirish 			if (rs != NPI_SUCCESS)
237344961713Sgirish 				goto fail;
237444961713Sgirish 			nxgep->mac.ipg[0] = MII_GMII_IPG_12;
237544961713Sgirish 		}
237644961713Sgirish 		if ((rs = npi_xmac_tx_config(handle, INIT, portn,
237744961713Sgirish 				CFG_XMAC_TX_CRC | CFG_XMAC_TX)) != NPI_SUCCESS)
237844961713Sgirish 			goto fail;
237944961713Sgirish 		nxgep->mac.tx_config = CFG_XMAC_TX_CRC | CFG_XMAC_TX;
238044961713Sgirish 		nxgep->mac.maxburstsize = 0;	/* not programmable */
238144961713Sgirish 		nxgep->mac.ctrltype = 0;	/* not programmable */
238244961713Sgirish 		nxgep->mac.pa_size = 0;		/* not programmable */
238344961713Sgirish 
238444961713Sgirish 		if ((rs = npi_xmac_zap_tx_counters(handle, portn))
238544961713Sgirish 							!= NPI_SUCCESS)
238644961713Sgirish 			goto fail;
238744961713Sgirish 
238844961713Sgirish 	} else {
238944961713Sgirish 		if ((rs = npi_bmac_tx_iconfig(handle, INIT, portn,
239044961713Sgirish 				0)) != NPI_SUCCESS)
239144961713Sgirish 			goto fail;
239244961713Sgirish 		nxgep->mac.tx_iconfig = NXGE_BMAC_TX_INTRS;
239344961713Sgirish 
239444961713Sgirish 		SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_CTRL_TYPE, 0x8808,
239544961713Sgirish 				rs);
239644961713Sgirish 		if (rs != NPI_SUCCESS)
239744961713Sgirish 			goto fail;
239844961713Sgirish 		nxgep->mac.ctrltype = 0x8808;
239944961713Sgirish 
240044961713Sgirish 		SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_PA_SIZE, 0x7, rs);
240144961713Sgirish 		if (rs != NPI_SUCCESS)
240244961713Sgirish 			goto fail;
240344961713Sgirish 		nxgep->mac.pa_size = 0x7;
240444961713Sgirish 
240544961713Sgirish 		if ((rs = npi_bmac_tx_config(handle, INIT, portn,
240644961713Sgirish 				CFG_BMAC_TX_CRC | CFG_BMAC_TX)) != NPI_SUCCESS)
240744961713Sgirish 			goto fail;
240844961713Sgirish 		nxgep->mac.tx_config = CFG_BMAC_TX_CRC | CFG_BMAC_TX;
240944961713Sgirish 	}
241044961713Sgirish 
241144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_init: port<%d>",
241244961713Sgirish 			portn));
241344961713Sgirish 
241444961713Sgirish 	return (NXGE_OK);
241544961713Sgirish fail:
241644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
241744961713Sgirish 		"nxge_tx_mac_init: failed to initialize port<%d> TXMAC",
241844961713Sgirish 					portn));
241944961713Sgirish 
242044961713Sgirish 	return (NXGE_ERROR | rs);
242144961713Sgirish }
242244961713Sgirish 
242344961713Sgirish /* Initialize the RxMAC sub-block */
242444961713Sgirish 
242544961713Sgirish nxge_status_t
242644961713Sgirish nxge_rx_mac_init(p_nxge_t nxgep)
242744961713Sgirish {
242844961713Sgirish 	npi_attr_t		ap;
242944961713Sgirish 	uint32_t		i;
243044961713Sgirish 	uint16_t		hashtab_e;
243144961713Sgirish 	p_hash_filter_t		hash_filter;
243244961713Sgirish 	nxge_port_t		portt;
243344961713Sgirish 	uint8_t			portn;
243444961713Sgirish 	npi_handle_t		handle;
243544961713Sgirish 	npi_status_t		rs = NPI_SUCCESS;
243644961713Sgirish 	uint16_t 		*addr16p;
243744961713Sgirish 	uint16_t 		addr0, addr1, addr2;
243844961713Sgirish 	xmac_rx_config_t	xconfig;
243944961713Sgirish 	bmac_rx_config_t	bconfig;
244044961713Sgirish 
244144961713Sgirish 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
244244961713Sgirish 
244344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_init: port<%d>\n",
244444961713Sgirish 			portn));
244544961713Sgirish 	handle = nxgep->npi_handle;
244644961713Sgirish 	portt = nxgep->mac.porttype;
244744961713Sgirish 
244844961713Sgirish 	addr16p = (uint16_t *)nxgep->ouraddr.ether_addr_octet;
244944961713Sgirish 	addr0 = ntohs(addr16p[2]);
245044961713Sgirish 	addr1 = ntohs(addr16p[1]);
245144961713Sgirish 	addr2 = ntohs(addr16p[0]);
245244961713Sgirish 	SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR, addr0, addr1, addr2,
245344961713Sgirish 		rs);
245444961713Sgirish 
245544961713Sgirish 	if (rs != NPI_SUCCESS)
245644961713Sgirish 		goto fail;
245744961713Sgirish 	SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR_FILTER, 0, 0, 0, rs);
245844961713Sgirish 	if (rs != NPI_SUCCESS)
245944961713Sgirish 		goto fail;
246044961713Sgirish 	SET_MAC_ATTR2(handle, ap, portn, MAC_PORT_ADDR_FILTER_MASK, 0, 0, rs);
246144961713Sgirish 	if (rs != NPI_SUCCESS)
246244961713Sgirish 		goto fail;
246344961713Sgirish 
246444961713Sgirish 	/*
246544961713Sgirish 	 * Load the multicast hash filter bits.
246644961713Sgirish 	 */
246744961713Sgirish 	hash_filter = nxgep->hash_filter;
246844961713Sgirish 	for (i = 0; i < MAC_MAX_HASH_ENTRY; i++) {
246944961713Sgirish 		if (hash_filter != NULL) {
247044961713Sgirish 			hashtab_e = (uint16_t)hash_filter->hash_filter_regs[
247144961713Sgirish 				(NMCFILTER_REGS - 1) - i];
247244961713Sgirish 		} else {
247344961713Sgirish 			hashtab_e = 0;
247444961713Sgirish 		}
247544961713Sgirish 
247644961713Sgirish 		if ((rs = npi_mac_hashtab_entry(handle, OP_SET, portn, i,
247744961713Sgirish 					(uint16_t *)&hashtab_e)) != NPI_SUCCESS)
247844961713Sgirish 			goto fail;
247944961713Sgirish 	}
248044961713Sgirish 
248144961713Sgirish 	if (portt == PORT_TYPE_XMAC) {
248244961713Sgirish 		if ((rs = npi_xmac_rx_iconfig(handle, INIT, portn,
248344961713Sgirish 				0)) != NPI_SUCCESS)
248444961713Sgirish 			goto fail;
248544961713Sgirish 		nxgep->mac.rx_iconfig = NXGE_XMAC_RX_INTRS;
248644961713Sgirish 
248744961713Sgirish 		(void) nxge_fflp_init_hostinfo(nxgep);
248844961713Sgirish 
248944961713Sgirish 		xconfig = CFG_XMAC_RX_ERRCHK | CFG_XMAC_RX_CRC_CHK |
2490a3c5bd6dSspeer 			CFG_XMAC_RX | CFG_XMAC_RX_CODE_VIO_CHK &
2491a3c5bd6dSspeer 			~CFG_XMAC_RX_STRIP_CRC;
249244961713Sgirish 
249344961713Sgirish 		if (nxgep->filter.all_phys_cnt != 0)
249444961713Sgirish 			xconfig |= CFG_XMAC_RX_PROMISCUOUS;
249544961713Sgirish 
249644961713Sgirish 		if (nxgep->filter.all_multicast_cnt != 0)
249744961713Sgirish 			xconfig |= CFG_XMAC_RX_PROMISCUOUSGROUP;
249844961713Sgirish 
249944961713Sgirish 		xconfig |= CFG_XMAC_RX_HASH_FILTER;
250044961713Sgirish 
250144961713Sgirish 		if ((rs = npi_xmac_rx_config(handle, INIT, portn,
250244961713Sgirish 					xconfig)) != NPI_SUCCESS)
250344961713Sgirish 			goto fail;
250444961713Sgirish 		nxgep->mac.rx_config = xconfig;
250544961713Sgirish 
250644961713Sgirish 		/* Comparison of mac unique address is always enabled on XMAC */
250744961713Sgirish 
250844961713Sgirish 		if ((rs = npi_xmac_zap_rx_counters(handle, portn))
250944961713Sgirish 							!= NPI_SUCCESS)
251044961713Sgirish 			goto fail;
251144961713Sgirish 	} else {
251244961713Sgirish 		(void) nxge_fflp_init_hostinfo(nxgep);
251344961713Sgirish 
251444961713Sgirish 		if (npi_bmac_rx_iconfig(nxgep->npi_handle, INIT, portn,
251544961713Sgirish 					0) != NPI_SUCCESS)
251644961713Sgirish 			goto fail;
251744961713Sgirish 		nxgep->mac.rx_iconfig = NXGE_BMAC_RX_INTRS;
251844961713Sgirish 
2519a3c5bd6dSspeer 		bconfig = CFG_BMAC_RX_DISCARD_ON_ERR | CFG_BMAC_RX &
2520a3c5bd6dSspeer 			~CFG_BMAC_RX_STRIP_CRC;
252144961713Sgirish 
252244961713Sgirish 		if (nxgep->filter.all_phys_cnt != 0)
252344961713Sgirish 			bconfig |= CFG_BMAC_RX_PROMISCUOUS;
252444961713Sgirish 
252544961713Sgirish 		if (nxgep->filter.all_multicast_cnt != 0)
252644961713Sgirish 			bconfig |= CFG_BMAC_RX_PROMISCUOUSGROUP;
252744961713Sgirish 
252844961713Sgirish 		bconfig |= CFG_BMAC_RX_HASH_FILTER;
252944961713Sgirish 		if ((rs = npi_bmac_rx_config(handle, INIT, portn,
253044961713Sgirish 					bconfig)) != NPI_SUCCESS)
253144961713Sgirish 			goto fail;
253244961713Sgirish 		nxgep->mac.rx_config = bconfig;
253344961713Sgirish 
253444961713Sgirish 		/* Always enable comparison of mac unique address */
253544961713Sgirish 		if ((rs = npi_mac_altaddr_enable(handle, portn, 0))
253644961713Sgirish 					!= NPI_SUCCESS)
253744961713Sgirish 			goto fail;
253844961713Sgirish 	}
253944961713Sgirish 
254044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_init: port<%d>\n",
254144961713Sgirish 			portn));
254244961713Sgirish 
254344961713Sgirish 	return (NXGE_OK);
254444961713Sgirish 
254544961713Sgirish fail:
254644961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
254744961713Sgirish 		"nxge_rx_mac_init: Failed to Initialize port<%d> RxMAC",
254844961713Sgirish 				portn));
254944961713Sgirish 
255044961713Sgirish 	return (NXGE_ERROR | rs);
255144961713Sgirish }
255244961713Sgirish 
255344961713Sgirish /* Enable TXMAC */
255444961713Sgirish 
255544961713Sgirish nxge_status_t
255644961713Sgirish nxge_tx_mac_enable(p_nxge_t nxgep)
255744961713Sgirish {
255844961713Sgirish 	npi_handle_t	handle;
255944961713Sgirish 	npi_status_t	rs = NPI_SUCCESS;
256044961713Sgirish 	nxge_status_t	status = NXGE_OK;
256144961713Sgirish 
256244961713Sgirish 	handle = nxgep->npi_handle;
256344961713Sgirish 
256444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_enable: port<%d>",
256544961713Sgirish 			nxgep->mac.portnum));
256644961713Sgirish 
256744961713Sgirish 	if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK)
256844961713Sgirish 		goto fail;
256944961713Sgirish 
257044961713Sgirish 	/* based on speed */
257144961713Sgirish 	nxgep->msg_min = ETHERMIN;
257244961713Sgirish 
257344961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
257444961713Sgirish 		if ((rs = npi_xmac_tx_config(handle, ENABLE, nxgep->mac.portnum,
257544961713Sgirish 						CFG_XMAC_TX)) != NPI_SUCCESS)
257644961713Sgirish 			goto fail;
257744961713Sgirish 	} else {
257844961713Sgirish 		if ((rs = npi_bmac_tx_config(handle, ENABLE, nxgep->mac.portnum,
257944961713Sgirish 						CFG_BMAC_TX)) != NPI_SUCCESS)
258044961713Sgirish 			goto fail;
258144961713Sgirish 	}
258244961713Sgirish 
258344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_enable: port<%d>",
258444961713Sgirish 			nxgep->mac.portnum));
258544961713Sgirish 
258644961713Sgirish 	return (NXGE_OK);
258744961713Sgirish fail:
258844961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
258944961713Sgirish 			"nxgep_tx_mac_enable: Failed to enable port<%d> TxMAC",
259044961713Sgirish 			nxgep->mac.portnum));
259144961713Sgirish 	if (rs != NPI_SUCCESS)
259244961713Sgirish 		return (NXGE_ERROR | rs);
259344961713Sgirish 	else
259444961713Sgirish 		return (status);
259544961713Sgirish }
259644961713Sgirish 
259744961713Sgirish /* Disable TXMAC */
259844961713Sgirish 
259944961713Sgirish nxge_status_t
260044961713Sgirish nxge_tx_mac_disable(p_nxge_t nxgep)
260144961713Sgirish {
260244961713Sgirish 	npi_handle_t	handle;
260344961713Sgirish 	npi_status_t	rs = NPI_SUCCESS;
260444961713Sgirish 
260544961713Sgirish 	handle = nxgep->npi_handle;
260644961713Sgirish 
260744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_disable: port<%d>",
260844961713Sgirish 			nxgep->mac.portnum));
260944961713Sgirish 
261044961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
261144961713Sgirish 		if ((rs = npi_xmac_tx_config(handle, DISABLE,
261244961713Sgirish 			nxgep->mac.portnum, CFG_XMAC_TX)) != NPI_SUCCESS)
261344961713Sgirish 			goto fail;
261444961713Sgirish 	} else {
261544961713Sgirish 		if ((rs = npi_bmac_tx_config(handle, DISABLE,
261644961713Sgirish 			nxgep->mac.portnum, CFG_BMAC_TX)) != NPI_SUCCESS)
261744961713Sgirish 			goto fail;
261844961713Sgirish 	}
261944961713Sgirish 
262044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_disable: port<%d>",
262144961713Sgirish 			nxgep->mac.portnum));
262244961713Sgirish 	return (NXGE_OK);
262344961713Sgirish fail:
262444961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
262544961713Sgirish 			"nxge_tx_mac_disable: Failed to disable port<%d> TxMAC",
262644961713Sgirish 			nxgep->mac.portnum));
262744961713Sgirish 	return (NXGE_ERROR | rs);
262844961713Sgirish }
262944961713Sgirish 
263044961713Sgirish /* Enable RXMAC */
263144961713Sgirish 
263244961713Sgirish nxge_status_t
263344961713Sgirish nxge_rx_mac_enable(p_nxge_t nxgep)
263444961713Sgirish {
263544961713Sgirish 	npi_handle_t	handle;
263644961713Sgirish 	uint8_t 	portn;
263744961713Sgirish 	npi_status_t	rs = NPI_SUCCESS;
263844961713Sgirish 	nxge_status_t	status = NXGE_OK;
263944961713Sgirish 
264044961713Sgirish 	handle = nxgep->npi_handle;
264144961713Sgirish 	portn = nxgep->mac.portnum;
264244961713Sgirish 
264344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_enable: port<%d>",
264444961713Sgirish 			portn));
264544961713Sgirish 
264644961713Sgirish 	if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
264744961713Sgirish 		goto fail;
264844961713Sgirish 
264944961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
265044961713Sgirish 		if ((rs = npi_xmac_rx_config(handle, ENABLE, portn,
265144961713Sgirish 						CFG_XMAC_RX)) != NPI_SUCCESS)
265244961713Sgirish 			goto fail;
265344961713Sgirish 	} else {
265444961713Sgirish 		if ((rs = npi_bmac_rx_config(handle, ENABLE, portn,
265544961713Sgirish 						CFG_BMAC_RX)) != NPI_SUCCESS)
265644961713Sgirish 			goto fail;
265744961713Sgirish 	}
265844961713Sgirish 
265944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_enable: port<%d>",
266044961713Sgirish 			portn));
266144961713Sgirish 
266244961713Sgirish 	return (NXGE_OK);
266344961713Sgirish fail:
266444961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
266544961713Sgirish 			"nxgep_rx_mac_enable: Failed to enable port<%d> RxMAC",
266644961713Sgirish 			portn));
266744961713Sgirish 
266844961713Sgirish 	if (rs != NPI_SUCCESS)
266944961713Sgirish 		return (NXGE_ERROR | rs);
267044961713Sgirish 	else
267144961713Sgirish 		return (status);
267244961713Sgirish }
267344961713Sgirish 
267444961713Sgirish /* Disable RXMAC */
267544961713Sgirish 
267644961713Sgirish nxge_status_t
267744961713Sgirish nxge_rx_mac_disable(p_nxge_t nxgep)
267844961713Sgirish {
267944961713Sgirish 	npi_handle_t	handle;
268044961713Sgirish 	uint8_t		portn;
268144961713Sgirish 	npi_status_t	rs = NPI_SUCCESS;
268244961713Sgirish 
268344961713Sgirish 	handle = nxgep->npi_handle;
268444961713Sgirish 	portn = nxgep->mac.portnum;
268544961713Sgirish 
268644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_disable: port<%d>",
268744961713Sgirish 			portn));
268844961713Sgirish 
268944961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
269044961713Sgirish 		if ((rs = npi_xmac_rx_config(handle, DISABLE, portn,
269144961713Sgirish 						CFG_XMAC_RX)) != NPI_SUCCESS)
269244961713Sgirish 			goto fail;
269344961713Sgirish 	} else {
269444961713Sgirish 		if ((rs = npi_bmac_rx_config(handle, DISABLE, portn,
269544961713Sgirish 						CFG_BMAC_RX)) != NPI_SUCCESS)
269644961713Sgirish 			goto fail;
269744961713Sgirish 	}
269844961713Sgirish 
269944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_disable: port<%d>",
270044961713Sgirish 			portn));
270144961713Sgirish 	return (NXGE_OK);
270244961713Sgirish fail:
270344961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
270444961713Sgirish 			"nxgep_rx_mac_disable: ",
270544961713Sgirish 			"Failed to disable port<%d> RxMAC",
270644961713Sgirish 			portn));
270744961713Sgirish 
270844961713Sgirish 	return (NXGE_ERROR | rs);
270944961713Sgirish }
271044961713Sgirish 
271144961713Sgirish /* Reset TXMAC */
271244961713Sgirish 
271344961713Sgirish nxge_status_t
271444961713Sgirish nxge_tx_mac_reset(p_nxge_t nxgep)
271544961713Sgirish {
271644961713Sgirish 	npi_handle_t	handle;
271744961713Sgirish 	uint8_t		portn;
271844961713Sgirish 	npi_status_t	rs = NPI_SUCCESS;
271944961713Sgirish 
272044961713Sgirish 	handle = nxgep->npi_handle;
272144961713Sgirish 	portn = nxgep->mac.portnum;
272244961713Sgirish 
272344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_reset: port<%d>",
272444961713Sgirish 			portn));
272544961713Sgirish 
272644961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
272744961713Sgirish 		if ((rs = npi_xmac_reset(handle, portn, XTX_MAC_RESET_ALL))
272844961713Sgirish 		    != NPI_SUCCESS)
272944961713Sgirish 			goto fail;
273044961713Sgirish 	} else {
273144961713Sgirish 		if ((rs = npi_bmac_reset(handle, portn, TX_MAC_RESET))
273244961713Sgirish 					!= NPI_SUCCESS)
273344961713Sgirish 			goto fail;
273444961713Sgirish 	}
273544961713Sgirish 
273644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_reset: port<%d>",
273744961713Sgirish 			portn));
273844961713Sgirish 
273944961713Sgirish 	return (NXGE_OK);
274044961713Sgirish fail:
274144961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
274244961713Sgirish 			"nxge_tx_mac_reset: Failed to Reset TxMAC port<%d>",
274344961713Sgirish 			portn));
274444961713Sgirish 
274544961713Sgirish 	return (NXGE_ERROR | rs);
274644961713Sgirish }
274744961713Sgirish 
274844961713Sgirish /* Reset RXMAC */
274944961713Sgirish 
275044961713Sgirish nxge_status_t
275144961713Sgirish nxge_rx_mac_reset(p_nxge_t nxgep)
275244961713Sgirish {
275344961713Sgirish 	npi_handle_t	handle;
275444961713Sgirish 	uint8_t		portn;
275544961713Sgirish 	npi_status_t	rs = NPI_SUCCESS;
275644961713Sgirish 
275744961713Sgirish 	handle = nxgep->npi_handle;
275844961713Sgirish 	portn = nxgep->mac.portnum;
275944961713Sgirish 
276044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_reset: port<%d>",
276144961713Sgirish 			portn));
276244961713Sgirish 
276344961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
276444961713Sgirish 		if ((rs = npi_xmac_reset(handle, portn, XRX_MAC_RESET_ALL))
276544961713Sgirish 		    != NPI_SUCCESS)
276644961713Sgirish 		goto fail;
276744961713Sgirish 	} else {
276844961713Sgirish 		if ((rs = npi_bmac_reset(handle, portn, RX_MAC_RESET))
276944961713Sgirish 					!= NPI_SUCCESS)
277044961713Sgirish 		goto fail;
277144961713Sgirish 	}
277244961713Sgirish 
277344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_reset: port<%d>",
277444961713Sgirish 			portn));
277544961713Sgirish 
277659ac0c16Sdavemq 	return (NXGE_OK);
277759ac0c16Sdavemq fail:
277859ac0c16Sdavemq 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
277959ac0c16Sdavemq 			"nxge_rx_mac_reset: Failed to Reset RxMAC port<%d>",
278059ac0c16Sdavemq 			portn));
278159ac0c16Sdavemq 	return (NXGE_ERROR | rs);
278259ac0c16Sdavemq }
278359ac0c16Sdavemq 
278459ac0c16Sdavemq /* 10G fiber link interrupt start routine */
278559ac0c16Sdavemq 
278659ac0c16Sdavemq static nxge_status_t
278759ac0c16Sdavemq nxge_10G_link_intr_start(p_nxge_t nxgep)
278859ac0c16Sdavemq {
278959ac0c16Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
279059ac0c16Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
279159ac0c16Sdavemq 
279259ac0c16Sdavemq 	rs = npi_xmac_xpcs_link_intr_enable(nxgep->npi_handle, portn);
279359ac0c16Sdavemq 
279459ac0c16Sdavemq 	if (rs != NPI_SUCCESS)
279559ac0c16Sdavemq 		return (NXGE_ERROR | rs);
279659ac0c16Sdavemq 	else
279759ac0c16Sdavemq 		return (NXGE_OK);
279859ac0c16Sdavemq }
279959ac0c16Sdavemq 
280059ac0c16Sdavemq /* 10G fiber link interrupt stop routine */
280159ac0c16Sdavemq 
280259ac0c16Sdavemq static nxge_status_t
280359ac0c16Sdavemq nxge_10G_link_intr_stop(p_nxge_t nxgep)
280459ac0c16Sdavemq {
280559ac0c16Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
280659ac0c16Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
280759ac0c16Sdavemq 
280859ac0c16Sdavemq 	rs = npi_xmac_xpcs_link_intr_disable(nxgep->npi_handle, portn);
280959ac0c16Sdavemq 
281059ac0c16Sdavemq 	if (rs != NPI_SUCCESS)
281159ac0c16Sdavemq 		return (NXGE_ERROR | rs);
281259ac0c16Sdavemq 	else
281359ac0c16Sdavemq 		return (NXGE_OK);
281459ac0c16Sdavemq }
281559ac0c16Sdavemq 
281659ac0c16Sdavemq /* 1G fiber link interrupt start routine */
281759ac0c16Sdavemq 
281859ac0c16Sdavemq static nxge_status_t
281959ac0c16Sdavemq nxge_1G_fiber_link_intr_start(p_nxge_t nxgep)
282059ac0c16Sdavemq {
282159ac0c16Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
282259ac0c16Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
282359ac0c16Sdavemq 
282459ac0c16Sdavemq 	rs = npi_mac_pcs_link_intr_enable(nxgep->npi_handle, portn);
282559ac0c16Sdavemq 	if (rs != NPI_SUCCESS)
282659ac0c16Sdavemq 		return (NXGE_ERROR | rs);
282759ac0c16Sdavemq 	else
282859ac0c16Sdavemq 		return (NXGE_OK);
282959ac0c16Sdavemq }
283059ac0c16Sdavemq 
283159ac0c16Sdavemq /* 1G fiber link interrupt stop routine */
283259ac0c16Sdavemq 
283359ac0c16Sdavemq static nxge_status_t
283459ac0c16Sdavemq nxge_1G_fiber_link_intr_stop(p_nxge_t nxgep)
283559ac0c16Sdavemq {
283659ac0c16Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
283759ac0c16Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
283859ac0c16Sdavemq 
283959ac0c16Sdavemq 	rs = npi_mac_pcs_link_intr_disable(nxgep->npi_handle, portn);
284059ac0c16Sdavemq 
284159ac0c16Sdavemq 	if (rs != NPI_SUCCESS)
284259ac0c16Sdavemq 		return (NXGE_ERROR | rs);
284359ac0c16Sdavemq 	else
284459ac0c16Sdavemq 		return (NXGE_OK);
284559ac0c16Sdavemq }
284659ac0c16Sdavemq 
284759ac0c16Sdavemq /* 1G copper link interrupt start routine */
284859ac0c16Sdavemq 
284959ac0c16Sdavemq static nxge_status_t
285059ac0c16Sdavemq nxge_1G_copper_link_intr_start(p_nxge_t nxgep)
285159ac0c16Sdavemq {
285259ac0c16Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
285359ac0c16Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
285459ac0c16Sdavemq 
285559ac0c16Sdavemq 	rs = npi_mac_mif_link_intr_enable(nxgep->npi_handle, portn,
28566b438925Ssbehera 	    MII_STATUS, MII_STATUS_LINKUP);
285759ac0c16Sdavemq 
285859ac0c16Sdavemq 	if (rs != NPI_SUCCESS)
285959ac0c16Sdavemq 		return (NXGE_ERROR | rs);
286059ac0c16Sdavemq 	else
286159ac0c16Sdavemq 		return (NXGE_OK);
286244961713Sgirish }
286344961713Sgirish 
286459ac0c16Sdavemq /* 1G copper link interrupt stop routine */
286559ac0c16Sdavemq 
286659ac0c16Sdavemq static nxge_status_t
286759ac0c16Sdavemq nxge_1G_copper_link_intr_stop(p_nxge_t nxgep)
286859ac0c16Sdavemq {
286959ac0c16Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
287059ac0c16Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
287159ac0c16Sdavemq 
287259ac0c16Sdavemq 	rs = npi_mac_mif_link_intr_disable(nxgep->npi_handle, portn);
287359ac0c16Sdavemq 
287459ac0c16Sdavemq 	if (rs != NPI_SUCCESS)
287559ac0c16Sdavemq 		return (NXGE_ERROR | rs);
287659ac0c16Sdavemq 	else
287759ac0c16Sdavemq 		return (NXGE_OK);
287859ac0c16Sdavemq }
287944961713Sgirish 
288059ac0c16Sdavemq /* Enable/Disable Link Status change interrupt */
288144961713Sgirish 
288244961713Sgirish nxge_status_t
288344961713Sgirish nxge_link_intr(p_nxge_t nxgep, link_intr_enable_t enable)
288444961713Sgirish {
288559ac0c16Sdavemq 	uint8_t		portn;
288659ac0c16Sdavemq 	nxge_status_t	status = NXGE_OK;
288744961713Sgirish 
288844961713Sgirish 	portn = nxgep->mac.portnum;
288944961713Sgirish 
289044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_intr: port<%d>", portn));
289159ac0c16Sdavemq 	if (!nxgep->xcvr.link_intr_stop || !nxgep->xcvr.link_intr_start)
289259ac0c16Sdavemq 		return (NXGE_OK);
289344961713Sgirish 
289459ac0c16Sdavemq 	if (enable == LINK_INTR_START)
289559ac0c16Sdavemq 		status = nxgep->xcvr.link_intr_start(nxgep);
289659ac0c16Sdavemq 	else if (enable == LINK_INTR_STOP)
289759ac0c16Sdavemq 		status = nxgep->xcvr.link_intr_stop(nxgep);
289859ac0c16Sdavemq 	if (status != NXGE_OK)
289959ac0c16Sdavemq 		goto fail;
290044961713Sgirish 
290144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_intr: port<%d>", portn));
290244961713Sgirish 
290344961713Sgirish 	return (NXGE_OK);
290444961713Sgirish fail:
290544961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
290644961713Sgirish 			"nxge_link_intr: Failed to set port<%d> mif intr mode",
290744961713Sgirish 			portn));
290844961713Sgirish 
290959ac0c16Sdavemq 	return (status);
291044961713Sgirish }
291144961713Sgirish 
291244961713Sgirish /* Initialize 1G Fiber / Copper transceiver using Clause 22 */
291344961713Sgirish 
291444961713Sgirish nxge_status_t
291544961713Sgirish nxge_mii_xcvr_init(p_nxge_t nxgep)
291644961713Sgirish {
291744961713Sgirish 	p_nxge_param_t	param_arr;
291844961713Sgirish 	p_nxge_stats_t	statsp;
291944961713Sgirish 	uint8_t		xcvr_portn;
292044961713Sgirish 	p_mii_regs_t	mii_regs;
292144961713Sgirish 	mii_bmcr_t	bmcr;
292244961713Sgirish 	mii_bmsr_t	bmsr;
292344961713Sgirish 	mii_anar_t	anar;
292444961713Sgirish 	mii_gcr_t	gcr;
292544961713Sgirish 	mii_esr_t	esr;
292644961713Sgirish 	mii_aux_ctl_t	bcm5464r_aux;
292744961713Sgirish 	int		status = NXGE_OK;
292844961713Sgirish 
292944961713Sgirish 	uint_t delay;
293044961713Sgirish 
293144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_init"));
293244961713Sgirish 
293344961713Sgirish 	param_arr = nxgep->param_arr;
293444961713Sgirish 	statsp = nxgep->statsp;
293544961713Sgirish 	xcvr_portn = statsp->mac_stats.xcvr_portn;
293644961713Sgirish 
293744961713Sgirish 	mii_regs = NULL;
293844961713Sgirish 
293944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
294044961713Sgirish 		"nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value));
294144961713Sgirish 
2942d81011f0Ssbehera 	/*
2943d81011f0Ssbehera 	 * The mif phy mode may be connected to either a copper link
2944d81011f0Ssbehera 	 * or fiber link. Read the mode control register to get the fiber
2945d81011f0Ssbehera 	 * configuration if it is hard-wired to fiber link.
2946d81011f0Ssbehera 	 */
2947d81011f0Ssbehera 	(void) nxge_mii_get_link_mode(nxgep);
2948d81011f0Ssbehera 	if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) {
2949d81011f0Ssbehera 		return (nxge_mii_xcvr_fiber_init(nxgep));
2950d81011f0Ssbehera 	}
2951d81011f0Ssbehera 
295244961713Sgirish 	/*
295344961713Sgirish 	 * Reset the transceiver.
295444961713Sgirish 	 */
295544961713Sgirish 	delay = 0;
295644961713Sgirish 	bmcr.value = 0;
295744961713Sgirish 	bmcr.bits.reset = 1;
295844961713Sgirish 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
2959adfcba55Sjoycey #if defined(__i386)
2960adfcba55Sjoycey 		(uint8_t)(uint32_t)&mii_regs->bmcr, bmcr.value)) != NXGE_OK)
2961adfcba55Sjoycey #else
296244961713Sgirish 		(uint8_t)(uint64_t)&mii_regs->bmcr, bmcr.value)) != NXGE_OK)
2963adfcba55Sjoycey #endif
296444961713Sgirish 		goto fail;
296544961713Sgirish 	do {
296644961713Sgirish 		drv_usecwait(500);
296744961713Sgirish 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
2968adfcba55Sjoycey #if defined(__i386)
2969adfcba55Sjoycey 			(uint8_t)(uint32_t)&mii_regs->bmcr, &bmcr.value))
2970adfcba55Sjoycey #else
297144961713Sgirish 			(uint8_t)(uint64_t)&mii_regs->bmcr, &bmcr.value))
2972adfcba55Sjoycey #endif
297344961713Sgirish 				!= NXGE_OK)
297444961713Sgirish 			goto fail;
297544961713Sgirish 		delay++;
297644961713Sgirish 	} while ((bmcr.bits.reset) && (delay < 1000));
297744961713Sgirish 	if (delay == 1000) {
297844961713Sgirish 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed."));
297944961713Sgirish 		goto fail;
298044961713Sgirish 	}
298144961713Sgirish 
298244961713Sgirish 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
2983adfcba55Sjoycey #if defined(__i386)
2984adfcba55Sjoycey 			(uint8_t)(uint32_t)(&mii_regs->bmsr),
2985adfcba55Sjoycey #else
298644961713Sgirish 			(uint8_t)(uint64_t)(&mii_regs->bmsr),
2987adfcba55Sjoycey #endif
298844961713Sgirish 			&bmsr.value)) != NXGE_OK)
298944961713Sgirish 		goto fail;
299044961713Sgirish 
299144961713Sgirish 	param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able;
299244961713Sgirish 	param_arr[param_anar_100T4].value &= bmsr.bits.link_100T4;
299344961713Sgirish 	param_arr[param_anar_100fdx].value &= bmsr.bits.link_100fdx;
299444961713Sgirish 	param_arr[param_anar_100hdx].value = 0;
299544961713Sgirish 	param_arr[param_anar_10fdx].value &= bmsr.bits.link_10fdx;
299644961713Sgirish 	param_arr[param_anar_10hdx].value = 0;
299744961713Sgirish 
299844961713Sgirish 	/*
299958324dfcSspeer 	 * Initialize the xcvr statistics.
300044961713Sgirish 	 */
300144961713Sgirish 	statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able;
300244961713Sgirish 	statsp->mac_stats.cap_100T4 = bmsr.bits.link_100T4;
300344961713Sgirish 	statsp->mac_stats.cap_100fdx = bmsr.bits.link_100fdx;
300444961713Sgirish 	statsp->mac_stats.cap_100hdx = 0;
300544961713Sgirish 	statsp->mac_stats.cap_10fdx = bmsr.bits.link_10fdx;
300644961713Sgirish 	statsp->mac_stats.cap_10hdx = 0;
300744961713Sgirish 	statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value;
300844961713Sgirish 	statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value;
300944961713Sgirish 
301044961713Sgirish 	/*
301144961713Sgirish 	 * Initialise the xcvr advertised capability statistics.
301244961713Sgirish 	 */
301344961713Sgirish 	statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value;
301444961713Sgirish 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
301544961713Sgirish 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
301644961713Sgirish 	statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value;
301744961713Sgirish 	statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value;
301844961713Sgirish 	statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value;
301944961713Sgirish 	statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value;
302044961713Sgirish 	statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value;
302144961713Sgirish 	statsp->mac_stats.adv_cap_asmpause =
302244961713Sgirish 					param_arr[param_anar_asmpause].value;
302344961713Sgirish 	statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
302444961713Sgirish 
302544961713Sgirish 
302644961713Sgirish 	/*
302744961713Sgirish 	 * Check for extended status just in case we're
302844961713Sgirish 	 * running a Gigibit phy.
302944961713Sgirish 	 */
303044961713Sgirish 	if (bmsr.bits.extend_status) {
303144961713Sgirish 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
3032adfcba55Sjoycey #if defined(__i386)
3033adfcba55Sjoycey 			(uint8_t)(uint32_t)(&mii_regs->esr), &esr.value))
3034adfcba55Sjoycey #else
303544961713Sgirish 			(uint8_t)(uint64_t)(&mii_regs->esr), &esr.value))
3036adfcba55Sjoycey #endif
303744961713Sgirish 				!= NXGE_OK)
303844961713Sgirish 			goto fail;
303944961713Sgirish 		param_arr[param_anar_1000fdx].value &=
304044961713Sgirish 					esr.bits.link_1000fdx;
304144961713Sgirish 		param_arr[param_anar_1000hdx].value = 0;
304244961713Sgirish 
304344961713Sgirish 		statsp->mac_stats.cap_1000fdx =
304444961713Sgirish 			(esr.bits.link_1000Xfdx ||
304544961713Sgirish 				esr.bits.link_1000fdx);
304644961713Sgirish 		statsp->mac_stats.cap_1000hdx = 0;
304744961713Sgirish 	} else {
304844961713Sgirish 		param_arr[param_anar_1000fdx].value = 0;
304944961713Sgirish 		param_arr[param_anar_1000hdx].value = 0;
305044961713Sgirish 	}
305144961713Sgirish 
305244961713Sgirish 	/*
305344961713Sgirish 	 * Initialize 1G Statistics once the capability is established.
305444961713Sgirish 	 */
305544961713Sgirish 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
305644961713Sgirish 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
305744961713Sgirish 
305844961713Sgirish 	/*
305944961713Sgirish 	 * Initialise the link statistics.
306044961713Sgirish 	 */
306144961713Sgirish 	statsp->mac_stats.link_T4 = 0;
306244961713Sgirish 	statsp->mac_stats.link_asmpause = 0;
306344961713Sgirish 	statsp->mac_stats.link_pause = 0;
306444961713Sgirish 	statsp->mac_stats.link_speed = 0;
306544961713Sgirish 	statsp->mac_stats.link_duplex = 0;
306644961713Sgirish 	statsp->mac_stats.link_up = 0;
306744961713Sgirish 
306844961713Sgirish 	/*
306944961713Sgirish 	 * Switch off Auto-negotiation, 100M and full duplex.
307044961713Sgirish 	 */
307144961713Sgirish 	bmcr.value = 0;
307244961713Sgirish 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
3073adfcba55Sjoycey #if defined(__i386)
3074adfcba55Sjoycey 		(uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
3075adfcba55Sjoycey #else
307644961713Sgirish 		(uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
3077adfcba55Sjoycey #endif
307844961713Sgirish 		goto fail;
307944961713Sgirish 
308044961713Sgirish 	if ((statsp->port_stats.lb_mode == nxge_lb_phy) ||
308144961713Sgirish 			(statsp->port_stats.lb_mode == nxge_lb_phy1000)) {
308244961713Sgirish 		bmcr.bits.loopback = 1;
308344961713Sgirish 		bmcr.bits.enable_autoneg = 0;
308444961713Sgirish 		if (statsp->port_stats.lb_mode == nxge_lb_phy1000)
308544961713Sgirish 			bmcr.bits.speed_1000_sel = 1;
308644961713Sgirish 		bmcr.bits.duplex_mode = 1;
308744961713Sgirish 		param_arr[param_autoneg].value = 0;
308844961713Sgirish 	} else {
308944961713Sgirish 		bmcr.bits.loopback = 0;
309044961713Sgirish 	}
309144961713Sgirish 
309244961713Sgirish 	if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
309344961713Sgirish 		(statsp->port_stats.lb_mode == nxge_lb_ext100) ||
309444961713Sgirish 		(statsp->port_stats.lb_mode == nxge_lb_ext10)) {
309544961713Sgirish 		param_arr[param_autoneg].value = 0;
309644961713Sgirish 		bcm5464r_aux.value = 0;
309744961713Sgirish 		bcm5464r_aux.bits.ext_lb = 1;
309844961713Sgirish 		bcm5464r_aux.bits.write_1 = 1;
309944961713Sgirish 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
310044961713Sgirish 				BCM5464R_AUX_CTL, bcm5464r_aux.value))
310144961713Sgirish 				!= NXGE_OK)
310244961713Sgirish 			goto fail;
310344961713Sgirish 	}
310444961713Sgirish 
310544961713Sgirish 	if (param_arr[param_autoneg].value) {
310644961713Sgirish 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
310744961713Sgirish 				"Restarting Auto-negotiation."));
310844961713Sgirish 		/*
310944961713Sgirish 		 * Setup our Auto-negotiation advertisement register.
311044961713Sgirish 		 */
311144961713Sgirish 		anar.value = 0;
311244961713Sgirish 		anar.bits.selector = 1;
311344961713Sgirish 		anar.bits.cap_100T4 = param_arr[param_anar_100T4].value;
311444961713Sgirish 		anar.bits.cap_100fdx = param_arr[param_anar_100fdx].value;
311544961713Sgirish 		anar.bits.cap_100hdx = param_arr[param_anar_100hdx].value;
311644961713Sgirish 		anar.bits.cap_10fdx = param_arr[param_anar_10fdx].value;
311744961713Sgirish 		anar.bits.cap_10hdx = param_arr[param_anar_10hdx].value;
311844961713Sgirish 		anar.bits.cap_asmpause = 0;
311944961713Sgirish 		anar.bits.cap_pause = 0;
312044961713Sgirish 		if (param_arr[param_anar_1000fdx].value ||
312144961713Sgirish 			param_arr[param_anar_100fdx].value ||
312244961713Sgirish 			param_arr[param_anar_10fdx].value) {
312344961713Sgirish 			anar.bits.cap_asmpause = statsp->mac_stats.cap_asmpause;
312444961713Sgirish 			anar.bits.cap_pause = statsp->mac_stats.cap_pause;
312544961713Sgirish 		}
312644961713Sgirish 
312744961713Sgirish 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
3128adfcba55Sjoycey #if defined(__i386)
3129adfcba55Sjoycey 			(uint8_t)(uint32_t)(&mii_regs->anar), anar.value))
3130adfcba55Sjoycey #else
313144961713Sgirish 			(uint8_t)(uint64_t)(&mii_regs->anar), anar.value))
3132adfcba55Sjoycey #endif
313344961713Sgirish 				!= NXGE_OK)
313444961713Sgirish 			goto fail;
313544961713Sgirish 		if (bmsr.bits.extend_status) {
313644961713Sgirish 			gcr.value = 0;
313744961713Sgirish 			gcr.bits.ms_mode_en =
313844961713Sgirish 				param_arr[param_master_cfg_enable].value;
313944961713Sgirish 			gcr.bits.master =
314044961713Sgirish 				param_arr[param_master_cfg_value].value;
314144961713Sgirish 			gcr.bits.link_1000fdx =
314244961713Sgirish 				param_arr[param_anar_1000fdx].value;
314344961713Sgirish 			gcr.bits.link_1000hdx =
314444961713Sgirish 				param_arr[param_anar_1000hdx].value;
314544961713Sgirish 			if ((status = nxge_mii_write(nxgep, xcvr_portn,
3146adfcba55Sjoycey #if defined(__i386)
3147adfcba55Sjoycey 				(uint8_t)(uint32_t)(&mii_regs->gcr), gcr.value))
3148adfcba55Sjoycey #else
314944961713Sgirish 				(uint8_t)(uint64_t)(&mii_regs->gcr), gcr.value))
3150adfcba55Sjoycey #endif
315144961713Sgirish 				!= NXGE_OK)
315244961713Sgirish 				goto fail;
315344961713Sgirish 		}
315444961713Sgirish 
315544961713Sgirish 		bmcr.bits.enable_autoneg = 1;
315644961713Sgirish 		bmcr.bits.restart_autoneg = 1;
315744961713Sgirish 
315844961713Sgirish 	} else {
315944961713Sgirish 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode."));
316044961713Sgirish 		bmcr.bits.speed_1000_sel =
316144961713Sgirish 			param_arr[param_anar_1000fdx].value |
316244961713Sgirish 				param_arr[param_anar_1000hdx].value;
316344961713Sgirish 		bmcr.bits.speed_sel = (~bmcr.bits.speed_1000_sel) &
316444961713Sgirish 			(param_arr[param_anar_100fdx].value |
316544961713Sgirish 				param_arr[param_anar_100hdx].value);
316644961713Sgirish 		if (bmcr.bits.speed_1000_sel) {
316744961713Sgirish 			statsp->mac_stats.link_speed = 1000;
316844961713Sgirish 			gcr.value = 0;
316944961713Sgirish 			gcr.bits.ms_mode_en =
317044961713Sgirish 				param_arr[param_master_cfg_enable].value;
317144961713Sgirish 			gcr.bits.master =
317244961713Sgirish 				param_arr[param_master_cfg_value].value;
317344961713Sgirish 			if ((status = nxge_mii_write(nxgep, xcvr_portn,
3174adfcba55Sjoycey #if defined(__i386)
3175adfcba55Sjoycey 				(uint8_t)(uint32_t)(&mii_regs->gcr),
3176adfcba55Sjoycey #else
317744961713Sgirish 				(uint8_t)(uint64_t)(&mii_regs->gcr),
3178adfcba55Sjoycey #endif
317944961713Sgirish 				gcr.value))
318044961713Sgirish 				!= NXGE_OK)
318144961713Sgirish 				goto fail;
318244961713Sgirish 			if (param_arr[param_anar_1000fdx].value) {
318344961713Sgirish 				bmcr.bits.duplex_mode = 1;
318444961713Sgirish 				statsp->mac_stats.link_duplex = 2;
318544961713Sgirish 			} else
318644961713Sgirish 				statsp->mac_stats.link_duplex = 1;
318744961713Sgirish 		} else if (bmcr.bits.speed_sel) {
318844961713Sgirish 			statsp->mac_stats.link_speed = 100;
318944961713Sgirish 			if (param_arr[param_anar_100fdx].value) {
319044961713Sgirish 				bmcr.bits.duplex_mode = 1;
319144961713Sgirish 				statsp->mac_stats.link_duplex = 2;
319244961713Sgirish 			} else
319344961713Sgirish 				statsp->mac_stats.link_duplex = 1;
319444961713Sgirish 		} else {
319544961713Sgirish 			statsp->mac_stats.link_speed = 10;
319644961713Sgirish 			if (param_arr[param_anar_10fdx].value) {
319744961713Sgirish 				bmcr.bits.duplex_mode = 1;
319844961713Sgirish 				statsp->mac_stats.link_duplex = 2;
319944961713Sgirish 			} else
320044961713Sgirish 				statsp->mac_stats.link_duplex = 1;
320144961713Sgirish 		}
320244961713Sgirish 		if (statsp->mac_stats.link_duplex != 1) {
320344961713Sgirish 			statsp->mac_stats.link_asmpause =
320444961713Sgirish 						statsp->mac_stats.cap_asmpause;
320544961713Sgirish 			statsp->mac_stats.link_pause =
320644961713Sgirish 						statsp->mac_stats.cap_pause;
320744961713Sgirish 		}
320844961713Sgirish 
320944961713Sgirish 		if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
321044961713Sgirish 			(statsp->port_stats.lb_mode == nxge_lb_ext100) ||
321144961713Sgirish 			(statsp->port_stats.lb_mode == nxge_lb_ext10)) {
321244961713Sgirish 			if (statsp->port_stats.lb_mode == nxge_lb_ext1000) {
321344961713Sgirish 				/* BCM5464R 1000mbps external loopback mode */
321444961713Sgirish 				gcr.value = 0;
321544961713Sgirish 				gcr.bits.ms_mode_en = 1;
321644961713Sgirish 				gcr.bits.master = 1;
321744961713Sgirish 				if ((status = nxge_mii_write(nxgep, xcvr_portn,
3218adfcba55Sjoycey #if defined(__i386)
3219adfcba55Sjoycey 					(uint8_t)(uint32_t)(&mii_regs->gcr),
3220adfcba55Sjoycey #else
322144961713Sgirish 					(uint8_t)(uint64_t)(&mii_regs->gcr),
3222adfcba55Sjoycey #endif
322344961713Sgirish 					gcr.value))
322444961713Sgirish 					!= NXGE_OK)
322544961713Sgirish 					goto fail;
322644961713Sgirish 				bmcr.value = 0;
322744961713Sgirish 				bmcr.bits.speed_1000_sel = 1;
322844961713Sgirish 				statsp->mac_stats.link_speed = 1000;
322944961713Sgirish 			} else if (statsp->port_stats.lb_mode
323044961713Sgirish 			    == nxge_lb_ext100) {
323144961713Sgirish 				/* BCM5464R 100mbps external loopback mode */
323244961713Sgirish 				bmcr.value = 0;
323344961713Sgirish 				bmcr.bits.speed_sel = 1;
323444961713Sgirish 				bmcr.bits.duplex_mode = 1;
323544961713Sgirish 				statsp->mac_stats.link_speed = 100;
323644961713Sgirish 			} else if (statsp->port_stats.lb_mode
323744961713Sgirish 			    == nxge_lb_ext10) {
323844961713Sgirish 				/* BCM5464R 10mbps external loopback mode */
323944961713Sgirish 				bmcr.value = 0;
324044961713Sgirish 				bmcr.bits.duplex_mode = 1;
324144961713Sgirish 				statsp->mac_stats.link_speed = 10;
324244961713Sgirish 			}
324344961713Sgirish 		}
324444961713Sgirish 	}
324544961713Sgirish 
324644961713Sgirish 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
3247adfcba55Sjoycey #if defined(__i386)
3248adfcba55Sjoycey 			(uint8_t)(uint32_t)(&mii_regs->bmcr),
3249adfcba55Sjoycey #else
325044961713Sgirish 			(uint8_t)(uint64_t)(&mii_regs->bmcr),
3251adfcba55Sjoycey #endif
325244961713Sgirish 			bmcr.value)) != NXGE_OK)
325344961713Sgirish 		goto fail;
325444961713Sgirish 
325544961713Sgirish 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
3256adfcba55Sjoycey #if defined(__i386)
3257adfcba55Sjoycey 		(uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
3258adfcba55Sjoycey #else
325944961713Sgirish 		(uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
3260adfcba55Sjoycey #endif
326144961713Sgirish 		goto fail;
326244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "bmcr = 0x%04X", bmcr.value));
326344961713Sgirish 
326444961713Sgirish 	/*
326544961713Sgirish 	 * Initialize the xcvr status kept in the context structure.
326644961713Sgirish 	 */
326744961713Sgirish 	nxgep->soft_bmsr.value = 0;
326844961713Sgirish 
326944961713Sgirish 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
3270adfcba55Sjoycey #if defined(__i386)
3271adfcba55Sjoycey 		(uint8_t)(uint32_t)(&mii_regs->bmsr),
3272adfcba55Sjoycey #else
327344961713Sgirish 		(uint8_t)(uint64_t)(&mii_regs->bmsr),
3274adfcba55Sjoycey #endif
327544961713Sgirish 			&nxgep->bmsr.value)) != NXGE_OK)
327644961713Sgirish 		goto fail;
327744961713Sgirish 
327844961713Sgirish 	statsp->mac_stats.xcvr_inits++;
327944961713Sgirish 	nxgep->bmsr.value = 0;
328044961713Sgirish 
328144961713Sgirish fail:
328244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
328344961713Sgirish 			"<== nxge_mii_xcvr_init status 0x%x", status));
328444961713Sgirish 	return (status);
328544961713Sgirish }
328644961713Sgirish 
3287d81011f0Ssbehera nxge_status_t
3288d81011f0Ssbehera nxge_mii_xcvr_fiber_init(p_nxge_t nxgep)
3289d81011f0Ssbehera {
3290d81011f0Ssbehera 	p_nxge_param_t	param_arr;
3291d81011f0Ssbehera 	p_nxge_stats_t	statsp;
3292d81011f0Ssbehera 	uint8_t		xcvr_portn;
3293d81011f0Ssbehera 	p_mii_regs_t	mii_regs;
3294d81011f0Ssbehera 	mii_bmcr_t	bmcr;
3295d81011f0Ssbehera 	mii_bmsr_t	bmsr;
3296d81011f0Ssbehera 	mii_gcr_t	gcr;
3297d81011f0Ssbehera 	mii_esr_t	esr;
3298d81011f0Ssbehera 	mii_aux_ctl_t	bcm5464r_aux;
3299d81011f0Ssbehera 	int		status = NXGE_OK;
3300d81011f0Ssbehera 
3301d81011f0Ssbehera 	uint_t delay;
3302d81011f0Ssbehera 
3303d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_fiber_init"));
3304d81011f0Ssbehera 
3305d81011f0Ssbehera 	param_arr = nxgep->param_arr;
3306d81011f0Ssbehera 	statsp = nxgep->statsp;
3307d81011f0Ssbehera 	xcvr_portn = statsp->mac_stats.xcvr_portn;
3308d81011f0Ssbehera 
3309d81011f0Ssbehera 	mii_regs = NULL;
3310d81011f0Ssbehera 
3311d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3312d81011f0Ssbehera 	    "nxge_mii_xcvr_fiber_init: "
3313d81011f0Ssbehera 	    "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value));
3314d81011f0Ssbehera 
3315d81011f0Ssbehera 	/*
3316d81011f0Ssbehera 	 * Reset the transceiver.
3317d81011f0Ssbehera 	 */
3318d81011f0Ssbehera 	delay = 0;
3319d81011f0Ssbehera 	bmcr.value = 0;
3320d81011f0Ssbehera 	bmcr.bits.reset = 1;
3321d81011f0Ssbehera 
3322d81011f0Ssbehera #if defined(__i386)
3323d81011f0Ssbehera 
3324d81011f0Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
3325d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
3326d81011f0Ssbehera 		goto fail;
3327d81011f0Ssbehera #else
3328d81011f0Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
3329d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
3330d81011f0Ssbehera 		goto fail;
3331d81011f0Ssbehera #endif
3332d81011f0Ssbehera 	do {
3333d81011f0Ssbehera 		drv_usecwait(500);
3334d81011f0Ssbehera #if defined(__i386)
3335d81011f0Ssbehera 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
3336d81011f0Ssbehera 		    (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value))
3337d81011f0Ssbehera 		    != NXGE_OK)
3338d81011f0Ssbehera 			goto fail;
3339d81011f0Ssbehera #else
3340d81011f0Ssbehera 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
3341d81011f0Ssbehera 		    (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value))
3342d81011f0Ssbehera 		    != NXGE_OK)
3343d81011f0Ssbehera 			goto fail;
3344d81011f0Ssbehera #endif
3345d81011f0Ssbehera 		delay++;
3346d81011f0Ssbehera 	} while ((bmcr.bits.reset) && (delay < 1000));
3347d81011f0Ssbehera 	if (delay == 1000) {
3348d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed."));
3349d81011f0Ssbehera 		goto fail;
3350d81011f0Ssbehera 	}
3351d81011f0Ssbehera 
3352d81011f0Ssbehera #if defined(__i386)
3353d81011f0Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
3354d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK)
3355d81011f0Ssbehera 		goto fail;
3356d81011f0Ssbehera #else
3357d81011f0Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
3358d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK)
3359d81011f0Ssbehera 		goto fail;
3360d81011f0Ssbehera #endif
3361d81011f0Ssbehera 
3362d81011f0Ssbehera 	param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able;
3363d81011f0Ssbehera 	param_arr[param_anar_100T4].value = 0;
3364d81011f0Ssbehera 	param_arr[param_anar_100fdx].value = 0;
3365d81011f0Ssbehera 	param_arr[param_anar_100hdx].value = 0;
3366d81011f0Ssbehera 	param_arr[param_anar_10fdx].value = 0;
3367d81011f0Ssbehera 	param_arr[param_anar_10hdx].value = 0;
3368d81011f0Ssbehera 
3369d81011f0Ssbehera 	/*
3370d81011f0Ssbehera 	 * Initialize the xcvr statistics.
3371d81011f0Ssbehera 	 */
3372d81011f0Ssbehera 	statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able;
3373d81011f0Ssbehera 	statsp->mac_stats.cap_100T4 = 0;
3374d81011f0Ssbehera 	statsp->mac_stats.cap_100fdx = 0;
3375d81011f0Ssbehera 	statsp->mac_stats.cap_100hdx = 0;
3376d81011f0Ssbehera 	statsp->mac_stats.cap_10fdx = 0;
3377d81011f0Ssbehera 	statsp->mac_stats.cap_10hdx = 0;
3378d81011f0Ssbehera 	statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value;
3379d81011f0Ssbehera 	statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value;
3380d81011f0Ssbehera 
3381d81011f0Ssbehera 	/*
3382d81011f0Ssbehera 	 * Initialize the xcvr advertised capability statistics.
3383d81011f0Ssbehera 	 */
3384d81011f0Ssbehera 	statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value;
3385d81011f0Ssbehera 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
3386d81011f0Ssbehera 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
3387d81011f0Ssbehera 	statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value;
3388d81011f0Ssbehera 	statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value;
3389d81011f0Ssbehera 	statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value;
3390d81011f0Ssbehera 	statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value;
3391d81011f0Ssbehera 	statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value;
3392d81011f0Ssbehera 	statsp->mac_stats.adv_cap_asmpause =
3393d81011f0Ssbehera 	    param_arr[param_anar_asmpause].value;
3394d81011f0Ssbehera 	statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
3395d81011f0Ssbehera 
3396d81011f0Ssbehera 	/*
3397d81011f0Ssbehera 	 * Check for extended status just in case we're
3398d81011f0Ssbehera 	 * running a Gigibit phy.
3399d81011f0Ssbehera 	 */
3400d81011f0Ssbehera 	if (bmsr.bits.extend_status) {
3401d81011f0Ssbehera #if defined(__i386)
3402d81011f0Ssbehera 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
3403d81011f0Ssbehera 		    (uint8_t)(uint32_t)(&mii_regs->esr), &esr.value)) !=
3404d81011f0Ssbehera 		    NXGE_OK)
3405d81011f0Ssbehera 			goto fail;
3406d81011f0Ssbehera #else
3407d81011f0Ssbehera 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
3408d81011f0Ssbehera 		    (uint8_t)(uint64_t)(&mii_regs->esr), &esr.value)) !=
3409d81011f0Ssbehera 		    NXGE_OK)
3410d81011f0Ssbehera 			goto fail;
3411d81011f0Ssbehera #endif
3412d81011f0Ssbehera 		param_arr[param_anar_1000fdx].value &=
3413d81011f0Ssbehera 		    esr.bits.link_1000fdx;
3414d81011f0Ssbehera 		param_arr[param_anar_1000hdx].value = 0;
3415d81011f0Ssbehera 
3416d81011f0Ssbehera 		statsp->mac_stats.cap_1000fdx =
3417d81011f0Ssbehera 		    (esr.bits.link_1000Xfdx || esr.bits.link_1000fdx);
3418d81011f0Ssbehera 		statsp->mac_stats.cap_1000hdx = 0;
3419d81011f0Ssbehera 	} else {
3420d81011f0Ssbehera 		param_arr[param_anar_1000fdx].value = 0;
3421d81011f0Ssbehera 		param_arr[param_anar_1000hdx].value = 0;
3422d81011f0Ssbehera 	}
3423d81011f0Ssbehera 
3424d81011f0Ssbehera 	/*
3425d81011f0Ssbehera 	 * Initialize 1G Statistics once the capability is established.
3426d81011f0Ssbehera 	 */
3427d81011f0Ssbehera 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
3428d81011f0Ssbehera 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
3429d81011f0Ssbehera 
3430d81011f0Ssbehera 	/*
3431d81011f0Ssbehera 	 * Initialize the link statistics.
3432d81011f0Ssbehera 	 */
3433d81011f0Ssbehera 	statsp->mac_stats.link_T4 = 0;
3434d81011f0Ssbehera 	statsp->mac_stats.link_asmpause = 0;
3435d81011f0Ssbehera 	statsp->mac_stats.link_pause = 0;
3436d81011f0Ssbehera 	statsp->mac_stats.link_speed = 0;
3437d81011f0Ssbehera 	statsp->mac_stats.link_duplex = 0;
3438d81011f0Ssbehera 	statsp->mac_stats.link_up = 0;
3439d81011f0Ssbehera 
3440d81011f0Ssbehera 	/*
3441d81011f0Ssbehera 	 * Switch off Auto-negotiation, 100M and full duplex.
3442d81011f0Ssbehera 	 */
3443d81011f0Ssbehera 	bmcr.value = 0;
3444d81011f0Ssbehera #if defined(__i386)
3445d81011f0Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
3446d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
3447d81011f0Ssbehera 		goto fail;
3448d81011f0Ssbehera #else
3449d81011f0Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
3450d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
3451d81011f0Ssbehera 		goto fail;
3452d81011f0Ssbehera #endif
3453d81011f0Ssbehera 
3454d81011f0Ssbehera 	if ((statsp->port_stats.lb_mode == nxge_lb_phy) ||
3455d81011f0Ssbehera 	    (statsp->port_stats.lb_mode == nxge_lb_phy1000)) {
3456d81011f0Ssbehera 		bmcr.bits.loopback = 1;
3457d81011f0Ssbehera 		bmcr.bits.enable_autoneg = 0;
3458d81011f0Ssbehera 		if (statsp->port_stats.lb_mode == nxge_lb_phy1000)
3459d81011f0Ssbehera 			bmcr.bits.speed_1000_sel = 1;
3460d81011f0Ssbehera 		bmcr.bits.duplex_mode = 1;
3461d81011f0Ssbehera 		param_arr[param_autoneg].value = 0;
3462d81011f0Ssbehera 	} else {
3463d81011f0Ssbehera 		bmcr.bits.loopback = 0;
3464d81011f0Ssbehera 	}
3465d81011f0Ssbehera 
3466d81011f0Ssbehera 	if (statsp->port_stats.lb_mode == nxge_lb_ext1000) {
3467d81011f0Ssbehera 		param_arr[param_autoneg].value = 0;
3468d81011f0Ssbehera 		bcm5464r_aux.value = 0;
3469d81011f0Ssbehera 		bcm5464r_aux.bits.ext_lb = 1;
3470d81011f0Ssbehera 		bcm5464r_aux.bits.write_1 = 1;
3471d81011f0Ssbehera 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
3472d81011f0Ssbehera 		    BCM5464R_AUX_CTL, bcm5464r_aux.value)) != NXGE_OK)
3473d81011f0Ssbehera 			goto fail;
3474d81011f0Ssbehera 	}
3475d81011f0Ssbehera 
3476d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode."));
3477d81011f0Ssbehera 	bmcr.bits.speed_1000_sel = 1;
3478d81011f0Ssbehera 	bmcr.bits.speed_sel = 0;
3479d81011f0Ssbehera 	bmcr.bits.duplex_mode = 1;
3480d81011f0Ssbehera 	statsp->mac_stats.link_speed = 1000;
3481d81011f0Ssbehera 	statsp->mac_stats.link_duplex = 2;
3482d81011f0Ssbehera 
3483d81011f0Ssbehera 	if ((statsp->port_stats.lb_mode == nxge_lb_ext1000)) {
3484d81011f0Ssbehera 		/* BCM5464R 1000mbps external loopback mode */
3485d81011f0Ssbehera 		gcr.value = 0;
3486d81011f0Ssbehera 		gcr.bits.ms_mode_en = 1;
3487d81011f0Ssbehera 		gcr.bits.master = 1;
3488d81011f0Ssbehera #if defined(__i386)
3489d81011f0Ssbehera 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
3490d81011f0Ssbehera 		    (uint8_t)(uint32_t)(&mii_regs->gcr),
3491d81011f0Ssbehera 		    gcr.value)) != NXGE_OK)
3492d81011f0Ssbehera 			goto fail;
3493d81011f0Ssbehera #else
3494d81011f0Ssbehera 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
3495d81011f0Ssbehera 		    (uint8_t)(uint64_t)(&mii_regs->gcr),
3496d81011f0Ssbehera 		    gcr.value)) != NXGE_OK)
3497d81011f0Ssbehera 			goto fail;
3498d81011f0Ssbehera #endif
3499d81011f0Ssbehera 		bmcr.value = 0;
3500d81011f0Ssbehera 		bmcr.bits.speed_1000_sel = 1;
3501d81011f0Ssbehera 		statsp->mac_stats.link_speed = 1000;
3502d81011f0Ssbehera 	}
3503d81011f0Ssbehera 
3504d81011f0Ssbehera #if defined(__i386)
3505d81011f0Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
3506d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr),
3507d81011f0Ssbehera 	    bmcr.value)) != NXGE_OK)
3508d81011f0Ssbehera 		goto fail;
3509d81011f0Ssbehera #else
3510d81011f0Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
3511d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr),
3512d81011f0Ssbehera 	    bmcr.value)) != NXGE_OK)
3513d81011f0Ssbehera 		goto fail;
3514d81011f0Ssbehera #endif
3515d81011f0Ssbehera 
3516d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3517d81011f0Ssbehera 	    "nxge_mii_xcvr_fiber_init: value wrote bmcr = 0x%x",
3518d81011f0Ssbehera 	    bmcr.value));
3519d81011f0Ssbehera 
3520d81011f0Ssbehera #if defined(__i386)
3521d81011f0Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
3522d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
3523d81011f0Ssbehera 		goto fail;
3524d81011f0Ssbehera #else
3525d81011f0Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
3526d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
3527d81011f0Ssbehera 		goto fail;
3528d81011f0Ssbehera #endif
3529d81011f0Ssbehera 
3530d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3531d81011f0Ssbehera 	    "nxge_mii_xcvr_fiber_init: read bmcr = 0x%04X", bmcr.value));
3532d81011f0Ssbehera 
3533d81011f0Ssbehera 	/*
3534d81011f0Ssbehera 	 * Initialize the xcvr status kept in the context structure.
3535d81011f0Ssbehera 	 */
3536d81011f0Ssbehera 	nxgep->soft_bmsr.value = 0;
3537d81011f0Ssbehera #if defined(__i386)
3538d81011f0Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
3539d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmsr),
3540d81011f0Ssbehera 	    &nxgep->bmsr.value)) != NXGE_OK)
3541d81011f0Ssbehera 		goto fail;
3542d81011f0Ssbehera #else
3543d81011f0Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
3544d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmsr),
3545d81011f0Ssbehera 	    &nxgep->bmsr.value)) != NXGE_OK)
3546d81011f0Ssbehera 		goto fail;
3547d81011f0Ssbehera #endif
3548d81011f0Ssbehera 
3549d81011f0Ssbehera 	statsp->mac_stats.xcvr_inits++;
3550d81011f0Ssbehera 	nxgep->bmsr.value = 0;
3551d81011f0Ssbehera 
3552d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3553d81011f0Ssbehera 	    "<== nxge_mii_xcvr_fiber_init status 0x%x", status));
3554d81011f0Ssbehera 	return (status);
3555d81011f0Ssbehera 
3556d81011f0Ssbehera fail:
3557d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3558d81011f0Ssbehera 	    "<== nxge_mii_xcvr_fiber_init status 0x%x", status));
3559d81011f0Ssbehera 	return (status);
3560d81011f0Ssbehera }
3561d81011f0Ssbehera 
356244961713Sgirish /* Read from a MII compliant register */
356344961713Sgirish 
356444961713Sgirish nxge_status_t
356544961713Sgirish nxge_mii_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg,
356644961713Sgirish 		uint16_t *value)
356744961713Sgirish {
356844961713Sgirish 	npi_status_t rs = NPI_SUCCESS;
356944961713Sgirish 
357044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_read: xcvr_port<%d>"
357144961713Sgirish 			"xcvr_reg<%d>", xcvr_portn, xcvr_reg));
357244961713Sgirish 
3573*321febdeSsbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
357444961713Sgirish 
3575d81011f0Ssbehera 	if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
3576d81011f0Ssbehera 	    (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) {
357744961713Sgirish 		if ((rs = npi_mac_mif_mii_read(nxgep->npi_handle,
357844961713Sgirish 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
357944961713Sgirish 			goto fail;
35802e59129aSraghus 	} else if ((nxgep->mac.portmode == PORT_1G_FIBER) ||
35812e59129aSraghus 	    (nxgep->mac.portmode == PORT_1G_SERDES)) {
358244961713Sgirish 		if ((rs = npi_mac_pcs_mii_read(nxgep->npi_handle,
358344961713Sgirish 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
358444961713Sgirish 			goto fail;
358544961713Sgirish 	} else
358644961713Sgirish 		goto fail;
358744961713Sgirish 
3588*321febdeSsbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
358944961713Sgirish 
359044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_read: xcvr_port<%d>"
359144961713Sgirish 			"xcvr_reg<%d> value=0x%x",
359244961713Sgirish 			xcvr_portn, xcvr_reg, *value));
359344961713Sgirish 	return (NXGE_OK);
359444961713Sgirish fail:
3595*321febdeSsbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
359644961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
359744961713Sgirish 			"nxge_mii_read: Failed to read mii on xcvr %d",
359844961713Sgirish 			xcvr_portn));
359944961713Sgirish 
360044961713Sgirish 	return (NXGE_ERROR | rs);
360144961713Sgirish }
360244961713Sgirish 
360344961713Sgirish /* Write to a MII compliant Register */
360444961713Sgirish 
360544961713Sgirish nxge_status_t
360644961713Sgirish nxge_mii_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg,
360744961713Sgirish 		uint16_t value)
360844961713Sgirish {
360944961713Sgirish 	npi_status_t rs = NPI_SUCCESS;
361044961713Sgirish 
361144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_write: xcvr_port<%d>"
361244961713Sgirish 			"xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg,
361344961713Sgirish 			value));
361444961713Sgirish 
3615*321febdeSsbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
361644961713Sgirish 
3617d81011f0Ssbehera 	if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
3618d81011f0Ssbehera 	    (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) {
361944961713Sgirish 		if ((rs = npi_mac_mif_mii_write(nxgep->npi_handle,
362044961713Sgirish 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
362144961713Sgirish 			goto fail;
36222e59129aSraghus 	} else if ((nxgep->mac.portmode == PORT_1G_FIBER) ||
36232e59129aSraghus 	    (nxgep->mac.portmode == PORT_1G_SERDES)) {
362444961713Sgirish 		if ((rs = npi_mac_pcs_mii_write(nxgep->npi_handle,
362544961713Sgirish 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
362644961713Sgirish 			goto fail;
362744961713Sgirish 	} else
362844961713Sgirish 		goto fail;
362944961713Sgirish 
3630*321febdeSsbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
363144961713Sgirish 
363244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_write: xcvr_port<%d>"
363344961713Sgirish 			"xcvr_reg<%d>", xcvr_portn, xcvr_reg));
363444961713Sgirish 	return (NXGE_OK);
363544961713Sgirish fail:
3636*321febdeSsbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
363744961713Sgirish 
363844961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
363944961713Sgirish 			"nxge_mii_write: Failed to write mii on xcvr %d",
364044961713Sgirish 			xcvr_portn));
364144961713Sgirish 
364244961713Sgirish 	return (NXGE_ERROR | rs);
364344961713Sgirish }
364444961713Sgirish 
364544961713Sgirish /* Perform read from Clause45 serdes / transceiver device */
364644961713Sgirish 
364744961713Sgirish nxge_status_t
364844961713Sgirish nxge_mdio_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device,
364944961713Sgirish 		uint16_t xcvr_reg, uint16_t *value)
365044961713Sgirish {
365144961713Sgirish 	npi_status_t rs = NPI_SUCCESS;
365244961713Sgirish 
365344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_read: xcvr_port<%d>",
365444961713Sgirish 			xcvr_portn));
365544961713Sgirish 
365653560810Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
365744961713Sgirish 
365844961713Sgirish 	if ((rs = npi_mac_mif_mdio_read(nxgep->npi_handle,
365944961713Sgirish 			xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS)
366044961713Sgirish 		goto fail;
366144961713Sgirish 
366253560810Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
366344961713Sgirish 
366444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_read: xcvr_port<%d>",
366544961713Sgirish 			xcvr_portn));
366644961713Sgirish 	return (NXGE_OK);
366744961713Sgirish fail:
366853560810Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
366944961713Sgirish 
367044961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
367144961713Sgirish 			"nxge_mdio_read: Failed to read mdio on xcvr %d",
367244961713Sgirish 			xcvr_portn));
367344961713Sgirish 
367444961713Sgirish 	return (NXGE_ERROR | rs);
367544961713Sgirish }
367644961713Sgirish 
367744961713Sgirish /* Perform write to Clause45 serdes / transceiver device */
367844961713Sgirish 
367944961713Sgirish nxge_status_t
368044961713Sgirish nxge_mdio_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device,
368144961713Sgirish 		uint16_t xcvr_reg, uint16_t value)
368244961713Sgirish {
368344961713Sgirish 	npi_status_t rs = NPI_SUCCESS;
368444961713Sgirish 
368544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_write: xcvr_port<%d>",
368644961713Sgirish 			xcvr_portn));
368744961713Sgirish 
368853560810Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
368944961713Sgirish 
369044961713Sgirish 	if ((rs = npi_mac_mif_mdio_write(nxgep->npi_handle,
369144961713Sgirish 			xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS)
369244961713Sgirish 		goto fail;
369344961713Sgirish 
369453560810Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
369544961713Sgirish 
369644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_write: xcvr_port<%d>",
369744961713Sgirish 			xcvr_portn));
369844961713Sgirish 	return (NXGE_OK);
369944961713Sgirish fail:
370053560810Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
370144961713Sgirish 
370244961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
370344961713Sgirish 			"nxge_mdio_write: Failed to write mdio on xcvr %d",
370444961713Sgirish 			xcvr_portn));
370544961713Sgirish 
370644961713Sgirish 	return (NXGE_ERROR | rs);
370744961713Sgirish }
370844961713Sgirish 
370944961713Sgirish 
371044961713Sgirish /* Check MII to see if there is any link status change */
371144961713Sgirish 
371244961713Sgirish nxge_status_t
3713a3c5bd6dSspeer nxge_mii_check(p_nxge_t nxgep, mii_bmsr_t bmsr, mii_bmsr_t bmsr_ints,
3714a3c5bd6dSspeer 		nxge_link_state_t *link_up)
371544961713Sgirish {
371644961713Sgirish 	p_nxge_param_t	param_arr;
371744961713Sgirish 	p_nxge_stats_t	statsp;
371844961713Sgirish 	p_mii_regs_t	mii_regs;
371944961713Sgirish 	p_mii_bmsr_t	soft_bmsr;
372044961713Sgirish 	mii_anar_t	anar;
372144961713Sgirish 	mii_anlpar_t	anlpar;
372244961713Sgirish 	mii_anar_t	an_common;
372344961713Sgirish 	mii_aner_t	aner;
372444961713Sgirish 	mii_gsr_t	gsr;
372544961713Sgirish 	nxge_status_t	status = NXGE_OK;
372644961713Sgirish 
372744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_check"));
372844961713Sgirish 
372944961713Sgirish 	mii_regs = NULL;
373044961713Sgirish 	param_arr = nxgep->param_arr;
373144961713Sgirish 	statsp = nxgep->statsp;
373244961713Sgirish 	soft_bmsr = &nxgep->soft_bmsr;
3733a3c5bd6dSspeer 	*link_up = LINK_NO_CHANGE;
373444961713Sgirish 
3735d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3736d81011f0Ssbehera 	    "==> nxge_mii_check bmsr 0x%x bmsr_int 0x%x",
3737d81011f0Ssbehera 	    bmsr.value, bmsr_ints.value));
3738d81011f0Ssbehera 
373944961713Sgirish 	if (bmsr_ints.bits.link_status) {
3740d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3741d81011f0Ssbehera 		    "==> nxge_mii_check (link up) bmsr 0x%x bmsr_int 0x%x",
3742d81011f0Ssbehera 		    bmsr.value, bmsr_ints.value));
374344961713Sgirish 		if (bmsr.bits.link_status) {
374444961713Sgirish 			soft_bmsr->bits.link_status = 1;
3745d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3746d81011f0Ssbehera 		    "==> nxge_mii_check (link up) soft bmsr 0x%x bmsr_int "
3747d81011f0Ssbehera 		    "0x%x", bmsr.value, bmsr_ints.value));
374844961713Sgirish 		} else {
374944961713Sgirish 			statsp->mac_stats.link_up = 0;
375044961713Sgirish 			soft_bmsr->bits.link_status = 0;
375144961713Sgirish 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
375244961713Sgirish 					"Link down cable problem"));
3753a3c5bd6dSspeer 			*link_up = LINK_IS_DOWN;
375444961713Sgirish 		}
375544961713Sgirish 	}
375644961713Sgirish 
3757d81011f0Ssbehera 	if (nxgep->mac.portmode == PORT_1G_COPPER &&
3758d81011f0Ssbehera 	    param_arr[param_autoneg].value) {
375944961713Sgirish 		if (bmsr_ints.bits.auto_neg_complete) {
376044961713Sgirish 			if (bmsr.bits.auto_neg_complete)
376144961713Sgirish 				soft_bmsr->bits.auto_neg_complete = 1;
376244961713Sgirish 			else
376344961713Sgirish 				soft_bmsr->bits.auto_neg_complete = 0;
376444961713Sgirish 		}
376544961713Sgirish 		if (soft_bmsr->bits.link_status == 0) {
376644961713Sgirish 			statsp->mac_stats.link_T4 = 0;
376744961713Sgirish 			statsp->mac_stats.link_speed = 0;
376844961713Sgirish 			statsp->mac_stats.link_duplex = 0;
376944961713Sgirish 			statsp->mac_stats.link_asmpause = 0;
377044961713Sgirish 			statsp->mac_stats.link_pause = 0;
377144961713Sgirish 			statsp->mac_stats.lp_cap_autoneg = 0;
377244961713Sgirish 			statsp->mac_stats.lp_cap_100T4 = 0;
377344961713Sgirish 			statsp->mac_stats.lp_cap_1000fdx = 0;
377444961713Sgirish 			statsp->mac_stats.lp_cap_1000hdx = 0;
377544961713Sgirish 			statsp->mac_stats.lp_cap_100fdx = 0;
377644961713Sgirish 			statsp->mac_stats.lp_cap_100hdx = 0;
377744961713Sgirish 			statsp->mac_stats.lp_cap_10fdx = 0;
377844961713Sgirish 			statsp->mac_stats.lp_cap_10hdx = 0;
377944961713Sgirish 			statsp->mac_stats.lp_cap_10gfdx = 0;
378044961713Sgirish 			statsp->mac_stats.lp_cap_10ghdx = 0;
378144961713Sgirish 			statsp->mac_stats.lp_cap_asmpause = 0;
378244961713Sgirish 			statsp->mac_stats.lp_cap_pause = 0;
378344961713Sgirish 		}
378444961713Sgirish 	} else
378544961713Sgirish 		soft_bmsr->bits.auto_neg_complete = 1;
378644961713Sgirish 
378744961713Sgirish 	if ((bmsr_ints.bits.link_status ||
378844961713Sgirish 		bmsr_ints.bits.auto_neg_complete) &&
378944961713Sgirish 		soft_bmsr->bits.link_status &&
379044961713Sgirish 		soft_bmsr->bits.auto_neg_complete) {
379144961713Sgirish 		statsp->mac_stats.link_up = 1;
3792d81011f0Ssbehera 
3793d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3794d81011f0Ssbehera 		    "==> nxge_mii_check "
3795d81011f0Ssbehera 		    "(auto negotiation complete or link up) "
3796d81011f0Ssbehera 		    "soft bmsr 0x%x bmsr_int 0x%x",
3797d81011f0Ssbehera 		    bmsr.value, bmsr_ints.value));
3798d81011f0Ssbehera 
3799d81011f0Ssbehera 		if (nxgep->mac.portmode == PORT_1G_COPPER &&
3800d81011f0Ssbehera 		    param_arr[param_autoneg].value) {
380144961713Sgirish 			if ((status = nxge_mii_read(nxgep,
380244961713Sgirish 				statsp->mac_stats.xcvr_portn,
3803adfcba55Sjoycey #if defined(__i386)
3804adfcba55Sjoycey 				(uint8_t)(uint32_t)(&mii_regs->anar),
3805adfcba55Sjoycey #else
380644961713Sgirish 				(uint8_t)(uint64_t)(&mii_regs->anar),
3807adfcba55Sjoycey #endif
380844961713Sgirish 					&anar.value)) != NXGE_OK)
380944961713Sgirish 				goto fail;
381044961713Sgirish 			if ((status = nxge_mii_read(nxgep,
381144961713Sgirish 				statsp->mac_stats.xcvr_portn,
3812adfcba55Sjoycey #if defined(__i386)
3813adfcba55Sjoycey 				(uint8_t)(uint32_t)(&mii_regs->anlpar),
3814adfcba55Sjoycey #else
381544961713Sgirish 				(uint8_t)(uint64_t)(&mii_regs->anlpar),
3816adfcba55Sjoycey #endif
381744961713Sgirish 					&anlpar.value)) != NXGE_OK)
381844961713Sgirish 				goto fail;
381944961713Sgirish 			if ((status = nxge_mii_read(nxgep,
382044961713Sgirish 				statsp->mac_stats.xcvr_portn,
3821adfcba55Sjoycey #if defined(__i386)
3822adfcba55Sjoycey 				(uint8_t)(uint32_t)(&mii_regs->aner),
3823adfcba55Sjoycey #else
382444961713Sgirish 				(uint8_t)(uint64_t)(&mii_regs->aner),
3825adfcba55Sjoycey #endif
382644961713Sgirish 					&aner.value)) != NXGE_OK)
382744961713Sgirish 				goto fail;
382844961713Sgirish 			statsp->mac_stats.lp_cap_autoneg = aner.bits.lp_an_able;
382944961713Sgirish 			statsp->mac_stats.lp_cap_100T4 = anlpar.bits.cap_100T4;
383044961713Sgirish 			statsp->mac_stats.lp_cap_100fdx =
383144961713Sgirish 							anlpar.bits.cap_100fdx;
383244961713Sgirish 			statsp->mac_stats.lp_cap_100hdx =
383344961713Sgirish 							anlpar.bits.cap_100hdx;
383444961713Sgirish 			statsp->mac_stats.lp_cap_10fdx = anlpar.bits.cap_10fdx;
383544961713Sgirish 			statsp->mac_stats.lp_cap_10hdx = anlpar.bits.cap_10hdx;
383644961713Sgirish 			statsp->mac_stats.lp_cap_asmpause =
383744961713Sgirish 						anlpar.bits.cap_asmpause;
383844961713Sgirish 			statsp->mac_stats.lp_cap_pause = anlpar.bits.cap_pause;
383944961713Sgirish 			an_common.value = anar.value & anlpar.value;
384044961713Sgirish 			if (param_arr[param_anar_1000fdx].value ||
384144961713Sgirish 				param_arr[param_anar_1000hdx].value) {
384244961713Sgirish 				if ((status = nxge_mii_read(nxgep,
384344961713Sgirish 					statsp->mac_stats.xcvr_portn,
3844adfcba55Sjoycey #if defined(__i386)
3845adfcba55Sjoycey 					(uint8_t)(uint32_t)(&mii_regs->gsr),
3846adfcba55Sjoycey #else
384744961713Sgirish 					(uint8_t)(uint64_t)(&mii_regs->gsr),
3848adfcba55Sjoycey #endif
384944961713Sgirish 						&gsr.value))
385044961713Sgirish 						!= NXGE_OK)
385144961713Sgirish 					goto fail;
385244961713Sgirish 				statsp->mac_stats.lp_cap_1000fdx =
385344961713Sgirish 					gsr.bits.link_1000fdx;
385444961713Sgirish 				statsp->mac_stats.lp_cap_1000hdx =
385544961713Sgirish 					gsr.bits.link_1000hdx;
385644961713Sgirish 				if (param_arr[param_anar_1000fdx].value &&
385744961713Sgirish 					gsr.bits.link_1000fdx) {
385844961713Sgirish 					statsp->mac_stats.link_speed = 1000;
385944961713Sgirish 					statsp->mac_stats.link_duplex = 2;
386044961713Sgirish 				} else if (
386144961713Sgirish 					param_arr[param_anar_1000hdx].value &&
386244961713Sgirish 						gsr.bits.link_1000hdx) {
386344961713Sgirish 					statsp->mac_stats.link_speed = 1000;
386444961713Sgirish 					statsp->mac_stats.link_duplex = 1;
386544961713Sgirish 				}
386644961713Sgirish 			}
386744961713Sgirish 			if ((an_common.value != 0) &&
386844961713Sgirish 					!(statsp->mac_stats.link_speed)) {
386944961713Sgirish 				if (an_common.bits.cap_100T4) {
387044961713Sgirish 					statsp->mac_stats.link_T4 = 1;
387144961713Sgirish 					statsp->mac_stats.link_speed = 100;
387244961713Sgirish 					statsp->mac_stats.link_duplex = 1;
387344961713Sgirish 				} else if (an_common.bits.cap_100fdx) {
387444961713Sgirish 					statsp->mac_stats.link_speed = 100;
387544961713Sgirish 					statsp->mac_stats.link_duplex = 2;
387644961713Sgirish 				} else if (an_common.bits.cap_100hdx) {
387744961713Sgirish 					statsp->mac_stats.link_speed = 100;
387844961713Sgirish 					statsp->mac_stats.link_duplex = 1;
387944961713Sgirish 				} else if (an_common.bits.cap_10fdx) {
388044961713Sgirish 					statsp->mac_stats.link_speed = 10;
388144961713Sgirish 					statsp->mac_stats.link_duplex = 2;
388244961713Sgirish 				} else if (an_common.bits.cap_10hdx) {
388344961713Sgirish 					statsp->mac_stats.link_speed = 10;
388444961713Sgirish 					statsp->mac_stats.link_duplex = 1;
388544961713Sgirish 				} else {
388644961713Sgirish 					goto fail;
388744961713Sgirish 				}
388844961713Sgirish 			}
388944961713Sgirish 			if (statsp->mac_stats.link_duplex != 1) {
389044961713Sgirish 				statsp->mac_stats.link_asmpause =
389144961713Sgirish 					an_common.bits.cap_asmpause;
389244961713Sgirish 				if (statsp->mac_stats.link_asmpause)
389344961713Sgirish 				if ((statsp->mac_stats.cap_pause == 0) &&
389444961713Sgirish 						(statsp->mac_stats.lp_cap_pause
389544961713Sgirish 						== 1))
389644961713Sgirish 						statsp->mac_stats.link_pause
389744961713Sgirish 						= 0;
389844961713Sgirish 					else
389944961713Sgirish 						statsp->mac_stats.link_pause
390044961713Sgirish 						= 1;
390144961713Sgirish 				else
390244961713Sgirish 					statsp->mac_stats.link_pause =
390344961713Sgirish 						an_common.bits.cap_pause;
390444961713Sgirish 			}
3905d81011f0Ssbehera 		} else if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) {
3906d81011f0Ssbehera 			statsp->mac_stats.link_speed = 1000;
3907d81011f0Ssbehera 			statsp->mac_stats.link_duplex = 2;
390844961713Sgirish 		}
3909a3c5bd6dSspeer 		*link_up = LINK_IS_UP;
3910a3c5bd6dSspeer 	}
3911a3c5bd6dSspeer 
3912a3c5bd6dSspeer 	if (nxgep->link_notify) {
3913a3c5bd6dSspeer 		*link_up = ((statsp->mac_stats.link_up) ? LINK_IS_UP :
3914a3c5bd6dSspeer 				LINK_IS_DOWN);
3915a3c5bd6dSspeer 		nxgep->link_notify = B_FALSE;
391644961713Sgirish 	}
391744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mii_check"));
391844961713Sgirish 	return (NXGE_OK);
391944961713Sgirish fail:
392044961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
392144961713Sgirish 			"nxge_mii_check: Unable to check MII"));
392244961713Sgirish 	return (status);
392344961713Sgirish }
392444961713Sgirish 
39252e59129aSraghus /* Check PCS to see if there is any link status change */
39262e59129aSraghus nxge_status_t
39272e59129aSraghus nxge_pcs_check(p_nxge_t nxgep, uint8_t portn, nxge_link_state_t *link_up)
39282e59129aSraghus {
39292e59129aSraghus 	p_nxge_stats_t	statsp;
39302e59129aSraghus 	nxge_status_t	status = NXGE_OK;
39312e59129aSraghus 	boolean_t	linkup;
39322e59129aSraghus 
39332e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_check"));
39342e59129aSraghus 
39352e59129aSraghus 	statsp = nxgep->statsp;
39362e59129aSraghus 	*link_up = LINK_NO_CHANGE;
39372e59129aSraghus 
39382e59129aSraghus 	(void) npi_mac_get_link_status(nxgep->npi_handle, portn, &linkup);
39392e59129aSraghus 	if (linkup) {
39402e59129aSraghus 		if (nxgep->link_notify ||
39412e59129aSraghus 		    nxgep->statsp->mac_stats.link_up == 0) {
39422e59129aSraghus 			statsp->mac_stats.link_up = 1;
39432e59129aSraghus 			statsp->mac_stats.link_speed = 1000;
39442e59129aSraghus 			statsp->mac_stats.link_duplex = 2;
39452e59129aSraghus 			*link_up = LINK_IS_UP;
39462e59129aSraghus 			nxgep->link_notify = B_FALSE;
39472e59129aSraghus 		}
39482e59129aSraghus 	} else {
39492e59129aSraghus 		if (nxgep->link_notify ||
39502e59129aSraghus 		    nxgep->statsp->mac_stats.link_up == 1) {
39512e59129aSraghus 			statsp->mac_stats.link_up = 0;
39522e59129aSraghus 			statsp->mac_stats.link_speed = 0;
39532e59129aSraghus 			statsp->mac_stats.link_duplex = 0;
39542e59129aSraghus 			*link_up = LINK_IS_DOWN;
39552e59129aSraghus 			nxgep->link_notify = B_FALSE;
39562e59129aSraghus 		}
39572e59129aSraghus 	}
39582e59129aSraghus 
39592e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_check"));
39602e59129aSraghus 	return (NXGE_OK);
39612e59129aSraghus fail:
39622e59129aSraghus 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
39632e59129aSraghus 	    "nxge_pcs_check: Unable to check PCS"));
39642e59129aSraghus 	return (status);
39652e59129aSraghus }
39662e59129aSraghus 
396744961713Sgirish /* Add a multicast address entry into the HW hash table */
396844961713Sgirish 
396944961713Sgirish nxge_status_t
397044961713Sgirish nxge_add_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp)
397144961713Sgirish {
397244961713Sgirish 	uint32_t mchash;
397344961713Sgirish 	p_hash_filter_t hash_filter;
397444961713Sgirish 	uint16_t hash_bit;
397544961713Sgirish 	boolean_t rx_init = B_FALSE;
397644961713Sgirish 	uint_t j;
397744961713Sgirish 	nxge_status_t status = NXGE_OK;
397844961713Sgirish 
397944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_add_mcast_addr"));
398044961713Sgirish 
398144961713Sgirish 	RW_ENTER_WRITER(&nxgep->filter_lock);
398244961713Sgirish 	mchash = crc32_mchash(addrp);
398344961713Sgirish 	if (nxgep->hash_filter == NULL) {
398444961713Sgirish 		NXGE_DEBUG_MSG((NULL, STR_CTL,
398544961713Sgirish 			"Allocating hash filter storage."));
398644961713Sgirish 		nxgep->hash_filter = KMEM_ZALLOC(sizeof (hash_filter_t),
398744961713Sgirish 					KM_SLEEP);
398844961713Sgirish 	}
398944961713Sgirish 	hash_filter = nxgep->hash_filter;
399044961713Sgirish 	j = mchash / HASH_REG_WIDTH;
399144961713Sgirish 	hash_bit = (1 << (mchash % HASH_REG_WIDTH));
399244961713Sgirish 	hash_filter->hash_filter_regs[j] |= hash_bit;
399344961713Sgirish 	hash_filter->hash_bit_ref_cnt[mchash]++;
399444961713Sgirish 	if (hash_filter->hash_bit_ref_cnt[mchash] == 1) {
399544961713Sgirish 		hash_filter->hash_ref_cnt++;
399644961713Sgirish 		rx_init = B_TRUE;
399744961713Sgirish 	}
399844961713Sgirish 	if (rx_init) {
399944961713Sgirish 		if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
400044961713Sgirish 			goto fail;
400144961713Sgirish 		if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
400244961713Sgirish 			goto fail;
400344961713Sgirish 	}
400444961713Sgirish 
400544961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
400644961713Sgirish 
400744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_add_mcast_addr"));
400844961713Sgirish 
400944961713Sgirish 	return (NXGE_OK);
401044961713Sgirish fail:
401144961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
401244961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_add_mcast_addr: "
401344961713Sgirish 					"Unable to add multicast address"));
401444961713Sgirish 	return (status);
401544961713Sgirish }
401644961713Sgirish 
401744961713Sgirish /* Remove a multicast address entry from the HW hash table */
401844961713Sgirish 
401944961713Sgirish nxge_status_t
402044961713Sgirish nxge_del_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp)
402144961713Sgirish {
402244961713Sgirish 	uint32_t mchash;
402344961713Sgirish 	p_hash_filter_t hash_filter;
402444961713Sgirish 	uint16_t hash_bit;
402544961713Sgirish 	boolean_t rx_init = B_FALSE;
402644961713Sgirish 	uint_t j;
402744961713Sgirish 	nxge_status_t status = NXGE_OK;
402844961713Sgirish 
402944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_del_mcast_addr"));
403044961713Sgirish 	RW_ENTER_WRITER(&nxgep->filter_lock);
403144961713Sgirish 	mchash = crc32_mchash(addrp);
403244961713Sgirish 	if (nxgep->hash_filter == NULL) {
403344961713Sgirish 		NXGE_DEBUG_MSG((NULL, STR_CTL,
403444961713Sgirish 			"Hash filter already de_allocated."));
403544961713Sgirish 		RW_EXIT(&nxgep->filter_lock);
403644961713Sgirish 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr"));
403744961713Sgirish 		return (NXGE_OK);
403844961713Sgirish 	}
403944961713Sgirish 	hash_filter = nxgep->hash_filter;
404044961713Sgirish 	hash_filter->hash_bit_ref_cnt[mchash]--;
404144961713Sgirish 	if (hash_filter->hash_bit_ref_cnt[mchash] == 0) {
404244961713Sgirish 		j = mchash / HASH_REG_WIDTH;
404344961713Sgirish 		hash_bit = (1 << (mchash % HASH_REG_WIDTH));
404444961713Sgirish 		hash_filter->hash_filter_regs[j] &= ~hash_bit;
404544961713Sgirish 		hash_filter->hash_ref_cnt--;
404644961713Sgirish 		rx_init = B_TRUE;
404744961713Sgirish 	}
404844961713Sgirish 	if (hash_filter->hash_ref_cnt == 0) {
404944961713Sgirish 		NXGE_DEBUG_MSG((NULL, STR_CTL,
405044961713Sgirish 			"De-allocating hash filter storage."));
405144961713Sgirish 		KMEM_FREE(hash_filter, sizeof (hash_filter_t));
405244961713Sgirish 		nxgep->hash_filter = NULL;
405344961713Sgirish 	}
405444961713Sgirish 
405544961713Sgirish 	if (rx_init) {
405644961713Sgirish 		if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
405744961713Sgirish 			goto fail;
405844961713Sgirish 		if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
405944961713Sgirish 			goto fail;
406044961713Sgirish 	}
406144961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
406244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr"));
406344961713Sgirish 
406444961713Sgirish 	return (NXGE_OK);
406544961713Sgirish fail:
406644961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
406744961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_del_mcast_addr: "
406844961713Sgirish 			"Unable to remove multicast address"));
406944961713Sgirish 
407044961713Sgirish 	return (status);
407144961713Sgirish }
407244961713Sgirish 
407344961713Sgirish /* Set MAC address into MAC address HW registers */
407444961713Sgirish 
407544961713Sgirish nxge_status_t
407644961713Sgirish nxge_set_mac_addr(p_nxge_t nxgep, struct ether_addr *addrp)
407744961713Sgirish {
407844961713Sgirish 	nxge_status_t status = NXGE_OK;
407944961713Sgirish 
408044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_mac_addr"));
408144961713Sgirish 
408244961713Sgirish 	MUTEX_ENTER(&nxgep->ouraddr_lock);
408344961713Sgirish 	/*
408444961713Sgirish 	 * Exit if the address is same as ouraddr or multicast or broadcast
408544961713Sgirish 	 */
408644961713Sgirish 	if (((addrp->ether_addr_octet[0] & 01) == 1) ||
408744961713Sgirish 		(ether_cmp(addrp, &etherbroadcastaddr) == 0) ||
408844961713Sgirish 		(ether_cmp(addrp, &nxgep->ouraddr) == 0)) {
408944961713Sgirish 		goto nxge_set_mac_addr_exit;
409044961713Sgirish 	}
409144961713Sgirish 	nxgep->ouraddr = *addrp;
409244961713Sgirish 	/*
409344961713Sgirish 	 * Set new interface local address and re-init device.
409444961713Sgirish 	 * This is destructive to any other streams attached
409544961713Sgirish 	 * to this device.
409644961713Sgirish 	 */
409744961713Sgirish 	RW_ENTER_WRITER(&nxgep->filter_lock);
409844961713Sgirish 	if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
409944961713Sgirish 		goto fail;
410044961713Sgirish 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
410144961713Sgirish 		goto fail;
410244961713Sgirish 
410344961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
410444961713Sgirish 	MUTEX_EXIT(&nxgep->ouraddr_lock);
410544961713Sgirish 	goto nxge_set_mac_addr_end;
410644961713Sgirish nxge_set_mac_addr_exit:
410744961713Sgirish 	MUTEX_EXIT(&nxgep->ouraddr_lock);
410844961713Sgirish nxge_set_mac_addr_end:
410944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_mac_addr"));
411044961713Sgirish 
411144961713Sgirish 	return (NXGE_OK);
411244961713Sgirish fail:
411344961713Sgirish 	MUTEX_EXIT(&nxgep->ouraddr_lock);
411444961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_mac_addr: "
411544961713Sgirish 			"Unable to set mac address"));
411644961713Sgirish 	return (status);
411744961713Sgirish }
411844961713Sgirish 
411998ecde52Stm static
412098ecde52Stm check_link_state_t
412198ecde52Stm nxge_check_link_stop(
412298ecde52Stm 	nxge_t *nxge)
412398ecde52Stm {
412498ecde52Stm 	/* If the poll has been cancelled, return STOP. */
412598ecde52Stm 	MUTEX_ENTER(&nxge->poll_lock);
412698ecde52Stm 	if (nxge->suspended || nxge->poll_state == LINK_MONITOR_STOPPING) {
412798ecde52Stm 		nxge->poll_state = LINK_MONITOR_STOP;
412898ecde52Stm 		nxge->nxge_link_poll_timerid = 0;
412998ecde52Stm 		cv_broadcast(&nxge->poll_cv);
413098ecde52Stm 		MUTEX_EXIT(&nxge->poll_lock);
413198ecde52Stm 
413298ecde52Stm 		NXGE_DEBUG_MSG((nxge, MAC_CTL,
413398ecde52Stm 		    "nxge_check_%s_link(port<%d>) stopped.",
413498ecde52Stm 		    nxge->mac.portmode == PORT_10G_FIBER ? "10g" : "mii",
413598ecde52Stm 		    nxge->mac.portnum));
413698ecde52Stm 		return (CHECK_LINK_STOP);
413798ecde52Stm 	}
413898ecde52Stm 	MUTEX_EXIT(&nxge->poll_lock);
413998ecde52Stm 
414098ecde52Stm 	return (CHECK_LINK_RESCHEDULE);
414198ecde52Stm }
414298ecde52Stm 
414344961713Sgirish /* Check status of MII (MIF or PCS) link */
414444961713Sgirish 
414559ac0c16Sdavemq static nxge_status_t
414644961713Sgirish nxge_check_mii_link(p_nxge_t nxgep)
414744961713Sgirish {
414844961713Sgirish 	mii_bmsr_t bmsr_ints, bmsr_data;
414944961713Sgirish 	mii_anlpar_t anlpar;
415044961713Sgirish 	mii_gsr_t gsr;
415144961713Sgirish 	p_mii_regs_t mii_regs;
415244961713Sgirish 	nxge_status_t status = NXGE_OK;
415344961713Sgirish 	uint8_t portn;
4154a3c5bd6dSspeer 	nxge_link_state_t link_up;
415544961713Sgirish 
415698ecde52Stm 	if (nxgep->nxge_magic != NXGE_MAGIC)
415798ecde52Stm 		return (NXGE_ERROR);
415898ecde52Stm 
415998ecde52Stm 	if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
416098ecde52Stm 		return (NXGE_OK);
416198ecde52Stm 
416244961713Sgirish 	portn = nxgep->mac.portnum;
416344961713Sgirish 
416444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_mii_link port<%d>",
416598ecde52Stm 	    portn));
416644961713Sgirish 
416744961713Sgirish 	mii_regs = NULL;
416844961713Sgirish 
416944961713Sgirish 	RW_ENTER_WRITER(&nxgep->filter_lock);
417044961713Sgirish 
417144961713Sgirish 	if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10)
417244961713Sgirish 		goto nxge_check_mii_link_exit;
417344961713Sgirish 
41742e59129aSraghus 	switch (nxgep->mac.portmode) {
41752e59129aSraghus 	default:
4176d81011f0Ssbehera 		bmsr_data.value = 0;
417744961713Sgirish 		if ((status = nxge_mii_read(nxgep,
41782e59129aSraghus 		    nxgep->statsp->mac_stats.xcvr_portn,
4179adfcba55Sjoycey #if defined(__i386)
4180adfcba55Sjoycey 		    (uint8_t)(uint32_t)(&mii_regs->bmsr),
4181adfcba55Sjoycey #else
41822e59129aSraghus 		    (uint8_t)(uint64_t)(&mii_regs->bmsr),
4183adfcba55Sjoycey #endif
41842e59129aSraghus 		    &bmsr_data.value)) != NXGE_OK) {
418544961713Sgirish 			goto fail;
418644961713Sgirish 		}
418744961713Sgirish 
4188d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4189d81011f0Ssbehera 		    "==> nxge_check_mii_link port<0x%x> "
4190d81011f0Ssbehera 		    "RIGHT AFTER READ bmsr_data 0x%x (nxgep->bmsr 0x%x ",
41912d17280bSsbehera 		    portn, bmsr_data.value, nxgep->bmsr.value));
4192d81011f0Ssbehera 
41932e59129aSraghus 		if (nxgep->param_arr[param_autoneg].value) {
41942e59129aSraghus 			if ((status = nxge_mii_read(nxgep,
41952e59129aSraghus 				nxgep->statsp->mac_stats.xcvr_portn,
4196adfcba55Sjoycey #if defined(__i386)
4197adfcba55Sjoycey 				(uint8_t)(uint32_t)(&mii_regs->gsr),
4198adfcba55Sjoycey #else
41992e59129aSraghus 				(uint8_t)(uint64_t)(&mii_regs->gsr),
4200adfcba55Sjoycey #endif
42012e59129aSraghus 				&gsr.value)) != NXGE_OK)
42022e59129aSraghus 				goto fail;
42032e59129aSraghus 			if ((status = nxge_mii_read(nxgep,
42042e59129aSraghus 				nxgep->statsp->mac_stats.xcvr_portn,
4205adfcba55Sjoycey #if defined(__i386)
4206adfcba55Sjoycey 				(uint8_t)(uint32_t)(&mii_regs->anlpar),
4207adfcba55Sjoycey #else
42082e59129aSraghus 				(uint8_t)(uint64_t)(&mii_regs->anlpar),
4209adfcba55Sjoycey #endif
42102e59129aSraghus 				&anlpar.value)) != NXGE_OK)
42112e59129aSraghus 				goto fail;
4212d81011f0Ssbehera 			if (nxgep->mac.portmode != PORT_1G_RGMII_FIBER) {
4213d81011f0Ssbehera 
4214d81011f0Ssbehera 				if (nxgep->statsp->mac_stats.link_up &&
4215d81011f0Ssbehera 				    ((nxgep->statsp->mac_stats.lp_cap_1000fdx ^
4216d81011f0Ssbehera 				    gsr.bits.link_1000fdx) ||
4217d81011f0Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_1000hdx ^
4218d81011f0Ssbehera 				    gsr.bits.link_1000hdx) ||
4219d81011f0Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_100T4 ^
4220d81011f0Ssbehera 				    anlpar.bits.cap_100T4) ||
4221d81011f0Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_100fdx ^
4222d81011f0Ssbehera 				    anlpar.bits.cap_100fdx) ||
4223d81011f0Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_100hdx ^
4224d81011f0Ssbehera 				    anlpar.bits.cap_100hdx) ||
4225d81011f0Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_10fdx ^
4226d81011f0Ssbehera 				    anlpar.bits.cap_10fdx) ||
4227d81011f0Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_10hdx ^
4228d81011f0Ssbehera 				    anlpar.bits.cap_10hdx))) {
4229d81011f0Ssbehera 					bmsr_data.bits.link_status = 0;
4230d81011f0Ssbehera 				}
42312e59129aSraghus 			}
42322e59129aSraghus 		}
423344961713Sgirish 
42342e59129aSraghus 		/* Workaround for link down issue */
42352e59129aSraghus 		if (bmsr_data.value == 0) {
42362e59129aSraghus 			cmn_err(CE_NOTE, "!LINK DEBUG: Read zero bmsr\n");
42372e59129aSraghus 			goto nxge_check_mii_link_exit;
42382e59129aSraghus 		}
42392e59129aSraghus 
4240d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4241d81011f0Ssbehera 		    "==> nxge_check_mii_link port<0x%x> :"
4242d81011f0Ssbehera 		    "BEFORE BMSR ^ nxgep->bmsr 0x%x bmsr_data 0x%x",
42432d17280bSsbehera 		    portn, nxgep->bmsr.value, bmsr_data.value));
4244d81011f0Ssbehera 
42452e59129aSraghus 		bmsr_ints.value = nxgep->bmsr.value ^ bmsr_data.value;
42462e59129aSraghus 		nxgep->bmsr.value = bmsr_data.value;
4247d81011f0Ssbehera 
4248d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4249d81011f0Ssbehera 		    "==> nxge_check_mii_link port<0x%x> CALLING "
4250d81011f0Ssbehera 		    "bmsr_data 0x%x bmsr_ints.value 0x%x",
42512d17280bSsbehera 		    portn, bmsr_data.value, bmsr_ints.value));
4252d81011f0Ssbehera 
42532e59129aSraghus 		if ((status = nxge_mii_check(nxgep, bmsr_data, bmsr_ints,
42542e59129aSraghus 		    &link_up)) != NXGE_OK) {
42552e59129aSraghus 			goto fail;
42562e59129aSraghus 		}
42572e59129aSraghus 		break;
42582e59129aSraghus 
42592e59129aSraghus 	case PORT_1G_SERDES:
42602e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
42612e59129aSraghus 		    "==> nxge_check_mii_link port<%d> (SERDES)", portn));
42622e59129aSraghus 		if ((status = nxge_pcs_check(nxgep, portn, &link_up))
42632e59129aSraghus 		    != NXGE_OK) {
42642e59129aSraghus 			goto fail;
42652e59129aSraghus 		}
42662e59129aSraghus 		break;
42672e59129aSraghus 	}
426844961713Sgirish 
426944961713Sgirish nxge_check_mii_link_exit:
427044961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
4271a3c5bd6dSspeer 	if (link_up == LINK_IS_UP) {
4272a3c5bd6dSspeer 		nxge_link_is_up(nxgep);
4273a3c5bd6dSspeer 	} else if (link_up == LINK_IS_DOWN) {
4274a3c5bd6dSspeer 		nxge_link_is_down(nxgep);
4275a3c5bd6dSspeer 	}
427644961713Sgirish 
427744961713Sgirish 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
427844961713Sgirish 
427944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_mii_link port<%d>",
42802e59129aSraghus 				portn));
428144961713Sgirish 	return (NXGE_OK);
428244961713Sgirish 
428344961713Sgirish fail:
428444961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
428544961713Sgirish 
428644961713Sgirish 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
428744961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
42882e59129aSraghus 			"nxge_check_mii_link: Failed to check link port<%d>",
42892e59129aSraghus 			portn));
429044961713Sgirish 	return (status);
429144961713Sgirish }
429244961713Sgirish 
429344961713Sgirish 
429444961713Sgirish /*ARGSUSED*/
429559ac0c16Sdavemq static nxge_status_t
429644961713Sgirish nxge_check_10g_link(p_nxge_t nxgep)
429744961713Sgirish {
429844961713Sgirish 	uint8_t		portn;
429944961713Sgirish 	nxge_status_t	status = NXGE_OK;
4300763fcc44Ssbehera 	boolean_t	link_up;
43012e59129aSraghus 	uint32_t	val;
43022e59129aSraghus 	npi_status_t	rs;
430344961713Sgirish 
430498ecde52Stm 	if (nxgep->nxge_magic != NXGE_MAGIC)
430598ecde52Stm 		return (NXGE_ERROR);
430698ecde52Stm 
430798ecde52Stm 	if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
430898ecde52Stm 		return (NXGE_OK);
430998ecde52Stm 
431044961713Sgirish 	portn = nxgep->mac.portnum;
4311d81011f0Ssbehera 	val = 0;
4312d81011f0Ssbehera 	rs = NPI_SUCCESS;
431344961713Sgirish 
431444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_10g_link port<%d>",
431598ecde52Stm 	    portn));
431644961713Sgirish 
43172e59129aSraghus 	switch (nxgep->mac.portmode) {
43182e59129aSraghus 	default:
43192d17280bSsbehera 		/*
43202d17280bSsbehera 		 * Check if the phy is present in case of hot swappable phy
43212d17280bSsbehera 		 */
43222d17280bSsbehera 		if (nxgep->hot_swappable_phy) {
43232d17280bSsbehera 			boolean_t phy_present_now = B_FALSE;
43242d17280bSsbehera 
43252d17280bSsbehera 			/*
43262d17280bSsbehera 			 * If this is the 2nd Goa port, then check 2 addresses
43272d17280bSsbehera 			 * to take care of the Goa NEM card requirements.
43282d17280bSsbehera 			 */
43292d17280bSsbehera 			if (portn == 1) {
43302d17280bSsbehera 				if (nxge_is_phy_present(nxgep,
43312d17280bSsbehera 				    BCM8706_ALT_GOA_PORT1_ADDR,
43322d17280bSsbehera 				    BCM8706_DEV_ID, BCM_PHY_ID_MASK)) {
43332d17280bSsbehera 					phy_present_now = B_TRUE;
43342d17280bSsbehera 					nxgep->xcvr_addr =
43352d17280bSsbehera 					    BCM8706_ALT_GOA_PORT1_ADDR;
43362d17280bSsbehera 					goto phy_check_done;
43372d17280bSsbehera 				}
43382d17280bSsbehera 			}
43392d17280bSsbehera 			if (nxge_is_phy_present(nxgep,
43402d17280bSsbehera 			    (BCM8706_GOA_PORT_ADDR_BASE) + portn,
43412d17280bSsbehera 			    BCM8706_DEV_ID, BCM_PHY_ID_MASK)) {
43422d17280bSsbehera 				nxgep->xcvr_addr =
43432d17280bSsbehera 				    (BCM8706_GOA_PORT_ADDR_BASE) + portn;
43442d17280bSsbehera 				phy_present_now = B_TRUE;
43452d17280bSsbehera 			}
43462d17280bSsbehera 
43472d17280bSsbehera phy_check_done:
43482d17280bSsbehera 			if (nxgep->phy_absent) {
43492d17280bSsbehera 				if (phy_present_now) {
43502d17280bSsbehera 				/*
43512d17280bSsbehera 				 * Detect, Initialize phy and do link up
43522d17280bSsbehera 				 * set xcvr vals, link_init, nxge_init
43532d17280bSsbehera 				 */
43542d17280bSsbehera 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
43552d17280bSsbehera 					    "Hot swappable phy DETECTED!!"));
43562d17280bSsbehera 					nxgep->phy_absent = B_FALSE;
43572d17280bSsbehera 					(void) nxge_xcvr_find(nxgep);
43582d17280bSsbehera 					(void) nxge_link_init(nxgep);
43592d17280bSsbehera 					if (!(nxgep->drv_state &
43602d17280bSsbehera 					    STATE_HW_INITIALIZED)) {
43612d17280bSsbehera 						status = nxge_init(nxgep);
43622d17280bSsbehera 						if (status != NXGE_OK) {
43632d17280bSsbehera 							NXGE_ERROR_MSG((nxgep,
43642d17280bSsbehera 							    NXGE_ERR_CTL,
43652d17280bSsbehera 							    "Hot swappable "
43662d17280bSsbehera 							    "phy present, but"
43672d17280bSsbehera 							    " driver init"
43682d17280bSsbehera 							    "  failed..."));
43692d17280bSsbehera 							goto fail;
43702d17280bSsbehera 						}
43712d17280bSsbehera 					}
43722d17280bSsbehera 				}
43732d17280bSsbehera 
43742d17280bSsbehera 				goto start_link_check;
43752d17280bSsbehera 
43762d17280bSsbehera 			} else if (!phy_present_now) {
43772d17280bSsbehera 				/*
43782d17280bSsbehera 				 * Phy gone, bring link down reset xcvr vals
43792d17280bSsbehera 				 */
43802d17280bSsbehera 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
43812d17280bSsbehera 				    "Hot swappable phy REMOVED!!"));
43822d17280bSsbehera 				nxgep->phy_absent = B_TRUE;
43832d17280bSsbehera 				nxgep->statsp->mac_stats.link_up = 0;
43842d17280bSsbehera 				nxgep->statsp->mac_stats.link_speed = 0;
43852d17280bSsbehera 				nxgep->statsp->mac_stats.link_duplex = 0;
43862d17280bSsbehera 				nxge_link_is_down(nxgep);
43872d17280bSsbehera 				nxgep->link_notify = B_FALSE;
43882d17280bSsbehera 
43892d17280bSsbehera 				(void) nxge_xcvr_find(nxgep);
43902d17280bSsbehera 
43912d17280bSsbehera 				goto start_link_check;
43922d17280bSsbehera 
43932d17280bSsbehera 			}
43942d17280bSsbehera 		}
43952d17280bSsbehera 
43962e59129aSraghus 		status = nxge_check_bcm8704_link(nxgep, &link_up);
43972e59129aSraghus 		if (status != NXGE_OK)
43982e59129aSraghus 			goto fail;
43992e59129aSraghus 		break;
44002e59129aSraghus 	case PORT_10G_SERDES:
44012e59129aSraghus 		rs = npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
4402763fcc44Ssbehera 		    XPCS_REG_STATUS, &val);
44032e59129aSraghus 		if (rs != 0)
44042e59129aSraghus 			goto fail;
44052e59129aSraghus 
44062e59129aSraghus 		link_up = B_FALSE;
4407763fcc44Ssbehera 		if (val & XPCS_STATUS_LANE_ALIGN) {
4408763fcc44Ssbehera 			link_up = B_TRUE;
44092e59129aSraghus 		}
44102e59129aSraghus 
44112e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
44122e59129aSraghus 		    "==> nxge_check_10g_link port<%d> "
4413763fcc44Ssbehera 		    "XPCS_REG_STATUS2 0x%x link_up %d",
4414763fcc44Ssbehera 		    portn, val, link_up));
44152e59129aSraghus 
44162e59129aSraghus 		break;
44172e59129aSraghus 	}
441844961713Sgirish 
441944961713Sgirish 	if (link_up) {
4420a3c5bd6dSspeer 		if (nxgep->link_notify ||
4421a3c5bd6dSspeer 			nxgep->statsp->mac_stats.link_up == 0) {
442244961713Sgirish 			if (nxge_10g_link_led_on(nxgep) != NXGE_OK)
442344961713Sgirish 				goto fail;
442444961713Sgirish 			nxgep->statsp->mac_stats.link_up = 1;
442544961713Sgirish 			nxgep->statsp->mac_stats.link_speed = 10000;
442644961713Sgirish 			nxgep->statsp->mac_stats.link_duplex = 2;
442744961713Sgirish 
442844961713Sgirish 			nxge_link_is_up(nxgep);
4429a3c5bd6dSspeer 			nxgep->link_notify = B_FALSE;
443044961713Sgirish 		}
443144961713Sgirish 	} else {
4432a3c5bd6dSspeer 		if (nxgep->link_notify ||
4433a3c5bd6dSspeer 			nxgep->statsp->mac_stats.link_up == 1) {
443444961713Sgirish 			if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
443544961713Sgirish 				goto fail;
443644961713Sgirish 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
44372e59129aSraghus 					"Link down cable problem"));
443844961713Sgirish 			nxgep->statsp->mac_stats.link_up = 0;
443944961713Sgirish 			nxgep->statsp->mac_stats.link_speed = 0;
444044961713Sgirish 			nxgep->statsp->mac_stats.link_duplex = 0;
444144961713Sgirish 
444244961713Sgirish 			nxge_link_is_down(nxgep);
4443a3c5bd6dSspeer 			nxgep->link_notify = B_FALSE;
444444961713Sgirish 		}
444544961713Sgirish 	}
444644961713Sgirish 
44472d17280bSsbehera start_link_check:
444844961713Sgirish 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
444944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_10g_link port<%d>",
445098ecde52Stm 	    portn));
445144961713Sgirish 	return (NXGE_OK);
445244961713Sgirish 
445344961713Sgirish fail:
445498ecde52Stm 	(void) nxge_check_link_stop(nxgep);
445598ecde52Stm 
445644961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
445798ecde52Stm 	    "nxge_check_10g_link: Failed to check link port<%d>",
445898ecde52Stm 	    portn));
445944961713Sgirish 	return (status);
446044961713Sgirish }
446144961713Sgirish 
446244961713Sgirish 
446344961713Sgirish /* Declare link down */
446444961713Sgirish 
446544961713Sgirish void
446644961713Sgirish nxge_link_is_down(p_nxge_t nxgep)
446744961713Sgirish {
446859ac0c16Sdavemq 	p_nxge_stats_t statsp;
446959ac0c16Sdavemq 	char link_stat_msg[64];
447059ac0c16Sdavemq 
447144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_down"));
447244961713Sgirish 
447359ac0c16Sdavemq 	statsp = nxgep->statsp;
447459ac0c16Sdavemq 	(void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is down",
447559ac0c16Sdavemq 	    statsp->mac_stats.xcvr_portn);
447659ac0c16Sdavemq 
447759ac0c16Sdavemq 	if (nxge_no_msg == B_FALSE) {
447859ac0c16Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg));
447959ac0c16Sdavemq 	}
448059ac0c16Sdavemq 
448144961713Sgirish 	mac_link_update(nxgep->mach, LINK_STATE_DOWN);
448244961713Sgirish 
448344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_down"));
448444961713Sgirish }
448544961713Sgirish 
448644961713Sgirish /* Declare link up */
448744961713Sgirish 
448844961713Sgirish void
448944961713Sgirish nxge_link_is_up(p_nxge_t nxgep)
449044961713Sgirish {
449159ac0c16Sdavemq 	p_nxge_stats_t statsp;
449259ac0c16Sdavemq 	char link_stat_msg[64];
449344961713Sgirish 	uint32_t val;
449444961713Sgirish 
449544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_up"));
449644961713Sgirish 
449759ac0c16Sdavemq 	statsp = nxgep->statsp;
449859ac0c16Sdavemq 	(void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is up %d Mbps ",
449959ac0c16Sdavemq 	    statsp->mac_stats.xcvr_portn,
450059ac0c16Sdavemq 	    statsp->mac_stats.link_speed);
450159ac0c16Sdavemq 
450259ac0c16Sdavemq 	if (statsp->mac_stats.link_T4)
450359ac0c16Sdavemq 		(void) strcat(link_stat_msg, "T4");
450459ac0c16Sdavemq 	else if (statsp->mac_stats.link_duplex == 2)
450559ac0c16Sdavemq 		(void) strcat(link_stat_msg, "full duplex");
450659ac0c16Sdavemq 	else
450759ac0c16Sdavemq 		(void) strcat(link_stat_msg, "half duplex");
450859ac0c16Sdavemq 
450944961713Sgirish 	(void) nxge_xif_init(nxgep);
451044961713Sgirish 
451144961713Sgirish 	/* Clean up symbol errors incurred during link transition */
45122e59129aSraghus 	if ((nxgep->mac.portmode == PORT_10G_FIBER) ||
45132e59129aSraghus 	    (nxgep->mac.portmode == PORT_10G_SERDES)) {
451444961713Sgirish 		(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
451544961713Sgirish 					XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val);
451644961713Sgirish 		(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
451744961713Sgirish 					XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val);
451844961713Sgirish 	}
451944961713Sgirish 
452059ac0c16Sdavemq 	if (nxge_no_msg == B_FALSE) {
452159ac0c16Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg));
452259ac0c16Sdavemq 	}
452359ac0c16Sdavemq 
452444961713Sgirish 	mac_link_update(nxgep->mach, LINK_STATE_UP);
452544961713Sgirish 
452644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_up"));
452744961713Sgirish }
452844961713Sgirish 
452944961713Sgirish /*
453044961713Sgirish  * Calculate the bit in the multicast address filter
453144961713Sgirish  * that selects the given * address.
453244961713Sgirish  * Note: For GEM, the last 8-bits are used.
453344961713Sgirish  */
453444961713Sgirish uint32_t
453544961713Sgirish crc32_mchash(p_ether_addr_t addr)
453644961713Sgirish {
453744961713Sgirish 	uint8_t *cp;
453844961713Sgirish 	uint32_t crc;
453944961713Sgirish 	uint32_t c;
454044961713Sgirish 	int byte;
454144961713Sgirish 	int bit;
454244961713Sgirish 
454344961713Sgirish 	cp = (uint8_t *)addr;
454444961713Sgirish 	crc = (uint32_t)0xffffffff;
454544961713Sgirish 	for (byte = 0; byte < 6; byte++) {
454644961713Sgirish 		c = (uint32_t)cp[byte];
454744961713Sgirish 		for (bit = 0; bit < 8; bit++) {
454844961713Sgirish 			if ((c & 0x1) ^ (crc & 0x1))
454944961713Sgirish 				crc = (crc >> 1)^0xedb88320;
455044961713Sgirish 			else
455144961713Sgirish 				crc = (crc >> 1);
455244961713Sgirish 			c >>= 1;
455344961713Sgirish 		}
455444961713Sgirish 	}
455544961713Sgirish 	return ((~crc) >> (32 - HASH_BITS));
455644961713Sgirish }
455744961713Sgirish 
455844961713Sgirish /* Reset serdes */
455944961713Sgirish 
456044961713Sgirish nxge_status_t
456144961713Sgirish nxge_serdes_reset(p_nxge_t nxgep)
456244961713Sgirish {
456344961713Sgirish 	npi_handle_t		handle;
456444961713Sgirish 
456544961713Sgirish 	handle = nxgep->npi_handle;
456644961713Sgirish 
456744961713Sgirish 	ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0 | ESR_RESET_1);
456844961713Sgirish 	drv_usecwait(500);
456944961713Sgirish 	ESR_REG_WR(handle, ESR_CONFIG_REG, 0);
457044961713Sgirish 
457144961713Sgirish 	return (NXGE_OK);
457244961713Sgirish }
457344961713Sgirish 
457444961713Sgirish /* Monitor link status using interrupt or polling */
457544961713Sgirish 
457644961713Sgirish nxge_status_t
457744961713Sgirish nxge_link_monitor(p_nxge_t nxgep, link_mon_enable_t enable)
457844961713Sgirish {
457944961713Sgirish 	nxge_status_t status = NXGE_OK;
458044961713Sgirish 
458144961713Sgirish 	/*
458298ecde52Stm 	 * Return immediately if this is an imaginary XMAC port.
458398ecde52Stm 	 * (At least, we don't have 4-port XMAC cards yet.)
458444961713Sgirish 	 */
45852e59129aSraghus 	if ((nxgep->mac.portmode == PORT_10G_FIBER ||
45862e59129aSraghus 	    nxgep->mac.portmode == PORT_10G_SERDES) &&
45872e59129aSraghus 	    (nxgep->mac.portnum > 1))
458844961713Sgirish 		return (NXGE_OK);
458944961713Sgirish 
459044961713Sgirish 	if (nxgep->statsp == NULL) {
459144961713Sgirish 		/* stats has not been allocated. */
459244961713Sgirish 		return (NXGE_OK);
459344961713Sgirish 	}
4594*321febdeSsbehera 	/* Don't check link if we're in internal loopback mode */
4595*321febdeSsbehera 	if (nxgep->statsp->port_stats.lb_mode >= nxge_lb_serdes10g)
459644961713Sgirish 		return (NXGE_OK);
459744961713Sgirish 
459844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
459998ecde52Stm 	    "==> nxge_link_monitor port<%d> enable=%d",
460098ecde52Stm 	    nxgep->mac.portnum, enable));
460144961713Sgirish 	if (enable == LINK_MONITOR_START) {
460244961713Sgirish 		if (nxgep->mac.linkchkmode == LINKCHK_INTR) {
460344961713Sgirish 			if ((status = nxge_link_intr(nxgep, LINK_INTR_START))
460498ecde52Stm 			    != NXGE_OK)
460544961713Sgirish 				goto fail;
460644961713Sgirish 		} else {
460798ecde52Stm 			timeout_id_t timerid;
460898ecde52Stm 
460998ecde52Stm 			if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
461098ecde52Stm 				return (NXGE_OK);
461198ecde52Stm 
461259ac0c16Sdavemq 			if (nxgep->xcvr.check_link) {
461359ac0c16Sdavemq 				timerid = timeout(
461459ac0c16Sdavemq 				    (fptrv_t)(nxgep->xcvr.check_link),
461598ecde52Stm 				    nxgep,
461698ecde52Stm 				    drv_usectohz(LINK_MONITOR_PERIOD));
461759ac0c16Sdavemq 				MUTEX_ENTER(&nxgep->poll_lock);
461859ac0c16Sdavemq 				nxgep->nxge_link_poll_timerid = timerid;
461959ac0c16Sdavemq 				MUTEX_EXIT(&nxgep->poll_lock);
462059ac0c16Sdavemq 			} else {
462198ecde52Stm 				return (NXGE_ERROR);
462244961713Sgirish 			}
462344961713Sgirish 		}
462444961713Sgirish 	} else {
462544961713Sgirish 		if (nxgep->mac.linkchkmode == LINKCHK_INTR) {
462644961713Sgirish 			if ((status = nxge_link_intr(nxgep, LINK_INTR_STOP))
462798ecde52Stm 			    != NXGE_OK)
462844961713Sgirish 				goto fail;
462944961713Sgirish 		} else {
463098ecde52Stm 			clock_t rv;
463198ecde52Stm 
463298ecde52Stm 			MUTEX_ENTER(&nxgep->poll_lock);
463398ecde52Stm 
463498ecde52Stm 			/* If <timerid> == 0, the link monitor has */
463598ecde52Stm 			/* never been started, or just now stopped. */
463698ecde52Stm 			if (nxgep->nxge_link_poll_timerid == 0) {
463798ecde52Stm 				MUTEX_EXIT(&nxgep->poll_lock);
463898ecde52Stm 				return (NXGE_OK);
463998ecde52Stm 			}
464098ecde52Stm 
464198ecde52Stm 			nxgep->poll_state = LINK_MONITOR_STOPPING;
464298ecde52Stm 			rv = cv_timedwait(&nxgep->poll_cv,
464398ecde52Stm 			    &nxgep->poll_lock,
464498ecde52Stm 			    ddi_get_lbolt() +
464598ecde52Stm 			    drv_usectohz(LM_WAIT_MULTIPLIER *
464698ecde52Stm 			    LINK_MONITOR_PERIOD));
464798ecde52Stm 			if (rv == -1) {
464898ecde52Stm 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
464998ecde52Stm 				    "==> stopping port %d: "
465098ecde52Stm 				    "cv_timedwait(%d) timed out",
465198ecde52Stm 				    nxgep->mac.portnum, nxgep->poll_state));
465298ecde52Stm 				nxgep->poll_state = LINK_MONITOR_STOP;
465344961713Sgirish 				nxgep->nxge_link_poll_timerid = 0;
465444961713Sgirish 			}
465598ecde52Stm 
465698ecde52Stm 			MUTEX_EXIT(&nxgep->poll_lock);
465744961713Sgirish 		}
465844961713Sgirish 	}
465944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
466098ecde52Stm 	    "<== nxge_link_monitor port<%d> enable=%d",
466198ecde52Stm 	    nxgep->mac.portnum, enable));
466244961713Sgirish 	return (NXGE_OK);
466344961713Sgirish fail:
466444961713Sgirish 	return (status);
466544961713Sgirish }
466644961713Sgirish 
466744961713Sgirish /* Set promiscous mode */
466844961713Sgirish 
466944961713Sgirish nxge_status_t
467044961713Sgirish nxge_set_promisc(p_nxge_t nxgep, boolean_t on)
467144961713Sgirish {
467244961713Sgirish 	nxge_status_t status = NXGE_OK;
467344961713Sgirish 
467459ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_promisc: on %d", on));
467544961713Sgirish 
467644961713Sgirish 	nxgep->filter.all_phys_cnt = ((on) ? 1 : 0);
467744961713Sgirish 
467844961713Sgirish 	RW_ENTER_WRITER(&nxgep->filter_lock);
467944961713Sgirish 
468044961713Sgirish 	if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) {
468144961713Sgirish 		goto fail;
468244961713Sgirish 	}
468344961713Sgirish 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) {
468444961713Sgirish 		goto fail;
468544961713Sgirish 	}
468644961713Sgirish 
468744961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
468844961713Sgirish 
468944961713Sgirish 	if (on)
469044961713Sgirish 		nxgep->statsp->mac_stats.promisc = B_TRUE;
469144961713Sgirish 	else
469244961713Sgirish 		nxgep->statsp->mac_stats.promisc = B_FALSE;
469344961713Sgirish 
469444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_promisc"));
469544961713Sgirish 
469644961713Sgirish 	return (NXGE_OK);
469744961713Sgirish fail:
469844961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
469944961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_promisc: "
470059ac0c16Sdavemq 	    "Unable to set promisc (%d)", on));
470144961713Sgirish 
470244961713Sgirish 	return (status);
470344961713Sgirish }
470444961713Sgirish 
470544961713Sgirish /*ARGSUSED*/
470644961713Sgirish uint_t
470744961713Sgirish nxge_mif_intr(void *arg1, void *arg2)
470844961713Sgirish {
470944961713Sgirish #ifdef	NXGE_DEBUG
471044961713Sgirish 	p_nxge_t		nxgep = (p_nxge_t)arg2;
471144961713Sgirish #endif
471244961713Sgirish #if NXGE_MIF
471344961713Sgirish 	p_nxge_ldv_t		ldvp = (p_nxge_ldv_t)arg1;
471444961713Sgirish 	uint32_t		status;
471544961713Sgirish 	npi_handle_t		handle;
471644961713Sgirish 	uint8_t			portn;
471744961713Sgirish 	p_nxge_stats_t		statsp;
471844961713Sgirish #endif
471944961713Sgirish 
472044961713Sgirish #ifdef	NXGE_MIF
472144961713Sgirish 	if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
472244961713Sgirish 		nxgep = ldvp->nxgep;
472344961713Sgirish 	}
472444961713Sgirish 	nxgep = ldvp->nxgep;
472544961713Sgirish #endif
472644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mif_intr"));
472744961713Sgirish 
472844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr"));
472944961713Sgirish 	return (DDI_INTR_CLAIMED);
473044961713Sgirish 
473144961713Sgirish mif_intr_fail:
473244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr"));
473344961713Sgirish 	return (DDI_INTR_UNCLAIMED);
473444961713Sgirish }
473544961713Sgirish 
473644961713Sgirish /*ARGSUSED*/
473744961713Sgirish uint_t
473844961713Sgirish nxge_mac_intr(void *arg1, void *arg2)
473944961713Sgirish {
474044961713Sgirish 	p_nxge_t		nxgep = (p_nxge_t)arg2;
474144961713Sgirish 	p_nxge_ldv_t		ldvp = (p_nxge_ldv_t)arg1;
474244961713Sgirish 	p_nxge_ldg_t		ldgp;
474344961713Sgirish 	uint32_t		status;
474444961713Sgirish 	npi_handle_t		handle;
474544961713Sgirish 	uint8_t			portn;
474644961713Sgirish 	p_nxge_stats_t		statsp;
474744961713Sgirish 	npi_status_t		rs = NPI_SUCCESS;
474844961713Sgirish 
474944961713Sgirish 	if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
475044961713Sgirish 		nxgep = ldvp->nxgep;
475144961713Sgirish 	}
475244961713Sgirish 
475344961713Sgirish 	ldgp = ldvp->ldgp;
475444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mac_intr: "
475559ac0c16Sdavemq 	    "group %d", ldgp->ldg));
475644961713Sgirish 
475744961713Sgirish 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
475844961713Sgirish 	/*
475944961713Sgirish 	 * This interrupt handler is for a specific
476044961713Sgirish 	 * mac port.
476144961713Sgirish 	 */
476244961713Sgirish 	statsp = (p_nxge_stats_t)nxgep->statsp;
476344961713Sgirish 	portn = nxgep->mac.portnum;
476444961713Sgirish 
476544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL,
476659ac0c16Sdavemq 	    "==> nxge_mac_intr: reading mac stats: port<%d>", portn));
476744961713Sgirish 
476844961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
476944961713Sgirish 		rs = npi_xmac_tx_get_istatus(handle, portn,
477044961713Sgirish 					(xmac_tx_iconfig_t *)&status);
477144961713Sgirish 		if (rs != NPI_SUCCESS)
477244961713Sgirish 			goto npi_fail;
477344961713Sgirish 		if (status & ICFG_XMAC_TX_ALL) {
477444961713Sgirish 			if (status & ICFG_XMAC_TX_UNDERRUN) {
477544961713Sgirish 				statsp->xmac_stats.tx_underflow_err++;
477644961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
477744961713Sgirish 					NXGE_FM_EREPORT_TXMAC_UNDERFLOW);
477844961713Sgirish 			}
477944961713Sgirish 			if (status & ICFG_XMAC_TX_MAX_PACKET_ERR) {
478044961713Sgirish 				statsp->xmac_stats.tx_maxpktsize_err++;
4781f6485eecSyc 				/*
4782f6485eecSyc 				 * Do not send FMA ereport because this
4783f6485eecSyc 				 * error does not indicate HW failure.
4784f6485eecSyc 				 */
478544961713Sgirish 			}
478644961713Sgirish 			if (status & ICFG_XMAC_TX_OVERFLOW) {
478744961713Sgirish 				statsp->xmac_stats.tx_overflow_err++;
478844961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
478944961713Sgirish 					NXGE_FM_EREPORT_TXMAC_OVERFLOW);
479044961713Sgirish 			}
479144961713Sgirish 			if (status & ICFG_XMAC_TX_FIFO_XFR_ERR) {
479244961713Sgirish 				statsp->xmac_stats.tx_fifo_xfr_err++;
479344961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
479444961713Sgirish 					NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR);
479544961713Sgirish 			}
479644961713Sgirish 			if (status & ICFG_XMAC_TX_BYTE_CNT_EXP) {
479744961713Sgirish 				statsp->xmac_stats.tx_byte_cnt +=
479844961713Sgirish 							XTXMAC_BYTE_CNT_MASK;
479944961713Sgirish 			}
480044961713Sgirish 			if (status & ICFG_XMAC_TX_FRAME_CNT_EXP) {
480144961713Sgirish 				statsp->xmac_stats.tx_frame_cnt +=
480244961713Sgirish 							XTXMAC_FRM_CNT_MASK;
480344961713Sgirish 			}
480444961713Sgirish 		}
480544961713Sgirish 
480644961713Sgirish 		rs = npi_xmac_rx_get_istatus(handle, portn,
480744961713Sgirish 					(xmac_rx_iconfig_t *)&status);
480844961713Sgirish 		if (rs != NPI_SUCCESS)
480944961713Sgirish 			goto npi_fail;
481044961713Sgirish 		if (status & ICFG_XMAC_RX_ALL) {
481144961713Sgirish 			if (status & ICFG_XMAC_RX_OVERFLOW)
481244961713Sgirish 				statsp->xmac_stats.rx_overflow_err++;
481344961713Sgirish 			if (status & ICFG_XMAC_RX_UNDERFLOW) {
481444961713Sgirish 				statsp->xmac_stats.rx_underflow_err++;
481544961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
481644961713Sgirish 					NXGE_FM_EREPORT_RXMAC_UNDERFLOW);
481744961713Sgirish 			}
4818f6485eecSyc 			/*
4819f6485eecSyc 			 * Do not send FMA ereport for the following 3 errors
4820f6485eecSyc 			 * because they do not indicate HW failures.
4821f6485eecSyc 			 */
482244961713Sgirish 			if (status & ICFG_XMAC_RX_CRC_ERR_CNT_EXP) {
482344961713Sgirish 				statsp->xmac_stats.rx_crc_err_cnt +=
482444961713Sgirish 							XRXMAC_CRC_ER_CNT_MASK;
482544961713Sgirish 			}
482644961713Sgirish 			if (status & ICFG_XMAC_RX_LEN_ERR_CNT_EXP) {
482744961713Sgirish 				statsp->xmac_stats.rx_len_err_cnt +=
482844961713Sgirish 							MAC_LEN_ER_CNT_MASK;
482944961713Sgirish 			}
483044961713Sgirish 			if (status & ICFG_XMAC_RX_VIOL_ERR_CNT_EXP) {
483144961713Sgirish 				statsp->xmac_stats.rx_viol_err_cnt +=
483244961713Sgirish 							XRXMAC_CD_VIO_CNT_MASK;
483344961713Sgirish 			}
483444961713Sgirish 			if (status & ICFG_XMAC_RX_OCT_CNT_EXP) {
483544961713Sgirish 				statsp->xmac_stats.rx_byte_cnt +=
483644961713Sgirish 							XRXMAC_BT_CNT_MASK;
483744961713Sgirish 			}
483844961713Sgirish 			if (status & ICFG_XMAC_RX_HST_CNT1_EXP) {
483944961713Sgirish 				statsp->xmac_stats.rx_hist1_cnt +=
484044961713Sgirish 							XRXMAC_HIST_CNT1_MASK;
484144961713Sgirish 			}
484244961713Sgirish 			if (status & ICFG_XMAC_RX_HST_CNT2_EXP) {
484344961713Sgirish 				statsp->xmac_stats.rx_hist2_cnt +=
484444961713Sgirish 							XRXMAC_HIST_CNT2_MASK;
484544961713Sgirish 			}
484644961713Sgirish 			if (status & ICFG_XMAC_RX_HST_CNT3_EXP) {
484744961713Sgirish 				statsp->xmac_stats.rx_hist3_cnt +=
484844961713Sgirish 							XRXMAC_HIST_CNT3_MASK;
484944961713Sgirish 			}
485044961713Sgirish 			if (status & ICFG_XMAC_RX_HST_CNT4_EXP) {
485144961713Sgirish 				statsp->xmac_stats.rx_hist4_cnt +=
485244961713Sgirish 							XRXMAC_HIST_CNT4_MASK;
485344961713Sgirish 			}
485444961713Sgirish 			if (status & ICFG_XMAC_RX_HST_CNT5_EXP) {
485544961713Sgirish 				statsp->xmac_stats.rx_hist5_cnt +=
485644961713Sgirish 							XRXMAC_HIST_CNT5_MASK;
485744961713Sgirish 			}
485844961713Sgirish 			if (status & ICFG_XMAC_RX_HST_CNT6_EXP) {
485944961713Sgirish 				statsp->xmac_stats.rx_hist6_cnt +=
486044961713Sgirish 							XRXMAC_HIST_CNT6_MASK;
486144961713Sgirish 			}
486244961713Sgirish 			if (status & ICFG_XMAC_RX_BCAST_CNT_EXP) {
486344961713Sgirish 				statsp->xmac_stats.rx_broadcast_cnt +=
486444961713Sgirish 							XRXMAC_BC_FRM_CNT_MASK;
486544961713Sgirish 			}
486644961713Sgirish 			if (status & ICFG_XMAC_RX_MCAST_CNT_EXP) {
486744961713Sgirish 				statsp->xmac_stats.rx_mult_cnt +=
486844961713Sgirish 							XRXMAC_MC_FRM_CNT_MASK;
486944961713Sgirish 			}
4870f6485eecSyc 			/*
4871f6485eecSyc 			 * Do not send FMA ereport for the following 3 errors
4872f6485eecSyc 			 * because they do not indicate HW failures.
4873f6485eecSyc 			 */
487444961713Sgirish 			if (status & ICFG_XMAC_RX_FRAG_CNT_EXP) {
487544961713Sgirish 				statsp->xmac_stats.rx_frag_cnt +=
487644961713Sgirish 							XRXMAC_FRAG_CNT_MASK;
487744961713Sgirish 			}
487844961713Sgirish 			if (status & ICFG_XMAC_RX_ALIGNERR_CNT_EXP) {
487944961713Sgirish 				statsp->xmac_stats.rx_frame_align_err_cnt +=
488044961713Sgirish 							XRXMAC_AL_ER_CNT_MASK;
488144961713Sgirish 			}
488244961713Sgirish 			if (status & ICFG_XMAC_RX_LINK_FLT_CNT_EXP) {
488344961713Sgirish 				statsp->xmac_stats.rx_linkfault_err_cnt +=
488444961713Sgirish 							XMAC_LINK_FLT_CNT_MASK;
488544961713Sgirish 			}
488644961713Sgirish 			if (status & ICFG_XMAC_RX_REMOTE_FLT_DET) {
488744961713Sgirish 				statsp->xmac_stats.rx_remotefault_err++;
488844961713Sgirish 			}
488944961713Sgirish 			if (status & ICFG_XMAC_RX_LOCAL_FLT_DET) {
489044961713Sgirish 				statsp->xmac_stats.rx_localfault_err++;
489144961713Sgirish 			}
489244961713Sgirish 		}
489344961713Sgirish 
489444961713Sgirish 		rs = npi_xmac_ctl_get_istatus(handle, portn,
489544961713Sgirish 						(xmac_ctl_iconfig_t *)&status);
489644961713Sgirish 		if (rs != NPI_SUCCESS)
489744961713Sgirish 			goto npi_fail;
489844961713Sgirish 		if (status & ICFG_XMAC_CTRL_ALL) {
489944961713Sgirish 			if (status & ICFG_XMAC_CTRL_PAUSE_RCVD)
490044961713Sgirish 				statsp->xmac_stats.rx_pause_cnt++;
490144961713Sgirish 			if (status & ICFG_XMAC_CTRL_PAUSE_STATE)
490244961713Sgirish 				statsp->xmac_stats.tx_pause_state++;
490344961713Sgirish 			if (status & ICFG_XMAC_CTRL_NOPAUSE_STATE)
490444961713Sgirish 				statsp->xmac_stats.tx_nopause_state++;
490544961713Sgirish 		}
490644961713Sgirish 	} else if (nxgep->mac.porttype == PORT_TYPE_BMAC) {
490744961713Sgirish 		rs = npi_bmac_tx_get_istatus(handle, portn,
490844961713Sgirish 						(bmac_tx_iconfig_t *)&status);
490944961713Sgirish 		if (rs != NPI_SUCCESS)
491044961713Sgirish 			goto npi_fail;
491144961713Sgirish 		if (status & ICFG_BMAC_TX_ALL) {
491244961713Sgirish 			if (status & ICFG_BMAC_TX_UNDERFLOW) {
491344961713Sgirish 				statsp->bmac_stats.tx_underrun_err++;
491444961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
491544961713Sgirish 					NXGE_FM_EREPORT_TXMAC_UNDERFLOW);
491644961713Sgirish 			}
491744961713Sgirish 			if (status & ICFG_BMAC_TX_MAXPKTSZ_ERR) {
491844961713Sgirish 				statsp->bmac_stats.tx_max_pkt_err++;
491944961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
492044961713Sgirish 					NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR);
492144961713Sgirish 			}
492244961713Sgirish 			if (status & ICFG_BMAC_TX_BYTE_CNT_EXP) {
492344961713Sgirish 				statsp->bmac_stats.tx_byte_cnt +=
492444961713Sgirish 							BTXMAC_BYTE_CNT_MASK;
492544961713Sgirish 			}
492644961713Sgirish 			if (status & ICFG_BMAC_TX_FRAME_CNT_EXP) {
492744961713Sgirish 				statsp->bmac_stats.tx_frame_cnt +=
492844961713Sgirish 							BTXMAC_FRM_CNT_MASK;
492944961713Sgirish 			}
493044961713Sgirish 		}
493144961713Sgirish 
493244961713Sgirish 		rs = npi_bmac_rx_get_istatus(handle, portn,
493344961713Sgirish 						(bmac_rx_iconfig_t *)&status);
493444961713Sgirish 		if (rs != NPI_SUCCESS)
493544961713Sgirish 			goto npi_fail;
493644961713Sgirish 		if (status & ICFG_BMAC_RX_ALL) {
493744961713Sgirish 			if (status & ICFG_BMAC_RX_OVERFLOW) {
493844961713Sgirish 				statsp->bmac_stats.rx_overflow_err++;
493944961713Sgirish 			}
494044961713Sgirish 			if (status & ICFG_BMAC_RX_FRAME_CNT_EXP) {
494144961713Sgirish 				statsp->bmac_stats.rx_frame_cnt +=
494244961713Sgirish 							RXMAC_FRM_CNT_MASK;
494344961713Sgirish 			}
494444961713Sgirish 			if (status & ICFG_BMAC_RX_CRC_ERR_CNT_EXP) {
494544961713Sgirish 				statsp->bmac_stats.rx_crc_err_cnt +=
494644961713Sgirish 							BMAC_CRC_ER_CNT_MASK;
494744961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
494844961713Sgirish 					NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP);
494944961713Sgirish 			}
495044961713Sgirish 			if (status & ICFG_BMAC_RX_LEN_ERR_CNT_EXP) {
495144961713Sgirish 				statsp->bmac_stats.rx_len_err_cnt +=
495244961713Sgirish 							MAC_LEN_ER_CNT_MASK;
495344961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
495444961713Sgirish 				NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP);
495544961713Sgirish 			}
495644961713Sgirish 			if (status & ICFG_BMAC_RX_VIOL_ERR_CNT_EXP)
495744961713Sgirish 				statsp->bmac_stats.rx_viol_err_cnt +=
495844961713Sgirish 							BMAC_CD_VIO_CNT_MASK;
495944961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
496044961713Sgirish 					NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP);
496144961713Sgirish 			}
496244961713Sgirish 			if (status & ICFG_BMAC_RX_BYTE_CNT_EXP) {
496344961713Sgirish 				statsp->bmac_stats.rx_byte_cnt +=
496444961713Sgirish 							BRXMAC_BYTE_CNT_MASK;
496544961713Sgirish 			}
496644961713Sgirish 			if (status & ICFG_BMAC_RX_ALIGNERR_CNT_EXP) {
496744961713Sgirish 				statsp->bmac_stats.rx_align_err_cnt +=
496844961713Sgirish 							BMAC_AL_ER_CNT_MASK;
496944961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
497044961713Sgirish 					NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP);
497144961713Sgirish 			}
497244961713Sgirish 
497344961713Sgirish 			rs = npi_bmac_ctl_get_istatus(handle, portn,
497444961713Sgirish 						(bmac_ctl_iconfig_t *)&status);
497544961713Sgirish 			if (rs != NPI_SUCCESS)
497644961713Sgirish 				goto npi_fail;
497744961713Sgirish 
497844961713Sgirish 			if (status & ICFG_BMAC_CTL_ALL) {
497944961713Sgirish 				if (status & ICFG_BMAC_CTL_RCVPAUSE)
498044961713Sgirish 					statsp->bmac_stats.rx_pause_cnt++;
498144961713Sgirish 				if (status & ICFG_BMAC_CTL_INPAUSE_ST)
498244961713Sgirish 					statsp->bmac_stats.tx_pause_state++;
498344961713Sgirish 				if (status & ICFG_BMAC_CTL_INNOTPAUSE_ST)
498444961713Sgirish 					statsp->bmac_stats.tx_nopause_state++;
498544961713Sgirish 			}
498644961713Sgirish 		}
498744961713Sgirish 
498844961713Sgirish 	if (ldgp->nldvs == 1) {
498944961713Sgirish 		(void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg,
499044961713Sgirish 			B_TRUE, ldgp->ldg_timer);
499144961713Sgirish 	}
499244961713Sgirish 
499344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mac_intr"));
499444961713Sgirish 	return (DDI_INTR_CLAIMED);
499544961713Sgirish 
499644961713Sgirish npi_fail:
499744961713Sgirish 	NXGE_ERROR_MSG((nxgep, INT_CTL, "<== nxge_mac_intr"));
499844961713Sgirish 	return (DDI_INTR_UNCLAIMED);
499944961713Sgirish }
500044961713Sgirish 
500144961713Sgirish nxge_status_t
500244961713Sgirish nxge_check_bcm8704_link(p_nxge_t nxgep, boolean_t *link_up)
500344961713Sgirish {
500444961713Sgirish 	uint8_t		phy_port_addr;
500544961713Sgirish 	nxge_status_t	status = NXGE_OK;
500644961713Sgirish 	boolean_t	rx_sig_ok;
500744961713Sgirish 	boolean_t	pcs_blk_lock;
500844961713Sgirish 	boolean_t	link_align;
500944961713Sgirish 	uint16_t	val1, val2, val3;
501044961713Sgirish #ifdef	NXGE_DEBUG_SYMBOL_ERR
501144961713Sgirish 	uint16_t	val_debug;
501244961713Sgirish 	uint16_t	val;
501344961713Sgirish #endif
501444961713Sgirish 
501544961713Sgirish 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
501644961713Sgirish 
501744961713Sgirish #ifdef	NXGE_DEBUG_SYMBOL_ERR
501844961713Sgirish 	/* Check Device 3 Register Device 3 0xC809 */
501944961713Sgirish 	(void) nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0xC809, &val_debug);
502044961713Sgirish 	if ((val_debug & ~0x200) != 0) {
502144961713Sgirish 		cmn_err(CE_NOTE, "!Port%d BCM8704 Dev3 Reg 0xc809 = 0x%x\n",
502244961713Sgirish 				nxgep->mac.portnum, val_debug);
502344961713Sgirish 		(void) nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18,
502444961713Sgirish 				&val_debug);
502544961713Sgirish 		cmn_err(CE_NOTE, "!Port%d BCM8704 Dev4 Reg 0x18 = 0x%x\n",
502644961713Sgirish 				nxgep->mac.portnum, val_debug);
502744961713Sgirish 	}
502844961713Sgirish 
502944961713Sgirish 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
503044961713Sgirish 					XPCS_REG_DESCWERR_COUNTER, &val);
503144961713Sgirish 	if (val != 0)
503244961713Sgirish 		cmn_err(CE_NOTE, "!XPCS DESCWERR = 0x%x\n", val);
503344961713Sgirish 
503444961713Sgirish 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
503544961713Sgirish 					XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val);
503644961713Sgirish 	if (val != 0)
503744961713Sgirish 		cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L0_1 = 0x%x\n", val);
503844961713Sgirish 
503944961713Sgirish 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
504044961713Sgirish 					XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val);
504144961713Sgirish 	if (val != 0)
504244961713Sgirish 		cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L2_3 = 0x%x\n", val);
504344961713Sgirish #endif
504444961713Sgirish 
504544961713Sgirish 	/* Check from BCM8704 if 10G link is up or down */
504644961713Sgirish 
504744961713Sgirish 	/* Check Device 1 Register 0xA bit0 */
504844961713Sgirish 	status = nxge_mdio_read(nxgep, phy_port_addr,
504944961713Sgirish 			BCM8704_PMA_PMD_DEV_ADDR,
505044961713Sgirish 			BCM8704_PMD_RECEIVE_SIG_DETECT,
505144961713Sgirish 			&val1);
505244961713Sgirish 	if (status != NXGE_OK)
505344961713Sgirish 		goto fail;
505444961713Sgirish 	rx_sig_ok = ((val1 & GLOB_PMD_RX_SIG_OK) ? B_TRUE : B_FALSE);
505544961713Sgirish 
505644961713Sgirish 	/* Check Device 3 Register 0x20 bit0 */
505744961713Sgirish 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
505844961713Sgirish 			BCM8704_PCS_DEV_ADDR,
505944961713Sgirish 			BCM8704_10GBASE_R_PCS_STATUS_REG,
506044961713Sgirish 			&val2)) != NPI_SUCCESS)
506144961713Sgirish 		goto fail;
506244961713Sgirish 	pcs_blk_lock = ((val2 & PCS_10GBASE_R_PCS_BLK_LOCK) ? B_TRUE : B_FALSE);
506344961713Sgirish 
506444961713Sgirish 	/* Check Device 4 Register 0x18 bit12 */
506544961713Sgirish 	status = nxge_mdio_read(nxgep, phy_port_addr,
506644961713Sgirish 			BCM8704_PHYXS_ADDR,
506744961713Sgirish 			BCM8704_PHYXS_XGXS_LANE_STATUS_REG,
506844961713Sgirish 			&val3);
506944961713Sgirish 	if (status != NXGE_OK)
507044961713Sgirish 		goto fail;
50712d17280bSsbehera 
50722d17280bSsbehera 	switch (nxgep->chip_id) {
50732d17280bSsbehera 	case BCM8704_CHIP_ID:
50742d17280bSsbehera 		link_align = (val3 == (XGXS_LANE_ALIGN_STATUS |
50752d17280bSsbehera 		    XGXS_LANE3_SYNC | XGXS_LANE2_SYNC | XGXS_LANE1_SYNC |
50762d17280bSsbehera 		    XGXS_LANE0_SYNC | 0x400)) ? B_TRUE : B_FALSE;
50772d17280bSsbehera 		break;
50782d17280bSsbehera 	case BCM8706_CHIP_ID:
50792d17280bSsbehera 		link_align = ((val3 & XGXS_LANE_ALIGN_STATUS) &&
50802d17280bSsbehera 		    (val3 & XGXS_LANE3_SYNC) && (val3 & XGXS_LANE2_SYNC) &&
50812d17280bSsbehera 		    (val3 & XGXS_LANE1_SYNC) && (val3 & XGXS_LANE0_SYNC)) ?
50822d17280bSsbehera 		    B_TRUE : B_FALSE;
50832d17280bSsbehera 		break;
50842d17280bSsbehera 	default:
50852d17280bSsbehera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_check_bcm8704_link:"
50862d17280bSsbehera 		    "Unknown chip ID [0x%x]", nxgep->chip_id));
50872d17280bSsbehera 		goto fail;
50882d17280bSsbehera 	}
50892d17280bSsbehera 
509044961713Sgirish 
509144961713Sgirish #ifdef	NXGE_DEBUG_ALIGN_ERR
509244961713Sgirish 	/* Temp workaround for link down issue */
509344961713Sgirish 	if (pcs_blk_lock == B_FALSE) {
509444961713Sgirish 		if (val2 != 0x4) {
509544961713Sgirish 			pcs_blk_lock = B_TRUE;
509644961713Sgirish 			cmn_err(CE_NOTE,
509744961713Sgirish 				"!LINK DEBUG: port%d PHY Dev3 "
509844961713Sgirish 				"Reg 0x20 = 0x%x\n",
509944961713Sgirish 				nxgep->mac.portnum, val2);
510044961713Sgirish 		}
510144961713Sgirish 	}
510244961713Sgirish 
510344961713Sgirish 	if (link_align == B_FALSE) {
510444961713Sgirish 		if (val3 != 0x140f) {
510544961713Sgirish 			link_align = B_TRUE;
510644961713Sgirish 			cmn_err(CE_NOTE,
510744961713Sgirish 				"!LINK DEBUG: port%d PHY Dev4 "
510844961713Sgirish 				"Reg 0x18 = 0x%x\n",
510944961713Sgirish 				nxgep->mac.portnum, val3);
511044961713Sgirish 		}
511144961713Sgirish 	}
511244961713Sgirish 
511344961713Sgirish 	if (rx_sig_ok == B_FALSE) {
511444961713Sgirish 		if ((val2 == 0) || (val3 == 0)) {
511544961713Sgirish 			rx_sig_ok = B_TRUE;
511644961713Sgirish 			cmn_err(CE_NOTE,
511744961713Sgirish 				"!LINK DEBUG: port %d Dev3 or Dev4 read zero\n",
511844961713Sgirish 				nxgep->mac.portnum);
511944961713Sgirish 		}
512044961713Sgirish 	}
512144961713Sgirish #endif
512244961713Sgirish 
512344961713Sgirish 	*link_up = ((rx_sig_ok == B_TRUE) && (pcs_blk_lock == B_TRUE) &&
512444961713Sgirish 			(link_align == B_TRUE)) ? B_TRUE : B_FALSE;
512544961713Sgirish 
512644961713Sgirish 	return (NXGE_OK);
512744961713Sgirish fail:
512844961713Sgirish 	return (status);
512944961713Sgirish }
513044961713Sgirish 
513159ac0c16Sdavemq nxge_status_t
513259ac0c16Sdavemq nxge_10g_link_led_on(p_nxge_t nxgep)
513359ac0c16Sdavemq {
513459ac0c16Sdavemq 	if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_TRUE)
513559ac0c16Sdavemq 	    != NPI_SUCCESS)
513659ac0c16Sdavemq 		return (NXGE_ERROR);
513759ac0c16Sdavemq 	else
513859ac0c16Sdavemq 		return (NXGE_OK);
513959ac0c16Sdavemq }
514044961713Sgirish 
514144961713Sgirish nxge_status_t
514259ac0c16Sdavemq nxge_10g_link_led_off(p_nxge_t nxgep)
514344961713Sgirish {
514459ac0c16Sdavemq 	if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_FALSE)
514559ac0c16Sdavemq 	    != NPI_SUCCESS)
514659ac0c16Sdavemq 		return (NXGE_ERROR);
514759ac0c16Sdavemq 	else
514859ac0c16Sdavemq 		return (NXGE_OK);
514959ac0c16Sdavemq }
515044961713Sgirish 
51512d17280bSsbehera static boolean_t
51522d17280bSsbehera nxge_is_phy_present(p_nxge_t nxgep, int addr, uint32_t id, uint32_t mask)
51532d17280bSsbehera {
51542d17280bSsbehera 	uint32_t pma_pmd_id = 0;
51552d17280bSsbehera 	uint32_t pcs_id = 0;
51562d17280bSsbehera 	uint32_t phy_id = 0;
51572d17280bSsbehera 
51582d17280bSsbehera 	pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, addr);
51592d17280bSsbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
51602d17280bSsbehera 	    "nxge_is_phy_present: pma_pmd_id[0x%x]", pma_pmd_id));
51612d17280bSsbehera 	if ((pma_pmd_id & mask) == (id & mask))
51622d17280bSsbehera 		goto found_phy;
51632d17280bSsbehera 	pcs_id = nxge_get_cl45_pcs_id(nxgep, addr);
51642d17280bSsbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
51652d17280bSsbehera 	    "nxge_is_phy_present: pcs_id[0x%x]", pcs_id));
51662d17280bSsbehera 	if ((pcs_id & mask) == (id & mask))
51672d17280bSsbehera 		goto found_phy;
51682d17280bSsbehera 	phy_id = nxge_get_cl22_phy_id(nxgep, addr);
51692d17280bSsbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
51702d17280bSsbehera 	    "nxge_is_phy_present: phy_id[0x%x]", phy_id));
51712d17280bSsbehera 	if ((phy_id & mask) == (id & mask))
51722d17280bSsbehera 		goto found_phy;
51732d17280bSsbehera 
51742d17280bSsbehera 	return (B_FALSE);
51752d17280bSsbehera 
51762d17280bSsbehera found_phy:
51772d17280bSsbehera 	return (B_TRUE);
51782d17280bSsbehera }
51792d17280bSsbehera 
518059ac0c16Sdavemq /* Check if the given id read using the given MDIO Clause is supported */
518159ac0c16Sdavemq 
518259ac0c16Sdavemq static boolean_t
518359ac0c16Sdavemq nxge_is_supported_phy(uint32_t id, uint8_t type)
518459ac0c16Sdavemq {
518559ac0c16Sdavemq 	int		i;
518659ac0c16Sdavemq 	int		cl45_arr_len = NUM_CLAUSE_45_IDS;
518759ac0c16Sdavemq 	int		cl22_arr_len = NUM_CLAUSE_22_IDS;
518859ac0c16Sdavemq 	boolean_t	found = B_FALSE;
518959ac0c16Sdavemq 
519059ac0c16Sdavemq 	switch (type) {
519159ac0c16Sdavemq 	case CLAUSE_45_TYPE:
519259ac0c16Sdavemq 		for (i = 0; i < cl45_arr_len; i++) {
519330505775Ssbehera 			if ((nxge_supported_cl45_ids[i] & BCM_PHY_ID_MASK) ==
519430505775Ssbehera 			    (id & BCM_PHY_ID_MASK)) {
519559ac0c16Sdavemq 				found = B_TRUE;
519659ac0c16Sdavemq 				break;
519759ac0c16Sdavemq 			}
519859ac0c16Sdavemq 		}
519959ac0c16Sdavemq 		break;
520059ac0c16Sdavemq 	case CLAUSE_22_TYPE:
520159ac0c16Sdavemq 		for (i = 0; i < cl22_arr_len; i++) {
520230505775Ssbehera 			if ((nxge_supported_cl22_ids[i] & BCM_PHY_ID_MASK) ==
520330505775Ssbehera 			    (id & BCM_PHY_ID_MASK)) {
520459ac0c16Sdavemq 				found = B_TRUE;
520559ac0c16Sdavemq 				break;
520656d930aeSspeer 			}
520744961713Sgirish 		}
520859ac0c16Sdavemq 		break;
520959ac0c16Sdavemq 	default:
521059ac0c16Sdavemq 		break;
521156d930aeSspeer 	}
521256d930aeSspeer 
521359ac0c16Sdavemq 	return (found);
521459ac0c16Sdavemq }
521559ac0c16Sdavemq 
52162e59129aSraghus static uint32_t
52172e59129aSraghus nxge_get_cl45_pma_pmd_id(p_nxge_t nxgep, int phy_port)
52182e59129aSraghus {
52192e59129aSraghus 	uint16_t	val1 = 0;
52202e59129aSraghus 	uint16_t	val2 = 0;
52212e59129aSraghus 	uint32_t	pma_pmd_dev_id = 0;
52222e59129aSraghus 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
52232e59129aSraghus 
522453560810Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
52252e59129aSraghus 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR,
52262e59129aSraghus 	    NXGE_DEV_ID_REG_1, &val1);
52272e59129aSraghus 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR,
52282e59129aSraghus 	    NXGE_DEV_ID_REG_2, &val2);
522953560810Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
52302e59129aSraghus 
52312e59129aSraghus 	pma_pmd_dev_id = val1;
52322e59129aSraghus 	pma_pmd_dev_id = (pma_pmd_dev_id << 16);
52332e59129aSraghus 	pma_pmd_dev_id |= val2;
52342e59129aSraghus 
52352e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PMA/PMD "
52362e59129aSraghus 	    "devid[0x%llx]", phy_port, pma_pmd_dev_id));
52372e59129aSraghus 
52382e59129aSraghus 	return (pma_pmd_dev_id);
52392e59129aSraghus }
52402e59129aSraghus 
52412e59129aSraghus static uint32_t
52422e59129aSraghus nxge_get_cl45_pcs_id(p_nxge_t nxgep, int phy_port)
52432e59129aSraghus {
52442e59129aSraghus 	uint16_t	val1 = 0;
52452e59129aSraghus 	uint16_t	val2 = 0;
52462e59129aSraghus 	uint32_t	pcs_dev_id = 0;
52472e59129aSraghus 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
52482e59129aSraghus 
524953560810Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
52502e59129aSraghus 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR,
52512e59129aSraghus 	    NXGE_DEV_ID_REG_1, &val1);
52522e59129aSraghus 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR,
52532e59129aSraghus 	    NXGE_DEV_ID_REG_2, &val2);
525453560810Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
52552e59129aSraghus 
52562e59129aSraghus 	pcs_dev_id = val1;
52572e59129aSraghus 	pcs_dev_id = (pcs_dev_id << 16);
52582e59129aSraghus 	pcs_dev_id |= val2;
52592e59129aSraghus 
52602e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS "
52612e59129aSraghus 	    "devid[0x%llx]", phy_port, pcs_dev_id));
52622e59129aSraghus 
52632e59129aSraghus 	return (pcs_dev_id);
52642e59129aSraghus }
52652e59129aSraghus 
52662e59129aSraghus static uint32_t
52672e59129aSraghus nxge_get_cl22_phy_id(p_nxge_t nxgep, int phy_port)
52682e59129aSraghus {
52692e59129aSraghus 	uint16_t	val1 = 0;
52702e59129aSraghus 	uint16_t	val2 = 0;
52712e59129aSraghus 	uint32_t	phy_id = 0;
52722e59129aSraghus 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
52732e59129aSraghus 	npi_status_t	npi_status = NPI_SUCCESS;
52742e59129aSraghus 
5275*321febdeSsbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
52762e59129aSraghus 	npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_1,
52772e59129aSraghus 	    &val1);
52782e59129aSraghus 	if (npi_status != NPI_SUCCESS) {
52792e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
52802e59129aSraghus 		    "clause 22 read to reg 2 failed!!!"));
52812e59129aSraghus 		goto exit;
52822e59129aSraghus 	}
52832e59129aSraghus 	npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_2,
52842e59129aSraghus 	    &val2);
52852e59129aSraghus 	if (npi_status != 0) {
52862e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
52872e59129aSraghus 		    "clause 22 read to reg 3 failed!!!"));
52882e59129aSraghus 		goto exit;
52892e59129aSraghus 	}
52902e59129aSraghus 	phy_id = val1;
52912e59129aSraghus 	phy_id = (phy_id << 16);
52922e59129aSraghus 	phy_id |= val2;
52932e59129aSraghus 
52942e59129aSraghus exit:
5295*321febdeSsbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
52962e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID [0x%llx]",
52972e59129aSraghus 	    phy_port, phy_id));
52982e59129aSraghus 
52992e59129aSraghus 	return (phy_id);
53002e59129aSraghus }
53012e59129aSraghus 
530259ac0c16Sdavemq /*
530359ac0c16Sdavemq  * Scan the PHY ports 0 through 31 to get the PHY ID using Clause 22 MDIO
530459ac0c16Sdavemq  * read and the PMA/PMD device ID and the PCS device ID using Clause 45 MDIO
530559ac0c16Sdavemq  * read. Then use the values obtained to determine the phy type of each port
530659ac0c16Sdavemq  * and the Neptune type.
530759ac0c16Sdavemq  */
530859ac0c16Sdavemq 
530959ac0c16Sdavemq nxge_status_t
531059ac0c16Sdavemq nxge_scan_ports_phy(p_nxge_t nxgep, p_nxge_hw_list_t hw_p)
531159ac0c16Sdavemq {
531259ac0c16Sdavemq 	int		i, j, k, l;
531359ac0c16Sdavemq 	uint32_t	pma_pmd_dev_id = 0;
531459ac0c16Sdavemq 	uint32_t	pcs_dev_id = 0;
531559ac0c16Sdavemq 	uint32_t	phy_id = 0;
531630505775Ssbehera 	uint32_t	port_pma_pmd_dev_id[NXGE_PORTS_NEPTUNE];
531730505775Ssbehera 	uint32_t	port_pcs_dev_id[NXGE_PORTS_NEPTUNE];
531830505775Ssbehera 	uint32_t	port_phy_id[NXGE_PORTS_NEPTUNE];
531959ac0c16Sdavemq 	uint8_t		pma_pmd_dev_fd[NXGE_MAX_PHY_PORTS];
532059ac0c16Sdavemq 	uint8_t		pcs_dev_fd[NXGE_MAX_PHY_PORTS];
53212d17280bSsbehera 	uint8_t		phy_fd_arr[NXGE_MAX_PHY_PORTS];
53222d17280bSsbehera 	uint8_t		port_fd_arr[NXGE_MAX_PHY_PORTS];
532359ac0c16Sdavemq 	uint8_t		total_port_fd, total_phy_fd;
532459ac0c16Sdavemq 	nxge_status_t	status = NXGE_OK;
532556d930aeSspeer 
532659ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_scan_ports_phy: "));
532756d930aeSspeer 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
532859ac0c16Sdavemq 	    "==> nxge_scan_ports_phy: nxge niu_type[0x%x]",
532959ac0c16Sdavemq 	    nxgep->niu_type));
533059ac0c16Sdavemq 
533159ac0c16Sdavemq 	j = k = l = 0;
533259ac0c16Sdavemq 	total_port_fd = total_phy_fd = 0;
533356d930aeSspeer 	/*
533459ac0c16Sdavemq 	 * Clause 45 and Clause 22 port/phy addresses 0 through 7 are reserved
533559ac0c16Sdavemq 	 * for on chip serdes usages.
533656d930aeSspeer 	 */
533759ac0c16Sdavemq 	for (i = NXGE_EXT_PHY_PORT_ST; i < NXGE_MAX_PHY_PORTS; i++) {
53382e59129aSraghus 
53392e59129aSraghus 		pma_pmd_dev_id = nxge_get_cl45_pma_pmd_id(nxgep, i);
534059ac0c16Sdavemq 
534159ac0c16Sdavemq 		if (nxge_is_supported_phy(pma_pmd_dev_id, CLAUSE_45_TYPE)) {
534259ac0c16Sdavemq 			pma_pmd_dev_fd[i] = 1;
534359ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
534459ac0c16Sdavemq 			    "PMA/PMD dev found", i));
534530505775Ssbehera 			if (j < NXGE_PORTS_NEPTUNE) {
534630505775Ssbehera 				port_pma_pmd_dev_id[j] = pma_pmd_dev_id &
534730505775Ssbehera 				    BCM_PHY_ID_MASK;
53482d17280bSsbehera 				port_fd_arr[j] = (uint8_t)i;
534959ac0c16Sdavemq 				j++;
535059ac0c16Sdavemq 			}
535159ac0c16Sdavemq 		} else {
535259ac0c16Sdavemq 			pma_pmd_dev_fd[i] = 0;
535359ac0c16Sdavemq 		}
535459ac0c16Sdavemq 
53552e59129aSraghus 		pcs_dev_id = nxge_get_cl45_pcs_id(nxgep, i);
535659ac0c16Sdavemq 
535759ac0c16Sdavemq 		if (nxge_is_supported_phy(pcs_dev_id, CLAUSE_45_TYPE)) {
535859ac0c16Sdavemq 			pcs_dev_fd[i] = 1;
535959ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS "
536059ac0c16Sdavemq 			    "dev found", i));
536130505775Ssbehera 			if (k < NXGE_PORTS_NEPTUNE) {
536230505775Ssbehera 				port_pcs_dev_id[k] = pcs_dev_id &
536330505775Ssbehera 				    BCM_PHY_ID_MASK;
53642d17280bSsbehera 				port_fd_arr[k] = (uint8_t)i;
536559ac0c16Sdavemq 				k++;
536659ac0c16Sdavemq 			}
536759ac0c16Sdavemq 		} else {
536859ac0c16Sdavemq 			pcs_dev_fd[i] = 0;
536959ac0c16Sdavemq 		}
537059ac0c16Sdavemq 
53712d17280bSsbehera 		if (pcs_dev_fd[i] || pma_pmd_dev_fd[i]) {
53722d17280bSsbehera 			total_port_fd ++;
53732d17280bSsbehera 		}
537459ac0c16Sdavemq 
53752e59129aSraghus 		phy_id = nxge_get_cl22_phy_id(nxgep, i);
537659ac0c16Sdavemq 
537759ac0c16Sdavemq 		if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) {
53782d17280bSsbehera 			total_phy_fd ++;
537959ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID"
538059ac0c16Sdavemq 			    "found", i));
538130505775Ssbehera 			if (l < NXGE_PORTS_NEPTUNE) {
538230505775Ssbehera 				port_phy_id[l] = phy_id & BCM_PHY_ID_MASK;
53832d17280bSsbehera 				phy_fd_arr[l] = (uint8_t)i;
538459ac0c16Sdavemq 				l++;
538559ac0c16Sdavemq 			}
538659ac0c16Sdavemq 		}
538759ac0c16Sdavemq 	}
538859ac0c16Sdavemq 
538959ac0c16Sdavemq 	switch (total_port_fd) {
539059ac0c16Sdavemq 	case 2:
539159ac0c16Sdavemq 		switch (total_phy_fd) {
539259ac0c16Sdavemq 		case 2:
53932e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
53942e59129aSraghus 			    "Unsupported neptune type 1"));
53952e59129aSraghus 			goto error_exit;
539659ac0c16Sdavemq 		case 1:
539759ac0c16Sdavemq 			/* TODO - 2 10G, 1 1G */
539859ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
539959ac0c16Sdavemq 			    "Unsupported neptune type 2 10G, 1 1G"));
540059ac0c16Sdavemq 			goto error_exit;
540159ac0c16Sdavemq 		case 0:
540259ac0c16Sdavemq 			/* 2 10G */
540330505775Ssbehera 			if (((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) &&
540430505775Ssbehera 			    (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) ||
540530505775Ssbehera 			    ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) &&
540630505775Ssbehera 			    (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) {
54072e59129aSraghus 
54082e59129aSraghus 				/*
54092e59129aSraghus 				 * Check the first phy port address against
54102e59129aSraghus 				 * the known phy start addresses to determine
54112e59129aSraghus 				 * the platform type.
54122e59129aSraghus 				 */
54132d17280bSsbehera 
54142d17280bSsbehera 				switch (port_fd_arr[0]) {
54152d17280bSsbehera 				case BCM8704_NEPTUNE_PORT_ADDR_BASE:
54162e59129aSraghus 					hw_p->niu_type = NEPTUNE_2_10GF;
54172e59129aSraghus 					hw_p->platform_type =
54182e59129aSraghus 					    P_NEPTUNE_ATLAS_2PORT;
54192d17280bSsbehera 					break;
54202d17280bSsbehera 				case BCM8706_GOA_PORT_ADDR_BASE:
54212d17280bSsbehera 					if (hw_p->platform_type !=
54222d17280bSsbehera 					    P_NEPTUNE_NIU) {
54232d17280bSsbehera 						hw_p->platform_type =
54242d17280bSsbehera 						    P_NEPTUNE_GENERIC;
54252d17280bSsbehera 						hw_p->niu_type =
54262d17280bSsbehera 						    NEPTUNE_2_10GF;
54272d17280bSsbehera 					}
54282d17280bSsbehera 					break;
54292d17280bSsbehera 				default:
54302d17280bSsbehera 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
54312e59129aSraghus 					    "Unsupported neptune type 2 - 1"));
54322e59129aSraghus 					goto error_exit;
54332e59129aSraghus 				}
54342d17280bSsbehera 
54352d17280bSsbehera 				for (i = 0; i < 2; i++) {
54362d17280bSsbehera 					hw_p->xcvr_addr[i] = port_fd_arr[i];
54372d17280bSsbehera 				}
543859ac0c16Sdavemq 			} else {
543959ac0c16Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
544059ac0c16Sdavemq 				    "Unsupported neptune type 2"));
544159ac0c16Sdavemq 				goto error_exit;
544259ac0c16Sdavemq 			}
544359ac0c16Sdavemq 			break;
544459ac0c16Sdavemq 		case 4:
544559ac0c16Sdavemq 			/* Maramba with 2 XAUI */
544630505775Ssbehera 			if ((((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) &&
544730505775Ssbehera 			    (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) ||
544830505775Ssbehera 			    ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) &&
544930505775Ssbehera 			    (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) &&
545030505775Ssbehera 			    ((port_phy_id[0] == PHY_BCM5464R_FAMILY) &&
545130505775Ssbehera 			    (port_phy_id[1] == PHY_BCM5464R_FAMILY) &&
545230505775Ssbehera 			    (port_phy_id[2] == PHY_BCM5464R_FAMILY) &&
545330505775Ssbehera 			    (port_phy_id[3] == PHY_BCM5464R_FAMILY))) {
545459ac0c16Sdavemq 
545559ac0c16Sdavemq 				/*
545659ac0c16Sdavemq 				 * Check the first phy port address against
545759ac0c16Sdavemq 				 * the known phy start addresses to determine
545859ac0c16Sdavemq 				 * the platform type.
545959ac0c16Sdavemq 				 */
54602d17280bSsbehera 				switch (phy_fd_arr[0]) {
54612d17280bSsbehera 				case BCM5464_MARAMBA_P0_PORT_ADDR_BASE:
546259ac0c16Sdavemq 					hw_p->platform_type =
546359ac0c16Sdavemq 					    P_NEPTUNE_MARAMBA_P0;
54642d17280bSsbehera 					break;
54652d17280bSsbehera 				case BCM5464_MARAMBA_P1_PORT_ADDR_BASE:
546659ac0c16Sdavemq 					hw_p->platform_type =
546759ac0c16Sdavemq 					    P_NEPTUNE_MARAMBA_P1;
54682d17280bSsbehera 					break;
54692d17280bSsbehera 				default:
547059ac0c16Sdavemq 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
547159ac0c16Sdavemq 					    "Unknown port %d...Cannot "
547259ac0c16Sdavemq 					    "determine platform type", i));
54732e59129aSraghus 					goto error_exit;
547459ac0c16Sdavemq 				}
54752d17280bSsbehera 
54762e59129aSraghus 				hw_p->niu_type = NEPTUNE_2_10GF_2_1GC;
54772e59129aSraghus 
54782d17280bSsbehera 				hw_p->xcvr_addr[0] = port_fd_arr[0];
54792d17280bSsbehera 				hw_p->xcvr_addr[1] = port_fd_arr[1];
54802d17280bSsbehera 				hw_p->xcvr_addr[2] = phy_fd_arr[2];
54812d17280bSsbehera 				hw_p->xcvr_addr[3] = phy_fd_arr[3];
54822d17280bSsbehera 
548359ac0c16Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
548459ac0c16Sdavemq 				    "Maramba with 2 XAUI"));
548559ac0c16Sdavemq 			} else {
548659ac0c16Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
548759ac0c16Sdavemq 				    "Unsupported neptune type 3"));
548859ac0c16Sdavemq 				goto error_exit;
548959ac0c16Sdavemq 			}
549059ac0c16Sdavemq 			break;
549159ac0c16Sdavemq 		default:
549259ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
549359ac0c16Sdavemq 			    "Unsupported neptune type 5"));
549459ac0c16Sdavemq 			goto error_exit;
549559ac0c16Sdavemq 		}
549630505775Ssbehera 		break;
549759ac0c16Sdavemq 	case 1:
549859ac0c16Sdavemq 		switch (total_phy_fd) {
549959ac0c16Sdavemq 		case 3:
55002e59129aSraghus 			/*
55012e59129aSraghus 			 * TODO 3 1G, 1 10G mode.
55022e59129aSraghus 			 * Differentiate between 1_1G_1_10G_2_1G and
55032e59129aSraghus 			 * 1_10G_3_1G
55042e59129aSraghus 			 */
55052e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
55062e59129aSraghus 			    "Unsupported neptune type 7"));
55072e59129aSraghus 			goto error_exit;
550859ac0c16Sdavemq 		case 2:
550959ac0c16Sdavemq 			/*
551059ac0c16Sdavemq 			 * TODO 2 1G, 1 10G mode.
551159ac0c16Sdavemq 			 * Differentiate between 1_1G_1_10G_1_1G and
551259ac0c16Sdavemq 			 * 1_10G_2_1G
551359ac0c16Sdavemq 			 */
551459ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
551559ac0c16Sdavemq 			    "Unsupported neptune type 8"));
551659ac0c16Sdavemq 			goto error_exit;
551759ac0c16Sdavemq 		case 1:
551859ac0c16Sdavemq 			/*
551959ac0c16Sdavemq 			 * TODO 1 1G, 1 10G mode.
552059ac0c16Sdavemq 			 * Differentiate between 1_1G_1_10G and
552159ac0c16Sdavemq 			 * 1_10G_1_1G
552259ac0c16Sdavemq 			 */
552359ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
552459ac0c16Sdavemq 			    "Unsupported neptune type 9"));
552559ac0c16Sdavemq 			goto error_exit;
552659ac0c16Sdavemq 		case 0:
55272d17280bSsbehera 			/* 1 10G mode, N2 with 1 XAUI */
55282d17280bSsbehera 			if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY ||
55292d17280bSsbehera 			    port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) {
55302d17280bSsbehera 
55312d17280bSsbehera 				/*
55322d17280bSsbehera 				 * Check the first phy port address against
55332d17280bSsbehera 				 * the known phy start addresses to determine
55342d17280bSsbehera 				 * the platform type.
55352d17280bSsbehera 				 */
55362d17280bSsbehera 
55372d17280bSsbehera 				switch (port_fd_arr[0]) {
55382d17280bSsbehera 				case BCM8704_N2_PORT_ADDR_BASE:
55392d17280bSsbehera 				case (BCM8704_N2_PORT_ADDR_BASE + 1):
55402d17280bSsbehera 				case BCM8706_ALT_GOA_PORT1_ADDR:
55412d17280bSsbehera 					if (hw_p->platform_type !=
55422d17280bSsbehera 					    P_NEPTUNE_NIU) {
55432d17280bSsbehera 						hw_p->platform_type =
55442d17280bSsbehera 						    P_NEPTUNE_GENERIC;
55452d17280bSsbehera 						hw_p->niu_type =
55462d17280bSsbehera 						    NEPTUNE_2_10GF;
55472d17280bSsbehera 					}
55482d17280bSsbehera 					break;
55492d17280bSsbehera 				default:
55502d17280bSsbehera 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
55512d17280bSsbehera 					    "Unsupported neptune type 10"));
55522d17280bSsbehera 					goto error_exit;
55532d17280bSsbehera 				}
5554*321febdeSsbehera 				/*
5555*321febdeSsbehera 				 * For GOA, which is a hot swappable PHY, the
5556*321febdeSsbehera 				 * phy address to function number mapping
5557*321febdeSsbehera 				 * should be preserved, i.e., addr 16 is
5558*321febdeSsbehera 				 * assigned to function 0 and 20 to function 1
5559*321febdeSsbehera 				 * But for Huron XAUI, the assignment should
5560*321febdeSsbehera 				 * be by function number, i.e., whichever
5561*321febdeSsbehera 				 * function number attaches should be
5562*321febdeSsbehera 				 * assigned the available PHY (this is required
5563*321febdeSsbehera 				 * primarily to support pre-production Huron
5564*321febdeSsbehera 				 * boards where function 0 is mapped to addr 17
5565*321febdeSsbehera 				 */
5566*321febdeSsbehera 				if (port_fd_arr[0] ==
5567*321febdeSsbehera 				    BCM8706_ALT_GOA_PORT1_ADDR) {
5568*321febdeSsbehera 					hw_p->xcvr_addr[1] = port_fd_arr[0];
5569*321febdeSsbehera 				} else {
5570*321febdeSsbehera 					hw_p->xcvr_addr[nxgep->function_num] =
5571*321febdeSsbehera 					    port_fd_arr[0];
5572*321febdeSsbehera 				}
55732d17280bSsbehera 			} else {
55742d17280bSsbehera 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
55752d17280bSsbehera 				    "Unsupported neptune type 10 - 1"));
55762d17280bSsbehera 				goto error_exit;
55772d17280bSsbehera 			}
55782d17280bSsbehera 			break;
557959ac0c16Sdavemq 		case 4:
558059ac0c16Sdavemq 			/* Maramba with 1 XAUI */
558130505775Ssbehera 			if ((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) ||
558230505775Ssbehera 			    (port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY)) {
558359ac0c16Sdavemq 
558459ac0c16Sdavemq 				/*
558559ac0c16Sdavemq 				 * Check the first phy port address against
558659ac0c16Sdavemq 				 * the known phy start addresses to determine
558759ac0c16Sdavemq 				 * the platform type.
558859ac0c16Sdavemq 				 */
55892d17280bSsbehera 				switch (phy_fd_arr[0]) {
55902d17280bSsbehera 				case BCM5464_MARAMBA_P0_PORT_ADDR_BASE:
559159ac0c16Sdavemq 					hw_p->platform_type =
559259ac0c16Sdavemq 					    P_NEPTUNE_MARAMBA_P0;
55932d17280bSsbehera 					break;
55942d17280bSsbehera 				case BCM5464_MARAMBA_P1_PORT_ADDR_BASE:
559559ac0c16Sdavemq 					hw_p->platform_type =
559659ac0c16Sdavemq 					    P_NEPTUNE_MARAMBA_P1;
55972d17280bSsbehera 					break;
55982d17280bSsbehera 				default:
559959ac0c16Sdavemq 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
560059ac0c16Sdavemq 					    "Unknown port %d...Cannot "
56012d17280bSsbehera 					    "determine platform type 10 - 2",
56022d17280bSsbehera 					    i));
56032e59129aSraghus 					goto error_exit;
56042e59129aSraghus 				}
56052e59129aSraghus 
56062d17280bSsbehera 				/*
56072d17280bSsbehera 				 * Check the BCM8704 address to determine
56082d17280bSsbehera 				 * if XAUI is in port 0 or port 1.
56092d17280bSsbehera 				 */
56102d17280bSsbehera 				switch (port_fd_arr[0]) {
56112d17280bSsbehera 				case BCM8704_MARAMBA_PORT_ADDR_BASE:
56122e59129aSraghus 					hw_p->niu_type = NEPTUNE_1_10GF_3_1GC;
56132d17280bSsbehera 					hw_p->xcvr_addr[0] = port_fd_arr[0];
56142d17280bSsbehera 					for (i = 1; i < NXGE_MAX_PORTS; i++) {
56152d17280bSsbehera 						hw_p->xcvr_addr[i] =
56162d17280bSsbehera 						    phy_fd_arr[i];
56172d17280bSsbehera 					}
56182d17280bSsbehera 					break;
56192d17280bSsbehera 				case (BCM8704_MARAMBA_PORT_ADDR_BASE + 1):
56202e59129aSraghus 					hw_p->niu_type =
56212e59129aSraghus 					    NEPTUNE_1_1GC_1_10GF_2_1GC;
56222d17280bSsbehera 					hw_p->xcvr_addr[0] = phy_fd_arr[0];
56232d17280bSsbehera 					hw_p->xcvr_addr[1] = port_fd_arr[0];
56242d17280bSsbehera 					hw_p->xcvr_addr[2] = phy_fd_arr[2];
56252d17280bSsbehera 					hw_p->xcvr_addr[3] = phy_fd_arr[3];
56262d17280bSsbehera 					break;
56272d17280bSsbehera 				default:
56282e59129aSraghus 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
56292e59129aSraghus 					    "Unsupported neptune type 11"));
56302e59129aSraghus 					goto error_exit;
563159ac0c16Sdavemq 				}
563259ac0c16Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
563359ac0c16Sdavemq 				    "Maramba with 1 XAUI"));
563459ac0c16Sdavemq 			} else {
563559ac0c16Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
563659ac0c16Sdavemq 				    "Unsupported neptune type 12"));
563759ac0c16Sdavemq 				goto error_exit;
563859ac0c16Sdavemq 			}
563959ac0c16Sdavemq 			break;
564059ac0c16Sdavemq 		default:
564159ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
564259ac0c16Sdavemq 			    "Unsupported neptune type 13"));
564359ac0c16Sdavemq 			goto error_exit;
564459ac0c16Sdavemq 		}
564559ac0c16Sdavemq 		break;
564659ac0c16Sdavemq 	case 0:
564759ac0c16Sdavemq 		switch (total_phy_fd) {
564859ac0c16Sdavemq 		case 4:
564930505775Ssbehera 			if ((port_phy_id[0] == PHY_BCM5464R_FAMILY) &&
565030505775Ssbehera 			    (port_phy_id[1] == PHY_BCM5464R_FAMILY) &&
565130505775Ssbehera 			    (port_phy_id[2] == PHY_BCM5464R_FAMILY) &&
565230505775Ssbehera 			    (port_phy_id[3] == PHY_BCM5464R_FAMILY)) {
565359ac0c16Sdavemq 
565459ac0c16Sdavemq 				/*
565559ac0c16Sdavemq 				 * Check the first phy port address against
565659ac0c16Sdavemq 				 * the known phy start addresses to determine
565759ac0c16Sdavemq 				 * the platform type.
565859ac0c16Sdavemq 				 */
56592d17280bSsbehera 				switch (phy_fd_arr[0]) {
56602d17280bSsbehera 				case BCM5464_MARAMBA_P1_PORT_ADDR_BASE:
566159ac0c16Sdavemq 					hw_p->platform_type =
566259ac0c16Sdavemq 					    P_NEPTUNE_MARAMBA_P1;
56632d17280bSsbehera 					break;
56642d17280bSsbehera 				case BCM5464_NEPTUNE_PORT_ADDR_BASE:
56652e59129aSraghus 					hw_p->platform_type =
56662e59129aSraghus 					    P_NEPTUNE_ATLAS_4PORT;
56672d17280bSsbehera 					break;
56682d17280bSsbehera 				default:
56692e59129aSraghus 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
56702e59129aSraghus 					    "Unknown port %d...Cannot "
56712e59129aSraghus 					    "determine platform type", i));
56722e59129aSraghus 					goto error_exit;
567359ac0c16Sdavemq 				}
56742e59129aSraghus 				hw_p->niu_type = NEPTUNE_4_1GC;
56752d17280bSsbehera 				for (i = 0; i < NXGE_MAX_PORTS; i++) {
56762d17280bSsbehera 					hw_p->xcvr_addr[i] = phy_fd_arr[i];
56772d17280bSsbehera 				}
567859ac0c16Sdavemq 			} else {
567959ac0c16Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
568059ac0c16Sdavemq 				    "Unsupported neptune type 14"));
568159ac0c16Sdavemq 				goto error_exit;
568259ac0c16Sdavemq 			}
568359ac0c16Sdavemq 			break;
568459ac0c16Sdavemq 		case 3:
568559ac0c16Sdavemq 			/* TODO 3 1G mode */
568659ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
568759ac0c16Sdavemq 			    "Unsupported neptune type 15"));
568859ac0c16Sdavemq 			goto error_exit;
568959ac0c16Sdavemq 		case 2:
569059ac0c16Sdavemq 			/* TODO 2 1G mode */
569159ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
569259ac0c16Sdavemq 			    "Unsupported neptune type 16"));
569359ac0c16Sdavemq 			goto error_exit;
569459ac0c16Sdavemq 		case 1:
569559ac0c16Sdavemq 			/* TODO 1 1G mode */
569659ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
569759ac0c16Sdavemq 			    "Unsupported neptune type 17"));
569859ac0c16Sdavemq 			goto error_exit;
569959ac0c16Sdavemq 		default:
570059ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
570159ac0c16Sdavemq 			    "Unsupported neptune type 18, total phy fd %d",
570259ac0c16Sdavemq 			    total_phy_fd));
570359ac0c16Sdavemq 			goto error_exit;
570459ac0c16Sdavemq 		}
570559ac0c16Sdavemq 		break;
570659ac0c16Sdavemq 	default:
570756d930aeSspeer 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
570859ac0c16Sdavemq 		    "Unsupported neptune type 19"));
570959ac0c16Sdavemq 		goto error_exit;
571044961713Sgirish 	}
571144961713Sgirish 
571259ac0c16Sdavemq scan_exit:
571344961713Sgirish 
571459ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_scan_ports_phy, "
571559ac0c16Sdavemq 	    "niu type [0x%x]\n", hw_p->niu_type));
571659ac0c16Sdavemq 	return (status);
571744961713Sgirish 
571859ac0c16Sdavemq error_exit:
571959ac0c16Sdavemq 	return (NXGE_ERROR);
572044961713Sgirish }
572156d930aeSspeer 
572256d930aeSspeer boolean_t
572356d930aeSspeer nxge_is_valid_local_mac(ether_addr_st mac_addr)
572456d930aeSspeer {
572556d930aeSspeer 	if ((mac_addr.ether_addr_octet[0] & 0x01) ||
572656d930aeSspeer 	    (ether_cmp(&mac_addr, &etherbroadcastaddr) == 0) ||
572756d930aeSspeer 	    (ether_cmp(&mac_addr, &etherzeroaddr) == 0))
572856d930aeSspeer 		return (B_FALSE);
572956d930aeSspeer 	else
573056d930aeSspeer 		return (B_TRUE);
573156d930aeSspeer }
573259ac0c16Sdavemq 
573359ac0c16Sdavemq static void
573459ac0c16Sdavemq nxge_bcm5464_link_led_off(p_nxge_t nxgep) {
573559ac0c16Sdavemq 
573659ac0c16Sdavemq 	npi_status_t rs = NPI_SUCCESS;
573759ac0c16Sdavemq 	uint8_t xcvr_portn;
573859ac0c16Sdavemq 	uint8_t	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
573959ac0c16Sdavemq 
574059ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_bcm5464_link_led_off"));
574159ac0c16Sdavemq 
574259ac0c16Sdavemq 	if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P1) {
574359ac0c16Sdavemq 		xcvr_portn = BCM5464_MARAMBA_P1_PORT_ADDR_BASE;
574459ac0c16Sdavemq 	} else if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P0) {
574559ac0c16Sdavemq 		xcvr_portn = BCM5464_MARAMBA_P0_PORT_ADDR_BASE;
574659ac0c16Sdavemq 	}
574759ac0c16Sdavemq 	/*
574859ac0c16Sdavemq 	 * For Altas 4-1G copper, Xcvr port numbers are
574959ac0c16Sdavemq 	 * swapped with ethernet port number. This is
575059ac0c16Sdavemq 	 * designed for better signal integrity in routing.
575159ac0c16Sdavemq 	 */
575259ac0c16Sdavemq 	switch (portn) {
575359ac0c16Sdavemq 	case 0:
575459ac0c16Sdavemq 		xcvr_portn += 3;
575559ac0c16Sdavemq 		break;
575659ac0c16Sdavemq 	case 1:
575759ac0c16Sdavemq 		xcvr_portn += 2;
575859ac0c16Sdavemq 		break;
575959ac0c16Sdavemq 	case 2:
576059ac0c16Sdavemq 		xcvr_portn += 1;
576159ac0c16Sdavemq 		break;
576259ac0c16Sdavemq 	case 3:
576359ac0c16Sdavemq 	default:
576459ac0c16Sdavemq 		break;
576559ac0c16Sdavemq 	}
576659ac0c16Sdavemq 
5767*321febdeSsbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
576859ac0c16Sdavemq 	rs = npi_mac_mif_mii_write(nxgep->npi_handle,
576959ac0c16Sdavemq 	    xcvr_portn, BCM5464R_MISC, 0xb4ee);
577059ac0c16Sdavemq 	if (rs != NPI_SUCCESS) {
577159ac0c16Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
577259ac0c16Sdavemq 		    "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write "
577359ac0c16Sdavemq 		    "returned error 0x[%x]", rs));
5774*321febdeSsbehera 		MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
577559ac0c16Sdavemq 		return;
577659ac0c16Sdavemq 	}
577759ac0c16Sdavemq 
577859ac0c16Sdavemq 	rs = npi_mac_mif_mii_write(nxgep->npi_handle,
577959ac0c16Sdavemq 	    xcvr_portn, BCM5464R_MISC, 0xb8ee);
578059ac0c16Sdavemq 	if (rs != NPI_SUCCESS) {
578159ac0c16Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
578259ac0c16Sdavemq 		    "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write "
578359ac0c16Sdavemq 		    "returned error 0x[%x]", rs));
578459ac0c16Sdavemq 	}
578559ac0c16Sdavemq 
5786*321febdeSsbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
578759ac0c16Sdavemq }
5788d81011f0Ssbehera 
5789d81011f0Ssbehera static nxge_status_t
5790d81011f0Ssbehera nxge_mii_get_link_mode(p_nxge_t nxgep)
5791d81011f0Ssbehera {
5792d81011f0Ssbehera 	p_nxge_stats_t	statsp;
5793d81011f0Ssbehera 	uint8_t		xcvr_portn;
5794d81011f0Ssbehera 	p_mii_regs_t	mii_regs;
5795d81011f0Ssbehera 	mii_mode_control_stat_t	mode;
5796d81011f0Ssbehera 	int		status = NXGE_OK;
5797d81011f0Ssbehera 
5798d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_get_link_mode"));
5799d81011f0Ssbehera 
5800d81011f0Ssbehera 	statsp = nxgep->statsp;
5801d81011f0Ssbehera 	xcvr_portn = statsp->mac_stats.xcvr_portn;
5802d81011f0Ssbehera 	mii_regs = NULL;
5803d81011f0Ssbehera 	mode.value = 0;
58046b438925Ssbehera 	mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG;
5805d81011f0Ssbehera #if defined(__i386)
5806d81011f0Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
5807d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->shadow),
5808d81011f0Ssbehera 	    mode.value)) != NXGE_OK) {
5809d81011f0Ssbehera 		goto fail;
5810d81011f0Ssbehera #else
5811d81011f0Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
5812d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->shadow),
5813d81011f0Ssbehera 	    mode.value)) != NXGE_OK) {
5814d81011f0Ssbehera 		goto fail;
5815d81011f0Ssbehera #endif
5816d81011f0Ssbehera 	}
5817d81011f0Ssbehera #if defined(__i386)
5818d81011f0Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
5819d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->shadow),
5820d81011f0Ssbehera 	    &mode.value)) != NXGE_OK) {
5821d81011f0Ssbehera 		goto fail;
5822d81011f0Ssbehera 	}
5823d81011f0Ssbehera #else
5824d81011f0Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
5825d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->shadow),
5826d81011f0Ssbehera 	    &mode.value)) != NXGE_OK) {
5827d81011f0Ssbehera 		goto fail;
5828d81011f0Ssbehera 	}
5829d81011f0Ssbehera #endif
5830d81011f0Ssbehera 
5831d81011f0Ssbehera 	if (mode.bits.mode == NXGE_MODE_SELECT_FIBER) {
5832d81011f0Ssbehera 		nxgep->mac.portmode = PORT_1G_RGMII_FIBER;
5833d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5834d81011f0Ssbehera 		    "nxge_mii_get_link_mode: fiber mode"));
5835d81011f0Ssbehera 	}
5836d81011f0Ssbehera 
5837d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5838d81011f0Ssbehera 	    "nxge_mii_get_link_mode: "
5839d81011f0Ssbehera 	    "(address 0x%x) port 0x%x mode value 0x%x link mode 0x%x",
58406b438925Ssbehera 	    NXGE_MII_MODE_CONTROL_REG, xcvr_portn,
5841d81011f0Ssbehera 	    mode.value, nxgep->mac.portmode));
5842d81011f0Ssbehera 
5843d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5844d81011f0Ssbehera 	    "<== nxge_mii_get_link_mode"));
5845d81011f0Ssbehera 	return (status);
5846d81011f0Ssbehera fail:
5847d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5848d81011f0Ssbehera 	    "<== nxge_mii_get_link_mode (failed)"));
5849d81011f0Ssbehera 	return (NXGE_ERROR);
5850d81011f0Ssbehera }
5851d81011f0Ssbehera 
5852d81011f0Ssbehera #ifdef NXGE_DEBUG
5853d81011f0Ssbehera static void
5854d81011f0Ssbehera nxge_mii_dump(p_nxge_t nxgep)
5855d81011f0Ssbehera {
5856d81011f0Ssbehera 	p_nxge_stats_t	statsp;
5857d81011f0Ssbehera 	uint8_t		xcvr_portn;
5858d81011f0Ssbehera 	p_mii_regs_t	mii_regs;
5859d81011f0Ssbehera 	mii_bmcr_t	bmcr;
5860d81011f0Ssbehera 	mii_bmsr_t	bmsr;
5861d81011f0Ssbehera 	mii_idr1_t	idr1;
5862d81011f0Ssbehera 	mii_idr2_t	idr2;
5863d81011f0Ssbehera 	mii_mode_control_stat_t	mode;
5864d81011f0Ssbehera 
5865d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_mii_dump"));
5866d81011f0Ssbehera 
5867d81011f0Ssbehera 	statsp = nxgep->statsp;
5868d81011f0Ssbehera 	xcvr_portn = statsp->mac_stats.xcvr_portn;
5869d81011f0Ssbehera 
5870d81011f0Ssbehera 	mii_regs = NULL;
5871d81011f0Ssbehera 
5872d81011f0Ssbehera #if defined(__i386)
5873d81011f0Ssbehera 	(void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn,
5874d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value);
5875d81011f0Ssbehera #else
5876d81011f0Ssbehera 	(void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn,
5877d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value);
5878d81011f0Ssbehera #endif
5879d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5880d81011f0Ssbehera 	    "nxge_mii_dump: bmcr (0) xcvr 0x%x value 0x%x",
5881d81011f0Ssbehera 	    xcvr_portn, bmcr.value));
5882d81011f0Ssbehera 
5883d81011f0Ssbehera #if defined(__i386)
5884d81011f0Ssbehera 	(void) nxge_mii_read(nxgep,
5885d81011f0Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
5886d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value);
5887d81011f0Ssbehera #else
5888d81011f0Ssbehera 	(void) nxge_mii_read(nxgep,
5889d81011f0Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
5890d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value);
5891d81011f0Ssbehera #endif
5892d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5893d81011f0Ssbehera 	    "nxge_mii_dump: bmsr (1) xcvr 0x%x value 0x%x",
5894d81011f0Ssbehera 	    xcvr_portn, bmsr.value));
5895d81011f0Ssbehera 
5896d81011f0Ssbehera #if defined(__i386)
5897d81011f0Ssbehera 	(void) nxge_mii_read(nxgep,
5898d81011f0Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
5899d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->idr1), &idr1.value);
5900d81011f0Ssbehera #else
5901d81011f0Ssbehera 	(void) nxge_mii_read(nxgep,
5902d81011f0Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
5903d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->idr1), &idr1.value);
5904d81011f0Ssbehera #endif
5905d81011f0Ssbehera 
5906d81011f0Ssbehera 
5907d81011f0Ssbehera #if defined(__i386)
5908d81011f0Ssbehera 	(void) nxge_mii_read(nxgep,
5909d81011f0Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
5910d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->idr2), &idr2.value);
5911d81011f0Ssbehera #else
5912d81011f0Ssbehera 	(void) nxge_mii_read(nxgep,
5913d81011f0Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
5914d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->idr2), &idr2.value);
5915d81011f0Ssbehera #endif
5916d81011f0Ssbehera 
5917d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5918d81011f0Ssbehera 	    "nxge_mii_dump: idr1 (2) xcvr 0x%x value 0x%x",
5919d81011f0Ssbehera 	    xcvr_portn, idr1.value));
5920d81011f0Ssbehera 
5921d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5922d81011f0Ssbehera 	    "nxge_mii_dump: idr2 (3) xcvr 0x%x value 0x%x",
5923d81011f0Ssbehera 	    xcvr_portn, idr2.value));
5924d81011f0Ssbehera 
5925d81011f0Ssbehera 	mode.value = 0;
59266b438925Ssbehera 	mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG;
5927d81011f0Ssbehera 
5928d81011f0Ssbehera #if defined(__i386)
5929d81011f0Ssbehera 	(void) nxge_mii_write(nxgep, xcvr_portn,
5930d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->shadow), mode.value);
5931d81011f0Ssbehera 
5932d81011f0Ssbehera 	(void) nxge_mii_read(nxgep, xcvr_portn,
5933d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->shadow), &mode.value);
5934d81011f0Ssbehera #else
5935d81011f0Ssbehera 	(void) nxge_mii_write(nxgep, xcvr_portn,
5936d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->shadow), mode.value);
5937d81011f0Ssbehera 
5938d81011f0Ssbehera 	(void) nxge_mii_read(nxgep, xcvr_portn,
5939d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->shadow), &mode.value);
5940d81011f0Ssbehera #endif
5941d81011f0Ssbehera 
5942d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5943d81011f0Ssbehera 	    "nxge_mii_dump: mode control xcvr 0x%x value 0x%x",
5944d81011f0Ssbehera 	    xcvr_portn, mode.value));
5945d81011f0Ssbehera }
5946d81011f0Ssbehera #endif
5947